ansible playbooks loop循環


在一個task中循環某個操作

1、標准循環

  1. - name: add several users
  2. user:
  3. name: "{{ item }}"
  4. state: present
  5. groups: "wheel"
  6. loop:
  7. - testuser1
  8. - testuser2
  9. #如果已經在變量文件中,定義了yaml列表,可以這么寫
  10. loop: "{{ somelist }}"
note:在2.5 Ansible之前主要使用with_ <lookup>關鍵字來創建循環,循環關鍵字基本上類似於with_list,with_items。
我現在也在用,啊哈!
一些ansible插件,類似yum和apt模塊可以直接列出引用的選項,比使用loop更好,如下:
  1. - name: optimal yum
  2. yum:
  3. name: "{{list_of_packages}}"
  4. state: present
  5. - name: non optimal yum, not only slower but might cause issues with interdependencies
  6. yum:
  7. name: "{{item}}"
  8. state: present
  9. loop: "{{list_of_packages}}"
迭代的items類型也可以是hash列表,例如:
  1. - name: add several users
  2. user:
  3. name: "{{ item.name }}"
  4. state: present
  5. groups: "{{ item.groups }}"
  6. loop:
  7. - { name: 'testuser1', groups: 'wheel' }
  8. - { name: 'testuser2', groups: 'root' }

2、復雜的循環

有時候你不只是需要一個簡單列表,你可以用jinja2表達式創建復雜的列表,例如使用 “netsed" lookup
  1. - name: give users access to multiple databases
  2. mysql_user:
  3. name: "{{ item[0] }}"
  4. priv: "{{ item[1] }}.*:ALL"
  5. append_privs: yes
  6. password: "foo"
  7. loop: "{{ query('nested', [ 'alice', 'bob' ], [ 'clientdb', 'employeedb', 'providerdb' ]) }}"
note: with_ 循環實際上是組合了 with_ + lookup(),甚至是with_items。 loop也可以這么搞,類似上邊例子。

3、使用lookup 與 用loop查詢

ansible2.5加入了新的函數 query,為lookup插件增加一些益處,當使用新的關鍵字loop時候。query提供一個更簡單的借口和可預測性更好的輸出,確保兼容loop。
一些情況中,lookup函數不會返回 loop需要的list,下列的調用是相等的:
  1. loop: "{{ query('nested', ['alice', 'bob'], ['clientdb', 'employeedb', 'providerdb']) }}"
  2. loop: "{{ lookup('nested', ['alice', 'bob'], ['clientdb', 'employeedb', 'providerdb'], wantlist=True) }}"

4、Do-Until循環

  1. - shell: /usr/bin/foo
  2. register: result
  3. until: result.stdout.find("all systems go") != -1
  4. retries: 5
  5. delay: 10
上例 遞歸執行shell模塊,直到“all systems go”在標准輸出出現,或者每個10s執行1次,執行5次之后無結果。 retries默認值是3,delay默認值是5。
note:如果until參數沒有定義, retries值被強制設置為1。

5、使用loop中的register

  1. - shell: "echo {{ item }}"
  2. loop:
  3. - "one"
  4. - "two"
  5. register: echo
與使用loop和register不同的例子
  1. {
  2. "changed": true,
  3. "msg": "All items completed",
  4. "results": [
  5. {
  6. "changed": true,
  7. "cmd": "echo \"one\" ",
  8. "delta": "0:00:00.003110",
  9. "end": "2013-12-19 12:00:05.187153",
  10. "invocation": {
  11. "module_args": "echo \"one\"",
  12. "module_name": "shell"
  13. },
  14. "item": "one",
  15. "rc": 0,
  16. "start": "2013-12-19 12:00:05.184043",
  17. "stderr": "",
  18. "stdout": "one"
  19. },
  20. {
  21. "changed": true,
  22. "cmd": "echo \"two\" ",
  23. "delta": "0:00:00.002920",
  24. "end": "2013-12-19 12:00:05.245502",
  25. "invocation": {
  26. "module_args": "echo \"two\"",
  27. "module_name": "shell"
  28. },
  29. "item": "two",
  30. "rc": 0,
  31. "start": "2013-12-19 12:00:05.242582",
  32. "stderr": "",
  33. "stdout": "two"
  34. }
  35. ]
  36. }
