Skip to content

Commit 7015914

Browse files
committed
Make mirrowAwsTags a method in the AWSResourceMAnager interface
1 parent bced95a commit 7015914

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

templates/pkg/resource/manager.go.tpl

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func (rm *resourceManager) ReadOne(
8989
panic("resource manager's ReadOne() method received resource with nil CR object")
9090
}
9191
observed, err := rm.sdkFind(ctx, r)
92+
mirrorAWSTags(r, observed)
9293
if err != nil {
9394
if observed != nil {
9495
return rm.onError(observed, err)
@@ -140,7 +141,6 @@ func (rm *resourceManager) Update(
140141
// Should never happen... if it does, it's buggy code.
141142
panic("resource manager's Update() method received resource with nil CR object")
142143
}
143-
syncAWSTags(desired, latest)
144144
updated, err := rm.sdkUpdate(ctx, desired, latest, delta)
145145
if err != nil {
146146
if updated != nil {
@@ -312,13 +312,13 @@ func (rm *resourceManager) EnsureTags(
312312
{{- end }}
313313
}
314314
315-
// filterAWSTags ignores tags that have keys that start with "aws:"
315+
// FilterAWSTags ignores tags that have keys that start with "aws:"
316316
// is needed to ensure the controller does not attempt to remove
317317
// tags set by AWS. This function needs to be called after each Read
318318
// operation.
319319
// Eg. resources created with cloudformation have tags that cannot be
320320
//removed by an ACK controller
321-
func (rm *resourceManager) FilterAWSTags(res acktypes.AWSResource) {
321+
func (rm *resourceManager) FilterSystemTags(res acktypes.AWSResource) {
322322
{{- if $hookCode := Hook .CRD "filter_tags" }}
323323
{{ $hookCode }}
324324
{{ else }}
@@ -342,21 +342,25 @@ func (rm *resourceManager) FilterAWSTags(res acktypes.AWSResource) {
342342
{{ end -}}
343343
existingTags = r.ko.Spec.{{ $tagField.Path }}
344344
resourceTags := ToACKTags(existingTags)
345-
acktags.IgnoreAWSTags(resourceTags)
345+
IgnoreAWSTags(resourceTags)
346346
{{ GoCodeInitializeNestedStructField .CRD "r.ko" $tagField "svcapitypes" 1 -}}
347347
r.ko.Spec.{{ $tagField.Path }} = FromACKTags(resourceTags)
348348
{{- end }}
349349
{{- end }}
350350
}
351351
352-
353-
// syncAWSTags ignores tags that have keys that start with "aws:"
354-
// is needed to ensure the controller does not attempt to remove
355-
// tags set by AWS. This function needs to be called after each Read
356-
// operation.
357-
// Eg. resources created with cloudformation have tags that cannot be
358-
//removed by an ACK controller
359-
func syncAWSTags(a *resource, b *resource) {
352+
// MirrorAWSTags ensures that AWS tags are included in the desired resource
353+
// if they are present in the latest resource. This will ensure that the
354+
// aws tags are not present in a diff. The logic of the controller will
355+
// ensure these tags aren't patched to the resource in the cluster, and
356+
// will only be present to make sure we don't try to remove these tags.
357+
//
358+
// Although there are a lot of similarities between this function and
359+
// EnsureTags, they are very much different.
360+
// While EnsureTags tries to make sure the resource contains the controller
361+
// tags, mirrowAWSTags tries to make sure tags injected by AWS are mirrored
362+
// from the latest resoruce to the desired resource.
363+
func mirrorAWSTags(a *resource, b *resource) {
360364
{{- if $hookCode := Hook .CRD "sync_tags" }}
361365
{{ $hookCode }}
362366
{{ else }}
@@ -391,7 +395,7 @@ func syncAWSTags(a *resource, b *resource) {
391395
existingLatestTags = b.ko.Spec.{{ $tagField.Path }}
392396
desiredTags := ToACKTags(existingDesiredTags)
393397
latestTags := ToACKTags(existingLatestTags)
394-
acktags.SyncAWSTags(desiredTags, latestTags)
398+
SyncAWSTags(desiredTags, latestTags)
395399
{{ GoCodeInitializeNestedStructField .CRD "a.ko" $tagField "svcapitypes" 1 -}}
396400
a.ko.Spec.{{ $tagField.Path }} = FromACKTags(desiredTags)
397401
{{- end }}

templates/pkg/resource/tags.go.tpl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,45 @@ func FromACKTags(tags acktags.Tags) {{ $tagFieldGoType }} {
8686
return result
8787
}
8888
{{ end }}
89+
90+
// IgnoreAWSTags ignores tags that have keys that start with "aws:"
91+
// is needed to ensure the controller does not attempt to remove
92+
// tags set by AWS
93+
// Eg. resources created with cloudformation have tags that cannot be
94+
// removed by an ACK controller
95+
func IgnoreAWSTags(tags acktags.Tags) {
96+
for k := range tags {
97+
if strings.HasPrefix(k, "aws:") ||
98+
strings.HasPrefix(k, "services.k8s.aws/") {
99+
delete(tags, k)
100+
}
101+
}
102+
}
103+
104+
// SyncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state
105+
// are preserved in the desired state. This prevents the controller from attempting to
106+
// modify AWS-managed tags, which would result in an error.
107+
//
108+
// AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog)
109+
// and cannot be modified or deleted through normal tag operations. Common examples include:
110+
// - aws:cloudformation:stack-name
111+
// - aws:servicecatalog:productArn
112+
//
113+
// Parameters:
114+
// - a: The target Tags map to be updated (typically desired state)
115+
// - b: The source Tags map containing AWS-managed tags (typically latest state)
116+
//
117+
// Example:
118+
//
119+
// latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"}
120+
// desired := Tags{"environment": "dev"}
121+
// SyncAWSTags(desired, latest)
122+
// desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"}
123+
func SyncAWSTags(a acktags.Tags, b acktags.Tags) {
124+
for k := range b {
125+
if strings.HasPrefix(k, "aws:") {
126+
a[k] = b[k]
127+
}
128+
}
129+
}
89130
{{ end }}

0 commit comments

Comments
 (0)