Skip to content

comoyo/condensation

Repository files navigation

travis-ci.org

Condensation

A Clojure library for making AWS CloudFormation easier to use.

Usage

Leiningen coordinate:

[com.comoyo/condensation "0.2.2"]

Template definition

To define templates, require [com.comoyo.condensation.template :as cft].

Then, define resources:

(cft/defresource vpc
  {"Type" "AWS::EC2::VPC"
   "Properties" {"CidrBlock" "10.10.0.0/16"
                 "EnableDnsSupport" "true"
                 "EnableDnsHostnames" "true"}})

(cft/defresource route-table
  {"Type" "AWS::EC2::RouteTable"
   "Properties" {"VpcId" (cft/ref vpc)}})

We can also create resources that take parameters:

(cft/defresource security-group
  [vpc]
  {"Type" "AWS::EC2::SecurityGroup"
   "Properties" {"VpcId" vpc
                 "SecurityGroupIngress" [{"IpProtocol" "tcp"
                                          "FromPort" "22"
                                          "ToPort" "22"
                                          "CidrIp" "0.0.0.0/0"}]}})

Logical names are automatically defined based on resource names.

We can now use the ref function to refer to resources, like with

(cft/ref vpc) => {"Ref" "Vpc"}

above.

The get-att function can be used to refer to attributes:

(cft/get-att vpc "DefaultSecurityGroup")
=> {"Fn::GetAtt" ["Vpc" "DefaultSecurityGroup"]}

We can now use the resources macro to access the Resources map:

(cft/resources vpc
               route-table
               (security-group "vpc-id"))
=> {"RouteTable" {"Properties" {"VpcId" {"Ref" "Vpc"}}
                  "Type" "AWS::EC2::RouteTable"}
    "Vpc" {"Properties" {"CidrBlock" "10.10.0.0/16"
                         "EnableDnsHostnames" "true"
                         "EnableDnsSupport" "true"}
           "Type" "AWS::EC2::VPC"}
    "SecurityGroup" {"Type" "AWS::EC2::SecurityGroup"
                     "Properties" {"VpcId" "vpc-id"
                                   "SecurityGroupIngress" [{"IpProtocol" "tcp"
                                                            "FromPort" "22"
                                                            "ToPort" "22"
                                                            "CidrIp" "0.0.0.0/0"}]}}}

We can also define outputs using the defoutputs macro:

(cft/defoutput vpc-id
  "The VPC ID"
  (cft/ref vpc))

(cft/defoutput security-group-id
  "The security group ID"
  (cft/ref security-group))

The outputs function then creates the outputs map:

(cft/outputs vpc-id
             security-group-id)
=> {"SecurityGroupId" {"Description" "The security group ID"
                       "Value" {"Ref" "SecurityGroup"}}
    "VpcId" {"Description" "The VPC ID"
             "Value" {"Ref" "Vpc"}}}

Finally, the templates function can be used to create the template map:

(cft/template :description "A template"
              :resources (cft/resources vpc
                                        route-table
                                        (security-group "vpc-id"))
              :outputs (cft/outputs vpc-id
                                    security-group-id))
=> {"AWSTemplateFormatVersion" "2010-09-09"
    "Description" "A template"
    "Outputs" {"SecurityGroupId" {"Description" "The security group ID"
                                  "Value" {"Ref" "SecurityGroup"}}
               "VpcId" {"Description" "The VPC ID"
                        "Value" {"Ref" "Vpc"}}}
    "Resources" {"RouteTable" {"Properties" {"VpcId" {"Ref" "Vpc"}}
                               "Type" "AWS::EC2::RouteTable"}
                 "Vpc" {"Properties" {"CidrBlock" "10.10.0.0/16"
                                      "EnableDnsHostnames" "true"
                                      "EnableDnsSupport" "true"}
                        "Type" "AWS::EC2::VPC"}
                 "SecurityGroup" {"Type" "AWS::EC2::SecurityGroup"
                                  "Properties" {"VpcId" "vpc-id"
                                                "SecurityGroupIngress" [{"IpProtocol" "tcp"
                                                                         "FromPort" "22"
                                                                         "ToPort" "22"
                                                                         "CidrIp" "0.0.0.0/0"}]}}}}

Dealing with stacks

To create a stack, use the create-or-update-stack function:

(create-or-update-stack :stack-name "dummy" :cloudformation-template-map template)

where template is created by template/template as described above.

If the stack already exists it is updated.

Use :wait? false to return without waiting for the create/update operation to be done.

To delete a stack, use delete-stack:

(delete-stack :stack-name "dummy")

You can also use the get-outputs function to get easy access to stack outputs:

(:vpc-id
 (get-outputs "dummy"))

About

A Clojure library for making AWS CloudFormation easier to use

Resources

License

Stars

Watchers

Forks

Packages