Skip to content

Latest commit

 

History

History
208 lines (153 loc) · 8.12 KB

README.md

File metadata and controls

208 lines (153 loc) · 8.12 KB

This framework lets you easily deploy logical units of infrastructure called "components".

What you need to know before you can use this framework

To be successful using this framework, you will need to understand how to build infrastructure using the Terraform language. You will also need to know how to set variables using POSIX shell syntax. Here are some guides to get you started on these topics:

As you gain more confidence in using this framework, you can use advanced POSIX sh shell scripting to dynamically adjust values passed in to your Terraform, and you can deploy more advanced Terraform constructs like conditional resources.

What is a component?

A component is a logical unit of infrastructure. It does something. What it does is up to you. When creating a component, plan what its function is within the infrastructure, thoughtfully. Components should not try to do too much and, at the same time, not be so small as to offer no value on their own.

Anatomy of a component

Here is what a component looks like, one generated by terraform-component create:

$ tree components/terraform_state_backend_s3
components/terraform_state_backend_s3
├── LICENSE.md
├── README.md
├── build-env.sh
├── deploy-env.sh
├── deploy-hooks.sh
└── terraform
    ├── main.tf
    ├── outputs.tf
    └── variables.tf

All components have this structure, which generally falls into three categories:

  1. Informational files that tell you what the component is and how it can be reused. LICENSE.md and README.md
  2. POSIX shell scripts that pass data from the command line invocation into the Terraform HCL, at various points throughout the deployment life-cycle. build-env.sh, deploy-env.sh, and deploy-hooks.sh.
  3. The infrastructure implementation, in Terraform HCL within the terraform/ sub-directory. You may have one or more files in here. By convention there are:
    • main.tf, which holds the implementation of your infrastructure component
    • outputs.tf, which documents the outputs this component makes available to other components
    • variables.tf, which documents what inputs the component needs to implement the infrastructure.

Terraform versions

Different versions of Terraform offer different features. Generally, the higher the version number, the more features. Usually you want to use the latest possible version, to take advantage of new features and bug and security fixes.

Each component, individually, declares what version of Terraform it wants to use. This allows you to develop components independently: older components can continue to use older versions of Terraform, while newer ones use newer versions.

Set the value of TERRAFORM_VERSION in your build-env.sh file to the version of Terraform you want to use, or if you do not, your component inherits the value from this framework.

Available versions are listed at Docker Hub.

Tip: always set the Terraform version in your components.

Variables

Variables specified in the terraform/variables.tf file (or any other *.tf file that holds a variable terraform declaration) must be given before your component will deploy. The values are specified in the deploy-env.sh file.

Normally, the values are expressed using simple assignment, like:

TF_VAR_region=us-west-2

However, you can use shell scripting to calculate values dynamically, based on other values in the environment. For example, to use the value of a variable named AWS_REGION if it exists, but otherwise default to us-west-2, you could use:

TF_VAR_region=${AWS_REGION:-us-west-2}

To experiment with the shell, you can run:

docker run -it --entrypoint /bin/sh hashicorp/terraform

Read more about Terraform variables.

Outputs

Your component may output information that other components to depend upon. This often happens when a component creates a resource then needs to share that resource's identifier with dependent components.

Outputs specified in the terraform/outputs.tf file (or any other *.tf file that holds an output terraform declaration) will be available for other components to use. (See the next section on expression dependencies.)

Read more about Terraform outputs.

Expressing dependencies

As much as possible, components should be independent and not depend upon other components, because it simplifies replicating environments and reduces the complexity of understanding relationships between components.

However, there are times when you want or need component dependencies, so this framework supports them. Refer to the Terraform documentation for more.

Licensing

While this framework is licensed under the GNU General Public License, version 3, components within this sub-directory may have a different license. Components must specify their license in the form of a LICENSE.md file, even if it's the same as this framework.

Components without a LICENSE.md inherit the license of this framework: GPLv3.

Component deployment life-cycle

When you run terraform-component deploy, the framework code runs through a series of well-defined steps called "the deployment life-cycle" on the component you've chosen to deploy.

The first step is to build a Docker image that houses the logical combination of your component's code and the base files provided by the framework. This image has everything needed to deploy the Terraform. So long as you make no changes to your component's Terraform or shell configuration, this image will be used every time you deploy. The configuration values in build-env.sh drive various features available in the built image, and that's the extent of configurability you have on the build step.

The second step is to deploy the built Docker image. This step is far more customizable. The deploy-env.sh script runs, programatically setting values for your Terraform to access. Since the terraform process is multi-staged (init, plan, apply, etc), you can configure behavior before and after each of these stages with the deploy-hooks.sh file.

Extending terraform-component

You can use this framework standalone via fork and clone, which is the easiest way to get started. It's meant to be easy, so that you can focus on getting infrastructure-as-code deployed.

You can also extend this framework with your own custom behavior or private components. A common way to do this is:

  1. At install time, download a copy of this framework (npm install, composer install, etc.) using curl (or similar) and store in a directory named deployer (or similar).
  2. Write a script that wraps this framework's terraform-component. For example, that script might authenticate the user with the cloud provider.
  3. Arrange for your wrapper script to point to your components and use your environment setup.

Here's a rough outline of these steps:

# download the latest release of this framework and put into a directory named `deployer`
curl https://api.github.com/repos/bishopb/terraform-component/tarball \
  | tar xzC deployer --strip 1

# invoke the framework deployer, after setting up the environment and pointing it
# to our custom components
env \
  default_TF_VAR_providers=aws \
  default_TF_VAR_credentials=aws \
  default_TF_VAR_backend=s3 \
  COMPONENT_PATH=./components:./deployer/components \
  ./deployer/bin/terraform-component deploy "component-name" "apply"

There is no limit to how you can compose this framework into your environment.

Additional resources

  • To learn how to create components, run terraform-component create and read the help documentation.
  • To better understand the organization of a component, refer to the lib/component_skeleton directory.