Поиск по сайту:

Использование When условных операторов в Ansible Playbooks

Принятие решений с помощью условных операторов When в Ansible

Если вы имеете опыт программирования или написания сценариев, то вам должно быть знакомо понятие "условные операторы". Условные операторы позволяют выполнять код на основе результата условия. Аналогично в ansible вы можете использовать условные операторы When для выполнения задач. Если условие оценивается как истинное, задача будет запущена, в противном случае задача будет пропущена.

Синтаксис условного оператора when следующий. В последующих разделах вы узнаете, как применять условное выражение к задачам.

Play definition

tasks:

    Task 1
    when: condition 

    Task 2
    when: condition 

'When' условные операторы с Ansible Facts

Факты — это информация, связанная с системой, собранная Ansible с помощью модуля настройки на управляемых узлах. Могут быть случаи, когда вам придется принимать решения на основе собранных фактов.

Если вы понятия не имеете о фактах, у нас есть краткая статья о фактах, и вы можете получить к ней доступ, перейдя по ссылке ниже.

  • Объяснение фактов об Ansible на примерах

В следующем сборнике я написал задачу по установке репозитория epel-release с помощью модуля dnf. Используя факт(ansible_distribution), я написал условное выражение для установки пакета только на «неустойчивый» Linux. Я использовал фильтр преобразования регистра jinga2 (нижний), чтобы преобразовать выходные данные ansible_distribution в нижний регистр.

---
- name: Installing packages
  hosts: all
  become: true
  gather_facts: true    # By default it is set to true

  tasks:

   - name: Install epel-release
     dnf:
       pkg: epel-release
       state: present
     when: ansible_distribution | lower == "rocky"

Когда я запускаю плейбук, условие When будет оценивать и запускать задачу только в Rocky Linux. Задача будет пропущена для всех остальных дистрибутивов.

ansible-playbook when_condition_test.yml 

PLAY [Installing packages] ********************************************************

TASK [Gathering Facts] ************************************************************
ok: [rocky.anslab.com]
ok: [ubuntu.anslab.com]

TASK [Install epel-release] ***********************************************************************************
skipping: [ubuntu.anslab.com]
ok: [rocky.anslab.com]

PLAY RECAP ***********************************************************************************
rocky.anslab.com           : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu.anslab.com          : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

Условные операторы Ansible 'When' с логическими операторами И/ИЛИ

Вы можете использовать логический оператор И/ИЛИ для оценки нескольких условий. Я использую ту же книгу, но добавил еще одно условие, основанное на фактах. Эта игра будет пропущена, поскольку у меня установлена версия дистрибутива 8, и я проверяю условие по версии 9.

   - name: Logical AND Testing
     dnf:
       pkg: htop
       state: present
     when: ansible_distribution | lower == "rocky" and ansible_distribution_major_version == "9"

Пример вывода:

TASK [Gathering Facts] *********************************************************************************************************************
ok: [rocky.anslab.com]
ok: [ubuntu.anslab.com]

TASK [Logical AND Testing] *****************************************************************************************************************
skipping: [ubuntu.anslab.com]
skipping: [rocky.anslab.com]

Вы также можете написать логическое И, используя формат списка YAML.

   - name: Logical AND using List syntax
     dnf:
       pkg: htop
       state: present
     when:
       - ansible_distribution | lower == "rocky"
       - ansible_distribution_major_version == "9"

Когда я запускаю ту же книгу с логическим оператором ИЛИ, задача выполняется нормально.

TASK [Gathering Facts] *********************************************************************************************************************
ok: [ubuntu.anslab.com]
ok: [rocky.anslab.com]

TASK [Logical OR Testing] ******************************************************************************************************************
skipping: [ubuntu.anslab.com]
ok: [rocky.anslab.com]

Если вам нужно оценить несколько выражений, вы можете поместить их в круглые скобки. Здесь я использую синтаксис JINJA2(int >= 8), чтобы оценить, больше ли версия дистрибутива 8 или равна ей.

   - name: Multiple conditions
     dnf:
       pkg: epel-release
       state: present
     when: (ansible_distribution | lower == "centos" or ansible_distribution | lower == "rocky") and ansible_distribution_major_version | int >= 8

Условный оператор Ansible 'When' с оператором членства

Вы можете использовать оператор IN для оценки выражения по списку значений. В следующем сборнике я создал задачу для запуска в дистрибутивах на основе RHEL.

   - name: Membership Operator
     dnf:
       pkg: epel-release
       state: present
     when: ansible_distribution | lower in ["centos","rocky"]

Пример вывода:

