一、ansible中循环的介绍
我们通过”{{groups.ungrouped}}”获取到了未分组的返回信息,并使用关键字”with_items”接收了返回信息,然后使用debug模块输出了名为”item”变量的变量值,”with_items”关键字会把返回的列表信息自动处理,将每一条信息单独放在一个名为”item”的变量中,我们只要获取到名为”item”变量的变量值,即可循环的获取到列表中的每一条信息。
应用格式:
- 对迭代项的引用,固定变量名为 "item";
- 要在 task 中使用 with_items 或 loop 关键字给定要迭代的元素列表;
示例:
---
- hosts: web
remote_user: root
tasks:
- name: test xunhuan
debug:
msg: "{{ item }}"
with_items: ["1","2","3"]
# - 1
# - 2
# - 3
[root@k8s-master-1 for]# ansible-playbook -C test1.yaml
PLAY [web] **********************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.134.138]
TASK [test xunhuan] *************************************************************************************************
ok: [192.168.134.138] => (item=1) => {
"msg": "1"
}
ok: [192.168.134.138] => (item=2) => {
"msg": "2"
}
ok: [192.168.134.138] => (item=3) => {
"msg": "3"
}
PLAY RECAP ******************************************************************************************************
192.168.134.138 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
示例2:稍微复杂点的
---
- hosts: web
remote_user: root
tasks:
- name: test xh
debug:
msg: "{{ item.test1 }}"
with_items:
- { test1: a,test2: b }
- { test1: c,test2: d }
# 上例中自定义列表中的每一个条目都是一个对象,我们可以通过对象的属性对应的”键”,获取到对应的”值”,
# 如上例所示,第一个条目的test1键对应的值是a,第二个条目的test1键对应的值是c,所以执行上例playbook以后,”a”和”c”会被输出:
示例3:
比如:在不会使用循环之前,我们要在同一目录下创建4个文件,代码如下:
--
- hosts: web
remote_user: root
tasks:
- file:
path: "/opt/a"
state: touch
- file:
path: "/opt/b"
state: touch
- file:
path: "/opt/c"
state: touch
- file:
path: "/opt/d"
state: touch
这样看着很臃肿,可以使用循环来实现创建文件
--
- hosts: web
remote_user: root
tasks:
- name: touch file
file:
path: "{{ item }}"
state: touch
with_items: [ /tmp/a,/tmp/b,/tmp/c,/tmp/d ]
或者:
- /tmp/a
- /tmp/b
- /tmp/c
- /tmp/d
[root@k8s-master-1 for]# ansible-playbook -C test2.yaml
PLAY [web] ********************************************
TASK [Gathering Facts] ********************************
ok: [192.168.134.138]
TASK [touch file] *************************************
ok: [192.168.134.138] => (item=/tmp/a)
ok: [192.168.134.138] => (item=/tmp/b)
ok: [192.168.134.138] => (item=/tmp/c)
ok: [192.168.134.138] => (item=/tmp/d)
PLAY RECAP ********************************************
192.168.134.138 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
一、使用loop关键字 做循环
示例1:2..6版本之后 官方推荐使用loop循环
---
- hosts: web
remote_user: root
tasks:
- name: test xunhuan
debug:
msg: "{{ item }}"
loop: ["1","2","3"]
[root@k8s-master-1 for]# ansible-playbook -C test1.yaml
PLAY [web] ***********************************************************************************
TASK [Gathering Facts] **********************************************************************
ok: [192.168.134.138]
TASK [test xunhuan] ****************************************************************************
ok: [192.168.134.138] => (item=1) => {
"msg": "1"
}
ok: [192.168.134.138] => (item=2) => {
"msg": "2"
}
ok: [192.168.134.138] => (item=3) => {
"msg": "3"
}
PLAY RECAP ********************************************************************************************
192.168.134.138 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
示例2:
---
- hosts: web
remote_user: root
vars:
test:
- 1
- 2
tasks:
- name: test loop
debug:
msg: "{{ item }}"
loop: "{{ test }}"
[root@k8s-master-1 for]# ansible-playbook test1.yaml
PLAY [web] *****************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [192.168.134.138]
TASK [test loop] *************************************************************************************
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=2) => {
"msg": 2
}
PLAY RECAP ************************************************************************************************
192.168.134.138 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
示例3:使用循环批量创建用户
---
- hosts: web
remote_user: root
tasks:
- name: create group
group:
name: "{{ item }}"
state: present
loop:
- group1
- group2
- group3
- name: create user
user:
name: "{{ item.user }}"
group: "{{ item.group }}"
uid: "{{ item.uid }}"
state: present
create_home: yes
loop:
- { user: user1, group: group1, uid: 2001}
- { user: user2, group: group2, uid: 2002}
- { user: user3, group: group3, uid: 2003}
[root@k8s-master-1 for]# ansible-playbook -C test4.yaml
TASK [create group] ***********************************************************************************
changed: [192.168.134.138] => (item=group1)
changed: [192.168.134.138] => (item=group2)
changed: [192.168.134.138] => (item=group3)
TASK [create user] ************************************************************************************
changed: [192.168.134.138] => (item={u'group': u'group1', u'user': u'user1', u'uid': 2001})
changed: [192.168.134.138] => (item={u'group': u'group2', u'user': u'user2', u'uid': 2002})
changed: [192.168.134.138] => (item={u'group': u'group3', u'user': u'user3', u'uid': 2003})
PLAY RECAP ***************************************************************************
192.168.134.138 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
二、for循环
示例:
---
- hosts: web
tasks:
- shell: "ls /home"
register: returnvalue
- debug:
var: returnvalue
将shell模块执行后的返回值写入了名为”returnvalue”的变量中,然后使用debug模块输出了”returnvalue”变量的值,如下图
上例并没有借助循环重复调用shell模块,如果使用循环多次调用shell模块执行不同的命令,返回信息的格式还会和原来一样吗?
---
- hosts: web
remote_user: root
tasks:
- shell: "{{ item }}"
with_items:
- "ls /home"
- "ls /k8s"
register: returnvalue
- debug:
var: returnvalue
# 如上例所示,我们使用循环重复调用了shell模块两次,分别执行了两条命令,然后将shell模块的返回值存放到了”returnvalue”变量中,
# 最后使用debug模块输出了”returnvalue”变量的值.
[root@k8s-master-1 for]# ansible-playbook test3.yaml
TASK [shell] *************************************************************************
changed: [192.168.134.138] => (item=ls /home)
changed: [192.168.134.138] => (item=ls /k8s)
TASK [debug] **************************************************************************
ok: [192.168.134.138] => {
"returnvalue": {
"changed": true,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "ls /home",
"delta": "0:00:00.004525",
"end": "2023-07-26 16:15:29.446294",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "ls /home",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "ls /home",
"rc": 0,
"start": "2023-07-26 16:15:29.441769",
"stderr": "",
"stderr_lines": [],
"stdout": "job\nwuzhaobo",
"stdout_lines": [
"job",
"wuzhaobo"
]
},
{
"ansible_loop_var": "item",
"changed": true,
"cmd": "ls /k8s",
"delta": "0:00:00.004677",
"end": "2023-07-26 16:15:29.739434",
"failed": false,
"invocation": {
"module_args": {
"_raw_params": "ls /k8s",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"item": "ls /k8s",
"rc": 0,
"start": "2023-07-26 16:15:29.734757",
"stderr": "",
"stderr_lines": [],
"stdout": "data\netcd\nkubernetes",
"stdout_lines": [
"data",
"etcd",
"kubernetes"
]
}
]
}
}
PLAY RECAP *******************************************************************************
192.168.134.138 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 可以发现,当使用了循环以后,每次shell模块执行后的返回值都会放入一个名为”results”的序列中,其实,”results”也是一个返回值,
# 当模块中使用了循环时,模块每次执行的返回值都会追加存放到”results”这个返回值中,所以,我们可以通过”results”关键字获取到每次模块执行后的返回值,
# 示例如下:
---
- hosts: web
remote_user: root
tasks:
- shell: "{{ item }}"
with_items:
- "ls /home"
- "ls /k8s"
register: returnvalue
- debug:
msg: "{{ item.stdout }}"
with_items: "{{ returnvalue.results }}"
# 上例中,我们先使用循环重复的调用了shell模块,然后将shell模块每次执行后的返回值注册到了变量”returnvalue”中,之后,在使用debug模块时,通过返回值”results”获取到了之前每次执行shell模块的返回值(shell每次执行后的返回值已经被放入到item变量中),最后又通过返回值”stdout”获取到了每次shell模块执行后的标准输出.如下图:
或者使用for打印信息
---
- hosts: web
remote_user: root
tasks:
- shell: "{{ item }}"
# register: returnvalue
with_items:
- "ls /home"
- "ls /k8s"
register: returnvalue
- debug:
msg:
"{% for i in returnvalue.results %}
{{ i.stdout }}
{% endfor %}"
[root@k8s-master-1 for]# ansible-playbook test3.yaml
PLAY [web] *********************************
TASK [Gathering Facts] *********************
ok: [192.168.134.138]
TASK [shell] ******************************
changed: [192.168.134.138] => (item=ls /home)
changed: [192.168.134.138] => (item=ls /k8s)
TASK [debug] ******************************
ok: [192.168.134.138] => {
"msg": " job\nwuzhaobo data\netcd\nkubernetes "
}
PLAY RECAP *******************************
192.168.134.138 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#上例使用了一个for循环遍历了” returnvalue.results”列表,上例中for循环的语法为jinja2语言中的for循环语法,jinja2是一种模板语言,jinja2是一个基于python的模板引擎,所以,在ansible中,我们可以使用jinja2编写模板文件,然后再根据模板文件来生成配置文件,jinja2中也有一些控制语句结构,比如for循环,上例中使用的就是jinja2语法中的for循环,如果你执行了上例的playbook,你会发现,debug模块只执行了一次,msg中对应的信息是所有shell模块执行后的stdout返回值,因为debug模块只是输出了经过jinja2的for循环处理过的信息而已,debug模块并没有因为for循环而被重复的调用。
三、loop循环寄过滤器
1、loop代替with_list
loop 代替with_list:当处理列表是,列表不会别拉平
示例:
---
- hosts: web
remote_user: root
vars:
test:
- 1
- [ 1,a,b ]
- 2
tasks:
- name: test loop
debug:
msg: "{{ item }}"
loop: "{{ test }}"
[root@k8s-master-1 for]# ansible-playbook -C test1.yaml
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=[1, u'a', u'b']) => {
"msg": [
1,
"a",
"b"
]
}
ok: [192.168.134.138] => (item=2) => {
"msg": 2
}
2、loop+flatten 过滤器 代替 with_flattened
flatten过滤器可以替代 with_flattened,当处理多层嵌套时,列表中的层级都会被拉平
---
- hosts: web
remote_user: root
vars:
test:
- 1
- [ 1,a,b ]
- 2
tasks:
- name: test loop
debug:
msg: "{{ item }}"
loop: "{{ test | flatten }}"
[root@k8s-master-1 for]# ansible-playbook -C test1.yaml
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=a) => {
"msg": "a"
}
ok: [192.168.134.138] => (item=b) => {
"msg": "b"
}
ok: [192.168.134.138] => (item=2) => {
"msg": 2
}
3、loop+flatten 过滤器(加参数) 代替 with_items
loop+flatten 过滤器(加参数 levels=2 ) 代替 with_items:档处理多层嵌套列表时,只有列表的第2层会被拉平
---
- hosts: web
remote_user: root
vars:
test:
- [ 1,[a,b,[c,d]],[q,w]]
tasks:
- name: test loop
debug:
msg: "{{ item }}"
loop: "{{ test | flatten(levels=2) }}"
[root@k8s-master-1 for]# ansible-playbook -C test1.yaml
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=a) => {
"msg": "a"
}
ok: [192.168.134.138] => (item=b) => {
"msg": "b"
}
ok: [192.168.134.138] => (item=[u'c', u'd']) => {
"msg": [
"c",
"d"
]
}
ok: [192.168.134.138] => (item=q) => {
"msg": "q"
}
ok: [192.168.134.138] => (item=w) => {
"msg": "w"
}
可以看到 只有列表的第二层被拉平,如果levels=1,则只有列表第一层回被拉平
4、zip_longest过滤器+list过滤器代替 with_together。将两个列表中的元素”对齐合并”
zip_longest过滤器配合list过滤器 示例:
---
- hosts: web
remote_user: root
vars:
testlist1: [a,b,c]
testlist2: [1,2,3]
testlist3: [A,B,C,D]
tasks:
- name: test with_together
debug:
msg: "{{ item.0 }} - {{ item.1 }} - {{ item.2 }}"
with_together:
- "{{ testlist1 }}"
- "{{ testlist2 }}"
- "{{ testlist3 }}"
- name: test zip_longest+list
debug:
msg: "{{ item.0 }} - {{ item.1 }} - {{ item.2 }}"
loop: "{{ testlist1 | zip_longest(testlist2,testlist3) | list }}"
[root@k8s-master-1 for]# ansible-playbook -C test1.yaml
ok: [192.168.134.138] => (item=[u'a', 1, u'A']) => {
"msg": "a - 1 - A"
}
ok: [192.168.134.138] => (item=[u'b', 2, u'B']) => {
"msg": "b - 2 - B"
}
ok: [192.168.134.138] => (item=[u'c', 3, u'C']) => {
"msg": "c - 3 - C"
}
ok: [192.168.134.138] => (item=[None, None, u'D']) => {
"msg": " - - D"
}
TASK [test zip_longest+list] *************************************************************
ok: [192.168.134.138] => (item=[u'a', 1, u'A']) => {
"msg": "a - 1 - A"
}
ok: [192.168.134.138] => (item=[u'b', 2, u'B']) => {
"msg": "b - 2 - B"
}
ok: [192.168.134.138] => (item=[u'c', 3, u'C']) => {
"msg": "c - 3 - C"
}
ok: [192.168.134.138] => (item=[None, None, u'D']) => {
"msg": " - - D"
}
可以看到两个关键字 输出的结果是一样的,with_together、loop: zip_longest(var1,var2) | list
当多个列表使用with_together进行合并时,如果多个列表的长度不同,则使用最长的列表长度进行对其,由于段列表中的长度不够,会使用空置来对齐。
zip_longest和with_together 一样,对列表进行组合,但是还需要使用 list过滤 将组合后的数据列表化,
zip_longest 默认也是使用空值进行对齐,如果不想为空,可以设置默认值“fillvalue='W'”:此时,为空的就会用W 来代替
loop: "{{ testlist1 | zip_longest(testlist2,testlist3,fillvalue='W') | list }}"
zip_longest 是使用最长的列表进行对齐
zip:是使用最短的列表进行对齐
5、product过滤器配合list过滤器代替with_nested/with_cartesian
6、range过滤器配合list过滤器with_sequence
7、random函数 替代 with_random_choice
8、dictsort过滤器也可以替代with_dict
9、subelements过滤器with_subelements
二、with_items、with_list、with_flattened、with_together之间的区别和联系
一、with_items
示例1:
---
- hosts: web
remote_user: root
tasks:
- name: item_list
debug:
msg: "{{ item }}"
with_list:
- [1,2,3]
- [a,b]
[root@k8s-master-1 for]# ansible-playbook -C test2.yaml
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=2) => {
"msg": 2
}
ok: [192.168.134.138] => (item=3) => {
"msg": 3
}
ok: [192.168.134.138] => (item=a) => {
"msg": "a"
}
ok: [192.168.134.138] => (item=b) => {
"msg": "b"
}
二、with_list
从示例1可以看出,debug将每个小列表的值都输出了一遍,那如果我们想,将每个小列表作为一个整体输出,该怎么办呢?使用with_list关键字替换with_items、或者 with_flattened 关键字
示例2:
---
- hosts: web
remote_user: root
tasks:
- name: item_list
debug:
msg: "{{ item }}"
with_list:
- [1,2,3]
- [a,b,c]
[root@k8s-master-1 for]# ansible-playbook -C test2.yaml
ok: [192.168.134.138] => (item=[1, 2, 3]) => {
"msg": [
1,
2,
3
]
}
ok: [192.168.134.138] => (item=[u'a', u'b', u'c']) => {
"msg": [
"a",
"b",
"c"
]
}
PLAY RECAP ***************************************************************************
192.168.134.138 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
// 如上述信息所示,经过with_list处理后,每个嵌套在大列表中的小列表都被当做一个整体存放在item变量中,最终被debug作为一个小整体输出了,而不会像with_items一样将小列表”展开拉平”后一并将小列表中的元素循环输出。
// 当处理单层的简单列表时,with_list与with_items没有任何区别,只有在处理上例中的”嵌套列表”时,才会体现出区别,区别就是,with_items会将嵌套在内的小列表”拉平”,拉平后循环处理所有元素,而with_list则不会”拉平”嵌套的列表,with_list只会循环的处理列表(最外层列表)中的每一项。
三、with_flattened
当处理这种嵌套的列表时,如果想要实现”拉平”的效果,我们还能使用另外一个关键字,它就是with_flattened关键字。
示例:
---
- hosts: web
remote_user: root
tasks:
- name: test with_indexed_items
debug:
# msg: "index is {{ item.0}} value is {{ item.1 }}"
msg: "{{ item }}"
with_flattened:
- [ a,b,c ]
- [ 1,2,[ q,w ] ]
[root@k8s-master-1 for]# ansible-playbook -C test6.yaml
ok: [192.168.134.138] => (item=a) => {
"msg": "a"
}
ok: [192.168.134.138] => (item=b) => {
"msg": "b"
}
ok: [192.168.134.138] => (item=c) => {
"msg": "c"
}
ok: [192.168.134.138] => (item=1) => {
"msg": 1
}
ok: [192.168.134.138] => (item=2) => {
"msg": 2
}
ok: [192.168.134.138] => (item=q) => {
"msg": "q"
}
ok: [192.168.134.138] => (item=w) => {
"msg": "w"
}
四、with_together
with_together可以将两个列表中的元素”对齐合并”
---
- hosts: web
remote_user: root
tasks:
- name: item_list
debug:
msg: "{{ item }}"
with_together:
- [1,2,3]
- [a,b,c]
[root@k8s-master-1 for]# ansible-playbook -C test2.yaml
ok: [192.168.134.138] => (item=[1, u'a']) => {
"msg": [
1,
"a"
]
}
ok: [192.168.134.138] => (item=[2, u'b']) => {
"msg": [
2,
"b"
]
}
ok: [192.168.134.138] => (item=[3, u'c']) => {
"msg": [
3,
"c"
]
}
这就是with_together所谓的”对齐合并”功能
如果列表中的元素数量不同,使用with_together 关键字效果如下
ok: [192.168.134.138] => (item=[1, u'a']) => {
"msg": [
1,
"a"
]
}
ok: [192.168.134.138] => (item=[2, u'b']) => {
"msg": [
2,
"b"
]
}
ok: [192.168.134.138] => (item=[3, None]) => {
"msg": [
3,
null
]
}
总结:
在处理简单的单层列表时,他们没有区别,但是当处理嵌套的多层列表时,with_items与with_flattened会将嵌套列表”拉平展开”,循环的处理每个元素,而with_list只会处理最外层的列表,将最外层的列表中的每一项循环处理。
五、with_cartesian
上边了解了一些循环的关键字,其实还有很多,比如,现在有个需求,要在服务器创建a、b、c、三个目录,并且这3个目录都有相同的子目录,我们的实现方法有:
1、直接使用命令创建
[root@k8s-node-2 tmp]# mkdir -p a/test1
[root@k8s-node-2 tmp]# mkdir -p a/test2
[root@k8s-node-2 tmp]# mkdir -p b/test1
[root@k8s-node-2 tmp]# mkdir -p b/test2
[root@k8s-node-2 tmp]# mkdir -p c/test1
[root@k8s-node-2 tmp]# mkdir -p c/test2
2、使用通配符创建
[root@k8s-node-2 tmp]# mkdir -p {a,b,c}/{test1,test2}
3、使用ansible 的shell 模块创建
[root@k8s-master-1 for]# ansible web -m shell -a "mkdir -p /tmp/{a,b,c}/{test1,test2}"
4、使用ansible的循环来创建,关键字:with_cartesian
---
- hosts: web
remote_user: root
tasks:
- name: create file
file:
state: directory
path: /tmp/{{ item.0 }}/{{ item.1 }}
with_cartesian:
- [ a,b,c ]
- [ test1,test2 ]
[root@k8s-master-1 for]# ansible-playbook test5.yaml
changed: [192.168.134.138] => (item=[u'a', u'test1'])
changed: [192.168.134.138] => (item=[u'a', u'test2'])
changed: [192.168.134.138] => (item=[u'b', u'test1'])
changed: [192.168.134.138] => (item=[u'b', u'test2'])
changed: [192.168.134.138] => (item=[u'c', u'test1'])
changed: [192.168.134.138] => (item=[u'c', u'test2'])
5、或者使用”with_nested” 关键字,与with_cartesian的效果一致,不做演示
六、with_indexed_items
with_indexed_items的作用就是在循环处理列表时,为列表中的每一项添加“数字索引”,索引从0 开始。
示例:
---
- hosts: web
remote_user: root
tasks:
- name: test with_indexed_items
debug:
msg: "{{ item }}"
with_indexed_items:
- a
- b
- c
[root@k8s-master-1 for]# ansible-playbook -C test6.yaml
ok: [192.168.134.138] => (item=[0, u'a']) => {
"msg": [
0,
"a"
]
}
ok: [192.168.134.138] => (item=[1, u'b']) => {
"msg": [
1,
"b"
]
}
ok: [192.168.134.138] => (item=[2, u'c']) => {
"msg": [
2,
"c"
]
}
从上述信息可以看到“with_indexed_items”将添加过编号的每一项放入到item中,所以,我们也可以获取到他的编号:
---
- hosts: web
remote_user: root
tasks:
- name: test with_indexed_items
debug:
msg: "index is {{ item.0}} value is {{ item.1 }}"
with_indexed_items:
- a
- b
- c
[root@k8s-master-1 for]# ansible-playbook -C test6.yaml
ok: [192.168.134.138] => (item=[0, u'a']) => {
"msg": "index is 0 value is a"
}
ok: [192.168.134.138] => (item=[1, u'b']) => {
"msg": "index is 1 value is b"
}
ok: [192.168.134.138] => (item=[2, u'c']) => {
"msg": "index is 2 value is c"
}
如果遇到比较复杂的嵌套列表,with_indesed_items的处理如下:;
tasks:
- name: test with_indexed_items
debug:
msg: "index is {{ item.0}} value is {{ item.1 }}"
with_indexed_items:
- [ a,b,c ]
- [ 1,2,3 ]
- [ wu,kang,zhao ]
// 输出也没有问题
ok: [192.168.134.138] => (item=[0, u'a']) => {
"msg": "index is 0 value is a"
}
ok: [192.168.134.138] => (item=[1, u'b']) => {
"msg": "index is 1 value is b"
}
ok: [192.168.134.138] => (item=[2, u'c']) => {
"msg": "index is 2 value is c"
}
ok: [192.168.134.138] => (item=[3, 1]) => {
"msg": "index is 3 value is 1"
}
ok: [192.168.134.138] => (item=[4, 2]) => {
"msg": "index is 4 value is 2"
}
ok: [192.168.134.138] => (item=[5, 3]) => {
"msg": "index is 5 value is 3"
}
ok: [192.168.134.138] => (item=[6, u'wu']) => {
"msg": "index is 6 value is wu"
}
ok: [192.168.134.138] => (item=[7, u'kang']) => {
"msg": "index is 7 value is kang"
}
ok: [192.168.134.138] => (item=[8, u'zhao']) => {
"msg": "index is 8 value is zhao"
}
在嵌套一层 看看:
with_indexed_items:
- [ a,b,c ]
- [ 1,2,[ q,w ] ]
- [ wu,kang,zhao ]
可以看到 [ q,w ] 这个列表 并不会被完全拉平显示,没有”with_flattened” 强大
ok: [192.168.134.138] => (item=[5, [u'q', u'w']]) => {
"msg": "index is 5 value is [u'q', u'w']"
七、with_sequence
需求:要在目标主机创建5个目录,分别是 t2 、t4、t6、t8、t10、用ansible怎么实现?
使用:with_sequence 关键字
"with_sequence"可以帮助我们按照顺序生成数字序列,with_sequence的设置是"start=2 end=10 stride=2",其中start=2表示从2开始,end=10表示到10结束, stride=2表示步长为2,即从2到10每次增加2。
count=5表示数字序列默认从1开始,到5结束,默认步长为1
当我们不指定stride的值时,stride的值默认为1,但是,当end的值小于start的值时,则必须指定stride的值,而且stride的值必须是负数,
示例:
---
- hosts: web
remote_user: root
tasks:
- name: test with_sequenec
debug:
msg: "{{ item }}"
with_sequence:
start=2
end=10
stride=2
[root@k8s-master-1 for]# ansible-playbook -C test7.yaml
ok: [192.168.134.138] => (item=2) => {
"msg": "2"
}
ok: [192.168.134.138] => (item=4) => {
"msg": "4"
}
ok: [192.168.134.138] => (item=6) => {
"msg": "6"
}
ok: [192.168.134.138] => (item=8) => {
"msg": "8"
}
ok: [192.168.134.138] => (item=10) => {
"msg": "10"
}
八、with_random_choice
使用"with_random_choice"可以从列表的多个值中随机返回一个值
---
- hosts: web
remote_user: root
tasks:
- name: test with_indexed_items
debug:
msg: "{{ item }}"
with_random_choice:
- 1
- 2
- 3
- 4
[root@k8s-master-1 for]# ansible-playbook -C test6.yaml
ok: [192.168.134.138] => (item=3) => {
"msg": 3
}
每次只返回列表中随机的一个
ok: [192.168.134.138] => (item=4) => {
"msg": 4
}
九、with_dict
示例:
---
- hosts: web
remote_user: root
vars:
users:
wuzhaobo: male
kangkexin: female
tasks:
- debug:
msg: "{{ item }}"
with_dict: "{{ users }}"
[root@k8s-master-1 for]# ansible-playbook -C test7.yaml
ok: [192.168.134.138] => (item={u'key': u'wuzhaobo', u'value': u'male'}) => {
"msg": {
"key": "wuzhaobo",
"value": "male"
}
}
ok: [192.168.134.138] => (item={u'key': u'kangkexin', u'value': u'female'}) => {
"msg": {
"key": "kangkexin",
"value": "female"
}
}
// 从输出信息可以看出,字典格式的users变量经过"with_dict"处理后,字典中的每个键值对被放到了item变量中,而且,键值对中的"键"被放入了"key"关键字中,键值对中的"值"被放入了"value"关键字中,所以,我们可以通过key关键字和value关键字分别获取到字典中键值对的"键"和"值",
示例
---
- hosts: web
remote_user: root
vars:
users:
wuzhaobo: male
kangkexin: female
tasks:
- debug:
msg: "User name is: {{item.key}},User grnder is: {{item.value}}"
with_dict: "{{ users }}"
[root@k8s-master-1 for]# ansible-playbook -C test7.yaml
ok: [192.168.134.138] => (item={u'key': u'wuzhaobo', u'value': u'male'}) => {
"msg": "User name is: wuzhaobo,User grnder is: male"
}
ok: [192.168.134.138] => (item={u'key': u'kangkexin', u'value': u'female'}) => {
"msg": "User name is: kangkexin,User grnder is: female"
}
稍微复杂点的
示例:
---
- hosts: web
remote_user: root
vars:
users:
wuzhaobo:
name: wuzhaobo
age: 28
telephone: 123-456-789
kangkexin:
name: kangkexin
age: 26
telephone: 987-654-321
tasks:
- debug:
msg: "{{item}}"
//msg: "User {{item.key}} is {{item.value.name}},User age is {{item.value.age}},User telephone is:{{item.value.telephone}}"
with_dict: "{{users}}"
[root@k8s-master-1 for]# ansible-playbook -C test7.yaml
ok: [192.168.134.138] => (item={u'key': u'wuzhaobo', u'value': {u'age': 28, u'name': u'wuzhaobo', u'telephone': u'123-456-789'}}) => {
"msg": {
"key": "wuzhaobo",
"value": {
"age": 28,
"name": "wuzhaobo",
"telephone": "123-456-789"
}
}
}
ok: [192.168.134.138] => (item={u'key': u'kangkexin', u'value': {u'age': 26, u'name': u'kangkexin', u'telephone': u'987-654-321'}}) => {
"msg": {
"key": "kangkexin",
"value": {
"age": 26,
"name": "kangkexin",
"telephone": "987-654-321"
}
}
}
ok: [192.168.134.138] => (item={u'key': u'wuzhaobo', u'value': {u'age': 28, u'name': u'wuzhaobo', u'telephone': u'123-456-789'}}) => {
"msg": "User wuzhaobo is wuzhaobo,User age is 28,User telephone is:123-456-789"
}
ok: [192.168.134.138] => (item={u'key': u'kangkexin', u'value': {u'age': 26, u'name': u'kangkexin', u'telephone': u'987-654-321'}}) => {
"msg": "User kangkexin is kangkexin,User age is 26,User telephone is:987-654-321"
}
十、with_subelements
"with_subelements"可以处理一个复合结构的字典数据,在处理这个字典的同时,需要指定一个子元素,这个子元素的值必须是一个列表,之后,"with_subelements"会将子元素的列表中的每一项作为一个整体,将其他子元素作为一个整体,然后将两个整体组合成item。
示例:
---
- hosts: web
remote_user: root
vars:
users:
- name: wuzhaobo
age: 28
telephone: 123-456-789
hobby: [chi,he]
- name: kangkexin
age: 26
telephone: 987-654-321
hobby:
- chi
tasks:
- debug:
#msg: "{{item}}"
msg: "{{item.0.name}} 's hobby is {{item.1}}"
with_subelements:
- "{{users}}"
- hobby
[root@k8s-master-1 for]# ansible-playbook -C test7.yaml
ok: [192.168.134.138] => (item=[{u'age': 28, u'name': u'wuzhaobo', u'telephone': u'123-456-789'}, u'chi']) => {
"msg": "wuzhaobo 's hobby is chi"
}
ok: [192.168.134.138] => (item=[{u'age': 28, u'name': u'wuzhaobo', u'telephone': u'123-456-789'}, u'he']) => {
"msg": "wuzhaobo 's hobby is he"
}
ok: [192.168.134.138] => (item=[{u'age': 26, u'name': u'kangkexin', u'telephone': u'987-654-321'}, u'chi']) => {
"msg": "kangkexin 's hobby is chi"
}
上例中,我们使用“with_subelements”关键字处理了users 变量,并指定了一个属性 hobby .
“hobby属性" 是users中每个块序列的子元素,而且,hobby属性是一个 "键值对”,其"值"是一个列表