Post

YAML Anchors

In Ansible, you can define variables in a variety of places, including inventory files, playbook files, and role defaults and vars files. When defining variables, you can use YAML anchors and aliases to reduce repetition and make your code more readable.

1
2
3
4
5
6
7
8
9
10
11
vars:
  # Define an anchor called "common_vars"
  common_vars: &common_vars
      version: 2.0
      name: My Application

  # Define a variable that uses the "common_vars" anchor and
  # adds additional information
  prod_vars: &prod_vars
      <<: *common_vars
      environment: production

Here’s an example of using anchors and aliases in an Ansible playbook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
---
- name: Example 1
  hosts: localhost
  gather_facts: false
  vars:
    # Define an anchor called "common_vars"
    common_vars: &common_vars
      version: 2.0
      name: My Application
      servers:
        - server1

    # Define a variable that uses the "common_vars" anchor and
    # adds additional information
    app1_vars:
      <<: *common_vars
      environment: production
      servers:
        - prod_svr1
        - prod_svr2

    # Define another variable that uses the "common_vars" anchor and
    # adds additional information
    app2_vars:
      <<: *common_vars
      environment: staging
      servers:
        - stg_svr1

  tasks:
    # Use the variables in tasks
    - name: Print app 1
      debug:
        var: app1_vars

    - name: Print app 2
      debug:
        var: app2_vars
...

In this example, we define an anchor called “common_vars” that contains some common variables used by multiple applications. We then use the alias syntax * to define two new variables, “app1_vars” and “app2_vars”, that use the “common_vars” anchor and add additional information specific to each application.

Note that the “servers” key in the “app1_vars” and “app2_vars” variables overrides the “servers” key in the “common_vars” anchor, so each application has its own list of servers.

Finally, we use the variables in tasks to display the configuration of each application. Below is the output for each application, which includes the common variables and the additional information specific to each application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
user@box:~/$ ansible-playbook example1.yml

PLAY [Example 1] **************************************************************
TASK [Print app 1] ************************************************************
ok: [localhost] => {
    "app1_vars": {
        "environment": "production",
        "name": "My Application",
        "servers": [
            "prod_svr1",
            "prod_svr2"
        ],
        "version": 2.0
    }
}

TASK [Print app 2] ************************************************************
ok: [localhost] => {
    "app2_vars": {
        "environment": "staging",
        "name": "My Application",
        "servers": [
            "stg_svr1"
        ],
        "version": 2.0
    }
}

PLAY RECAP ********************************************************************

Using anchors and aliases can be particularly helpful when defining complex variables that are used in multiple places in your playbook or role. Instead of copy-pasting the same data multiple times, you can define an anchor once and then use it throughout your code. This can make your code more readable, easier to maintain, and less error-prone.

Though anchors and aliases are really handy it can be easy over use them or used them when there is no benefit from using them. Here is one example that highlights a situation where I have found myself using an anchor with no benefit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
---
- name: Example 2
  hosts: localhost
  gather_facts: false
  vars:

    app1_vars: &app1_vars
      environment: production
      servers:
        - server1

    app2_vars: &app2_vars
      environment: staging
      servers:
        - server2
    # Define a list using the alias
    app_list1:
      - <<: *app1_vars
      - <<: *app2_vars

    # Define a list with YAML variables
    app_list2:
      - ""
      - ""


  tasks:
    # Use the variables in tasks
    - name: Print App List 1
      debug:
        var: app_list1

    - name: Print App List 2
      debug:
        var: app_list2
...

In this example, we define an anchor called “app1_vars” and “app2_vars” that contains some common variables describing our applications. We then use the alias syntax to define a list of our applications, “app_list1”, that use the anchors of app1 and app2. Next we define the list “app2_list” using the regular YAML variable syntax.

Here both lists that have been created are identical. The use of an anchor in a situation like this may just be making the code harder to read and possibly a bit harder for the next person to understand what the goal was.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
user@box:~/$ ansible-playbook example2.yml
PLAY [Example 3] **************************************************************

TASK [Print App List 1] *******************************************************
ok: [localhost] => {
    "app_list1": [
        {
            "environment": "production",
            "servers": [
                "server1"
            ]
        },
        {
            "environment": "staging",
            "servers": [
                "server2"
            ]
        }
    ]
}

TASK [Print App List 2] *******************************************************
ok: [localhost] => {
    "app_list2": [
        {
            "environment": "production",
            "servers": [
                "server1"
            ]
        },
        {
            "environment": "staging",
            "servers": [
                "server2"
            ]
        }
    ]
}

PLAY RECAP ********************************************************************

In summary, YAML anchors and aliases are a powerful feature that can help you reduce repetition in your Ansible playbooks and roles and make them more readable and maintainable. By using anchors and aliases, you can avoid copy-pasting the same data multiple times and make it easier to update your variables in the future.

All of the examples shown are available here if you would like a copy.

This post is licensed under CC BY 4.0 by the author.