Only execute task if variable is defined when using with_items?

I want the following task to be executed only when etc_hosts is defined

  • name: other important hosts in /etc/hosts
    lineinfile: >
    dest=‘/etc/hosts’
    regexp=‘.*{{ item.hostname }}$’
    line=‘{{ item.address }} {{ item.hostname }}’
    state=‘present’
    with_items:
  • ‘{{ etc_hosts }}’

All these tasks fail for one reason or another.

  • name: other important hosts in /etc/hosts
    lineinfile: >
    dest=‘/etc/hosts’
    regexp=‘.*{{ item.hostname }}$’
    line=‘{{ item.address }} {{ item.hostname }}’
    state=‘present’
    when: etc_hosts is defined
    with_items:
  • ‘{{ etc_hosts }}’

FAILED! => {“failed”: true, “msg”: “ERROR! ‘etc_hosts’ is undefined”}

  • name: other important hosts in /etc/hosts
    lineinfile: >
    dest=‘/etc/hosts’
    regexp=‘.*{{ item.hostname }}$’
    line=‘{{ item.address }} {{ item.hostname }}’
    state=‘present’
    when: {{ etc_hosts }} is defined
    with_items:
  • ‘{{ etc_hosts }}’

The offending line appears to be:

state=‘present’
when: {{ etc_hosts }} is defined
^ here

  • name: other important hosts in /etc/hosts
    lineinfile: >
    dest=‘/etc/hosts’
    regexp=‘.*{{ item.hostname }}$’
    line=‘{{ item.address }} {{ item.hostname }}’
    state=‘present’
    when: “{{ etc_hosts }}” is defined
    with_items:
  • ‘{{ etc_hosts }}’

The offending line appears to be:

state=‘present’
when: “{{ etc_hosts }}” is defined
^ here

Hm, the doc only gives an example on how to fail the whole play in a controlled way if the variable is not defined, Is that an option for you?

tasks:
    - shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
      when: foo is defined

    - fail: msg="Bailing out. this play requires 'bar'"
      when: bar is undefined

when: executes per item so you cannot use it to bypass a with_items:
undefined, use default filter:

with_items: "{{etc_hosts|default() }}"

this returns an empty list, which will skip the loop and the task.