|
|||||||
Как собрать нестандартный факт с нескольких хостов в одну переменную?
Время создания: 29.05.2023 08:39
Текстовые метки: ansible, факт, fact, set_fact, нестандартный, одна, переменная, собрать, накопить, хост, несколько, фильтр
Раздел: Компьютер - Linux - Оркестрация - Ansible
Запись: xintrea/mytetra_syncro/master/base/1685338765ntf19n6lnz/text.html на raw.github.com
|
|||||||
|
|||||||
Имеется следующая задача: Необходимо создать такой плейбук, который получит версию нестандартного Linux-дистрибутива из специализированного файла на каждом хосте. Чтобы узнать версию дистрибутива, в bash можно давать команду cat /etc/dist_version. Другими словами, заранее проверяемая версия на хостах неизвестна. То есть, нельзя просто написать сравнение с заранее заданным значением. Надо собрать все значения со всех хостов, и потом проверить, чтобы все версии на хостах совпадали. Как это сделать? В качестве решения можно предложить следующий код: # Здесь для каждого хоста сохраняется вывод в переменную os_version - hosts: test_hosts tasks: - name: "get OS version" command: "cat /etc/redhat-release" register: os_version - debug: var: os_version # Здесь заводится пустой словарь и в цикле в него добавляются значения - hosts: localhost vars: os_versions: {} tasks: - name: "OS version in one dict" set_fact: os_versions: "{{ hostvars[item]['os_version']['stdout'] | append_to_dict(os_versions, item) }}" with_items: "{{ groups['test_hosts'] }}" - debug: var: os_versions В этом коде надо обратить внимание, что есть переменная os_version (без "s" на конце), в которую попадает версия ОС. Значения этой переменной для каждого хоста хранится в hostvars[item]['os_version'] после выполнения первого блока. А так же во втором блоке есть переменная os_versions (с "s" на конце), которая является словарем ИмяХоста -> Версия ОС. Эта переменная заполняется в цикле, организованным через with_items. Вывод будет выглядеть примерно так: ok: [localhost] => { "os_versions": { "test01": "Red Hat Enterprise Linux release 8.2 (Ootpa)", "test02": "Red Hat Enterprise Linux release 8.2 (Ootpa)", "test03": "Red Hat Enterprise Linux release 8.2 (Ootpa)" } } Для работы вышеуказанного кода потребуется самописный фильтр. Для это в каталоге с плейбуками необходимо создать подкаталог /filter_plugins, в котором разместить файл core.py следующего содержания: def append_to_dict(_val, _dict, _hostname): _dict[_hostname] = _val return _dict class FilterModule(object): def filters(self): return { 'append_to_dict': append_to_dict } Вызов функции фильтра происходит следующим образом. В качестве первого аргумента _val устанавливается значение, стоящее слева от вертикальной черты "|" в Jinja-выражении. То есть, в обычной трактовке, первый аргумент - это фильтруемый объект. В данном случае передается hostvars[item]['os_version']['stdout']. Однако это значение передается как фильтруемый объект только для того, чтобы передать в функцию фильтра в качестве первого аргумента значение версии операционной системы для перебираемого хоста. В качестве последующих аргументов передаются значения, указанные в скобках после имени фильтра в Jinja-выражении. То есть, в качестве _dict буден передан словарь os_versions, в качестве _hostname будет передан item (то есть, имя перебираемого хоста). Примечение: те же самые действия можно сделать даже не создавая самописный фильтр. Достаточно воспользоваться стандартным фильтром combine: - name: "OS version in one dict" set_fact: os_versions: "{{ os_versions | combine( { item: hostvars[item]['os_version']['stdout']} ) }}" with_items: "{{ groups['test_hosts'] }}" Фильр combine складывает два словаря, возвращая один общий словарь. Далее уже несложно сделать еще один фильтр is_equal_value_in_dict, который обработает os_versions и если обнаружит, что в этом словаре все значения версии ОС совпадают, вернет True, или в противном случае False. Это значение можно использовать в модуле fail, вот так: - name: Проверка соответствия версий ОС fail: msg: Некоторые версии ОС не совпадают с другими when: "{{ os_versions|is_equal_value_in_dict }}" Кстати, проверить что словарь содержит только одинаковые значения, можно стандартными методами и фильтрами, без написания самодельных. |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|