Использование 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