Categorygithub.com/molecule-man/stack-assembly
modulepackage
0.5.2
Repository: https://github.com/molecule-man/stack-assembly.git
Documentation: pkg.go.dev

# README

Stack-Assembly ##############

Stack-Assembly is a command line tool to configure and deploy AWS Cloudformation stacks in a safe way. The safety aspect is enabled by utilizing Cloudformation Changesets <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-changesets.html>_ and letting the user to view and confirm changes to be deployed.

.. class:: no-web

|build|

.. class:: no-web

.. image:: demo.gif
    :alt: stack-assembly in action
    :width: 100%
    :align: center

.. contents::

.. section-numbering::

Main features

  • No dependencies (NodeJS, Python interpreter, aws cli etc.) - Stack-Assembly is a single statically linked binary
  • Configuration powered by Golang Templates <https://golang.org/pkg/text/template/>_
  • Interactive interface which enables user to view, diff and confirm changes to be deployed
  • Colorized terminal output
  • Documentation
  • Test coverage

Installation

The pre-compiled binaries can be downloaded from the release page <https://github.com/molecule-man/stack-assembly/releases>_. The following OSs are supported:

  • Windows amd64/386
  • Linux amd64/386
  • Darwin amd64/386

Build it yourself

This requires go 1.11 to be installed

.. code-block:: bash

$ git clone [email protected]:molecule-man/stack-assembly.git
$ cd stack-assembly
$ make build

This will build binary inside bin folder.

Quick start example

For demonstration purposes it is assumed that there exists file ./path/to/cf-tpls/sqs.yaml containing cloudformation template you want to deploy. For example:

.. code-block:: yaml

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  QueueName:
    Type: String
  VisibilityTimeout:
    Type: Number
Resources:
  MyQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Ref QueueName
      VisibilityTimeout: !Ref VisibilityTimeout

Then create Stack-Assembly configuration file in the root folder of your project stack-assembly.yaml:

.. code-block:: yaml

# In this simple example two stacks are configured. Both stacks use the same
# cloudformation template
stacks:
  # tpl1 is the id of the stack. This id has meaning only inside this
  # config. You can use this id to deploy a particular stack instead of
  # deploying all stacks as it's done by default. You can do it by running
  # `stas sync tpl1`
  tpl1:
    name: demo-tpl1
    path: path/to/cf-tpls/sqs.yaml
    # parameters is a key-value map where values are strings. Numeric
    # parameters have to be defined as strings as you can see in the example
    # of VisibilityTimeout parameter
    parameters:
      QueueName: demo1
      VisibilityTimeout: "10"
  tpl2:
    name: demo-tpl2
    path: path/to/cf-tpls/sqs.yaml
    parameters:
      QueueName: demo2
      VisibilityTimeout: "20"

Assuming you have configured AWS credentials_ then you can deploy your stacks by running:

.. code-block:: bash

$ stas sync

By default Stack-Assembly is executed in interactive mode. During the deployment it shows the changes that are about to be deployed and asks user's confirmation to proceed with deployment.

Usage

.. code-block::

$ stas help sync
Creates or updates stacks specified in the config file(s).

By default sync command deploys all the stacks described in the config file(s).
To deploy a particular stack, ID argument has to be provided. ID is an
identifier of a stack within the config file. For example, ID is tpl1 in the
following yaml config:

    stacks:
      tpl1: # <--- this is ID
        name: mystack
        path: path/to/tpl.json

The config can be nested:
    stacks:
      parent_tpl:
        name: my-parent-stack
        path: path/to/tpl.json
        stacks:
          child_tpl: # <--- this is ID of the stack we want to deploy
            name: my-child-stack
            path: path/to/tpl.json

In this case specifying ID of only wanted stack is not enough all the parent IDs
have to be specified as well:

  stas sync parent_tpl child_tpl

Usage:
  stas sync [<ID> [<ID> ...]] [flags]

Aliases:
  sync, deploy

Flags:
  -h, --help   help for sync

Global Flags:
  -c, --configs strings            Alternative config file(s). Default: stack-assembly.yaml
  -n, --no-interaction             Do not ask any interactive questions
      --nocolor                    Disables color output
  -p, --profile string             AWS named profile (default "default")
  -r, --region string              AWS region
  -v, --var -v myParam=someValue   Additional variables to use as parameters in config.
                                   Example: -v myParam=someValue

