第六章、Ansible循环+判断实施任务控制

第六章、Ansible循环+判断实施任务控制

目录

一. 编写循环和条件任务

1、较早之前的循环关键字

1.1、with_items迭代列表

1.2、with_dict迭代字典

1.3、with_fileglob迭代文件

1.4、with_lines迭代行

1.6、with_sequence 排序列

1.7、with_random_choice

2、将Register变量与Loop一起使用

2.1、使用加密算法对字符串进行hash加密

二、ansible判断

1、判断变量的一些tests:

2、判断执行结果的一些tests

3、判断路径的一些tests

4、判断字符串的一些tests

5、其他的一些tests

三、处理任务失败

1、红帽CE例题

五、判断与错误处理

六、过滤器扩展题


一. 编写循环和条件任务

通过利用循环,我们无需编写多个使用同一模块的任务。例如,他们不必编写五个任务来确保存在五个用户,而是只需编写一个任务来对含有五个用户的列表迭代,从而确保它们都存在。

Ansible支持使用loop关键字对一组项目迭代任务。可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。

1、较早之前的循环关键字

1.1、with_items迭代列表

比如Linux中依次需要安装多个软件包时,我们可以使用with_items迭代功能进行实现

例如:

安装httpd、samba、samba-client软件包时

[root@node1 ~]#  Vim b.yml
---
- name: install packages
  hosts: node1
  tasks:
    - name: install pks
      yum:
        name: "{{ item }}"     #使用item可选择多个值循环判断
        state: present
      with_items:
        - httpd
        - samba
        - samba-client

下载服务时可以下载多个

1.2、with_dict迭代字典

item.key对应着是字典的键

:前为键 后为值

item.value对应着字典的值

[root@node1 ~]# Vim c.yml
---
- name: test
  hosts: node1
  tasks:
    - name: debug
      debug:
        msg: "{{item.key}} & {{item.value}}"     #匹配两个数值
      with_dict:
        address: 1
        netmask: 2
        gateway: 3

也可以单独只显示{{item.key}} 的键

1.3、with_fileglob迭代文件

例如拷贝多个文件到受控主机上时,可以使用

