Управление задачами с условиями и циклами

AnsibleBeginner
Практиковаться сейчас

Введение

Один плейбук может выбирать разную работу для каждого хоста без дублирования всего списка задач. Вы объедините логические входные данные политики с фактами ОС, обработаете каждый элемент структурированного списка и используете настоящие зарегистрированные результаты обследования для независимого решения об одобрении. Настоящие файлы и явная очистка сделают наблюдаемыми и выбранное, и пропущенное поведение.

Выбирайте задачи по логическим входным данным и фактам

На этом шаге вы заставите один многократно используемый плейбук действовать по-разному на двух хостах и явно удалять результаты при отключении политики.

В подготовленном окружении отдельный входной файл одобрения /home/automation/maintenance-approved есть только на web1. Пока оставьте его без изменений; первое решение политики использует логическую переменную и обнаруженные факты ОС.

Перейдите в проект управляющего узла:

cd /home/labex/project

Файлы переменных хостов связывают данные с каждым именем инвентаря. Записывайте логические значения YAML без кавычек, чтобы они оставались значениями true/false, а не строками:

cat > host_vars/web1.yml <<'YAML'
maintenance_enabled: true
YAML
cat > host_vars/web2.yml <<'YAML'
maintenance_enabled: false
YAML

Ключевое слово when вычисляет логическое выражение для текущего хоста. Не заключайте выражение в скобки Jinja. Здесь and требует и включённую политику, и факты семейства Debian. not инвертирует логическое значение, а or позволяет любой из причин выбрать ветвь очистки.

cat > maintenance.yml <<'YAML'
- name: Apply a host-specific maintenance policy
  hosts: all
  gather_facts: true
  tasks:
    - name: Prepare the common policy directory
      ansible.builtin.file:
        path: /home/automation/maintenance-policy
        state: directory
        mode: "0750"

    - name: Record enabled Debian maintenance
      ansible.builtin.copy:
        dest: /home/automation/maintenance-policy/enabled.txt
        content: "Enabled maintenance\n"
        mode: "0640"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Remove the marker when the policy is disabled
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/enabled.txt
        state: absent
      when: not maintenance_enabled or ansible_facts.os_family != "Debian"
YAML

Общий каталог существует на обоих хостах. Только хосты Debian с включённой политикой получают маркер; дополняющая задача absent удаляет его при отключении политики. Один лишь пропуск задачи создания оставил бы старый маркер, поэтому очистка — отдельная задача желаемого состояния.

Проверьте и примените политику:

ansible-playbook maintenance.yml --syntax-check
ansible-playbook maintenance.yml

Вывод должен показывать разные решения changed/ok/skipped для web1 и web2. Изучите фактические метаданные маркера на обоих хостах:

ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/enabled.txt'

Stat должен сообщить exists true на web1 и false на web2. Для проверки очистки переопределите логическое значение для обоих хостов. Дополнительные переменные JSON сохраняют тип Boolean false; внешние одинарные кавычки защищают JSON от интерпретации оболочкой:

ansible-playbook maintenance.yml -e '{"maintenance_enabled":false}'
ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/enabled.txt'

Теперь оба маркера должны отсутствовать. Восстановите сохранённую политику каждого хоста запуском без временного переопределения:

ansible-playbook maintenance.yml

Web1 должен снова получить маркер, а web2 — остаться отключённым. Переопределение не редактировало сохранённые файлы переменных хостов.

Примените каждый элемент структурированного цикла

На этом шаге вы создадите настоящую запись проверки обслуживания для каждого объявленного элемента на хосте с включённой политикой.

Список YAML содержит несколько записей, начинающихся с дефиса. Каждая запись ниже — отображение с полями name и purpose. Переменные группы all делают этот список доступным обоим хостам, а существующее логическое условие по-прежнему решает, какой хост получает результаты.

cat > group_vars/all.yml <<'YAML'
maintenance_checks:
  - name: disk
    purpose: Inspect disk space
  - name: logs
    purpose: Inspect application logs
  - name: packages
    purpose: Inspect package state
YAML

loop повторяет одну задачу для каждой записи списка. Внутри итерации item.name и item.purpose читают поля этой записи. Условие when вычисляется для каждого хоста и элемента. Добавьте эти задачи в существующий плейбук, сохранив отступы на уровне предыдущих задач:

