From c504bc37c2fc850da5a34355c04b67f8a2d265eb Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Thu, 10 Oct 2024 02:06:55 -0700 Subject: [PATCH] Detect modification for resources that does not use generation Signed-off-by: Tamal Saha --- client/client.go | 13 +++++++++++-- meta/hash.go | 25 +++++++++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/client/client.go b/client/client.go index 519c087df..68b8da6b1 100644 --- a/client/client.go +++ b/client/client.go @@ -21,6 +21,8 @@ import ( "reflect" "strings" + "kmodules.xyz/client-go/meta" + "github.com/pkg/errors" kerr "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -116,8 +118,15 @@ func CreateOrPatch(ctx context.Context, c client.Client, obj client.Object, tran } vt := kutil.VerbUnchanged - if cur.GetGeneration() != mod.GetGeneration() { - vt = kutil.VerbPatched + if mod.GetGeneration() > 0 { + if cur.GetGeneration() != mod.GetGeneration() { + vt = kutil.VerbPatched + } + } else { + // Secret, ServiceAccount etc resources do not use metadata.generation + if meta.ObjectHash(cur) != meta.ObjectHash(mod) { + vt = kutil.VerbPatched + } } assign(obj, mod) return vt, nil diff --git a/meta/hash.go b/meta/hash.go index 6fc87ae33..0e7778f4f 100644 --- a/meta/hash.go +++ b/meta/hash.go @@ -33,7 +33,11 @@ func ResourceHash(obj metav1.Object) string { h := xxh3.New() _, _ = h.WriteString(string(obj.GetUID())) _, _ = h.WriteString(",") - _, _ = h.WriteString(strconv.FormatInt(obj.GetGeneration(), 10)) + if obj.GetGeneration() > 0 { + _, _ = h.WriteString(strconv.FormatInt(obj.GetGeneration(), 10)) + } else { + _, _ = h.WriteString(ObjectHash(obj)) + } return strconv.FormatUint(h.Sum64(), 10) } @@ -57,11 +61,20 @@ func ObjectHash(in metav1.Object) string { obj["annotations"] = data } - st := structs.New(in) - for _, field := range st.Fields() { - fieldName := field.Name() - if fieldName != "ObjectMeta" && fieldName != "TypeMeta" && fieldName != "Status" { - obj[fieldName] = field.Value() + u, isUnstructured := in.(*unstructured.Unstructured) + if isUnstructured { + for fieldName, v := range u.UnstructuredContent() { + if fieldName != "metadata" && fieldName != "apiVersion" && fieldName != "kind" && fieldName != "status" { + obj[fieldName] = v + } + } + } else { + st := structs.New(in) + for _, field := range st.Fields() { + fieldName := field.Name() + if fieldName != "ObjectMeta" && fieldName != "TypeMeta" && fieldName != "Status" { + obj[fieldName] = field.Value() + } } }