Ansible(四)如何进行流程控制

ansible-playbook中,也可以像其他编程语言一样进行条件判断、循环等流程控制。除此之外,还可以控制task的执行结果。

条件判断 WHEN

ansible中,可以通过when语句来执行条件判断,只有符合条件,才会执行对应的task
when语句和task对齐,在when语句中,变量不需要使用{{ }}括起来。

常用判断条件

条件 示例
字符串相等 ansible_machine == "x86_64"
数值相等 max_memory == 512
小于 min_memory < 128
大于 min_memory > 128
小于等于 min_memory <=512
大于等于 min_memory >= 512
不等于 min_memory != 512
变量存在 min_memory is defined
变量不存在 min_memory is not defined
变量值为true1,True,yes等价与true memory_available
变量值为false0,False,no等价与false not memory_available
第一个变量值在第二个变量列表中 ansible_distribution in supported_distros

单条件判断

# when 示例
tasks:
 - name:  install service
   yum:
     name: "{{ my_service }}"
   when: mysql_service is defined

多条件判断

使用and表示且,or表示或。也可以使用列表,表示且的关系

# and 示例
tasks:
 - name: add user when hosts in groups dev and user is defined
   user:
     name: "{{ my_user }}"
   when: "'dev' in group_names and my_user is defined"

# 列表表示且示例 以下条件与上述条件等同
tasks:
 - name: add user when hosts in groups dev and user is defined
   user:
     name: "{{ my_user }}"
   when: 
      - "'dev' in group_names"
      - my_user is defined

# or 示例
tasks:
 - name: add user when hosts in groups dev and user is defined
   user:
     name: "{{ my_user }}"
   when: "'dev' in group_names or 'test' in group_names"

循环 loop

使用loop进行循环,一般在loop中设置一个变量,这个变量是一个列表,使用item来调用loop循环中的内容。
loop中的一个项目可以包含多个内容,使用item.name来调用循环中的内容。
looptask对齐

# 单列表循环示例
--- 
- hosts: all
  vars:
    packages_for_install:
      - firewalld
      - gcc
  tasks:
    - name: install pascages
      yum:
        name: "{{ item }}"
      loop: "{{ packages_for_install }}"

# 多列表循环示例
# 下面这个loop的变量中有两项,每项都包括name和groups。只循环两次
--- 
- hosts: all
  tasks:
      - name: Users exist and are in the correct groups
        user:
          name: "{{ item.name }}"
          groups: "{{ item.groups }}"
          state: present
        loop: 
          - name: jane
            groups: whell
          - name: joe
            groups: root

task执行结果控制

ansible-playbook中,我们可以通过一些方法控制task的结果。以便再特定情况下执行对应的操作

控制changed

Handlers

在某些情况下,我们可能希望只有task进行了实际改变时才执行某些操作,比如只有配置文件变更了,才重启对应的服务。Handlers提供了这种功能。
handlers中定义要执行的操作名称,在task中使用notify指定要执行的操作名称。当task的结果为changed时,就会执行指定的handler
handlerstasks对齐
notifytask对齐

执行条件

只有在task中被notify,并且这个task的状态是changed,才会执行对应的handler
handlers只有在tasks都执行成功的情况下,才会执行
多次notifyhandler只会执行一次
如果handlers中定义的名称没有在tasksnotify,就不会执行
多个相同名称的handlers只会执行第一个

执行顺序

默认只有在成功执行完tasks中的所有操作后才执行handlers中的操作
handler的执行顺序按照它们在handlers中定义的顺序执行,与notify的顺序无关

强制执行handlers

即使tasks中出现错误,也执行handlers中的内容。
只是忽略tasks中的错误,实际是否执行还取决于是否notify changed。

# 示例
---
- hosts: all
  force_handlers: yes
  tasks:
    - name:
       template:
        src: /var/lib/templates/demo.example.conf.template
        dest: /etc/httpd/conf.d/demo.example.conf
       notify:
        - restart mysql
        - restart apache
  handlers:
     - name: restart apache
       service:
        name: httpd
        state: restarted    
     - name: restart mysql
       service:
         name: mariadb
         state: restarted

控制task是否更改

为了更好的使用handlersansible允许我们使用changed_when语句对task的结果进行变更(ok/changed)。
注意:在执行命令或脚本时,即使实际没有更改任何东西,task的结果默认也为changed

---
- hosts: all
  tasks:
    # task的结果为ok
    - name : get Kerbores credentials as 'admin'
      shell: echo "{{ krb_admin_pass }}" | kinit -f admin
      changed_when: false
    # 只有shell命令的结果包括"Success"时结果才为changed
    - shell:
        cmd: /usr/local/bin/upgrade-database
      register: command_result
      changed_when: "'Success' in command_result.stdout"
      notify:
        - restart_database

  handlers:
    - name: restart_database
      service:
        name: mariadb
        state: restarted

控制failed

默认情况下,如果一个task失败了,该节点上后续的task都不会继续执行

忽略错误

要忽略失败的task,继续执行其他的task,可以使用ignore_errors

tasks: 
 - name: Run the user creation script
   command: /usr/local/bin/create_users.sh
   ignore_errors: yes

在出现错误时执行指定的操作

使用block-rescue-always可以执行一系列的操作

  • block
    里面可以放置多个task,可以将when语句与block对齐,将条件应用于block中的所有task
  • rescue
    block对齐,当block中的task执行失败时,执行这部分task
  • always
    block对齐,无论block中的task是否失败,都执行这部分内容
---
- hosts: all
  tasks:
    - block: 
       # 创建一个1500M的逻辑卷 
       - name: create lv size 1500
         lvol:
           vg: research
           lv: np
           size: 1500
      rescue:
       # 如果创建失败,创建个800M的逻辑卷
       - name: create lv size 800
         lvol:
           vg: research
           lv: np
           size: 800
      always:
       # 格式化
       - name: Makes a filesystem
         filesystem:
           device: /dev/research/np
           fstype: xfs

控制task是否失败

使用failed_when控制task是否失败,当前task会执行,之后的task不会执行
使用fail模块可以使task失败并输出特定的错误消息。

---
- hosts: all
  tasks:
    - name : Run the user creation script
      command: /usr/local/bin/create_users.sh
      register: command_result
      failed_when: "'Password missing' in command_result.stdout"

    - name: Run the user creation script
      command: /usr/local/bin/create_users.sh
      register: command_result
      ignore_errors: yes

    - name: Report script failure
      fail:
        msg: "The password is missing in the output"
      when: "'Password missing' in command_result.stdout"

猜你喜欢

转载自blog.51cto.com/13540167/2607079