Skip to Content

3 ways to create a dictionary variable in Ansible

In Ansible, a dictionary (also known as a hash, map, or associative array) is a data type that allows you to store and manipulate key-value pairs.

Dictionaries are commonly used to represent configuration data, variables, and other structured information in Ansible playbooks.

A dictionary in Ansible is enclosed in curly braces {} and consists of key-value pairs separated by colons :.

Keys are strings, and values can be of any data type, including strings, numbers, lists, or even nested dictionaries.

Dictionaries are commonly used in tasks and playbooks to pass and manipulate data, configure tasks, and conditionally execute tasks based on the values of certain keys.

They provide a flexible and powerful way to store and manage structured data in Ansible, allowing you to customize the behavior of your playbooks based on dynamic input.

Here’s an example of a dictionary in Ansible:

---
- name: Configure Users
  hosts: localhost
  gather_facts: no
  tasks:
    - name: Create dictionary of users
      set_fact:
        users:
          user1:
            name: jdoe
            uid: 1001
            state: present
          user2:
            name: jsmith
            uid: 1002
            state: absent
          user3:
            name: jbrown
            uid: 1003
            state: present

In this example, a dictionary called users is defined using the set_fact module. The users dictionary contains three users, each represented as a key-value pair, with the key as the username and the value as a dictionary containing the user’s properties such as name, uid, and state.

how to check if a variable is a dict in ansible?

In Ansible, you can use the type_debug filter to check if a variable is a dictionary. Here’s an example:

---
- name: Check if Variable is a Dictionary
  hosts: localhost
  gather_facts: no
  vars:
    var1:
      key1: value1
      key2: value2
    var2: "Not a dictionary"
  tasks:
    - name: Check if var1 is a dictionary
      debug:
        msg: "var1 is a dictionary."
      when: "'dict' in (var1|type_debug)"

    - name: Check if var2 is a dictionary
      debug:
        msg: "var2 is not a dictionary."
      when: "'dict' not in (var2|type_debug)"

In this example, we define two variables var1 and var2, where var1 is a dictionary and var2 is a string. We then use the type_debug filter in combination with the in and not in operators to check the type of each variable.

In the first task, we use the when condition to check if var1 is a dictionary by checking if the string ‘dict’ is present in the output of (var1|type_debug). If it is, the task will display a message saying “var1 is a dictionary.”

In the second task, we use the when condition to check if var2 is not a dictionary by checking if the string ‘dict’ is not present in the output of (var2|type_debug). If it is not, the task will display a message saying “var2 is not a dictionary.”

Define a dict using the vars section in Ansible playbook

There are a few methods to create dictionaries in Ansible.

we can define a dictionary using the vars section in your playbook. Here’s an simple example:

---
- name: Define a Simple Dictionary
  hosts: localhost
  gather_facts: no
  vars:
    my_dict:
      key1: value1
      key2: value2
      key3: value3
  tasks:
    - name: Display the Dictionary
      debug:
        var: my_dict
    - name: Display the keys in Dictionary
      debug:
        var: my_dict.keys()
    - name: Display the values in Dictionary
      debug:
        var: my_dict.values()  


Output:

PLAY [Define a Simple Dictionary] **************************************************************************************************************************************************************************************

TASK [Display the Dictionary] ******************************************************************************************************************************************************************************************
ok: [localhost] => {
    "my_dict": {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }
}
  

TASK [Display the keys in Dictionary] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "my_dict.keys()": [
        "key1",
        "key2",
        "key3"
    ]
}

TASK [Display the values in Dictionary] **********************************************************************************************************************************************************************************
ok: [localhost] => {
    "my_dict.values()": [
        "value1",
        "value2",
        "value3"
    ]
}

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

In this example, we define a dictionary my_dict using the vars section with keys (key1, key2, key3) and their corresponding values (value1, value2, value3).

We then use the debug module to display the contents of the my_dict dictionary. You can access the values from the dictionary using the my_dict.key syntax within your tasks or templates as needed.

Let’s see a another example.

---
- name: Define and Use a Dictionary
  hosts: localhost
  gather_facts: no
  vars:
    server_config:
      server1:
        ip: 192.168.1.101
        port: 8080
        user: admin
      server2:
        ip: 192.168.1.102
        port: 8080
        user: admin
      server3:
        ip: 192.168.1.103
        port: 8080
        user: admin
  tasks:
    - name: Display server configuration
      debug:
        var: server_config

    # You can use the dictionary values in tasks
    - name: Configure servers
      debug:
        msg: "Configuring server {{ item.key }} with IP: {{ item.value.ip }}, Port: {{ item.value.port }}, User: {{ item.value.user }}"
      loop: "{{ server_config|dict2items }}"

    - name: Configure servers
      debug:
        msg: "Configuring server  {{ item.key }}"
      with_dict :  "{{ server_config }}"

    - name: Configure servers
      debug:
        msg: "Configuring server  {{ item.value }}"
      with_dict :  "{{ server_config }}"
      


