Ansible Playbook Conditionals

一般,play的结果可能取决于变量的值,facts(有关远程系统的知识)或先前的任务结果。 在某些状况下,变量的值可能取决于其余变量。 此外,能够建立其余组,以根据主机是否与其余条件匹配来管理主机。 在Ansible中有许多控制执行流程的选项。 支持条件的更多示例能够在这里找到: http : //jinja.pocoo.org/docs/dev/templates/#comparisonshtml

When 语句

有时您会想要跳过特定主机上的特定步骤。 若是操做系统是特定版本,这多是一个简单的方法,若是没有安装某个包,或者若是文件系统正在充满,可能会执行一些清理步骤。web

这在使用when子句很容易作到,它包含一个没有双大括号的原始Jinja2表达式(见变量 )。 其实很简单: shell

tasks: - name: "shut down Debian flavored systems" command: /sbin/shutdown -t now when: ansible_os_family == "Debian" # note that Ansible facts and vars like ansible_os_family can be used # directly in conditionals without double curly braces

您也能够使用括号来分组条件:
tasks: - name: "shut down CentOS 6 and Debian 7 systems" command: /sbin/shutdown -t now when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or (ansible_distribution == "Debian" and ansible_distribution_major_version == "7")
全部须要为真的多个条件(逻辑“和”)也能够指定为列表:
asks: - name: "shut down CentOS 6 systems" command: /sbin/shutdown -t now when: - ansible_distribution == "CentOS" - ansible_distribution_major_version == "6"

一些Jinja2“过滤器”也能够在语句中使用,其中一些是惟一的,由Ansible提供。 假设咱们想忽略一个语句的错误,而后决定根据成功或失败有条件地作某些事情:
tasks: - command: /bin/false register: result ignore_errors: True - command: /bin/something when: result|failed # In older versions of ansible use |success, now both are valid but succeeded uses the correct tense. - command: /bin/something_else when: result|succeeded - command: /bin/still/something_else when: result|skipped


请注意,这是“register”声明的一点点预示。 咱们稍后会在本章中讨论。

提醒您,要查看特定系统上有哪些facts,您能够执行如下操做: apache

ansible hostname.example.com -m setup

提示:有时您会收到一个字符串的变量,您将须要对其进行数学运算比较。 你能够这样作:

tasks: - shell: echo "only on Red Hat 6, derivatives, and later"  when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6


也能够使用在playbooks或inventory中定义的变量。 一个例子多是基于一个变量的布尔值执行一个任务:
vars: epic: true

那么条件执行可能以下所示:
tasks: - shell: echo "This certainly is epic!" when: epic
要么:
tasks: - shell: echo "This certainly isn't epic!" when: not epic

若是未设置必需变量,则能够使用Jinja2 定义的测试来跳过或失败。 例如:
tasks: - shell: echo "I've got '{{ foo }}' and am not afraid to use it!" when: foo is defined - fail: msg="Bailing out. this play requires 'bar'"  when: bar is undefined

这与vars文件的条件导入(见下文)相结合特别有用。 如示例所示,您不须要使用{{}}在条件中使用变量,由于这些变量已经被隐含。

Loops and Conditionals

结合with_items (请参阅循环 ),请注意,每一个项目分别处理when语句。 这是设计:json

tasks: - command: echo {{ item }} with_items: [ 0, 2, 4, 6, 8, 10 ] when: item > 5


若是须要根据定义的循环变量跳过整个任务,则使用| default过滤器来提供一个空的迭代器:
- command: echo {{ item }} with_items: "{{ mylist|default([]) }}" when: item > 5

若是使用没有列表的with_dict
- command: echo {{ item.key }} with_dict: "{{ mydict|default({}) }}" when: item.value > 5

Loading in Custom Facts

若是须要,提供本身的facts也很容易,这在开发模块中有所体现。 要运行它们,只需在您的任务列表顶部调用您本身的自定义facts收集模块,返回的变量将在之后的任务中访问:ruby

tasks: - name: gather site specific fact data action: site_facts - command: /usr/bin/thingy when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'

Applying ‘when’ to roles and includes