cat >> maintenance.yml <<'YAML'

    - name: Prepare checks only for enabled Debian hosts
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/checks
        state: directory
        mode: "0750"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Write every declared maintenance check
      ansible.builtin.copy:
        dest: "/home/automation/maintenance-policy/checks/{{ item.name }}.txt"
        content: |
          host={{ inventory_hostname }}
          check={{ item.name }}
          purpose={{ item.purpose }}
        mode: "0640"
      loop: "{{ maintenance_checks }}"
      when: maintenance_enabled and ansible_facts.os_family == "Debian"

    - name: Remove check outputs when the policy is disabled
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/checks
        state: absent
      when: not maintenance_enabled or ansible_facts.os_family != "Debian"
YAML

Задача очистки удаляет весь каталог проверок на хостах с отключённой политикой, включая старые результаты ранее включённой политики. Цикл записывает стабильное содержимое с явными правами на хостах с включённой политикой.

Примените расширенный плейбук:

ansible-playbook maintenance.yml

У web1 должно быть три результата цикла — по одному на проверку. Web2 должен пропустить эти записи и не иметь каталога checks. Прочитайте все три настоящих объекта web1, не считая один успешный элемент подтверждением всего списка:

ansible web1 -m ansible.builtin.command -a 'cat /home/automation/maintenance-policy/checks/disk.txt /home/automation/maintenance-policy/checks/logs.txt /home/automation/maintenance-policy/checks/packages.txt'

Вывод должен указывать host=web1 в каждой записи и показывать соответствующие имя проверки и назначение. Независимо изучите хост с отключённой политикой:

ansible web2 -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/checks'

Его результат stat должен сообщать exists false. Эти записи объявляют инструкции проверок обслуживания; они не выдают себя за выполнение самих проверок диска, журналов или пакетов.

Выполните ветвление по зарегистрированному результату обследования

На этом шаге вы используете настоящий результат stat как независимые входные данные решения и убедитесь, что полная политика стабильна при повторении.

Входной файл одобрения отделён от maintenance_enabled. Задача stat всегда обследует каждый хост, затем register сохраняет результат этого хоста. Логическое значение stat.exists безопасно различает существующий входной файл и отсутствующий путь. Добавьте обследование и дополняющие задачи результатов:

cat >> maintenance.yml <<'YAML'

    - name: Inspect the independent approval input
      ansible.builtin.stat:
        path: /home/automation/maintenance-approved
      register: approval_info

    - name: Record an existing approval input
      ansible.builtin.copy:
        dest: /home/automation/maintenance-policy/approved.txt
        content: "Approval input exists\n"
        mode: "0640"
      when: approval_info.stat.exists

    - name: Remove the output when approval input is absent
      ansible.builtin.file:
        path: /home/automation/maintenance-policy/approved.txt
        state: absent
      when: not approval_info.stat.exists
YAML

Задача copy использует зарегистрированное значение exists. Задача absent охватывает противоположный случай, чтобы удаление входного файла одобрения также удаляло устаревший результат одобрения. Эта ветвь основана на обследованном состоянии, а не на фиксированном сообщении debug.

Запустите полную политику:

ansible-playbook maintenance.yml

Подготовленный входной файл одобрения существует только на web1, поэтому approved.txt должен быть только у web1. Изучите оба фактических пути результатов:

ansible all -m ansible.builtin.stat -a 'path=/home/automation/maintenance-policy/approved.txt'

Web1 должен сообщать exists true, а web2 — false. Повторите плейбук:

ansible-playbook maintenance.yml

Обе строки итога должны сообщать changed=0, failed=0 и unreachable=0. Пропущенные задачи ожидаемы там, где условие ложно; каждый требуемый элемент цикла и выбранный результат всё равно должны существовать с правильным содержимым.

Резюме

Вы использовали логические данные каждого хоста и обнаруженные факты для выбора задач, обработали каждое отображение в цикле и выполнили ветвление по зарегистрированным метаданным stat. Дополняющие задачи absent удаляли устаревшие результаты вместо предположения, что пропуск создания отменяет старое состояние. Оба хоста достигли своих разных результатов политики без ненужных повторных изменений.