Benny
Benny

Reputation: 879

Iterate over a dictionary and changing the value of each item based on a condition in a loop in Ansible

I have a file in host_vars folder which looks like this:

tags:
  tag1: value1 
  tag2: value2 
  tag3: ''  <<-- This is an empty value which I would like to fill with some string

Now I wanted to go through each of these items and check if the value is empty and if it is add "NA" as a string to it, I used the following code for this:

 - name: Clean any Tag inconsistencies
  set_fact:
    tags: "{{ item }} + NA"
  when: (item | length == 0)
  with_items: tags
 - debug: var=tags

However, this does not do anything, it just prints the same list when checking the debug. What is wrong with this approach?

Edit:

I changed my code to respect that I am using a dictionary. This is my current approach. It prints out the values with key and name but does not change any item. I also tried using the jinja default filter which did not do anything:

- name: "Clean Tags"
  set_fact:
    tags: "{{ (tags | default('NA', true)) }}"                               
  loop: "{{ tags | dict2items }}"

What I would like to achieve in the end is that it checks each dict value and if it is empty, it should add the value "NA" to it, so in the end above tags dictionary will look like this:

tags:
  tag1: value1 
  tag2: value2 
  tag3: 'NA'

Upvotes: 1

Views: 1282

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67959

The play below

- hosts: localhost
  vars:
    my_tags:
      tag1: value1
      tag2: ''
      tag3: ''
  tasks:
    - set_fact:
        my_tags: "{{ my_tags|combine(dict(my_empty_tags|product(['NA']))) }}"
      vars:
        my_empty_tags: "{{ my_tags|dict2items|json_query(query) }}"
        query: "[?value == ''].key"
    - debug:
        var: my_tags

gives (abridged)

  my_tags:
    tag1: value1
    tag2: NA
    tag3: NA

The same result can be achieved without json_query. Replace the task vars

      vars:
        my_empty_tags: "{{ my_tags|dict2items|
                           selectattr('value', 'eq', '')|
                           map(attribute='key')|
                           list }}"

tags is a playbook's keyword. You should have seen:

[WARNING]: Found variable using reserved name: tags

Q: "What happens in the set_fact section?"

A: Decompose the filter. First, create the product of the empty tags and the string 'NA'

    - debug:
        msg: "{{ my_empty_tags|product(['NA'])|list }}"

gives

  msg:
  - - tag2
    - NA
  - - tag3
    - NA

Then create dictionaries from the items in the list

    - debug:
        msg: "{{ dict(my_empty_tags|product(['NA'])) }}"

gives

  msg:
    tag2: NA
    tag3: NA

The last step in the filter is to combine the dictionaries.

Upvotes: 2

Related Questions