有可能在一個任務中,可能要作不少事情,例如建立多個用戶,安裝不少個包等,那麼就有可能用到循環。mysql
重複的任務能夠用下面的方式:sql
- name: add several usersshell user: name={{ item }} state=present groups=wheelapp with_items:負載均衡 - testuser1dom - testuser2ssh
|
若是你定義了一個變量文件建立了一個YAML的列表,或者是在var節中,那麼可使用如下的方式:ide
with_items:"{{somelist}}"
|
上面的和下面的表示爲相同的含義,以下:oop
-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的時候,能夠減小包管理事務。spa
在遍歷的各項中,能夠不是簡單的列表,若是是hash列表的時候,你可使用子健,以下:
-name:add several users user:name={{ item.name }} state=present groups={{ item.groups }} with_items: -{name:'testuser1',groups:'wheel'} -{name:'testuser2',groups:'root'}
|
嵌套循環以下所示:
-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']
|
假設存在如下變量:
--- 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}}"
|
「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" }
|
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 路徑
假設存在如下的變量:
--- 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}}"
|
假設你想遍歷一個用戶列表,建立他們,而且用特定的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密鑰在記錄以內
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
|
random_choice表示爲隨機的選擇,可是不是一個負載均衡,在有的程度上至關於負載均衡,以下:
-debug:msg={{ item }} with_random_choice: -"gothroughthedoor" -"drinkfromthegoblet" -"presstheredbutton" -"donothing"
|
提供的字符串將會有一個被隨機選中。
有的時候會去嘗試一個任務在特定的條件下,以下:
-action:shell /usr/bin/foo register:result until:result.stdout.find("all systems go") != -1 retries:5 delay:10
|
在默認狀況下,retries值爲3,delay爲5秒,在查看的時候,可使用-vv的選項來查看變量的值
這不是一個循環,可是很接近。當你在引用一個文件的時候,取決於上一個文件的內容或者是名稱,那麼能夠以下:
-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
|
在有的時候,須要遍歷執行的結果,須要注意的是,這是在遠程機器上執行的,而不是在本機器上執行的,以下:
-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}}"
|
能夠遍歷如下集合,以下:
[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 } ] }
|
當使用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}}"
|
當你想在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
|
在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 |