Ansible переменная регистрируется в двух задачах либо одна, либо другая
У меня есть роль Ansible, которая управляет некоторыми компонентами Zabbix. Эта роль имеет набор задач для проверки типа и версии агента Zabbix (1 или 2).
- name: Check if Zabbix Agent 2 is installed
ansible.builtin.shell:
cmd: which zabbix_agent2
register: zabbix_agent2_installed
ignore_errors: yes
- name: Check if Zabbix Agent D is installed
ansible.builtin.shell:
cmd: which zabbix_agentd
when: not zabbix_agent2_installed.stdout
register: zabbix_agentd_installed
ignore_errors: yes
- name: Stop if there is no Agent installed
ansible.builtin.fail:
msg: |
Zabbix Agent is not installed.
when: not zabbix_agent2_installed.stdout and not zabbix_agentd_installed.stdout and zabbix_component == "agent"
- name: Fetch Zabbix Agent 2 version
ansible.builtin.shell:
cmd: zabbix_agent2 -V | grep "zabbix_agent" | cut -d' ' -f3
when: zabbix_agent2_installed.stdout
register: zabbix_agent_ver_old
failed_when: zabbix_agent_ver_old.stderr
- name: Fetch Zabbix Agent D version
ansible.builtin.shell:
cmd: zabbix_agentd -V | grep "zabbix_agent" | cut -d' ' -f4
when: not zabbix_agentd_installed.skipped
register: zabbix_agent_ver_old
failed_when: zabbix_agent_ver_old.stderr
Когда я запускаю playbook, переменная "zabbix_agentd_ver_old" регистрируется дважды в двух последних задачах с тем же именем. Даже если последняя задача пропущена, переменная регистрируется как пропущенная.
TASK [zabbix_ansible : Check if Zabbix Agent 2 is installed] *********************************************************************
changed: [zbxproxy]
TASK [zabbix_ansible : Check if Zabbix Agent D is installed] *********************************************************************
skipping: [zbxproxy]
TASK [zabbix_ansible : Stop if there is no Agent installed] **********************************************************************
skipping: [zbxproxy]
TASK [zabbix_ansible : Fetch Zabbix Agent 2 version] *****************************************************************************
changed: [zbxproxy]
TASK [zabbix_ansible : Fetch Zabbix Agent D version] *******************************************************************************
skipping: [zbxproxy]
TASK [zabbix_ansible : ansible.builtin.debug] ************************************************************************************
ok: [zbxproxy] =>
zabbix_agent_ver_old:
changed: false
skip_reason: Conditional result was False
skipped: true
Я хочу избежать изменения имени переменной, поэтому мне нужно, чтобы переменная была зарегистрирована в одной из двух последних задач, а не в обеих.
Как вообще пропустить последнее задание, включая регистрацию, если его условие не выполнено?
2 ответа
Множественные задачи, ветвящиеся с небольшими вариациями, раздражают при написании в Ansible, и они выполняются медленно из-за накладных расходов на задачу. Иногда это можно свернуть в один скрипт с переменными. Вот моя быстрая и грязная попытка с несколькими строками оболочки. Отказ от ответственности: я не проверял это с zabbix, хотя общие понятия не сложны.
- name: Fetch Zabbix Agent version
register: zabbix_agent_ver_result
shell:
# Note use of YAML multiple line to embed script http://yaml-multiline.info/
# Although much longer should probably go in a separate file with and a script task
cmd: |
WHICHZAGENT=$(which zabbix_agent2 || which zabbix_agentd );
case $WHICHZAGENT in
*agent2 )
VERFIELD=3
;;
*agentd )
VERFIELD=4
;;
esac;
${WHICHZAGENT} --version | grep 'zabbix_agent' | cut -d' ' -f ${VERFIELD};
- name: zabbix agent ver short name
set_fact:
zabbix_agent_ver: "{{ zabbix_agent_ver_result.stdout }}"
- debug:
var: zabbix_agent_ver
Register: перезапишет переменную (в области хоста), существующую с тем же именем. Дело не в том, что пропущенные задачи ничего не возвращают, они возвращают статус «пропущено». Это сбивает с толку, я рекомендую всем зарегистрированным именам переменных задачи быть уникальными.
В задачах Ansible писать ветвящийся поток не так удобно, как во многих языках программирования.
См. также: community.zabbix В коллекции есть community.zabbix.zabbix_agent роль с другим способом ведения дел. Установите пакет агента из репозитория программного обеспечения, а затем создайте шаблон файла конфигурации, в котором большинство возможных значений могут быть получены из переменных. Очень распространенные шаблоны для Ansible.
Лично я предпочитаю стиль установки пакетов программного обеспечения, которые должны быть там. Он может исправить отсутствующие агенты, и вам не придется выяснять, что находится на хосте.
Это типичный случай для нестандартных фактов . Создайте динамические факты о Zabbix, добавив исполняемый скрипт zabbix.fact в /etc/ansible/facts.d на удаленных хостах.
Приведенный ниже скрипт проверяет наличие исполняемых файлов в списке zabbix_agent_list и возвращает словарь JSON ansible_custom_zabix_agent с существующими элементами, разделенными запятыми.
shell> cat zabbix.fact
#!/bin/sh
zabbix_agent_list="/usr/local/bin/zabbix_agentd \
/usr/local/bin/zabbix_agent2"
zabbix_agent=""
for a in $zabbix_agent_list; do
if [ -x $a ]; then
zabbix_agent="$zabbix_agent $a"
fi
done
zabbix_agent=`echo $zabbix_agent | tr ' ' ','`
echo '{"'ansible_custom_zabix_agent'"': '"'$zabbix_agent'"}'
Распространите этот сценарий на удаленные хосты, которым вы хотите предоставить этот специальный факт.
- hosts: all
tasks:
- file:
state: directory
dest: /etc/ansible/facts.d
- copy:
src: zabbix.fact
dest: /etc/ansible/facts.d
mode: '0755'
Попробуй это. Учитывая удаленные хосты test_11 и test_13
shell> ssh admin@test_11 ls -1 /usr/local/bin/zabbix_agent2
/usr/local/bin/zabbix_agent2
shell> ssh admin@test_13 ls -1 /usr/local/bin/zabbix_agentd
/usr/local/bin/zabbix_agentd
Игра ниже
- hosts: all
vars:
zabbix_agent: "{{ ansible_facts.ansible_local.zabbix.ansible_custom_zabix_agent|
default('')|
split(',')|
first }}"
tasks:
- setup:
gather_subset: local
- debug:
var: ansible_facts.ansible_local.zabbix.ansible_custom_zabix_agent
- debug:
var: zabbix_agent
дает (в сокращении)
ok: [test_11] =>
zabbix_agent: /usr/local/bin/zabbix_agent2
ok: [test_13] =>
zabbix_agent: /usr/local/bin/zabbix_agentd
Примечания:
По умолчанию факты собираются для каждой игры . В этом случае вам не придется запускать настройку задачи .
Если вы отключили сбор фактов или хотите обновить факты, запустите настройку задачи.
Ускорьте сбор фактов, ограничившись местными фактами. Набор
gather_subset: local
Переменная ansible_custom_zabix_agent будет добавлена в словарь ansible_facts.ansible_local.zabbix.ansible_custom_zabix_agent
ansible_local: локальные факты ( collect_subset: local )
zabbix: факты, собранные zabbix.fact
ansible_custom_zabix_agent: список агентов, разделенных запятыми
Переменная ansible_custom_zabix_agent в приведенном выше примере может быть списком элементов, разделенных запятыми, если существуют дополнительные элементы из списка zabbix_agent_list . В этом случае разделите строку на список и возьмите первый элемент.
Вы можете добавить в скрипт другие функции и возвращать другие факты.
Для написания скриптов можно использовать любой другой язык, например Python.
Пример скрипта Python
shell> cat /etc/ansible/facts.d/apache.fact
#!/usr/bin/env python3
import shutil
import subprocess
import yaml
import json
def main():
name = 'httpd'
path = shutil.which(name)
if path:
result = subprocess.run([name, '-v'], capture_output=True, text=True)
version = yaml.safe_load(result.stdout)
else:
version = None
ansible_custom_facts = {
'path': path,
'version': version
}
print(json.dumps(ansible_custom_facts))
if __name__ == '__main__':
main()
дает, например,
ansible_facts.ansible_local:
apache:
path: /usr/local/sbin/httpd
version:
Server built: unknown
Server version: Apache/2.4.46 (FreeBSD)