August 2, 2021

Ansible, списки, костыли и магия

В рамках задачи писал с нуля роль для Ansible, чтобы пользователями в БД управлять. Среди прочего - надо ей принять список из командной строки по запуску, а потом сравнить его с структурой данных из yml-файла и сделать действия. И вот на этот моменте нашлось забавное (нет) поведение Ansible, которые пришлось подпирать костылями.

Если краткое - имеем мы yml-файл вида:

users: - name: user1 data: bla-bla - name: user2 data: meow-meow - name: user3 data: auf-auf

Комментарии думаю излишни, у нас здесь набор users с тремя элементами.

И плейбук у нас тоже конечно есть, скажем:

- debug: var: userslist

- debug: msg: "{{ item.name }}" when: item.name in userslist with_items: "{{ users }}"

Сюда мы закинули две задачи. Первая печатает переменную userslist всю, вторая уже в случае вхождения одного списка в другой (а мы рассчитываем на два списка) он выдаст нам эту запись

Запускаем мы все это дело командой волшебной:

ansible-playbook myplaybook.yml -e "userslist=['user12','user2']" -e "ссылка-на-наш-yaml-с-пользователями"

И что мы видим? Сначала мы видим что да, мы ему передали лист с двумя записями - "users12" и "user2". А после, вместо того, чтобы выдать нам только user2, ведь никакого user12 нет, он нам выдает и user1. Почему? Потому что он входит как подстрока в user1.

...и здесь мы понимаем, что оператор in с списками в Ansible работает как-то своеобразно. Как лечить, чтобы было по красоте? Без понятия, может через месяц и буду знать, но пока мой уровень владения Ansible-магией слабоват для этих чар.

...и поэтому на помощь к нам приходит костыль! И выглядит он вот так:

- set_fact: usersinwork: "{{ userslist.split(',') }}"

- debug: msg: usersinwork

- debug: msg: "{{ item.name }}" when: item.name in usersinwork with_items: "{{ users }}"

Ну и команда запуска меняется на:

ansible-playbook myplaybook.yml -e "userslist=user12,user2" -e "ссылка-на-наш-yaml-с-пользователями"

И вот теперь все работает как надо, и печатает только user2. Хотя мы получаем вроде такой же лист, 1-в-1, но обрабатывается он совсем иначе и корректно.

Почему же так? It's magic!, чо. Может в будущем я все же найду это в глубинах сакральных знаний работы Ansible, но явно не сегодня.