设为首页 收藏本站
查看: 1221|回复: 0

[经验分享] Ansible Playbook Conditionals

[复制链接]

尚未签到

发表于 2018-1-2 14:55:05 | 显示全部楼层 |阅读模式
  通常,play的结果可能取决于变量的值,facts(有关远程系统的知识)或先前的任务结果。 在某些情况下,变量的值可能取决于其他变量。 此外,可以创建其他组,以根据主机是否与其他条件匹配来管理主机。 在Ansible中有许多控制执行流程的选项。 支持条件的更多示例可以在这里找到: http : //jinja.pocoo.org/docs/dev/templates/#comparisons

When 语句
  有时您会想要跳过特定主机上的特定步骤。 如果操作系统是特定版本,这可能是一个简单的方法,如果没有安装某个包,或者如果文件系统正在充满,可能会执行一些清理步骤。
  这在使用when子句时很容易做到,它包含一个没有双大括号的原始Jinja2表达式(见变量 )。 其实很简单:
  

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,您可以执行以下操作:
  

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语句。 这是设计:
  

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收集模块,返回的变量将在以后的任务中访问:
  

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语句。 所有的任务得到评估,但条件应用于每个任务:
  

- 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就是一个很好的例子。
  例如,CentOS和Debian之间的Apache软件包的名称可能不同,但可以在一个可读的Playbook中使用最少的语法进行处理:
  

---  
- 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
  有时您要复制的配置文件或您将使用的模板可能取决于变量。 以下构造选择适合于给定主机的变量的第一个可用文件,这通常比在模板中放入大量条件更为干净。
  以下示例显示如何模板化出与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 == ""
  

  

  

  

  

  

  

  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-430835-1-1.html 上篇帖子: 【Ansible 文档】【译文】常见问题 下篇帖子: Ansible:变量详解【转】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表