Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.24.0

require (
github.com/aws-controllers-k8s/pkg v0.0.19
github.com/aws-controllers-k8s/runtime v0.54.0
github.com/aws-controllers-k8s/runtime v0.54.1
github.com/aws/aws-sdk-go v1.49.0
github.com/aws/aws-sdk-go-v2 v1.32.7
github.com/dlclark/regexp2 v1.10.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,12 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws-controllers-k8s/pkg v0.0.19 h1:q/NhMvj6fCkHAJTyasrOWNdYME9/eCdeA5tStz4hHb8=
github.com/aws-controllers-k8s/pkg v0.0.19/go.mod h1:VvdjLWmR6IJ3KU8KByKiq/lJE8M+ur2piXysXKTGUS0=
github.com/aws-controllers-k8s/runtime v0.53.1 h1:l9MkR1KfZW8H8icT5rrRK3pdnVVA4io/eINVe5aspWs=
github.com/aws-controllers-k8s/runtime v0.53.1/go.mod h1:OkUJN+Ds799JLYZsMJrO2vDJ4snxUeHK2MgrQHbU+Qc=
github.com/aws-controllers-k8s/runtime v0.54.0 h1:RWv5cVb428styiRTHugRF8bMWjXkgsDc5E6Q/BoD8gA=
github.com/aws-controllers-k8s/runtime v0.54.0/go.mod h1:OkUJN+Ds799JLYZsMJrO2vDJ4snxUeHK2MgrQHbU+Qc=
github.com/aws-controllers-k8s/runtime v0.54.1 h1:0mbCJELz3t7jbG4abNecF0yeRd8YeFZQPr7nnzr8DC8=
github.com/aws-controllers-k8s/runtime v0.54.1/go.mod h1:OkUJN+Ds799JLYZsMJrO2vDJ4snxUeHK2MgrQHbU+Qc=
github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY=
github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw=
Expand Down
2 changes: 1 addition & 1 deletion pkg/generate/ack/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (frm *fakeRM) EnsureTags(
return nil
}

func (frm *fakeRM) FilterSystemTags(acktypes.AWSResource) {}
func (frm *fakeRM) FilterSystemTags(acktypes.AWSResource, []string) {}

// This test is mostly just a hack to introduce a Go module dependency between
// the ACK runtime library and the code generator. The code generator doesn't
Expand Down
29 changes: 21 additions & 8 deletions templates/pkg/resource/manager.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,26 @@ func (rm *resourceManager) EnsureTags(
{{- end }}
}

// FilterAWSTags ignores tags that have keys that start with "aws:"
// is needed to ensure the controller does not attempt to remove
// tags set by AWS. This function needs to be called after each Read
// operation.
// Eg. resources created with cloudformation have tags that cannot be
//removed by an ACK controller
func (rm *resourceManager) FilterSystemTags(res acktypes.AWSResource) {
// FilterSystemTags removes system-managed tags from the resource's tag collection
// to prevent the controller from attempting to manage them. This includes:
// - Tags with keys starting with "aws:" (AWS-managed system tags)
// - Tags specified via the --resource-tags startup flag (controller-level tags)
// - Tags injected by AWS services (e.g., CloudFormation, EKS, etc.)
//
// This filtering is essential because:
// 1. AWS services automatically add system tags that cannot be modified by users
// 2. Attempting to remove these tags would result in API errors
// 3. The controller should only manage user-defined tags, not system tags
//
// Must be called after each Read operation to ensure the resource state
// reflects only manageable tags. This prevents unnecessary update attempts
// and maintains consistency between desired and actual resource state.
//
// Example system tags that are filtered:
// - aws:cloudformation:stack-name (CloudFormation)
// - aws:eks:cluster-name (EKS)
// - services.k8s.aws/* (Kubernetes-managed)
func (rm *resourceManager) FilterSystemTags(res acktypes.AWSResource, systemTags []string) {
{{- if $hookCode := Hook .CRD "filter_tags" }}
{{ $hookCode }}
{{ else }}
Expand All @@ -342,7 +355,7 @@ func (rm *resourceManager) FilterSystemTags(res acktypes.AWSResource) {
{{ end -}}
existingTags = r.ko.Spec.{{ $tagField.Path }}
resourceTags, tagKeyOrder := convertToOrderedACKTags(existingTags)
ignoreSystemTags(resourceTags)
ignoreSystemTags(resourceTags, systemTags)
{{ GoCodeInitializeNestedStructField .CRD "r.ko" $tagField "svcapitypes" 1 -}}
r.ko.Spec.{{ $tagField.Path }} = fromACKTags(resourceTags, tagKeyOrder)
{{- end }}
Expand Down
8 changes: 4 additions & 4 deletions templates/pkg/resource/tags.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import(
var (
_ = svcapitypes.{{ .CRD.Kind }}{}
_ = acktags.NewTags()
ACKSystemTags = []string{"services.k8s.aws/namespace", "services.k8s.aws/controller-version"}
)

{{- if $hookCode := Hook .CRD "convert_tags" }}
Expand Down Expand Up @@ -59,13 +58,14 @@ func fromACKTags(tags acktags.Tags, keyOrder []string) {{ $tagFieldGoType }} {
{{ end }}

// ignoreSystemTags ignores tags that have keys that start with "aws:"
// and ACKSystemTags, to avoid patching them to the resourceSpec.
// and systemTags defined on startup via the --resource-tags flag,
// to avoid patching them to the resourceSpec.
// Eg. resources created with cloudformation have tags that cannot be
// removed by an ACK controller
func ignoreSystemTags(tags acktags.Tags) {
func ignoreSystemTags(tags acktags.Tags, systemTags []string) {
for k := range tags {
if strings.HasPrefix(k, "aws:") ||
slices.Contains(ACKSystemTags, k) {
slices.Contains(systemTags, k) {
delete(tags, k)
}
}
Expand Down