diff --git a/pkg/generate/code/set_resource.go b/pkg/generate/code/set_resource.go index 45a6e8fc..7576cc0b 100644 --- a/pkg/generate/code/set_resource.go +++ b/pkg/generate/code/set_resource.go @@ -97,10 +97,7 @@ func SetResource( case model.OpTypeGet: op = r.Ops.ReadOne case model.OpTypeList: - return setResourceReadMany( - cfg, r, - r.Ops.ReadMany, sourceVarName, targetVarName, indentLevel, - ) + op = r.Ops.ReadMany case model.OpTypeUpdate: op = r.Ops.Update case model.OpTypeDelete: @@ -116,9 +113,28 @@ func SetResource( return "" } - // Use the wrapper field path if it's given in the ack-generate config file. + // If the output shape has a list containing the resource, + // then call setResourceReadMany to generate for-range loops. + // Output shape will be a list for ReadMany operations or if + // designated via output wrapper config. wrapperFieldPath := r.GetOutputWrapperFieldPath(op) - if wrapperFieldPath != nil { + if op == r.Ops.ReadMany { + return setResourceReadMany( + cfg, r, + op, sourceVarName, targetVarName, indentLevel, + ) + } else if wrapperFieldPath != nil { + // fieldpath api requires fully-qualified path + qwfp := fieldpath.FromString(op.OutputRef.ShapeName + "." + *wrapperFieldPath) + for _, sref := range qwfp.IterShapeRefs(&op.OutputRef) { + // if there's at least 1 list to unpack, call setResourceReadMany + if sref.Shape.Type == "list" { + return setResourceReadMany( + cfg, r, + op, sourceVarName, targetVarName, indentLevel, + ) + } + } sourceVarName += "." + *wrapperFieldPath } else { // If the wrapper field path is not specified in the config file and if @@ -133,6 +149,7 @@ func SetResource( } } } + out := "\n" indent := strings.Repeat("\t", indentLevel) @@ -440,14 +457,30 @@ func setResourceReadMany( var sourceElemShape *awssdkmodel.Shape // Find the element in the output shape that contains the list of - // resources. This heuristic is simplistic (just look for the field with a - // list type) but seems to be followed consistently by the aws-sdk-go for - // List operations. - for memberName, memberShapeRef := range outputShape.MemberRefs { - if memberShapeRef.Shape.Type == "list" { - listShapeName = memberName - sourceElemShape = memberShapeRef.Shape.MemberRef.Shape - break + // resources: + // Check if there's a wrapperFieldPath, which will + // point directly to the shape. + wrapperFieldPath := r.GetOutputWrapperFieldPath(op) + if wrapperFieldPath != nil { + // fieldpath API needs fully qualified name + wfp := fieldpath.FromString(outputShape.ShapeName + "." + *wrapperFieldPath) + wfpShapeRef := wfp.ShapeRef(&op.OutputRef) + if wfpShapeRef != nil { + listShapeName = wfpShapeRef.ShapeName + sourceElemShape = wfpShapeRef.Shape.MemberRef.Shape + } + } + + // If listShape can't be found using wrapperFieldPath, + // then fall back to looking for the first field with a list type; + // this heuristic seems to work for most list operations in aws-sdk-go. + if listShapeName == "" { + for memberName, memberShapeRef := range outputShape.MemberRefs { + if memberShapeRef.Shape.Type == "list" { + listShapeName = memberName + sourceElemShape = memberShapeRef.Shape.MemberRef.Shape + break + } } } @@ -472,47 +505,53 @@ func setResourceReadMany( // found := false out += fmt.Sprintf("%sfound := false\n", indent) + elemVarName := "elem" + pathToShape := listShapeName + if wrapperFieldPath != nil { + pathToShape = *wrapperFieldPath + } + // for _, elem := range resp.CacheClusters { - out += fmt.Sprintf( - "%sfor _, elem := range %s.%s {\n", - indent, sourceVarName, listShapeName, - ) + opening, closing, flIndentLvl := generateForRangeLoops(&op.OutputRef, pathToShape, sourceVarName, elemVarName, indentLevel) + innerForIndent := strings.Repeat("\t", flIndentLvl) + out += opening + for memberIndex, memberName := range sourceElemShape.MemberNames() { sourceMemberShapeRef := sourceElemShape.MemberRefs[memberName] sourceMemberShape := sourceMemberShapeRef.Shape - sourceAdaptedVarName := "elem." + memberName + sourceAdaptedVarName := elemVarName + "." + memberName if r.IsPrimaryARNField(memberName) { out += fmt.Sprintf( - "%s\tif %s != nil {\n", indent, sourceAdaptedVarName, + "%sif %s != nil {\n", innerForIndent, sourceAdaptedVarName, ) // if ko.Status.ACKResourceMetadata == nil { // ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{} // } out += fmt.Sprintf( - "%s\t\tif %s.Status.ACKResourceMetadata == nil {\n", - indent, targetVarName, + "%s\tif %s.Status.ACKResourceMetadata == nil {\n", + innerForIndent, targetVarName, ) out += fmt.Sprintf( - "%s\t\t\t%s.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}\n", - indent, targetVarName, + "%s\t\t%s.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}\n", + innerForIndent, targetVarName, ) out += fmt.Sprintf( - "\t\t%s}\n", indent, + "\t%s}\n", innerForIndent, ) // tmpARN := ackv1alpha1.AWSResourceName(*elemARN) // ko.Status.ACKResourceMetadata.ARN = &tmpARN out += fmt.Sprintf( - "%s\t\ttmpARN := ackv1alpha1.AWSResourceName(*%s)\n", - indent, + "%s\ttmpARN := ackv1alpha1.AWSResourceName(*%s)\n", + innerForIndent, sourceAdaptedVarName, ) out += fmt.Sprintf( - "%s\t\t%s.Status.ACKResourceMetadata.ARN = &tmpARN\n", - indent, + "%s\t%s.Status.ACKResourceMetadata.ARN = &tmpARN\n", + innerForIndent, targetVarName, ) out += fmt.Sprintf( - "\t%s}\n", indent, + "%s}\n", innerForIndent, ) continue } @@ -550,7 +589,7 @@ func setResourceReadMany( targetMemberShapeRef = f.ShapeRef out += fmt.Sprintf( - "%s\tif %s != nil {\n", indent, sourceAdaptedVarName, + "%sif %s != nil {\n", innerForIndent, sourceAdaptedVarName, ) //ex: r.ko.Spec.CacheClusterID @@ -565,7 +604,7 @@ func setResourceReadMany( cfg, r, memberVarName, targetMemberShapeRef.Shape, - indentLevel+2, + flIndentLvl+1, ) out += setResourceForContainer( cfg, r, @@ -577,13 +616,13 @@ func setResourceReadMany( sourceMemberShapeRef, f.Names.Camel, model.OpTypeList, - indentLevel+2, + flIndentLvl+1, ) out += setResourceForScalar( qualifiedTargetVar, memberVarName, sourceMemberShapeRef, - indentLevel+2, + flIndentLvl+1, ) } default: @@ -594,26 +633,26 @@ func setResourceReadMany( // } if util.InStrings(fieldName, matchFieldNames) { out += fmt.Sprintf( - "%s\t\tif %s.%s != nil {\n", - indent, + "%s\tif %s.%s != nil {\n", + innerForIndent, targetAdaptedVarName, f.Names.Camel, ) out += fmt.Sprintf( - "%s\t\t\tif *%s != *%s.%s {\n", - indent, + "%s\t\tif *%s != *%s.%s {\n", + innerForIndent, sourceAdaptedVarName, targetAdaptedVarName, f.Names.Camel, ) out += fmt.Sprintf( - "%s\t\t\t\tcontinue\n", indent, + "%s\t\t\tcontinue\n", innerForIndent, ) out += fmt.Sprintf( - "%s\t\t\t}\n", indent, + "%s\t\t}\n", innerForIndent, ) out += fmt.Sprintf( - "%s\t\t}\n", indent, + "%s\t}\n", innerForIndent, ) } // r.ko.Spec.CacheClusterID = elem.CacheClusterId @@ -621,18 +660,18 @@ func setResourceReadMany( qualifiedTargetVar, sourceAdaptedVarName, sourceMemberShapeRef, - indentLevel+2, + flIndentLvl+1, ) } out += fmt.Sprintf( - "%s%s} else {\n", indent, indent, + "%s} else {\n", innerForIndent, ) out += fmt.Sprintf( - "%s%s%s%s.%s = nil\n", indent, indent, indent, + "%s\t%s.%s = nil\n", innerForIndent, targetAdaptedVarName, f.Names.Camel, ) out += fmt.Sprintf( - "%s%s}\n", indent, indent, + "%s}\n", innerForIndent, ) } // When we don't have custom matching/filtering logic for the list @@ -642,12 +681,12 @@ func setResourceReadMany( // match. Thus, we will break here only when getting a record where // all match fields have matched. out += fmt.Sprintf( - "%s\tfound = true\n", indent, + "%sfound = true\n", innerForIndent, ) - out += fmt.Sprintf( - "%s\tbreak\n", indent, - ) - out += fmt.Sprintf("%s}\n", indent) + + // End of for-range loops + out += closing + // if !found { // return nil, ackerr.NotFound // } @@ -1566,3 +1605,88 @@ func setResourceForScalar( out += fmt.Sprintf("%s%s = %s\n", indent, targetVar, setTo) return out } + +// generateForRangeLoops returns strings of Go code and an int +// representing indentLevel of the inner-most for loop + 1. +// This function unpacks a collection from a shapeRef +// using path and builds the opening and closing +// pieces of a for-range loop written in Go in order +// to access the element contained within the collection. +// The name of this element value is designated with outputVarName: +// ex: 'for _, := ...' +// Limitations: path supports lists and structs only and +// the 'break' is coupled with for-range loop to only take +// first element of a list. +// +// Sample Input: +// - shapeRef: DescribeInstancesOutputShape +// - path: Reservations.Instances +// - sourceVarName: resp +// - outputVarName: elem +// - indentLevel: 1 +// +// Sample Output (omit formatting for readability): +// - opening: "for _, iter0 := range resp.Reservations { +// for _, elem := range iter0.Instances {" +// - closing: "break } break }" +// - updatedIndentLevel: 3 +func generateForRangeLoops( + // shapeRef of the shape containing element + shapeRef *awssdkmodel.ShapeRef, + // path is the path to the element relative to shapeRef + path string, + // sourceVarName is the name of struct or field used to access source value + sourceVarName string, + // outputVarName is the desired name of the element, once unwrapped + outputVarName string, + indentLevel int, +) (string, string, int) { + opening, closing := "", "" + updatedIndentLevel := indentLevel + + fp := fieldpath.FromString(path) + unwrapCount := 0 + iterVarName := fmt.Sprintf("iter%d", unwrapCount) + collectionVarName := sourceVarName + unpackShape := shapeRef.Shape + + for fp.Size() > 0 { + pathPart := fp.PopFront() + partShapeRef, _ := unpackShape.MemberRefs[pathPart] + unpackShape = partShapeRef.Shape + indent := strings.Repeat("\t", updatedIndentLevel) + iterVarName = fmt.Sprintf("iter%d", unwrapCount) + collectionVarName += "." + pathPart + + // Using the fieldpath as a guide, unwrap the shapeRef + // to generate for-range loops. If pathPart points + // to a struct member, then simply append struct name + // to collectionVarName and move on to unwrap the next pathPart/shape. + // If pathPart points to a list member, then generate for-range loop + // code and update collectionVarName, unpackShape, and updatedIndentLevel + // for processing the next loop, if applicable. + if partShapeRef.Shape.Type == "list" { + // ex: for _, iter0 := range resp.Reservations { + opening += fmt.Sprintf("%sfor _, %s := range %s {\n", indent, iterVarName, collectionVarName) + // ex: + // break + // } + closeLoop := fmt.Sprintf("%s\tbreak\n%s}\n", indent, indent) + if closing != "" { + // nested loops need to output inner most closing braces first + closeLoop += closing + closing = closeLoop + } else { + closing += closeLoop + } + // reference iterVarName in subsequent for-loop, if any + collectionVarName = iterVarName + unpackShape = partShapeRef.Shape.MemberRef.Shape + updatedIndentLevel += 1 + } + unwrapCount += 1 + } + // replace inner-most range loop value's name with desired outputVarName + opening = strings.Replace(opening, iterVarName, outputVarName, 1) + return opening, closing, updatedIndentLevel +} diff --git a/pkg/generate/code/set_resource_test.go b/pkg/generate/code/set_resource_test.go index e9b4e892..56a8d36e 100644 --- a/pkg/generate/code/set_resource_test.go +++ b/pkg/generate/code/set_resource_test.go @@ -3257,3 +3257,1050 @@ func TestSetResource_EC2_DHCPOptions_NestedSetConfig(t *testing.T) { code.SetResource(crd.Config(), crd, model.OpTypeCreate, "resp", "ko", 1), ) } + +func TestSetResource_EC2_Instance_Create(t *testing.T) { + // Check that the RunInstances output (Reservation) + // uses the first element of the returned list of Instances + // to populate Instance CR + assert := assert.New(t) + require := require.New(t) + + g := testutil.NewModelForService(t, "ec2") + op := model.OpTypeCreate + + crd := testutil.GetCRDByName(t, g, "Instance") + require.NotNil(crd) + + expected := ` + found := false + for _, elem := range resp.Instances { + if elem.AmiLaunchIndex != nil { + ko.Status.AMILaunchIndex = elem.AmiLaunchIndex + } else { + ko.Status.AMILaunchIndex = nil + } + if elem.Architecture != nil { + ko.Status.Architecture = elem.Architecture + } else { + ko.Status.Architecture = nil + } + if elem.BlockDeviceMappings != nil { + f2 := []*svcapitypes.BlockDeviceMapping{} + for _, f2iter := range elem.BlockDeviceMappings { + f2elem := &svcapitypes.BlockDeviceMapping{} + if f2iter.DeviceName != nil { + f2elem.DeviceName = f2iter.DeviceName + } + if f2iter.Ebs != nil { + f2elemf1 := &svcapitypes.EBSBlockDevice{} + if f2iter.Ebs.DeleteOnTermination != nil { + f2elemf1.DeleteOnTermination = f2iter.Ebs.DeleteOnTermination + } + f2elem.EBS = f2elemf1 + } + f2 = append(f2, f2elem) + } + ko.Spec.BlockDeviceMappings = f2 + } else { + ko.Spec.BlockDeviceMappings = nil + } + if elem.BootMode != nil { + ko.Status.BootMode = elem.BootMode + } else { + ko.Status.BootMode = nil + } + if elem.CapacityReservationId != nil { + ko.Status.CapacityReservationID = elem.CapacityReservationId + } else { + ko.Status.CapacityReservationID = nil + } + if elem.CapacityReservationSpecification != nil { + f5 := &svcapitypes.CapacityReservationSpecification{} + if elem.CapacityReservationSpecification.CapacityReservationPreference != nil { + f5.CapacityReservationPreference = elem.CapacityReservationSpecification.CapacityReservationPreference + } + if elem.CapacityReservationSpecification.CapacityReservationTarget != nil { + f5f1 := &svcapitypes.CapacityReservationTarget{} + if elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId != nil { + f5f1.CapacityReservationID = elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId + } + if elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn != nil { + f5f1.CapacityReservationResourceGroupARN = elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn + } + f5.CapacityReservationTarget = f5f1 + } + ko.Spec.CapacityReservationSpecification = f5 + } else { + ko.Spec.CapacityReservationSpecification = nil + } + if elem.CpuOptions != nil { + f6 := &svcapitypes.CPUOptionsRequest{} + if elem.CpuOptions.CoreCount != nil { + f6.CoreCount = elem.CpuOptions.CoreCount + } + if elem.CpuOptions.ThreadsPerCore != nil { + f6.ThreadsPerCore = elem.CpuOptions.ThreadsPerCore + } + ko.Spec.CPUOptions = f6 + } else { + ko.Spec.CPUOptions = nil + } + if elem.EbsOptimized != nil { + ko.Spec.EBSOptimized = elem.EbsOptimized + } else { + ko.Spec.EBSOptimized = nil + } + if elem.ElasticGpuAssociations != nil { + f8 := []*svcapitypes.ElasticGPUAssociation{} + for _, f8iter := range elem.ElasticGpuAssociations { + f8elem := &svcapitypes.ElasticGPUAssociation{} + if f8iter.ElasticGpuAssociationId != nil { + f8elem.ElasticGPUAssociationID = f8iter.ElasticGpuAssociationId + } + if f8iter.ElasticGpuAssociationState != nil { + f8elem.ElasticGPUAssociationState = f8iter.ElasticGpuAssociationState + } + if f8iter.ElasticGpuAssociationTime != nil { + f8elem.ElasticGPUAssociationTime = f8iter.ElasticGpuAssociationTime + } + if f8iter.ElasticGpuId != nil { + f8elem.ElasticGPUID = f8iter.ElasticGpuId + } + f8 = append(f8, f8elem) + } + ko.Status.ElasticGPUAssociations = f8 + } else { + ko.Status.ElasticGPUAssociations = nil + } + if elem.ElasticInferenceAcceleratorAssociations != nil { + f9 := []*svcapitypes.ElasticInferenceAcceleratorAssociation{} + for _, f9iter := range elem.ElasticInferenceAcceleratorAssociations { + f9elem := &svcapitypes.ElasticInferenceAcceleratorAssociation{} + if f9iter.ElasticInferenceAcceleratorArn != nil { + f9elem.ElasticInferenceAcceleratorARN = f9iter.ElasticInferenceAcceleratorArn + } + if f9iter.ElasticInferenceAcceleratorAssociationId != nil { + f9elem.ElasticInferenceAcceleratorAssociationID = f9iter.ElasticInferenceAcceleratorAssociationId + } + if f9iter.ElasticInferenceAcceleratorAssociationState != nil { + f9elem.ElasticInferenceAcceleratorAssociationState = f9iter.ElasticInferenceAcceleratorAssociationState + } + if f9iter.ElasticInferenceAcceleratorAssociationTime != nil { + f9elem.ElasticInferenceAcceleratorAssociationTime = &metav1.Time{*f9iter.ElasticInferenceAcceleratorAssociationTime} + } + f9 = append(f9, f9elem) + } + ko.Status.ElasticInferenceAcceleratorAssociations = f9 + } else { + ko.Status.ElasticInferenceAcceleratorAssociations = nil + } + if elem.EnaSupport != nil { + ko.Status.ENASupport = elem.EnaSupport + } else { + ko.Status.ENASupport = nil + } + if elem.EnclaveOptions != nil { + f11 := &svcapitypes.EnclaveOptionsRequest{} + if elem.EnclaveOptions.Enabled != nil { + f11.Enabled = elem.EnclaveOptions.Enabled + } + ko.Spec.EnclaveOptions = f11 + } else { + ko.Spec.EnclaveOptions = nil + } + if elem.HibernationOptions != nil { + f12 := &svcapitypes.HibernationOptionsRequest{} + if elem.HibernationOptions.Configured != nil { + f12.Configured = elem.HibernationOptions.Configured + } + ko.Spec.HibernationOptions = f12 + } else { + ko.Spec.HibernationOptions = nil + } + if elem.Hypervisor != nil { + ko.Status.Hypervisor = elem.Hypervisor + } else { + ko.Status.Hypervisor = nil + } + if elem.IamInstanceProfile != nil { + f14 := &svcapitypes.IAMInstanceProfileSpecification{} + if elem.IamInstanceProfile.Arn != nil { + f14.ARN = elem.IamInstanceProfile.Arn + } + ko.Spec.IAMInstanceProfile = f14 + } else { + ko.Spec.IAMInstanceProfile = nil + } + if elem.ImageId != nil { + ko.Spec.ImageID = elem.ImageId + } else { + ko.Spec.ImageID = nil + } + if elem.InstanceId != nil { + ko.Status.InstanceID = elem.InstanceId + } else { + ko.Status.InstanceID = nil + } + if elem.InstanceLifecycle != nil { + ko.Status.InstanceLifecycle = elem.InstanceLifecycle + } else { + ko.Status.InstanceLifecycle = nil + } + if elem.InstanceType != nil { + ko.Spec.InstanceType = elem.InstanceType + } else { + ko.Spec.InstanceType = nil + } + if elem.KernelId != nil { + ko.Spec.KernelID = elem.KernelId + } else { + ko.Spec.KernelID = nil + } + if elem.KeyName != nil { + ko.Spec.KeyName = elem.KeyName + } else { + ko.Spec.KeyName = nil + } + if elem.LaunchTime != nil { + ko.Status.LaunchTime = &metav1.Time{*elem.LaunchTime} + } else { + ko.Status.LaunchTime = nil + } + if elem.Licenses != nil { + f22 := []*svcapitypes.LicenseConfiguration{} + for _, f22iter := range elem.Licenses { + f22elem := &svcapitypes.LicenseConfiguration{} + if f22iter.LicenseConfigurationArn != nil { + f22elem.LicenseConfigurationARN = f22iter.LicenseConfigurationArn + } + f22 = append(f22, f22elem) + } + ko.Status.Licenses = f22 + } else { + ko.Status.Licenses = nil + } + if elem.MetadataOptions != nil { + f23 := &svcapitypes.InstanceMetadataOptionsRequest{} + if elem.MetadataOptions.HttpEndpoint != nil { + f23.HTTPEndpoint = elem.MetadataOptions.HttpEndpoint + } + if elem.MetadataOptions.HttpProtocolIpv6 != nil { + f23.HTTPProtocolIPv6 = elem.MetadataOptions.HttpProtocolIpv6 + } + if elem.MetadataOptions.HttpPutResponseHopLimit != nil { + f23.HTTPPutResponseHopLimit = elem.MetadataOptions.HttpPutResponseHopLimit + } + if elem.MetadataOptions.HttpTokens != nil { + f23.HTTPTokens = elem.MetadataOptions.HttpTokens + } + ko.Spec.MetadataOptions = f23 + } else { + ko.Spec.MetadataOptions = nil + } + if elem.Monitoring != nil { + f24 := &svcapitypes.RunInstancesMonitoringEnabled{} + ko.Spec.Monitoring = f24 + } else { + ko.Spec.Monitoring = nil + } + if elem.NetworkInterfaces != nil { + f25 := []*svcapitypes.InstanceNetworkInterfaceSpecification{} + for _, f25iter := range elem.NetworkInterfaces { + f25elem := &svcapitypes.InstanceNetworkInterfaceSpecification{} + if f25iter.Description != nil { + f25elem.Description = f25iter.Description + } + if f25iter.InterfaceType != nil { + f25elem.InterfaceType = f25iter.InterfaceType + } + if f25iter.Ipv4Prefixes != nil { + f25elemf5 := []*svcapitypes.IPv4PrefixSpecificationRequest{} + for _, f25elemf5iter := range f25iter.Ipv4Prefixes { + f25elemf5elem := &svcapitypes.IPv4PrefixSpecificationRequest{} + if f25elemf5iter.Ipv4Prefix != nil { + f25elemf5elem.IPv4Prefix = f25elemf5iter.Ipv4Prefix + } + f25elemf5 = append(f25elemf5, f25elemf5elem) + } + f25elem.IPv4Prefixes = f25elemf5 + } + if f25iter.Ipv6Addresses != nil { + f25elemf6 := []*svcapitypes.InstanceIPv6Address{} + for _, f25elemf6iter := range f25iter.Ipv6Addresses { + f25elemf6elem := &svcapitypes.InstanceIPv6Address{} + if f25elemf6iter.Ipv6Address != nil { + f25elemf6elem.IPv6Address = f25elemf6iter.Ipv6Address + } + f25elemf6 = append(f25elemf6, f25elemf6elem) + } + f25elem.IPv6Addresses = f25elemf6 + } + if f25iter.Ipv6Prefixes != nil { + f25elemf7 := []*svcapitypes.IPv6PrefixSpecificationRequest{} + for _, f25elemf7iter := range f25iter.Ipv6Prefixes { + f25elemf7elem := &svcapitypes.IPv6PrefixSpecificationRequest{} + if f25elemf7iter.Ipv6Prefix != nil { + f25elemf7elem.IPv6Prefix = f25elemf7iter.Ipv6Prefix + } + f25elemf7 = append(f25elemf7, f25elemf7elem) + } + f25elem.IPv6Prefixes = f25elemf7 + } + if f25iter.NetworkInterfaceId != nil { + f25elem.NetworkInterfaceID = f25iter.NetworkInterfaceId + } + if f25iter.PrivateIpAddress != nil { + f25elem.PrivateIPAddress = f25iter.PrivateIpAddress + } + if f25iter.PrivateIpAddresses != nil { + f25elemf13 := []*svcapitypes.PrivateIPAddressSpecification{} + for _, f25elemf13iter := range f25iter.PrivateIpAddresses { + f25elemf13elem := &svcapitypes.PrivateIPAddressSpecification{} + if f25elemf13iter.Primary != nil { + f25elemf13elem.Primary = f25elemf13iter.Primary + } + if f25elemf13iter.PrivateIpAddress != nil { + f25elemf13elem.PrivateIPAddress = f25elemf13iter.PrivateIpAddress + } + f25elemf13 = append(f25elemf13, f25elemf13elem) + } + f25elem.PrivateIPAddresses = f25elemf13 + } + if f25iter.SubnetId != nil { + f25elem.SubnetID = f25iter.SubnetId + } + f25 = append(f25, f25elem) + } + ko.Spec.NetworkInterfaces = f25 + } else { + ko.Spec.NetworkInterfaces = nil + } + if elem.OutpostArn != nil { + ko.Status.OutpostARN = elem.OutpostArn + } else { + ko.Status.OutpostARN = nil + } + if elem.Placement != nil { + f27 := &svcapitypes.Placement{} + if elem.Placement.Affinity != nil { + f27.Affinity = elem.Placement.Affinity + } + if elem.Placement.AvailabilityZone != nil { + f27.AvailabilityZone = elem.Placement.AvailabilityZone + } + if elem.Placement.GroupName != nil { + f27.GroupName = elem.Placement.GroupName + } + if elem.Placement.HostId != nil { + f27.HostID = elem.Placement.HostId + } + if elem.Placement.HostResourceGroupArn != nil { + f27.HostResourceGroupARN = elem.Placement.HostResourceGroupArn + } + if elem.Placement.PartitionNumber != nil { + f27.PartitionNumber = elem.Placement.PartitionNumber + } + if elem.Placement.SpreadDomain != nil { + f27.SpreadDomain = elem.Placement.SpreadDomain + } + if elem.Placement.Tenancy != nil { + f27.Tenancy = elem.Placement.Tenancy + } + ko.Spec.Placement = f27 + } else { + ko.Spec.Placement = nil + } + if elem.Platform != nil { + ko.Status.Platform = elem.Platform + } else { + ko.Status.Platform = nil + } + if elem.PlatformDetails != nil { + ko.Status.PlatformDetails = elem.PlatformDetails + } else { + ko.Status.PlatformDetails = nil + } + if elem.PrivateDnsName != nil { + ko.Status.PrivateDNSName = elem.PrivateDnsName + } else { + ko.Status.PrivateDNSName = nil + } + if elem.PrivateIpAddress != nil { + ko.Spec.PrivateIPAddress = elem.PrivateIpAddress + } else { + ko.Spec.PrivateIPAddress = nil + } + if elem.ProductCodes != nil { + f32 := []*svcapitypes.ProductCode{} + for _, f32iter := range elem.ProductCodes { + f32elem := &svcapitypes.ProductCode{} + if f32iter.ProductCodeId != nil { + f32elem.ProductCodeID = f32iter.ProductCodeId + } + if f32iter.ProductCodeType != nil { + f32elem.ProductCodeType = f32iter.ProductCodeType + } + f32 = append(f32, f32elem) + } + ko.Status.ProductCodes = f32 + } else { + ko.Status.ProductCodes = nil + } + if elem.PublicDnsName != nil { + ko.Status.PublicDNSName = elem.PublicDnsName + } else { + ko.Status.PublicDNSName = nil + } + if elem.PublicIpAddress != nil { + ko.Status.PublicIPAddress = elem.PublicIpAddress + } else { + ko.Status.PublicIPAddress = nil + } + if elem.RamdiskId != nil { + ko.Spec.RAMDiskID = elem.RamdiskId + } else { + ko.Spec.RAMDiskID = nil + } + if elem.RootDeviceName != nil { + ko.Status.RootDeviceName = elem.RootDeviceName + } else { + ko.Status.RootDeviceName = nil + } + if elem.RootDeviceType != nil { + ko.Status.RootDeviceType = elem.RootDeviceType + } else { + ko.Status.RootDeviceType = nil + } + if elem.SecurityGroups != nil { + f38 := []*string{} + for _, f38iter := range elem.SecurityGroups { + var f38elem string + f38elem = *f38iter.GroupName + f38 = append(f38, &f38elem) + } + ko.Spec.SecurityGroups = f38 + } else { + ko.Spec.SecurityGroups = nil + } + if elem.SourceDestCheck != nil { + ko.Status.SourceDestCheck = elem.SourceDestCheck + } else { + ko.Status.SourceDestCheck = nil + } + if elem.SpotInstanceRequestId != nil { + ko.Status.SpotInstanceRequestID = elem.SpotInstanceRequestId + } else { + ko.Status.SpotInstanceRequestID = nil + } + if elem.SriovNetSupport != nil { + ko.Status.SRIOVNetSupport = elem.SriovNetSupport + } else { + ko.Status.SRIOVNetSupport = nil + } + if elem.State != nil { + f42 := &svcapitypes.InstanceState{} + if elem.State.Code != nil { + f42.Code = elem.State.Code + } + if elem.State.Name != nil { + f42.Name = elem.State.Name + } + ko.Status.State = f42 + } else { + ko.Status.State = nil + } + if elem.StateReason != nil { + f43 := &svcapitypes.StateReason{} + if elem.StateReason.Code != nil { + f43.Code = elem.StateReason.Code + } + if elem.StateReason.Message != nil { + f43.Message = elem.StateReason.Message + } + ko.Status.StateReason = f43 + } else { + ko.Status.StateReason = nil + } + if elem.StateTransitionReason != nil { + ko.Status.StateTransitionReason = elem.StateTransitionReason + } else { + ko.Status.StateTransitionReason = nil + } + if elem.SubnetId != nil { + ko.Spec.SubnetID = elem.SubnetId + } else { + ko.Spec.SubnetID = nil + } + if elem.Tags != nil { + f46 := []*svcapitypes.Tag{} + for _, f46iter := range elem.Tags { + f46elem := &svcapitypes.Tag{} + if f46iter.Key != nil { + f46elem.Key = f46iter.Key + } + if f46iter.Value != nil { + f46elem.Value = f46iter.Value + } + f46 = append(f46, f46elem) + } + ko.Status.Tags = f46 + } else { + ko.Status.Tags = nil + } + if elem.UsageOperation != nil { + ko.Status.UsageOperation = elem.UsageOperation + } else { + ko.Status.UsageOperation = nil + } + if elem.UsageOperationUpdateTime != nil { + ko.Status.UsageOperationUpdateTime = &metav1.Time{*elem.UsageOperationUpdateTime} + } else { + ko.Status.UsageOperationUpdateTime = nil + } + if elem.VirtualizationType != nil { + ko.Status.VirtualizationType = elem.VirtualizationType + } else { + ko.Status.VirtualizationType = nil + } + if elem.VpcId != nil { + ko.Status.VPCID = elem.VpcId + } else { + ko.Status.VPCID = nil + } + found = true + break + } + if !found { + return nil, ackerr.NotFound + } +` + assert.Equal( + expected, + code.SetResource(crd.Config(), crd, op, "resp", "ko", 1), + ) +} + +func TestSetResource_EC2_Instance_ReadMany(t *testing.T) { + // DescribeInstances returns a list of Reservations + // containing a list of Instances. The first Instance + // in the first Reservation list should be used to populate CR. + assert := assert.New(t) + require := require.New(t) + + g := testutil.NewModelForService(t, "ec2") + op := model.OpTypeList + + crd := testutil.GetCRDByName(t, g, "Instance") + require.NotNil(crd) + + expected := ` + found := false + for _, iter0 := range resp.Reservations { + for _, elem := range iter0.Instances { + if elem.AmiLaunchIndex != nil { + ko.Status.AMILaunchIndex = elem.AmiLaunchIndex + } else { + ko.Status.AMILaunchIndex = nil + } + if elem.Architecture != nil { + ko.Status.Architecture = elem.Architecture + } else { + ko.Status.Architecture = nil + } + if elem.BlockDeviceMappings != nil { + f2 := []*svcapitypes.BlockDeviceMapping{} + for _, f2iter := range elem.BlockDeviceMappings { + f2elem := &svcapitypes.BlockDeviceMapping{} + if f2iter.DeviceName != nil { + f2elem.DeviceName = f2iter.DeviceName + } + if f2iter.Ebs != nil { + f2elemf1 := &svcapitypes.EBSBlockDevice{} + if f2iter.Ebs.DeleteOnTermination != nil { + f2elemf1.DeleteOnTermination = f2iter.Ebs.DeleteOnTermination + } + f2elem.EBS = f2elemf1 + } + f2 = append(f2, f2elem) + } + ko.Spec.BlockDeviceMappings = f2 + } else { + ko.Spec.BlockDeviceMappings = nil + } + if elem.BootMode != nil { + ko.Status.BootMode = elem.BootMode + } else { + ko.Status.BootMode = nil + } + if elem.CapacityReservationId != nil { + ko.Status.CapacityReservationID = elem.CapacityReservationId + } else { + ko.Status.CapacityReservationID = nil + } + if elem.CapacityReservationSpecification != nil { + f5 := &svcapitypes.CapacityReservationSpecification{} + if elem.CapacityReservationSpecification.CapacityReservationPreference != nil { + f5.CapacityReservationPreference = elem.CapacityReservationSpecification.CapacityReservationPreference + } + if elem.CapacityReservationSpecification.CapacityReservationTarget != nil { + f5f1 := &svcapitypes.CapacityReservationTarget{} + if elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId != nil { + f5f1.CapacityReservationID = elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationId + } + if elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn != nil { + f5f1.CapacityReservationResourceGroupARN = elem.CapacityReservationSpecification.CapacityReservationTarget.CapacityReservationResourceGroupArn + } + f5.CapacityReservationTarget = f5f1 + } + ko.Spec.CapacityReservationSpecification = f5 + } else { + ko.Spec.CapacityReservationSpecification = nil + } + if elem.CpuOptions != nil { + f6 := &svcapitypes.CPUOptionsRequest{} + if elem.CpuOptions.CoreCount != nil { + f6.CoreCount = elem.CpuOptions.CoreCount + } + if elem.CpuOptions.ThreadsPerCore != nil { + f6.ThreadsPerCore = elem.CpuOptions.ThreadsPerCore + } + ko.Spec.CPUOptions = f6 + } else { + ko.Spec.CPUOptions = nil + } + if elem.EbsOptimized != nil { + ko.Spec.EBSOptimized = elem.EbsOptimized + } else { + ko.Spec.EBSOptimized = nil + } + if elem.ElasticGpuAssociations != nil { + f8 := []*svcapitypes.ElasticGPUAssociation{} + for _, f8iter := range elem.ElasticGpuAssociations { + f8elem := &svcapitypes.ElasticGPUAssociation{} + if f8iter.ElasticGpuAssociationId != nil { + f8elem.ElasticGPUAssociationID = f8iter.ElasticGpuAssociationId + } + if f8iter.ElasticGpuAssociationState != nil { + f8elem.ElasticGPUAssociationState = f8iter.ElasticGpuAssociationState + } + if f8iter.ElasticGpuAssociationTime != nil { + f8elem.ElasticGPUAssociationTime = f8iter.ElasticGpuAssociationTime + } + if f8iter.ElasticGpuId != nil { + f8elem.ElasticGPUID = f8iter.ElasticGpuId + } + f8 = append(f8, f8elem) + } + ko.Status.ElasticGPUAssociations = f8 + } else { + ko.Status.ElasticGPUAssociations = nil + } + if elem.ElasticInferenceAcceleratorAssociations != nil { + f9 := []*svcapitypes.ElasticInferenceAcceleratorAssociation{} + for _, f9iter := range elem.ElasticInferenceAcceleratorAssociations { + f9elem := &svcapitypes.ElasticInferenceAcceleratorAssociation{} + if f9iter.ElasticInferenceAcceleratorArn != nil { + f9elem.ElasticInferenceAcceleratorARN = f9iter.ElasticInferenceAcceleratorArn + } + if f9iter.ElasticInferenceAcceleratorAssociationId != nil { + f9elem.ElasticInferenceAcceleratorAssociationID = f9iter.ElasticInferenceAcceleratorAssociationId + } + if f9iter.ElasticInferenceAcceleratorAssociationState != nil { + f9elem.ElasticInferenceAcceleratorAssociationState = f9iter.ElasticInferenceAcceleratorAssociationState + } + if f9iter.ElasticInferenceAcceleratorAssociationTime != nil { + f9elem.ElasticInferenceAcceleratorAssociationTime = &metav1.Time{*f9iter.ElasticInferenceAcceleratorAssociationTime} + } + f9 = append(f9, f9elem) + } + ko.Status.ElasticInferenceAcceleratorAssociations = f9 + } else { + ko.Status.ElasticInferenceAcceleratorAssociations = nil + } + if elem.EnaSupport != nil { + ko.Status.ENASupport = elem.EnaSupport + } else { + ko.Status.ENASupport = nil + } + if elem.EnclaveOptions != nil { + f11 := &svcapitypes.EnclaveOptionsRequest{} + if elem.EnclaveOptions.Enabled != nil { + f11.Enabled = elem.EnclaveOptions.Enabled + } + ko.Spec.EnclaveOptions = f11 + } else { + ko.Spec.EnclaveOptions = nil + } + if elem.HibernationOptions != nil { + f12 := &svcapitypes.HibernationOptionsRequest{} + if elem.HibernationOptions.Configured != nil { + f12.Configured = elem.HibernationOptions.Configured + } + ko.Spec.HibernationOptions = f12 + } else { + ko.Spec.HibernationOptions = nil + } + if elem.Hypervisor != nil { + ko.Status.Hypervisor = elem.Hypervisor + } else { + ko.Status.Hypervisor = nil + } + if elem.IamInstanceProfile != nil { + f14 := &svcapitypes.IAMInstanceProfileSpecification{} + if elem.IamInstanceProfile.Arn != nil { + f14.ARN = elem.IamInstanceProfile.Arn + } + ko.Spec.IAMInstanceProfile = f14 + } else { + ko.Spec.IAMInstanceProfile = nil + } + if elem.ImageId != nil { + ko.Spec.ImageID = elem.ImageId + } else { + ko.Spec.ImageID = nil + } + if elem.InstanceId != nil { + ko.Status.InstanceID = elem.InstanceId + } else { + ko.Status.InstanceID = nil + } + if elem.InstanceLifecycle != nil { + ko.Status.InstanceLifecycle = elem.InstanceLifecycle + } else { + ko.Status.InstanceLifecycle = nil + } + if elem.InstanceType != nil { + ko.Spec.InstanceType = elem.InstanceType + } else { + ko.Spec.InstanceType = nil + } + if elem.KernelId != nil { + ko.Spec.KernelID = elem.KernelId + } else { + ko.Spec.KernelID = nil + } + if elem.KeyName != nil { + ko.Spec.KeyName = elem.KeyName + } else { + ko.Spec.KeyName = nil + } + if elem.LaunchTime != nil { + ko.Status.LaunchTime = &metav1.Time{*elem.LaunchTime} + } else { + ko.Status.LaunchTime = nil + } + if elem.Licenses != nil { + f22 := []*svcapitypes.LicenseConfiguration{} + for _, f22iter := range elem.Licenses { + f22elem := &svcapitypes.LicenseConfiguration{} + if f22iter.LicenseConfigurationArn != nil { + f22elem.LicenseConfigurationARN = f22iter.LicenseConfigurationArn + } + f22 = append(f22, f22elem) + } + ko.Status.Licenses = f22 + } else { + ko.Status.Licenses = nil + } + if elem.MetadataOptions != nil { + f23 := &svcapitypes.InstanceMetadataOptionsRequest{} + if elem.MetadataOptions.HttpEndpoint != nil { + f23.HTTPEndpoint = elem.MetadataOptions.HttpEndpoint + } + if elem.MetadataOptions.HttpProtocolIpv6 != nil { + f23.HTTPProtocolIPv6 = elem.MetadataOptions.HttpProtocolIpv6 + } + if elem.MetadataOptions.HttpPutResponseHopLimit != nil { + f23.HTTPPutResponseHopLimit = elem.MetadataOptions.HttpPutResponseHopLimit + } + if elem.MetadataOptions.HttpTokens != nil { + f23.HTTPTokens = elem.MetadataOptions.HttpTokens + } + ko.Spec.MetadataOptions = f23 + } else { + ko.Spec.MetadataOptions = nil + } + if elem.Monitoring != nil { + f24 := &svcapitypes.RunInstancesMonitoringEnabled{} + ko.Spec.Monitoring = f24 + } else { + ko.Spec.Monitoring = nil + } + if elem.NetworkInterfaces != nil { + f25 := []*svcapitypes.InstanceNetworkInterfaceSpecification{} + for _, f25iter := range elem.NetworkInterfaces { + f25elem := &svcapitypes.InstanceNetworkInterfaceSpecification{} + if f25iter.Description != nil { + f25elem.Description = f25iter.Description + } + if f25iter.InterfaceType != nil { + f25elem.InterfaceType = f25iter.InterfaceType + } + if f25iter.Ipv4Prefixes != nil { + f25elemf5 := []*svcapitypes.IPv4PrefixSpecificationRequest{} + for _, f25elemf5iter := range f25iter.Ipv4Prefixes { + f25elemf5elem := &svcapitypes.IPv4PrefixSpecificationRequest{} + if f25elemf5iter.Ipv4Prefix != nil { + f25elemf5elem.IPv4Prefix = f25elemf5iter.Ipv4Prefix + } + f25elemf5 = append(f25elemf5, f25elemf5elem) + } + f25elem.IPv4Prefixes = f25elemf5 + } + if f25iter.Ipv6Addresses != nil { + f25elemf6 := []*svcapitypes.InstanceIPv6Address{} + for _, f25elemf6iter := range f25iter.Ipv6Addresses { + f25elemf6elem := &svcapitypes.InstanceIPv6Address{} + if f25elemf6iter.Ipv6Address != nil { + f25elemf6elem.IPv6Address = f25elemf6iter.Ipv6Address + } + f25elemf6 = append(f25elemf6, f25elemf6elem) + } + f25elem.IPv6Addresses = f25elemf6 + } + if f25iter.Ipv6Prefixes != nil { + f25elemf7 := []*svcapitypes.IPv6PrefixSpecificationRequest{} + for _, f25elemf7iter := range f25iter.Ipv6Prefixes { + f25elemf7elem := &svcapitypes.IPv6PrefixSpecificationRequest{} + if f25elemf7iter.Ipv6Prefix != nil { + f25elemf7elem.IPv6Prefix = f25elemf7iter.Ipv6Prefix + } + f25elemf7 = append(f25elemf7, f25elemf7elem) + } + f25elem.IPv6Prefixes = f25elemf7 + } + if f25iter.NetworkInterfaceId != nil { + f25elem.NetworkInterfaceID = f25iter.NetworkInterfaceId + } + if f25iter.PrivateIpAddress != nil { + f25elem.PrivateIPAddress = f25iter.PrivateIpAddress + } + if f25iter.PrivateIpAddresses != nil { + f25elemf13 := []*svcapitypes.PrivateIPAddressSpecification{} + for _, f25elemf13iter := range f25iter.PrivateIpAddresses { + f25elemf13elem := &svcapitypes.PrivateIPAddressSpecification{} + if f25elemf13iter.Primary != nil { + f25elemf13elem.Primary = f25elemf13iter.Primary + } + if f25elemf13iter.PrivateIpAddress != nil { + f25elemf13elem.PrivateIPAddress = f25elemf13iter.PrivateIpAddress + } + f25elemf13 = append(f25elemf13, f25elemf13elem) + } + f25elem.PrivateIPAddresses = f25elemf13 + } + if f25iter.SubnetId != nil { + f25elem.SubnetID = f25iter.SubnetId + } + f25 = append(f25, f25elem) + } + ko.Spec.NetworkInterfaces = f25 + } else { + ko.Spec.NetworkInterfaces = nil + } + if elem.OutpostArn != nil { + ko.Status.OutpostARN = elem.OutpostArn + } else { + ko.Status.OutpostARN = nil + } + if elem.Placement != nil { + f27 := &svcapitypes.Placement{} + if elem.Placement.Affinity != nil { + f27.Affinity = elem.Placement.Affinity + } + if elem.Placement.AvailabilityZone != nil { + f27.AvailabilityZone = elem.Placement.AvailabilityZone + } + if elem.Placement.GroupName != nil { + f27.GroupName = elem.Placement.GroupName + } + if elem.Placement.HostId != nil { + f27.HostID = elem.Placement.HostId + } + if elem.Placement.HostResourceGroupArn != nil { + f27.HostResourceGroupARN = elem.Placement.HostResourceGroupArn + } + if elem.Placement.PartitionNumber != nil { + f27.PartitionNumber = elem.Placement.PartitionNumber + } + if elem.Placement.SpreadDomain != nil { + f27.SpreadDomain = elem.Placement.SpreadDomain + } + if elem.Placement.Tenancy != nil { + f27.Tenancy = elem.Placement.Tenancy + } + ko.Spec.Placement = f27 + } else { + ko.Spec.Placement = nil + } + if elem.Platform != nil { + ko.Status.Platform = elem.Platform + } else { + ko.Status.Platform = nil + } + if elem.PlatformDetails != nil { + ko.Status.PlatformDetails = elem.PlatformDetails + } else { + ko.Status.PlatformDetails = nil + } + if elem.PrivateDnsName != nil { + ko.Status.PrivateDNSName = elem.PrivateDnsName + } else { + ko.Status.PrivateDNSName = nil + } + if elem.PrivateIpAddress != nil { + ko.Spec.PrivateIPAddress = elem.PrivateIpAddress + } else { + ko.Spec.PrivateIPAddress = nil + } + if elem.ProductCodes != nil { + f32 := []*svcapitypes.ProductCode{} + for _, f32iter := range elem.ProductCodes { + f32elem := &svcapitypes.ProductCode{} + if f32iter.ProductCodeId != nil { + f32elem.ProductCodeID = f32iter.ProductCodeId + } + if f32iter.ProductCodeType != nil { + f32elem.ProductCodeType = f32iter.ProductCodeType + } + f32 = append(f32, f32elem) + } + ko.Status.ProductCodes = f32 + } else { + ko.Status.ProductCodes = nil + } + if elem.PublicDnsName != nil { + ko.Status.PublicDNSName = elem.PublicDnsName + } else { + ko.Status.PublicDNSName = nil + } + if elem.PublicIpAddress != nil { + ko.Status.PublicIPAddress = elem.PublicIpAddress + } else { + ko.Status.PublicIPAddress = nil + } + if elem.RamdiskId != nil { + ko.Spec.RAMDiskID = elem.RamdiskId + } else { + ko.Spec.RAMDiskID = nil + } + if elem.RootDeviceName != nil { + ko.Status.RootDeviceName = elem.RootDeviceName + } else { + ko.Status.RootDeviceName = nil + } + if elem.RootDeviceType != nil { + ko.Status.RootDeviceType = elem.RootDeviceType + } else { + ko.Status.RootDeviceType = nil + } + if elem.SecurityGroups != nil { + f38 := []*string{} + for _, f38iter := range elem.SecurityGroups { + var f38elem string + f38elem = *f38iter.GroupName + f38 = append(f38, &f38elem) + } + ko.Spec.SecurityGroups = f38 + } else { + ko.Spec.SecurityGroups = nil + } + if elem.SourceDestCheck != nil { + ko.Status.SourceDestCheck = elem.SourceDestCheck + } else { + ko.Status.SourceDestCheck = nil + } + if elem.SpotInstanceRequestId != nil { + ko.Status.SpotInstanceRequestID = elem.SpotInstanceRequestId + } else { + ko.Status.SpotInstanceRequestID = nil + } + if elem.SriovNetSupport != nil { + ko.Status.SRIOVNetSupport = elem.SriovNetSupport + } else { + ko.Status.SRIOVNetSupport = nil + } + if elem.State != nil { + f42 := &svcapitypes.InstanceState{} + if elem.State.Code != nil { + f42.Code = elem.State.Code + } + if elem.State.Name != nil { + f42.Name = elem.State.Name + } + ko.Status.State = f42 + } else { + ko.Status.State = nil + } + if elem.StateReason != nil { + f43 := &svcapitypes.StateReason{} + if elem.StateReason.Code != nil { + f43.Code = elem.StateReason.Code + } + if elem.StateReason.Message != nil { + f43.Message = elem.StateReason.Message + } + ko.Status.StateReason = f43 + } else { + ko.Status.StateReason = nil + } + if elem.StateTransitionReason != nil { + ko.Status.StateTransitionReason = elem.StateTransitionReason + } else { + ko.Status.StateTransitionReason = nil + } + if elem.SubnetId != nil { + ko.Spec.SubnetID = elem.SubnetId + } else { + ko.Spec.SubnetID = nil + } + if elem.Tags != nil { + f46 := []*svcapitypes.Tag{} + for _, f46iter := range elem.Tags { + f46elem := &svcapitypes.Tag{} + if f46iter.Key != nil { + f46elem.Key = f46iter.Key + } + if f46iter.Value != nil { + f46elem.Value = f46iter.Value + } + f46 = append(f46, f46elem) + } + ko.Status.Tags = f46 + } else { + ko.Status.Tags = nil + } + if elem.UsageOperation != nil { + ko.Status.UsageOperation = elem.UsageOperation + } else { + ko.Status.UsageOperation = nil + } + if elem.UsageOperationUpdateTime != nil { + ko.Status.UsageOperationUpdateTime = &metav1.Time{*elem.UsageOperationUpdateTime} + } else { + ko.Status.UsageOperationUpdateTime = nil + } + if elem.VirtualizationType != nil { + ko.Status.VirtualizationType = elem.VirtualizationType + } else { + ko.Status.VirtualizationType = nil + } + if elem.VpcId != nil { + ko.Status.VPCID = elem.VpcId + } else { + ko.Status.VPCID = nil + } + found = true + break + } + break + } + if !found { + return nil, ackerr.NotFound + } +` + assert.Equal( + expected, + code.SetResource(crd.Config(), crd, op, "resp", "ko", 1), + ) +} diff --git a/pkg/model/crd.go b/pkg/model/crd.go index bab070f4..1ef2a7fb 100644 --- a/pkg/model/crd.go +++ b/pkg/model/crd.go @@ -23,6 +23,7 @@ import ( "github.com/gertd/go-pluralize" ackgenconfig "github.com/aws-controllers-k8s/code-generator/pkg/config" + "github.com/aws-controllers-k8s/code-generator/pkg/fieldpath" "github.com/aws-controllers-k8s/code-generator/pkg/names" "github.com/aws-controllers-k8s/code-generator/pkg/util" ) @@ -468,8 +469,8 @@ func (r *CRD) getWrapperOutputShape( if fieldPath == "" { return shape, nil } - fieldPathParts := strings.Split(fieldPath, ".") - wrapperField := fieldPathParts[0] + fp := fieldpath.FromString(fieldPath) + wrapperField := fp.PopFront() memberRef, ok := shape.MemberRefs[wrapperField] if !ok { @@ -478,15 +479,17 @@ func (r *CRD) getWrapperOutputShape( wrapperField, shape.ShapeName) } - // wrapper field must be structure; otherwise cannot unpack + // wrapper field must be list or structure; otherwise cannot unpack + if memberRef.Shape.Type == "list" { + memberRef = &memberRef.Shape.MemberRef + } if memberRef.Shape.Type != "structure" { return nil, fmt.Errorf( "output wrapper overrides can only contain fields of type"+ " 'structure'. Found wrapper override field %s of type '%s'", wrapperField, memberRef.Shape.Type) } - remainPath := strings.Join(fieldPathParts[1:], ".") - return r.getWrapperOutputShape(memberRef.Shape, remainPath) + return r.getWrapperOutputShape(memberRef.Shape, fp.String()) } // GetCustomImplementation returns custom implementation method name for the diff --git a/pkg/model/model_ec2_test.go b/pkg/model/model_ec2_test.go index 142cbdd7..47dd2cff 100644 --- a/pkg/model/model_ec2_test.go +++ b/pkg/model/model_ec2_test.go @@ -184,3 +184,154 @@ func TestEC2_NestedReference(t *testing.T) { assert.Equal("GatewayRef", gatewayRefAttr.Names.Camel) assert.Equal("*ackv1alpha1.AWSResourceReferenceWrapper", gatewayRefAttr.GoType) } + +func TestEC2_VPCEndpoint_WrapperOutput(t *testing.T) { + // CreateVpcEndpointOutput has a VpcEndpoint struct + // containing the VPCEndpoint data; therefore, + // unwrap the struct using config: + // output_wrapper_field_path: VpcEndpoint + assert := assert.New(t) + require := require.New(t) + + g := testutil.NewModelForService(t, "ec2") + + crds, err := g.GetCRDs() + require.Nil(err) + + crd := getCRDByName("VpcEndpoint", crds) + require.NotNil(crd) + + assert.Equal("VPCEndpoint", crd.Names.Camel) + assert.Equal("vpcEndpoint", crd.Names.CamelLower) + assert.Equal("vpc_endpoint", crd.Names.Snake) + + specFields := crd.SpecFields + statusFields := crd.StatusFields + + expSpecFieldCamel := []string{ + "ClientToken", + "PolicyDocument", + "PrivateDNSEnabled", + "RouteTableIDs", + "SecurityGroupIDs", + "ServiceName", + "SubnetIDs", + "TagSpecifications", + "VPCEndpointType", + "VPCID", + } + assert.Equal(expSpecFieldCamel, attrCamelNames(specFields)) + + expStatusFieldCamel := []string{ + "CreationTimestamp", + "DNSEntries", + "Groups", + "LastError", + "NetworkInterfaceIDs", + "OwnerID", + "RequesterManaged", + "State", + "Tags", + "VPCEndpointID", + } + assert.Equal(expStatusFieldCamel, attrCamelNames(statusFields)) +} + +func TestEC2_Instance_WrapperOutput(t *testing.T) { + // Reservation (RunInstances output shape) has a list + // of Instances. This list needs to be "unwrapped" to + // extract Instance data out of the FIRST entry; therefore, + // unwrap the list using config: + // output_wrapper_field_path: Instances + assert := assert.New(t) + require := require.New(t) + + g := testutil.NewModelForService(t, "ec2") + + crds, err := g.GetCRDs() + require.Nil(err) + + crd := getCRDByName("Instance", crds) + require.NotNil(crd) + + assert.Equal("Instance", crd.Names.Camel) + assert.Equal("instance", crd.Names.CamelLower) + assert.Equal("instance", crd.Names.Snake) + + specFields := crd.SpecFields + statusFields := crd.StatusFields + + expSpecFieldCamel := []string{ + "BlockDeviceMappings", + "CPUOptions", + "CapacityReservationSpecification", + "CreditSpecification", + "DisableAPITermination", + "EBSOptimized", + "ElasticGPUSpecification", + "ElasticInferenceAccelerators", + "EnclaveOptions", + "HibernationOptions", + "IAMInstanceProfile", + "IPv6AddressCount", + "IPv6Addresses", + "ImageID", + "InstanceInitiatedShutdownBehavior", + "InstanceMarketOptions", + "InstanceType", + "KernelID", + "KeyName", + "LaunchTemplate", + "LicenseSpecifications", + "MaxCount", + "MetadataOptions", + "MinCount", + "Monitoring", + "NetworkInterfaces", + "Placement", + "PrivateIPAddress", + "RAMDiskID", + "SecurityGroupIDs", + "SecurityGroups", + "SubnetID", + "TagSpecifications", + "UserData", + } + assert.Equal(expSpecFieldCamel, attrCamelNames(specFields)) + + expStatusFieldCamel := []string{ + "AMILaunchIndex", + "Architecture", + "BootMode", + "CapacityReservationID", + "ENASupport", + "ElasticGPUAssociations", + "ElasticInferenceAcceleratorAssociations", + "Hypervisor", + "InstanceID", + "InstanceLifecycle", + "LaunchTime", + "Licenses", + "OutpostARN", + "Platform", + "PlatformDetails", + "PrivateDNSName", + "ProductCodes", + "PublicDNSName", + "PublicIPAddress", + "RootDeviceName", + "RootDeviceType", + "SRIOVNetSupport", + "SourceDestCheck", + "SpotInstanceRequestID", + "State", + "StateReason", + "StateTransitionReason", + "Tags", + "UsageOperation", + "UsageOperationUpdateTime", + "VPCID", + "VirtualizationType", + } + assert.Equal(expStatusFieldCamel, attrCamelNames(statusFields)) +} diff --git a/pkg/testdata/models/apis/ec2/0000-00-00/generator.yaml b/pkg/testdata/models/apis/ec2/0000-00-00/generator.yaml index e1111e9d..67a5b5da 100644 --- a/pkg/testdata/models/apis/ec2/0000-00-00/generator.yaml +++ b/pkg/testdata/models/apis/ec2/0000-00-00/generator.yaml @@ -1,7 +1,13 @@ ignore: field_paths: - - CreateVpcInput.DryRun - CreateDhcpOptionsInput.DryRun + - CreateVpcInput.DryRun + - CreateVpcEndpointInput.DryRun + - Instance.ClientToken + - InstanceNetworkInterfaceSpecification.Groups + - RunInstancesInput.AdditionalInfo + - RunInstancesInput.ClientToken + - RunInstancesInput.DryRun resource_names: - AccountAttribute - CapacityReservation @@ -16,7 +22,7 @@ ignore: - Fleet - FpgaImage - Image - - Instance + #- Instance - InstanceExportTask - InternetGateway - KeyPair @@ -68,13 +74,33 @@ operations: output_wrapper_field_path: LaunchTemplate CreateVpcEndpoint: output_wrapper_field_path: VpcEndpoint - + RunInstances: + #ouput shape: Reservation + output_wrapper_field_path: Instances + operation_type: + - Create + resource_name: Instance + DescribeInstances: + #output shape: DescribeInstancesOutput + output_wrapper_field_path: Reservations.Instances + operation_type: + - List + resource_name: Instance + TerminateInstances: + operation_type: + - Delete + resource_name: Instance resources: DhcpOptions: fields: DHCPConfigurations.Values: set: - from: AttributeValue.Value + Instance: + fields: + SecurityGroups: + set: + - from: GroupName SecurityGroup: renames: operations: