14
14
package api_key
15
15
16
16
import (
17
+ "context"
17
18
"fmt"
18
19
"strings"
19
20
20
21
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
22
+ ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log"
21
23
"github.com/aws/aws-sdk-go-v2/aws"
22
24
svcsdk "github.com/aws/aws-sdk-go-v2/service/apigateway"
23
25
svcsdktypes "github.com/aws/aws-sdk-go-v2/service/apigateway/types"
@@ -43,6 +45,9 @@ func updateApiKeyInput(desired *resource, input *svcsdk.UpdateApiKeyInput, delta
43
45
patchSet .Replace ("/customerId" , desiredSpec .CustomerID )
44
46
}
45
47
48
+ // Tags are managed through separate TagResource/UntagResource APIs,
49
+ // not through patch operations in UpdateApiKey
50
+
46
51
// Handle StageKeys with add/remove operations
47
52
if delta .DifferentAt ("Spec.StageKeys" ) && desiredSpec .StageKeys != nil {
48
53
// Convert StageKey objects to strings in the format "restApiId/stageName"
@@ -65,3 +70,127 @@ func updateApiKeyInput(desired *resource, input *svcsdk.UpdateApiKeyInput, delta
65
70
patchOps := patchSet .GetPatchOperations ()
66
71
input .PatchOperations = append (patchOps , stageKeyPatches ... )
67
72
}
73
+
74
+ // syncTags keeps tags in sync by calling TagResource and UntagResource APIs
75
+ func (rm * resourceManager ) syncTags (
76
+ ctx context.Context ,
77
+ desired * resource ,
78
+ latest * resource ,
79
+ ) (err error ) {
80
+ rlog := ackrtlog .FromContext (ctx )
81
+ exit := rlog .Trace ("rm.syncTags" )
82
+ defer func () {
83
+ exit (err )
84
+ }()
85
+
86
+ if latest .ko .Status .ACKResourceMetadata == nil || latest .ko .Status .ACKResourceMetadata .ARN == nil {
87
+ return fmt .Errorf ("resource ARN is nil" )
88
+ }
89
+
90
+ resourceARN := aws .String (string (* latest .ko .Status .ACKResourceMetadata .ARN ))
91
+
92
+ desiredTagsMap := desired .ko .Spec .Tags
93
+ latestTagsMap := latest .ko .Spec .Tags
94
+
95
+ desiredTags , _ := convertToOrderedACKTags (desiredTagsMap )
96
+ latestTags , _ := convertToOrderedACKTags (latestTagsMap )
97
+
98
+ added , updated , removed := ackcompare .GetTagsDifference (latestTags , desiredTags )
99
+
100
+ // Combine added and updated tags
101
+ toAdd := make (map [string ]string )
102
+ for k , v := range added {
103
+ toAdd [k ] = v
104
+ }
105
+ for k , v := range updated {
106
+ toAdd [k ] = v
107
+ }
108
+
109
+ var toRemoveTagKeys []string
110
+ for k := range removed {
111
+ toRemoveTagKeys = append (toRemoveTagKeys , k )
112
+ }
113
+
114
+ // Remove tags using UntagResource API:
115
+ if len (toRemoveTagKeys ) > 0 {
116
+ rlog .Debug ("removing tags from resource" , "tags" , toRemoveTagKeys )
117
+ _ , err = rm .sdkapi .UntagResource (
118
+ ctx ,
119
+ & svcsdk.UntagResourceInput {
120
+ ResourceArn : resourceARN ,
121
+ TagKeys : toRemoveTagKeys ,
122
+ },
123
+ )
124
+ rm .metrics .RecordAPICall ("UPDATE" , "UntagResource" , err )
125
+ if err != nil {
126
+ return err
127
+ }
128
+ }
129
+
130
+ // Add tags using TagResource API
131
+ if len (toAdd ) > 0 {
132
+ rlog .Debug ("adding tags to resource" , "tags" , toAdd )
133
+ _ , err = rm .sdkapi .TagResource (
134
+ ctx ,
135
+ & svcsdk.TagResourceInput {
136
+ ResourceArn : resourceARN ,
137
+ Tags : toAdd ,
138
+ },
139
+ )
140
+ rm .metrics .RecordAPICall ("UPDATE" , "TagResource" , err )
141
+ if err != nil {
142
+ return err
143
+ }
144
+ }
145
+
146
+ return nil
147
+ }
148
+
149
+ func compareTags (
150
+ delta * ackcompare.Delta ,
151
+ a * resource ,
152
+ b * resource ,
153
+ ) {
154
+ if len (a .ko .Spec .Tags ) != len (b .ko .Spec .Tags ) {
155
+ delta .Add ("Spec.Tags" , a .ko .Spec .Tags , b .ko .Spec .Tags )
156
+ } else if len (a .ko .Spec .Tags ) > 0 {
157
+ // Convert map[string]*string to acktags.Tags for GetTagsDifference
158
+ aTagsConverted , _ := convertToOrderedACKTags (a .ko .Spec .Tags )
159
+ bTagsConverted , _ := convertToOrderedACKTags (b .ko .Spec .Tags )
160
+
161
+ added , updated , removed := ackcompare .GetTagsDifference (bTagsConverted , aTagsConverted )
162
+ if len (added ) != 0 || len (updated ) != 0 || len (removed ) != 0 {
163
+ delta .Add ("Spec.Tags" , a .ko .Spec .Tags , b .ko .Spec .Tags )
164
+ }
165
+ }
166
+ }
167
+
168
+ // fetchCurrentTags returns the current tags for the resource
169
+ // using the GetTags API: GET /tags/resource_arn
170
+ func (rm * resourceManager ) fetchCurrentTags (
171
+ ctx context.Context ,
172
+ resourceARN * string ,
173
+ ) (map [string ]string , error ) {
174
+ output , err := rm .sdkapi .GetTags (
175
+ ctx ,
176
+ & svcsdk.GetTagsInput {
177
+ ResourceArn : resourceARN ,
178
+ },
179
+ )
180
+
181
+ if err != nil {
182
+ return nil , err
183
+ }
184
+
185
+ return output .Tags , nil
186
+ }
187
+
188
+ // CustomResourcesDifference helps return differences in custom resources
189
+ func (rm * resourceManager ) CustomResourcesDifference (
190
+ a * resource ,
191
+ b * resource ,
192
+ ) * ackcompare.Delta {
193
+ delta := ackcompare .NewDelta ()
194
+ compareTags (delta , a , b )
195
+ return delta
196
+ }
0 commit comments