Skip to content

Commit 831f5ac

Browse files
committed
feat: return error on missing required fields
During resource Adoption, the ACK controllers only returned an error when there was a missing PrimaryKey. If a Resource requires more than 1 field to describe a Resource (eg. Lambda alias requires Name and FunctionName), the controller only verifies the Primary identifier (ARN, ID, Name) and nothing else. With this change, we look into the SDK model to retrieve the required fields and return an error if all are not defined during `PopulateResourceFromAnnotation`
1 parent b2dc0f4 commit 831f5ac

File tree

2 files changed

+27
-23
lines changed

2 files changed

+27
-23
lines changed

pkg/generate/code/set_resource.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ func identifierNameOrIDGuardConstructor(
847847
// return ackerrors.MissingNameIdentifier
848848
// }
849849
func requiredFieldGuardContructor(
850+
holdingVar string,
850851
// String representing the fields map that contains the required
851852
// fields for adoption
852853
sourceVarName string,
@@ -856,7 +857,7 @@ func requiredFieldGuardContructor(
856857
indentLevel int,
857858
) string {
858859
indent := strings.Repeat("\t", indentLevel)
859-
out := fmt.Sprintf("%stmp, ok := %s[\"%s\"]\n", indent, sourceVarName, requiredField)
860+
out := fmt.Sprintf("%s%s, ok := %s[\"%s\"]\n", indent, holdingVar, sourceVarName, requiredField)
860861
out += fmt.Sprintf("%sif !ok {\n", indent)
861862
out += fmt.Sprintf("%s\treturn ackerrors.NewTerminalError(fmt.Errorf(\"required field missing: %s\"))\n", indent, requiredField)
862863
out += fmt.Sprintf("%s}\n", indent)
@@ -1355,10 +1356,10 @@ func PopulateResourceFromAnnotation(
13551356
out := "\n"
13561357
// Check if the CRD defines the primary keys
13571358
primaryKeyConditionalOut := "\n"
1358-
primaryKeyConditionalOut += requiredFieldGuardContructor(sourceVarName, "arn", indentLevel)
1359+
primaryKeyConditionalOut += requiredFieldGuardContructor("resourceARN", sourceVarName, "arn", indentLevel)
13591360
arnOut += ackResourceMetadataGuardConstructor(fmt.Sprintf("%s.Status", targetVarName), indentLevel)
13601361
arnOut += fmt.Sprintf(
1361-
"%sarn := ackv1alpha1.AWSResourceName(tmp)\n",
1362+
"%sarn := ackv1alpha1.AWSResourceName(resourceARN)\n",
13621363
indent,
13631364
)
13641365
arnOut += fmt.Sprintf(
@@ -1377,9 +1378,10 @@ func PopulateResourceFromAnnotation(
13771378
isPrimarySet := primaryField != nil
13781379
if isPrimarySet {
13791380
memberPath, _ := findFieldInCR(cfg, r, primaryField.Names.Original)
1380-
primaryKeyOut += requiredFieldGuardContructor(sourceVarName, primaryField.Names.CamelLower, indentLevel)
1381+
primaryKeyOut += requiredFieldGuardContructor("primaryKey", sourceVarName, primaryField.Names.CamelLower, indentLevel)
13811382
targetVarPath := fmt.Sprintf("%s%s", targetVarName, memberPath)
13821383
primaryKeyOut += setResourceIdentifierPrimaryIdentifierAnn(cfg, r,
1384+
"&primaryKey",
13831385
primaryField,
13841386
targetVarPath,
13851387
sourceVarName,
@@ -1451,18 +1453,18 @@ func PopulateResourceFromAnnotation(
14511453
switch targetField.ShapeRef.Shape.Type {
14521454
case "list", "structure", "map":
14531455
panic("primary identifier '" + targetField.Path + "' must be a scalar type since NameOrID is a string")
1454-
default:
1455-
break
14561456
}
14571457

14581458
targetVarPath := fmt.Sprintf("%s%s", targetVarName, memberPath)
1459-
if isPrimaryIdentifier {
1460-
primaryKeyOut += requiredFieldGuardContructor(sourceVarName, targetField.Names.CamelLower, indentLevel)
1459+
if inputShape.IsRequired(memberName) || isPrimaryIdentifier {
1460+
primaryKeyOut += requiredFieldGuardContructor(fmt.Sprintf("f%d", memberIndex), sourceVarName, targetField.Names.CamelLower, indentLevel)
14611461
primaryKeyOut += setResourceIdentifierPrimaryIdentifierAnn(cfg, r,
1462+
fmt.Sprintf("&f%d", memberIndex),
14621463
targetField,
14631464
targetVarPath,
14641465
sourceVarName,
1465-
indentLevel)
1466+
indentLevel,
1467+
)
14661468
} else {
14671469
additionalKeyOut += setResourceIdentifierAdditionalKeyAnn(
14681470
cfg, r,
@@ -1471,7 +1473,8 @@ func PopulateResourceFromAnnotation(
14711473
targetVarPath,
14721474
sourceVarName,
14731475
names.New(fieldName).CamelLower,
1474-
indentLevel)
1476+
indentLevel,
1477+
)
14751478
}
14761479
}
14771480

@@ -1539,6 +1542,8 @@ func setResourceIdentifierPrimaryIdentifier(
15391542
func setResourceIdentifierPrimaryIdentifierAnn(
15401543
cfg *ackgenconfig.Config,
15411544
r *model.CRD,
1545+
// The variable used for primary key
1546+
requiredFieldVarName string,
15421547
// The field that will be set on the target variable
15431548
targetField *model.Field,
15441549
// The variable name that we want to set a value to
@@ -1548,12 +1553,11 @@ func setResourceIdentifierPrimaryIdentifierAnn(
15481553
// Number of levels of indentation to use
15491554
indentLevel int,
15501555
) string {
1551-
adaptedMemberPath := fmt.Sprintf("&tmp")
15521556
qualifiedTargetVar := fmt.Sprintf("%s.%s", targetVarName, targetField.Path)
15531557

15541558
return setResourceForScalar(
15551559
qualifiedTargetVar,
1556-
adaptedMemberPath,
1560+
requiredFieldVarName,
15571561
targetField.ShapeRef,
15581562
indentLevel,
15591563
false,

pkg/generate/code/set_resource_test.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ func TestSetResource_APIGWv2_Route_ReadOne(t *testing.T) {
204204
)
205205
}
206206

207-
208207
func TestSetResource_SageMaker_Domain_ReadOne(t *testing.T) {
209208
assert := assert.New(t)
210209
require := require.New(t)
@@ -1800,11 +1799,11 @@ func TestSetResource_EKS_Cluster_PopulateResourceFromAnnotation(t *testing.T) {
18001799
require.NotNil(crd)
18011800

18021801
expected := `
1803-
tmp, ok := fields["name"]
1802+
f0, ok := fields["name"]
18041803
if !ok {
18051804
return ackerrors.NewTerminalError(fmt.Errorf("required field missing: name"))
18061805
}
1807-
r.ko.Spec.Name = &tmp
1806+
r.ko.Spec.Name = &f0
18081807
18091808
`
18101809
assert.Equal(
@@ -1823,15 +1822,15 @@ func TestSetResource_SageMaker_ModelPackage_PopulateResourceFromAnnotation(t *te
18231822
require.NotNil(crd)
18241823

18251824
expected := `
1826-
tmp, ok := identifier["arn"]
1825+
resourceARN, ok := identifier["arn"]
18271826
if !ok {
18281827
return ackerrors.NewTerminalError(fmt.Errorf("required field missing: arn"))
18291828
}
18301829
18311830
if r.ko.Status.ACKResourceMetadata == nil {
18321831
r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
18331832
}
1834-
arn := ackv1alpha1.AWSResourceName(tmp)
1833+
arn := ackv1alpha1.AWSResourceName(resourceARN)
18351834
r.ko.Status.ACKResourceMetadata.ARN = &arn
18361835
`
18371836
assert.Equal(
@@ -1850,16 +1849,17 @@ func TestSetResource_APIGWV2_ApiMapping_PopulateResourceFromAnnotation(t *testin
18501849
require.NotNil(crd)
18511850

18521851
expected := `
1853-
tmp, ok := fields["apiMappingID"]
1852+
f0, ok := fields["apiMappingID"]
18541853
if !ok {
18551854
return ackerrors.NewTerminalError(fmt.Errorf("required field missing: apiMappingID"))
18561855
}
1857-
r.ko.Status.APIMappingID = &tmp
1858-
1859-
f1, f1ok := fields["domainName"]
1860-
if f1ok {
1861-
r.ko.Spec.DomainName = aws.String(f1)
1856+
r.ko.Status.APIMappingID = &f0
1857+
f1, ok := fields["domainName"]
1858+
if !ok {
1859+
return ackerrors.NewTerminalError(fmt.Errorf("required field missing: domainName"))
18621860
}
1861+
r.ko.Spec.DomainName = &f1
1862+
18631863
`
18641864
assert.Equal(
18651865
expected,

0 commit comments

Comments
 (0)