Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a key/value to a dict in an ansible playbook, conditional

Let's say I want to add InterestingVar dict key and the associated value when the variable test_var exists (passed with -e in command line), how can I do that ?

# ansible-playbook ./add_to_dict_on_condition.yml -i 127.0.0.1, -e env=test -e test_var=123
- hosts: localhost
  gather_facts: no
  vars:
    - tags:
        InterestingVar: "{{test_var}}" # How to omit this line if test_var == '' ?
        Name: xxx
        Env: "{{ env }}"

  tasks:
    - debug: var=tags

I tested

 InterestingVar: "{{test_var|default(omit)}}

but I get :

"InterestingVar": "__omit_place_holder__caca01e207397883640613b08e8ce3a8fbdd6"

instead of nothing.

Any help will be greatly appreciated.

I use ansible 1.8

like image 804
Gilles Quenot Avatar asked Oct 28 '15 14:10

Gilles Quenot


People also ask

How do you write an Ansible dictionary?

Creating a Dictionary in Ansible using the default function You can also create a dictionary within the task itself and define some variable as a dictionary by default, the default value kicks in when there was no previous declaration for the same variable.

How do you define an item in Ansible?

Ansible with_items is a lookup type plugins which is used to return list items passed into it. Actual plugin name is items. Ansible have different plugin types, further these plugin types have various plugins in each category. One such plugin type is lookup, which allows ansible to access data from outside resources.

What are dictionaries in Ansible?

Dictionary variables are another type of ansible variable additionally supported in the playbook. To define the dictionary variable, simply ident the key-value pair just below the dictionary variable.


1 Answers

The only thing I can think of is to combine dictionaries with a set_fact task when your condition is met. This relies on the combine filter introduced in Ansible 2.0.

- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    - tags:
        Name: xxx
        Env: "{{ env }}"
    - optional_tags:
        InterestingVar: "{{ test_var }}"

  tasks:
    - name: combine tags
      set_fact:
        tags: "{{ tags | combine(optional_tags) }}"
      when: test_var is defined

    - name: debug tags
      debug: var=tags

Which outputs the following then test_var is not defined:

vagrant@Test-02:~$ ansible-playbook -i "localhost," conditional_key.yml -e "env=test"

PLAY ***************************************************************************

TASK [combine tags] ************************************************************
skipping: [localhost]

TASK [debug tags] **************************************************************
ok: [localhost] => {
    "changed": false,
    "tags": {
        "Env": "test",
        "Name": "xxx"
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

And this output when it is defined:

vagrant@Test-02:~$ ansible-playbook -i "localhost," conditional_key.yml -e "env=test" -e "test_var=123"

PLAY ***************************************************************************

TASK [combine tags] ************************************************************
ok: [localhost]

TASK [debug tags] **************************************************************
ok: [localhost] => {
    "changed": false,
    "tags": {
        "Env": "test",
        "InterestingVar": "123",
        "Name": "xxx"
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

If you are unable to use 2.0+ then another option may be to change Ansible's hash behaviour to merge dictionaries rather than overriding them by setting:

hash_behaviour=merge

in your ansible.cfg.

With this you could then use something like this:

- hosts: localhost
  connection: local
  gather_facts: no
  vars:
    - tags:
        Name: xxx
        Env: "{{ env }}"
    - tags:
        InterestingVar: "{{ test_var }}"

  tasks:
    - name: debug tags
      debug: var=tags

With your vars defined in the following files:

vagrant@Test-01:~$ cat tags.yml
tags:
  Name: xxx
  Env: "{{ env }}"
vagrant@Test-01:~$ cat optional_tags.yml
tags:
  InterestingVar: "{{ test_var }}"

This then gives you the output you want but you have to make sure not to include optional_vars.yml when you don't have test_var defined:

vagrant@Test-01:~$ ansible-playbook -i "localhost," conditional_key.yml -e "env=test" -e "test_var=123" [email protected] -e@optional_tags.yml

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

TASK: [debug tags] ************************************************************
ok: [localhost] => {
    "var": {
        "tags": {
            "Env": "test",
            "InterestingVar": "123",
            "Name": "xxx"
        }
    }
}

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0

Be aware that when using this approach any expected overriding of dictionaries through inheritance will now merge the dictionaries instead so this may not be all that useful for anyone overriding things in their inventories.

like image 170
ydaetskcoR Avatar answered Sep 29 '22 03:09

ydaetskcoR