fan
fan

Reputation: 2364

Ansible how to ignore undefined item in a loop

I'm trying to have list of paths. The variables folder (web_folder, app_folder or db_folder ) may be undefined and is expected to be undefined.
In this case I just don't want the undefined value in the the list.

- set_fact: root_paths="{{ root_paths | default([]) + [ item ] }}"
  loop:
    - "{{ web_folder }}"
    - "{{ app_folder }}"
    - "{{ db_folder }}"
  when: item is defined

When I do this I get an error message 'The task includes an option with an undefined variable.'

I can make this work if I define default values e.g. '-' and replace the when condition with

when: item != '-'

I don't like this solution.

I tried a few things like

Any suggestions?

Upvotes: 1

Views: 5700

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68004

Q: I get an error message 'The task includes an option with an undefined variable.' I can make this work if I define default values e.g. '-' and replace the when condition with when: item != '-'. I don't like this solution.

A: The expansion of an undefined variable causes the error. Either the variables are tested explicitly or default filter is used.

Testing each variable is cumbersome

  tasks:
    - set_fact:
        folders_defined: []
    - set_fact:
        folders_defined: "{{ folders_defined + [web_folder] }}"
      when: web_folder is defined
    - set_fact:
        folders_defined: "{{ folders_defined + [app_folder] }}"
      when: app_folder is defined
    - set_fact:
        folders_defined: "{{ folders_defined + [db_folder] }}"
      when: db_folder is defined
    - debug:
        var: folders_defined

The next option (which is very similar to the one you don't like) is to test a default value assigned to undefined variables. For example, the playbook below tests default empty string. If necessary fit this condition to your needs.

- hosts: localhost
  vars:
    web_folder: /my/web/folder
    app_folder: /my/app/folder
    folders: [web_folder, app_folder, db_folder]
  tasks:
    - set_fact:
        folders_defined: "{{ folders_defined|default([]) +
                             [lookup('vars', item)] }}"
      loop: "{{ folders }}"
      when: lookup('vars', item, default='')|length > 0
    - debug:
        var: folders_defined

gives

ok: [localhost] => {
    "folders_defined": [
        "/my/web/folder", 
        "/my/app/folder"
    ]
}

Upvotes: 1

ilias-sp
ilias-sp

Reputation: 6685

The variables folder (web_folder, app_folder or db_folder ) may be undefined and is expected to be undefined.

you could use the default filter to initialize them to an empty array, in case they are not defined:

- set_fact: root_paths="{{ root_paths | default([]) + [ item ] }}"
  loop:
    - "{{ web_folder | default([]) }}"
    - "{{ app_folder | default([]) }}"
    - "{{ db_folder | default([]) }}"
  when: item is defined

hope it helps.

Upvotes: 1

Related Questions