Writing templates and overlays
This document will use the example CloudFormation YAML template provided here, but you can use your own if you prefer. In this guide we will create one test overlay and one prod overlay.
Step 1: Folder structure
Start your project by defining a base template. First create a folder in your project for templates and overlays:
cd [your project]
mkdir crustomize
mkdir crustomize/base
mkdir -p crustomize/overlays/test
Step 2: Overlays
Place the CloudFormation template in crustomize/base/template-name.yml
.
The name doesn’t matter, all YAML files in base/
will be read and
merged into one master base template.
Create a crustomize.yml
file in the crustomize/overlays/test
folder
with this content:
base: ../../base
Verify it works by running crustomize apply crustomize/overlays/test
. The
command should output the template itself.
Next, add an overlay in crustomize/overlays/test/ECSTaskExecutionRole.yml
Here, we will just add a Description
property:
Resources:
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
Description: This is a test execution role
Note that the Resources:
property is crucial for crustomize to merge
the overlay.
Add the overlay to crustomize.yml
like this:
base: ../../
overlays:
- ECSTaskExecutionRole.yml
Verify by running crustomize apply crustomize/overlays/test
. The outputted
template should contain the added Description
property.
Create a prod overlay by creating a crustomize/overlays/prod
folder.
Copy the test/crustomize.yml
file to that folder along with the
ECSTaskExecutionRole.yml
overlay.
Modify the crustomize/overlays/prod/ECSTaskExecutionRole.yml
like this:
Resources:
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
Description: This is a prod execution role
Verify by running crustomize apply crustomize/overlays/prod
. There should
now be a different description.
Step 3: JSON Patch
Sometimes overlays are not enough, particularly when you need to target
a specific item in an array. In these cases it may be necessary to use
a JSON patch. JSON patch can target specific elements and perform the
operations you define. Here, we will target the ClusterSettings
list
and set the name using JSON patch.
Modify test/crustomize.yml
like this:
base: ../../
overlays:
- ECSTaskExecutionRole.yml
patches:
- op: replace
path: "/Resources/ECSCluster/Properties/ClusterSettings/0/Name"
value: containerInsightsTest
Run crustomize apply crustomize/overlays/test
to verify the cluster
name has been changed to containerInsightsTest
.
Repeat the same for the prod
overlay and verify your changes.
For more information, consult Javascript Object Notation
Patch
IETF specifications.
Step 4: Template rendering
You can use either EJS or Handlebars as a template rendering engine. Handlebars offers a more strict method of rendering by limiting what sort of in-process commands can be used. EJS is more flexible in that regard. In this example we’ll use Handlebars.
Modify the ECSCluster
section in the base template so it looks like this:
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
{{#if values.Description}}
Description: {{values.Description}}
{{/if}}
ClusterSettings:
- Name: containerInsightsTest
Value: enabled
Add a Description value in test/crustomize.yml
like this:
base: ../../
overlays:
- ECSTaskExecutionRole.yml
patches:
- op: replace
path: "/Resources/ECSCluster/Properties/ClusterSettings/0/Name"
value: containerInsightsTest
values:
Description: Test cluster
Verify and repeat the process for prod/crustomize.yml
but with a different
Description.
You can also add templating instructions in overlays. Modify
test/crustomize.yml
and add a Stage
value property:
base: ../../
overlays:
- ECSTaskExecutionRole.yml
patches:
- op: replace
path: "/Resources/ECSCluster/Properties/ClusterSettings/0/Name"
value: containerInsightsTest
values:
Description: Test cluster
Stage: test
Modify the test/ECSTaskExecutionRole.yml
like this:
Resources:
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
Description: This is a {{values.Stage}} execution role
When you run crustomize apply crustomize/overlays/test
the ``
directive will be replaced with the value defined in the relevant
crustomize.yml
file. Now, repeat for overlays/prod/
.
In addition to values.xxx
you can use the helpers documented in
doc/helpers.md as well as environment variables.
Environment variables are accessed using env.NAME_OF_VARIABLE
.
You can also defined common variables in an env.yml
file and reference
it using the -e
flag. These will also be accessible using the env.NAME
method.
If you have used or created Helm charts, you should be familiar with many
of the helper functions. If you find you need a specific helper, you can
create your own helper functions and expose them to crustomize
using the
CRUSTOMIZE_HELPERS
environment variable.
A custom helpers is just a Javascript function that returns a helper function, like this:
// Params:
// wd: String: This is the folder of the current overlay/crustomize.yml
// i.e. /path/to/overlay folder
// profile: AWS_PROFILE, default is 'default'
// bin: function that runs a shell process
export function cat({wd, profile, run}) {
return function (filename) {
const cat = bin.bind('cat')
return cat([filename])
}
}
One possible use case is to bind bin
to the aws
CLI in order to perfom
lookup operations against resources in AWS.