mirror of
https://github.com/actions-runner-controller/actions-runner-controller.git
synced 2026-09-30 23:52:14 +02:00
Reconcilers deep copied the object they had just fetched on every single reconcile, purely so a merge patch could be computed on the rare pass that actually changes something. The copy is a full recursive walk and allocation of the object, and the overwhelming majority of reconciles throw it away untouched. Introduce lazyCopy, which takes the snapshot on the first call to Mutate and hands back the live object. Because Mutate is the only way to reach the object, the snapshot cannot be taken after the mutation it is supposed to be diffed against, which is the way this optimization is usually gotten wrong. Apply it to the four Reconcile entry points, and move the two EphemeralRunnerSet status copies inside the branch that patches, so they are only paid for when the status really changed. While here, drop the short circuit in the EphemeralRunner finalizer block: `addedFinalizers || AddFinalizer(...)` skipped adding the actions finalizer whenever the first finalizer was added. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
64 lines
1.8 KiB
Go
64 lines
1.8 KiB
Go
package actionsgithubcom
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
)
|
|
|
|
func TestLazyCopyDoesNotCopyUntilMutated(t *testing.T) {
|
|
pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod"}}
|
|
lazy := newLazyCopy(pod)
|
|
|
|
assert.False(t, lazy.Modified())
|
|
assert.Panics(t, func() { lazy.MergeFrom() })
|
|
}
|
|
|
|
func TestLazyCopySnapshotsBeforeTheFirstMutation(t *testing.T) {
|
|
pod := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod",
|
|
Annotations: map[string]string{"key": "old"},
|
|
},
|
|
}
|
|
lazy := newLazyCopy(pod)
|
|
|
|
lazy.Mutate().Annotations["key"] = "new"
|
|
require.True(t, lazy.Modified())
|
|
|
|
data, err := lazy.MergeFrom().Data(pod)
|
|
require.NoError(t, err)
|
|
assert.JSONEq(t, `{"metadata":{"annotations":{"key":"new"}}}`, string(data))
|
|
}
|
|
|
|
func TestLazyCopySnapshotsOnlyOnce(t *testing.T) {
|
|
pod := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod",
|
|
Annotations: map[string]string{"first": "old", "second": "old"},
|
|
},
|
|
}
|
|
lazy := newLazyCopy(pod)
|
|
|
|
lazy.Mutate().Annotations["first"] = "new"
|
|
// The second mutation must diff against the state before the first one,
|
|
// otherwise the earlier change is dropped from the patch.
|
|
lazy.Mutate().Annotations["second"] = "new"
|
|
|
|
data, err := lazy.MergeFrom().Data(pod)
|
|
require.NoError(t, err)
|
|
assert.JSONEq(t, `{"metadata":{"annotations":{"first":"new","second":"new"}}}`, string(data))
|
|
}
|
|
|
|
func TestLazyCopyMergeFromIsAMergePatch(t *testing.T) {
|
|
pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod"}}
|
|
lazy := newLazyCopy(pod)
|
|
lazy.Mutate().Labels = map[string]string{"key": "value"}
|
|
|
|
assert.Equal(t, client.MergeFrom(pod).Type(), lazy.MergeFrom().Type())
|
|
}
|