Generic framework for creating AWS CloudFormation custom resources
This module contains an extensible framework for creating AWS CloudFormation custom resource handlers. The included template.yml can be used to create a custom resource handler stack. It outputs the ServiceToken so that it can be used as a nested stack.
Currently supported resources types:
Custom::AWS-ElasticTranscoder-Pipeline
Custom::AWS-ElasticTranscoder-Preset
Custom::AWS-APIGateway-Deployment
Custom::AWS-APIGateway-ApiKey
Notes:
- unfortunately due to a limitation of CloudFormation, '::' cannot be used as a separator.
- Supported property names mostly resemble their AWS Javascript SDK counterparts to allow a one-to-one mapping
Transcoder:
Type: Custom::AWS-ElasticTranscoder-Pipeline
Properties:
ServiceToken: !GetAtt CustomResourceHandlerStack.Outputs.Arn
InputBucket: !Ref InputBucket
Role: !GetAtt ElasticTranscoderRole.Arn
Notifications:
Progressing: ''
Completed: !Ref TranscodingCompletedSNSTopic
Warning: ''
Error: ''
ContentConfig:
Bucket: !Ref ContentBucket
StorageClass: Standard
Permissions:
- Access:
- Read
Grantee: AuthenticatedUsers
GranteeType: Group
ThumbnailConfig:
Bucket: !Ref ThumbnailBucket
Permissions: []
Preset:
Type: Custom::AWS-ElasticTranscoder-Preset
Properties:
ServiceToken: !GetAtt CustomResourceHandlerStack.Outputs.Arn
Description: "My custom preset"
Container: mp3
Audio:
Channels: '1'
SampleRate: auto
Codec: mp3
BitRate: '64'
Stage:
Type: AWS::ApiGateway::Stage
Properties:
StageName: mystage
DeploymentId: !Ref Deployment
RestApiId: !Ref MyAPI
Deployment:
Type: Custom::AWS-APIGateway-Deployment
Properties:
ServiceToken: !GetAtt CustomResourceHandlerStack.Outputs.Arn
description: version ${env:CODEBUILD_RESOLVED_SOURCE_VERSION}
restApiId: !Ref MyAPI
Notes: The resource has to change to trigger a custom resource request. Therefore the description has to change whenever a new version needs to be deployed. In this example this has been done by using the commit SHA from AWS CodeBuild. The env construct is modelled according to the syntax defined by serverless.com. The following ugly preprocessing script replaces environment variables by their value:
# replace environment variables based on the syntax defined by serverless.com, i.e. ${env: VARIABLE_NAME}
sed -e 's/\(.*\)${[[:space:]]*env:[[:space:]]*\([[:graph:]]\+\)[[:space:]]*}/echo "\1$\2"/eg'
It needs to be excuted before packaging and executing the template. This makes the deployment nicely appear in the AWS API Gateway console with description 'version <git commit SHA>'
APIKey:
Type: Custom::AWS-APIGateway-ApiKey
Properties:
ServiceToken: !GetAtt CustomResourceHandler.Arn
enabled: true
value: 'valueabcdefghijklmnopqrstuvwxyz123456789'
stageKeys:
- restApiId: !Ref MyAPI
stageName: mystage
CloudFormation calls CustomResource.request to create/update/delete a resource. It acts as a factory method that creates a CustomResource instance based on the resource type. It does this by removing the 'Custom::' prefix, and splitting the type into [brand, service, resource] based on the '-' separator. Currently this is mapped on the ${service}${resource} class. In the future it will be mapped on the directory structure. The cfn-response module is used to send responses to the CloudFormation request. Implementations of a resource type are currently based on 3 base classes.
The most basic representation of a resource.
Depending on the custom resource request type, its Create/Delete/Update
methods are called with the request as a parameter.
A custom resource implementation that maps a resource type on the AWS[Service].[<create|delete|read>Resource] methods of the AWS Javascript SDK.
- Its
<create|delete|...>Params
methods are called to create the SDK method parameters, whose default implementations map the resource properties to the most common SDK parameter patterns. - Its response method is called to map the data returned from the SDK method, to CloudFormation attributes. It needs to contains at least the Id property containing the resource Id. Note that this is not implemented consistently in the SDK.
As an example, the APIGatewayDeployment class uses this base class with custom delete parameters.
Updating a resource is implemented by first trying to delete the current resource. In any case a new resource is created. Note that in case the resource cannot be deleted, cloudformation will normally delete it in its cleanup phase if the resource that was referring to it, has freed its reference.
A CustomAWSResource that updates a resource by using the update method of the associated SDK service.
- Write unit tests. This module should have been developed with TDD of course :-(