Bootstrap FreeKB - Ansible - Create variable, list or dictionary using set_fact
Ansible - Create variable, list or dictionary using set_fact

Updated:   |  Ansible articles

Following are the differet ways that variables, lists and dictionaries can be set in Ansible. This list is in the order of precedence, where the option higher in the list takes precedence over options lower in the list.

In this example, set_fact is used so that the "foo" variable contains a value of "Hello World" and the debug module is be used to print the variable.

AVOID TROUBLE

The -e or --extra-vars command line option or Extra Variables in Tower will take precedence over set_fact.

---
- hosts: localhost
  tasks:
  - set_fact: 
      foo: "Hello World"

  - debug:
      var: foo
...

 

Which should produce the following.

ok: [localhost] => {
    "foo": "Hello World"
}

 


In this example, set_fact is used to create a list that contains two values, "Hello" and "World".

---
- hosts: localhost
  tasks:
  - set_fact:
      list: "[ 'Hello', 'World']"

  - debug: 
      msg: "{{ list }}"
...

 

Which should produce the following.

ok: [localhost] => {
    "msg": [
        "Hello",
        "World"
    ]
}

 


In this example, set_fact is used to create a dictionary that contains two key/value pairs.

---
- hosts: localhost
  tasks:
  - set_fact:
      mydict:
        - { key: 'fruit', value: 'apple' }
        - { key: 'veggy', value: 'pepper' }

  - debug: 
      msg: "{{ mydict }}"
...

 

Which should produce the following.

ok: [localhost] => {
    "mydict": {
        "key": "fruit",
        "value": "apple",
        "key": "veggy",
        "value": "pepper"
    }
}

 


create multiple variables using a with_items loop

Here is how you can define multiple variables using a with_items loop. In this example, the "foo" variable will contain a value of "Hello" and the "bar" variable will contain a value of "World".

---
- hosts: locahost
  tasks:
  - set_fact: 
      "{{ item.key }}": "{{ item.value }}"
    with_items:
    - { key: "foo", value: "Hello" }
    - { key: "bar", value: "World" }
...

 


Redefine variable

Let's say you used the vars plugin to give the "foo" key a value of "Hello". set_fact can be used to update the value of the "foo" key. In this example, the "foo" key will be updated to have a value of "World". set_fact will take precedence over vars.

---
- hosts: localhost
  vars:
    foo: "Hello"
  tasks:
  - set_fact: 
      foo: "World"

  - debug:
      var: foo
...

 


From an Ansible Fact to a variable

Commonly, set_fact is used to create a variable of an Ansible Fact. For example, let's say the df command on server1 returns the following.

[john.doe@server1 ~]# df
Filesystem                           1K-blocks     Used Available Use% Mounted on
/dev/sda1                               372607   170989    177862  50% /boot
/dev/sda2                               129774     6994    122780   6% /

 

Here is how you would create a variable named foo that contains the available bytes of /dev/sda1 (177862).

---
- hosts: localhost
  tasks:
  - set_fact:
      size: "{{ item.size_available }}"
    with_items: "{{ ansible_mounts }}"

  - debug:
      var: size
...

 

Which should return the following.

TASK [debug]
ok: [localhost] => {
    "size": "177862"
}

 

AVOID TROUBLE

Notice 177862 is wrapped in double quotes, meaning that the size variable contains a string, not an integer, which can be confirmed using the type_debug filter. This is because Jinja2 templating (the double curly braces) always returns a string. However, you can apply some of type filter, such as the bool or int filter in a when statement because Jinja2 templating cannot be used in a when statement.

---
- hosts: localhost
  tasks:
  - set_fact:
      size: "{{ item.size_available }}"
    with_items: "{{ ansible_mounts }}"

  - debug:
      msg: size is greater than 123456
    when: size | int > 123456
...

 


Setting fact based on a condition (when parameter / if else statement)

The when parameter can be used to set fact based on a condition. In this example, if the managed node hostname begins with a "d" then the environment variable will contain a value of "development.

---
- hosts: localhost
  tasks:
  - set_fact: 
      env: development
    when: inventory_hostname|lower is regex '^d.*'

  - set_fact: 
      env: production
    when: inventory_hostname|lower is regex '^p.*'
...

 

However, it may be more efflective to use a jinja2 if / else statement so that you have a single task that sets the fact.

---
- hosts: localhost
  tasks:
  - set_fact: 
      env: "{% if inventory_hostname|lower is regex '^d.*' %}development{% elif inventory_hostname|lower is regex '^p.*' %}producution{% endif %}"
...

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 3f88a8 in the box below so that we can be sure you are a human.