âPlaybooks Are YAMLâ
âBas Meijer, Lorin Hochstein, Rene Moser, âAnsible: Up and Runningâ
Core Idea
Playbooks are YAML, so master the grammar: lists and dictionaries, block strings, when to quote, and anchors for reuse, plus Ansibleâs own string idioms.
- Core structures: lists and dictionaries, with Ansibleâs practice of quoting strings.
- Multi-line strings: literal, folded, and the chomping and indentation indicators.
- Ansible-specific: pure YAML instead of string arguments, quoting rules, and YAML anchors with aliases.
You donât need to quote YAML strings. Even if there are spaces, you donât need to quote them.In some scenarios in Ansible, you will need to quote strings. It is a good practice just to quote all strings.
List
Indent list items and delimit them with hyphens. Lists have a name followed by a colon, as follows:
shows:
- My Fair Lady
- Oklahoma
- The Pirates of PenzanceInline list
shows: [ My Fair Lady , Oklahoma , The Pirates of Penzance ]Dictionaries
he YAML specification calls them mappings, but we call them dictionaries here to be consistent with the Ansible documentation
address:
street: Main Street
appt: 742
city: Logan
state: OhioInline Dictionaries
address: { street: Main Street, appt: '742', city: Logan, state: Ohio}Multi-line Strings
You can format multi-line strings with YAML by combining a block style indicator (| or >), a block chomping indicator (+ or â), and even an indentation indicator (1 to 9).
# Block style | (literal): Preserves newlines and spacing
literal_example: |
This is line 1
This is line 2
This is line 3 with preserved line breaks.
# Block style > (folded): Collapses newlines into spaces
folded_example: >
This is line 1
This is line 2
This is line 3, but newlines are folded into spaces.
# Block chomping indicator + (keep): Retains trailing newlines
keep_trailing_example: |+
This is line 1
This is line 2
# Block chomping indicator - (strip): Removes all trailing newlines
strip_trailing_example: |-
This is line 1
This is line 2
# Indentation indicator (1 to 9): Specifies indentation levels
indented_example: >
This is line 1
This is line 2 (indented by 2 spaces)
This is line 3 (indented by 4 spaces)The greater-than sign (
>) immediately following thecommand:module directive tells YAML âautomatically quote the next set of indented lines as one long string, with each line separated by a spaceâ.
Pure YAML Instead of String Arguments
Lorin likes this style:
- name: Ensure nginx is installed
package: name=nginx update_cache=trueBas prefers pure-YAML style, because that can be parsed for correctness by yamllint:
- name: Ensure nginx is installed
package:
name: nginx
update_cache: trueWhat is
---Â in YAML?
- In YAML,Â
---Â signifies the beginning of a new document. Itâs especially useful when multiple YAML documents are present in a single file.- Optional but Recommended: While not strictly required for single-document YAML files (like most Ansible playbooks), includingÂ
---Â is a good practice. It enhances readability and clearly delineates the start of the YAML content.
Quoting in Ansible Strings
If you reference a variable right after specifying the module, the YAML parser will misinterpret the variable reference as the beginning of an inline dictionary. Consider the following example:
- name: Perform some task
command: {{ myapp }} -a fooAnsible will try to parse the first part of {{ myapp }} -a foo as a dictionary instead of a string, and will return an error. In this case, you must quote the arguments:
- name: Perform some task
command: "{{ myapp }} -a foo"A similar problem arises if your argument contains a colon. For example:
- name: Show a debug message
debug:
msg: The debug module will print a message: neat, eh?The colon in the msg argument trips up the YAML parser. To get around this, you need to quote the entire msg string. Single and double quotes are both correct; Bas prefers to use double quotes when the string has variables:
- name: Show a debug message
debug:
msg: "The debug module will print a message: neat, eh?"This will make the YAML parser happy. Ansible supports alternating single and double quotes, so you can do this:
- name: Show escaped quotes
debug:
msg: '"The module will print escaped quotes: neat, eh?"'
- name: Show quoted quotes
debug:
msg: "'The module will print quoted quotes: neat, eh?'""This yields the expected output:
TASK [Show escaped quotes] *****************************************************
ok: [localhost] ==> {
"msg": "\"The module will print escaped quotes: neat, eh?\""
}
TASK [Show quoted quotes] ******************************************************
ok: [localhost] ==> {
"msg": "'The module will print quoted quotes: neat, eh?'"
}YAML Anchors (&) and Aliases (*)
list - How to merge YAML arrays? - Stack Overflow
Donât Repeat Yourself with Anchors, Aliases and Extensions in Docker Compose Files | by King Chung Huang | Medium
YAML provides anchors (&) and aliases (*) to reuse parts of a configuration, reducing duplication and improving maintainability.
- Anchor (
&name) â Defines a reusable block. - Alias (
*name) â References an existing anchor.
# Repetitive Code
server1:
name: web-server
image: nginx
ports:
- "80:80"
server2:
name: web-server
image: nginx
ports:
- "80:80"# DRY Code
server-config: &common-config
image: nginx
ports:
- "80:80"
server1:
<<: *common-config
name: web-server-1
server2:
<<: *common-config
name: web-server-2
image: apache # Overriding the image for server2# Using Anchors in Lists
ports: &default-ports
- "80:80"
- "443:443"
server1:
image: nginx
ports: *default-ports# You can combine multiple anchors for greater flexibility.
base-config: &base
image: nginx
restart: always
logging-config: &logging
logging:
driver: "json-file"
options:
max-size: "10m"
server:
<<: [*base, *logging]
name: web-server