循環遍歷注冊的變量來檢查結果:
  1. - name: Fail if return code is not 0
  2. fail:
  3. msg: "The command ({{ item.cmd }}) did not have a 0 return code"
  4. when: item.rc != 0
  5. loop: "{{ echo.results }}"
在迭代期間,當前item的結果將被放置在變量中
  1. - shell: echo "{{ item }}"
  2. loop:
  3. - one
  4. - two
  5. register: echo
  6. changed_when: echo.stdout != "one"

6、循環inventory

如果想循環inventory中的hosts或者部分hosts,你可以用loop的ansible_play_batch或者groups變量:
  1. # show all the hosts in the inventory
  2. - debug:
  3. msg: "{{ item }}"
  4. loop: "{{ groups['all'] }}"
  5. #show all the hosts in the current play
  6. - debug:
  7. msg: "{{ item }}"
  8. loop: "{{ ansible_play_batch }}"
使用lookup 插件 inventory_hostname 實現:
  1. # show all the hosts in the inventory
  2. - debug:
  3. msg: "{{ item }}"
  4. loop: "{{ query('inventory_hostnames', 'all') }}"
  5. # show all the hosts matching the pattern, ie all but the group www
  6. - debug:
  7. msg: "{{ item }}"
  8. loop: "{{ query('inventory_hostnames', 'all!www') }}"
 

7、循環控制

2.0版本你可以使用loops和task includes(不能用playbook includes)。這增加了一次循環一組任務的能力。每次循環,Ansible默認設置循環變量item,這會導致這些嵌套loop覆蓋來自“外部”循環的項目的值。從Ansible 2.1開始,loop_control選項可用於指定要用於循環的變量名。
  1. # main.yml
  2. - include: inner.yml
  3. - include_tasks: inner.yml
  4. loop:
  5. - 1
  6. - 2
  7. - 3
  8. loop_control:
  9. loop_var: outer_item
  10. # inner.yml
  11. - debug:
  12. msg: "outer item={{ outer_item }} inner item={{ item }}"
  13. loop:
  14. - a
  15. - b
  16. - c
note:如果Ansible檢測到當前循環正在使用已定義的變量,則會引發錯誤以使任務失敗。
當使用復雜的數據結構來循環顯示時,可能會出現busy情況,這就是label指令提供幫助的地方
  1. - name: create servers
  2. digital_ocean:
  3. name: "{{ item.name }}"
  4. state: present
  5. loop:
  6. - name: server1
  7. disks: 3gb
  8. ram: 15Gb
  9. network:
  10. nic01: 100Gb
  11. nic02: 10Gb
  12. ...
  13. loop_control:
  14. label: "{{ item.name }}"
現在,它將只顯示標簽字段,而不是每個項目的整個結構,它默認為{{item}}來照常顯示內容。
 
循環控制的另一個選項是暫停,它允許您控制執行任務循環中的項目之間的時間(以秒為單位)。
  1. # main.yml
  2. - name: create servers, pause 3s before creating next
  3. digital_ocean:
  4. name: "{{ item }}"
  5. state: present
  6. loop:
  7. - server1
  8. - server2
  9. loop_control:
  10. pause: 3
如果您需要跟蹤您在循環中的位置,可以使用index_var選項來循環控制以指定變量名稱以包含當前循環索引。
  1. - name: count our fruit
  2. debug:
  3. msg: "{{ item }} with index {{ my_idx }}"
  4. loop:
  5. - apple
  6. - banana
  7. - pear
  8. loop_control:
  9. index_var: my_idx

8、loops和 includes (2.0版本)

由於loop_control在Ansible 2.0中不可用,因此當使用帶有循環的include時,應該使用set_fact保存item的“outer”循環值:
  1. # main.yml
  2. - include_tasks: inner.yml
  3. loop:
  4. - 1
  5. - 2
  6. - 3
  7. # inner.yml
  8. - set_fact:
  9. outer_item: "{{ item }}"
  10. - debug:
  11. msg: "outer item={{ outer_item }} inner item={{ item }}"
  12. loop:
  13. - a
  14. - b
  15. - c
  16. Note


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM