Skip to content
cultureampPublic

About

Wrangle parameters for AWS CloudFormation

Resources

Stars

1 star

Watchers

29 watching

Forks

Latest commit

 

History

418 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cfparams

Wrangle CloudFormation parameters.

Reads expected parameter keys from a CloudFormation template, accepts values from command line or YAML file, emits JSON suitable for aws cloudformation *-stack --parameters="..." commands. Supports the use of default and previous values.

Installation Instructions

  • If you use Homebrew, you can simply run: brew install cultureamp/tap/cfparams (only in the Culture Amp organization at the moment, sorry).
  • Alternatively, if you want the latest version, download the executable directly from the release page
  • Rename and move the cfparams executable to your path, e.g: mv cfparams /usr/local/bin (or move to your favourite spot and symlink).
  • To check whether your installation is successful, run the command cfparams and the output would be similar to:
    $ cfparams
    CloudFormation template or tags file required
        e.g: --template=cloudformation.yaml
        e.g: --tags=tags-foo.yaml
  • If it still doesn't work you may need to hash -r to clear the path cache or restart the shell

Example use-cases

CloudFormation template excerpt describing an ECS service to be provisioned onto an existing ECS cluster.

# cfn.yaml excerpt
Parameters:
  Greeting:
    Type: String
    Description: greeting message to send
    Default: Hello
  Recipient:
    Description: name of the greeting recipient
    Type: String
  ImageRepo:
    Type: String
    Description: repository of Docker image to run
    Default: "123.dkr.ecr.us-east-1.amazonaws.com/greeting"
  ImageTag:
    Type: String
    Description: tag of Docker image to run
    Default: latest
  Cluster:
    Description: ECS cluster ID to run service on
    Type: String

Creating ECS service CloudFormation stack

Launching the CloudFormation stack for the first time. Accept some defaults from the template, specify all other parameters.

params="$(
  cfparams --template=cfn.yaml --accept-defaults --no-previous \
    Recipient=world ImageTag=v1 Cluster=nanoservices
)"
  • --template loads supported Parameters from a CloudFormation template.
  • --accept-defaults omits keys that have a default in the CloudFormation template.
  • --no-previous means fail if a key has no default in the template and isn't specified on the command line. Without this option, those keys will be auto-filled as "UsePreviousValue": true.

Resulting JSON:

[
  {"ParameterKey": "Recipient", "ParameterValue": "world"},
  {"ParameterKey": "ImageTag", "ParameterValue": "v1"},
  {"ParameterKey": "Cluster", "ParameterValue": "nanoservices"}
]
aws cloudformation create-stack \
  --stack-name=greeting \
  --template-body=file://cfn.yaml \
  --parameters="$params"

Deploying a new version of the app

Deploying a new version of the app, e.g. from CI. Only ImageTag should change, all other parameters use previous value.

params="$(cfparams --template=cfn.yaml ImageTag=v2)"

Resulting JSON:

[
  {"ParameterKey": "Greeting", "UsePreviousValue": true},
  {"ParameterKey": "Recipient", "UsePreviousValue": true},
  {"ParameterKey": "ImageRepo", "UsePreviousValue": true},
  {"ParameterKey": "ImageTag", "ParameterValue": "v2"},
  {"ParameterKey": "Cluster", "UsePreviousValue": true}
]

Update stack:

aws cloudformation update-stack \
  --stack-name=greeting \
  --use-previous-template \
  --parameters="$params"

Updating the CloudFormation stack

Changing the stack, for example introducing a FooHost parameter.

 # cfn.yaml excerpt
 Parameters:
+  FooHost:
+    Type: String
+    Description: API key to access Foo service
   Greeting:
params="$(cfparams --template=cfn-foohost.yaml FooHost=foo.example.com)"

Resulting JSON:

[
  {"ParameterKey": "FooHost", "ParameterValue": "foo.example.com"},
  {"ParameterKey": "Greeting", "UsePreviousValue": true},
  {"ParameterKey": "Recipient", "UsePreviousValue": true},
  {"ParameterKey": "ImageRepo", "UsePreviousValue": true},
  {"ParameterKey": "ImageTag", "UsePreviousValue": true},
  {"ParameterKey": "Cluster", "UsePreviousValue": true}
]
name="greeting-update-$(date +%Y%m%d-%H%M%S)"

aws cloudformation create-change-set \
  --stack-name=greeting \
  --change-set-name="$name" \
  --use-previous-template \
  --parameters="$(cfparams --template=cfn.yaml FooHost=foo.example.com)"

# review Change Set here

aws cloudformation execute-change-set \
  --stack-name=greeting \
  --change-set-name="$name"

Introducing version-controlled parameters files

Now we introduce some version-controlled files to the subset of parameters that make sense to exist in the codebase. ImageTag is not included in this file.

# parameters-staging.yaml
FooHost: foo.local
Greeting: Howdy
Recipient: team
Cluster: staging
# parameters-production.yaml
FooHost: foo.example.com
Greeting: Hello
Recipient: world
Cluster: production
params="$(
  cfparams --template=cfn-foohost.yaml --parameters=parameters-staging.yaml \
    ImageTag=v3 Greeting=Bonjour
)

Resulting JSON:

[
  {"ParameterKey": "FooHost", "ParameterValue": "foo.local"},
  {"ParameterKey": "Greeting", "ParameterValue": "Howdy"},
  {"ParameterKey": "Recipient", "ParameterValue": "team"},
  {"ParameterKey": "ImageRepo", "UsePreviousValue": true},
  {"ParameterKey": "ImageTag", "ParameterValue": "v3"},
  {"ParameterKey": "Cluster", "ParameterValue": "staging"}
]

Bonus feature: Stack Tags

CloudFormation stacks can be tagged, and those tags flow into all taggable resources the stack creates. As with --parameters, the aws cloudformation commands expect these in an awkward format. cfparams --tags file.yaml helps.

aws cloudformation create-stack \
  ... \
  --tags "$(cfparams --tags=tags-production.yaml)" \
  ...
# tags-production.yaml
Name: Widgets as a Service
asset: widget-api
workload: production
cfparams --tags=tags-production.yaml
[
  {
    "Key": "Name",
    "Value": "Widgets as a Service"
  },
  {
    "Key": "asset",
    "Value": "widget-api"
  },
  {
    "Key": "workload",
    "Value": "production"
  }
]

Tags can also be overridden and added to on the command line, just like parameters can:

#tags-test.yaml
asset: buildkite
workload: delivery
buildkite-group: build-test
> cfparams --tags=tags-test.yaml buildkite-group=build-pylons message=extra-tag
[
  {
    "Key": "buildkite-group",
    "Value": "build-pylons"
  },
  {
    "Key": "message",
    "Value": "extra-tag"
  },
  {
    "Key": "asset",
    "Value": "buildkite"
  },
  {
    "Key": "workload",
    "Value": "delivery"
  }
]

About

Wrangle parameters for AWS CloudFormation

Resources

Stars

1 star

Watchers

29 watching

Forks

Releases

Packages

Used by

Contributors

Languages