How to Use Atmos with Existing Terraform
Problem
Not everyone beginning to implement Atmos is starting with a clean slate, and many users would like to put Atmos to use with their existing Terraform infrastructure. However, the SweetOps approach is highly opinionated and as a result, can be intimidating for new users to begin to apply the practices to existing infrastructure. How can we leverage Atmos to incrementally build off our existing Terraform infrastructure and begin to DRY variable configurations?
Solution
Applying Atmos to existing infrastructure can be an easy process if broken into a few parts. The following sections will outline each key concept with Atmos and the steps to apply each to your existing Terraform code.
TL;DR: Follow the 5 steps below for a detailed explanation of each step.
-
Copy all terraform components to
components/terraform/
. See Components -
Create each stack under
stacks/
. See Stacks -
Define each component within
stacks/catalog/
and import into stacks. See How to Use Imports and Catalogs in Stacks -
Copy existing Terraform variable definitions into the component defaults, catalog definitions, or stack configuration.
-
Import existing state using Atmos. See Atmos
Part 1: Organization
The first and foremost key to success with Atmos is organization. Organization of Terraform components, variables, and environment configuration naturally lead to DRY code, easier understanding, and less room for errors. With Atmos, we organize all components
(Components) and variables configuration, referred to as stacks
(Stacks), into respective folders. An example layout would look like the following:
infrastructure/
├── ...
├── components/
│ ├── terraform/
│ │ ├── ec2-instance/
│ │ └── vpc/
└── stacks/
Steps
-
Decide on a unique name to give your components. Make sure if follows our Components.
-
Create the folder in
components/terraform
with the given name of the component -
Move all existing Terraform code to the path
components/terraform
.
Part 2: Stacks
Stacks are what Atmos uses to define configuration and variables for each component in any environment. Our standard convention is that each stack
operates in a given region and environment; for example, ue1-nonprod.yaml
defines the configuration for nonprod
operating in the us-east-1
region. Anything included in these stacks should be unique to that given region and environment or be imported by a global configuration file. Read more about Stacks
infrastructure/
├── ...
├── components/
└── stacks/
├── use1-nonprod.yaml
├── usw1-nonprod.yaml
├── use1-prod.yaml
└── usw1-prod.yaml
Steps
-
Create a
yaml
file for each environment and region -
Use the following as an example to start each stack. Only include unique configuration for the given environment and region.
vars:
stage: nonprod
terraform:
vars: {}
components:
terraform: {}
Part 3: Catalog
The catalog
defines every component available to use. Each component is given a configuration file within the catalog
where common config is set.
For example, a basic configuration for a component called ec2-instance
would look like the following:
components:
terraform:
ec2-instance:
backend:
s3:
workspace_key_prefix: ec2-instance
vars:
enabled: true
When we want to use a component
with a stack
, we can import that component
from the catalog
. Then that given stack
can define unique variables for that component
. Read more about the catalog
and how to use imports under How to Use Imports and Catalogs in Stacks
Steps
-
Create the
catalog
folder understacks/
-
Create a
yaml
configuration file for each component. -
Import the
component
into anystack
file you want the component deployed, using the path to the catalog entry. For example:
import:
- catalog/ec2-instance