Skip to content

Commit 99f620a

Browse files
authored
Minor Refactor in pkg/generate/code (#150)
Issue #, if available: [#890](aws-controllers-k8s/community#890) * This is preliminary work to aid in resolving this issue. A PR will follow to close out this issue completely. Description of changes: * Adds `getSanitizedMemberPath` helper to **check.go** * Adds new file `common.go` containing helpers that can be used throughout `code` pkg. These 2 helpers make it easier to extract identifier(s) from a given Shape or CRD Testing: * `make test` ✅ By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 4d0db1b commit 99f620a

File tree

4 files changed

+229
-26
lines changed

4 files changed

+229
-26
lines changed

pkg/generate/code/check.go

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -132,32 +132,17 @@ func checkRequiredFieldsMissingFromShape(
132132
missing = append(missing, primaryARNCondition)
133133
continue
134134
}
135-
cleanMemberNames := names.New(memberName)
136-
cleanMemberName := cleanMemberNames.Camel
137135

138-
resVarPath := koVarName
139-
// Check that the field has potentially been renamed
140-
renamedName, wasRenamed := r.InputFieldRename(
141-
op.Name, memberName,
142-
)
143-
_, found := r.SpecFields[renamedName]
144-
if found && !wasRenamed {
145-
resVarPath = resVarPath + r.Config().PrefixConfig.SpecField + "." + cleanMemberName
146-
} else if found {
147-
resVarPath = resVarPath + r.Config().PrefixConfig.SpecField + "." + renamedName
148-
} else {
149-
_, found = r.StatusFields[memberName]
150-
if !found {
151-
// If it isn't in our spec/status fields, we have a problem!
152-
msg := fmt.Sprintf(
153-
"GENERATION FAILURE! there's a required field %s in "+
154-
"Shape %s that isn't in either the CR's Spec or "+
155-
"Status structs!",
156-
memberName, shape.ShapeName,
157-
)
158-
panic(msg)
159-
}
160-
resVarPath = resVarPath + r.Config().PrefixConfig.StatusField + "." + cleanMemberName
136+
resVarPath, err := getSanitizedMemberPath(memberName, r, op, koVarName)
137+
if err != nil {
138+
// If it isn't in our spec/status fields, we have a problem!
139+
msg := fmt.Sprintf(
140+
"GENERATION FAILURE! there's a required field %s in "+
141+
"Shape %s that isn't in either the CR's Spec or "+
142+
"Status structs!",
143+
memberName, shape.ShapeName,
144+
)
145+
panic(msg)
161146
}
162147
missing = append(missing, fmt.Sprintf("%s == nil", resVarPath))
163148
}
@@ -166,3 +151,34 @@ func checkRequiredFieldsMissingFromShape(
166151
missingCondition := strings.Join(missing, " || ")
167152
return fmt.Sprintf("%sreturn %s\n", indent, missingCondition)
168153
}
154+
155+
// getSanitizedMemberPath takes a shape member field, checks for renames, checks
156+
// for existence in Spec and Status, then constructs and returns the var path.
157+
// Returns error if memberName is not present in either Spec or Status.
158+
func getSanitizedMemberPath(
159+
memberName string,
160+
r *model.CRD,
161+
op *awssdkmodel.Operation,
162+
koVarName string) (string, error) {
163+
resVarPath := koVarName
164+
cleanMemberNames := names.New(memberName)
165+
cleanMemberName := cleanMemberNames.Camel
166+
// Check that the field has potentially been renamed
167+
renamedName, wasRenamed := r.InputFieldRename(
168+
op.Name, memberName,
169+
)
170+
_, found := r.SpecFields[renamedName]
171+
if found && !wasRenamed {
172+
resVarPath = resVarPath + r.Config().PrefixConfig.SpecField + "." + cleanMemberName
173+
} else if found {
174+
resVarPath = resVarPath + r.Config().PrefixConfig.SpecField + "." + renamedName
175+
} else {
176+
_, found = r.StatusFields[memberName]
177+
if !found {
178+
return "", fmt.Errorf(
179+
"the required field %s is NOT present in CR's Spec or Status", memberName)
180+
}
181+
resVarPath = resVarPath + r.Config().PrefixConfig.StatusField + "." + cleanMemberName
182+
}
183+
return resVarPath, nil
184+
}

pkg/generate/code/common.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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+
awssdkmodel "github.com/aws/aws-sdk-go/private/model/api"
18+
19+
"github.com/aws-controllers-k8s/code-generator/pkg/model"
20+
"github.com/aws-controllers-k8s/code-generator/pkg/util"
21+
)
22+
23+
// FindIdentifiersInShape returns the identifier fields of a given shape which
24+
// can be singular or plural. Errors iff multiple identifier fields detected
25+
// in the shape.
26+
func FindIdentifiersInShape(
27+
r *model.CRD,
28+
shape *awssdkmodel.Shape) []string {
29+
identifierLookup := []string{
30+
"Id",
31+
"Ids",
32+
"Name",
33+
"Names",
34+
r.Names.Original + "Name",
35+
r.Names.Original + "Names",
36+
r.Names.Original + "Id",
37+
r.Names.Original + "Ids",
38+
}
39+
var identifiers []string
40+
41+
for _, memberName := range shape.MemberNames() {
42+
if util.InStrings(memberName, identifierLookup) {
43+
identifiers = append(identifiers, memberName)
44+
}
45+
}
46+
47+
return identifiers
48+
}
49+
50+
// FindIdentifiersInCRD returns the identifier field of a given CRD which
51+
// can be singular or plural. Errors iff multiple identifier fields detected
52+
// in the CRD.
53+
func FindIdentifiersInCRD(
54+
r *model.CRD) []string {
55+
identifierLookup := []string{
56+
"Id",
57+
"Ids",
58+
"Name",
59+
"Names",
60+
r.Names.Original + "Name",
61+
r.Names.Original + "Names",
62+
r.Names.Original + "Id",
63+
r.Names.Original + "Ids",
64+
}
65+
var identifiers []string
66+
67+
for _, id := range identifierLookup {
68+
_, found := r.SpecFields[id]
69+
if !found {
70+
_, found = r.StatusFields[id]
71+
}
72+
if found {
73+
identifiers = append(identifiers, id)
74+
}
75+
}
76+
77+
return identifiers
78+
}

