Skip to main content

!literal

The !literal Atmos 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.

Usage​

# Preserve template syntax for downstream tools
value: !literal "{{external.email}}"

# In lists
db_users:
- !literal "{{external.email}}"
- !literal "{{external.admin}}"

# Inline array syntax
users: [!literal "{{user1}}", !literal "{{user2}}"]

# Multiline values
script: !literal |
#!/bin/bash
echo "Hello ${USER}"
export VAR={{value}}

Arguments​

value (required)

The string value to preserve. Can be quoted, unquoted, or use YAML multiline syntax. The value is passed through exactly as written, without any template processing.

Examples​

Terraform templatefile() Variables​

Pass variables to Terraform templates without Atmos processing them:

components:
terraform:
ec2-instance:
vars:
user_data_template: !literal "#!/bin/bash\necho ${hostname}"
config_template: !literal "${var.environment}-config.json"

Helm Values​

Pass Helm template expressions that should be processed by Helm, not Atmos:

components:
terraform:
helm-release:
vars:
ingress_annotations: !literal "{{ .Values.ingress.class }}"
service_name: !literal "{{ .Release.Name }}-api"

ArgoCD and External Templating Systems​

Preserve template syntax for external tools like ArgoCD, Jsonnet, or Kustomize:

components:
terraform:
argocd-app:
vars:
config_url: !literal "{{external.config_url}}"
sync_policy: !literal "{{argocd.sync.policy}}"

Documentation and Examples​

Include template examples in your configuration without evaluation:

metadata:
example_usage: !literal "Use {{component}} to reference components"
template_syntax: !literal "Variables use ${var.name} syntax"

Regex Patterns​

Preserve patterns containing brace-like syntax:

vars:
filename_pattern: !literal "user_{id}_{timestamp}.log"
validation_regex: !literal "^[a-z]+\\d{3}$"

Inline Arrays​

Use !literal in inline array syntax for compact configuration:

vars:
db_users: [!literal "{{external.email}}", !literal "{{external.admin}}", regular_user]
allowed_patterns: [!literal "${prefix}*", !literal "*${suffix}"]

Nested Structures​

Use !literal within deeply nested configurations:

components:
terraform:
application:
vars:
templates:
helm:
annotations: !literal "{{ .Values.ingress.class }}"
terraform:
user_data: !literal "#!/bin/bash\necho ${hostname}"
argocd:
config: !literal "{{external.config}}"

Step Definitions and atmos.yaml​

!literal works in atmos.yaml and in the step definitions of custom commands, workflows, and hooks. Atmos renders step fields as Go templates when a step runs, so a Starlark script or shell command that contains {{ }} text would fail with a template error. Tag the field with !literal and Atmos runs it exactly as written.

commands:
- name: report
description: Print a summary
steps:
- name: summary
type: script
interpreter: starlark
# The braces below are Starlark, not Atmos templates.
script: !literal |
rows = [{"name": "vpc", "status": "ok"}]
for row in rows:
print("{} is {}".format(row["name"], row["status"]))
print("Atmos templates look like {{ .vars.stage }}")
- name: echo
command: !literal echo "Atmos templates look like {{ .vars.stage }}"

The same tag works on steps in a workflow manifest, including steps nested in parallel and matrix groups, and on the steps of a step or steps hook.

These step fields honor !literal:

script
The body of a script step, in every step context.
command
The command of a shell step, and the string command of a custom command step.
interpreter
The interpreter of a script step.
working_directory
The working directory of a step.
env values
Each value in a step's env map, tagged on its own, such as GREETING: !literal "{{ not a template }}".

Other fields of the same step keep rendering as templates, so you can combine a literal script with a templated env value. Only a field that carries the tag directly is literal: tagging a whole env map or steps list has no effect on the entries inside it.

!literal on stack vars, settings, env, and similar data keeps its existing behavior: Atmos clears the tag and keeps the value as written.

Why !literal is Needed​

Atmos processes Go templates and Gomplate expressions in stack configurations. When your configuration contains {{...}} or ${...} syntax intended for downstream tools, Atmos attempts to evaluate these expressions, causing errors or unexpected behavior.

The Problem​

Without !literal, these configurations fail or produce incorrect results:

# This fails - Atmos tries to evaluate {{external.email}}
db_users:
- "{{external.email}}"

# This fails - Atmos tries to evaluate ${hostname}
user_data: "echo ${hostname}"

Previous Workarounds​

Before !literal, users had to use awkward escaping:

# Workaround 1: Double braces (fragile, hard to read)
db_users:
- "{{'{{external.email}}'}}"

# Workaround 2: Template escaping (verbose)
db_users:
- "{{ `{{external.email}}` }}"

The Solution​

!literal provides a clean, self-documenting solution:

# Clear intent, preserves value exactly
db_users:
- !literal "{{external.email}}"

Comparison with Other Functions​

FunctionPurposeTemplate Processing
!literalPreserve value exactlyBypassed
!templateEvaluate Go templates and convert JSON to YAML typesEnabled
!execExecute shell commandsCommand may contain templates
!envRead environment variablesNo template processing

Common Use Cases​

  • Terraform: Pass ${var.name} or templatefile() syntax
  • Helm: Pass {{ .Values.* }} template expressions
  • ArgoCD: Pass {{external.*}} application set parameters
  • Kustomize: Pass patch placeholders
  • Documentation: Include template syntax examples
  • Regex/Patterns: Preserve brace patterns in strings
When to Use !literal

Use !literal whenever you need to pass {{...}}, ${...}, or similar template syntax to a downstream tool. If Atmos is trying to evaluate something it shouldn't, !literal is the solution.