cfoo
cfoo copied to clipboard
CloudFormation master
Cfoo
Cfoo (pronounced "sifu") lets you write your CloudFormation templates in YAML, and makes it easier with some helpers.
Installation
Cfoo can be installed as a Ruby Gem
$ gem install cfoo
Usage
-
Write your CloudFormation templates using Cfoo YAML
-
Turn your Cfoo templates into normal CloudFormation templates
$ cfoo web-server.template.yml database.template.yml > web-stack.template.json
- Create your stack with CloudFormation
$ cfn-create-stack --stack-name WebStack -f web-stack.template.json
Templates
Comparison with standard CloudFormation templates
Snippet from a CloudFormation template (based on this example):
"Properties": {
"ImageId" : { "Fn::FindInMap" : [ "AWSRegion2AMI", { "Ref" : "AWS::Region" }, "AMI" ] },
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroups" : [ {"Ref" : "FrontendGroup"} ],
"KeyName" : { "Ref" : "KeyName" },
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -v\n",
"yum update -y aws-cfn-bootstrap\n",
"function error_exit\n",
"{\n",
" /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WaitHandle" }, "'\n",
" exit 1\n",
"}\n",
"/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServer ",
" --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n",
"/opt/aws/bin/cfn-signal -e 0 -r \"cfn-init complete\" '", { "Ref" : "WaitHandle" }, "'\n"
]]}}
}
Equivalent Cfoo template snippet:
Properties:
ImageId : AWSRegion2AMI[$(AWS::Region)][AMI]
InstanceType: $(InstanceType)
SecurityGroups:
- $(FrontendGroup)
KeyName: $(KeyName)
UserData: !Base64 |
#!/bin/bash -v
yum update -y aws-cfn-bootstrap
function error_exit
{
/opt/aws/bin/cfn-signal -e 1 -r "\$1" '$(WaitHandle)'
exit 1
}
/opt/aws/bin/cfn-init -s $(AWS::StackId) -r WebServer --region $(AWS::Region) || error_exit 'Failed to run cfn-init'
/opt/aws/bin/cfn-signal -e 0 -r "cfn-init completed" '$(WaitHandle)'
Projects
Using Cfoo, it is possible to split your templates up into logical components that will combined to form your CloudFormation template.
First, create a directory in your project directory called modules. For each module,
create some Cfoo templates defining the different parts of your app. Your project
structure will look like this:
my-web-app
└── modules
├── application
│ ├── app_servers.yml
│ ├── database.yml
│ └── public_load_balancer.yml
├── instances
│ └── instance_mappings.yml
└── network
├── bastion.yml
├── cfn_user.yml
├── dns.yml
├── nat.yml
├── private_subnet.yml
├── public_subnet.yml
└── vpc.yml
Use Cfoo to generate your project's CloudFormation template
$ cfoo > web-app.template.json
Shortcuts
Cfoo allows you to simplify CloudFormation intrinsic function references using its own shorthand
Reference
CloudFormation: { "Ref" : "InstanceType" }
Cfoo Shortcut: $(InstanceType)
Mapping Reference
CloudFormation: { "FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ] }
Cfoo Shortcut: $(SubnetConfig[VPC][CIDR])
Attribute Reference
CloudFormation: { "Fn::GetAtt" : [ "Ec2Instance", "PublicIp" ] }
Cfoo Shortcut: $(Ec2Instance[PublicIp])
Embedded Reference
CloudFormation: { "Fn::Join" : [ "", [{"Ref" : "HostedZone"}, "." ]]}
Cfoo Shortcut: $(HostedZone).
YAML Types
Cfoo gives you the option of using YAML custom data-types where it helps to make your templates easier to read.
Reference
CloudFormation:
{ "Ref" : "InstanceType" }
YAML Type:
!Ref InstanceType
Mapping Reference
CloudFormation:
{ "FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ] }
YAML Type:
!FindInMap [ SubnetConfig, VPC, CIDR ]
Attribute Reference
CloudFormation:
{ "Fn::GetAtt" : [ "Ec2Instance", "PublicIp" ] }
YAML Type:
!GetAtt [ Ec2Instance, PublicIp ]
Base64 String
CloudFormation:
{ "Fn::Base64" : "#!/bin/bash\necho 'Running script...'" }
YAML Type:
!Base64 "#!/bin/bash\necho 'running script...'"
Alternative YAML Type:
!Base64 |
#!/bin/bash
echo 'running script...'
Condition Function
CloudFormation:
{ "Fn::Equals": [ "sg-mysggroup", {"Ref": "ASecurityGroup"} ] },
YAML Type:
!Equals [ "sg-mysggroup", $(ASecurityGroup) ]
Goals
Primary Goals
Cfoo aims to let developers simplify CloudFormation templates by:
- allowing them to write templates in YAML
- providing an expression language to simplify CF Ref/Attr/etc expressions
- allowing templates to be split up into logical components (to simplify and share)
Secondary Goals
Cfoo also aims (subject to Primary Goals) to:
- allow inclusion existing JSON templates (so you don't have to switch all at once)
Non-goals
Cfoo does not (yet) aim to:
- provide commandline utilities for interacting directly with CloudFormation (it just generates the templates for now)
- resolve/validate references (the CloudFormation API already does this)
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Make your changes (with tests please)
- Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request