Skip to content

Latest commit

 

History

History
251 lines (179 loc) · 6.3 KB

README.md

File metadata and controls

251 lines (179 loc) · 6.3 KB

Cfoo

Build Status Coverage Status Code Climate

Gem Version Dependency Status

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

  1. Write your CloudFormation templates using Cfoo YAML

  2. Turn your Cfoo templates into normal CloudFormation templates

$ cfoo web-server.template.yml database.template.yml > web-stack.template.json
  1. 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

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Make your changes (with tests please)
  4. Commit your changes (git commit -am 'Add some feature')
  5. Push to the branch (git push origin my-new-feature)
  6. Create new Pull Request