设为首页 收藏本站
查看: 943|回复: 0

[经验分享] Ansible的循环

[复制链接]

尚未签到

发表于 2018-1-2 15:22:34 | 显示全部楼层 |阅读模式
1、       前言
  有可能在一个任务中,可能要做很多事情,例如创建多个用户,安装很多个包等,那么就有可能用到循环。

2、       标准循环
  重复的任务可以用下面的方式:

- name: add several users

  user: name={{ item }} state=present groups=wheel

with_items:

     - testuser1

     - testuser2

  如果你定义了一个变量文件创建了一个YAML的列表,或者是在var节中,那么可以使用以下的方式:
  

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_items的时候,可以减少包管理事务。
  在遍历的各项中,可以不是简单的列表,如果是hash列表的时候,你可以使用子健,如下:
  

-name:add several users  

user:name={{ item.name }} state=present groups={{ item.groups }}  

with_items:  

-{name:'testuser1',groups:'wheel'}  

-{name:'testuser2',groups:'root'}  


3、       嵌套循环
  嵌套循环如下所示:
  

-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']  


4、       遍历hash
  假设存在以下变量:
  

---  

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}}"  


5、       遍历文件
  “with_file”迭代建立在一系列文件的内容之上,item将被设置为序列中每个文件的内容,如下所示:
  

---  

-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"  

}  


6、       遍历文件夹(fileglobs)
  with_fileglob对应于单一目录下的所有文件,不递归的匹配模式,如下:
  

---  

-hosts:all  

  

tasks:  

  

# first ensure our target directory exists  

-file:dest=/etc/fooapp state=directory  

  

# copy each file over that matches the given pattern  

-copy:src={{ item }} dest=/etc/fooapp/ owner=root mode=600  

with_fileglob:  

-/playbooks/files/fooapp/*  

  注意:当在role里使用with_fileglob的时候,ansible会将路径解析为
  roles/<rolename>/files 路径

7、       遍历数据的并行集
  假设存在以下的变量:
  

---  

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}}"  


8、       遍历子元素
  假设你想遍历一个用户列表,创建他们,并且用特定的ssh key来进行登录,假设存在以下的变量内容:
  

---  

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"  

  那么将会像如下所示:
  

-user:name={{ item.name }} state=present generate_ssh_key=yes  

with_items:"{{users}}"  

  

-authorized_key:"user={{item.0.name}}key='{{lookup('file',item.1)}}'"  

with_subelements:  

-users  

-authorized  

  给出MySQL的主机并且提供ssh密钥的列表,那么将可以遍历一个嵌套的子健:
  

-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  

  子元素会沿着哈希表遍历并且给出ssh密钥在记录之内

9、       遍历整数系列
  with_sequence生成项目数字的序列,也可以指定开始,结束,或者一个步长值。
  参数也可以指定为key=value的格式,如果提供了,那么会格式化为printf的类型字符串。
  数字值可以指定为2进制,10进制,16进制,负数不支持,如下:
  

---  

-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  


10、  随机选择
  random_choice表示为随机的选择,但是不是一个负载均衡,在有的程度上相当于负载均衡,如下:
  

-debug:msg={{ item }}  

with_random_choice:  

-"gothroughthedoor"  

-"drinkfromthegoblet"  

-"presstheredbutton"  

-"donothing"  

  提供的字符串将会有一个被随机选中。

11、  Do-until循环
  有的时候会去尝试一个任务在特定的条件下,如下:
  

-action:shell /usr/bin/foo  

register:result  

until:result.stdout.find("all systems go") != -1  

retries:5  

delay:10  

  在默认情况下,retries值为3,delay为5秒,在查看的时候,可以使用-vv的选项来查看变量的值

12、  找到第一个匹配的文件
  这不是一个循环,但是很接近。当你在引用一个文件的时候,取决于上一个文件的内容或者是名称,那么可以如下:
  

-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  


13、  迭代程序执行的结果
  在有的时候,需要遍历执行的结果,需要注意的是,这是在远程机器上执行的,而不是在本机器上执行的,如下:
  

-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}}"  


14、  在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":"Allitemscompleted",  

"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  

}  

]  

}  


15、  在循环中使用register
  当使用register来存储变量的时候,那么保存的是一个列表,整个属性为results
  如下:
  

-shell:echo "{{ item }}"  

with_items:  

-one  

-two  

register:echo  

  当使用register而不使用循环的时候返回值如下:
  

{  

"changed":true,  

"msg":"Allitemscompleted",  

"results":[  

{  

"changed":true,  

"cmd":"echo\"one\"",  

"delta":"0:00:00.003110",  

"end":"2013-12-1912:00:05.187153",  

"invocation":{  

"module_args":"echo\"one\"",  

"module_name":"shell"  

},  

"item":"one",  

"rc":0,  

"start":"2013-12-1912:00:05.184043",  

"stderr":"",  

"stdout":"one"  

},  

{  

"changed":true,  

"cmd":"echo\"two\"",  

"delta":"0:00:00.002920",  

"end":"2013-12-1912:00:05.245502",  

"invocation":{  

"module_args":"echo\"two\"",  

"module_name":"shell"  

},  

"item":"two",  

"rc":0,  

"start":"2013-12-1912:00:05.242582",  

"stderr":"",  

"stdout":"two"  

}  

]  

}  

  使用循环并使用register的结果如下:
  

-name:Fail if return code is not 0  

fail:  

msg:"Thecommand({{item.cmd}})didnothavea0returncode"  

when:item.rc != 0  

with_items:"{{echo.results}}"  


16、  在inventory中使用循环
  当你想在inventory中进行遍历,或者是一个子集,那么可以如下所示:
# 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_hostname:
# show all the hosts in the inventory  

-debug:msg={{ item }}  

with_inventory_hostname:all  

  

# show all the hosts matching the pattern, ie all but the group www  

-debug:msg={{ item }}  

with_inventory_hostname:all:!www  


17、  在include中使用循环
  在include中使用循环如下:
  (注意:在included的任务中含有自己的with_loop值,会覆盖掉特定的item的值,如果既要使用include的item又要使用当前任务的item,必须使用set_fact去创建一个别名)
  

-include:test.yml  

with_items:  

-1  

-2  

-3  

  在test.yml中:
  

-set_fact:outer_loop="{{item}}"  

  

-debug:msg="outer item={{outer_loop}} inner item={{item}}"  

with_items:  

-a  

-b  

-c  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-430846-1-1.html 上篇帖子: Ansible系列(二):选项和常用模块 下篇帖子: 【Ansible 文档】【译文】入门教程
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表