Ansible循环+判断

  • Post author:
  • Post category:其他




循环



1









with_items




迭代列表

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

例如:

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

Vim b.yml

– name: install packages

hosts: node1

tasks:

– name: yum_repo1

yum_repository:

file: server

name: baseos

description: rhel8

baseurl: file:///mnt/BaseOS

enabled: yes

gpgcheck: no

– name: yum_repo2

yum_repository:

file: server

name: appstream

description: appstream

baseurl: file:///mnt/AppStream

enabled: yes

gpgcheck: no

– name: mount cdrom

mount:

src: /dev/cdrom

path: /mnt

fstype: iso9660

state: mounted

– name: install pks

yum:

name: “{

{item}}”

state: present

with_items:

– httpd

– samba

– samba-client



2









with_dict




迭代字典

item.key对应着是字典的键,item.value对应着字典的值

Vim c.yml

– name: test

hosts: node1

tasks:

– name: debug

debug:

msg: “{

{item.key}} & {

{item.value}}”

with_dict:

address: 1

netmask: 2

gateway: 3



3  with_fileglob




迭代文件

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

Vim d.yml

– name: test

hosts: node1

tasks:

– name: cp file

copy:

src: “{

{item}}”

dest: /tmp/

with_fileglob:

– /tmp/*.sh

– /tmp/*.py



4  with_lines




迭代行

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

Vim e.yml

– name: test

hosts: node1

tasks:

– name: cp file

copy:

src: “{

{item}}”

dest: /tmp/

with_lines:

– find  /etc/ansible  -name  “*.yml”



5  w




i




t




h




_nested




嵌套迭代

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

Vim f.yml

– name: test

hosts: node1

tasks:

– name: debug

debug:

msg: “{

{item[0]}} & {

{item[1]}}”

with_nested:

– [a,b]

– [1,2,3]



6  with_sequence




排序列




(start




是从什么开始,




end




结束




stride




每隔多少




)

Vim g.yml

– name: test

hosts: node1

tasks:

– name: debug

debug:

msg: “{

{item}}”

with_sequence:

start=1

end=5

stride=1



7  with_random_choice




随机获得列表中的一个值

Vim h.yml

– name: test

hosts: node1

tasks:

– name: debug

debug:

msg: “{

{item}}”

with_random_choice:

– 1

– 2

– a

– b

– c

Loop:

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

过滤器:

常用字符串有关的过滤器

– name: test

hosts: node1

vars:

testvar: “abc123ABC 666”

testvar1: ” abc ”

tasks:

– name: debug1

debug:

#upper将字符串转换成纯大写

msg: “{

{testvar | upper}}”

– name: debug2

debug:

#lower将字符串转换成纯小写

msg: “{

{testvar | lower}}”

– name: debug3

debug:

#trim将字符串的首尾空格去掉

msg: “{

{testvar1 | trim}}”

– name: debug4

debug:

#length求字符串的长度

msg: “{

{testvar | length}}”

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

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

– name: create user

hosts: node1

tasks:

– name: create chenyu

user:

name: chenyu

password: “{

{‘redhat’ | password_hash(‘sha512’)}}”


补充过滤器:

[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’) }}”



ansible




判断

When

判断运算符

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

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

判断变量的一些tests

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

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

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

Vim  test.yml

– name: test

hosts: node1

vars:

aa: 11

cc:

tasks:

– name: create debug1

debug:

msg: a

when: aa is defined

– name: create debug2

debug:

msg: ab

when: bb is undefined

– name: create debug3

debug:

msg: abc

when: cc is none

判断执行结果的一些tests

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

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

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

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

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

判断路径的一些tests

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

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

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

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

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

exists:判断路径是否存在

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

– name: debug2

debug:

msg: “this is directory”

when: a2 is directory

– 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

判断字符串的一些tests

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

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

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

其他的一些tests

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

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

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

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

例题:

创建一个名为/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一起用

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



版权声明:本文为weixin_54822053原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。