/cloudformation

Example AWS CloudFormation

Primary LanguageEmacs Lisp

This is an experiment in using literate-programming to specify cloud infrastructure. Literate-programming allows us to create CloudFormation templates interleaved with explanations and diagrams. See these documents rendered in HTML here.

This README.org file contains functions for deploying, updating, and tearing down infrastructure. Within Emacs these functions are fully interactive.

Variables

Env VarValue
AWS_PROFILEdev
AWS_DEFAULT_REGIONus-east-2
TEMPLATE_PATH_out/s3/bucket.yaml

OrgFilePath

OrgFilePath is the relative path to the .org file that corresponds to the $TEMPLATE_PATH yaml file.

(let ((template-path (getenv "TEMPLATE_PATH")))
  (f-join "org"
          (f-swap-ext (f-relative template-path "_out" ) "org")))

Params

Params is the contents of the Params table in the OrgFilePath as a list of pairs. Currently this table is required.

(with-temp-buffer
  (insert-file-contents OrgFilePath)
  (org-mode)
  (car (read-from-string (org-sbe "Params"))))

TemplateName

$TemplateName is the $TEMPLATE_PATH using dashes and without a file extension.

(let* ((template-path (getenv "TEMPLATE_PATH"))
       (parent-dir (f-base (f-parent template-path)))
       (base-name-dashes (s-replace "_" "-" (f-base template-path))))
  (concat parent-dir "-" base-name-dashes))

StackName

$StackName is $TemplateName or $DeploymentName-$TemplateName, depending on whether the $Params specify a $DeploymentName.

(let ((deployment-name (assoc "DeploymentName" Params)))
  (if deployment-name
      (concat (nth 1 deployment-name) "-" TemplateName)
    TemplateName))

CreateParamString

CreateParamString is a string of parameters suitable for use with the aws cloudformation create-stack command.

(let ((format-param (lambda (pair)
                      (s-format "ParameterKey=$0,ParameterValue=$1" 'elt pair))))
  (s-join " " (mapcar format-param Params)))

DeployParamString

DeployParamString is a string of paramaters suitable for use with the aws cloudformation deploy command.

(let ((format-param (lambda (pair) (s-format "$0=$1" 'elt pair))))
  (s-join " " (mapcar format-param Params)))

Create Stack

Package

Only required if the template requires packaging. For a list of properties that can be filled in by packaging, see the package command.

TODO!

aws cloudformation package \
    --template-file file://$TEMPLATE_PATH \
    --output-template-file output.yaml \
    --s3-bucket $BucketName

Deploy

Create or update a stack.

aws cloudformation deploy \
    --stack-name $StackName \
    --template $TEMPLATE_PATH \
    --capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_IAM CAPABILITY_NAMED_IAM \
    --parameter-overrides $ParamString

Create

aws cloudformation create-stack \
    --stack-name $StackName \
    --template-body file://$TEMPLATE_PATH \
    --capabilities \
    CAPABILITY_AUTO_EXPAND CAPABILITY_IAM CAPABILITY_NAMED_IAM \
    --parameters $ParamString

Update Stack

In Place

aws cloudformation update-stack \
    --stack-name $StackName \
    --template-body file://$TEMPLATE_PATH \
    --capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_IAM CAPABILITY_NAMED_IAM \
    --parameters $ParamString

Using a ChangeSet

Create a change set:

aws cloudformation create-change-set \
    --stack-name $StackName \
    --template-body file://$TEMPLATE_PATH \
    --change-set-name my-changes

Describe a change set:

aws cloudformation describe-change-set \
    --change-set-name my-changes \
    --stack-name $StackName

Apply a change set:

aws cloudformation execute-change-set \
    --change-set-name my-changes \
    --stack-name $StackName

Delete a change set. Does the change set get deleted automatically when it is applied?

aws cloudformation delete-change-set \
    --change-set-name my-changes \
    --stack-name $StackName

Delete Stack

aws cloudformation delete-stack \
    --stack-name $StackName

Get Stack Logs

aws cloudformation describe-stack-events \
    --stack-name $StackName

  • [ ] Update sitemap to not include setup.html
  • [ ] When deploying a stack with prerequisites, automatically deploy the prerequisites
    • [ ] Maybe, prereqs are a table? Make a func that checks if there is a stack with that name, and if not, create it.
  • [ ] Use nested stacks? As is the best practice.

Local Vars