diff --git a/pkg/config/field.go b/pkg/config/field.go index dbaf2de6..44399b28 100644 --- a/pkg/config/field.go +++ b/pkg/config/field.go @@ -14,6 +14,7 @@ package config import ( + "encoding/json" "strings" ) @@ -226,7 +227,38 @@ type SetFieldConfig struct { // - method: Update // ignore: true // ``` - Ignore bool `json:"ignore,omitempty"` + Ignore BoolOrString `json:"ignore,omitempty"` +} + +// IgnoreResourceSetter returns true if the field should be ignored when setting +// the resource's field value from the SDK output shape. +func (s *SetFieldConfig) IgnoreResourceSetter() bool { + if s.Ignore.Bool != nil { + return *s.Ignore.Bool + } + if s.Ignore.String != nil { + return strings.EqualFold(*s.Ignore.String, "from") || strings.EqualFold(*s.Ignore.String, "all") + } + return false +} + +// IgnoreSDKSetter returns true if the field should be ignored when setting the +// SDK field value from the resource's field. +func (s *SetFieldConfig) IgnoreSDKSetter() bool { + if s.Ignore.Bool != nil { + return false + } + if s.Ignore.String != nil { + return strings.EqualFold(*s.Ignore.String, "to") || strings.EqualFold(*s.Ignore.String, "all") + } + return false +} + +// IsAllIgnored returns true if the field should be ignored when setting the +// resource's field value from the SDK output shape and when setting the SDK +// field value from the resource's field. +func (s *SetFieldConfig) IsAllIgnored() bool { + return s.IgnoreResourceSetter() && s.IgnoreSDKSetter() } // CompareFieldConfig informs the code generator how to compare two values of a @@ -486,3 +518,31 @@ func (c *Config) GetLateInitConfigByPath(resourceName string, fieldPath string) } return nil } + +// BoolOrString is a type that can be unmarshalled from either a boolean or a +// string. +type BoolOrString struct { + // Bool is the boolean value of the field. This field is non-nil if the + // field was unmarshalled from a boolean value. + Bool *bool + // String is the string value of the field. This field is non-nil if the + // field was unmarshalled from a string value. + String *string +} + +// UnmarshalJSON unmarshals a BoolOrString from a YAML/JSON byte slice. +func (a *BoolOrString) UnmarshalJSON(b []byte) error { + var str string + err := json.Unmarshal(b, &str) + if err != nil { + var boolean bool + err := json.Unmarshal(b, &boolean) + if err != nil { + return err + } + a.Bool = &boolean + } else { + a.String = &str + } + return nil +} diff --git a/pkg/generate/ack/controller.go b/pkg/generate/ack/controller.go index 259adbeb..8873e61c 100644 --- a/pkg/generate/ack/controller.go +++ b/pkg/generate/ack/controller.go @@ -122,7 +122,7 @@ var ( return code.SetSDK(r.Config(), r, ackmodel.OpTypeDelete, sourceVarName, targetVarName, indentLevel) }, "GoCodeSetSDKForStruct": func(r *ackmodel.CRD, targetFieldName string, targetVarName string, targetShapeRef *awssdkmodel.ShapeRef, sourceFieldPath string, sourceVarName string, indentLevel int) string { - return code.SetSDKForStruct(r.Config(), r, targetFieldName, targetVarName, targetShapeRef, sourceFieldPath, sourceVarName, indentLevel) + return code.SetSDKForStruct(r.Config(), r, targetFieldName, targetVarName, targetShapeRef, sourceFieldPath, sourceVarName, model.OpTypeList, indentLevel) }, "GoCodeSetResourceForStruct": func(r *ackmodel.CRD, targetFieldName string, targetVarName string, targetShapeRef *awssdkmodel.ShapeRef, sourceVarName string, sourceShapeRef *awssdkmodel.ShapeRef, indentLevel int) string { var setCfg *ackgenconfig.SetFieldConfig = nil @@ -135,7 +135,7 @@ var ( if ok { setCfg = f.GetSetterConfig(ackmodel.OpTypeList) } - if setCfg != nil && setCfg.Ignore { + if setCfg != nil && setCfg.IgnoreResourceSetter() { return "" } return code.SetResourceForStruct(r.Config(), r, targetVarName, targetShapeRef, setCfg, sourceVarName, sourceShapeRef, "", model.OpTypeList, indentLevel) diff --git a/pkg/generate/code/set_resource.go b/pkg/generate/code/set_resource.go index 5c535207..e771abb3 100644 --- a/pkg/generate/code/set_resource.go +++ b/pkg/generate/code/set_resource.go @@ -231,7 +231,7 @@ func SetResource( // field value... setCfg := f.GetSetterConfig(opType) - if setCfg != nil && setCfg.Ignore { + if setCfg != nil && setCfg.IgnoreResourceSetter() { continue } @@ -588,7 +588,7 @@ func setResourceReadMany( // field value... setCfg := f.GetSetterConfig(model.OpTypeList) - if setCfg != nil && setCfg.Ignore { + if setCfg != nil && setCfg.IgnoreResourceSetter() { continue } diff --git a/pkg/generate/code/set_sdk.go b/pkg/generate/code/set_sdk.go index a04841ab..75c914a1 100644 --- a/pkg/generate/code/set_sdk.go +++ b/pkg/generate/code/set_sdk.go @@ -345,6 +345,7 @@ func SetSDK( sourceFieldPath, sourceAdaptedVarName, memberShapeRef, + opType, indentLevel+1, ) out += setSDKForScalar( @@ -928,6 +929,7 @@ func setSDKForContainer( sourceVarName string, // ShapeRef of the target struct field targetShapeRef *awssdkmodel.ShapeRef, + op model.OpType, indentLevel int, ) string { switch targetShapeRef.Shape.Type { @@ -939,6 +941,7 @@ func setSDKForContainer( targetShapeRef, sourceFieldPath, sourceVarName, + op, indentLevel, ) case "list": @@ -949,6 +952,7 @@ func setSDKForContainer( targetShapeRef, sourceFieldPath, sourceVarName, + op, indentLevel, ) case "map": @@ -959,6 +963,7 @@ func setSDKForContainer( targetShapeRef, sourceFieldPath, sourceVarName, + op, indentLevel, ) default: @@ -1082,6 +1087,7 @@ func SetSDKForStruct( sourceFieldPath string, // The struct or struct field that we access our source value from sourceVarName string, + op model.OpType, indentLevel int, ) string { out := "" @@ -1096,6 +1102,29 @@ func SetSDKForStruct( sourceAdaptedVarName := sourceVarName + "." + cleanMemberName memberFieldPath := sourceFieldPath + "." + cleanMemberName + // todo: To make `ignore` functionality work for all fields that has `ignore` set to `true`, + // we need to add the below logic inside `SetSDK` function. + + // To check if the field member has `ignore` set to `true`. + // This condition currently applies only for members of a field whose shape is `structure` + var setCfg *ackgenconfig.SetFieldConfig + f, ok := r.Fields[targetFieldName] + if ok { + mf, ok := f.MemberFields[memberName] + if ok { + setCfg = mf.GetSetterConfig(op) + if setCfg != nil && setCfg.IgnoreSDKSetter() { + continue + } + } + + } + + fallBackName := r.GetMatchingInputShapeFieldName(op, targetFieldName) + if fallBackName == memberName { + // TODO: implement @AmineHilaly + } + out += fmt.Sprintf( "%sif %s != nil {\n", indent, sourceAdaptedVarName, ) @@ -1119,6 +1148,7 @@ func SetSDKForStruct( memberFieldPath, sourceAdaptedVarName, memberShapeRef, + op, indentLevel+1, ) out += setSDKForScalar( @@ -1176,6 +1206,7 @@ func setSDKForSlice( sourceFieldPath string, // The struct or struct field that we access our source value from sourceVarName string, + op model.OpType, indentLevel int, ) string { out := "" @@ -1209,6 +1240,7 @@ func setSDKForSlice( sourceFieldPath, iterVarName, &targetShape.MemberRef, + op, indentLevel+1, ) addressOfVar := "" @@ -1239,6 +1271,7 @@ func setSDKForMap( sourceFieldPath string, // The struct or struct field that we access our source value from sourceVarName string, + op model.OpType, indentLevel int, ) string { out := "" @@ -1273,6 +1306,7 @@ func setSDKForMap( sourceFieldPath, valIterVarName, &targetShape.ValueRef, + op, indentLevel+1, ) addressOfVar := "" diff --git a/pkg/generate/code/set_sdk_test.go b/pkg/generate/code/set_sdk_test.go index 7a10fd3a..cb14b321 100644 --- a/pkg/generate/code/set_sdk_test.go +++ b/pkg/generate/code/set_sdk_test.go @@ -2190,3 +2190,180 @@ func TestSetSDK_IAM_User_NewPath(t *testing.T) { code.SetSDK(crd.Config(), crd, model.OpTypeUpdate, "r.ko", "res", 1), ) } + +func TestSetSDK_Lambda_Ignore_Code_SHA256(t *testing.T) { + assert := assert.New(t) + require := require.New(t) + + g := testutil.NewModelForServiceWithOptions(t, "lambda", &testutil.TestingModelOptions{ + GeneratorConfigFile: "generator-lambda-ignore-code-sha256.yaml", + }) + + crd := testutil.GetCRDByName(t, g, "Function") + require.NotNil(crd) + + expected := ` + if r.ko.Spec.Code != nil { + f0 := &svcsdk.FunctionCode{} + if r.ko.Spec.Code.ImageURI != nil { + f0.SetImageUri(*r.ko.Spec.Code.ImageURI) + } + if r.ko.Spec.Code.S3Bucket != nil { + f0.SetS3Bucket(*r.ko.Spec.Code.S3Bucket) + } + if r.ko.Spec.Code.S3Key != nil { + f0.SetS3Key(*r.ko.Spec.Code.S3Key) + } + if r.ko.Spec.Code.S3ObjectVersion != nil { + f0.SetS3ObjectVersion(*r.ko.Spec.Code.S3ObjectVersion) + } + if r.ko.Spec.Code.ZipFile != nil { + f0.SetZipFile(r.ko.Spec.Code.ZipFile) + } + res.SetCode(f0) + } + if r.ko.Spec.CodeSigningConfigARN != nil { + res.SetCodeSigningConfigArn(*r.ko.Spec.CodeSigningConfigARN) + } + if r.ko.Spec.DeadLetterConfig != nil { + f2 := &svcsdk.DeadLetterConfig{} + if r.ko.Spec.DeadLetterConfig.TargetARN != nil { + f2.SetTargetArn(*r.ko.Spec.DeadLetterConfig.TargetARN) + } + res.SetDeadLetterConfig(f2) + } + if r.ko.Spec.Description != nil { + res.SetDescription(*r.ko.Spec.Description) + } + if r.ko.Spec.Environment != nil { + f4 := &svcsdk.Environment{} + if r.ko.Spec.Environment.Variables != nil { + f4f0 := map[string]*string{} + for f4f0key, f4f0valiter := range r.ko.Spec.Environment.Variables { + var f4f0val string + f4f0val = *f4f0valiter + f4f0[f4f0key] = &f4f0val + } + f4.SetVariables(f4f0) + } + res.SetEnvironment(f4) + } + if r.ko.Spec.FileSystemConfigs != nil { + f5 := []*svcsdk.FileSystemConfig{} + for _, f5iter := range r.ko.Spec.FileSystemConfigs { + f5elem := &svcsdk.FileSystemConfig{} + if f5iter.ARN != nil { + f5elem.SetArn(*f5iter.ARN) + } + if f5iter.LocalMountPath != nil { + f5elem.SetLocalMountPath(*f5iter.LocalMountPath) + } + f5 = append(f5, f5elem) + } + res.SetFileSystemConfigs(f5) + } + if r.ko.Spec.FunctionName != nil { + res.SetFunctionName(*r.ko.Spec.FunctionName) + } + if r.ko.Spec.Handler != nil { + res.SetHandler(*r.ko.Spec.Handler) + } + if r.ko.Spec.ImageConfig != nil { + f8 := &svcsdk.ImageConfig{} + if r.ko.Spec.ImageConfig.Command != nil { + f8f0 := []*string{} + for _, f8f0iter := range r.ko.Spec.ImageConfig.Command { + var f8f0elem string + f8f0elem = *f8f0iter + f8f0 = append(f8f0, &f8f0elem) + } + f8.SetCommand(f8f0) + } + if r.ko.Spec.ImageConfig.EntryPoint != nil { + f8f1 := []*string{} + for _, f8f1iter := range r.ko.Spec.ImageConfig.EntryPoint { + var f8f1elem string + f8f1elem = *f8f1iter + f8f1 = append(f8f1, &f8f1elem) + } + f8.SetEntryPoint(f8f1) + } + if r.ko.Spec.ImageConfig.WorkingDirectory != nil { + f8.SetWorkingDirectory(*r.ko.Spec.ImageConfig.WorkingDirectory) + } + res.SetImageConfig(f8) + } + if r.ko.Spec.KMSKeyARN != nil { + res.SetKMSKeyArn(*r.ko.Spec.KMSKeyARN) + } + if r.ko.Spec.Layers != nil { + f10 := []*string{} + for _, f10iter := range r.ko.Spec.Layers { + var f10elem string + f10elem = *f10iter + f10 = append(f10, &f10elem) + } + res.SetLayers(f10) + } + if r.ko.Spec.MemorySize != nil { + res.SetMemorySize(*r.ko.Spec.MemorySize) + } + if r.ko.Spec.PackageType != nil { + res.SetPackageType(*r.ko.Spec.PackageType) + } + if r.ko.Spec.Publish != nil { + res.SetPublish(*r.ko.Spec.Publish) + } + if r.ko.Spec.Role != nil { + res.SetRole(*r.ko.Spec.Role) + } + if r.ko.Spec.Runtime != nil { + res.SetRuntime(*r.ko.Spec.Runtime) + } + if r.ko.Spec.Tags != nil { + f16 := map[string]*string{} + for f16key, f16valiter := range r.ko.Spec.Tags { + var f16val string + f16val = *f16valiter + f16[f16key] = &f16val + } + res.SetTags(f16) + } + if r.ko.Spec.Timeout != nil { + res.SetTimeout(*r.ko.Spec.Timeout) + } + if r.ko.Spec.TracingConfig != nil { + f18 := &svcsdk.TracingConfig{} + if r.ko.Spec.TracingConfig.Mode != nil { + f18.SetMode(*r.ko.Spec.TracingConfig.Mode) + } + res.SetTracingConfig(f18) + } + if r.ko.Spec.VPCConfig != nil { + f19 := &svcsdk.VpcConfig{} + if r.ko.Spec.VPCConfig.SecurityGroupIDs != nil { + f19f0 := []*string{} + for _, f19f0iter := range r.ko.Spec.VPCConfig.SecurityGroupIDs { + var f19f0elem string + f19f0elem = *f19f0iter + f19f0 = append(f19f0, &f19f0elem) + } + f19.SetSecurityGroupIds(f19f0) + } + if r.ko.Spec.VPCConfig.SubnetIDs != nil { + f19f1 := []*string{} + for _, f19f1iter := range r.ko.Spec.VPCConfig.SubnetIDs { + var f19f1elem string + f19f1elem = *f19f1iter + f19f1 = append(f19f1, &f19f1elem) + } + f19.SetSubnetIds(f19f1) + } + res.SetVpcConfig(f19) + } +` + assert.Equal( + expected, + code.SetSDK(crd.Config(), crd, model.OpTypeCreate, "r.ko", "res", 1), + ) +} diff --git a/pkg/model/crd.go b/pkg/model/crd.go index 532e4e62..7618b80e 100644 --- a/pkg/model/crd.go +++ b/pkg/model/crd.go @@ -428,10 +428,7 @@ func (r *CRD) GetMatchingInputShapeFieldName(opType OpType, sdkField string) str } rmMethod := ResourceManagerMethodFromOpType(opType) for _, setCfg := range f.FieldConfig.Set { - if setCfg == nil { - continue - } - if setCfg.Ignore == true || setCfg.To == nil { + if setCfg == nil || setCfg.IgnoreSDKSetter() { continue } // If the Method attribute is nil, that means the setter config applies to diff --git a/pkg/model/field.go b/pkg/model/field.go index 98f1d526..a2e41a3a 100644 --- a/pkg/model/field.go +++ b/pkg/model/field.go @@ -196,6 +196,9 @@ func (f *Field) GetSetterConfig(opType OpType) *ackgenconfig.SetFieldConfig { } rmMethod := ResourceManagerMethodFromOpType(opType) for _, setCfg := range f.FieldConfig.Set { + if setCfg == nil { + continue + } // If the Method attribute is nil, that means the setter config applies to // all resource manager methods for this field. if setCfg.Method == nil || strings.EqualFold(rmMethod, *setCfg.Method) { diff --git a/pkg/testdata/models/apis/lambda/0000-00-00/generator-lambda-ignore-code-sha256.yaml b/pkg/testdata/models/apis/lambda/0000-00-00/generator-lambda-ignore-code-sha256.yaml new file mode 100644 index 00000000..f938991d --- /dev/null +++ b/pkg/testdata/models/apis/lambda/0000-00-00/generator-lambda-ignore-code-sha256.yaml @@ -0,0 +1,8 @@ +resources: + Function: + fields: + Code.S3SHA256: + type: string + set: + - ignore: "to" + method: Create \ No newline at end of file diff --git a/pkg/testdata/models/apis/lambda/0000-00-00/generator-with-custom-nested-types.yaml b/pkg/testdata/models/apis/lambda/0000-00-00/generator-with-custom-nested-types.yaml index ee512480..068088fc 100644 --- a/pkg/testdata/models/apis/lambda/0000-00-00/generator-with-custom-nested-types.yaml +++ b/pkg/testdata/models/apis/lambda/0000-00-00/generator-with-custom-nested-types.yaml @@ -9,6 +9,9 @@ resources: type: string compare: is_ignored: true + set: + - ignore: true + method: Create ImageConfigResponse.Error.New: is_read_only: true type: string