Ansible13:Playbook循環語句

循環語句

簡介

咱們在編寫playbook的時候,不可避免的要執行一些重複性操做,好比指安裝軟件包,批量建立用戶,操做某個目錄下的全部文件等。正如咱們所說,ansible一門簡單的自動化語言,因此流程控制、循環語句這些編程語言的基本元素它一樣都具有。web

下面咱們簡單的說一說Playbook中循環語句。sql

loop關鍵字說明

在playbook中使用循環,直接使用loop關鍵字便可。shell

以下示例,啓動httpd和postfilx服務:編程

tasks:
  - name: postfix and httpd are running
    service:
      name: "{{ item }}"
      state: started
    loop:
      - postfix
      - httpd

也能夠將loop循環的列表提早賦值給一個變量,而後在循環語句中調用:dom

#cat test_services.yml
test_services:
  - postfix
  - httpd

# cat install_pkgs.yml 
- name: start services
  hosts: test
  vars_files:
    - test_services.yml
  tasks:
    - name: postfix and httpd are running
      service:
        name: "{{ item }}"
        state: started
      loop: "{{ test_services }}"

下面是一個循環更復雜類型數據的示例:ssh

# cat test_loop.yml 
- name: test loop
  hosts: test
  tasks:
  - name: add www group
    group: 
      name: www
  - name: add several users
    user: 
      name: "{{ item.name }}"
      state: present 
      groups: "{{ item.groups }}"
    loop:
      - { name: 'testuser1', groups: 'wheel' }
      - { name: 'testuser2', groups: 'www' }

在循環語句中註冊變量

下面是一個register的變量在循環中使用的例子:編程語言

# cat register_loop.yml 
- name: registered variable usage as a loop list
  hosts: test
  tasks:
      - name: ensure /mnt/bkspool exists
        file:
          path: /mnt/bkspool
          state: directory
      - name: retrieve the list of home directories
        command: ls /home
        register: home_dirs
      - name: Show home_dirs results
        debug:
          var: home_dirs.stdout_lines
      - name: add home dirs to the backup spooler
        file: 
          path: /mnt/bkspool/{{ item }}
          src: /home/{{ item }}
          state: link
          force: yes
        loop: "{{ home_dirs.stdout_lines }}"

在循環語句中註冊變量:ide

- name: Loop Register test
  gather_facts: no
  hosts: test
  tasks:
    - name: Looping Echo Task
      shell: "echo this is my item: {{ item }}"
      loop:
        - one
        - two
      register: echo_results
    - name: Show echo_results variable
      debug:
        var: echo_results

執行語句,能夠看到變量的返回結果爲一個字典列表:oop

ok: [10.1.61.187] => {
    "echo_results": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo this is my item: one",
                "delta": "0:00:00.004905",
                "end": "2019-06-10 00:23:51.814151",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo this is my item: one",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "one",
                "rc": 0,
                "start": "2019-06-10 00:23:51.809246",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "this is my item: one",
                "stdout_lines": [
                    "this is my item: one"
                ]
            },
            {
                "ansible_loop_var": "item",
                "changed": true,
                "cmd": "echo this is my item: two",
                "delta": "0:00:00.004736",
                "end": "2019-06-10 00:23:52.008981",
                "failed": false,
                "invocation": {
                    "module_args": {
                        "_raw_params": "echo this is my item: two",
                        "_uses_shell": true,
                        "argv": null,
                        "chdir": null,
                        "creates": null,
                        "executable": null,
                        "removes": null,
                        "stdin": null,
                        "stdin_add_newline": true,
                        "strip_empty_ends": true,
                        "warn": true
                    }
                },
                "item": "two",
                "rc": 0,
                "start": "2019-06-10 00:23:52.004245",
                "stderr": "",
                "stderr_lines": [],
                "stdout": "this is my item: two",
                "stdout_lines": [
                    "this is my item: two"
                ]
            }
        ]
    }
}

舊循環語句

在Ansible 2.5之前,playbook經過不一樣的循環語句以實現不一樣的循環,這些語句使用with_做爲前綴。這些語法目前仍然兼容,但在將來的某個時間點,會逐步廢棄。

循環語句關鍵字 描述
with_items 簡單的列表循環
with_nested 嵌套循環
with_dict 循環字典
with_fileglob 循環指定目錄中的全部文件
with_lines 循環一個文件中的全部行
with_sequence 生成一個自增的整數序列,能夠指定起始值和結束值以及步長。參數以key=value的形式指定,format指定輸出的格式。數字能夠是十進制、十六進制、八進制
with_subelement 遍歷子元素
with_together 遍歷數據並行集合

1. with_items

- hosts: test
  vars:
    data:
      - user0
      - user1
      - user2
  tasks:
    - name: "with_items"
      debug:
        msg: "{{ item }}"
      with_items: "{{ data }}"

2. with_nested

tasks: 
  - name: debug loops
    debug: msg="name is {{ item[0] }}  vaule is {{ item[1] }} num is {{ item[2] }}"
    with_nested:
      - ['alice','bob']
      - ['a','b','c']
      - ['1','2','3']

item[0]是循環的第一個列表的值['alice','bob']。item[1]是第二個列表的值;item[2]則是第三個列表的值,以上的執行輸出以下:

# ansible-playbook with_nested_ex.yml 

PLAY [with_nested test] ******************************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [10.1.61.187]

