Browse the Repo

file-type-icon.circleci
file-type-icon_ci
file-type-icon_docs
file-type-iconexamples
file-type-iconmodules
file-type-iconaws-helpers
file-type-iconbuild-helpers
file-type-iconcheck-url
file-type-iconcircleci-helpers
file-type-iconec2-backup
file-type-iconecs-deploy-runner-invoke-iam-policy
file-type-iconecs-deploy-runner-standard-configuration
file-type-iconecs-deploy-runner
file-type-icongit-helpers
file-type-icongruntwork-module-circleci-helpers
file-type-iconiam-policies
file-type-iconinfrastructure-deploy-script
file-type-iconinfrastructure_deploy_script
file-type-iconscripts
file-type-icontest
file-type-iconREADME.adoc
file-type-iconcore-concepts.md
file-type-icondev_requirements.txt
file-type-iconinstall.sh
file-type-iconrequirements.txt
file-type-iconsetup.py
file-type-iconinfrastructure-deployer
file-type-iconinstall-jenkins
file-type-iconjenkins-server
file-type-iconkubernetes-circleci-helpers
file-type-iconterraform-helpers
file-type-icontest
file-type-icontestdep
file-type-icon.gitignore
file-type-icon.pre-commit-config.yaml
file-type-iconCODEOWNERS
file-type-iconLICENSE.txt
file-type-iconREADME-CircleCI.adoc
file-type-iconREADME-Jenkins.adoc
file-type-iconREADME-Terraform-Terragrunt-Pipeline.adoc
file-type-iconREADME-TravisCI.adoc
file-type-iconREADME.adoc
file-type-iconsetup.cfg
file-type-iconterraform-cloud-enterprise-private-module-...

Browse the Repo

file-type-icon.circleci
file-type-icon_ci
file-type-icon_docs
file-type-iconexamples
file-type-iconmodules
file-type-iconaws-helpers
file-type-iconbuild-helpers
file-type-iconcheck-url
file-type-iconcircleci-helpers
file-type-iconec2-backup
file-type-iconecs-deploy-runner-invoke-iam-policy
file-type-iconecs-deploy-runner-standard-configuration
file-type-iconecs-deploy-runner
file-type-icongit-helpers
file-type-icongruntwork-module-circleci-helpers
file-type-iconiam-policies
file-type-iconinfrastructure-deploy-script
file-type-iconinfrastructure_deploy_script
file-type-iconscripts
file-type-icontest
file-type-iconREADME.adoc
file-type-iconcore-concepts.md
file-type-icondev_requirements.txt
file-type-iconinstall.sh
file-type-iconrequirements.txt
file-type-iconsetup.py
file-type-iconinfrastructure-deployer
file-type-iconinstall-jenkins
file-type-iconjenkins-server
file-type-iconkubernetes-circleci-helpers
file-type-iconterraform-helpers
file-type-icontest
file-type-icontestdep
file-type-icon.gitignore
file-type-icon.pre-commit-config.yaml
file-type-iconCODEOWNERS
file-type-iconLICENSE.txt
file-type-iconREADME-CircleCI.adoc
file-type-iconREADME-Jenkins.adoc
file-type-iconREADME-Terraform-Terragrunt-Pipeline.adoc
file-type-iconREADME-TravisCI.adoc
file-type-iconREADME.adoc
file-type-iconsetup.cfg
file-type-iconterraform-cloud-enterprise-private-module-...
EC2 backup

EC2 backup

Snapshot your EC2 instances on a scheduled basis.

Code Preview

Preview the Code

mobile file icon

core-concepts.md

down

Core Concepts

Overview

This module contains helper scripts for implementing automated pipelines that run Terraform and Terragrunt remotely. This script is designed to be run within a Docker container that is executed from a remote server that:

  • Has all the tools and dependencies installed.
  • Has the necessary IAM permissions to deploy the target module.
  • Insulates the environment from CI servers so that you don't have to grant IAM permissions to CI servers.