[root@server ~]#   Vim d.yml
---
- name: test
  hosts: node1
  tasks:
    - name: cp file
      copy:
        src: "{{ item }}"
        dest: /tmp/
      with_fileglob:     #匹配以/tmp目录下的以后缀.sh  .py的文件
        - /tmp/*.sh
        - /tmp/*.py

1.4、with_lines迭代行

With_lines可以将命令行的输出结果按行迭代

[root@server ~]# Vim e.yml
---
- name: test
  hosts: node1
  tasks:
    - name: cp file
      copy:
        src: "{{ item }}"         #返回数值
        dest: /tmp/
      with_lines:
        - find  /etc/ansible  -name  "*.yml"    #所找查的结果将返回给 {{ item }}值

1.5、with_nested嵌套迭代

a和b分别与1、2、3连接组合

也就是互相相乘

[root@server ~]#  Vim f.yml
---
- name: test
  hosts: node1
  tasks:
    - name: debug
      debug:
        msg: "{{ item[0] }} & {{ item[1] }}"     #[0]代表先匹配第一组,[1]代表第二组
      with_nested:
        - [a,b]
        - [1,2,3]

规则:a1、a2、a3。b1、等

1.6、with_sequence 排序列

(start是从什么开始,end结束、stride每隔多少)

[root@server ~]# Vim g.yml
---
- name: test
  hosts: node1
  tasks:
    - name: debug
      debug:
        msg: "{{ item }}"
      with_sequence:         #类似于匹配从1-5开始,中间间隔2位数
        start=1
        end=5
        stride=2

第一个匹配的值是1,3,5

也可以将 stride=—2 做为递减

1.7、with_random_choice

随机获得列表中的一个值

[root@server ~]#  Vim h.yml
---
- name: test
  hosts: node1
  tasks:
    - name: debug
      debug:
        msg: "{{ item }}"
      with_random_choice:     #在以下值中随机匹配
        - 1
        - 2
        - a
        - b
        - c

2、将Register变量与Loop一起使用

Loop:

现在loop已经替代了with,更多的是loop配合过滤器(Register)进行使用

过滤器:

常用字符串有关的过滤器

[root@server ~]#  Vim h.yml
---
- name: test
  hosts: node1
  vars:                                    #定义好变量以便调用
    testvar: "abc123ABC 666"
    testvar1: " abc "
  tasks:
    - name: debug1
      debug:
        msg: "{{ testvar | upper }}"  #upper将字符串转换成纯大写
 
    - name: debug2
      debug:
        msg: "{{ testvar | lower }}"  #lower将字符串转换成纯小写
 
    - name: debug3
      debug:
        msg: "{{ testvar1 | trim }}"  #trim将字符串的首尾空格去掉
 
    - name: debug4
      debug:
        msg: "{{ testvar | length }}"   #length求字符串的长度

2.1、使用加密算法对字符串进行hash加密

创建一个用户cy,并且设置密码为redhat,密码采用SHA512哈希格式进行密码加密

[root@server ~]# Vim h.yml
---
- name: create user
  hosts: node1
  tasks:
    - name: create cy
      user:
        name: cy
        password: "{{ 'redhat' | password_hash('sha512' )}}"

二、ansible判断

Ansible可使用conditionals在符合特定条件时执行任务或play。例如,可以利用一个条件在Ansible安装或配置服务前确定受管主机上的可用内存。

我们可以利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔值的运算符。

以下场景说明了在Ansible中使用条件的情况:

  • 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
  • Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。例如,如果某一程序失败,则将路过批处理。
  • 可以利用Ansible事实来确定受管主机网络配置,并决定要发送的模板文件(如,网络绑定或中继)。
  • 可以评估CPU的数量,来确定如何正确调节某一Web服务器。
  • 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。例如,测试服务配置文件的MD5检验以和查看服务是否已更改。

条件任务语法

when语句用于有条件地运行任务。它取要测试的条件为值。如果条件满足,则运行任务。如果条件不满足,则跳过任务。

判断运算符 :

“==” “!=” “>” “<” “>=” “<=” “and” “or” “not” is in

img

每次执行完一个任务,不管成功与失败,都会将执行的结果进行注册,可以使用这个注册的变量来进行when

1、判断变量的一些tests:

Defined:判断变量是否已经定义,已定义则返真

Undefined:判断变量是否已经定义,未定义则返真

None:判断变量值是否为空,如果变量已经定义,但是变量值为空,则返真

[root@server ~]#  Vim  test.yml
---
- name: test
  hosts: node1
  vars:
    aa: 11
    cc:
  tasks:
    - name: create debug1
      debug:
        msg: a
      when: aa is defined       #通过when来判断aa这个值是否存在,存在则运行msg命令行
 
                                                不存在则跳过该值
    - name: create debug2
      debug:
        msg: ab
      when: bb is undefined   #bb没有被定义
 
    - name: create debug3
      debug:
        msg: abc
      when: cc is none  #意为cc是没有值的

判断的依据为when:只有做出了正确的判断,数据才会成功运行,如若判断错误则会跳过。

2、判断执行结果的一些tests

\bullet Success/successed:通过任务的返回信息判断执行状态,任务执行成功返回真

\bullet Failure/failed:通过执行任务的返回信息判断执行状态,任务执行失败则返回真

\bullet Change/changed:通过任务的返回信息判断执行状态,任务返回状态为changed则返回真

\bullet Skip/skipped:通过任务的返回信息判断执行状态,当任务没有满足条件,而被跳过执行,则返回真。

[root@server ~]#  Vim test2.yml
---
- name: test
  hosts: node1
  vars:
    aa: 11
  tasks:
    - name: shell
      shell:
        cmd: ls /mnt
      when: aa == 11
      register: dd
 
    - name: create debug1 success
      debug:
        msg: chenyu success
      when: dd is success            #判断存在—成功
          
    - name: create debug2 fail
      debug:
        msg: chenyu failed
      when: dd is failed      #判断是失败的

    - name: create debug3 change
      debug:
        msg: chenyu changed
      when: dd is changed       #发生改变
 
    - name: create debug4 skip
      debug:
        msg: chenyu skip
      when: dd is skip      #发生跳过

3、判断路径的一些tests

注意:以下tests的判断均对ansible主机中的路径,与目标主机无关。

\bullet file:判断路径是否是一个文件

\bullet directory:判断路径是否是一个目录

\bullet link:判断路径是否是一个软连接

\bullet mount:判断路径是否是一个挂载点

\bullet exists:判断路径是否存在

[root@server ~]#  vim test.yml
 ---
- name: test
  hosts: node1
  vars:                    #这里的判断是在主机中进行的
    a1: /test/file1
    a2: /test/
    a3: /test/softlinka
    a4: /test/hardlinka
    a5: /boot/
 
  tasks:
    - name: debug1
      debug:
        msg: this is file
      when: a1 is file     #判断a1为文件
 
    - name: debug2
      debug:
        msg: "this is directory"
      when: a2 is directory    #判断a2为目录
 
    - name: debug3
      debug:
        msg: "this is softlink"
      when: a3 is link   #软连接
 
    - name: debug4
      debug:
        msg: "this is hardlink"
      when: a4 is link
 
    - name: debug5
      debug:
        msg: "this is mount directory"
      when: a5 is mount   #挂载目录
 
    - name: debug6
      debug:
        msg: "this is exists"
      when: a1 is  exists

4、判断字符串的一些tests

lower:判断包含字母的字符串中的字母是否纯小写

upper:判断包含字母的字符串中的字母是否纯大写

[root@server ~]#  vim test.yml
---
- name: test
  hosts: node1
  vars:
    a1: abc
    a2: ABC
    a3: a1b
 
  tasks:
    - name: debug1
      debug:
        msg: this string is all lower
      when: a1 is lower
 
    - name: debug2
      debug:
        msg: this string is all upper
      when: a2 is upper
 
    - name: debug3
      debug:
        msg: chenyu
      when: a3 is lower

5、其他的一些tests

string:判断对象是否是一个字符串

number:判断对象是否一个数字

[root@server ~]#  vim test.yml
---
- name: test
  hosts: node1
  vars:
    a1: 1
    a2: "1"
    a3: a
 
  tasks:
    - name: debug1
      debug:
        msg: this is number
      when: a1 is number
 
    - name: debug2
      debug:
        msg: this is string
      when: a2 is string
 
    - name: debug3
      debug:
        msg: this is string
      when: a3 is string

三、处理任务失败

Ansible评估任务的返回代码,从而确定任务是成功还是失败。通常而言,当任务失败时,Ansible将立即在该主机上中止play的其余部分并且跳过所有后续任务。

但有些时候,可能希望即使在任务失败时也继续执行play。例如,或许预期待定任务有可能会失败,并且希望通过有条件地运行某项其他任务来修复。

Ansible有多种功能可用于管理任务错误。

定义参数:

block/rescue/always: 限制性block,如果执行失败,则执行rescue,无论是block还是rescue执行失败还是成功,在最后都执行always

执行流程:

当block任务执行成功的时候,则执行always任务

当block任务执行失败的时候,则执行resvue任务,最后执行always任务(block任务执行失败,但是playbook不中止)

1、红帽CE例题

例题:

创建一个名为/etc/ansible/lv.yml 的playbook,它将在所有受管节点上运行以执行下列任务:

创建符合以下要求的逻辑卷:

​ 逻辑卷创建在research卷组中

​ 逻辑卷名称为data

​ 逻辑卷大小为1500MiB

使用ext4文件系统格式化逻辑卷

如果无法创建请求的逻辑卷大小,应显示错误消息

Could not create logical volume of that size,并且应改为使用大小 800MiB。

如果卷组research 不存在 ,应显示错误消息

​ Volume group does not exist。

不要以任何方式挂载逻辑卷

前提:在node1、node2上添加一块硬盘,然后新建卷组

Node1的卷组大小为2G 卷组名为research

Node2的卷组大小为1G 卷组名为research

1、vim vg.yml
--- 
- name: create vg for node1
  hosts: node1
  tasks:
    - name: create partition
      parted:
        device: /dev/sdb
        number: 1
        part_type: primary
        part_start: 10MiB
        part_end: 2058MiB
        state: present
 
    - name: create vg research
      lvg:
        vg: research
        pvs: /dev/sdb1
 
- name: create vg for node2
  hosts: node2
  tasks:
    - name: create partition for node2
      parted:
        device: /dev/sdb
        number: 1
        part_type: primary
        part_start: 10MiB
        part_end: 1034MiB
        state: present
 
    - name: create vg research for node2
      lvg:
        vg: research
        pvs: /dev/sdb1

2、执行vg.yml来给node1、node2创建vg

Ansible-playbook vg.yml

3、新建lv.yml,满足题目需求

Vim lv.yml
---
- name: create lvm
  hosts: node1,node2
  tasks:
    - name: create lv
      block:
        - name: create lvm 1500M
          lvol:
            vg: research
            lv: data
            size: 1500M
 
      rescue:
        - name: output fail message
          debug:
            msg: Could not create logical volume of that size
 
        - name: create lvm 800M
          lvol:
            vg: research
            lv: data
            size: 800M
 
      always:
        - name: format lvm
          filesystem:
            fstype: ext4
            dev: /dev/research/data
      when: "'research' in ansible_facts.lvm.vgs"
      #也可以用when: "'research' in ansible_lvm.vgs"
 
    - name: serach not exists
      debug:
        msg: Volume group does not exist
      when: "'research' not in ansible_facts.lvm.vgs"
      #也可以用when: "'research'  not in ansible_lvm.vgs"

五、判断与错误处理

fail模块可用于中断剧本,但我们一般是不会无故中断,除非在满足条件的情况下可以中断,经常和when一起用

[root@server ~]#  Vim c.yml
---
- name: test
  hosts: node1
  tasks:
    - name: shell
      shell:
        cmd: echo 'this is a string for testing--error'
      register: return_value            #定义值的变量
 
    - name: fail
      fail:
        msg: Conditions established,Interrupt running playbook
      when: "'error' in return_value.stdout"     #如果当该判断识别为真命题 则会手动停止
                                                                如为假命题则会跳过
 
    - name: debug
      debug:
        msg: I never execute,because the playbook has stopped

或者使用failed_when

---
- name: test
  hosts: node1
  tasks:
    - name: debug
      debug:
        msg: I execute normally
 
    - name: shell
      shell:
        cmd: echo 'this is a string testing--error'
      register: return_value
      failed_when: "'error' in return_value.stdout"        #使用这个也可以直接判断是否中断
 
    - name: debug2
      debug:
        msg: chenyu

ignore_errors: yes 跳过错误、忽略错误

例子:

---
- name: test
  hosts: node1
  tasks:
    - name: debug1
      debug:
        msg: "{{ ansible_fqdn }}"

    - name: debug2
      debug:
        msg: "{{ ansible_ip }}"   #这个变量是不存在的,但是会直接跳过
      ignore_errors: yes
 
    - name: create file
      file:
        path: /tmp/abc
        state: touch

Changed_when:可以修改任务执行后的最终状态

---
- name: test
  hosts: node1
  tasks:
    - name: debug1
      debug:
        msg: "{{ansible_fqdn}}"
      changed_when: true              #改变执行任务的颜色(误为已改变执行的)

或者可以让任务执行状态显示失败

---
- name: test
  hosts: node1
  tasks:
    - name: shell
      shell:
        cmd: ls /tmp
      changed_when: false         #会报红

六、过滤器扩展题

补充过滤器:

[root@foundation0 ansible]# cat filterstr.yml
---
- name: 过滤器
  hosts: servera
  vars:
    testvar: "abc123ABC 666"
    testvar1: " abc "
    testvar2: "123456789"
    testvar3: "1a2b,@#$%^&"
  tasks:
    - name: 将字符串转换成纯大写
    debug:	
      #将字符串转换成纯大写
      msg: "{{ testvar | upper }}"

    - name: 将字符串转换成纯小写
    debug:	
      #将字符串转换成纯小写
      msg: "{{ testvar | lower }}"

    - name: 将字符串首字母大写,之后的所有字母纯小写
    debug:	
      #将字符串首字母大写,之后的所有字母纯小写
      msg: "{{ testvar | capitalize }}"

    - name: 返回字符串的第一个字符
    debug:	
      #返回字符串的第一个字符
      msg: "{{ testvar | first }}"

    - name: 返回字符串的最后一个字符 
    debug:	#返回字符串的最后一个字符
      msg: "{{ testvar | last }}"

    - name: 将字符串开头和结尾的空格去除
    debug:	#将字符串开头和结尾的空格去除
      msg: "{{ testvar1 | trim }}"

    - name: 将字符串放在中间,并且设置字符串的长度为30,字符串两边用空格补齐30位长
    debug:
      #将字符串放在中间,并且设置字符串的长度为30,字符串两边用空格补齐30位长
      msg: "{{ testvar1 | center(width=30) }}"

    - name: 返回字符串长度,length与count等效,可以写为count
    debug:
      #返回字符串长度,length与count等效,可以写为count
      msg: "{{ testvar2 | length }}"

    - name: 将字符串转换成列表,每个字符作为一个元素
    debug:
      #将字符串转换成列表,每个字符作为一个元素
      msg: "{{ testvar3 | list }}"

    - name: 将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
    debug:
      #将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
      #shuffle的字面意思为洗牌
      msg: "{{ testvar3 | shuffle }}"

[root@foundation0 ansible]# ansible-playbook filterstr.yml

和数字操作有关的过滤器

[root@foundation0 ansible]# cat filterdata.yml
---
- name: this playbook
  hosts: servera
  vars:
    testvar4: -1
  tasks:
    - name: 将对应的值转换成int类型
      debug:
      #将对应的值转换成int类型
      #ansible中,字符串和整形不能直接计算,比如{{ 8+'8' }}会报错
      #所以,我们可以把一个值为数字的字符串转换成整形后再做计算
        msg: "{{ 8+('8' | int) }}"

    - name: 将对应的值转换成int类型,如果无法转换,默认返回0
      debug:
      #将对应的值转换成int类型,如果无法转换,默认返回0
      #使用int(default=6)或者int(6)时,如果无法转换则返回指定值6
        msg: "{{ 'a' | int(default=6) }}"

    - name: 将对应的值转换成浮点型,如果无法转换,默认返回'0.0'
      debug:
      #将对应的值转换成浮点型,如果无法转换,默认返回'0.0'
        msg: "{{ '8' | float }}" 

    - name: 当对应的值无法被转换成浮点型时,则返回指定值’8.88‘
      debug:
      #当对应的值无法被转换成浮点型时,则返回指定值’8.88‘
        msg: "{{ 'a' | float(8.88) }}"

    - name: 获取对应数值的绝对值
      debug:
      #获取对应数值的绝对值
        msg: "{{ testvar4 | abs }}"

    - name: 四舍五入
      debug:
      #四舍五入 
        msg: "{{ 12.5 | round }}"
  
    - name: 取小数点后五位
      debug:
      #取小数点后五位 
        msg: "{{ 3.1415926 | round(5) }}"

    - name: 从0到100中随机返回一个随机数
      debug:
      #从0到100中随机返回一个随机数
        msg: "{{ 100 | random }}"

    - name: 从5到10中随机返回一个随机数
      debug:
      #从5到10中随机返回一个随机数
        msg: "{{ 10 | random(start=5) }}"

    - name: 从5到15中随机返回一个随机数,步长为3
      debug:
      #从5到15中随机返回一个随机数,步长为3
      #步长为3的意思是返回的随机数只有可能是5、8、11、14中的一个
        msg: "{{ 15 | random(start=5,step=3) }}"

    - name: 从0到15中随机返回一个随机数,这个随机数是5的倍数
      debug:
      #从0到15中随机返回一个随机数,这个随机数是5的倍数
        msg: "{{ 15 | random(step=5) }}"

**文件或目录类过滤器**

[root@foundation0 ansible]# cat filterfile.yml
---
- name: 文件或目录类的过滤器
  hosts: servera
  tasks:
    - name: 使用sha1算法对字符串进行哈希
      debug:
        msg: "{{ '123456' | hash('sha1') }}"

    - name: 使用md5算法对字符串进行哈希
      debug:
        msg: "{{ '123456' | hash('md5') }}"

    - name: 获取到字符串的校验和,与md5哈希值一致
      debug:
        msg: "{{ '123456' | checksum }}"

    - name: 使用sha256算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值
      debug:
        msg: "{{ '123456' | password_hash('sha256') }}"

    - name: 使用sha256算法对字符串进行哈希,并使用指定的字符串作为"盐"
      debug:
        msg: "{{ '123456' | password_hash('sha256','mysalt') }}"

    - name: 使用sha512算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值
      debug:
        msg: "{{ '123123' | password_hash('sha512') }}"

    - name: 使用sha512算法对字符串进行哈希,并使用指定的字符串作为"盐"
      debug:
        msg: "{{ '123123' | password_hash('sha512','ebzL.U5cjaHe55KK') }}"
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值