PLAY [Define and Use a Dictionary] *************************************************************************************************************************************************************************************

TASK [Display server configuration] ************************************************************************************************************************************************************************************
ok: [localhost] => {
    "server_config": {
        "server1": {
            "ip": "192.168.1.101",
            "port": 8080,
            "user": "admin"
        },
        "server2": {
            "ip": "192.168.1.102",
            "port": 8080,
            "user": "admin"
        },
        "server3": {
            "ip": "192.168.1.103",
            "port": 8080,
            "user": "admin"
        }
    }
}

TASK [Configure servers] ***********************************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'server1', 'value': {'ip': '192.168.1.101', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server server1 with IP: 192.168.1.101, Port: 8080, User: admin"
}
ok: [localhost] => (item={'key': 'server2', 'value': {'ip': '192.168.1.102', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server server2 with IP: 192.168.1.102, Port: 8080, User: admin"
}
ok: [localhost] => (item={'key': 'server3', 'value': {'ip': '192.168.1.103', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server server3 with IP: 192.168.1.103, Port: 8080, User: admin"
}

TASK [Configure servers] ***********************************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'server1', 'value': {'ip': '192.168.1.101', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server  server1"
}
ok: [localhost] => (item={'key': 'server2', 'value': {'ip': '192.168.1.102', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server  server2"
}
ok: [localhost] => (item={'key': 'server3', 'value': {'ip': '192.168.1.103', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server  server3"
}

TASK [Configure servers] ***********************************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'server1', 'value': {'ip': '192.168.1.101', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server  {'ip': '192.168.1.101', 'port': 8080, 'user': 'admin'}"
}
ok: [localhost] => (item={'key': 'server2', 'value': {'ip': '192.168.1.102', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server  {'ip': '192.168.1.102', 'port': 8080, 'user': 'admin'}"
}
ok: [localhost] => (item={'key': 'server3', 'value': {'ip': '192.168.1.103', 'port': 8080, 'user': 'admin'}}) => {
    "msg": "Configuring server  {'ip': '192.168.1.103', 'port': 8080, 'user': 'admin'}"
}

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

In this example, we define a dictionary server_config using the vars section with keys representing the server names (server1, server2, server3) and values representing their respective IP addresses, ports, and users.

We then use the debug module to display the contents of the server_config dictionary. You can access the values from the dictionary using the item.value syntax within a loop, as shown in the second task, where we loop through the server_config dictionary using the dict2items filter and display the values in a message. You can replace the debug task with your actual configuration tasks as needed.

create dict variable with set_fact function in ansible

In Ansible, the set_fact module is used to set variables dynamically during playbook execution.

To define a dictionary variable using the set_fact module, you can follow the syntax below:

- hosts: localhost
  tasks:
    - name: Create dictionary
      set_fact:
        my_dict:
          key1: value1
          key2: value2
          key3: value3 

In this example, the set_fact module is used to define a dictionary named my_dict in the playbook and set its key-value pairs.

or you can use the following way.

- hosts: localhost
  tasks:
    - name: Create dictionary
      set_fact:
        my_dict: "{{ {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'} }}"
    - debug:
        var: my_dict
        
        
PLAY [localhost] *******************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create dictionary] ***********************************************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] ***********************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "my_dict": {
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
    }
}

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0         
view raw

In this case, it sets the “my_dict” variable to a dictionary with three key-value pairs: ‘key1’ with the value ‘value1’, ‘key2’ with the value ‘value2’, and ‘key3’ with the value ‘value3’. The dictionary is defined using YAML syntax within double curly braces “{{ }}” as an Ansible expression.

Here’s an example of creating a dictionary with the given key-value pairs using set_fact module in Ansible:

- hosts: localhost
  tasks:
    - name: Create dictionary
      set_fact:
        my_dict:
          name: David
          website: howtouselinux.com

    - name: Display dictionary values
      debug:
        var: my_dict

PLAY [localhost] *******************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create dictionary] ***********************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Display dictionary values] ***************************************************************************************************************************************************************************************
ok: [localhost] => {
    "my_dict": {
        "name": "David",
        "website": "howtouselinux.com"
    }
}

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

In this example, we are using the set_fact module in Ansible to create a dictionary named my_dict with two key-value pairs: name: David and website: howtouselinux.com. The my_dict variable is then available for use in subsequent tasks or roles within the playbook.

You can run this playbook on the localhost inventory (which represents the local machine) using the ansible-playbook command. When the playbook is run, the my_dict dictionary will be created and its values will be displayed using the debug module, allowing you to verify that the dictionary has been created successfully with the given key-value pairs.

Create a dictionary using the default filter in Ansible

Let’s see an example.

- hosts: localhost
  tasks:
    - name: Create dictionary
      set_fact:
        my_dict: "{{ my_dict | default({}) | combine({'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}) }}"
    - debug:
        var: my_dict  

This playbook has one play that targets the “localhost” host, meaning it will be executed locally on the machine where Ansible is running. The play consists of two tasks:

The first task is named “Create dictionary” and it uses the set_fact module to create a dictionary named “my_dict”. The set_fact module is used to set a fact (a variable) in Ansible. In this case, it sets the “my_dict” variable to a dictionary created using the default filter and the combine filter.

The default filter sets the value of “my_dict” to an empty dictionary if it is not already defined, and the combine filter is used to merge the empty dictionary with a new dictionary containing three key-value pairs: ‘key1’ with the value ‘value1’, ‘key2’ with the value ‘value2’, and ‘key3’ with the value ‘value3’. The resulting “my_dict” variable will be a dictionary with these key-value pairs.

The second task is named “debug” and it uses the debug module to display the value of the “my_dict” variable. The var parameter specifies the variable to be displayed, which is “my_dict” in this case. This task will print the contents of the “my_dict” dictionary during the playbook execution for debugging purposes.

In summary, this playbook creates a dictionary named “my_dict” with three key-value pairs, and then displays the contents of this dictionary using the “debug” task.

Here are more info about combine filter, .

In Ansible, the combine filter is used to merge two or more dictionaries into a single dictionary. It allows you to concatenate multiple dictionaries, overriding or extending the values of the keys in the process.

The syntax for using the combine filter is as follows:

dict1 | combine(dict2)

where dict1 and dict2 are the dictionaries that you want to merge. dict1 will be the base dictionary, and dict2 will be merged into it.

Here are some key points to understand about the combine filter:

The combine filter does not modify the original dictionaries. Instead, it returns a new dictionary that is the result of the merge.

If keys in dict2 already exist in dict1, their values will be overridden with the values from dict2.

If keys in dict2 do not exist in dict1, they will be added to the merged dictionary.

If you pass more than two dictionaries to the combine filter, they will be merged in the order they are provided, from left to right. This means that dictionaries on the right will take precedence over dictionaries on the left in case of key conflicts.

The combine filter can also be used with multiple dictionaries, like this:

dict1 | combine(dict2) | combine(dict3) | ...

This allows you to merge more than two dictionaries into a single dictionary.

Here’s an example of using the combine filter in an Ansible playbook:

- name: Merge dictionaries
  hosts: localhost
  tasks:
    - name: Create dict1
      set_fact:
        dict1:
          key1: value1
          key2: value2

    - name: Create dict2
      set_fact:
        dict2:
          key2: new_value2
          key3: value3

    - name: Merge dict1 and dict2
      set_fact:
        merged_dict: "{{ dict1 | combine(dict2) }}"

    - debug:
        var: merged_dict
     
 PLAY [Merge dictionaries] **********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create dict1] ****************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create dict2] ****************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Merge dict1 and dict2] *******************************************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] ***********************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "merged_dict": {
        "key1": "value1",
        "key2": "new_value2",
        "key3": "value3"
    }
}

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0     

