diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index ca50bdd..83a849b 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,8 +1,8 @@ ack_generate_info: - build_date: "2025-02-20T18:23:50Z" - build_hash: a326346bd3a6973254d247c9ab2dc76790c36241 + build_date: "2025-03-14T20:19:48Z" + build_hash: 0ab258c51775fd52af32e649da00d57373b20869 go_version: go1.24.0 - version: v0.43.2 + version: v0.43.2-6-g0ab258c api_directory_checksum: 73ba0942f1950c4700c2bff40dda380d5994ca6b api_version: v1alpha1 aws_sdk_go_version: 1.32.6 diff --git a/pkg/resource/domain/hooks.go b/pkg/resource/domain/hooks.go index ebc661b..50207e5 100644 --- a/pkg/resource/domain/hooks.go +++ b/pkg/resource/domain/hooks.go @@ -63,12 +63,12 @@ func (rm *resourceManager) syncTags( resourceArn := latest.ko.Status.ACKResourceMetadata.ARN - desiredTags := ToACKTags(desired.ko.Spec.Tags) - latestTags := ToACKTags(latest.ko.Spec.Tags) + desiredTags, _ := convertToOrderedACKTags(desired.ko.Spec.Tags) + latestTags, _ := convertToOrderedACKTags(latest.ko.Spec.Tags) added, _, removed := ackcompare.GetTagsDifference(latestTags, desiredTags) - toAdd := FromACKTags(added) + toAdd := fromACKTags(added, nil) var toDeleteTagKeys []string for k, _ := range removed { @@ -128,13 +128,13 @@ func compareTags( if len(a.ko.Spec.Tags) != len(b.ko.Spec.Tags) { delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) } else if len(a.ko.Spec.Tags) > 0 { - desiredTags := ToACKTags(a.ko.Spec.Tags) - latestTags := ToACKTags(b.ko.Spec.Tags) + desiredTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) + latestTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) added, _, removed := ackcompare.GetTagsDifference(latestTags, desiredTags) - toAdd := FromACKTags(added) - toDelete := FromACKTags(removed) + toAdd := fromACKTags(added, nil) + toDelete := fromACKTags(removed, nil) if len(toAdd) != 0 || len(toDelete) != 0 { delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) diff --git a/pkg/resource/domain/manager.go b/pkg/resource/domain/manager.go index 0ac80b3..9cb274a 100644 --- a/pkg/resource/domain/manager.go +++ b/pkg/resource/domain/manager.go @@ -291,9 +291,9 @@ func (rm *resourceManager) EnsureTags( defaultTags := ackrt.GetDefaultTags(&rm.cfg, r.ko, md) var existingTags []*svcapitypes.Tag existingTags = r.ko.Spec.Tags - resourceTags := ToACKTags(existingTags) + resourceTags, keyOrder := convertToOrderedACKTags(existingTags) tags := acktags.Merge(resourceTags, defaultTags) - r.ko.Spec.Tags = FromACKTags(tags) + r.ko.Spec.Tags = fromACKTags(tags, keyOrder) return nil } @@ -310,9 +310,9 @@ func (rm *resourceManager) FilterSystemTags(res acktypes.AWSResource) { } var existingTags []*svcapitypes.Tag existingTags = r.ko.Spec.Tags - resourceTags := ToACKTags(existingTags) + resourceTags, tagKeyOrder := convertToOrderedACKTags(existingTags) ignoreSystemTags(resourceTags) - r.ko.Spec.Tags = FromACKTags(resourceTags) + r.ko.Spec.Tags = fromACKTags(resourceTags, tagKeyOrder) } // mirrorAWSTags ensures that AWS tags are included in the desired resource @@ -334,10 +334,10 @@ func mirrorAWSTags(a *resource, b *resource) { var existingDesiredTags []*svcapitypes.Tag existingDesiredTags = a.ko.Spec.Tags existingLatestTags = b.ko.Spec.Tags - desiredTags := ToACKTags(existingDesiredTags) - latestTags := ToACKTags(existingLatestTags) + desiredTags, desiredTagKeyOrder := convertToOrderedACKTags(existingDesiredTags) + latestTags, _ := convertToOrderedACKTags(existingLatestTags) syncAWSTags(desiredTags, latestTags) - a.ko.Spec.Tags = FromACKTags(desiredTags) + a.ko.Spec.Tags = fromACKTags(desiredTags, desiredTagKeyOrder) } // newResourceManager returns a new struct implementing diff --git a/pkg/resource/domain/tags.go b/pkg/resource/domain/tags.go index 73a1a1c..ac41a39 100644 --- a/pkg/resource/domain/tags.go +++ b/pkg/resource/domain/tags.go @@ -30,39 +30,51 @@ var ( ACKSystemTags = []string{"services.k8s.aws/namespace", "services.k8s.aws/controller-version"} ) -// ToACKTags converts the tags parameter into 'acktags.Tags' shape. +// convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. // This method helps in creating the hub(acktags.Tags) for merging -// default controller tags with existing resource tags. -func ToACKTags(tags []*svcapitypes.Tag) acktags.Tags { +// default controller tags with existing resource tags. It also returns a slice +// of keys maintaining the original key Order when the tags are a list +func convertToOrderedACKTags(tags []*svcapitypes.Tag) (acktags.Tags, []string) { result := acktags.NewTags() - if tags == nil || len(tags) == 0 { - return result - } + keyOrder := []string{} + if len(tags) == 0 { + return result, keyOrder + } for _, t := range tags { if t.Key != nil { - if t.Value == nil { - result[*t.Key] = "" - } else { + keyOrder = append(keyOrder, *t.Key) + if t.Value != nil { result[*t.Key] = *t.Value + } else { + result[*t.Key] = "" } } } - return result + return result, keyOrder } -// FromACKTags converts the tags parameter into []*svcapitypes.Tag shape. +// fromACKTags converts the tags parameter into []*svcapitypes.Tag shape. // This method helps in setting the tags back inside AWSResource after merging -// default controller tags with existing resource tags. -func FromACKTags(tags acktags.Tags) []*svcapitypes.Tag { +// default controller tags with existing resource tags. When a list, +// it maintains the order from original +func fromACKTags(tags acktags.Tags, keyOrder []string) []*svcapitypes.Tag { result := []*svcapitypes.Tag{} + + for _, k := range keyOrder { + v, ok := tags[k] + if ok { + tag := svcapitypes.Tag{Key: &k, Value: &v} + result = append(result, &tag) + delete(tags, k) + } + } for k, v := range tags { - kCopy := k - vCopy := v - tag := svcapitypes.Tag{Key: &kCopy, Value: &vCopy} + tag := svcapitypes.Tag{Key: &k, Value: &v} result = append(result, &tag) } + return result } diff --git a/pkg/resource/package_group/hooks.go b/pkg/resource/package_group/hooks.go index 9167f81..f96029b 100644 --- a/pkg/resource/package_group/hooks.go +++ b/pkg/resource/package_group/hooks.go @@ -38,12 +38,12 @@ func (rm *resourceManager) syncTags( resourceArn := latest.ko.Status.ACKResourceMetadata.ARN - desiredTags := ToACKTags(desired.ko.Spec.Tags) - latestTags := ToACKTags(latest.ko.Spec.Tags) + desiredTags, _ := convertToOrderedACKTags(desired.ko.Spec.Tags) + latestTags, _ := convertToOrderedACKTags(latest.ko.Spec.Tags) added, _, removed := ackcompare.GetTagsDifference(latestTags, desiredTags) - toAdd := FromACKTags(added) + toAdd := fromACKTags(added, nil) var toDeleteTagKeys []string for k, _ := range removed { @@ -103,13 +103,13 @@ func compareTags( if len(a.ko.Spec.Tags) != len(b.ko.Spec.Tags) { delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) } else if len(a.ko.Spec.Tags) > 0 { - desiredTags := ToACKTags(a.ko.Spec.Tags) - latestTags := ToACKTags(b.ko.Spec.Tags) + desiredTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) + latestTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) added, _, removed := ackcompare.GetTagsDifference(latestTags, desiredTags) - toAdd := FromACKTags(added) - toDelete := FromACKTags(removed) + toAdd := fromACKTags(added, nil) + toDelete := fromACKTags(removed, nil) if len(toAdd) != 0 || len(toDelete) != 0 { delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) diff --git a/pkg/resource/package_group/manager.go b/pkg/resource/package_group/manager.go index 70fb397..445cb50 100644 --- a/pkg/resource/package_group/manager.go +++ b/pkg/resource/package_group/manager.go @@ -291,9 +291,9 @@ func (rm *resourceManager) EnsureTags( defaultTags := ackrt.GetDefaultTags(&rm.cfg, r.ko, md) var existingTags []*svcapitypes.Tag existingTags = r.ko.Spec.Tags - resourceTags := ToACKTags(existingTags) + resourceTags, keyOrder := convertToOrderedACKTags(existingTags) tags := acktags.Merge(resourceTags, defaultTags) - r.ko.Spec.Tags = FromACKTags(tags) + r.ko.Spec.Tags = fromACKTags(tags, keyOrder) return nil } @@ -310,9 +310,9 @@ func (rm *resourceManager) FilterSystemTags(res acktypes.AWSResource) { } var existingTags []*svcapitypes.Tag existingTags = r.ko.Spec.Tags - resourceTags := ToACKTags(existingTags) + resourceTags, tagKeyOrder := convertToOrderedACKTags(existingTags) ignoreSystemTags(resourceTags) - r.ko.Spec.Tags = FromACKTags(resourceTags) + r.ko.Spec.Tags = fromACKTags(resourceTags, tagKeyOrder) } // mirrorAWSTags ensures that AWS tags are included in the desired resource @@ -334,10 +334,10 @@ func mirrorAWSTags(a *resource, b *resource) { var existingDesiredTags []*svcapitypes.Tag existingDesiredTags = a.ko.Spec.Tags existingLatestTags = b.ko.Spec.Tags - desiredTags := ToACKTags(existingDesiredTags) - latestTags := ToACKTags(existingLatestTags) + desiredTags, desiredTagKeyOrder := convertToOrderedACKTags(existingDesiredTags) + latestTags, _ := convertToOrderedACKTags(existingLatestTags) syncAWSTags(desiredTags, latestTags) - a.ko.Spec.Tags = FromACKTags(desiredTags) + a.ko.Spec.Tags = fromACKTags(desiredTags, desiredTagKeyOrder) } // newResourceManager returns a new struct implementing diff --git a/pkg/resource/package_group/tags.go b/pkg/resource/package_group/tags.go index 694118f..ce5eba0 100644 --- a/pkg/resource/package_group/tags.go +++ b/pkg/resource/package_group/tags.go @@ -30,39 +30,51 @@ var ( ACKSystemTags = []string{"services.k8s.aws/namespace", "services.k8s.aws/controller-version"} ) -// ToACKTags converts the tags parameter into 'acktags.Tags' shape. +// convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. // This method helps in creating the hub(acktags.Tags) for merging -// default controller tags with existing resource tags. -func ToACKTags(tags []*svcapitypes.Tag) acktags.Tags { +// default controller tags with existing resource tags. It also returns a slice +// of keys maintaining the original key Order when the tags are a list +func convertToOrderedACKTags(tags []*svcapitypes.Tag) (acktags.Tags, []string) { result := acktags.NewTags() - if tags == nil || len(tags) == 0 { - return result - } + keyOrder := []string{} + if len(tags) == 0 { + return result, keyOrder + } for _, t := range tags { if t.Key != nil { - if t.Value == nil { - result[*t.Key] = "" - } else { + keyOrder = append(keyOrder, *t.Key) + if t.Value != nil { result[*t.Key] = *t.Value + } else { + result[*t.Key] = "" } } } - return result + return result, keyOrder } -// FromACKTags converts the tags parameter into []*svcapitypes.Tag shape. +// fromACKTags converts the tags parameter into []*svcapitypes.Tag shape. // This method helps in setting the tags back inside AWSResource after merging -// default controller tags with existing resource tags. -func FromACKTags(tags acktags.Tags) []*svcapitypes.Tag { +// default controller tags with existing resource tags. When a list, +// it maintains the order from original +func fromACKTags(tags acktags.Tags, keyOrder []string) []*svcapitypes.Tag { result := []*svcapitypes.Tag{} + + for _, k := range keyOrder { + v, ok := tags[k] + if ok { + tag := svcapitypes.Tag{Key: &k, Value: &v} + result = append(result, &tag) + delete(tags, k) + } + } for k, v := range tags { - kCopy := k - vCopy := v - tag := svcapitypes.Tag{Key: &kCopy, Value: &vCopy} + tag := svcapitypes.Tag{Key: &k, Value: &v} result = append(result, &tag) } + return result }