assembly

package module
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2023 License: MIT Imports: 8 Imported by: 0

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 git@github.com: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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MustSucceed

func MustSucceed(err error)

func Terminate added in v0.3.0

func Terminate(msg string)

Types

type SA added in v0.4.0

type SA struct {
	// contains filtered or unexported fields
}

func New added in v0.4.0

func New(c *cli.CLI) *SA

func (*SA) Delete added in v0.4.0

func (sa *SA) Delete(cfg conf.Config, nonInteractive bool) error

func (SA) Diff added in v0.4.0

func (sa SA) Diff(cfg conf.Config) error

func (SA) Info added in v0.4.0

func (sa SA) Info(stack *awscf.Stack) error

func (SA) InfoAll added in v0.4.0

func (sa SA) InfoAll(cfg conf.Config) error

func (SA) Sync added in v0.4.0

func (sa SA) Sync(cfg conf.Config, nonInteractive bool) ([]*awscf.Stack, error)

Directories

Path Synopsis
aws
cmd
Package main provides cmd stas application
Package main provides cmd stas application
Package depgraph provides functionality to resolve dependencies.
Package depgraph provides functionality to resolve dependencies.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL