# Atmos YAML Functions

_Recommended_

**YAML Functions are the recommended way to add dynamic behavior to your Atmos configurations.** They are native YAML features that work with the YAML parser, making them type-safe, predictable, and error-resistant. Unlike template functions which manipulate raw text, YAML functions operate on structured data after parsing.

## Why YAML Functions Are Safer

YAML functions are based on [YAML Explicit typing](https://yaml.org/spec/1.2.2/)
and user-defined [Explicit Tags](https://yaml.org/spec/1.2.2/#tags) (local data types).
Explicit tags are denoted by the exclamation point (**"!"**) symbol.

**Key advantages over template functions:**

- **Cannot break YAML syntax** - Functions execute after YAML parsing, not before
- **Type-safe** - Work with actual YAML types, not raw strings
- **No indentation issues** - The YAML structure is already established
- **Clear error messages** - Errors point to specific YAML nodes, not parsing failures
- **Predictable behavior** - Always return valid YAML data structures

Atmos detects the tags in the stack manifests and executes the corresponding functions.

:::info
YAML supports three types of data: core, defined, and user-defined.

- **Core types**: Universally supported, including floats, integers, strings, lists, and maps.
- **Defined types**: Advanced types like binary data, specified in the YAML standard but not always supported.
- **User-defined types**: Custom extensions for classes, structures, and functions. Atmos leverages user-defined types to implement its custom functions and extend YAML's capabilities.
  :::

## Use-cases

- The [**`!terraform.output`**](/functions/yaml/terraform.output) YAML function allows you to
  [access component outputs (remote state) directly within Atmos stack manifests](/stacks/remote-state).
  Note that this requires initializing each component (`terraform/tofu init`), which initializes all Terraform/OpenTofu
  modules and downloads all Terraform/OpenTofu providers, which may significantly impact performance. Consider using `!store` or `!terraform.state` functions instead, which don't have this performance penalty.

- The [**`!terraform.state`**](/functions/yaml/terraform.state) YAML function reads outputs **directly from the configured Terraform or OpenTofu backend**, without initializing providers or running Terraform — it's **very fast** and currently supports [S3 and local backends](/components/terraform/backends) for accessing [remote state](/stacks/remote-state).

- The [**`!store`**](/functions/yaml/store) YAML function allows reading the values from a
  remote [store](/cli/configuration/stores) (e.g. SSM Parameter Store, Artifactory, etc.)
  into Atmos stack manifests

- The [**`!store.get`**](/functions/yaml/store.get) YAML function allows retrieving arbitrary keys
  directly from a [store](/cli/configuration/stores)
  without following the Atmos stack/component/key naming convention.
  This is useful for accessing values stored by external systems
  or for retrieving global configuration that doesn't belong to a specific component.

- The [**`!include`**](/functions/yaml/include) YAML function allows downloading local or remote files from different sources,
  and assigning the file contents or individual values to the sections in Atmos stack manifests.

- The [**`!template`**](/functions/yaml/template) YAML function is designed to [evaluate and inject outputs containing maps or lists](/functions/template/atmos.Component#handling-outputs-containing-maps-or-lists)
  into the YAML document, whether generated by the [**`atmos.Component`**](/functions/template/atmos.Component) template function or any Go template.

- The [**`!exec`**](/functions/yaml/exec) YAML function is used to execute shell scripts and assign
  the results to the sections in Atmos stack manifests.

- The [**`!env`**](/functions/yaml/env) YAML function is used to retrieve environment variables
  and assign them to the sections in Atmos stack manifests.

- The [**`!repo-root`**](/functions/yaml/repo-root) YAML function is used to retrieve the
  root directory of the Atmos repository.

- The [**`!cwd`**](/functions/yaml/cwd) YAML function is used to retrieve the current working directory
  where Atmos is executed from. Useful when you need paths relative to where you run Atmos
  rather than relative to the configuration file.

- The [**`!random`**](/functions/yaml/random) YAML function generates a cryptographically secure random integer
  within a specified range, useful for generating random port numbers or IDs.

- The [**`!literal`**](/functions/yaml/literal) YAML function preserves values exactly as written,
  bypassing all template processing. Use it to pass template-like syntax (e.g., `{{...}}` or `${...}`)
  to downstream tools like Terraform, Helm, or ArgoCD without Atmos attempting to evaluate them.

- The [**`!aws.account_id`**](/functions/yaml/aws.account-id) YAML function retrieves the AWS account ID
  of the current caller identity using STS GetCallerIdentity.

- The [**`!aws.caller_identity_arn`**](/functions/yaml/aws.caller-identity-arn) YAML function retrieves the full ARN
  of the current AWS caller identity using STS GetCallerIdentity.

- The [**`!aws.caller_identity_user_id`**](/functions/yaml/aws.caller-identity-user-id) YAML function retrieves the unique user ID
  of the current AWS caller identity using STS GetCallerIdentity.

- The [**`!aws.region`**](/functions/yaml/aws.region) YAML function retrieves the AWS region
  from the current SDK configuration.

:::tip
You can combine [Atmos Stack Manifest Templating](/templates) with Atmos YAML functions within the same stack configuration.
Atmos processes templates first, followed by YAML functions, enabling you to dynamically provide parameters to the YAML functions.
:::

## Atmos sections supporting YAML functions

You can use the YAML functions in all Atmos stack manifest sections:

- `vars`
- `settings`
- `env`
- `metadata`
- `command`
- `component`
- `providers`
- `overrides`
- `backend`
- `backend_type`
- `remote_state_backend`
- `remote_state_backend_type`

## Examples

**File:** `stack.yaml`

```yaml
components:
  terraform:
    component2:
      settings:
        s1: !exec echo 's1'
      env:
        ENV_VAR_1: !template '{{ (atmos.Component "component3" .stack).settings.env.ENV_VAR_1 }}'
      vars:
        # Handle the output of type list from the `atmos.Component` template function
        test_1: !template '{{ toJson (atmos.Component "component1" "plat-ue2-dev").outputs.test_list }}'

        # Handle the output of type map from the `atmos.Component` template function
        test_2: !template '{{ toJson (atmos.Component "component1" .stack).outputs.test_map }}'

        # Execute the shell script and assign the result to the `test_3` variable
        test_3: !exec echo 42

        # Execute the shell script to get the `test_label_id` output from the `component1` component in the stack `plat-ue2-dev`
        test_4: !exec atmos terraform output component1 -s plat-ue2-dev --skip-init -- -json test_label_id

        # Execute the shell script to get the `test_map` output from the `component1` component in the current stack
        test_5: !exec atmos terraform output component1 -s {{ .stack }} --skip-init -- -json test_map

        # Execute the shell script to get the `test_list` output from the `component1` component in the current stack
        test_6: !exec atmos terraform output component1 -s {{ .stack }} --skip-init -- -json test_list

        # Get the `test_label_id` output of type string from the `component1` component in the stack `plat-ue2-dev`
        test_7: !terraform.output component1 plat-ue2-dev test_label_id

        # Get the `test_label_id` output of type string from the `component1` component in the current stack
        test_8: !terraform.output component1 {{ .stack }} test_label_id

        # Get the `test_list` output of type list from the `component1` component in the current stack
        test_9: !terraform.state component1 {{ .stack }} test_list

        # Get the `test_map` output of type map from the `component1` component in the current stack
        test_10: !terraform.state component1 {{ .stack }} test_map

        # Retrieve the value of an environment variable
        api_key: !env API_KEY

        # Include a local file
        config: !include ./dev-config.yaml

        # Download a remote JSON file with .json extension and query data using YQ
        # Note: URLs without extensions are treated as text, so use URLs with appropriate extensions
        github_data: !include ./github-meta.json .api

        # Generate a random port number between 1024 and 65535
        app_port: !random 1024 65535

        # Get the current AWS account ID
        aws_account_id: !aws.account_id

        # Get the ARN of the current AWS caller identity
        aws_caller_arn: !aws.caller_identity_arn

        # Get the unique user ID of the current AWS caller identity
        aws_user_id: !aws.caller_identity_user_id

        # Get the current AWS region
        aws_region: !aws.region

        # Preserve template syntax for downstream tools (Terraform, Helm, ArgoCD)
        helm_annotation: !literal "{{ .Values.ingress.class }}"
        terraform_var: !literal "${var.hostname}"
        db_users: [!literal "{{external.email}}", !literal "{{external.admin}}"]
```

## Native Atmos YAML Functions

Atmos natively supports the following YAML functions:
