Skip to content

Commit 0ab258c

Browse files
authored
Merge pull request #573 from michaelhtm/change-to/fromACKsign
Replace To/FromACKTags with to/fromACKTagsWithKeyOrder
2 parents ca12303 + becb821 commit 0ab258c

File tree

7 files changed

+335
-123
lines changed

7 files changed

+335
-123
lines changed

pkg/generate/ack/controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,12 @@ var (
203203
"GoCodeClearResolvedReferences": func(f *ackmodel.Field, targetVarName string, indentLevel int) string {
204204
return code.ClearResolvedReferencesForField(f, targetVarName, indentLevel)
205205
},
206+
"GoCodeConvertToACKTags": func(r *ackmodel.CRD, sourceVarName string, targetVarName string, keyOrderVarName string, indentLevel int) string {
207+
return code.GoCodeConvertToACKTags(r, sourceVarName, targetVarName, keyOrderVarName, indentLevel)
208+
},
209+
"GoCodeFromACKTags": func(r *ackmodel.CRD, sourceVarName string, orderVarName string, targetVarName string, indentLevel int) string {
210+
return code.GoCodeFromACKTags(r, sourceVarName, orderVarName, targetVarName, indentLevel)
211+
},
206212
}
207213
)
208214

pkg/generate/code/compare.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,9 +523,11 @@ func compareSlice(
523523
//
524524
// Output code will look something like this:
525525
//
526-
// if !ackcompare.MapStringStringEqual(ToACKTags(a.ko.Spec.Tags), ToACKTags(b.ko.Spec.Tags)) {
527-
// delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags)
528-
// }
526+
// desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags)
527+
// latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags)
528+
// if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) {
529+
// delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags)
530+
// }
529531
func compareTags(
530532
// String representing the name of the variable that is of type
531533
// `*ackcompare.Delta`. We will generate Go code that calls the `Add()`
@@ -549,7 +551,9 @@ func compareTags(
549551
out := ""
550552
indent := strings.Repeat("\t", indentLevel)
551553

552-
out += fmt.Sprintf("%sif !ackcompare.MapStringStringEqual(ToACKTags(%s), ToACKTags(%s)) {\n", indent, firstResVarName, secondResVarName)
554+
out += fmt.Sprintf("%sdesiredACKTags, _ := convertToOrderedACKTags(%s)\n", indent, firstResVarName)
555+
out += fmt.Sprintf("%slatestACKTags, _ := convertToOrderedACKTags(%s)\n", indent, secondResVarName)
556+
out += fmt.Sprintf("%sif !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) {\n", indent)
553557
out += fmt.Sprintf("%s\t%s.Add(\"%s\", %s, %s)\n", indent, deltaVarName, fieldPath, firstResVarName, secondResVarName)
554558
out += fmt.Sprintf("%s}\n", indent)
555559

pkg/generate/code/compare_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ func TestCompareResource_S3_Bucket(t *testing.T) {
127127
if ackcompare.HasNilDifference(a.ko.Spec.Tagging, b.ko.Spec.Tagging) {
128128
delta.Add("Spec.Tagging", a.ko.Spec.Tagging, b.ko.Spec.Tagging)
129129
} else if a.ko.Spec.Tagging != nil && b.ko.Spec.Tagging != nil {
130-
if !ackcompare.MapStringStringEqual(ToACKTags(a.ko.Spec.Tagging.TagSet), ToACKTags(b.ko.Spec.Tagging.TagSet)) {
130+
desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tagging.TagSet)
131+
latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tagging.TagSet)
132+
if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) {
131133
delta.Add("Spec.Tagging", a.ko.Spec.Tagging.TagSet, b.ko.Spec.Tagging.TagSet)
132134
}
133135
}
@@ -364,7 +366,9 @@ func TestCompareResource_Lambda_Function(t *testing.T) {
364366
delta.Add("Spec.Runtime", a.ko.Spec.Runtime, b.ko.Spec.Runtime)
365367
}
366368
}
367-
if !ackcompare.MapStringStringEqual(ToACKTags(a.ko.Spec.Tags), ToACKTags(b.ko.Spec.Tags)) {
369+
desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags)
370+
latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags)
371+
if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) {
368372
delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags)
369373
}
370374
if ackcompare.HasNilDifference(a.ko.Spec.Timeout, b.ko.Spec.Timeout) {
@@ -533,7 +537,9 @@ func TestCompareResource_IAM_OIDC_URL(t *testing.T) {
533537
delta.Add("Spec.ClientIDList", a.ko.Spec.ClientIDList, b.ko.Spec.ClientIDList)
534538
}
535539
}
536-
if !ackcompare.MapStringStringEqual(ToACKTags(a.ko.Spec.Tags), ToACKTags(b.ko.Spec.Tags)) {
540+
desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags)
541+
latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags)
542+
if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) {
537543
delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags)
538544
}
539545
if len(a.ko.Spec.ThumbprintList) != len(b.ko.Spec.ThumbprintList) {
@@ -586,7 +592,9 @@ func TestCompareResource_MemoryDB_User(t *testing.T) {
586592
delta.Add("Spec.Name", a.ko.Spec.Name, b.ko.Spec.Name)
587593
}
588594
}
589-
if !ackcompare.MapStringStringEqual(ToACKTags(a.ko.Spec.Tags), ToACKTags(b.ko.Spec.Tags)) {
595+
desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags)
596+
latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags)
597+
if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) {
590598
delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags)
591599
}
592600
`

pkg/generate/code/tags.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package code
15+
16+
import (
17+
"fmt"
18+
"strings"
19+
20+
"github.com/aws-controllers-k8s/code-generator/pkg/model"
21+
)
22+
23+
// GoCodeToACKTags returns Go code that converts Resource Tags
24+
// to ACK Tags. If Resource Tags field is of type list, we
25+
// also maintain and return the order of the list as a []string
26+
//
27+
//
28+
//
29+
// Sample output:
30+
//
31+
// for _, k := range keyOrder {
32+
// v, ok := tags[k]
33+
// if ok {
34+
// tag := svcapitypes.Tag{Key: &k, Value: &v}
35+
// result = append(result, &tag)
36+
// delete(tags, k)
37+
// }
38+
// }
39+
// for k, v := range tags {
40+
// tag := svcapitypes.Tag{Key: &k, Value: &v}
41+
// result = append(result, &tag)
42+
// }
43+
func GoCodeConvertToACKTags(r *model.CRD, sourceVarName string, targetVarName string, keyOrderVarName string, indentLevel int) string {
44+
45+
out := "\n"
46+
indent := strings.Repeat("\t", indentLevel)
47+
tagField, err := r.GetTagField()
48+
if err != nil {
49+
panic("error: resource does not have tags. ignore in generator.yaml")
50+
}
51+
52+
if tagField == nil {
53+
return ""
54+
}
55+
56+
tagFieldShapeType := tagField.ShapeRef.Shape.Type
57+
keyMemberName := r.GetTagKeyMemberName()
58+
valueMemberName := r.GetTagValueMemberName()
59+
60+
out += fmt.Sprintf("%sif len(%s) == 0 {\n", indent, sourceVarName)
61+
out += fmt.Sprintf("%s\treturn %s, %s\n", indent, targetVarName, keyOrderVarName)
62+
out += fmt.Sprintf("%s}\n", indent)
63+
64+
switch tagFieldShapeType {
65+
case "list":
66+
out += fmt.Sprintf("%sfor _, t := range %s {\n", indent, sourceVarName)
67+
out += fmt.Sprintf("%s\tif t.%s != nil {\n", indent, keyMemberName)
68+
out += fmt.Sprintf("%s\t\t%s = append(%s, *t.%s)\n", indent, keyOrderVarName, keyOrderVarName, keyMemberName)
69+
out += fmt.Sprintf("%s\t\tif t.%s != nil {\n", indent, valueMemberName)
70+
out += fmt.Sprintf("%s\t\t\t%s[*t.%s] = *t.%s\n", indent, targetVarName, keyMemberName, valueMemberName)
71+
out += fmt.Sprintf("%s\t\t} else {\n", indent)
72+
out += fmt.Sprintf("%s\t\t\t%s[*t.%s] = \"\"\n", indent, targetVarName, keyMemberName)
73+
out += fmt.Sprintf("%s\t\t}\n", indent)
74+
out += fmt.Sprintf("%s\t}\n", indent)
75+
out += fmt.Sprintf("%s}\n", indent)
76+
77+
case "map":
78+
out += fmt.Sprintf("%sfor k, v := range %s {\n", indent, sourceVarName)
79+
out += fmt.Sprintf("%s\tif v == nil {\n", indent)
80+
out += fmt.Sprintf("%s\t\t%s[k] = \"\"\n", indent, targetVarName)
81+
out += fmt.Sprintf("%s\t} else {\n", indent)
82+
out += fmt.Sprintf("%s\t\t%s[k] = *v\n", indent, targetVarName)
83+
out += fmt.Sprintf("%s\t}\n", indent)
84+
out += fmt.Sprintf("%s}\n", indent)
85+
default:
86+
msg := "error: tag type can only be a list or a map"
87+
panic(msg)
88+
}
89+
90+
return out
91+
}
92+
93+
// GoCodeFromACKTags returns Go code that converts ACKTags
94+
// to the Resource Tag shape type. Tag fields can only be
95+
// maps or lists of Tag Go type. If Tag field is a list,
96+
// when converting from ACK Tags, we try to preserve the
97+
// original order
98+
//
99+
//
100+
//
101+
// Sample output:
102+
//
103+
// for _, k := range keyOrder {
104+
// v, ok := tags[k]
105+
// if ok {
106+
// tag := svcapitypes.Tag{Key: &k, Value: &v}
107+
// result = append(result, &tag)
108+
// delete(tags, k)
109+
// }
110+
// }
111+
// for k, v := range tags {
112+
// tag := svcapitypes.Tag{Key: &k, Value: &v}
113+
// result = append(result, &tag)
114+
// }
115+
func GoCodeFromACKTags(r *model.CRD, tagsSourceVarName string, orderVarName string, targetVarName string, indentLevel int) string {
116+
out := "\n"
117+
indent := strings.Repeat("\t", indentLevel)
118+
tagField, _ := r.GetTagField()
119+
120+
if tagField == nil {
121+
return ""
122+
}
123+
124+
tagFieldShapeType := tagField.ShapeRef.Shape.Type
125+
tagFieldGoType := tagField.GoTypeElem
126+
keyMemberName := r.GetTagKeyMemberName()
127+
valueMemberName := r.GetTagValueMemberName()
128+
129+
switch tagFieldShapeType {
130+
case "list":
131+
out += fmt.Sprintf("%sfor _, k := range %s {\n", indent, orderVarName)
132+
out += fmt.Sprintf("%s\tv, ok := %s[k]\n", indent, tagsSourceVarName)
133+
out += fmt.Sprintf("%s\tif ok {\n", indent)
134+
out += fmt.Sprintf("%s\t\ttag := svcapitypes.%s{%s: &k, %s: &v}\n", indent, tagFieldGoType, keyMemberName, valueMemberName)
135+
out += fmt.Sprintf("%s\t\t%s = append(%s, &tag)\n", indent, targetVarName, targetVarName)
136+
out += fmt.Sprintf("%s\t\tdelete(%s, k)\n", indent, tagsSourceVarName)
137+
out += fmt.Sprintf("%s\t}\n", indent)
138+
out += fmt.Sprintf("%s}\n", indent)
139+
case "map":
140+
out += fmt.Sprintf("%s_ = %s\n", indent, orderVarName)
141+
default:
142+
msg := "error: tag type can only be a list of a map"
143+
panic(msg)
144+
}
145+
146+
out += fmt.Sprintf("%sfor k, v := range %s {\n", indent, tagsSourceVarName)
147+
switch tagFieldShapeType {
148+
case "list":
149+
out += fmt.Sprintf("%s\ttag := svcapitypes.%s{%s: &k, %s: &v}\n", indent, tagFieldGoType, keyMemberName, valueMemberName)
150+
out += fmt.Sprintf("%s\t%s = append(%s, &tag)\n", indent, targetVarName, targetVarName)
151+
case "map":
152+
out += fmt.Sprintf("%s\t%s[k] = &v\n", indent, targetVarName)
153+
}
154+
out += fmt.Sprintf("%s}\n", indent)
155+
156+
return out
157+
}

pkg/generate/code/tags_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package code_test
15+
16+
import (
17+
"testing"
18+
19+
"github.com/stretchr/testify/assert"
20+
"github.com/stretchr/testify/require"
21+
22+
"github.com/aws-controllers-k8s/code-generator/pkg/generate/code"
23+
"github.com/aws-controllers-k8s/code-generator/pkg/testutil"
24+
)
25+
26+
func TestToACKTagsForListShape(t *testing.T) {
27+
assert := assert.New(t)
28+
require := require.New(t)
29+
30+
g := testutil.NewModelForService(t, "ec2")
31+
32+
crd := testutil.GetCRDByName(t, g, "Vpc")
33+
require.NotNil(crd)
34+
35+
expectedSyncedConditions := `
36+
if len(tags) == 0 {
37+
return result, keyOrder
38+
}
39+
for _, t := range tags {
40+
if t.Key != nil {
41+
keyOrder = append(keyOrder, *t.Key)
42+
if t.Value != nil {
43+
result[*t.Key] = *t.Value
44+
} else {
45+
result[*t.Key] = ""
46+
}
47+
}
48+
}
49+
`
50+
assert.Equal(
51+
expectedSyncedConditions,
52+
code.GoCodeConvertToACKTags(
53+
crd, "tags", "result", "keyOrder", 1,
54+
),
55+
)
56+
}
57+
58+
func TestToACKTagsForMapShape(t *testing.T) {
59+
assert := assert.New(t)
60+
require := require.New(t)
61+
62+
g := testutil.NewModelForService(t, "apigatewayv2")
63+
64+
crd := testutil.GetCRDByName(t, g, "Api")
65+
require.NotNil(crd)
66+
67+
expectedSyncedConditions := `
68+
if len(tags) == 0 {
69+
return result, keyOrder
70+
}
71+
for k, v := range tags {
72+
if v == nil {
73+
result[k] = ""
74+
} else {
75+
result[k] = *v
76+
}
77+
}
78+
`
79+
assert.Equal(
80+
expectedSyncedConditions,
81+
code.GoCodeConvertToACKTags(
82+
crd, "tags", "result", "keyOrder", 1,
83+
),
84+
)
85+
}
86+
87+
func TestFromACKTagsForListShape(t *testing.T) {
88+
assert := assert.New(t)
89+
require := require.New(t)
90+
91+
g := testutil.NewModelForService(t, "ec2")
92+
93+
crd := testutil.GetCRDByName(t, g, "Vpc")
94+
require.NotNil(crd)
95+
96+
expectedSyncedConditions := `
97+
for _, k := range keyOrder {
98+
v, ok := tags[k]
99+
if ok {
100+
tag := svcapitypes.Tag{Key: &k, Value: &v}
101+
result = append(result, &tag)
102+
delete(tags, k)
103+
}
104+
}
105+
for k, v := range tags {
106+
tag := svcapitypes.Tag{Key: &k, Value: &v}
107+
result = append(result, &tag)
108+
}
109+
`
110+
assert.Equal(
111+
expectedSyncedConditions,
112+
code.GoCodeFromACKTags(
113+
crd, "tags", "keyOrder", "result", 1,
114+
),
115+
)
116+
}
117+
118+
func TestFromACKTagsForMapShape(t *testing.T) {
119+
assert := assert.New(t)
120+
require := require.New(t)
121+
122+
g := testutil.NewModelForService(t, "apigatewayv2")
123+
124+
crd := testutil.GetCRDByName(t, g, "Api")
125+
require.NotNil(crd)
126+
127+
expectedSyncedConditions := `
128+
_ = keyOrder
129+
for k, v := range tags {
130+
result[k] = &v
131+
}
132+
`
133+
assert.Equal(
134+
expectedSyncedConditions,
135+
code.GoCodeFromACKTags(
136+
crd, "tags", "keyOrder", "result", 1,
137+
),
138+
)
139+
}

0 commit comments

Comments
 (0)