From 629b147d8d1c93dc1c7e558a7065d77808941529 Mon Sep 17 00:00:00 2001 From: Jordon Phillips Date: Tue, 28 Feb 2023 17:10:07 +0100 Subject: [PATCH] Handle nested properties in cfn schema generation --- .../traits/CfnResourceIndex.java | 42 ++++++------ .../integ/nested-properties.cfn.json | 38 +++++++++++ .../fromsmithy/integ/nested-properties.smithy | 67 +++++++++++++++++++ 3 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.cfn.json create mode 100644 smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.smithy diff --git a/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceIndex.java b/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceIndex.java index 0733408101c..882bf90c985 100644 --- a/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceIndex.java +++ b/smithy-aws-cloudformation-traits/src/main/java/software/amazon/smithy/aws/cloudformation/traits/CfnResourceIndex.java @@ -28,9 +28,9 @@ import software.amazon.smithy.model.knowledge.BottomUpIndex; import software.amazon.smithy.model.knowledge.IdentifierBindingIndex; import software.amazon.smithy.model.knowledge.KnowledgeIndex; -import software.amazon.smithy.model.knowledge.OperationIndex; import software.amazon.smithy.model.knowledge.PropertyBindingIndex; import software.amazon.smithy.model.shapes.MemberShape; +import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ResourceShape; import software.amazon.smithy.model.shapes.Shape; import software.amazon.smithy.model.shapes.ShapeId; @@ -89,7 +89,7 @@ public enum Mutability { } public CfnResourceIndex(Model model) { - OperationIndex operationIndex = OperationIndex.of(model); + PropertyBindingIndex propertyIndex = PropertyBindingIndex.of(model); BottomUpIndex bottomUpIndex = BottomUpIndex.of(model); model.shapes(ResourceShape.class) .filter(shape -> shape.hasTrait(CfnResourceTrait.ID)) @@ -110,37 +110,37 @@ public CfnResourceIndex(Model model) { // Use the read lifecycle's input to collect the additional identifiers // and its output to collect readable properties. resource.getRead().ifPresent(operationId -> { - operationIndex.getInputShape(operationId).ifPresent(input -> { - addAdditionalIdentifiers(builder, computeResourceAdditionalIdentifiers(input)); - }); - operationIndex.getOutputShape(operationId).ifPresent(output -> { - updatePropertyMutabilities(builder, model, resourceId, operationId, output, - SetUtils.of(Mutability.READ), this::addReadMutability); - }); + OperationShape operation = model.expectShape(operationId, OperationShape.class); + StructureShape input = model.expectShape(operation.getInputShape(), StructureShape.class); + addAdditionalIdentifiers(builder, computeResourceAdditionalIdentifiers(input)); + + StructureShape output = propertyIndex.getOutputPropertiesShape(operation); + updatePropertyMutabilities(builder, model, resourceId, operationId, output, + SetUtils.of(Mutability.READ), this::addReadMutability); }); // Use the put lifecycle's input to collect put-able properties. resource.getPut().ifPresent(operationId -> { - operationIndex.getInputShape(operationId).ifPresent(input -> { - updatePropertyMutabilities(builder, model, resourceId, operationId, input, - SetUtils.of(Mutability.CREATE, Mutability.WRITE), this::addPutMutability); - }); + OperationShape operation = model.expectShape(operationId, OperationShape.class); + StructureShape input = propertyIndex.getInputPropertiesShape(operation); + updatePropertyMutabilities(builder, model, resourceId, operationId, input, + SetUtils.of(Mutability.CREATE, Mutability.WRITE), this::addPutMutability); }); // Use the create lifecycle's input to collect creatable properties. resource.getCreate().ifPresent(operationId -> { - operationIndex.getInputShape(operationId).ifPresent(input -> { - updatePropertyMutabilities(builder, model, resourceId, operationId, input, - SetUtils.of(Mutability.CREATE), this::addCreateMutability); - }); + OperationShape operation = model.expectShape(operationId, OperationShape.class); + StructureShape input = propertyIndex.getInputPropertiesShape(operation); + updatePropertyMutabilities(builder, model, resourceId, operationId, input, + SetUtils.of(Mutability.CREATE), this::addCreateMutability); }); // Use the update lifecycle's input to collect writeable properties. resource.getUpdate().ifPresent(operationId -> { - operationIndex.getInputShape(operationId).ifPresent(input -> { - updatePropertyMutabilities(builder, model, resourceId, operationId, input, - SetUtils.of(Mutability.WRITE), this::addWriteMutability); - }); + OperationShape operation = model.expectShape(operationId, OperationShape.class); + StructureShape input = propertyIndex.getInputPropertiesShape(operation); + updatePropertyMutabilities(builder, model, resourceId, operationId, input, + SetUtils.of(Mutability.WRITE), this::addWriteMutability); }); // Apply any members found through the trait's additionalSchemas property. diff --git a/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.cfn.json b/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.cfn.json new file mode 100644 index 00000000000..87ef2763016 --- /dev/null +++ b/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.cfn.json @@ -0,0 +1,38 @@ +{ + "typeName": "Smithy::TestService::Forecast", + "description": "Definition of Smithy::TestService::Forecast Resource Type", + "properties": { + "ChanceOfRain": { + "type": "number" + }, + "ForecastId": { + "type": "string" + } + }, + "createOnlyProperties": [ + "/properties/ForecastId" + ], + "primaryIdentifier": [ + "/properties/ForecastId" + ], + "handlers": { + "create": { + "permissions": [ + "testservice:CreateForecast", + "testservice:PutForecast" + ] + }, + "read": { + "permissions": [ + "testservice:GetForecast" + ] + }, + "update": { + "permissions": [ + "testservice:PutForecast", + "testservice:UpdateForecast" + ] + } + }, + "additionalProperties": false +} diff --git a/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.smithy b/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.smithy new file mode 100644 index 00000000000..9ba3c85238a --- /dev/null +++ b/smithy-aws-cloudformation/src/test/resources/software/amazon/smithy/aws/cloudformation/schema/fromsmithy/integ/nested-properties.smithy @@ -0,0 +1,67 @@ +$version: "2.0" + +namespace smithy.example + +use aws.cloudformation#cfnMutability +use aws.cloudformation#cfnResource + +service TestService { + version: "2020-07-02", + resources: [Forecast] +} + +@cfnResource() +resource Forecast { + identifiers: { + forecastId: String + } + properties: { + chanceOfRain: Float + } + read: GetForecast + put: PutForecast + create: CreateForecast + update: UpdateForecast +} + +@readonly +operation GetForecast { + input := { + @required + forecastId: String + } + output := { + @nestedProperties + forecastData: ForecastData + } +} + +@idempotent +operation PutForecast { + input := { + @required + forecastId: String + @nestedProperties + forecastData: ForecastData + } +} + +operation CreateForecast { + input := { + @nestedProperties + forecastData: ForecastData + } +} + +operation UpdateForecast { + input := { + @required + forecastId: String + @nestedProperties + forecastData: ForecastData + } +} + +structure ForecastData for Forecast { + $chanceOfRain +}