Skip to content
Open
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
3 changes: 2 additions & 1 deletion pkg/config/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ type ReferencesConfig struct {
// which contains generator.yaml
ServiceName string `json:"service_name,omitempty"`
// Resource mentions the K8s resource which is read to resolve the
// reference
// reference. It is used as the reference field name prefix when the
// field name consists of an identifier suffix only.
Resource string `json:"resource"`
// SkipResourceStateValidations if true, skips state validations performed during
// ResolveReferences step, that ensure the referenced resource exists in AWS and is synced.
Expand Down
5 changes: 1 addition & 4 deletions pkg/model/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,7 @@ func (f *Field) GetReferenceFieldName() (names.Names, error) {
}
}
if refNamePrefix == "" {
return names.Names{}, fmt.Errorf(
"reference field name cannot be just an identifier suffix (id/arn/name) — field: %s",
f.Names.Original,
)
refNamePrefix = f.FieldConfig.References.Resource
}
refName := refNamePrefix
// If the shape of corresponding field is a list, singularize the refNamePrefix
Expand Down
33 changes: 20 additions & 13 deletions pkg/model/field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,27 +254,34 @@ func TestGetReferenceFieldName(t *testing.T) {
fieldName string
expectedReferenceFieldName string
shapeRef *api.ShapeRef
references *ackgenconfig.ReferencesConfig
}{
{"ClusterName", "ClusterRef", &stringShape},
{"ClusterNames", "ClusterRefs", &listShape},
{"ClusterARN", "ClusterRef", &stringShape},
{"ClusterARNs", "ClusterRefs", &listShape},
{"ClusterID", "ClusterRef", &stringShape},
{"ClusterId", "ClusterRef", &stringShape},
{"ClusterIds", "ClusterRefs", &listShape},
{"ClusterIDs", "ClusterRefs", &listShape},
{"Cluster", "ClusterRef", &stringShape},
{"Clusters", "ClusterRefs", &listShape},
{"ClusterName", "ClusterRef", &stringShape, nil},
{"ClusterNames", "ClusterRefs", &listShape, nil},
{"ClusterARN", "ClusterRef", &stringShape, nil},
{"ClusterARNs", "ClusterRefs", &listShape, nil},
{"ClusterID", "ClusterRef", &stringShape, nil},
{"ClusterId", "ClusterRef", &stringShape, nil},
{"ClusterIds", "ClusterRefs", &listShape, nil},
{"ClusterIDs", "ClusterRefs", &listShape, nil},
{"Cluster", "ClusterRef", &stringShape, nil},
{"Clusters", "ClusterRefs", &listShape, nil},
// When the resource name indicates plural but it is singular. Ex: DHCPOptions
{"Clusters", "ClustersRef", &stringShape},
{"BlueDeploymentId", "BlueDeploymentRef", &stringShape},
{"GreenDeploymentId", "GreenDeploymentRef", &stringShape},
{"Clusters", "ClustersRef", &stringShape, nil},
{"BlueDeploymentId", "BlueDeploymentRef", &stringShape, nil},
{"GreenDeploymentId", "GreenDeploymentRef", &stringShape, nil},
{"Name", "ClusterRef", &stringShape, &ackgenconfig.ReferencesConfig{Resource: "Cluster"}},
{"Names", "ClusterRefs", &listShape, &ackgenconfig.ReferencesConfig{Resource: "Cluster"}},
{"Names", "ClusterRefs", &listShape, &ackgenconfig.ReferencesConfig{Resource: "Clusters"}},
// The resource name is only used when the field name does not contain a prefix itself.
{"ClusterName", "ClusterRef", &stringShape, &ackgenconfig.ReferencesConfig{Resource: "Other"}},
}

for _, tc := range testCases {
f := model.Field{}
f.ShapeRef = tc.shapeRef
f.Names = names.New(tc.fieldName)
f.FieldConfig = &ackgenconfig.FieldConfig{References: tc.references}
refNames, err := f.GetReferenceFieldName()
assert.NoError(err)
referenceFieldName := refNames.Camel
Expand Down
24 changes: 18 additions & 6 deletions pkg/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,9 @@ func (m *Model) processNestedFieldTypeDefs(
}
}
if field.FieldConfig.References != nil {
if err := updateTypeDefAttributeWithReference(crd, fieldPath, tdefs); err != nil {
if err := updateTypeDefAttributeWithReference(
crd, fieldPath, tdefs, field.FieldConfig,
); err != nil {
return fmt.Errorf("resource %q, field %q: %w", crd.Names.Original, fieldPath, err)
}
}
Expand Down Expand Up @@ -1012,13 +1014,18 @@ func setTypeDefAttributeImmutable(crd *CRD, fieldPath string, tdefs []*TypeDef)

// updateTypeDefAttributeWithReference adds a new AWSResourceReference attribute
// for the corresponding attribute represented by fieldPath of nested field
func updateTypeDefAttributeWithReference(crd *CRD, fieldPath string, tdefs []*TypeDef) error {
func updateTypeDefAttributeWithReference(
crd *CRD,
fieldPath string,
tdefs []*TypeDef,
fieldConfig *ackgenconfig.FieldConfig,
) error {
parentFieldTypeDef, fieldAttr, err := getAttributeFromPath(crd, fieldPath, tdefs)
if err != nil {
return err
}
if fieldAttr != nil && parentFieldTypeDef != nil {
if err := addReferenceAttribute(parentFieldTypeDef, fieldAttr); err != nil {
if err := addReferenceAttribute(parentFieldTypeDef, fieldAttr, fieldConfig); err != nil {
return err
}
}
Expand All @@ -1027,13 +1034,18 @@ func updateTypeDefAttributeWithReference(crd *CRD, fieldPath string, tdefs []*Ty

// addReferenceAttribute creates a corresponding reference attribute for
// "attr" attribute and adds it to "td" TypeDef
func addReferenceAttribute(td *TypeDef, attr *Attr) error {
func addReferenceAttribute(
td *TypeDef,
attr *Attr,
fieldConfig *ackgenconfig.FieldConfig,
) error {
// Create a custom "model.Field" to generate ReferenceFieldName and reuse
// the existing method for generating top-level reference fields
fieldShapeRef := awssdkmodel.ShapeRef{Shape: attr.Shape}
field := &Field{
Names: attr.Names,
ShapeRef: &fieldShapeRef,
Names: attr.Names,
ShapeRef: &fieldShapeRef,
FieldConfig: fieldConfig,
}
refAttrName, err := field.GetReferenceFieldName()
if err != nil {
Expand Down
48 changes: 48 additions & 0 deletions pkg/model/model_wafv2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,51 @@ func TestWAFv2_SharedShape_CustomNestedFields(t *testing.T) {
"%s.Rules.Statement.AndStatement should be string type", crd.name)
}
}

// TestWAFv2_NestedReferences verifies that references configured on nested
// ARN fields generate the expected reference field names for RuleGroup and
// WebACL.
func TestWAFv2_NestedReferences(t *testing.T) {
assert := assert.New(t)
require := require.New(t)

g := testutil.NewModelForService(t, "wafv2")

crds, err := g.GetCRDs()
require.NoError(err)

testCases := []struct {
resource string
fieldPath string
refName string
}{
{
resource: "RuleGroup",
fieldPath: "Rules.Statement.IPSetReferenceStatement.ARN",
refName: "IPSetRef",
},
{
resource: "WebACL",
fieldPath: "Rules.Statement.IPSetReferenceStatement.ARN",
refName: "IPSetRef",
},
{
resource: "WebACL",
fieldPath: "Rules.Statement.RuleGroupReferenceStatement.ARN",
refName: "RuleGroupRef",
},
}

for _, tc := range testCases {
crd := getCRDByName(tc.resource, crds)
require.NotNil(crd, "CRD %s not found", tc.resource)

field := crd.Fields[tc.fieldPath]
require.NotNil(field, "field %s.%s not found", tc.resource, tc.fieldPath)
assert.True(field.HasReference(), "field %s.%s should have a reference", tc.resource, tc.fieldPath)

refName, err := field.GetReferenceFieldName()
require.NoError(err)
assert.Equal(tc.refName, refName.Camel)
}
}
19 changes: 19 additions & 0 deletions pkg/testdata/models/apis/wafv2/0000-00-00/generator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ empty_shapes:
- RateLimitHTTPMethod
- NoneAction
operations:
GetIPSet:
output_wrapper_field_path: IPSet
GetRuleGroup:
output_wrapper_field_path: RuleGroup
GetWebACL:
output_wrapper_field_path: WebACL
resources:
IPSet:
fields:
Name:
is_primary_key: true
is_immutable: true
RuleGroup:
fields:
Name:
Expand All @@ -51,6 +58,10 @@ resources:
type: string
set:
- ignore: "all"
Rules.Statement.IPSetReferenceStatement.ARN:
references:
resource: IPSet
path: Status.ACKResourceMetadata.ARN
WebACL:
fields:
Name:
Expand All @@ -76,3 +87,11 @@ resources:
type: string
set:
- ignore: "all"
Rules.Statement.IPSetReferenceStatement.ARN:
references:
resource: IPSet
path: Status.ACKResourceMetadata.ARN
Rules.Statement.RuleGroupReferenceStatement.ARN:
references:
resource: RuleGroup
path: Status.ACKResourceMetadata.ARN