1.标准Loops
当我们想安装10个软件包的时候,为了避免写10个task来安装,我们可以直接使用标准的loops简单快速实现10个软件包的安装,下面例子是分别打印了one two这两个值:
#1.编写loop.yaml
[root@ansible01 ansible]# cat loops.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
debug: msg="name --> {{ item }}"
with_items:
- one
- two
#2.运行loop.yaml文件
[root@ansible01 ansible]# ansible-playbook loops.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=one) => {
"msg": "name --> one"
}
ok: [11.0.1.18] => (item=two) => {
"msg": "name --> two"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
with_items的值是python list数据结构,可以理解为每个task会循环读取list里面的值,然后key的名称是item,当然list里面也支持python字典,如下:
[root@ansible01 ansible]# cat loops2.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
debug: msg="name --> {{ item.key }} value -->{{ item.value}}"
with_items:
- {key: "one",value: "hello"}
- {key: "two",value: "wyx"}
[root@ansible01 ansible]# ansible-playbook loops2.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item={u'value': u'hello', u'key': u'one'}) => {
"msg": "name --> one value -->hello"
}
ok: [11.0.1.18] => (item={u'value': u'wyx', u'key': u'two'}) => {
"msg": "name --> two value -->wyx"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.嵌套Loops
嵌套Loops也是我们编写playbook中比较常见的一种循环,它主要实现一对多或者多对多的合并,如下:
[root@ansible01 ansible]# cat loops3.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
debug: msg="name --> {{ item[0] }} value --> {{ item[1] }}"
with_nested:
- ['A']
- ['a','b','c']
[root@ansible01 ansible]# ansible-playbook loops3.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=[u'A', u'a']) => {
"msg": "name --> A value --> a"
}
ok: [11.0.1.18] => (item=[u'A', u'b']) => {
"msg": "name --> A value --> b"
}
ok: [11.0.1.18] => (item=[u'A', u'c']) => {
"msg": "name --> A value --> c"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3. 散列loops
散列loops相比标准的loops就是变量支持更丰富的数据结构,比如标准loops的最外层数据必须是Python的list数据类型,而散列loops直接支持YAML格式的数据变量。如下:
[root@ansible01 ansible]# cat loops4.yaml
---
- hosts: 11.0.1.18
gather_facts: False
vars:
user:
shencan:
name: shencan
shell: bash
ruifengyun:
name: ruifengyun
shell: zsh
tasks:
- name: debug loops
debug: msg="name --> {{ item.key }} value --> {{ item.value.name }} shell --> {{ item.value.shell }}"
with_dict: "{{ user }}"
[root@ansible01 ansible]# ansible-playbook loops4.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item={u'key': u'ruifengyun', u'value': {u'shell': u'zsh', u'name': u'ruifengyun'}}) => {
"msg": "name --> ruifengyun value --> ruifengyun shell --> zsh"
}
ok: [11.0.1.18] => (item={u'key': u'shencan', u'value': {u'shell': u'bash', u'name': u'shencan'}}) => {
"msg": "name --> shencan value --> shencan shell --> bash"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4. 文件匹配loops
我们针对一个目录下指定格式的文件进行处理时,可以直接引用with_fileglob循环去匹配我们需要处理的文件即可,如下:
[root@ansible01 ansible]# cat /etc/ansible/loops5.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
debug: msg="files --> {{ item }}"
with_fileglob:
- /etc/ansible/*.yaml
[root@ansible01 ansible]# ansible-playbook loops5.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=/etc/ansible/loops2.yaml) => {
"msg": "files --> /etc/ansible/loops2.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops3.yaml) => {
"msg": "files --> /etc/ansible/loops3.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops5.yaml) => {
"msg": "files --> /etc/ansible/loops5.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops4.yaml) => {
"msg": "files --> /etc/ansible/loops4.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/variable.yaml) => {
"msg": "files --> /etc/ansible/variable.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/variable2.yaml) => {
"msg": "files --> /etc/ansible/variable2.yaml"
}
ok: [11.0.1.18] => (item=/etc/ansible/loops.yaml) => {
"msg": "files --> /etc/ansible/loops.yaml"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
with_fileglob 这个时候会匹配/etc/ansible下所有的yaml结尾的文件,当作{{ item }}变量来引用。
原理是使用了python glob模块去做的文件模糊匹配。
5. 随机选择loops
with_random_choice会从传入的list里面随机选择一个,作为item引用的参数
[root@ansible01 ansible]# cat loops6.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
debug: msg="names --> {{ item }}"
with_random_choice:
- "ansible1"
- "ansible2"
- "ansible3"
[root@ansible01 ansible]# ansible-playbook loops6.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=ansible3) => {
"msg": "names --> ansible3"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
6. 条件判断loops
有时候执行一个task后,我们需要检测这个task的结果是否达到了预想状态,如果没有达到我们预想的状态时,就需要退出整个playbook执行,这个时候我们需要对某个task结果一直进行循环检测,如下:
[root@ansible01 ansible]# cat loops7.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
shell: cat /etc/ansible/hosts
register: host
until: host.stdout.startswith("Master")
retries: 5
delay: 5
[root@ansible01 ansible]# ansible-playbook loops7.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
FAILED - RETRYING: debug loops (5 retries left).
FAILED - RETRYING: debug loops (4 retries left).
FAILED - RETRYING: debug loops (3 retries left).
FAILED - RETRYING: debug loops (2 retries left).
FAILED - RETRYING: debug loops (1 retries left).
fatal: [11.0.1.18]: FAILED! => {"attempts": 5, "changed": true, "cmd": "cat /etc/ansible/hosts", "delta": "0:00:00.005700", "end": "2024-04-30 09:49:27.614588", "rc": 0, "start": "2024-04-30 09:49:27.608888", "stderr": "", "stderr_lines": [], "stdout": "# This is the default ansible 'hosts' file.\n#\n# It should live in /etc/ansible/hosts\n#\n# - Comments begin with the '#' character\n# - Blank lines are ignored\n# - Groups of hosts are delimited by [header] elements\n# - You can enter hostnames or ip addresses\n# - A hostname/ip can be a member of multiple groups\n\n# Ex 1: Ungrouped hosts, specify before any group headers.\n\n## green.example.com\n## blue.example.com\n## 192.168.100.1\n## 192.168.100.10\n\n# Ex 2: A collection of hosts belonging to the 'webservers' group\n\n## [webservers]\n## alpha.example.org\n## beta.example.org\n## 192.168.1.100\n## 192.168.1.110\n\n# If you have multiple hosts following a pattern you can specify\n# them like this:\n\n## www[001:006].example.com\n\n# Ex 3: A collection of database servers in the 'dbservers' group\n\n## [dbservers]\n## \n## db01.intranet.mydomain.net\n## db02.intranet.mydomain.net\n## 10.25.1.56\n## 10.25.1.57\n\n# Here's another example of host ranges, this time there are no\n# leading 0s:\n#11.0.1.18\tkey=118\n#11.0.1.19\tkey=119\n[nginx]\n11.0.1.1[8:9]\n[nginx:vars]\nansible_python_interpreter=/usr/bin/python2.7", "stdout_lines": ["# This is the default ansible 'hosts' file.", "#", "# It should live in /etc/ansible/hosts", "#", "# - Comments begin with the '#' character", "# - Blank lines are ignored", "# - Groups of hosts are delimited by [header] elements", "# - You can enter hostnames or ip addresses", "# - A hostname/ip can be a member of multiple groups", "", "# Ex 1: Ungrouped hosts, specify before any group headers.", "", "## green.example.com", "## blue.example.com", "## 192.168.100.1", "## 192.168.100.10", "", "# Ex 2: A collection of hosts belonging to the 'webservers' group", "", "## [webservers]", "## alpha.example.org", "## beta.example.org", "## 192.168.1.100", "## 192.168.1.110", "", "# If you have multiple hosts following a pattern you can specify", "# them like this:", "", "## www[001:006].example.com", "", "# Ex 3: A collection of database servers in the 'dbservers' group", "", "## [dbservers]", "## ", "## db01.intranet.mydomain.net", "## db02.intranet.mydomain.net", "## 10.25.1.56", "## 10.25.1.57", "", "# Here's another example of host ranges, this time there are no", "# leading 0s:", "#11.0.1.18\tkey=118", "#11.0.1.19\tkey=119", "[nginx]", "11.0.1.1[8:9]", "[nginx:vars]", "ansible_python_interpreter=/usr/bin/python2.7"]}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
5s执行一次cat /etc/ansible/hosts,将结果register给host然后判断host.stdout.startswith的内容是否Master字符串开头,如果条件成立,此task运行完成,如果条件不成立5s后再重试,5次后还不成立,此task运行失败。
7. 文件优先匹配loops
这个与第4个文件匹配类似,就新增了一个优选项,如下:
[root@ansible01 ansible]# cat loops8.yaml
---
- hosts: 11.0.1.18
gather_facts: False
tasks:
- name: debug loops
debug: msg="files --> {{ item }}"
with_first_found:
- "wyx.yaml"
[root@ansible01 ansible]# ansible-playbook loops8.yaml
PLAY [11.0.1.18] **************************************************************************************************************************************************************************
TASK [debug loops] ************************************************************************************************************************************************************************
ok: [11.0.1.18] => (item=/etc/ansible/wyx.yaml) => {
"msg": "files --> /etc/ansible/wyx.yaml"
}
PLAY RECAP ********************************************************************************************************************************************************************************
11.0.1.18 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0