Using Remote State
Terraform natively supports the concept of remote state and there's a very easy way to access the outputs of one Terraform component in another component. We simplify this using the remote-state module, which is stack-aware and can be used to access the remote state of a component in the same or a different Atmos stack.
As your architecture grows, it helps to be more intentional about how you deconstruct and organize your components to keep your Terraform state small (see our best practices). By creating smaller components, your state becomes naturally more manageable. However, this introduces a new problem: there are now dependencies between your components, and the state becomes distributed. We need to find a new way for state to flow between your components and for and a way to share configuration. Plus, we want to avoid manual duplication of configurations as much as possible because that leads to bugs, like copy-paste mistakes.
You will learn
- How to use the 
remote-statemodule to access the remote state of a component in the same or a different Atmos stack - How to configure Atmos to work the 
remote-statemodule to access the remote state of a component - Alternatives that might be easier for your use case
 
In Atmos, this is solved by using these modules:
- 
terraform-provider-utils - The Cloud Posse Terraform Provider for various utilities, including stack configuration management
 - 
remote-state - Terraform module that loads and processes stack configurations from YAML sources and returns remote state outputs for Terraform components
 
The terraform-provider-utils is implemented in Go and uses Atmos Go modules to work with Atmos CLI config and Atmos stacks. The provider processes stack configurations to get the final config for an Atmos component in an Atmos stack. The final component config is then used by the remote-state Terraform module to return the remote state for the component in the stack.
Terraform remote state is incompatible with the local backend type. This is because the local backend is not recommended for production. Review the alternatives here, or consider switching to one of the other backend types.
Atmos now supports new ways to share data between components using the template function atmos.Component
and the Atmos YAML functions !terraform.state and !terraform.output in your Stack configurations:
{{ (atmos.Component <component> <stack>).outputs.<output_name> }}
!terraform.state <component> <stack> <output_name>
!terraform.output <component> <stack> <output_name>
The atmos.Component template function allows reading any Atmos section or any attribute (not just outputs) from a section
of an Atmos component in a stack.
For more details on atmos.Component function, refer to atmos.Component.
The !terraform.state and !terraform.output Atmos YAML functions allow reading any output (remote state) of an Atmos component in a stack.
For more details on !terraform.state YAML function, refer to !terraform.state.
For more details on !terraform.output YAML function, refer to !terraform.output.
Example
Here is an example.
Suppose that we need to provision two Terraform components:
The vpc Terraform component needs the outputs from the vpc-flow-logs-bucket Terraform component to
configure VPC Flow Logs and store them in the S3 bucket.
We will provision the two Terraform components in the ue2-dev Atmos stack (in the dev AWS account by setting stage = "dev" and in
the us-east-2 region by setting environment = "ue2").
Configure and Provision the vpc-flow-logs-bucket Component
In the stacks/catalog/vpc-flow-logs-bucket.yaml file, add the following default configuration for the vpc-flow-logs-bucket/defaults Atmos component:
stacks/catalog/vpc-flow-logs-bucket.yaml
In the stacks/ue2-dev.yaml stack config file, add the following config for the vpc-flow-logs-bucket-1 Atmos component in the ue2-dev Atmos
stack:
stacks/ue2-dev.yaml
Having the stacks configured as shown above, we can now provision the vpc-flow-logs-bucket-1 Atmos component into the ue2-dev stack by executing
the following Atmos commands:
atmos terraform plan vpc-flow-logs-bucket-1 -s ue2-dev
atmos terraform apply vpc-flow-logs-bucket-1 -s ue2-dev
Configure and Provision the vpc Component
Having the vpc-flow-logs-bucket Terraform component provisioned into the ue2-dev stack, we can now configure the vpc Terraform component
to obtain the outputs from the remote state of the vpc-flow-logs-bucket-1 Atmos component.
In the components/terraform/infra/vpc/remote-state.tf file, configure the
remote-state Terraform module to obtain the remote state
for the vpc-flow-logs-bucket-1 Atmos component:
components/terraform/infra/vpc/remote-state.tf
In the components/terraform/infra/vpc/vpc-flow-logs.tf file, configure the aws_flow_log resource for the vpc Terraform component to use the
remote state output vpc_flow_logs_bucket_arn from the vpc-flow-logs-bucket-1 Atmos component:
components/terraform/infra/vpc/vpc-flow-logs.tf
In the stacks/catalog/vpc.yaml file, add the following default config for the vpc/defaults Atmos component:
stacks/catalog/vpc.yaml
In the stacks/ue2-dev.yaml stack config file, add the following config for the vpc/1 Atmos component in the ue2-dev stack:
stacks/ue2-dev.yaml
Having the stacks configured as shown above, we can now provision the vpc/1 Atmos component into the ue2-dev stack by
executing the following Atmos commands:
atmos terraform plan vpc/1 -s ue2-dev
atmos terraform apply vpc/1 -s ue2-dev
Atmos Configuration
Both the atmos CLI and terraform-provider-utils Terraform provider use the same Go code, which try to locate the CLI config atmos.yaml file before parsing and processing Atmos stacks.
This means that atmos.yaml file must be at a location in the file system where all the processes can find it.
While placing atmos.yaml at the root of the repository will work for Atmos, it will not work for the terraform-provider-utils Terraform provider because the provider gets executed from the component's directory (e.g. components/terraform/infra/vpc), and we don't want to replicate atmos.yaml into every component's folder.
atmos.yaml is loaded from the following locations (from lowest to highest priority):
- System dir (
/usr/local/etc/atmos/atmos.yamlon Linux,%LOCALAPPDATA%/atmos/atmos.yamlon Windows) - Home dir (
~/.atmos/atmos.yaml) - Current directory
 - ENV variables 
