Ansible Playbook 循环
Standard Loops
为了节省一些打字,重复的任务可以写成如下:
- name: add several users
user:
name: "{{ item }}"
state: present
groups: "wheel"
with_items:
- testuser1
- testuser2 如果您在变量文件或“vars”部分中定义了YAML列表,则还可以执行以下操作:
with_items: "{{ somelist }}" 相当于
- name: add user testuser1
user:
name: "testuser1"
state: present
groups: "wheel"
- name: add user testuser2
user:
name: "testuser2"
state: present
groups: "wheel" yum和apt模块使用with_item来执行较少的包管理器事务。
请注意,使用“with_items”迭代的项目类型不必是简单的字符串列表。 如果你有一个哈希列表,你可以使用以下的东西来引用子项:
- name: add several users
user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups }}"
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' } 还要注意,当与with_items (或任何其他循环语句)组合时 ,对每个项目单独处理when语句。 请参阅When语句为例。
循环实际上是with_ + lookup()的组合,所以任何查找插件都可以用作循环的源,'items'是查找。
Nested Loops(嵌套循环)
- name: give users access to multiple databases
mysql_user:
name: "{{ item[0] }}"
priv: "{{ item[1] }}.*:ALL"
append_privs: yes
password: "foo"
with_nested:
- [ 'alice', 'bob' ]
- [ 'clientdb', 'employeedb', 'providerdb' ] 与上述'with_items'一样,您可以使用以前定义的变量:
- name: here, 'users' contains the above list of employees
mysql_user:
name: "{{ item[0] }}"
priv: "{{ item[1] }}.*:ALL"
append_privs: yes
password: "foo"
with_nested:
- "{{ users }}"
- [ 'clientdb', 'employeedb', 'providerdb' ]
Looping over Hashes
1.5版新功能
假设你有以下变量:
---
users:
alice:
name: Alice Appleworth
telephone: 123-456-7890
bob:
name: Bob Bananarama
telephone: 987-654-3210
并且您想打印每个用户的名字和电话号码。 您可以使用with_dict
循环遍历哈希的元素,如下所示:
tasks:
- name: Print phone records
debug:
msg: "User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
with_dict: "{{ users }}"
Looping over Files
with_file
遍历文件列表的内容, 项目将按顺序设置为每个文件的内容。 它可以像这样使用:
---
- hosts: all tasks: # emit a debug message containing the content of each file.
- debug:
msg: "{{ item }}"
with_file:
- first_example_file
- second_example_file 假设first_example_file
包含文本“hello”,而second_example_file
包含文本“world”,这将导致:
TASK [debug msg={{ item }}] ******************************************************
ok: [localhost] => (item=hello) => {
"item": "hello",
"msg": "hello"
}
ok: [localhost] => (item=world) => {
"item": "world",
"msg": "world"
}
Looping over Fileglobs
with_fileglob
匹配单个目录中的所有文件,非递归地匹配模式。 它调用Python的glob库 ,可以这样使用:
---
- hosts: all tasks: # first ensure our target directory exists
- name: Ensure target directory exists
file:
dest: "/etc/fooapp"
state: directory # copy each file over that matches the given pattern
- name: Copy each file over that matches the given pattern
copy:
src: "{{ item }}"
dest: "/etc/fooapp/"
owner: "root"
mode: 0600
with_fileglob:
- "/playbooks/files/fooapp/*"
Looping over Parallel Sets of Data
假设你有以下变量数据被加载到某处:
---
alpha: [ 'a', 'b', 'c', 'd' ]
numbers: [ 1, 2, 3, 4 ] 你想要一套“(a,1)”和“(b,2)”等等。 使用'with_together'得到这个:
tasks:
- debug:
msg: "{{ item.0 }} and {{ item.1 }}"
with_together:
- "{{ alpha }}"
- "{{ numbers }}"
Looping over Subelements
假设你想做一些像循环遍历用户列表,创建它们,并允许他们通过一组SSH密钥登录。
怎么可能实现? 假设你有以下定义并通过“vars_files”或“group_vars / all”文件加载:
---
users:
- name: alice
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
mysql:
password: mysql-password
hosts:
- "%"
- "127.0.0.1"
- "::1"
- "localhost"
privs:
- "*.*:SELECT"
- "DB1.*:ALL"
- name: bob
authorized:
- /tmp/bob/id_rsa.pub
mysql:
password: other-mysql-password
hosts:
- "db1"
privs:
- "*.*:SELECT"
- "DB2.*:ALL" 可能会发生如此:
- name: Create User
user:
name: "{{ item.name }}"
state: present
generate_ssh_key: yes
with_items:
- "{{ users }}" - name: Set authorized ssh key
authorized_key:
user: "{{ item.0.name }}"
key: "{{ lookup('file', item.1) }}"
with_subelements:
- "{{ users }}"
- authorized 给出mysql主机和privs子项列表,还可以遍历一个嵌套子项中的列表:
- name: Setup MySQL users
mysql_user:
name: "{{ item.0.name }}"
password: "{{ item.0.mysql.password }}"
host: "{{ item.1 }}"
priv: "{{ item.0.mysql.privs | join('/') }}"
with_subelements:
- "{{ users }}"
- "{{ mysql.hosts }}" 或者,您可以将第三个元素添加到子元素列表,该列表包含标志的字典。 目前您可以添加'skip_missing'标志。 如果设置为True,查找插件将跳过不包含给定子项的列表项。 没有这个标志,或者如果该标志设置为False,插件将产生一个错误,并抱怨丢失的子项。
authorized_key模式正是它最多出现的地方。
Looping over Integer Sequences
with_sequence
生成一个项目序列。 您可以指定起始值,结束值,可选的“stride”值,该值指定增加序列的步数,以及可选的printf样式格式字符串。
参数应指定为key = value对字符串。
参数string的简单快捷方式也被接受: [start-]end[/stride][:format]
。
数值可以十进制,十六进制(0x3f8)或八进制(0600)指定。 不支持负数。 这样做的工作如下:
---
- hosts: all tasks: # create groups
- group:
name: "evens"
state: present
- group:
name: "odds"
state: present # create some test users
- user:
name: "{{ item }}"
state: present
groups: "evens"
with_sequence: start=0 end=32 format=testuser%02x # create a series of directories with even numbers for some reason
- file:
dest: "/var/stuff/{{ item }}"
state: directory
with_sequence: start=4 end=16 stride=2 # a simpler way to use the sequence plugin
# create 4 groups
- group:
name: "group{{ item }}"
state: present
with_sequence: count=4
Random Choices
'random_choice'功能可以随机选择一些东西。 虽然它不是一个负载平衡器(有模块的那些),它可以有点被用作一个穷人的负载平衡器在MacGyver像情况:
- debug:
msg: "{{ item }}"
with_random_choice:
- "go through the door"
- "drink from the goblet"
- "press the red button"
- "do nothing"
所提供的字符串之一将随机选择。
在更基础的层面上,它们可以用来增加混乱和兴奋,以达到另外可预测的自动化环境。
Do-Until Loops
版本1.4中的新功能。
有时你想重试一个任务,直到满足一定的条件。 这里有一个例子:
- shell: /usr/bin/foo
register: result
until: result.stdout.find("all systems go") != -1
retries: 5
delay: 10 上述示例递归运行shell模块,直到模块的结果在其stdout中具有“所有系统”,或者任务已经重试了5次,延迟了10秒。 “重试”的默认值为3,“延迟”为5。
任务返回最后一个任务运行返回的结果。 单独重试的结果可以通过-vv选项查看。 注册的变量还将有一个新的密钥“attempts”,它将具有任务的重试次数。
Finding First Matched Files
这不是一个循环,但是很接近。 如果要根据与给定条件匹配的第一个文件使用对文件的引用,并且某些文件名由变量名称决定? 是的,你可以这样做:
- name: INTERFACES | Create Ansible header for /etc/network/interfaces
template:
src: "{{ item }}"
dest: "/etc/foo.conf"
with_first_found:
- "{{ ansible_virtualization_type }}_foo.conf"
- "default_foo.conf" 此工具还具有允许可配置搜索路径的长格式版本。 这里有一个例子:
- name: some configuration template
template:
src: "{{ item }}"
dest: "/etc/file.cfg"
mode: 0444
owner: "root"
group: "root"
with_first_found:
- files:
- "{{ inventory_hostname }}/etc/file.cfg"
paths:
- ../../../templates.overwrites
- ../../../templates
- files:
- etc/file.cfg
paths:
- templates
Iterating Over The Results of a Program Execution
有时你可能想执行一个程序,并根据该程序的输出,逐行循环结果。 尽管应该记住,这可以提供一个整洁的方式来实现,但这总是在控制机器上执行,而不是远程机器:
- name: Example of looping over a command result
shell: "/usr/bin/frobnicate {{ item }}"
with_lines:
- "/usr/bin/frobnications_per_host --param {{ inventory_hostname }}" 好的,那有点随意 实际上,如果您正在做一些与库存相关的内容,您可能只想编写一个动态库存源代码(请参阅动态库存 ),但这对于快速和脏的实现可能会偶尔有用。
如果您需要远程执行命令,则不能使用上述方法。 这样做:
- name: Example of looping over a REMOTE command result
shell: "/usr/bin/something"
register: command_result - name: Do something with each result
shell: "/usr/bin/something_else --param {{ item }}"
with_items:
- "{{ command_result.stdout_lines }}"
Looping Over A List With An Index
1.3版新功能
如果你想循环一个数组,并且还可以在数组中获得数组的数字索引,你也可以这样做。 这是不常用的:
- name: indexed loop demo
debug:
msg: "at array position {{ item.0 }} there is a value {{ item.1 }}"
with_indexed_items:
- "{{ some_list }}"
Using ini file with a loop
2.0版新功能
ini插件可以使用regexp来检索一组键。 因此,我们可以循环这个集合。 这是我们将使用的ini文件:
[section1]
value1=section1/value1
value2=section1/value2 [section2]
value1=section2/value1
value2=section2/value2 以下是使用with_ini
的示例:
- debug:
msg: "{{ item }}"
with_ini:
- value[1-2]
- section: section1
- file: "lookup.ini"
- re: true 这里是返回的值:
{
"changed": false,
"msg": "All items completed",
"results": [
{
"invocation": {
"module_args": "msg=\"section1/value1\"",
"module_name": "debug"
},
"item": "section1/value1",
"msg": "section1/value1",
"verbose_always": true
},
{
"invocation": {
"module_args": "msg=\"section1/value2\"",
"module_name": "debug"
},
"item": "section1/value2",
"msg": "section1/value2",
"verbose_always": true
}
]
}
Flattening A List(展开列表)
在极少数情况下,您可能有几个列表列表,您只需要迭代所有列表中的每个项目。 假设一个真正疯狂的假设数据结构:
----
# file: roles/foo/vars/main.yml
packages_base:
- [ 'foo-package', 'bar-package' ]
packages_apps:
- [ ['one-package', 'two-package' ]]
- [ ['red-package'], ['blue-package']] 您可以看到这些列表中的软件包的格式是完整的。 我们如何在两个列表中安装所有的包:
- name: flattened loop demo
yum:
name: "{{ item }}"
state: present
with_flattened:
- "{{ packages_base }}"
- "{{ packages_apps }}"
Using register with a loop
在使用register
循环后,放置在变量中的数据结构将包含一个results
属性,该属性是模块中所有响应的列表。
以下是使用with_items
register
的with_items
:
- shell: "echo {{ item }}"
with_items:
- "one"
- "two"
register: echo 这与使用没有循环的register
时返回的数据结构不同:
{
"changed": true,
"msg": "All items completed",
"results": [
{
"changed": true,
"cmd": "echo \"one\" ",
"delta": "0:00:00.003110",
"end": "2013-12-19 12:00:05.187153",
"invocation": {
"module_args": "echo \"one\"",
"module_name": "shell"
},
"item": "one",
"rc": 0,
"start": "2013-12-19 12:00:05.184043",
"stderr": "",
"stdout": "one"
},
{
"changed": true,
"cmd": "echo \"two\" ",
"delta": "0:00:00.002920",
"end": "2013-12-19 12:00:05.245502",
"invocation": {
"module_args": "echo \"two\"",
"module_name": "shell"
},
"item": "two",
"rc": 0,
"start": "2013-12-19 12:00:05.242582",
"stderr": "",
"stdout": "two"
}
]
} 对注册变量进行后续循环以检查结果可能如下所示:
- name: Fail if return code is not 0
fail:
msg: "The command ({{ item.cmd }}) did not have a 0 return code"
when: item.rc != 0
with_items: "{{ echo.results }}" 在迭代过程中,当前项目的结果将被放在变量中:
- shell: echo "{{ item }}"
with_items:
- one
- two
register: echo
changed_when: echo.stdout != "one"
Looping over the inventory
如果您希望循环查看广告资源,或只是其中的一部分,则有多种方法。 可以使用常规的with_items
与play_hosts
或groups
变量,如下所示:
# show all the hosts in the inventory
- debug:
msg: "{{ item }}"
with_items:
- "{{ groups['all'] }}" # show all the hosts in the current play
- debug:
msg: "{{ item }}"
with_items:
- "{{ play_hosts }}" 还有一个特定的查找插件inventory_hostnames
可以这样使用:
# show all the hosts in the inventory
- debug:
msg: "{{ item }}"
with_inventory_hostnames:
- all # show all the hosts matching the pattern, ie all but the group www
- debug:
msg: "{{ item }}"
with_inventory_hostnames:
- all:!www
Loop Control
2.1版新功能
在2.0中,您再次可以使用with_循环和任务包括(但不包括playbook)。 这增加了在一次镜像中循环该任务集的能力。 默认情况下可以设置每个循环的循环变量项 ,这会导致这些嵌套循环从“外部”循环覆盖项的值。 从Ansible 2.1开始, loop_control选项可用于指定要用于循环的变量的名称:
# main.yml
- include: inner.yml
with_items:
- 1
- 2
- 3
loop_control:
loop_var: outer_item # inner.yml
- debug:
msg: "outer item={{ outer_item }} inner item={{ item }}"
with_items:
- a
- b
- c 新版本2.2。
当使用复杂的数据结构来循环显示可能会有点太忙,这就是C(label)指令来帮助的:
- name: create servers
digital_ocean:
name: "{{ item.name }}"
state: present
with_items:
- name: server1
disks: 3gb
ram: 15Gb
network:
nic01: 100Gb
nic02: 10Gb
...
loop_control:
label: "{{item.name}}" 现在,它将只显示“label”字段而不是每个“item”的整个结构,它默认为“{{item}}”'以照常显示。
新版本2.2。
循环控制的另一个选项是C(暂停),它允许您控制任务循环中项目执行之间的时间(以秒为单位):
# main.yml
- name: create servers, pause 3s before creating next
digital_ocean:
name: "{{ item }}"
state: present
with_items:
- server1
- server2
loop_control:
pause: 3
Loops and Includes in 2.0
因为loop_control在Ansible 2.0中不可用,当使用带循环的include时,应该使用set_fact来保存项的“outer”循环值:
# main.yml
- include: inner.yml
with_items:
- 1
- 2
- 3 # inner.yml
- set_fact:
outer_item: "{{ item }}" - debug:
msg: "outer item={{ outer_item }} inner item={{ item }}"
with_items:
- a
- b
- c
Writing Your Own Iterators
虽然通常不需要,如果您希望编写自己的方法来循环任意数据结构,则可以阅读开发插件以获取一些启动器信息。 以上每个功能都实现为可插入的插件,因此有很多实现可供参考。
Ansible Playbook 循环的更多相关文章
- Ansible playbook循环实践总结<一>
1.标准Loops 标准loops可以直接减少task的次数,如下: [root@zero01 playbook]# vi loops.yaml --- - hosts: all gather_fac ...
- ansible playbook详解
ansible playbook是由yml语法书写,结构清晰,可读性强,所以必须掌握yml基础语法 语法 描述 缩进 YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成,不能使用tabs键 ...
- Ansible Playbook 详解
一.playbook 的简单使用 1.创建文件实例 (1)编辑配置文件 [root@tiejiangSRC1 ~]# cd /etc/ansible/ [root@tiejiangSRC1 ansib ...
- ansible playbook基本操作
一.ansible playbook简单使用 相当于是把模块写入到配置文件里面 vim /etc/ansible/test.yml //写入如下内容: --- - hosts: 127.0.0.1 r ...
- ansible playbook模式及语法
一.什么是playbook及其组成 什么是playbook playbook 翻译过来就是"剧本" playbook的组成 play:定义的是主机的角色 task:定义的是具体执行 ...
- ansible - playbook(剧组)
目录 ansible - playbook(剧组) 常用命令 五种传参方式 常用元素详解 tags handlers template when 循环 嵌套循环 ansible - playbook( ...
- Ansible PlayBook语法
PlayBook语法实例 playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过Ansible中的tasks定义好的角色(play的内容被称为ta ...
- Ansible playbook 编程
Ansible playbook 编程详解与各种小案例 主机规划 添加用户账号 说明: 1. 运维人员使用的登录账号: 2. 所有的业务都放在 /app/ 下「yun用户的家目录」,避免业务数据乱放: ...
- Ansible playbook API 开发 调用测试
Ansible是Agentless的轻量级批量配置管理工具,由于出现的比较晚(13年)基于Ansible进行开发的相关文档较少,因此,这里通过一些小的实验,结合现有资料以及源码,探索一下Ansible ...
随机推荐
- sysbench 0.5 基准测试
sysbench 介绍 SysBench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.它主要包括以下几种方式的测试: cpu性能 磁盘io性能 调度程 ...
- jeecg中的原生态组件
<!-- ztree --><link rel="stylesheet" type="text/css" href="plug-in ...
- netty初步
netty是java的高性能socket框架,linux下基epoll,这里不对他多牛逼作分析,网上资料很多,这里针对一般socket的业务作个例子 几个基本概念: channel类似于socket句 ...
- 【Spring学习笔记-MVC-6】SpringMVC 之@RequestBody 接收Json数组对象
作者:ssslinppp 1. 摘要 程序流程: 前台使用ajax技术,传递json字符串到后台: 后台使用Spring MVC注解@RequestBody 接受前台传递的json字符串, ...
- 通过 CeSi + Supervisor 可视化集中管理服务器节点进程
通过 CeSi + Supervisor 可视化集中管理服务器节点进程 简介 Supervisor 的安装及基本使用 1. 安装 2. 基本使用 2.1 启动 supervisor 2.2 Supe ...
- JQUERY dialog的用法详细解析
本篇文章主要是对JQUERY中dialog的用法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助 今天用到了客户端的对话框,把 jQuery UI 中的对话框学习了一下. 准备 jQ ...
- python中for...if...构建List
1.简单的for...[if]...语句 >>> a=[12, 3, 4, 6, 7, 13, 21] >>> newList = [x for x in a] & ...
- php 数组随机取值
array_rand()在你想从数组中取出一个或多个随机的单元时相当有用.它接受 input 作为输入数组和一个可选的参数 num_req,指明了你想取出多少个单元 - 如果没有指定,默认为 1. a ...
- 在 Linux 下使用mdadm创建 RAID 5
在 RAID 5 中,数据条带化后存储在分布式奇偶校验的多个磁盘上.分布式奇偶校验的条带化意味着它将奇偶校验信息和条带化数据分布在多个磁盘上,这样会有很好的数据冗余. 在 Linux 中配置 RAID ...
- 学习MongoDB 七: MongoDB索引(索引基本操作)(一)
一.简介 在MongoDB建立索引能提高查询效率,只需要扫描索引只存储的这个集合的一小部分,并只把这小部分加载到内存中,效率大大的提高,如果没有建立索引,在查询时,MongoDB必须执行全表扫描,在数 ...