Ansible Playbook循环语句

旧循环语句

在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: [192.168.0.187]

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

PLAY RECAP *******************************************************************************************************
192.168.0.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"
}
上一篇:3.0 Ansible Playbooks基础


下一篇:3.0 Ansible Playbooks基础