请注意,若是您有多个任务共享相同的条件语句,则能够将条件附加到以下的任务include语句。 全部的任务获得评估,但条件应用于每一个任务:app

- include: tasks/sometasks.yml when: "'reticulating splines' in output"

- hosts: webservers roles: - { role: debian_stock_config, when: ansible_os_family == 'Debian' }

在不符合条件的系统上使用此方法时,默认状况下,您将会注意到不少“跳过”输出。 在“ 关于模块”文档中的“group_by”模块上阅读,以得到更加精简的方式来完成相同的操做。

Conditional Imports

有时你会根据某些标准,在一个playbook里作一些不一样的事情。 有一本适用于多个平台和操做系统版本的playbook就是一个很好的例子。curl

例如,CentOS和Debian之间的Apache软件包的名称可能不一样,但能够在一个可读的Playbook中使用最少的语法进行处理:ide

---
- hosts: all remote_user: root vars_files: - "vars/common.yml" - [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ] tasks: - name: make sure apache is started service: name={{ apache }} state=started


做为提醒,各类YAML文件只包含键值和值:

---
# for vars/CentOS.yml apache: httpd somethingelse: 42

这个怎么用? 若是操做系统是“CentOS”,则第一个能够导入的文件是“vars / CentOS.yml”,若是该文件不存在,则为“/vars/os_defaults.yml”。
若是列表中没有找到任何文件,则会出现错误。 在Debian上,它会首先查看'vars / Debian.yml'而不是'vars / CentOS.yml',而后再回到'vars / os_defaults.yml'。 很简单
要使用这个条件导入功能,您须要在运行该playbook以前安装facter或ohai,但若是您喜欢,您能够将其与Ansible一块儿推出:
# for facter
ansible -m yum -a "pkg=facter state=present" ansible -m yum -a "pkg=ruby-json state=present" # for ohai ansible -m yum -a "pkg=ohai state=present"

可配置的配置方法 - 将变量与任务分离,使您的剧本不会变成具备丑陋的嵌套ifs,条件等的任意代码,并致使更精简和可审计的配置规则,特别是由于至少有一个决策点要跟踪。

Selecting Files And Templates Based On Variables

有时您要复制的配置文件或您将使用的模板可能取决于变量。 如下构造选择适合于给定主机的变量的第一个可用文件,这一般比在模板中放入大量条件更为干净。oop

如下示例显示如何模板化出与CentOS和Debian之间有很大不一样的配置文件:

- name: template a file template: src={{ item }} dest=/etc/myapp/foo.conf with_first_found: - files: - {{ ansible_distribution }}.conf - default.conf paths: - search_location_one/somedir/ - /opt/other_location/somedir/

Register Variables

一般在playbook中,将给定命令的结果存储在变量中多是有用的,而后再访问它。 以这种方式使用命令模块能够在不少方面消除编写站点特定事实的须要,例如,您能够测试特定程序的存在。

'register'关键字决定将结果保存到哪一个变量中。生成的变量能够在模板,动做行或when语句中使用。 看起来像这样(显而易见的例子):

- name: test play hosts: all tasks: - shell: cat /etc/motd register: motd_contents - shell: echo "motd contains the word hi" when: motd_contents.stdout.find('hi') != -1

如前所示,注册变量的字符串内容可经过'stdout'值访问。 注册结果能够在任务的“with_item”中被使用,若是它被转换成列表(或已是列表),以下所示。
“stdout_lines”也能够在对象上使用,可是若是须要也能够调用“home_dirs.stdout.split()”,而且能够被其余字段分割:
- name: registered variable usage as a with_items list hosts: all tasks: - name: retrieve the list of home directories command: ls /home register: home_dirs - name: add home dirs to the backup spooler file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link with_items: "{{ home_dirs.stdout_lines }}" # same as with_items: "{{ home_dirs.stdout.split() }}"

如前所示,注册变量的字符串内容可经过'stdout'值访问。 您能够检查注册变量的字符串内容为空:
- name: check registered variable for emptiness hosts: all tasks: - name: list contents of directory command: ls mydir register: contents - name: check contents for emptiness debug: msg="Directory is empty" when: contents.stdout == ""
相关文章
相关标签/搜索