Ansible со значением по умолчанию для подэлементов
у меня есть определение vars, как это:
sites:
 - site: mysite1.com
   exec_init:
    - "command1 to exec"
    - "command2 to exec"
 - site: mysite2.com
тогда у меня есть игра со следующей задачей
- name: Execute init scripts for all sites
  shell: "{{item.1}}"
  with_subelements: 
    - sites
    - exec_init
  when: item.0.exec_init is defined
идея здесь в том, что у меня будет несколько определений "сайта" с десятками других свойств в моих vars, затем я хотел бы выполнить несколько команд сценария оболочки для тех сайтов, у которых "exec_init" определен
делая это таким образом, он просто всегда пропускает выполнение задачи, я пробовал это во всех комбинациях, которые я могу себе представить, но я просто не могу получить это сработает...
это правильный способ сделать это? может быть, я пытаюсь достичь чего-то, что не имеет смысла?
Спасибо за помощь
4 ответов
Hm, похоже, имеет неоднородную структуру для элементов в sites что-то with_subelements не нравится. А также, что item не содержит подэлемент, указанный в списке with_subelements. Вы можете сделать несколько вещей:
- убедитесь, что есть - exec_initсписок, даже если он пустой.- with_subelementsпропускает элементы с пустыми подэлементами. Я думаю, что это лучший вариант, хотя немного неудобно при написании план.
- 
не используйте with_subelementsи batch execute yourself (немного некрасиво):- name: Execute init scripts for all sites shell: "echo '{{item.exec_init | join(';')}}' | bash" when: item.exec_init is defined with_items: sites
- 
настройка with_subelementsчтобы это были элементы с отсутствующим подэлементом. Вы можете скопировать оригинал (мой в/usr/local/lib/python2.7/dist-packages/ansible/runner/lookup_plugins/with_subelements.py) и положить его вlookup_pluginsкаталог рядом с вашей playbook, под другим именем (скажемsubelements_missingok.py). Затем измените строку 59 от:raise errors.AnsibleError("could not find '%s' key in iterated item '%s'" % (subelement, item0))в: continueтогда ваша задача может выглядеть так это: - name: Execute init scripts for all sites debug: "msg={{item.1}}" with_subelements_missingok: - sites - exec_init
есть другой способ, попробуйте:
- debug: "var=item"
  with_subelements:
    - "{{ sites | selectattr('exec_init', 'defined') | list }}"
    - exec_init
спасибо: https://github.com/PublicaMundi/ansible-plugins/blob/master/lookup_plugins/subelements_if_exist.py
и еще один способ, с флагом skip_missing (Ansible 2.0+):
- name: nested loop skip missing elements
  with_subelements:
    - sites
    - exec_init
    - flags:
      skip_missing: true
это работает для меня. Я использую версию 2.1.1 Просто добавьте третий элемент в список подэлементов, как показано
- name: Iterate over something with_subelements: - "{{ unit }}" - config - skip_missing: True
