“RHCE8.0讲义:编写循环和条件任务”的版本间的差异
(→组合循环和有条件任务) |
(→循环散列或字典列表) |
||
(未显示同一用户的15个中间版本) | |||
第2行: | 第2行: | ||
通过利用循环,管理员无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。 | 通过利用循环,管理员无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。 | ||
− | + | Ansible支持使用'''loop关键字'''对一组项目迭代任务。您可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。本节介绍迭代项目列表的简单循环。有关更高级的循环方案,请参阅文档。 | |
===简单循环=== | ===简单循环=== | ||
− | + | 简单循环对一组项目迭代任务。'''loop'''关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。 | |
请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态: | 请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态: | ||
<nowiki> | <nowiki> | ||
− | - name: | + | --- |
− | + | - name: Open server | |
− | + | hosts: slave | |
− | + | become: no | |
+ | tasks: | ||
+ | - name: firewalld enabled and running | ||
+ | service: | ||
+ | name: firewalld | ||
+ | enabled: true | ||
+ | state: started | ||
+ | - name: httpd enabled and running | ||
+ | service: | ||
+ | name: httpd | ||
+ | enabled: true | ||
+ | state: started</nowiki> | ||
+ | |||
+ | ansible-playbook test.yml --syntax-check | ||
− | - | + | ansible-playbook test.yml |
− | |||
− | |||
− | |||
这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行: | 这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行: | ||
− | <nowiki> | + | <nowiki> |
− | - name: | + | --- |
− | + | - name: Open server | |
− | + | hosts: slave | |
− | + | become: no | |
− | + | tasks: | |
− | + | - name: service enabled and running | |
− | + | service: | |
+ | name: "{{item}}" | ||
+ | enabled: true | ||
+ | state: started | ||
+ | loop: | ||
+ | - firewalld | ||
+ | - httpd | ||
</nowiki> | </nowiki> | ||
− | + | 输出: | |
<nowiki> | <nowiki> | ||
− | + | TASK [firewalld enabled and running] ******************************************* | |
− | + | ok: [10.0.0.40] => (item=firewalld) | |
− | + | ok: [10.0.0.40] => (item=httpd) | |
− | + | ok: [10.0.0.40] => (item=network)</nowiki> | |
+ | |||
+ | ===排错=== | ||
+ | The error was : 'item' is undefined | ||
+ | |||
+ | 可能是loop缩进不对引起的,loop应与模块名称service对齐。 | ||
+ | |||
+ | 可以通过一个变量提供loop所使用的列表。在以下示例中'变量mail_services含有需要处于 运行状态的服务的列表。 | ||
− | tasks: | + | <nowiki> |
− | + | --- | |
− | + | - name: Open server | |
− | + | hosts: slave | |
− | + | become: no | |
− | + | vars: | |
+ | basic_services: | ||
+ | - firewalld | ||
+ | - httpd | ||
+ | tasks: | ||
+ | - name: service enabled and running | ||
+ | service: | ||
+ | name: "{{item}}" | ||
+ | enabled: true | ||
+ | state: started | ||
+ | loop: "{{basic_services}}" | ||
+ | </nowiki> | ||
===循环散列或字典列表=== | ===循环散列或字典列表=== | ||
− | loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的 每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过 item. name 和 item. groups变量来检索。 | + | loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的 每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过 item.name 和 item.groups变量来检索。 |
<nowiki> | <nowiki> | ||
− | - name: Users exist and are in the correct groups | + | --- |
− | + | - name: create user | |
− | + | hosts: slave | |
− | + | become: no | |
− | + | tasks: | |
− | + | - name: Users exist and are in the correct groups | |
− | + | user: | |
− | + | name: "{{ item.name }}" | |
− | + | state: present | |
− | + | groups: "{{ item.groups }}" | |
+ | loop: | ||
+ | - name: jane | ||
+ | groups: wheel | ||
+ | - name: joe | ||
+ | groups: root</nowiki> | ||
上一任务的结果是用户jane存在且为组wheel的成员,并且用户joe存在且为组root的成员。 | 上一任务的结果是用户jane存在且为组wheel的成员,并且用户joe存在且为组root的成员。 | ||
− | |||
===较早样式的循环关键字=== | ===较早样式的循环关键字=== | ||
第73行: | 第111行: | ||
<nowiki>循环关键字 描述 | <nowiki>循环关键字 描述 | ||
− | with_items 行为与简单列表的loop关键字相同,例如字符串列表或散列/字典 | + | with_items 行为与简单列表的loop关键字相同,例如字符串列表或散列/字典 列表。但与loop不同的是,如果为with_items提供了列表的列表,它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。 |
with_file 此关键字需要控制节点文件名列表。循环变量item在每次迭代过 程中保存文件列表中相应文件的内容。 | with_file 此关键字需要控制节点文件名列表。循环变量item在每次迭代过 程中保存文件列表中相应文件的内容。 | ||
with_sequence 此关键字不需要列表,而是需要参数来根据数字序列生成值列表。 循环变量item在每次迭代过程中保存生成的序列中的一个生成项 的值。</nowiki> | with_sequence 此关键字不需要列表,而是需要参数来根据数字序列生成值列表。 循环变量item在每次迭代过程中保存生成的序列中的一个生成项 的值。</nowiki> | ||
第90行: | 第128行: | ||
debug: | debug: | ||
msg: "{{ item }}" | msg: "{{ item }}" | ||
− | with_items: " | + | with_items: "{{ data }}" |
</nowiki> | </nowiki> | ||
第109行: | 第147行: | ||
[student@workstation loopdemo]$ cat loop_register.yml | [student@workstation loopdemo]$ cat loop_register.yml | ||
− | - name: Loop Register Test | + | <nowiki>- name: Loop Register Test |
gather_facts: no | gather_facts: no | ||
hosts: localhost | hosts: localhost | ||
tasks: | tasks: | ||
- name: Looping Echo Task | - name: Looping Echo Task | ||
− | shell: "echo This is my item: {{ item } | + | shell: "echo This is my item: {{ item }}" |
loop: | loop: | ||
- one | - one | ||
第121行: | 第159行: | ||
- name: Show echo_results variable | - name: Show echo_results variable | ||
debug: | debug: | ||
− | var: echo_results (2) | + | var: echo_results (2)</nowiki> |
− | (1) echo_results变量已注册。 | + | (1)echo_results变量已注册。 |
(2)echo_results变量的内容显示在屏幕上。 | (2)echo_results变量的内容显示在屏幕上。 | ||
第129行: | 第167行: | ||
运行上面的playbook会产生以下输出: | 运行上面的playbook会产生以下输出: | ||
− | [student@workstation loopdemo]$ ansible-playbook loop_register.yml play | + | [student@workstation loopdemo]$ansible-playbook loop_register.yml play |
<nowiki>[Loop Register Test] **************************************** | <nowiki>[Loop Register Test] **************************************** | ||
第183行: | 第221行: | ||
{字符表示echo_results变量的开头由键值对组成。 | {字符表示echo_results变量的开头由键值对组成。 | ||
− | + | results键包含上一个任务的结果。[字符表示列表的开头。 | |
− | + | 第一项的任务元数据的开头(由item键表示)。echo命令的输出可在stdout键中找到。 第二项的任务结果元数据的幵头。 | |
]字符表示results列表的结尾。 | ]字符表示results列表的结尾。 | ||
− | + | 在上面,results键包含一个列表。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==有条件地运行任务== | ==有条件地运行任务== | ||
第248行: | 第254行: | ||
- name: httpd package is installed | - name: httpd package is installed | ||
yum: | yum: | ||
− | + | name: httpd | |
− | when: run_my_task</nowiki> | + | when: run_my_task |
+ | </nowiki> | ||
以下示例稍微复杂一些,它测试my_service变量是否具有值。若有值,则将my_service的值 用作要安装的软件包的名称。如果未定义my_service变量,则跳过任务且不显示错误。 | 以下示例稍微复杂一些,它测试my_service变量是否具有值。若有值,则将my_service的值 用作要安装的软件包的名称。如果未定义my_service变量,则跳过任务且不显示错误。 | ||
第259行: | 第266行: | ||
my_service: httpd | my_service: httpd | ||
tasks: | tasks: | ||
− | - name: | + | - name: "{{ my_service }} package is installed" |
yum: | yum: | ||
− | name: "{{ my_service } | + | name: "{{ my_service }}" |
− | when: my_service is defined</nowiki> | + | when: my_service is defined |
+ | </nowiki> | ||
下表显示了管理员在处理条件时可使用的一些运算: | 下表显示了管理员在处理条件时可使用的一些运算: | ||
第277行: | 第285行: | ||
变量存在 min_memory is defined | 变量存在 min_memory is defined | ||
变量不存在 min_memory is not defined | 变量不存在 min_memory is not defined | ||
− | 布尔变量是true、l、 True | + | 布尔变量是true、l、 True 或yes的求值为true memory_available |
布尔变量是false、0、False 或 no 的 求值为false not memory_available | 布尔变量是false、0、False 或 no 的 求值为false not memory_available | ||
第295行: | 第303行: | ||
- RedHat | - RedHat | ||
- Fedora | - Fedora | ||
+ | - Centos | ||
tasks: | tasks: | ||
- name: Install httpd using yum, where supported | - name: Install httpd using yum, where supported | ||
第326行: | 第335行: | ||
- ansible_distribution_version == "7.5" | - ansible_distribution_version == "7.5" | ||
- ansible_kernel == "3.10.0-327.el7.x86_64"</nowiki> | - ansible_kernel == "3.10.0-327.el7.x86_64"</nowiki> | ||
+ | |||
+ | 完整代码: | ||
+ | |||
+ | <nowiki>--- | ||
+ | - name: Demonstrate the "in" keyword | ||
+ | hosts: all | ||
+ | gather_facts: yes | ||
+ | vars: | ||
+ | supported_distros: | ||
+ | - RedHat | ||
+ | - Fedora | ||
+ | - Centos | ||
+ | tasks: | ||
+ | - name: Install httpd using yum, where supported | ||
+ | yum: | ||
+ | name: httpd | ||
+ | state: present | ||
+ | when: | ||
+ | - ansible_distribution_version >= "7.5" | ||
+ | - ansible_kernel >= "3.0.0-327.el7.x86_64"</nowiki> | ||
这种格式提高了可读性,而可读性是良好编写的Ansible Playbook的关键目标。 | 这种格式提高了可读性,而可读性是良好编写的Ansible Playbook的关键目标。 | ||
第347行: | 第376行: | ||
<nowiki> | <nowiki> | ||
− | - name: install mariadb-server if enough space on root | + | - name: Test Variable is Defined Demo |
− | + | hosts: slave | |
− | + | vars: | |
− | + | my_service: httpd | |
− | + | tasks: | |
− | + | - name: install mariadb-server if enough space on root | |
+ | yum: | ||
+ | name: mariadb-server | ||
+ | state: latest | ||
+ | loop: "{{ ansible_mounts }}" | ||
+ | when: item.mount == "/" and item.size_available > 300000000 | ||
+ | </nowiki> | ||
重要:对某个任务结合使用when和loop时,将对每个项检查when语句。 | 重要:对某个任务结合使用when和loop时,将对每个项检查when语句。 | ||
− | + | 下面是组合使用条件和注册变量的另一个示例。下方标注的playbook只有在postfix服务处于运行状态时才会重新启动httpd服务。 | |
− | <nowiki>-name: Restart HTTPD if Postfix is Running | + | <nowiki> |
− | hosts: all | + | --- |
− | tasks: | + | - name: Restart HTTPD if Postfix is Running |
− | -name: Get Postfix server status | + | hosts: all |
− | command: /usr/bin/systemctl is-active postfix | + | tasks: |
− | register: | + | - name: Get Postfix server status |
− | -name: Restart Apache HTTPD based on Postfix status | + | command: /usr/bin/systemctl is-active postfix |
− | service: | + | ignore_errors: yes |
− | name: httpd | + | register: result |
− | state: restarted | + | |
− | when: result. rc == | + | - name: Restart Apache HTTPD based on Postfix status |
+ | service: | ||
+ | name: httpd | ||
+ | state: restarted | ||
+ | when: result.rc == 0</nowiki> | ||
(1) Postfix是否在运行? | (1) Postfix是否在运行? |
2021年6月18日 (五) 03:51的最新版本
目录
利用循环迭代任务
通过利用循环,管理员无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。
Ansible支持使用loop关键字对一组项目迭代任务。您可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。本节介绍迭代项目列表的简单循环。有关更高级的循环方案,请参阅文档。
简单循环
简单循环对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。
请思考以下代码片段,它使用两次service模块来确保两个网络服务处于运行状态:
--- - name: Open server hosts: slave become: no tasks: - name: firewalld enabled and running service: name: firewalld enabled: true state: started - name: httpd enabled and running service: name: httpd enabled: true state: started
ansible-playbook test.yml --syntax-check
ansible-playbook test.yml
这两个任务可以重新编写为使用一个简单循环,从而只需一个任务来确保两个服务都在运行:
--- - name: Open server hosts: slave become: no tasks: - name: service enabled and running service: name: "{{item}}" enabled: true state: started loop: - firewalld - httpd
输出:
TASK [firewalld enabled and running] ******************************************* ok: [10.0.0.40] => (item=firewalld) ok: [10.0.0.40] => (item=httpd) ok: [10.0.0.40] => (item=network)
排错
The error was : 'item' is undefined
可能是loop缩进不对引起的,loop应与模块名称service对齐。
可以通过一个变量提供loop所使用的列表。在以下示例中'变量mail_services含有需要处于 运行状态的服务的列表。
--- - name: Open server hosts: slave become: no vars: basic_services: - firewalld - httpd tasks: - name: service enabled and running service: name: "{{item}}" enabled: true state: started loop: "{{basic_services}}"
循环散列或字典列表
loop列表不需要是简单值列表。在以下示例中,列表中的每个项实际上是散列或字典。示例中的 每个散列或字典具有两个键,即name和groups,当前item循环变量中每个键的值可以分别通过 item.name 和 item.groups变量来检索。
--- - name: create user hosts: slave become: no tasks: - name: Users exist and are in the correct groups user: name: "{{ item.name }}" state: present groups: "{{ item.groups }}" loop: - name: jane groups: wheel - name: joe groups: root
上一任务的结果是用户jane存在且为组wheel的成员,并且用户joe存在且为组root的成员。
较早样式的循环关键字
在Ansible 2.5之前,大多数playbook使用不同的循环语法。提供了多个循环关键字,前缀为 with_ ,后跟Ansible查找插件(一项高级功能,本课程中未加以详细介绍)的名称。这种循环语 法在现有playbook中很常见,但在将来的某个时候可能会被弃用。
下表列出了几个示例:
较早样式的Ansible循环
循环关键字 描述 with_items 行为与简单列表的loop关键字相同,例如字符串列表或散列/字典 列表。但与loop不同的是,如果为with_items提供了列表的列表,它们将被扁平化为单级列表。循环变量item保存每次迭代过程中使用的列表项。 with_file 此关键字需要控制节点文件名列表。循环变量item在每次迭代过 程中保存文件列表中相应文件的内容。 with_sequence 此关键字不需要列表,而是需要参数来根据数字序列生成值列表。 循环变量item在每次迭代过程中保存生成的序列中的一个生成项 的值。
playbook中的with_items的示例如下所示:
vars: data: - user0 - user1 - user2 tasks: - name: "with_items" debug: msg: "{{ item }}" with_items: "{{ data }}"
重要
从Ansible 2.5开始,建议使用loop关键字编写循环。
但是,您仍然应该了解旧语法,尤其是with_items,因为它广泛用于现有 playbooko您可能会遇到继续使用with_*关键字进行循环的playbook和角色。
使用旧语法的任何任务都可以转换为结合使用loop和Ansible过滤器。您不需要知道如何使用 Ansible过滤器来执行此操作。有关如何将旧循环转换为新语法,以及如何循环不是简单列表的 项的示例,Ansible 用户指南第从 with_X迁移至循环[https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#migrating-from-with-x-to-loop]节中的 Ansible 文档提供了 良好 的参善。
您可能会遇到包含with_*关键字的旧playbook中的任务。
高级循环技术不在本课程的讨论范围内。本课程中的所有迭代任务都可以使用withjtems或 loop关键字实施。
将Register变量与Loop —起使用
register关键字也可以捕获循环任务的输岀。以下代码片段显示了循环任务中register变量的结 构:
[student@workstation loopdemo]$ cat loop_register.yml
- name: Loop Register Test gather_facts: no hosts: localhost tasks: - name: Looping Echo Task shell: "echo This is my item: {{ item }}" loop: - one - two register: echo_results (1) - name: Show echo_results variable debug: var: echo_results (2)
(1)echo_results变量已注册。
(2)echo_results变量的内容显示在屏幕上。
运行上面的playbook会产生以下输出:
[student@workstation loopdemo]$ansible-playbook loop_register.yml play
[Loop Register Test] **************************************** TASK [Looping Echo Task] ************************** ... output omitted TASK [Show echo_results variable] ***************** ok: [localhost] => { "echo_results": {。 "changed": true, "msg": "All items completed", "results" : [O "_ansible_ignore_errors": null, ... output omitted "changed": true, "cmd": "echo This is my item: one", "delta": "0:00:00.011865", "end": "2018-11-01 16:32:56.080433", "failed": false, ...output omitted "item": "one", "re": 0, "start": "2018-11-01 16:32:56.068568", "stderr": "stderr_lines": "stdout": "This "stdout_lines": "This is my ] }, {O "_ansible_ignore_errors": null, ... output omitted "changed": true, "cmd": "echo This is my item: two", "delta": "0:00:00.011142"z "end": "2018-11-01 16:32:56.828196", "failed": false, ... output omitted "item": "two", "rc": 0, "start": "2018-11-01 16:32:56.817054", "stderr" : ,,n, "stderr_lines": "stdout": "This "stdout_lines": "This is my ] } [], is my item: one", item: one 口, is my item: two", item: two" ]❺ } } ... output omitted
{字符表示echo_results变量的开头由键值对组成。
results键包含上一个任务的结果。[字符表示列表的开头。
第一项的任务元数据的开头(由item键表示)。echo命令的输出可在stdout键中找到。 第二项的任务结果元数据的幵头。
]字符表示results列表的结尾。
在上面,results键包含一个列表。
有条件地运行任务
Ansible可使用conditionals在符合特定条件时执行任务或play。例如,可以利用一个条件在 Ansible安装或配置服务前确定受管主机上的可用内存。
管理员可利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变 量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔 值的运算符。
以下场景说明了在Ansible中使用条件的情况:
- 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
- Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如, 如果某一程序失败,则将跳过批处理。
- 可以利用Ansible事实来确定受管主机网络配置,并且决定要发送的模板文件(如,网络绑定或 中继)。
- 可以评估CPU的数量,来确定如何正确调节某一Web服务器。
- 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的 MD5校验和以查看服务是否已更改。
条件任务语法
when语句用于有条件地运行任务。它取要测试的条件作为值。如果条件满足,则运行任务。如何 条件不满足,则跳过任务。 可以测试的一个最简单条件是某一布尔变量是true还是falseo以下示例中的when语句导致任务仅 在 run_my_task 为 true 时运行:
- name: Simple Boolean Task Demo hosts: all vars: run_my_task: true tasks: - name: httpd package is installed yum: name: httpd when: run_my_task
以下示例稍微复杂一些,它测试my_service变量是否具有值。若有值,则将my_service的值 用作要安装的软件包的名称。如果未定义my_service变量,则跳过任务且不显示错误。
- name: Test Variable is Defined Demo hosts: all vars: my_service: httpd tasks: - name: "{{ my_service }} package is installed" yum: name: "{{ my_service }}" when: my_service is defined
下表显示了管理员在处理条件时可使用的一些运算:
示例条件 操作 示例 等于(值为字符串) ansible_machine == "x86_64" 等于(值为数字) max_memory == 512 小于 min_memory < 128 大于 min_memory > 256 小于等于 min_memory <= 256 大于等于 min_memory >= 512 不等于 min_memory != 512 变量存在 min_memory is defined 变量不存在 min_memory is not defined 布尔变量是true、l、 True 或yes的求值为true memory_available 布尔变量是false、0、False 或 no 的 求值为false not memory_available 第一个变量的值存在,作为第二个变量的列表中的值 ansible_distribution in supported_distros
上表中的最后一个条目初看起来有些令人困惑。下例演示了它的工作原理。
在示例中,ansible_distribution变量是在Gathering Facts任务期间确定的事 实,用于标识托管主机的操作系统分发。变量supported_distros由playbook作者创 建,包含该playbook支持的操作系统分发列表。如果ansible_distribution的值在 supported_distros列表中,则条件通过且任务运行。
--- - name: Demonstrate the "in" keyword hosts: all gather_facts: yes vars: supported_distros: - RedHat - Fedora - Centos tasks: - name: Install httpd using yum, where supported yum: name: http state: present when: ansible_distribution in supported_distros
重要
注意when语句的缩进。由于when语句不是模块变量,它必须通过缩进到任务的最 高级别,放置在模块的外面。
任务是YAML散列/字典,when语句只是任务中的又一个键,就如任务的名称以及它 所使用的模块一样。通常的惯例是将可能存在的任何when关键字放在任务名称和模 块(及模块参数)的后面。
测试多个条件
一个when语句可用于评估多个条件。为此,可以使用and或or关键字组合条件,并使用括号分 组条件。
下列代码片段显示了如何表达多个条件的一些示例。
- 如果任一条件为真时满足条件语句,则应当使用or语句。例如,如果计算机上运行的是红帽企 业Linux或Fedora,则下述条件得到满足:
when: ansible_distribution == "RedHat" or ansible_distribution == "Fedora"
使用and运算时,两个条件都必须为真,才能满足整个条件语句。例如,如果远程主机是红帽企 业Linux 7.5主机,并且安装的内核是指定版本,则将满足以下条件:
when: ansible_distribution_version == ”7.5" and ansible_kernel == "3.10.0-327.el7.X86_64"
when关键字还支持使用列表来描述条件列表。向when关键字提供列表时,将使用and运算组 合所有条件。下面的示例演示了使用and运算符组合多个条件语句的另一方式:
when: - ansible_distribution_version == "7.5" - ansible_kernel == "3.10.0-327.el7.x86_64"
完整代码:
--- - name: Demonstrate the "in" keyword hosts: all gather_facts: yes vars: supported_distros: - RedHat - Fedora - Centos tasks: - name: Install httpd using yum, where supported yum: name: httpd state: present when: - ansible_distribution_version >= "7.5" - ansible_kernel >= "3.0.0-327.el7.x86_64"
这种格式提高了可读性,而可读性是良好编写的Ansible Playbook的关键目标。
通过使用括号分组条件,可以表达更复杂的条件语句。这可确保正确解释它们。
例如,如果计算机上运行的是红帽企业Linux 7或Fedora28,则下述条件语句得到满足。此示例 使用大于字符(>),这样长条件就可以在playbook中分成多行,以便于阅读。
when: > ( ansible_distribution == "RedHat" and ansible_distribution_major_version == "7") or ( ansible_distribution == "Fedora" and ansible_distribution_major_version == "28")
组合循环和有条件任务
循环和条件可以组合使用。
在下例中,yum模块将安装mariadb-server软件包 只要/上挂载的文件系统具有超过300 MB的 可用空间。ansible_mounts事实是一组字典,各自代表一个已挂载文件系统的相关事实。循环 迭代列表中的每一字典,只有找到了代表两个条件都为真的已挂载文件系统的字典时,条件语句才 得到满足。
- name: Test Variable is Defined Demo hosts: slave vars: my_service: httpd tasks: - name: install mariadb-server if enough space on root yum: name: mariadb-server state: latest loop: "{{ ansible_mounts }}" when: item.mount == "/" and item.size_available > 300000000
重要:对某个任务结合使用when和loop时,将对每个项检查when语句。
下面是组合使用条件和注册变量的另一个示例。下方标注的playbook只有在postfix服务处于运行状态时才会重新启动httpd服务。
--- - name: Restart HTTPD if Postfix is Running hosts: all tasks: - name: Get Postfix server status command: /usr/bin/systemctl is-active postfix ignore_errors: yes register: result - name: Restart Apache HTTPD based on Postfix status service: name: httpd state: restarted when: result.rc == 0
(1) Postfix是否在运行?
(2)如果它不在运行并且命令失败,则不停止处理。
(3) 将模块的结果信息保存在名为result的变量中。
(4) 评估Postfix任务的输出。如果systemctl命令的退出代码为0,则Postfix激活并且此任务重 新启动httpd服务。
参考文献
IP 循环 — Ansible 文档 https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
测试 — Ansible 文档 https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html
条件 — Ansible 文档 https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html
什么是有效的变量名—变量— Ansible文档 https://docs.ansible.com/ansible/latest/user_guide/ playbooks_variables.html#what-makes-a-valid-variable-name