ATMOS_CLI_CONFIG_PATHandATMOS_BASE_PATH 
Initial Atmos configuration can be controlled by these ENV vars:
ATMOS_CLI_CONFIG_PATH- where to findatmos.yaml. Absolute path to a folder where theatmos.yamlCLI config file is locatedATMOS_BASE_PATH- absolute path to the folder containing thecomponentsandstacksfolders
Recommended Options
For this to work for both the atmos CLI and the Terraform provider, we recommend doing one of the following:
- 
Put
atmos.yamlat/usr/local/etc/atmos/atmos.yamlon local host and set the ENV varATMOS_BASE_PATHto point to the absolute path of the root of the repo - 
Put
atmos.yamlinto the home directory (~/.atmos/atmos.yaml) and set the ENV varATMOS_BASE_PATHpointing to the absolute path of the root of the repo - 
Put
atmos.yamlat a location in the file system and then set the ENV varATMOS_CLI_CONFIG_PATHto point to that location. The ENV var must point to a folder without theatmos.yamlfile name. For example, ifatmos.yamlis at/atmos/config/atmos.yaml, setATMOS_CLI_CONFIG_PATH=/atmos/config. Then set the ENV varATMOS_BASE_PATHpointing to the absolute path of the root of the repo - 
When working in a Docker container, place
atmos.yamlin therootfsdirectory at /rootfs/usr/local/etc/atmos/atmos.yaml and then copy it into the container's file system in the Dockerfile by executing theCOPY rootfs/ /Docker command. Then in the Dockerfile, set the ENV varATMOS_BASE_PATHpointing to the absolute path of the root of the repo. Note that the Atmos example uses Geodesic as the base Docker image. Geodesic sets the ENV varATMOS_BASE_PATHautomatically to the absolute path of the root of the repo on local host 
Summary
- 
Remote State for an Atmos component in an Atmos stack is obtained by using the remote-state Terraform module
 - 
The module calls the terraform-provider-utils Terraform provider which processes the stack configs and returns the configuration for the Atmos component in the stack. The terraform-provider-utils Terraform provider utilizes Atmos
Gomodules to parse and process stack configurations - 
The remote-state module accepts the
componentinput as the Atmos component name for which to get the remote state outputs - 
The module accepts the
contextinput as a way to provide the information about the stack (using the context variablesnamespace,tenant,environment,stagedefined in the stack manifests) - 
If the Atmos component (for which we want to get the remote state outputs) is provisioned in a different Atmos stack (in a different AWS OU, or different AWS account, or different AWS region), we can override the context variables
tenant,stageandenvironmentto point the module to the correct stack. For example, if the component is provisioned in a different AWS region (let's sayus-west-2), we can setenvironment = "uw2", and the remote-state module will get the remote state outputs for the Atmos component provisioned in that region 
Use Remote State in Stack Configurations
Atmos supports alternative ways to read the outputs (remote state) of components directly in Atmos stack manifests by
using the !terraform.output Atmos YAML function
and the atmos.Component Go template function instead of using
the remote-state module
and configuring Terraform/OpenTofu components to use the module.