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