diff --git a/lib/resourcemerge/core.go b/lib/resourcemerge/core.go index f8bec5583..950bbe67a 100644 --- a/lib/resourcemerge/core.go +++ b/lib/resourcemerge/core.go @@ -24,38 +24,8 @@ func ensurePodTemplateSpec(modified *bool, existing *corev1.PodTemplateSpec, req } func ensurePodSpec(modified *bool, existing *corev1.PodSpec, required corev1.PodSpec) { - // any container we specify, we require. - for _, required := range required.InitContainers { - var existingCurr *corev1.Container - for j, curr := range existing.InitContainers { - if curr.Name == required.Name { - existingCurr = &existing.InitContainers[j] - break - } - } - if existingCurr == nil { - *modified = true - existing.Containers = append(existing.InitContainers, corev1.Container{}) - existingCurr = &existing.InitContainers[len(existing.InitContainers)-1] - } - ensureContainer(modified, existingCurr, required) - } - - for _, required := range required.Containers { - var existingCurr *corev1.Container - for j, curr := range existing.Containers { - if curr.Name == required.Name { - existingCurr = &existing.Containers[j] - break - } - } - if existingCurr == nil { - *modified = true - existing.Containers = append(existing.Containers, corev1.Container{}) - existingCurr = &existing.Containers[len(existing.Containers)-1] - } - ensureContainer(modified, existingCurr, required) - } + ensureContainers(modified, &existing.InitContainers, required.InitContainers) + ensureContainers(modified, &existing.Containers, required.Containers) // any volume we specify, we require. for _, required := range required.Volumes { @@ -91,6 +61,37 @@ func ensurePodSpec(modified *bool, existing *corev1.PodSpec, required corev1.Pod setInt32Ptr(modified, &existing.Priority, required.Priority) } +func ensureContainers(modified *bool, existing *[]corev1.Container, required []corev1.Container) { + var existingCurr *corev1.Container + for i, existingContainer := range *existing { + for _, requiredContainer := range required { + if existingContainer.Name == requiredContainer.Name { + existingCurr = &(*existing)[i] + ensureContainer(modified, existingCurr, requiredContainer) + break + } + } + if existingCurr == nil { + *modified = true + *existing = append((*existing)[:i], (*existing)[i+1:]...) + } + } + + for _, requiredContainer := range required { + match := false + for _, existingContainer := range *existing { + if existingContainer.Name == requiredContainer.Name { + match = true + break + } + } + if !match { + *modified = true + *existing = append(*existing, requiredContainer) + } + } +} + func ensureContainer(modified *bool, existing *corev1.Container, required corev1.Container) { setStringIfSet(modified, &existing.Name, required.Name) setStringIfSet(modified, &existing.Image, required.Image) diff --git a/lib/resourcemerge/core_test.go b/lib/resourcemerge/core_test.go index f5f1fc1e0..918400552 100644 --- a/lib/resourcemerge/core_test.go +++ b/lib/resourcemerge/core_test.go @@ -5,6 +5,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/utils/pointer" ) @@ -16,14 +17,98 @@ func TestEnsurePodSpec(t *testing.T) { expectedModified bool expected corev1.PodSpec - }{{ - name: "empty inputs", - existing: corev1.PodSpec{}, - input: corev1.PodSpec{}, + }{ + { + name: "empty inputs", + existing: corev1.PodSpec{}, + input: corev1.PodSpec{}, - expectedModified: false, - expected: corev1.PodSpec{}, - }} + expectedModified: false, + expected: corev1.PodSpec{}, + }, + { + name: "remove regular containers from existing", + existing: corev1.PodSpec{ + Containers: []corev1.Container{ + corev1.Container{Name: "test"}}}, + input: corev1.PodSpec{}, + + expectedModified: true, + expected: corev1.PodSpec{}, + }, + { + name: "remove regular and init containers from existing", + existing: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init"}}, + Containers: []corev1.Container{ + corev1.Container{Name: "test"}}}, + input: corev1.PodSpec{}, + + expectedModified: true, + expected: corev1.PodSpec{}, + }, + { + name: "remove init containers from existing", + existing: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init"}}}, + input: corev1.PodSpec{}, + + expectedModified: true, + expected: corev1.PodSpec{}, + }, + { + name: "append regular and init containers", + existing: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init-a"}}, + Containers: []corev1.Container{ + corev1.Container{Name: "test-a"}}}, + input: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init-a"}, + corev1.Container{Name: "test-init-b"}, + }, + Containers: []corev1.Container{ + corev1.Container{Name: "test-a"}, + corev1.Container{Name: "test-b"}, + }, + }, + + expectedModified: true, + expected: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init-a"}, + corev1.Container{Name: "test-init-b"}, + }, + Containers: []corev1.Container{ + corev1.Container{Name: "test-a"}, + corev1.Container{Name: "test-b"}, + }, + }, + }, + { + name: "match regular and init containers", + existing: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init"}}, + Containers: []corev1.Container{ + corev1.Container{Name: "test"}}}, + input: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init"}}, + Containers: []corev1.Container{ + corev1.Container{Name: "test"}}}, + + expectedModified: false, + expected: corev1.PodSpec{ + InitContainers: []corev1.Container{ + corev1.Container{Name: "test-init"}}, + Containers: []corev1.Container{ + corev1.Container{Name: "test"}}}, + }, + } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -34,7 +119,7 @@ func TestEnsurePodSpec(t *testing.T) { } if !equality.Semantic.DeepEqual(test.existing, test.expected) { - t.Errorf("mismatch PodSpec got: %v want: %v", test.existing, test.expected) + t.Errorf("unexpected: %s", diff.ObjectReflectDiff(test.expected, test.existing)) } }) }