!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
scriptstep, in every step context. command- The command of a shell step, and the string
commandof a custom command step. interpreter- The interpreter of a
scriptstep. working_directory- The working directory of a step.
timeout- The timeout of a step.
envvaluesEach value in a step's
envmap, tagged on its own, such asGREETING: !literal "{{ not a template }}". This covers theenvof aparallelormatrixstep too, and the command-levelenvof a custom command.
A step written as a plain string works as well: - !literal 'echo "{{ not a template }}"' is a command step whose text
Atmos does not render.
A !literal tag on any other field of a step fails when the configuration loads. The error names the field and the step
and lists the supported fields: !literal is not supported on field "type" of step "build"; it is supported on script, command, interpreter, working_directory, timeout, and on individual env values. Atmos performs this check for the
steps of custom commands.
A script or command loaded with !include.raw is used exactly as written, with no Go
template rendering, so it needs no !literal tag. A script loaded with !include is still rendered as a template. When
a rendering error comes from an included script that contains {{, the error hint tells you to move that text into a
load()ed module or to include the file with !include.raw.
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
| Function | Purpose | Template Processing |
|---|---|---|
!literal | Preserve value exactly | Bypassed |
!template | Evaluate Go templates and convert JSON to YAML types | Enabled |
!exec | Execute shell commands | Command may contain templates |
!env | Read environment variables | No template processing |
Common Use Cases
- Terraform: Pass
${var.name}ortemplatefile()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
!literalUse !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.