diff --git a/e2e/assets/drift/correction-enabled/gitrepo.yaml b/e2e/assets/drift/correction-enabled/gitrepo.yaml index 10b527a5dd..f7cb2a42c4 100644 --- a/e2e/assets/drift/correction-enabled/gitrepo.yaml +++ b/e2e/assets/drift/correction-enabled/gitrepo.yaml @@ -9,3 +9,4 @@ spec: enabled: true paths: - drift + - drift-ignore-status diff --git a/e2e/drift/drift_test.go b/e2e/drift/drift_test.go index d42b6fd1a9..0de9030e60 100644 --- a/e2e/drift/drift_test.go +++ b/e2e/drift/drift_test.go @@ -184,6 +184,17 @@ var _ = Describe("Drift", Ordered, func() { `{"name":"http","port":1234,"protocol":"TCP","targetPort":"http-web-svc"}]}}`)) }) }) + + Context("Resource manifests containing status fields", func() { + // Status must be ignored for drift correction, despite being part of the manifests + It("Is marked as ready", func() { + bundleName := "drift-correction-test-drift-ignore-status" + Eventually(func() bool { + b := getBundle(bundleName, k) + return b.Status.Summary.Ready == 1 + }).Should(BeTrue()) + }) + }) }) When("Drift correction is enabled with force", func() { diff --git a/internal/cmd/agent/deployer/normalizers/norm.go b/internal/cmd/agent/deployer/normalizers/norm.go index a47164c836..64f826ac1b 100644 --- a/internal/cmd/agent/deployer/normalizers/norm.go +++ b/internal/cmd/agent/deployer/normalizers/norm.go @@ -22,6 +22,8 @@ func (n Norm) Normalize(un *unstructured.Unstructured) error { func New(lives objectset.ObjectByGVK, additions ...diff.Normalizer) Norm { n := Norm{ normalizers: []diff.Normalizer{ + // Status fields are normally subresources which can't be influenced by resource updates + &StatusNormalizer{}, &MutatingWebhookNormalizer{ Live: lives, }, diff --git a/internal/cmd/agent/deployer/normalizers/status.go b/internal/cmd/agent/deployer/normalizers/status.go new file mode 100644 index 0000000000..26f4605bef --- /dev/null +++ b/internal/cmd/agent/deployer/normalizers/status.go @@ -0,0 +1,13 @@ +package normalizers + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +// StatusNormalizer removes a top-level "status" fields from the object, if present +type StatusNormalizer struct{} + +func (_ StatusNormalizer) Normalize(un *unstructured.Unstructured) error { + unstructured.RemoveNestedField(un.Object, "status") + return nil +} diff --git a/internal/cmd/agent/deployer/normalizers/status_test.go b/internal/cmd/agent/deployer/normalizers/status_test.go new file mode 100644 index 0000000000..69fedebc2a --- /dev/null +++ b/internal/cmd/agent/deployer/normalizers/status_test.go @@ -0,0 +1,55 @@ +package normalizers + +import ( + "errors" + "testing" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" +) + +func TestStatusNormalizer_Normalize(t *testing.T) { + tests := []struct { + name string + obj runtime.Object + check func(object runtime.Object) error + }{ + { + name: "object with status", + obj: &corev1.Pod{ + Status: corev1.PodStatus{ + PodIP: "1.2.3.4", + }, + }, + check: func(obj runtime.Object) error { + if obj.(*corev1.Pod).Status.PodIP != "" { + return errors.New("status was not removed") + } + return nil + }, + }, + { + name: "object without status", + obj: &corev1.ConfigMap{}, + check: func(_ runtime.Object) error { return nil }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + un, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tt.obj) + if err != nil { + t.Fatal(err) + } + if err := (StatusNormalizer{}).Normalize(&unstructured.Unstructured{Object: un}); err != nil { + t.Fatal(err) + } + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(un, tt.obj); err != nil { + t.Fatal(err) + } + if err := tt.check(tt.obj); err != nil { + t.Error(err) + } + }) + } +}