Skip to content

Commit c5235cb

Browse files
UpdateTags support for InternetGateway resource (#94)
Description of changes: - Implemented update tags support for **Internet Gateway** resource. - Added integration tests for the same. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent a8e9391 commit c5235cb

File tree

9 files changed

+225
-4
lines changed

9 files changed

+225
-4
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
ack_generate_info:
2-
build_date: "2022-09-13T16:18:40Z"
2+
build_date: "2022-09-13T21:29:16Z"
33
build_hash: 585f06bbd6d4cc1b738acb85901e7a009bf452c7
44
go_version: go1.18.3
55
version: v0.20.0
66
api_directory_checksum: 3960da50b98c36b05635d3abbfd129ae7bb48e32
77
api_version: v1alpha1
88
aws_sdk_go_version: v1.42.0
99
generator_config_info:
10-
file_checksum: 7862e66fc124ed9cba5b17483244f5619039eb23
10+
file_checksum: 6dda562aa9c69e0c93f33141f2c5a671456fc306
1111
original_file_name: generator.yaml
1212
last_modification:
1313
reason: API generation

apis/v1alpha1/generator.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ resources:
247247
template_path: hooks/internet_gateway/sdk_read_many_post_set_output.go.tpl
248248
sdk_delete_pre_build_request:
249249
template_path: hooks/internet_gateway/sdk_delete_pre_build_request.go.tpl
250+
sdk_file_end:
251+
template_path: hooks/internet_gateway/sdk_file_end.go.tpl
250252
update_operation:
251253
custom_method_name: customUpdateInternetGateway
252254
NatGateway:

generator.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ resources:
247247
template_path: hooks/internet_gateway/sdk_read_many_post_set_output.go.tpl
248248
sdk_delete_pre_build_request:
249249
template_path: hooks/internet_gateway/sdk_delete_pre_build_request.go.tpl
250+
sdk_file_end:
251+
template_path: hooks/internet_gateway/sdk_file_end.go.tpl
250252
update_operation:
251253
custom_method_name: customUpdateInternetGateway
252254
NatGateway:

pkg/resource/internet_gateway/hook.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package internet_gateway
1616
import (
1717
"context"
1818

19+
svcapitypes "github.com/aws-controllers-k8s/ec2-controller/apis/v1alpha1"
1920
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
2021
ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log"
2122
svcsdk "github.com/aws/aws-sdk-go/service/ec2"
@@ -49,6 +50,12 @@ func (rm *resourceManager) customUpdateInternetGateway(
4950
}
5051
}
5152

53+
if delta.DifferentAt("Spec.Tags") {
54+
if err = rm.syncTags(ctx, desired, latest); err != nil {
55+
return nil, err
56+
}
57+
}
58+
5259
return &resource{ko}, nil
5360
}
5461

@@ -131,6 +138,105 @@ func (rm *resourceManager) detachFromVPC(
131138
return nil
132139
}
133140

