可以重复引用某个模块,不用再使用多个tasks。
如下:
with_item的值是Python list数据结构,可以理解为每个tasks会循环读取list里面的值,
然后key的值的名称是item,list里面也支持python字典,如下:
1:如下:
---
- hosts: all
gather_facts: False
tasks:
- name: debug loops
debug: msg="name ------> {{ item }}"
with_items:
- one
- two
[root@ansible-1 ansible]# ansible-playbook -i hosts loops.yaml
PLAY [all] ***********************************************
TASK [debug loops] *****************************************
ok: [192.168.124.129] => (item=one) => {
"changed": false,
"item": "one",
"msg": "name ------> one"
}
ok: [192.168.124.129] => (item=two) => {
"changed": false,
"item": "two",
"msg": "name ------> two"
}
PLAY RECAP ***************************************
192.168.124.129 : ok=1 changed=0 unreachable=0 failed=0
2:如下:
---
- hosts: all
gather_facts: False
tasks:
- name: config the loop
debug: msg="name ----->{{ item.key }} vlaue ----->{{ item.value }}"
with_items:
- { key: "one", value: "VALUE1" }
- { key: "two", value: "VALUE2" }
[root@ansible-1 ansible]# ansible-playbook -i hosts loops-1.yaml
PLAY [all] ***********************************************************
TASK [config the loop] *************************************************
ok: [192.168.124.129] => (item={u'key': u'one', u'value': u'VALUE1'}) => {
"changed": false,
"item": {
"key": "one",
"value": "VALUE1"
},
"msg": "name -----> one vlaue -----> VALUE1"
}
ok: [192.168.124.129] => (item={u'key': u'two', u'value': u'VALUE2'}) => {
"changed": false,
"item": {
"key": "two",
"value": "VALUE2"
},
"msg": "name -----> two vlaue -----> VALUE2"
}
PLAY RECAP **********************************************
192.168.124.129 : ok=1 changed=0 unreachable=0 failed=0
3:使用loops创建目录,如下:
---
- hosts: all
gather_facts: False
tasks:
- name: Ensuring config directories exist
file:
path: "{{ item }}"
state: "directory"
recurse: true
with_items:
- "/etc/os-net-config"
- "/var/lib/os-net-config"
- "/etc/wei/zhibiao/123/"
check_mode: no
#####################################################
with_items:的特殊用法如下:
- name: Copying files for keystone-ssh
vars:
keystone_ssh: "{{ keystone_services['keystone-ssh'] }}"
template:
src: "{{ item.src }}"
dest: "{{ node_config_directory }}/keystone-ssh/{{ item.dest }}"
mode: "0660"
become: true
with_items:
- { src: "sshd_config.j2", dest: "sshd_config" }
- { src: "id_rsa.pub", dest: "id_rsa.pub" }
when:
- inventory_hostname in groups[keystone_ssh.group]
- keystone_ssh.enabled | bool
notify:
- Restart keystone-ssh container
同一个item定义 两个key,前后对应,src------> dest
4:使用loops进行文件匹配,如下:不加班
---
- hosts: all
gather_facts: False
tasks:
- name: debug loops
debug: msg="files -----> {{ item }}"
with_fileglob:
- /etc/ansible/site-1.yml
5:随机选择loops使用,如下:
---
- hosts: all
gather_facts: False
tasks:
- name: debug loops
debug: msg="files -----> {{ item }}"
with_random_choice:
- "ansibel-1"
- "ansible-2"
- "ansible-3"
6:条件判断loops,如下:
---
- hosts: all
gather_facts: False
tasks:
- name: if else
shell: cat /etc/ansible/hosts
register: host ##将shel输出定义为变量
until: host.stdout.startswith("Master") ##判断变量是否是Master开头
retries: 5 ###重试次数
deply: 5 ###重试时间间隔
ignore_errors: True ###如果有错误可以强制成功,继续执行下面的task。
输出结果如下:
TASK [if else] *****************************
FAILED - RETRYING: if else (5 retries left).
FAILED - RETRYING: if else (4 retries left).
FAILED - RETRYING: if else (3 retries left).
FAILED - RETRYING: if else (2 retries left).
FAILED - RETRYING: if else (1 retries left).
fatal: [192.168.124.129]: FAILED! => {"attempts": 5, "changed": true,
"cmd": "cat /etc/ansible/hosts", "delta": "0:00:00.003797", "end":
"2020-03-13 15:22:45.048290", "rc": 0, "start": "2020-03-13 15:22:45.044493",
"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\n## db-[99:101]-node.example.com\n[test]\n192.168.124.129
key=www ", "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, 9 key=www "]}
to retry, use: --limit @/etc/ansible/loops-1.retry
PLAY RECAP ******************************************
192.168.124.129 : ok=4 changed=0 unreachable=0 failed=1
7:register loops,定义一个registry,多个tasks使用jinja2的for循环显示结果,如下:
---
- hosts: all
gather_facts: False
tasks:
- name: debug lopps-1
shell: "{{ item }}"
with_items:
- hostname
- uname -a
register: ret
- name: dispaly loops
debug: msg="{% for i in ret.results %} {{ i.stdout }} {% endfor %}"
;输出结果如下:
TASK [debug lopps-1] **********
changed: [192.168.124.129] => (item=hostname)
changed: [192.168.124.129] => (item=uname -a)
TASK [dispaly loops] ***********************************************
ok: [192.168.124.129] => {
"msg": " ansible-1 Linux ansible-1 3.10.0-1062.el7.x86_64 #1 SMP Wed Aug 7 18:08:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux "
}
PLAY RECAP ************************************************************
192.168.124.129 : ok=6 changed=1 unreachable=0 failed=0
8:with_dict:
举例如下:
---
- hosts: testB
remote_user: root
gather_facts: no
vars:
users:
alice: female
bob: male
tasks:
- debug:
msg: "{{item}}"
with_dict: "{{users}}"
从上述可以看出,变量users中的key为alice/bob,value为female/male
输出结果如下:
TASK [debug] ***********************************************
Tuesday 14 April 2020 11:11:44 +0800 (0:00:00.286) 0:00:00.286 *********
ok: [192.168.124.129] => (item={'value': {u'gender': u'male', u'name': u'Bob Jack', u'telephone': u'987-654-321'}, 'key': u'bob'}) => {
"msg": {
"key": "bob",
"value": {
"gender": "male",
"name": "Bob Jack",
"telephone": "987-654-321"
}
}
}
ok: [192.168.124.129] => (item={'value': {u'gender': u'female', u'name': u'Alice Natasha', u'telephone': u'123-456-789'}, 'key': u'alice'}) => {
"msg": {
"key": "alice",
"value": {
"gender": "female",
"name": "Alice Natasha",
"telephone": "123-456-789"
}
}
}
PLAY RECAP **********************************************
192.168.124.129 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
从输出信息可以看出,字典格式的users变量经过"with_dict"处理后,
字典中的每个键值对被放到了item变量中,而且,键值对中的"键"被放入了"key"关键字中,
键值对中的"值"被放入了"value"关键字中,所以,我们可以通过key关键字和value关键字
分别获取到字典中键值对的"键"和"值",示例playbook如下
扩展:
---
- hosts: testB
remote_user: root
gather_facts: no
vars:
users:
alice:
name: Alice Natasha
gender: female
telephone: 123-456-789
bob:
name: Bob Jack
gender: male
telephone: 987-654-321
tasks:
- debug:
msg: "User {{item.key}} is {{ item.value.name }}, Gender: {{ item.value.gender }}, Tel: {{ item.value.telephone }}"
with_dict: "{{users}}"
以上可以看出,value定义了name,gender,telephone,获取value的值。
每一个key需要有相同的value。
输出结果如下:
[root@ansible129 ansible]# ansible-playbook -i hosts debug-1.yml
PLAY [control] *************************************************************************************
TASK [debug] ***************************************************************************************
Tuesday 14 April 2020 11:17:24 +0800 (0:00:00.102) 0:00:00.102 *********
ok: [192.168.124.129] => (item={'value': {u'gender': u'male', u'name': u'Bob Jack', u'telephone': u'987-654-321'}, 'key': u'bob'}) => {
"msg": "User bob is Bob Jack, Gender: male, Tel: 987-654-321"
}
ok: [192.168.124.129] => (item={'value': {u'gender': u'female', u'name': u'Alice Natasha', u'telephone': u'123-456-789'}, 'key': u'alice'}) => {
"msg": "User alice is Alice Natasha, Gender: female, Tel: 123-456-789"
}
PLAY RECAP ********************************************************************************************
192.168.124.129 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Tuesday 14 April 2020 11:17:24 +0800 (0:00:00.358) 0:00:00.461 *********
===============================================================================
9:with_subelements复合变量
---
- hosts: testB
remote_user: root
gather_facts: no
vars:
users:
- name: alice
gender: female
hobby:
- Music
- name: bob
gender: male
hobby:
- Skateboard
- VideoGame
tasks:
- debug:
msg: "{{item}}“
msg: "{{item.0.name}}'s hobby is {{item.1}}"
with_subelements:
- "{{users}}"
- hobby
由于item由两个整体组成,所以,我们通过item.0获取到第一个小整体,
即gender和name属性,然后通过item.1获取到第二个小整体,即hobby列表中的每一项,
输出结果如下:
TASK [debug] ***************************************************************
Tuesday 14 April 2020 15:31:53 +0800 (0:00:00.306) 0:00:32.743 *********
ok: [192.168.124.129] => (item=[{u'gender': u'female', u'name': u'alice'}, u'Music']) => {
"msg": "alice's hobby is Music"
}
ok: [192.168.124.129] => (item=[{u'gender': u'male', u'name': u'bob'}, u'Skateboard']) => {
"msg": "bob's hobby is Skateboard"
}
ok: [192.168.124.129] => (item=[{u'gender': u'male', u'name': u'bob'}, u'VideoGame']) => {
"msg": "bob's hobby is VideoGame"
}
10:with_first_found遍历文件
- name: Copying over definitions.json
become: true
vars:
service: "{{ rabbitmq_services['rabbitmq'] }}"
template:
src: "{{ item }}"
dest: "{{ node_config_directory }}/{{ project_name }}/definitions.json"
mode: "0660"
with_first_found: ###匹配存在的文件,不存在则不匹配
- "{{ node_custom_config }}/rabbitmq/{{ inventory_hostname }}/definitions.json"
- "{{ node_custom_config }}/rabbitmq/definitions.json"
- "definitions.json.j2"
when:
- inventory_hostname in groups[service.group]
- service.enabled | bool
notify:
- Restart rabbitmq container (first node)
- Restart rabbitmq container (rest of nodes)
注释:当使用notify时,如需要立刻执行时,则添加如下:
- name: Flush handlers
meta: flush_handlers