#ansible
#ansible
Вопрос:
Пример сборника —
---
- hosts: localhost
vars:
lesson:
name: Physics
students:
- Bob
- Joe
tasks:
- name: Display student names
debug:
msg: '{{ item }}'
loop: "{{ lesson.students }}"
when: item | default("")
Приведенный выше сборник задач хорошо подходит для вывода имен учащихся.
Однако, если входные данные изменяются (как указано ниже) таким образом, что имена учащихся не определены, возникает ошибка. Есть ли простой способ заставить playbook пропустить эту задачу, если список не определен в соответствии с приведенными ниже данными? Я понимаю, что это сработает, если на входе будет указано students: [] , но поскольку этот ввод поступает от простых пользователей, они этого не узнают. Большое спасибо!
vars:
lesson:
name: Physics
students:
Ошибка: фатальная: [localhost]: СБОЙ! =>
сообщение: «Недопустимые данные, переданные в «цикл», для этого требуется список, вместо этого получил это: . Подсказка: если вы передали список / dict только из одного элемента, попробуйте добавить wantlist=True к вашему вызову поиска или используйте q / query вместо lookup .
Обновление — я пробовал приведенные ниже варианты, но все равно получаю ту же ошибку —
---
- hosts: localhost
vars:
lesson:
name: Physics
students:
tasks:
- name: Display student names variation 1
debug:
msg: '{{ item }}'
loop: "{{ lesson.students }}"
when: lesson.students is iterable
- name: Display student names variation 2
debug:
msg: '{{ item }}'
loop: "{{ lesson.students }}"
when: lesson.students is not none
- name: Display student names variation 3
debug:
msg: '{{ item }}'
loop: "{{ lesson.students }}"
when: ( item | default("") ) or ( item is not none )
Комментарии:
1. Директива «loop» вычисляется перед условием «when».
Ответ №1:
Реальная проблема заключается в том, что loop
требуется список, даже если это пустой список.
Если ваш параметр имеет значение undefined / None / empty string , он существует, но не является списком, и ваше условие when никогда не будет оценено, потому что цикл выдаст ошибку до того, как она будет достигнута.
В таких случаях вы должны по умолчанию использовать для вашего var пустой список, что приведет к циклу размером 0, эквивалентному пропуску задачи.
Поскольку ваш var определен, но None
вам нужно использовать второй необязательный параметр, чтобы default
также заменялись пустые / ложные значения
Примечание: я использовал короткий псевдоним d
default
в приведенных ниже примерах
- name: Display student names
debug:
msg: '{{ item }}'
loop: "{{ lesson.students | d([], true) }}"
Хорошей практикой здесь, которая бы пресекла эту ошибку в зародыше, было бы последовательное объявление данных либо:
- вообще не объявлять ключ и использовать простое значение по умолчанию, т.е.
# ... # vars: lesson: name: Physics # ... # loop: "{{ lesson.students | d([]) }}"
- объявите пустой список для ключа, а не
None
для значения, т.е.# ... # vars: lesson: name: Physics students: [] # ... # loop: "{{ lesson.students }}"
Мое первое предложение в любом случае является самым безопасным в этом случае и будет работать для всех приведенных выше объявлений vars.
Комментарии:
1. Единственный ответ, работающий для меня
Ответ №2:
Существует разница между undefined
переменной и переменной, имеющей None
значение.
Когда вы задаете имя переменной, но оставляете правую часть пустой. Переменная определена, но для нее установлено значение NoneType
.
Таким образом, ваше when:
условие должно иметь дополнительную проверку на NoneType
:
- hosts: localhost
vars:
lesson:
name: Physics
students:
tasks:
- name: Display student names
debug:
msg: '{{ item }}'
loop: "{{ lesson.students }}"
when: ( item | default("") ) or ( item is not none )
Это даст:
skipping: [localhost] => (item=None)
Комментарии:
1. Спасибо за ответ. Я протестировал это и все равно получаю ту же ошибку. Моя версия ansible — 2.9.4.
2. Это не будет работать, когда
lessons.students
существует, но нет (как в ответе OP, и вы поняли), потому что цикл оценивается первым и выдает ошибку (т. Е. «Мне нужен список !!!!») до того, как будет достигнуто какое-либо условие when. Смотрите мой ответ.