141+
// syncTags used to keep tags in sync by calling Create and Delete Tags API's
142+
func (rm *resourceManager) syncTags(
143+
ctx context.Context,
144+
desired *resource,
145+
latest *resource,
146+
) (err error) {
147+
rlog := ackrtlog.FromContext(ctx)
148+
exit := rlog.Trace("rm.syncTags")
149+
defer func(err error) {
150+
exit(err)
151+
}(err)
152+
153+
resourceId := []*string{latest.ko.Status.InternetGatewayID}
154+
155+
toAdd, toDelete := computeTagsDelta(
156+
desired.ko.Spec.Tags, latest.ko.Spec.Tags,
157+
)
158+
159+
if len(toDelete) > 0 {
160+
rlog.Debug("removing tags from InternetGateway resource", "tags", toDelete)
161+
_, err = rm.sdkapi.DeleteTagsWithContext(
162+
ctx,
163+
&svcsdk.DeleteTagsInput{
164+
Resources: resourceId,
165+
Tags: rm.sdkTags(toDelete),
166+
},
167+
)
168+
rm.metrics.RecordAPICall("UPDATE", "DeleteTags", err)
169+
if err != nil {
170+
return err
171+
}
172+
173+
}
174+
175+
if len(toAdd) > 0 {
176+
rlog.Debug("adding tags to InternetGateway resource", "tags", toAdd)
177+
_, err = rm.sdkapi.CreateTagsWithContext(
178+
ctx,
179+
&svcsdk.CreateTagsInput{
180+
Resources: resourceId,
181+
Tags: rm.sdkTags(toAdd),
182+
},
183+
)
184+
rm.metrics.RecordAPICall("UPDATE", "CreateTags", err)
185+
if err != nil {
186+
return err
187+
}
188+
}
189+
190+
return nil
191+
}
192+
193+
// sdkTags converts *svcapitypes.Tag array to a *svcsdk.Tag array
194+
func (rm *resourceManager) sdkTags(
195+
tags []*svcapitypes.Tag,
196+
) (sdktags []*svcsdk.Tag) {
197+
198+
for _, i := range tags {
199+
sdktag := rm.newTag(*i)
200+
sdktags = append(sdktags, sdktag)
201+
}
202+
203+
return sdktags
204+
}
205+
206+
// computeTagsDelta returns tags to be added and removed from the resource
207+
func computeTagsDelta(
208+
desired []*svcapitypes.Tag,
209+
latest []*svcapitypes.Tag,
210+
) (toAdd []*svcapitypes.Tag, toDelete []*svcapitypes.Tag) {
211+
212+
desiredTags := map[string]string{}
213+
for _, tag := range desired {
214+
desiredTags[*tag.Key] = *tag.Value
215+
}
216+
217+
latestTags := map[string]string{}
218+
for _, tag := range latest {
219+
latestTags[*tag.Key] = *tag.Value
220+
}
221+
222+
for _, tag := range desired {
223+
val, ok := latestTags[*tag.Key]
224+
if !ok || val != *tag.Value {
225+
toAdd = append(toAdd, tag)
226+
}
227+
}
228+
229+
for _, tag := range latest {
230+
_, ok := desiredTags[*tag.Key]
231+
if !ok {
232+
toDelete = append(toDelete, tag)
233+
}
234+
}
235+
236+
return toAdd, toDelete
237+
238+
}
239+
134240
// updateTagSpecificationsInCreateRequest adds
135241
// Tags defined in the Spec to CreateInternetGatewayInput.TagSpecification
136242
// and ensures the ResourceType is always set to 'internet-gateway'

pkg/resource/internet_gateway/sdk.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/resource/subnet/hooks.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ func toStrPtr(str string) *string {
250250
return &str
251251
}
252252

