Ansible with_subelements default value

Hm, looks like having a non-uniform structure for the elements in sites is something with_subelements doesn't like. And also that item doesn't contain the subelement you specified in the with_subelements list. You can do several things:

  1. Make sure to have an exec_init list, even if it's empty. with_subelements will skip items with empty subelements. I think this is the best option, although a bit inconvenient when writing the playbook.

  2. Don't use with_subelements and batch execute yourself (a bit ugly):

    - name: Execute init scripts for all sites
      shell: "echo '{{item.exec_init | join(';')}}' | bash"
      when: item.exec_init is defined
      with_items: sites
    
  3. Customize with_subelements so that it would items with the missing subelement. You can copy the original (mine is in /usr/local/lib/python2.7/dist-packages/ansible/runner/lookup_plugins/with_subelements.py) and put it in a lookup_plugins directory next to your playbook, under a different name (say subelements_missingok.py). Then change line 59 from:

    raise errors.AnsibleError("could not find '%s' key in iterated item '%s'" % (subelement, item0))
    

    to:

    continue
    

    Then your task can look like this:

    - name: Execute init scripts for all sites
      debug: "msg={{item.1}}"
      with_subelements_missingok:
        - sites
        - exec_init
    

And yet another way, with the skip_missing flag (Ansible 2.0+):

- name: nested loop skip missing elements
  with_subelements:
    - sites
    - exec_init
    - flags:
      skip_missing: true

The valid solution here (considering ansible 2.7+) is to use loop instead of with_subelements. As with loop you can apply subelements filter, that has skip_missing option (ie what @hkariti suggested in option 3 but in proper way).

So, code should look like:

- name: Execute init scripts for all sites
  shell: "{{ item.1 }}"
  loop: "{{ sites | subelements('exec_init', skip_missing=True) }}"

There's another way, try:

- debug: "var=item"
  with_subelements:
    - "{{ sites | selectattr('exec_init', 'defined') | list }}"
    - exec_init

Thanks to: https://github.com/PublicaMundi/ansible-plugins/blob/master/lookup_plugins/subelements_if_exist.py