Specifying multiple config files

You can supply multiple -c configuration files. When you supply multiple files, Stack-Assembly combines them into a single configuration. Subsequent files override and add to their predecessors.

For example, consider this command line:

.. code-block:: bash

$ stas sync -c stack-assembly.yml -c stack-assembly.staging.yml

The stack-assembly.yml file might look like this:

.. code-block:: yaml

stacks:
  ec2machine:
    name: ec2machine-dev
    path: cf-tpls/ec2machine.yml
    parameters:
      Size: t2.micro
      ImageID: ami-rt34fu

And the stack-assembly.staging.yml file might look like this:

.. code-block:: yaml

stacks:
  ec2machine:
    name: ec2machine-staging
    parameters:
      Size: t2.medium
    tags:
      ENV: staging

Stack-Assembly will apply configuration from stack-assembly.staging.yml on top of stack-assembly.yml and the result configuration will look like this:

.. code-block:: yaml

stacks:
  ec2machine:
    name: ec2machine-staging
    path: cf-tpls/ec2machine.yml
    parameters:
      Size: t2.medium
      ImageID: ami-rt34fu
    tags:
      ENV: staging

Configuration

Stack-Assembly uses simple yet powerful config file that can be in one of these three formats: yaml, toml, json. The next sections will use yaml as a format.

Config file location

Stack-Assembly will firstly try to use file stack-assembly.yaml in your project directory. If it's not found then Stack-Assembly will try to use stack-assembly.yml, stack-assembly.toml, stack-assembly.json.

Config file structure

Example of Stack-Assembly config file:

.. code-block:: yaml

settings:
  aws:
    # aws named profile. See the following link for more information
    # https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
    # This configuration option can be overriden by env variable AWS_PROFILE.
    # Or by command line parameter `--profile`
    profile: default

    # aws region. This configuration option can be overriden by env variable
    # AWS_REGION. Or by command line parameter `--region`
    region: us-west-2

# cloudformation parameters that are global for all stacks
parameters:
  Env: dev
  ServiceName: myservice

stacks:
  db:
    # cloudformation stack's name. It's possible to use golang templating
    # inside `name`
    name: "{{ .Params.DbName }}"

    # path to cloudformation template.
    # Either `path` or `body` has to be provided
    path: cf-tpls/rds.yml

    # cloudformation stack's parameters
    parameters:
      Type: db.t2.medium
      # it's possible to use golang templating inside parameter value
      DbName: "{{ .Params.ServiceName }}-{{ .Params.Env }}"

    # cloudformation stack's tags. It's also possible to use golang
    # templating inside tag value
    tags:
      ENV: "{{ .Params.Env }}"

    # it's possible to create a stack policy that will disallow to `update`
    # or `delete` certain stack resources. In this case the policy will be
    # applied to stack resource with `LogicalResourceId` equal to
    # `DbInstance`. See the following link for more information:
    # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html
    blocked:
      - DbInstance

  ec2app:
    name: "{{ .Params.ServiceName }}-{{ .Params.Env }}-ec2app"
    parameters:
      Type: t2.micro

    # `path` is not the only way to specify cloudformation template. It's
    # possible to specify the whole template body inside the config. It
    # might be especially useful when template generating tool (as e.g.
    # troposphere) is used.
    # In this example, given that `Env` is equal to "dev", body will have
    # contents of the output produced by executing
    # `python terraform_tpls/ec2.py dev`
    body: |
      {{ .Params.Env | Exec "python" "terraform_tpls/ec2.py" }}

    # dependsOn instruction tells Stack-Assembly that this stack should be
    # deployed after `db` stack is deployed
    dependsOn:
      - db

    # In some cases, you must explicity acknowledge that your stack template
    # contains certain capabilities in order for AWS CloudFormation to
    # create the stack. For more information, see
    # https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateStack.html
    capabilities:
      - CAPABILITY_IAM

    # Rollback triggers enable you to have AWS CloudFormation monitor the
    # state of your application during stack creation and updating, and to
    # roll back that operation if the application breaches the threshold of
    # any of the alarms you've specified.
    # For more information, see
    # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-rollback-triggers.html
    rollbackConfiguration:
      monitoringTimeInMinutes: 1
      rollbackTriggers:
        - arn: arn:aws:cloudwatch:{{ .AWS.Region }}:{{ .AWS.AccountID }}:alarm:{{ .Params.ServiceName }}-errors
          type: AWS::CloudWatch::Alarm