253-
// syncTags used to keep tags in sync using createTags and deleteTags functions
253+
// syncTags used to keep tags in sync by calling Create and Delete Tags API's
254254
func (rm *resourceManager) syncTags(
255255
ctx context.Context,
256256
desired *resource,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{{ $CRD := .CRD }}
2+
{{ $SDKAPI := .SDKAPI }}
3+
4+
{{/* Generate helper methods for Internet Gateway */}}
5+
{{- range $specFieldName, $specField := $CRD.Config.Resources.InternetGateway.Fields }}
6+
{{- if $specField.From }}
7+
{{- $operationName := $specField.From.Operation }}
8+
{{- $operation := (index $SDKAPI.API.Operations $operationName) -}}
9+
{{- range $igwRefName, $igwMemberRefs := $operation.InputRef.Shape.MemberRefs -}}
10+
{{- if eq $igwRefName "Tags" }}
11+
{{- $igwRef := $igwMemberRefs.Shape.MemberRef }}
12+
{{- $igwRefName = "Tag" }}
13+
func (rm *resourceManager) new{{ $igwRefName }}(
14+
c svcapitypes.{{ $igwRefName }},
15+
) *svcsdk.{{ $igwRefName }} {
16+
res := &svcsdk.{{ $igwRefName }}{}
17+
{{ GoCodeSetSDKForStruct $CRD "" "res" $igwRef "" "c" 1 }}
18+
return res
19+
}
20+
{{- end }}
21+
{{- end }}
22+
{{- end }}
23+
{{- end }}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
apiVersion: ec2.services.k8s.aws/v1alpha1
22
kind: InternetGateway
33
metadata:
4-
name: $INTERNET_GATEWAY_NAME
4+
name: $INTERNET_GATEWAY_NAME
5+
spec:
6+
tags:
7+
- key: $TAG_KEY
8+
value: $TAG_VALUE

test/e2e/tests/test_internet_gateway.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ def simple_internet_gateway(request, simple_vpc):
5050
(_, vpc_cr) = simple_vpc
5151
vpc_id = vpc_cr["status"]["vpcID"]
5252
replacements["VPC_ID"] = vpc_id
53+
if 'tag_key' in data:
54+
replacements["TAG_KEY"] = data["tag_key"]
55+
if 'tag_value' in data:
56+
replacements["TAG_VALUE"] = data["tag_value"]
5357

5458
# Load Internet Gateway CR
5559
resource_data = load_ec2_resource(
@@ -141,4 +145,70 @@ def test_vpc_association(self, ec2_client, simple_internet_gateway):
141145
time.sleep(DELETE_WAIT_AFTER_SECONDS)
142146

143147
# Check Internet Gateway no longer exists in AWS
148+
ec2_validator.assert_internet_gateway(resource_id, exists=False)
149+
150+
@pytest.mark.resource_data({'tag_key': 'initialtagkey', 'tag_value': 'initialtagvalue'})
151+
def test_crud_tags(self, ec2_client, simple_internet_gateway):
152+
(ref, cr) = simple_internet_gateway
153+
154+
resource = k8s.get_resource(ref)
155+
resource_id = cr["status"]["internetGatewayID"]
156+
157+
time.sleep(CREATE_WAIT_AFTER_SECONDS)
158+
159+
# Check IGW exists in AWS
160+
ec2_validator = EC2Validator(ec2_client)
161+
ec2_validator.assert_internet_gateway(resource_id)
162+
163+
# Check tags exist for IGW resource
164+
assert resource["spec"]["tags"][0]["key"] == "initialtagkey"
165+
assert resource["spec"]["tags"][0]["value"] == "initialtagvalue"
166+
167+
# New pair of tags
168+
new_tags = [
169+
{
170+
"key": "updatedtagkey",
171+
"value": "updatedtagvalue",
172+
}
173+
174+
]
175+
176+
# Patch the IGW, updating the tags with new pair
177+
updates = {
178+
"spec": {"tags": new_tags},
179+
}
180+
181+
k8s.patch_custom_resource(ref, updates)
182+
time.sleep(MODIFY_WAIT_AFTER_SECONDS)
183+
184+
# Check resource synced successfully
185+
assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=5)
186+
187+
# Assert tags are updated for IGW resource
188+
resource = k8s.get_resource(ref)
189+
assert resource["spec"]["tags"][0]["key"] == "updatedtagkey"
190+
assert resource["spec"]["tags"][0]["value"] == "updatedtagvalue"
191+
192+
# Patch the IGW resource, deleting the tags
193+
updates = {
194+
"spec": {"tags": []},
195+
}
196+
197+
k8s.patch_custom_resource(ref, updates)
198+
time.sleep(MODIFY_WAIT_AFTER_SECONDS)
199+
200+
# Check resource synced successfully
201+
assert k8s.wait_on_condition(ref, "ACK.ResourceSynced", "True", wait_periods=5)
202+
203+
# Assert tags are deleted
204+
resource = k8s.get_resource(ref)
205+
assert len(resource['spec']['tags']) == 0
206+
207+
# Delete k8s resource
208+
_, deleted = k8s.delete_custom_resource(ref)
209+
assert deleted is True
210+
211+
time.sleep(DELETE_WAIT_AFTER_SECONDS)
212+
213+
# Check IGW no longer exists in AWS
144214
ec2_validator.assert_internet_gateway(resource_id, exists=False)

0 commit comments

Comments
 (0)