Generating CloudFormation Resource Schemas from Smithy#
This guide describes how Smithy models can generate CloudFormation Resource Schemas.
Introduction#
CloudFormation Resource Schemas are the standard method of modeling a resource provider for use within CloudFormation. These schemas can then be used to develop the resource provider for support in CloudFormation. Generating Resource Schemas automatically from Smithy resources removes the duplicate effort of specifying them.
AWS CloudFormation traits define how CloudFormation Resource Schemas should be generated from Smithy resources. Automatically generating schemas from a service's API lowers the effort needed to generate and maintain them, keeps the schemas in sync with any changes to the Smithy model, reduces the potential for errors in the translation, and provides a more complete depiction of a resource in its schema. These schemas can be utilized by the CloudFormation Command Line Interface to build, register, and deploy resource providers.
Other traits may also influence CloudFormation Resource Schema generation.
Differences between Smithy resources and CloudFormation Resource Schemas#
Smithy and CloudFormation have different approaches to modeling resources. In Smithy, a resource is an entity with an identity that has a set of operations. CloudFormation resources are defined as a collection of properties and their attributes, along with additional information on which properties are identifiers or have restrictions on their mutability.
Generating Schemas with smithy-build#
The cloudformation
plugin contained in the software.amazon.smithy:smithy-aws-cloudformation
package can be used with either the Smithy Gradle plugin or Smithy CLI to
generate CloudFormation Resource Schemas from Smithy models.
The following example shows how to generate CloudFormation Resource Schemas from a Smithy model using the Smithy CLI:
{
"version": "1.0",
"maven": {
"dependencies": [
"software.amazon.smithy:smithy-aws-cloudformation:1.53.0",
// Required for @service trait
"software.amazon.smithy:smithy-aws-traits:1.53.0"
]
},
"plugins": {
"cloudformation": {
"service": "smithy.example#Queues",
"organizationName": "Smithy"
}
}
}
Important
A dependency on "software.amazon.smithy:smithy-aws-cloudformation:1.53.0" is required in order for smithy-build to map the "cloudformation" plugin name to the correct Java library implementation.
The following example shows how to configure Gradle to generate CloudFormation Resource Schemas from a Smithy model using a build-only dependency:
plugins {
java
id("software.amazon.smithy.gradle.smithy-jar").version("1.1.0")
}
dependencies {
smithyBuild("software.amazon.smithy:smithy-aws-cloudformation:1.53.0")
// Required for @service trait
implementation("software.amazon.smithy:smithy-aws-traits:1.53.0")
}
plugins {
id 'java'
id 'software.amazon.smithy.gradle.smithy-jar' version '1.1.0'
}
dependencies {
smithyBuild 'software.amazon.smithy:smithy-aws-cloudformation:1.53.0'
// Required for @service trait
implementation 'software.amazon.smithy:smithy-aws-traits:1.53.0'
}
Important
A build-only dependency on "software.amazon.smithy:smithy-aws-cloudformation:1.53.0" is required in order for smithy-build to map the "cloudformation" plugin name to the correct Java library implementation.
The Smithy Gradle plugin relies on a smithy-build.json
file found at the
root of a project to define the actual process of generating the CloudFormation
Resource Schemas. The following example defines a smithy-build.json
file
that generates a CloudFormation Resource Schemas for the specified resource
shapes bound to the smithy.example#Queues
service using the Smithy
organization.
{
"version": "1.0",
"plugins": {
"cloudformation": {
"service": "smithy.example#Queues",
"organizationName": "Smithy"
}
}
}
AWS Service teams SHOULD NOT set the organizationName
property, and instead
use the cloudFormationName property of the aws.api#service trait. The following configuration and model would
generate one Resource Schema with the typeName
of AWS:Queues:Queue
.
{
"version": "1.0",
"plugins": {
"cloudformation": {
"service": "smithy.example#QueueService",
}
}
}
$version: "2"
namespace smithy.example
use aws.api#service
@service(sdkId: "Queues", cloudFormationName: "Queues")
service QueueService {
version: "2020-07-02"
resources: [Queue]
}
CloudFormation configuration settings#
The cloudformation
plugin provides configuration options to influence the
Resource Schemas that it generates.
Tip
You typically only need to configure the service
and
organizationName
settings to generate Resource Schemas.
The following settings are supported:
- service (
string
) Required. The Smithy service shape ID to convert. For example,
smithy.example#Queues
.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy" } } }
- organizationName (
string
) The
Organization
component of the resource's type name. Defaults to "AWS" if the aws.api#service trait is present, otherwise is required.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy" } } }
- serviceName (
string
) Allows overriding the
Service
component of the resource's type name. This value defaults to the cloudFormationName property of the aws.api#service trait if present, or the shape name of the specified service shape otherwise.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#QueueService", "organizationName": "Smithy", "serviceName": "Queues" } } }
- externalDocs (
[string]
) Limits the source of generated "documentationUrl" fields to the specified priority ordered list of names in an externalDocumentation trait. This list is case insensitive. By default, this is a list of the following values: "Documentation Url", "DocumentationUrl", "API Reference", "User Guide", "Developer Guide", "Reference", and "Guide".
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "externalDocs": [ "Documentation Url", "Custom" ] } } }
- sourceDocs (
[string]
) Limits the source of generated "sourceUrl" fields to the specified priority ordered list of names in an externalDocumentation trait. This list is case insensitive. By default, this is a list of the following values: "Source Url", "SourceUrl", "Source", and "Source Code".
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "sourceDocs": [ "Source Url", "Custom" ] } } }
- jsonAdd (
Map<String, Map<String, Node>>
) Adds or replaces the JSON value in the generated Resource Schemas at the given JSON pointer locations with a different JSON value. The value must be a map where each key is a resource shape ID. The value is a map where each key is a valid JSON pointer string as defined in RFC 6901. Each value in the nested map is the JSON value to add or replace at the given target.
Values are added using similar semantics of the "add" operation of JSON Patch, as specified in RFC 6902, with the exception that adding properties to an undefined object will create nested objects in the result as needed.
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "jsonAdd": { "smithy.example#Queue": { "/info/title": "Replaced title value", "/info/nested/foo": { "hi": "Adding this object created intermediate objects too!" }, "/info/nested/foo/baz": true } } } } }
- disableHandlerPermissionGeneration (
boolean
) Sets whether to disable generating
handler
permission
lists for Resource Schemas. By default, handler permissions lists are automatically added to schemas based on Resource lifecycle operations and permissions listed in the requiredActions property of the aws.iam#iamAction trait on the operation. See the handlers section in the CloudFormation Resource Schemas documentation for more information.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "disableHandlerPermissionGeneration": true } } }
CloudFormation Resource Schema handlers determine what provisioning actions can be performed for the resource. The handlers utilized by CloudFormation align with some Resource lifecycle operations. These operations can also define other permission actions required to invoke them with the requiredActions property of the aws.iam#iamAction trait
When handler permission generation is enabled, all the actions required to invoke the operations related to the handler, including the actions for the operations themselves, are used to populate permission lists:
"handlers": { "create": { "permissions": [ "dependency:GetDependencyComponent", "queues:CreateQueue" ] }, "read": { "permissions": [ "queues:GetQueue" ] }, "update": { "permissions": [ "dependency:GetDependencyComponent", "queues:UpdateQueue" ] }, "delete": { "permissions": [ "queues:DeleteQueue" ] }, "list": { "permissions": [ "queues:ListQueues" ] } },
- disableDeprecatedPropertyGeneration (
boolean
) Sets whether to disable generating
deprecatedProperties
for Resource Schemas. By default, deprecated members are automatically added to thedeprecatedProperties
schema property. See the deprecatedProperties section in the CloudFormation Resource Schemas documentation for more information.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "disableDeprecatedPropertyGeneration": true } } }
- disableRequiredPropertyGeneration (
boolean
) Sets whether to disable generating
required
for Resource Schemas. By default, required members are automatically added to therequired
schema property. See the required property section in the CloudFormation Resource Schemas documentation for more information.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "disableRequiredPropertyGeneration": true } } }
- disableCapitalizedProperties (
boolean
) Sets whether to disable automatically capitalizing names of properties of Resource Schemas. By default, property names of resource schemas are capitalized if no cfnName trait is applied.
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "disableCapitalizedProperties": true } } }
JSON schema configuration settings#
- defaultTimestampFormat (
string
) Sets the assumed timestampFormat trait value for timestamps with no explicit timestampFormat trait. The provided value is expected to be a string. Defaults to "date-time" if not set. Can be set to "date-time", "epoch-seconds", or "http-date".
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "defaultTimestampFormat": "epoch-seconds" } } }
- schemaDocumentExtensions (
Map<String, any>
) Adds custom top-level key-value pairs to all of the generated CloudFormation Resource Schemas. Any existing value is overwritten.
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "schemaDocumentExtensions": { "x-my-custom-top-level-property": "Hello!", "x-another-custom-top-level-property": { "can be": ["complex", "value", "too!"] } } } } }
- disableFeatures (
[string]
) Disables JSON schema and CloudFormation schema property names from appearing in the generated CloudFormation Resource Schemas.
{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "disableFeatures": ["propertyNames"] } } }
- useIntegerType (
boolean
) Set to true to use the
integer
type when convertingbyte
,short
,integer
, andlong
shapes.By default, these shape types are converted with a type of
number
.{ "version": "1.0", "plugins": { "cloudformation": { "service": "smithy.example#Queues", "organizationName": "Smithy", "useIntegerType": true } } }
Other traits that influence generation#
In addition to the AWS CloudFormation traits, the following traits affect the generation of CloudFormation Resource Schemas.
documentation
- When applied to a Resource shape, the contents will be converted
into the
description
property of the generated Resource Schema. externalDocumentation
- When applied to a resource shape, the contents will be converted according to the externalDocs and sourceDocs settings.
Note
Custom traits defined in a Smithy model are not
converted and added to CloudFormation Resource Schemas. Doing so requires
the creation of a custom software.amazon.smithy.aws.cloudformation.schema.fromsmithy.Smithy2CfnExtension
.
Generating Schemas with code#
Developers that need more advanced control over the generation of
CloudFormation resources from Smithy can use the
software.amazon.smithy:smithy-aws-cloudformation
Java library to perform
the generation.
First, you'll need to get a copy of the library. The following example shows
how to install software.amazon.smithy:smithy-aws-cloudformation
through
Gradle:
dependencies {
implementation("software.amazon.smithy:smithy-aws-cloudformation:1.53.0")
}
dependencies {
implementation 'software.amazon.smithy:smithy-aws-cloudformation:1.53.0'
}
Next, you need to create and configure a CloudFormationConverter
:
import java.util.List;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.aws.cloudformation.schema.CfnConfig;
import software.amazon.smithy.aws.cloudformation.schema.fromsmithy.CfnConverter;
import software.amazon.smithy.aws.cloudformation.schema.model.ResourceSchema;
CfnConverter converter = CfnConverter.create();
// Add any necessary configuration settings.
CfnConfig config = new CfnConfig();
config.setService(ShapeId.from("smithy.example#Queues"));
config.setOrganizationName("Smithy");
// Generate the schemas.
List<ResourceSchema> schemas = converter.convert(myModel);
The conversion process is highly extensible through
software.amazon.smithy.aws.cloudformation.schema.fromsmithy.Smithy2CfnExtension
service providers. See the Javadocs for more information.