Config nesting

Every stack in stack-assembly config can contain nested stacks. This enables possibility to deploy subgroup (subtree) of stacks.

.. code-block:: yaml

stacks:
  staging:

    # settings, as well as parameters, are propagated down the tree.
    # All the child stacks of `staging` inherit settings and parameters
    # defined at `staging` level
    settings:
      aws:
        region: eu-west-1
    parameters:
      Env: staging

    stacks:
      db:
        name: "db-staging"
        path: cf-tpls/rds.yml
      app:
        name: "app-staging"
        path: cf-tpls/app.yml

  production:

    settings:
      aws:
        region: us-east-1
    parameters:
      Env: production

    stacks:
      db:
        name: "db-production"
        path: cf-tpls/rds.yml
      app:
        name: "app-production"
        path: cf-tpls/app.yml

Having this config one can deploy all the stacks under production by running:

.. code-block:: bash

stas sync production

Or, if one needs to deploy db stack under staging, one can use the following command:

.. code-block:: bash

stas sync staging db

Reuse

When writing complex config, it's almost inevitable to have duplication in the config. This section describes how stack-assembly helps to avoid copying-and-pasting.

Let's say we have a stack we want to deploy multiple times in different environments. Each environment is different from each other only by handful of parameters. Then we put the reused stack under the definitions in the root of the config. And then we can (re)use this stack in the config by referencing this stack with $basedOn field in the config:

.. code-block:: yaml

stacks:
  staging:
    "$basedOn": reused_stack
    parameters:
      Env: staging

  production:
    "$basedOn": reused_stack
    parameters:
      Env: production

definitions:
  reused_stack:
    name: "reused-stack-{{ .Params.Env }}"
    path: cf-tpls/stack.yml

AWS credentials

If you've ever used awscli or similar tool you probably already know about aws credentials file. Stack-Assembly also uses this file to read credentials. The default location of this file is $HOME/.aws/credentials. You can find more information in AWS documentation <https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html>_.

For the sake of example let's consider that you have configured aws credentials and now have this files in your home folder:

~/.aws/credentials

::

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

~/.aws/config

::

[default]
region=us-west-2

Now you have couple of options:

  1. Specify profile and region in the config file. See Config file structure_:

.. code-block:: yaml

settings:
  aws:
    profile: default
    region: eu-west-1

2. Use environmental variables:

.. code-block:: bash

$ export AWS_PROFILE=default
$ export AWS_REGION=eu-west-1
$ stas sync

3. Use command line flags:

.. code-block:: bash

$ stas sync --profile default --region eu-west-1

Other commands

Apart from sync command there are also couple of handy other commands you can use:

.. code-block:: bash

$ stas help
Usage:
  stas [command]

Available Commands:
  delete      Deletes deployed stacks
  diff        Show diff of the stacks to be deployed
  dump-config Dump loaded config into stdout
  help        Help about any command
  info        Show info about the stack
  sync        Synchronize (deploy) stacks

Drop-in replacement of cloudformation commands of aws-cli

Stack-assembly provides a possibility to enhance aws-cli <https://github.com/aws/aws-cli>_ by replacing create-stack <https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack.html>, update-stack <https://docs.aws.amazon.com/cli/latest/reference/cloudformation/update-stack.html> and deploy <https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy.html>_ commands with improved versions of those commands. More info can be found here <https://github.com/molecule-man/stack-assembly/blob/master/docs/aws-drop-in.md>_

TODO

  • Enable user to unblock the blocked resource (interactively).
  • Github support.
  • Add possibility to introspect aws resources??

.. |build| image:: https://circleci.com/gh/molecule-man/stack-assembly.svg?style=svg :target: https://circleci.com/gh/molecule-man/stack-assembly :alt: Build status of the master branch

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
Package main provides cmd stas application.
No description provided by the author
Package depgraph provides functionality to resolve dependencies.
No description provided by the author

# Functions

No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author