TASK [Gathering Facts] **********************************************************************************
ok: [ubuntu.anslab.com]
ok: [rocky.anslab.com]

TASK [Membership Operator] ***********************************************************************************
skipping: [ubuntu.anslab.com]
ok: [rocky.anslab.com]

Условные операторы 'When' с переменными Ansible

Вы можете оценивать условия по магическим переменным, переменным хоста, переменным группы.

Если вы понятия не имеете об ansible переменных, вы можете просмотреть нашу статью по ссылке ниже.

  • Как использовать переменные в Ansible Playbooks

В приведенной ниже книге я создал переменную с именем trigger_pipeline и установил для нее значение no. Условие задано таким образом, что задача будет выполняться только тогда, когда для trigger_pipeline установлено значение execute.

---
- name: Pipeline call
 hosts: all
 gather_facts: false

 vars:
   trigger_pipeline: no

 tasks:

   - name: Trigger Pipeline
     debug:
       msg: Running pipeline
     when: trigger_pipeline == "execute"

Когда я запускаю playbook, эта задача будет пропущена.

TASK [Trigger Pipeline] *********************************************************
skipping: [rocky.anslab.com]

Я могу переопределить переменную trigger_pipeline из командной строки, выполнив следующую команду.

ansible-playbook when_condition_test.yml -e trigger_pipeline=execute

TASK [Trigger Pipeline] **********************************************************************************
ok: [rocky.anslab.com] => {
    "msg": "Running pipeline"
}

Используя оператор IS, вы можете проверить, объявлена ли переменная не в условных операторах.

when: trigger_pipeline is defined          # TRUE only when var is defined
when: trigger_pipeline is undefined        # TRUE only when var is not defined

Условные операторы 'When' с регистром Ansible

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

В приведенных ниже задачах я создал две задачи, первая из которых будет использовать модуль shell и запускать /bin/true. Вывод будет сохранен в регистре переменных, который используется во второй задаче печати.

 tasks:

   - name: set to true
     shell: /bin/true
     register: result

   - name: print result
     debug:
       var: result

Пример вывода:

ok: [rocky.anslab.com] => {
    "result": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/libexec/platform-python"
        },
        "changed": true,
        "cmd": "/bin/true",
        "delta": "0:00:00.003477",
        "end": "2022-05-23 17:13:15.056197",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2022-05-23 17:13:15.052720",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "",
        "stdout_lines": []
    }
}

Вы можете использовать любое из этих значений для создания условий. Допустим, вы хотите запускать задачу только тогда, когда для rc установлено значение ноль, тогда вы можете написать условие, как показано ниже.

when: result.rc == 0

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

when: result.stdout != ""             # Checking if stdout is not empty
when: result.failed == "false"        # checking if failed is set to false
when: changed == "true"               # Checking if the status of changed is true

Условные операторы 'When' с циклами

Вы можете комбинировать условный оператор с циклами. В этом случае для каждого элемента условного оператора цикла будет выполняться оценка по заданному выражению.

Взгляните на пьесу ниже. Я создаю двух пользователей с именами ubuntu и rocky, используя пользовательский модуль. Директива цикла будет работать с переменной имени пользователя. Здесь условие написано таким образом, что пользователь Ubuntu должен быть создан только на хосте Ubuntu Linux, а пользователь Rocky должен быть создан на хосте Rocky Linux.

- name: Create Users
  hosts: all
  gather_facts: true
  become: true

 vars:
   username:
     - ubuntu
     - rocky

 tasks:

   - name: Create the user
     user:
       name: "{{ item }}"
       state: present
       password: "{{  item | password_hash('sha512') }}"
     loop: "{{ username }}"
     when: (item == "ubuntu" and ansible_distribution | lower == "ubuntu") or (item == "rocky" and ansible_distribution | lower == "rocky")

Как видно из приведенного ниже вывода, пользователи создаются в соответствующих дистрибутивах в соответствии с условием.

TASK [Create the user] ********************************************************************************
skipping: [rocky.anslab.com] => (item=ubuntu) 
changed: [ubuntu.anslab.com] => (item=ubuntu)
skipping: [ubuntu.anslab.com] => (item=rocky) 
changed: [rocky.anslab.com] => (item=rocky)

Заключение

В этой статье мы увидели, что такое условный оператор и как использовать условные операторы When в Ansible для оценки условий и запуска задач на основе результата.

Когда вы изучите расширенные концепции, такие как роли, импорт и включения, вы узнаете больше об условных операторах и о том, как их более эффективно использовать.

Ресурс:

  • Условные операторы Ansible

Статьи по данной тематике