Blueprints¶
Structuring your blueprints¶
Structure your blueprints including all templates and other files (e.g. userdata) in “modules”. StackFormation will load all stack.yml files from following locations:
blueprints/*/*/*/blueprints.yml
blueprints/*/*/blueprints.yml
blueprints/*/blueprints.yml
blueprints/blueprints.yml
blueprints.yml
So it’s suggested to create a directory structure like this one:
blueprints/
stack1/
userdata/
provisioning.sh
blueprints.yml
my.template
stack2/
blueprints.yml
...
All blueprints.yml
files will be merged together.
Parameters¶
Adding parameters¶
Add parameters in your my-stack.template
:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters: {
"MyParameter1": { "Type": "String" }
},
"Resources": {
"MyResource1": { "Type": "AWS::CloudFormation::WaitConditionHandle" }
}
}
… and configure that parameter in the blueprint.yml
file:
blueprints:
- stackname: my-stack
template: my-stack.template
parameters:
MyParameter1: 'Hello World'
Parameter values¶
Parameter | Syntax | Result |
---|---|---|
Output lookup | {output:<stack>:<output>} |
Output value |
Resource lookup | {resource:<stack>:<logicalResource>} |
Physical Id of that resource |
Parameter lookup | {parameter:<stack>:<logicalResource>} |
Parameter value (note that some parameters will not be shown if they’re ‘no_echo’) |
Env var lookup | {env:<var>} |
Value of environment variable var |
Env var lookup with fallback | {env:<var>:<defaultValue>} |
Value of environment variable var falling back to defaultValue if env var is not set |
Stack/global variable lookup | {var:<var>} |
Value variable var |
Current timestamp | {tstamp} |
e.g. 1453151115 |
MD5 sum | {md5:<filename>} |
e.g. fdd747e9989440289dcfb476c75b4268 |
Clean | {clean:2.1.7} |
217 removes all characters that arent allowed in stack names |
Switch profile | [profile:<profileName>:...] |
Will switch to a different profile and evaluate the second parameter there. This is useful in cross account setups |
Output and resource lookup allow you to “connect” stacks to each other by wiring the output or resources created in one stack to the input parameters needed in another stack that sits on top of the first one without manually managing the input values.
Example
blueprints:
- stackname: stack1-db
template: templates/stack1.template
[...]
- stackname: stack2-app
template: templates/stack2.template
parameters:
build: 's3://{output:stack1:bucketName}/{env:BUILD}/build.tar.gz'
db: '{output:stack1-db:DatabaseRds}'
Variables (global/local, nested into other placeholders)
vars:
KeyPair: 'mykeypair'
blueprints:
- stackname: mystack
vars:
ParentStack: 'MyParentStack'
parameters:
KeyPair: '{var:mykeypair}'
Database: '{output:{var:ParentStack}:DatabaseRds}'
[...]
Switch Profile Example (in this example an AMI is baked in a different account and shared with this account)
blueprints:
- stackname: mystack
parameters:
BaseAmi: '[profile:myDevAccountProfile:{output:bakestack:BaseAmi}]'
Conditional parameter values¶
You might end up deploying the same stacks to multiple environments or accounts. Instead of duplicating the blueprints (or using YAML reference) you’ll probably want to parameterize your blueprints like this
blueprints:
- stackname: 'app-{env:Environment}-build'
template: 'build.template'
parameters:
KeyPair: 'MyKeyPair'
[...]
… and then before deploying (locally or from your CI server) you’d set the env var first and then deploy:
$ export Environment=prod
$ vendor/bin/stackformation.php blueprint:deploy 'app-{env:Environment}-build'
But in many cases those stacks do have some minor differences in some of the parameters (e.g. different VPCs or KeyNames,…) You could solve it like this with nested placeholders:
blueprints:
- stackname: 'app-{env:Environment}-build'
template: 'build.template'
vars:
prod-KeyName: MyProdKey
stage-KeyName: MyStageKey
parameters:
KeyPair: '{var:{env:Environment}-KeyName}'
While this is perfectly possible this gets very confusing soon. Plus you’ll have to mention every variation of the variable explicitely.
Instead you can use a conditional value:
blueprints:
- stackname: 'app-{env:Environment}-build'
template: 'build.template'
parameters:
KeyPair:
'{env:Environment}==prod': MyProdKey
'{env:Environment}==stage': MyStageKey
'{env:Environment}~=/^dev[0-9]+$/': MyDevKey
'default': MyDevKey
StackFormation will evaluate all keys from top to bottom and the first key that evaluates to true will be returned. Allowed conditions: - A==B
- A!=B
- A~=/^regex$/
- ‘default’ (will always evaluate to true. Make sure you put this at the very end since everything after this will be ignored). Placeholders will be resolved before the conditions are evaluated.
Wildcards¶
When referencing a stack in {output:<stack>:<output>}
, {resource:<stack>:<logicalResource>}
, or {parameter:<stack>:<logicalResource>}
you can use a wildcard to specify a stack. In this case StackFormation looks up all live stacks and finds a stack matching the pattern. If there’s no stack or more than a single stack matching the pattern StackFormation will throw an exception. This feature is helpful when you know there’s always only a single stack of one type that has a placeholder in it’s stackname:
Example: Stackname: deployment-{env:BUILD_NUMBER}
In blueprints.yml:
blueprints:
- stackname: mystack
parameters:
Elb: '{output:deployment-*:Elb}'
Effective stackname¶
You can include environment variable in your stackname (which is very handy for automation via Jenkins). In this case your effective stackname (e.g. build-5
) will be different from the configured stackname (e.g. build-{env:BUILD_NUMBER}
)
Example
blueprints:
- stackname: 'build-{env:BUILD_NUMBER}'
template: templates/deploy_build.template
Reverse blueprint match¶
Let’s say you have a blueprint ecom-{env:ACCOUNT}-{env:ENVIRONMENT}-static-stack
and you want to deploy it with ACCOUNT=t and ENVIRONMENT=dpl. You would do this by setting the env vars ACCOUNT and ENVIRONMENT and then run the deploy command:
$ export ACCOUNT=t
$ export ENVIRONMENT=dpl
$ vendor/bin/stackformation.php deploy 'ecom-{env:ACCOUNT}-{env:ENVIRONMENT}-static-stack'
But instead you can also simply run the deploy command with the resulting stack name ecom-t-tst-static-stack
StackFormation will then attempt to find a matching tag, determine which environments need to be set and run the original blueprint for you:
$ vendor/bin/stackformation.php deploy 'ecom-t-tst-static-stack'
Blueprint reverse match found: ecom-{env:ACCOUNT}-{env:ENVIRONMENT}-static-stack
With ENV vars: ACCOUNT=t; ENVIRONMENT=tst
Use this blueprint and set env vars? [y/N] y
Setting env var: ACCOUNT=t
Setting env var: ENVIRONMENT=tst
...
Forcing ENV vars¶
This will automatically set environment variables in the context of that stack.
blueprints:
- stackname: 'demo'
env:
ACCOUNT: t
ENVIRONMENT: prod