Skip to content

Commit

Permalink
Handle nested properties in cfn schema generation
Browse files Browse the repository at this point in the history
  • Loading branch information
JordonPhillips committed Feb 28, 2023
1 parent b2df554 commit 86720ec
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 86720ec

Please sign in to comment.