Introduce Atmos `Go` template functions. Add `atmos.Component` function to read values from other Atmos components including outputs (remote state) @aknysh (#628)
## what- Introduce Atmos
Go
template functions - Add
atmos.Component
template function to read values from other Atmos components including outputs (remote state) - Update docs
why
-
Atmos now supports custom
Go
template functions similar to Sprig and GomplateIn
Go
templates in Atmos stack manifests, you can use the following functions and datasources:
description
The atmos.Component
template function allows you to read any Atmos section or any attribute from a section for an Atmos component in a stack, and use it in Go
templates in Atmos component configurations.
Usage
{{ (atmos.Component "<component>" "<stack>").<section>.<attribute> }}
Arguments
-
component
- Atmos component name -
stack
- Atmos stack name -
section
- Atmos section name. Any section returned by the CLI commandatmos describe component
can be used. A specialoutputs
section is also supported to get the outputs (remote state) of Terraform/OpenTofu components.NOTE: Using the
outputs
section in theatmos.Component
command is an alternative way to read the outputs (remote state) of a component in a stack directly in Atmos stack manifests instead of using theremote-state
module and configuring Terraform/OpenTofu components to use theremote-state
module as described in Component Remote State -
attribute
- attribute name (field) from thesection
.attribute
is optional, you can use thesection
itself if it's a simple type (e.g.string
). Any number of attributes can be chained using the dot (.
) notation. For example, if the first two attributes are maps, you can chain them and get a field from the last map:{{ (atmos.Component "<component>" "<stack>").<section>.<attribute1>.<attribute2>.<field1> }}
Specifying Atmos stack
stack
is the second argument of the atmos.Component
function, and it can be specified in a few different ways:
-
Hardcoded stack name. Use it if you want to get an output from a component from a different (well-known and static) stack. For example, you have a
tgw
component in a stackplat-ue2-dev
that requires thevpc_id
output from thevpc
component from the stackplat-ue2-prod
:components: terraform: tgw: vars: vpc_id: '{{ (atmos.Component "vpc" "plat-ue2-prod").outputs.vpc_id }}'
-
Use the
.stack
(or.atmos_stack
) template identifier to specify the same stack as the current component (for which theatmos.Component
function is executed):{{ (atmos.Component "<component>" .stack).<section>.<attribute> }} {{ (atmos.Component "<component>" .atmos_stack).<section>.<attribute> }}
For example, you have a
tgw
component that requires thevpc_id
output from thevpc
component in the same stack:components: terraform: tgw: vars: vpc_id: '{{ (atmos.Component "vpc" .stack).outputs.vpc_id }}'
-
Use the
printf
template function to construct stack names using static strings and dynamic identifiers:{{ (atmos.Component "<component>" (printf "%s-%s-%s" .vars.tenant .vars.environment .vars.stage)).<section>.<attribute> }} {{ (atmos.Component "<component>" (printf "plat-%s-prod" .vars.environment)).<section>.<attribute> }} {{ (atmos.Component "<component>" (printf "%s-%s-%s" .settings.context.tenant .settings.context.region .settings.context.account)).<section>.<attribute> }}
For example, you have a
tgw
component deployed in the stackplat-ue2-dev
. Thetgw
component requires thevpc_id
output from thevpc
component from the same environment (ue2
) and same stage (dev
), but from a different tenantnet
(instead ofplat
):components: terraform: tgw: vars: vpc_id: '{{ (atmos.Component "vpc" (printf "net-%s-%s" .vars.environment .vars.stage)).outputs.vpc_id }}'
NOTE: By using the
printf "%s-%s-%s"
function, you are constructing stack names using the stack context variables/identifiers. For more information on Atmos stack names and how to define them, refer tostacks.name_pattern
andstacks.name_template
sections inatmos.yaml
CLI config file
Examples
The following configurations show different ways of using the atmos.Component
template function to read values from different Atmos sections directly in Atmos stack manifests, including the outputs of other (already provisioned) components.
# Global `settings` section
# It will be added and deep-merged to the `settings` section of all components
settings:
test: true
components:
terraform:
test:
metadata:
# Point to the Terraform/OpenTofu component
component: "test"
vars:
name: "test"
test1:
metadata:
# Point to the Terraform/OpenTofu component
component: "test1"
vars:
name: "test1"
test2:
metadata:
# Point to the Terraform/OpenTofu component
component: "test2"
vars:
name: "test2"
# Use the `atmos.Component` function to get the outputs of the Atmos component `test1`
# The `test1` component must be already provisioned and its outputs stored in the Terraform/OpenTofu state
# Atmos will execute `terraform output` on the `test1` component in the same stack to read its outputs
test1_id: '{{ (atmos.Component "test1" .stack).outputs.test1_id }}'
tags:
# Get the `settings.test` field from the `test` component in the same stack
test: '{{ (atmos.Component "test" .stack).settings.test }}'
# Get the `metadata.component` field from the `test` component in the same stack
test_terraform_component: '{{ (atmos.Component "test" .stack).metadata.component }}'
# Get the `vars.name` field from the `test1` component in the same stack
test1_name: '{{ (atmos.Component "test1" .stack).vars.name }}'