In this example, two dictionaries “dict1” and “dict2” are created using the set_fact module. Then, the combine filter is used to merge “dict1” and “dict2” into a new dictionary called “merged_dict”. The resulting “merged_dict” will contain the keys and values from both “dict1” and “dict2”, with the value of “key2” overridden by “new_value2” from “dict2”. Finally, the “merged_dict” is displayed using the “debug” task.

Let’s see one more example.

---
- name: Dictionary playbook example
  hosts: localhost
  tasks:

    - name: Create and Add items to dictionary
      set_fact: 
          userdata: "{{ userdata | default({}) | combine({ item.key: item.value }) }}"
      loop:
        - key: 'Name'
          value: 'David'
        - key: 'Email'
          value: '[email protected]'
        - key: 'Nationality'
          value: 'US'

    - name: Display the Dictionary
      debug:
        var: userdata



PLAY [Dictionary playbook example] *************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Create and Add items to dictionary] ******************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'Name', 'value': 'David'})
ok: [localhost] => (item={'key': 'Email', 'value': '[email protected]'})
ok: [localhost] => (item={'key': 'Nationality', 'value': 'US'})

TASK [Display the Dictionary] ******************************************************************************************************************************************************************************************
ok: [localhost] => {
    "userdata": {
        "Email": "[email protected]",
        "Name": "David",
        "Nationality": "US"
    }
}

PLAY RECAP *************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

    

Aysad Kozanoglu

Friday 1st of December 2023

very usefull and helpfull documentation to understand dict lists with using in playbooks.

the different ways explains use case scenarios for diffent type of implementation.