what
- Update Atmos Stack imports
- Update docs https://atmos.tools/core-concepts/stacks/imports/
- Add imports schema with context
- Allow using Go templates in imported configurations
why
- Auto-generate Atmos components from templates
- Using imports with context and parameterized config files will help to make the stack configurations extremely DRY,
and is very useful when creating stacks and components for EKS blue-green deployment
Imports Schema
The import
section supports the following two formats:
-
a list of paths to the imported files, for example:
import: - mixins/region/us-east-2 - orgs/cp/tenant1/test1/_defaults - catalog/terraform/top-level-component1 - catalog/terraform/test-component - catalog/terraform/vpc - catalog/helmfile/echo-server
-
a list of objects with the following schema:
import: - path: "<path_to_imported_file>" context: {} - path: "<path_to_imported_file>" context: {}
where:
path
- the path to the imported filecontext
- an optional freeform map of context variables that are applied as template variables to the imported file (if the imported file is a Go template)
Go Templates in Imported Stacks
Atmos supports all the functionality of the Go templates in imported stack configurations (including functions). Stack configurations can be templatized and then reused with different settings provided via the import context
section.
For example, we can define the following configuration for EKS Atmos components in the catalog/terraform/eks_cluster_tmpl.yaml
template file:
# Imports can also be parameterized using `Go` templates
import: []
components:
terraform:
"eks-{{ .flavor }}/cluster":
metadata:
component: "test/test-component"
vars:
enabled: "{{ .enabled }}"
name: "eks-{{ .flavor }}"
service_1_name: "{{ .service_1_name }}"
service_2_name: "{{ .service_2_name }}"
tags:
flavor: "{{ .flavor }}"
NOTE: Since Go
processes templates as text files, we can parameterize the Atmos component name eks-{{ .flavor }}/cluster
and any values in any sections (vars
, settings
, env
, backend
, etc.), and even the import
section in the imported file (if the file imports other configurations).
Then we can import the template into a top-level stack multiple times providing different context variables to each import:
import:
- path: mixins/region/us-west-2
- path: orgs/cp/tenant1/test1/_defaults
# This import with the provided context will dynamically generate
# a new Atmos component `eks-blue/cluster` in the stack
- path: catalog/terraform/eks_cluster_tmpl
context:
flavor: "blue"
enabled: true
service_1_name: "blue-service-1"
service_2_name: "blue-service-2"
# This import with the provided context will dynamically generate
# a new Atmos component `eks-green/cluster` in the stack
- path: catalog/terraform/eks_cluster_tmpl
context:
flavor: "green"
enabled: false
service_1_name: "green-service-1"
service_2_name: "green-service-2"
Now we can execute the following Atmos commands to describe and provision the dynamically generated EKS components into the stack:
atmos describe component eks-blue/cluster -s tenant1-uw2-test-1
atmos describe component eks-green/cluster -s tenant1-uw2-test-1
atmos terraform apply eks-blue/cluster -s tenant1-uw2-test-1
atmos terraform apply eks-green/cluster -s tenant1-uw2-test-1
All the parameterized variables will get their values from the context
:
vars:
enabled: true
environment: uw2
name: eks-blue
namespace: cp
region: us-west-2
service_1_name: blue-service-1
service_2_name: blue-service-2
stage: test-1
tags:
flavor: blue
tenant: tenant1
vars:
enabled: true
environment: uw2
name: eks-green
namespace: cp
region: us-west-2
service_1_name: green-service-1
service_2_name: green-service-2
stage: test-1
tags:
flavor: green
tenant: tenant1
The dynamically generated Atmos components are visible in atmos describe affected
command as well:
atmos describe affected
{
"component": "eks-blue/cluster",
"component_type": "terraform",
"stack": "tenant1-uw2-test-1",
"affected": "stack.metadata"
},
{
"component": "eks-green/cluster",
"component_type": "terraform",
"stack": "tenant1-uw2-test-1",
"affected": "stack.metadata"
}
Hierarchical Imports with Context
Atmos supports hierarchical imports with context.
This will allow you to parameterize the entire chain of stack configurations and dynamically generate components in stacks.
For example, let's create the configuration stacks/catalog/terraform/eks_cluster_tmpl_hierarchical.yaml
with the following content:
import:
# Use `region_tmpl` `Go` template and provide `context` for it.
# This can also be done by using `Go` templates in the import path itself.
# - path: "mixins/region/{{ .region }}"
- path: "mixins/region/region_tmpl"
# `Go` templates in `context`
context:
region: "{{ .region }}"
environment: "{{ .environment }}"
# `Go` templates in the import path
- path: "orgs/cp/{{ .tenant }}/{{ .stage }}/_defaults"
components:
terraform:
# Parameterize Atmos component name
"eks-{{ .flavor }}/cluster":
metadata:
component: "test/test-component"
vars:
# Parameterize variables
enabled: "{{ .enabled }}"
name: "eks-{{ .flavor }}"
service_1_name: "{{ .service_1_name }}"
service_2_name: "{{ .service_2_name }}"
tags:
flavor: "{{ .flavor }}"
Then we can import the template into a top-level stack multiple times providing different context variables to each import and to the imports for the entire inheritance chain (which catalog/terraform/eks_cluster_tmpl_hierarchical
imports itself):
import:
# This import with the provided hierarchical context will dynamically generate
# a new Atmos component `eks-blue/cluster` in the `tenant1-uw1-test1` stack
- path: "catalog/terraform/eks_cluster_tmpl_hierarchical"
context:
# Context variables for the EKS component
flavor: "blue"
enabled: true
service_1_name: "blue-service-1"
service_2_name: "blue-service-2"
# Context variables for the hierarchical imports
# `catalog/terraform/eks_cluster_tmpl_hierarchical` imports other parameterized configurations
tenant: "tenant1"
region: "us-west-1"
environment: "uw1"
stage: "test1"
# This import with the provided hierarchical context will dynamically generate
# a new Atmos component `eks-green/cluster` in the `tenant1-uw1-test1` stack
- path: "catalog/terraform/eks_cluster_tmpl_hierarchical"
context:
# Context variables for the EKS component
flavor: "green"
enabled: false
service_1_name: "green-service-1"
service_2_name: "green-service-2"
# Context variables for the hierarchical imports
# `catalog/terraform/eks_cluster_tmpl_hierarchical` imports other parameterized configurations
tenant: "tenant1"
region: "us-west-1"
environment: "uw1"
stage: "test1"
In the case of hierarchical imports, Atmos performs the following steps:
-
Processes all the imports in the
import
section in the current configuration in the order they are specified providing thecontext
to all imported files -
For each imported file, Atmos deep-merges the parent
context
with the current context. Note that the currentcontext
(in the current file) takes precedence over the parentcontext
and will override items with the same keys. Atmos does this hierarchically for all imports in all files, effectively processing a graph of imports and deep-merging the contexts on all levels
For example, in the stacks/orgs/cp/tenant1/test1/us-west-1.yaml
configuration above, we first import
the catalog/terraform/eks_cluster_tmpl_hierarchical
and provide it with the context
which includes the context variables for the EKS component itself, as well as the context variables for all the hierarchical imports. Then, when processing the stacks/catalog/terraform/eks_cluster_tmpl_hierarchical
configuration, Atmos deep-merges the parent context
(from stacks/orgs/cp/tenant1/test1/us-west-1.yaml
) with the current context
and processes the Go
templates.
We are now able to dynamically generate the components eks-blue/cluster
and eks-green/cluster
in the stack tenant1-uw1-test1
and can execute the following Atmos commands to provision the components into the stack:
atmos terraform apply eks-blue/cluster -s tenant1-uw1-test-1
atmos terraform apply eks-green/cluster -s tenant1-uw1-test-1
All the parameterized variables get their values from the all the hierarchical context
settings:
vars:
enabled: true
environment: uw1
name: eks-blue
namespace: cp
region: us-west-1
service_1_name: blue-service-1
service_2_name: blue-service-2
stage: test-1
tags:
flavor: blue
tenant: tenant1