TASK [debug loops] ***********************************************************************************************
ok: [10.1.61.187] => (item=['alice', 'a', '1']) => {
    "msg": "name is alice  vaule is a num is 1"
}
ok: [10.1.61.187] => (item=['alice', 'a', '2']) => {
    "msg": "name is alice  vaule is a num is 2"
}
ok: [10.1.61.187] => (item=['alice', 'a', '3']) => {
    "msg": "name is alice  vaule is a num is 3"
}
ok: [10.1.61.187] => (item=['alice', 'b', '1']) => {
    "msg": "name is alice  vaule is b num is 1"
}
ok: [10.1.61.187] => (item=['alice', 'b', '2']) => {
    "msg": "name is alice  vaule is b num is 2"
}
ok: [10.1.61.187] => (item=['alice', 'b', '3']) => {
    "msg": "name is alice  vaule is b num is 3"
}
ok: [10.1.61.187] => (item=['alice', 'c', '1']) => {
    "msg": "name is alice  vaule is c num is 1"
}
ok: [10.1.61.187] => (item=['alice', 'c', '2']) => {
    "msg": "name is alice  vaule is c num is 2"
}
ok: [10.1.61.187] => (item=['alice', 'c', '3']) => {
    "msg": "name is alice  vaule is c num is 3"
}
ok: [10.1.61.187] => (item=['bob', 'a', '1']) => {
    "msg": "name is bob  vaule is a num is 1"
}
ok: [10.1.61.187] => (item=['bob', 'a', '2']) => {
    "msg": "name is bob  vaule is a num is 2"
}
ok: [10.1.61.187] => (item=['bob', 'a', '3']) => {
    "msg": "name is bob  vaule is a num is 3"
}
ok: [10.1.61.187] => (item=['bob', 'b', '1']) => {
    "msg": "name is bob  vaule is b num is 1"
}
ok: [10.1.61.187] => (item=['bob', 'b', '2']) => {
    "msg": "name is bob  vaule is b num is 2"
}
ok: [10.1.61.187] => (item=['bob', 'b', '3']) => {
    "msg": "name is bob  vaule is b num is 3"
}
ok: [10.1.61.187] => (item=['bob', 'c', '1']) => {
    "msg": "name is bob  vaule is c num is 1"
}
ok: [10.1.61.187] => (item=['bob', 'c', '2']) => {
    "msg": "name is bob  vaule is c num is 2"
}
ok: [10.1.61.187] => (item=['bob', 'c', '3']) => {
    "msg": "name is bob  vaule is c num is 3"
}

PLAY RECAP *******************************************************************************************************
10.1.61.187

3. with_dict

# 假若有以下變量內容:
users:
  alice:
    name: Alice Appleworth
    telephone: 123-456-7890
  bob:
    name: Bob Bananarama
    telephone: 987-654-3210

# 如今須要輸出每一個用戶的用戶名和手機號:
tasks:
  - name: Print phone records
    debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
    with_dict: "{{ users }}"

4. with_fileglob

- hosts: test
  tasks:
    - name: Make key directory     
      file: 
        path: /root/.sshkeys 
        state: directory 
        mode: 0700 
        owner: root 
        group: root 
        
    - name: Upload public keys     
      copy: 
        src: "{{ item }}"
        dest: /root/.sshkeys
        mode: 0600 
        owner: root 
        group: root  
      with_fileglob:
        - /root/.ssh/*.pub 
        
    - name: Assemble keys into authorized_keys file     
      assemble: 
        src: /root/.sshkeys 
        dest: /root/.ssh/authorized_keys
        mode: 0600 
        owner: root 
        group: root

5. with_lines

with_lines循環結構會讓你在控制主機上執行任意命令,並對命令的輸出進行逐行迭代。假設咱們有一個 文件test.txt包含以下行:

Breeze Yan
Bernie Yang
jerry Qing

咱們能夠經過以下方法進行逐行輸出:

- name: print all names
  debug: msg="{{ item }}"
  with_lines:
    - cat test.txt

6. with_subelement

假如如今須要遍歷一個用戶列表,並建立每一個用戶,並且還須要爲每一個用戶配置以特定的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"

playbook中定義以下:

tasks:
  - 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

也能夠遍歷嵌套的子列表:

- 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

7. with_sequence

- 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%02d
    # 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    # stride用於指定步長
    # a simpler way to use the sequence plugin
    # create 4 groups
    - group: name=group{{ item }} state=present
      with_sequence: count=4

8. with_random_choice

從列表中隨機取一個值:

- debug: msg={{ item }}
  with_random_choice:
     - "go through the door"
     - "drink from the goblet"
     - "press the red button"
     - "do nothing"

9. do-Util循環

- action: shell /usr/bin/foo
  register: result
  until: result.stdout.find("all systems go") != -1
  retries: 5
  delay: 10

重複執行shell模塊,當shell模塊執行的命令輸出內容包含"all systems go"的時候中止。重試5次,延遲時間10秒。retries默認值爲3,delay默認值爲5。任務的返回值爲最後一次循環的返回結果。

10. with_together

示例:

- hosts: webservers
  remote_user: root
  vars:
    alpha: [ 'a','b','c','d']
    numbers: [ 1,2,3,4 ]
  tasks:
    - debug: msg="{{ item.0 }} and {{ item.1 }}"
      with_together:
         - "{{ alpha }}"
         - "{{ numbers }}"
# 輸出的結果爲:
ok: [192.168.1.65] => (item=['a', 1]) => {
    "item": [
        "a",
        1
    ],
    "msg": "a and 1"
}
ok: [192.168.1.65] => (item=['b', 2]) => {
    "item": [
        "b",
        2
    ],
    "msg": "b and 2"
}
ok: [192.168.1.65] => (item=['c', 3]) => {
    "item": [
        "c",
        3
    ],
    "msg": "c and 3"
}
ok: [192.168.1.65] => (item=['d', 4]) => {
    "item": [
        "d",
        4
    ],
    "msg": "d and 4"
}
相關文章
相關標籤/搜索