Skip to content

Commit 23278de

Browse files
Allow override resource identifier to ARN (#163)
Closes aws-controllers-k8s/community#909 Description of changes: The SageMaker `ModelPackage` (in some cases) needs to be described using the resource ARN, even though the spec has a `ModelPackageName` and the `DescribeModelPackage` input shape has a `ModelPackageName` field. This pull requests allows the service teams to set the `primary_identifier_field_name` as `"ARN"`, to override the default generator logic in order to set the `ACKResourceMetadata.ARN` field to be `identifier.ARN`. Also refactored the identifier code to use the new `FindIdentifiersInShape` common method and to use the `setResourceForScalar` method. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent ac8470e commit 23278de

File tree

3 files changed

+117
-45
lines changed

3 files changed

+117
-45
lines changed

pkg/generate/code/set_resource.go

Lines changed: 87 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,19 @@ func SetResourceGetAttributes(
801801
// r.ko.Spec.ServiceNamespace = f1
802802
// }
803803
// ```
804+
// An example of code that uses the ARN:
805+
//
806+
// ```
807+
// if r.ko.Status.ACKResourceMetadata == nil {
808+
// r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
809+
// }
810+
// r.ko.Status.ACKResourceMetadata.ARN = identifier.ARN
811+
//
812+
// f0, f0ok := identifier.AdditionalKeys["modelPackageName"]
813+
// if f0ok {
814+
// r.ko.Spec.ModelPackageName = &f0
815+
// }
816+
// ```
804817
func SetResourceIdentifiers(
805818
cfg *ackgenconfig.Config,
806819
r *model.CRD,
@@ -832,15 +845,29 @@ func SetResourceIdentifiers(
832845
return ""
833846
}
834847

835-
primaryKeyOut := "\n"
836-
arnOut := ""
848+
primaryKeyOut := ""
849+
primaryKeyConditionalOut := "\n"
837850
additionalKeyOut := "\n"
838851

839852
indent := strings.Repeat("\t", indentLevel)
840853

841-
primaryKeyOut += fmt.Sprintf("%sif %s.NameOrID == \"\" {\n", indent, sourceVarName)
842-
primaryKeyOut += fmt.Sprintf("%s\treturn ackerrors.MissingNameIdentifier\n", indent)
843-
primaryKeyOut += fmt.Sprintf("%s}\n", indent)
854+
// if identifier.NameOrID == "" {
855+
// return ackerrors.MissingNameIdentifier
856+
// }
857+
primaryKeyConditionalOut += fmt.Sprintf("%sif %s.NameOrID == \"\" {\n", indent, sourceVarName)
858+
primaryKeyConditionalOut += fmt.Sprintf("%s\treturn ackerrors.MissingNameIdentifier\n", indent)
859+
primaryKeyConditionalOut += fmt.Sprintf("%s}\n", indent)
860+
861+
arnOut := "\n"
862+
// if r.ko.Status.ACKResourceMetadata == nil {
863+
// r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
864+
// }
865+
// r.ko.Status.ACKResourceMetadata.ARN = identifier.ARN
866+
arnOut += ackResourceMetadataGuardConstructor(fmt.Sprintf("%s.Status", targetVarName), indentLevel)
867+
arnOut += fmt.Sprintf(
868+
"%s%s.Status.ACKResourceMetadata.ARN = %s.ARN\n",
869+
indent, targetVarName, sourceVarName,
870+
)
844871

845872
primaryIdentifier := ""
846873

@@ -852,33 +879,20 @@ func SetResourceIdentifiers(
852879

853880
// Determine the "primary identifier" based on the names of each field
854881
if primaryIdentifier == "" {
855-
primaryIdentifierLookup := []string{
856-
"Name",
857-
"Names",
858-
r.Names.Original + "Name",
859-
r.Names.Original + "Names",
860-
r.Names.Original + "Id",
861-
r.Names.Original + "Ids",
862-
}
863-
864-
for _, memberName := range inputShape.MemberNames() {
865-
if util.InStrings(memberName, primaryIdentifierLookup) {
866-
if primaryIdentifier == "" {
867-
primaryIdentifier = memberName
868-
} else {
869-
panic("Found multiple possible primary identifiers for " +
870-
r.Names.Original + ". Set " +
871-
"`primary_identifier_field_name` for the " + op.Name +
872-
" operation in the generator config.")
873-
}
874-
}
875-
}
882+
identifiers := FindIdentifiersInShape(r, inputShape)
876883

877-
// Still haven't determined the identifier? Panic
878-
if primaryIdentifier == "" {
884+
switch len(identifiers) {
885+
case 0:
879886
panic("Could not find primary identifier for " + r.Names.Original +
880887
". Set `primary_identifier_field_name` for the " + op.Name +
881888
" operation in the generator config.")
889+
case 1:
890+
primaryIdentifier = identifiers[0]
891+
default:
892+
panic("Found multiple possible primary identifiers for " +
893+
r.Names.Original + ". Set " +
894+
"`primary_identifier_field_name` for the " + op.Name +
895+
" operation in the generator config.")
882896
}
883897
}
884898

@@ -894,11 +908,11 @@ func SetResourceIdentifiers(
894908
}
895909

896910
memberShapeRef, _ := inputShape.MemberRefs[memberName]
897-
memberShape := memberShapeRef.Shape
911+
sourceMemberShape := memberShapeRef.Shape
898912

899913
// Only strings are currently accepted as valid inputs for
900914
// additional key fields
901-
if memberShape.Type != "string" {
915+
if sourceMemberShape.Type != "string" {
902916
continue
903917
}
904918

@@ -908,40 +922,54 @@ func SetResourceIdentifiers(
908922
}
909923

910924
if r.IsPrimaryARNField(memberName) {
911-
// r.ko.Status.ACKResourceMetadata.ARN = identifier.ARN
912-
arnOut += fmt.Sprintf(
913-
"\n%s%s.Status.ACKResourceMetadata.ARN = %s.ARN\n",
914-
indent, targetVarName, sourceVarName,
915-
)
916925
continue
917-
918926
}
927+
919928
// Check that the field has potentially been renamed
920929
renamedName, _ := r.InputFieldRename(
921930
op.Name, memberName,
922931
)
923932

924933
isPrimaryIdentifier := memberName == primaryIdentifier
925934
cleanMemberNames := names.New(renamedName)
926-
cleanMemberName := cleanMemberNames.Camel
927935

928936
memberPath := ""
929-
_, inSpec := r.SpecFields[renamedName]
930-
_, inStatus := r.StatusFields[renamedName]
937+
var targetField *model.Field
938+
939+
specField, inSpec := r.SpecFields[renamedName]
940+
statusField, inStatus := r.StatusFields[renamedName]
931941
switch {
932942
case inSpec:
933943
memberPath = cfg.PrefixConfig.SpecField
944+
targetField = specField
934945
case inStatus:
935946
memberPath = cfg.PrefixConfig.StatusField
947+
targetField = statusField
936948
case isPrimaryIdentifier:
937949
panic("Primary identifier field '" + memberName + "' in operation '" + op.Name + "' cannot be found in either spec or status.")
938950
default:
939951
continue
940952
}
941953

954+
targetVarPath := fmt.Sprintf("%s%s", targetVarName, memberPath)
942955
if isPrimaryIdentifier {
943-
// r.ko.Status.BrokerID = identifier.NameOrID
944-
primaryKeyOut += fmt.Sprintf("%s%s%s.%s = &%s.NameOrID\n", indent, targetVarName, memberPath, cleanMemberName, sourceVarName)
956+
// r.ko.Status.BrokerID = &identifier.NameOrID
957+
adaptedMemberPath := fmt.Sprintf("&%s.NameOrID", sourceVarName)
958+
switch sourceMemberShape.Type {
959+
case "list", "structure", "map":
960+
// TODO(RedbackThomson): Add support for slices and maps
961+
// in ReadMany operations
962+
break
963+
default:
964+
primaryKeyOut += setResourceForScalar(
965+
cfg, r,
966+
targetField.Path,
967+
targetVarPath,
968+
adaptedMemberPath,
969+
memberShapeRef,
970+
indentLevel,
971+
)
972+
}
945973
} else {
946974
// f0, f0ok := identifier.AdditionalKeys["scalableDimension"]
947975
// if f0ok {
@@ -955,18 +983,33 @@ func SetResourceIdentifiers(
955983
// throwing an error accessible to the user
956984
additionalKeyOut += fmt.Sprintf("%s%s, %sok := %s\n", indent, fieldIndexName, fieldIndexName, sourceAdaptedVarName)
957985
additionalKeyOut += fmt.Sprintf("%sif %sok {\n", indent, fieldIndexName)
958-
additionalKeyOut += fmt.Sprintf("%s\t%s%s.%s = &%s\n", indent, targetVarName, memberPath, cleanMemberName, fieldIndexName)
986+
987+
switch sourceMemberShape.Type {
988+
case "list", "structure", "map":
989+
// TODO(RedbackThomson): Add support for slices and maps
990+
// in ReadMany operations
991+
break
992+
default:
993+
additionalKeyOut += setResourceForScalar(
994+
cfg, r,
995+
targetField.Path,
996+
targetVarPath,
997+
fmt.Sprintf("&%s", fieldIndexName),
998+
memberShapeRef,
999+
indentLevel+1,
1000+
)
1001+
}
9591002
additionalKeyOut += fmt.Sprintf("%s}\n", indent)
9601003

9611004
additionalKeyCount++
9621005
}
9631006
}
9641007

9651008
// Only use at most one of ARN or nameOrID as primary identifier outputs
966-
if arnOut != "" {
1009+
if primaryIdentifier == "ARN" || primaryKeyOut == "" {
9671010
return arnOut + additionalKeyOut
9681011
}
969-
return primaryKeyOut + additionalKeyOut
1012+
return primaryKeyConditionalOut + primaryKeyOut + additionalKeyOut
9701013
}
9711014

9721015
// setResourceForContainer returns a string of Go code that sets the value of a

pkg/generate/code/set_resource_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3092,3 +3092,29 @@ func TestSetResource_APIGWV2_ApiMapping_SetResourceIdentifiers(t *testing.T) {
30923092
code.SetResourceIdentifiers(crd.Config(), crd, "identifier", "r.ko", 1),
30933093
)
30943094
}
3095+
3096+
func TestSetResource_SageMaker_ModelPackage_SetResourceIdentifiers(t *testing.T) {
3097+
assert := assert.New(t)
3098+
require := require.New(t)
3099+
3100+
g := testutil.NewModelForService(t, "sagemaker")
3101+
3102+
crd := testutil.GetCRDByName(t, g, "ModelPackage")
3103+
require.NotNil(crd)
3104+
3105+
expected := `
3106+
if r.ko.Status.ACKResourceMetadata == nil {
3107+
r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
3108+
}
3109+
r.ko.Status.ACKResourceMetadata.ARN = identifier.ARN
3110+
3111+
f0, f0ok := identifier.AdditionalKeys["modelPackageName"]
3112+
if f0ok {
3113+
r.ko.Spec.ModelPackageName = &f0
3114+
}
3115+
`
3116+
assert.Equal(
3117+
expected,
3118+
code.SetResourceIdentifiers(crd.Config(), crd, "identifier", "r.ko", 1),
3119+
)
3120+
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ resources:
2222
Endpoint:
2323
reconcile:
2424
requeue_on_success_seconds: 10
25+
operations:
26+
DescribeModelPackage:
27+
primary_identifier_field_name: ARN
2528
ignore:
2629
resource_names:
2730
- Algorithm
@@ -50,7 +53,7 @@ ignore:
5053
- Model
5154
- ModelBiasJobDefinition
5255
- ModelExplainabilityJobDefinition
53-
- ModelPackage
56+
# - ModelPackage
5457
# ModelPackageGroup
5558
- ModelQualityJobDefinition
5659
- MonitoringSchedule

0 commit comments

Comments
 (0)