pkg/generate/code/common_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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+
"strings"
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
"github.com/stretchr/testify/require"
22+
23+
"github.com/aws-controllers-k8s/code-generator/pkg/generate/code"
24+
"github.com/aws-controllers-k8s/code-generator/pkg/testutil"
25+
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
26+
)
27+
28+
func TestFindIdentifiersInShape_EC2_VPC_ReadMany(t *testing.T) {
29+
assert := assert.New(t)
30+
require := require.New(t)
31+
32+
g := testutil.NewModelForService(t, "ec2")
33+
34+
crd := testutil.GetCRDByName(t, g, "Vpc")
35+
require.NotNil(crd)
36+
37+
expIdentifier := "VpcIds"
38+
actualIdentifiers := code.FindIdentifiersInShape(crd,
39+
crd.Ops.ReadMany.InputRef.Shape)
40+
assert.Len(actualIdentifiers, 1)
41+
assert.Equal(
42+
strings.TrimSpace(expIdentifier),
43+
strings.TrimSpace(actualIdentifiers[0]),
44+
)
45+
}
46+
47+
func TestFindIdentifiersInCRD_S3_Bucket_ReadMany_Empty(t *testing.T) {
48+
assert := assert.New(t)
49+
require := require.New(t)
50+
51+
g := testutil.NewModelForService(t, "s3")
52+
53+
crd := testutil.GetCRDByName(t, g, "Bucket")
54+
require.NotNil(crd)
55+
56+
actualIdentifiers := code.FindIdentifiersInShape(crd,
57+
crd.Ops.ReadMany.InputRef.Shape)
58+
assert.Len(actualIdentifiers, 0)
59+
}
60+
61+
func TestFindIdentifiersInCRD_EC2_VPC_StatusField(t *testing.T) {
62+
assert := assert.New(t)
63+
require := require.New(t)
64+
65+
g := testutil.NewModelForService(t, "ec2")
66+
67+
crd := testutil.GetCRDByName(t, g, "Vpc")
68+
require.NotNil(crd)
69+
70+
expIdentifier := "VpcId"
71+
actualIdentifiers := code.FindIdentifiersInCRD(crd)
72+
assert.Len(actualIdentifiers, 1)
73+
assert.Equal(
74+
strings.TrimSpace(expIdentifier),
75+
strings.TrimSpace(actualIdentifiers[0]),
76+
)
77+
}
78+
79+
func TestFindIdentifiersInCRD_S3_Bucket_SpecField(t *testing.T) {
80+
assert := assert.New(t)
81+
require := require.New(t)
82+
83+
g := testutil.NewModelForService(t, "s3")
84+
85+
crd := testutil.GetCRDByName(t, g, "Bucket")
86+
require.NotNil(crd)
87+
88+
expIdentifier := "Name"
89+
actualIdentifiers := code.FindIdentifiersInCRD(crd)
90+
assert.Len(actualIdentifiers, 1)
91+
assert.Equal(
92+
strings.TrimSpace(expIdentifier),
93+
strings.TrimSpace(actualIdentifiers[0]),
94+
)
95+
}
96+
97+
func TestFindIdentifiersInCRD_APIGatewayV2_API_Multiple(t *testing.T) {
98+
assert := assert.New(t)
99+
require := require.New(t)
100+
101+
g := testutil.NewModelForService(t, "apigatewayv2")
102+
crd := testutil.GetCRDByName(t, g, "Api")
103+
require.NotNil(crd)
104+
105+
expIdentifiers := []string{"ApiId", "Name"}
106+
actualIdentifiers := code.FindIdentifiersInCRD(crd)
107+
assert.Len(actualIdentifiers, 2)
108+
assert.True(ackcompare.SliceStringEqual(expIdentifiers, actualIdentifiers))
109+
}

pkg/testdata/models/apis/ec2/0000-00-00/generator.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ ignore:
5252
- VpcEndpointConnectionNotification
5353
- VpcEndpointServiceConfiguration
5454
- VpcEndpoint
55-
- Vpc
55+
# - Vpc
5656
- VpcCidrBlock
5757
- VpcPeeringConnection
5858
- VpnConnectionRoute

0 commit comments

Comments
 (0)