@@ -99,6 +99,11 @@ func CompareResource(
9999
100100 resConfig := cfg .GetResourceConfig (r .Names .Camel )
101101
102+ tagField , err := r .GetTagField ()
103+ if err != nil {
104+ panic (err )
105+ }
106+
102107 // We need a deterministic order to traverse our top-level fields...
103108 specFieldNames := []string {}
104109 for fieldName := range r .SpecFields {
@@ -147,10 +152,18 @@ func CompareResource(
147152 out += fmt .Sprintf ("%s}\n " , indent )
148153 continue
149154 }
155+
156+ // Use a special comparison model for tags, since they need to be
157+ // converted into the common ACK tag type before doing a map delta
158+ if tagField != nil && specField == tagField {
159+ out += compareTags (deltaVarName , firstResAdaptedVarName , secondResAdaptedVarName , fieldPath , indentLevel )
160+ continue
161+ }
162+
150163 memberShapeRef := specField .ShapeRef
151164 memberShape := memberShapeRef .Shape
152165
153- // if ackcompare.HasNilDifference(a.ko.Spec.Name, b.ko.Spec.Name == nil ) {
166+ // if ackcompare.HasNilDifference(a.ko.Spec.Name, b.ko.Spec.Name) {
154167 // delta.Add("Spec.Name", a.ko.Spec.Name, b.ko.Spec.Name)
155168 // }
156169 nilCode := compareNil (
@@ -520,6 +533,46 @@ func compareSlice(
520533 return out
521534}
522535
536+ // compareTags outputs Go code that compares two slices of tags from two
537+ // resource fields by first converting them to the common ACK tag type and then
538+ // using a map comparison. If there is a difference, adds the difference to a
539+ // variable representing an `ackcompare.Delta`.
540+ //
541+ // Output code will look something like this:
542+ //
543+ // if !ackcompare.MapStringStringEqual(ToACKTags(a.ko.Spec.Tags), ToACKTags(b.ko.Spec.Tags)) {
544+ // delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags)
545+ // }
546+ func compareTags (
547+ // String representing the name of the variable that is of type
548+ // `*ackcompare.Delta`. We will generate Go code that calls the `Add()`
549+ // method of this variable when differences between fields are detected.
550+ deltaVarName string ,
551+ // String representing the name of the variable that represents the first
552+ // CR under comparison. This will typically be something like
553+ // "a.ko.Spec.Name". See `templates/pkg/resource/delta.go.tpl`.
554+ firstResVarName string ,
555+ // String representing the name of the variable that represents the second
556+ // CR under comparison. This will typically be something like
557+ // "b.ko.Spec.Name". See `templates/pkg/resource/delta.go.tpl`.
558+ secondResVarName string ,
559+ // String indicating the current field path being evaluated, e.g.
560+ // "Author.Name". This does not include the top-level Spec or Status
561+ // struct.
562+ fieldPath string ,
563+ // Number of levels of indentation to use
564+ indentLevel int ,
565+ ) string {
566+ out := ""
567+ indent := strings .Repeat ("\t " , indentLevel )
568+
569+ out += fmt .Sprintf ("%sif !ackcompare.MapStringStringEqual(ToACKTags(%s), ToACKTags(%s)) {\n " , indent , firstResVarName , secondResVarName )
570+ out += fmt .Sprintf ("%s\t %s.Add(\" %s\" , %s, %s)\n " , indent , deltaVarName , fieldPath , firstResVarName , secondResVarName )
571+ out += fmt .Sprintf ("%s}\n " , indent )
572+
573+ return out
574+ }
575+
523576// CompareStruct outputs Go code that compares two struct values from two
524577// resource fields and, if there is a difference, adds the difference to a
525578// variable representing an `ackcompare.Delta`.
@@ -551,6 +604,11 @@ func CompareStruct(
551604) string {
552605 out := ""
553606
607+ tagField , err := r .GetTagField ()
608+ if err != nil {
609+ panic (err )
610+ }
611+
554612 fieldConfigs := cfg .GetFieldConfigs (r .Names .Original )
555613
556614 for _ , memberName := range shape .MemberNames () {
@@ -572,7 +630,9 @@ func CompareStruct(
572630 // memberFieldPath contains the field path along with the prefix cfg.PrefixConfig.SpecField + "." hence we
573631 // would need to substring to exclude cfg.PrefixConfig.SpecField + "." to get correct field config.
574632 specFieldLen := len (strings .TrimPrefix (cfg .PrefixConfig .SpecField , "." ))
575- fieldConfig := fieldConfigs [memberFieldPath [specFieldLen + 1 :len (memberFieldPath )]]
633+ trimmedFieldPath := memberFieldPath [specFieldLen + 1 :]
634+
635+ fieldConfig := fieldConfigs [trimmedFieldPath ]
576636 if fieldConfig != nil {
577637 compareConfig = fieldConfig .Compare
578638 }
@@ -583,6 +643,13 @@ func CompareStruct(
583643
584644 memberShape := memberShapeRef .Shape
585645
646+ // Use a special comparison model for tags, since they need to be
647+ // converted into the common ACK tag type before doing a map delta
648+ if tagField != nil && tagField .Path == trimmedFieldPath {
649+ out += compareTags (deltaVarName , firstResAdaptedVarName , secondResAdaptedVarName , fieldPath , indentLevel )
650+ continue
651+ }
652+
586653 // if ackcompare.HasNilDifference(a.ko.Spec.Name, b.ko.Spec.Name == nil) {
587654 // delta.Add("Spec.Name", a.ko.Spec.Name, b.ko.Spec.Name)
588655 // }
@@ -604,6 +671,7 @@ func CompareStruct(
604671 )
605672 indentLevel ++
606673 }
674+
607675 switch memberShape .Type {
608676 case "structure" :
609677 // Recurse through all the struct's fields and subfields, building
0 commit comments