This script can be used to achieve an automated workflow to implement CI/CD for your infrastructure code when used in combination with the ecs-deploy-runner module. Refer to the documentation for the ecs-deploy-runner module for more details.

When invoked, the script does the following:

  • Clone the repository containing the infrastructure code using git
  • Change the working directory to the desired path passed in the parameters
  • Run terraform or terragrunt with plan or apply depending on the passed in parameters, streaming the output to stdout and stderr
  • If the underlying command fails, look up to see if it is a known failure to retry and continue calling the command until the configured number of retries
  • Exit with the appropriate exit code depending on if the underlying command succeeded or failed

Operations

What are the system requirements for the deploy script?

The deploy-script is a python 3.7+ script that calls out to other tools such as git, terraform, and terragrunt. As such, the runtime environment will require:

  • Python (minimal version 3.7)
  • git
  • terraform
  • terragrunt

Where do I run the deploy script?

The script is designed to be run in an environment that has IAM permissions to deploy the module. In order to support arbitrary infrastructure deployment, this naturally translates to an environment with admin privileges to all the AWS accounts where infrastructure is managed with code. Therefore, it is not recommended to run the scripts directly on the CI servers such as CircleCI or Jenkins. Most companies are not comfortable with third party CI services holding admin level credentials to AWS accounts, and even for on-prem solutions, CI servers are notorious for being heavy targets for attackers, and are continuously subject to various vulnerabilities.

Instead, this script is designed to run in your AWS account in an isolated environment on ECS or EKS. You then configure your CI servers to remotely invoke the tasks, granting only the minimal permissions necessary to invoke from the CI servers.

Refer to the ecs-deploy-runner module to deploy the script as an ECS task that can be invoked from an AWS Lambda function, and the ecs-deploy-runner-invoke-iam-policy module for how to grant permissions to the IAM user used by your CI server to invoke the Lambda function.

Contributing

Local Development

The deploy script is a python script targetting version 3.8+ so that we can take advantage of a number of improvements that were introduced in newer versions of python. You will find the following folder structure:

  • scripts: Frontend CLI scripts that users interact with directly.
  • infrastructure_deploy_script: Implementation code for the script.
  • test: Python based unit tests for the library.
  • requirements.txt: The minimal requirements required for the lambda function handler to run.
  • dev_requirements.txt: Additional requirements for enhanced developer experiences. E.g mypy and type stubs for static analysis.
  • install.sh: Used by gruntwork-install to install the deploy script on to the target machine.

How to install python 3.8

The easiest way to install python 3.8 on Unix platforms is to use pyenv. Once you have pyenv installed, install Python 3.8 and enable it locally in the project:

pyenv install 3.8.1
pyenv local 3.8.1

Static type analysis

Python introduced optional type hints beginning with python 3.5. Type hints provides valuable static analysis to detect various kinds of bugs before you actively run the code. For example, consider the following code:

fruit: Union[Literal['apple'], Literal['orange'], Literal['pear']] = 'apple'

The above code sets the type of the variable fruit to the union of the string literals apple, orange, and pear. This means that fruit must be one of those string values. Python's type checker is strong enough that it can detect when you compare this against a value that is not in the type union. For example, consider the following if block:

if fruit == 'aple':
    raise Exception('This is impossible')

In this case, apple was misspelled in the if check. Since aple is not one of the supported types in the union, the type checker will throw an error saying the right hand side of the check does not match the type of the left hand side.

To run through the static type checker:

  • Install the requirements in dev_requirements.txt: pip install -r dev_requirements.txt
  • Run the type checker using mypy: mypy
  • Run the style checker using flake8: flake8

Unit tests

The unit tests for the deploy script are available in the test folder of this directory. The tests are written using the pytest framework. To run the unit tests:

  • Install the requirements in dev_requirements.txt: pip install -r dev_requirements.txt
  • Run pytest: PYTHONPATH=. pytest
    • We set the PYTHONPATH here so that pytest picks up the script library code in this directory.

Questions? Ask away.

We're here to talk about our services, answer any questions, give advice, or just to chat.

Ready to hand off the Gruntwork?