Ansible系列(六):循環和條件判斷


我寫了更完善的Ansible專欄文章:一步到位玩兒透Ansible

Ansible系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.html


1. 循環

ansible中的循環都是借助迭代來實現的。基本都是以"with_"開頭。以下是常見的幾種循環。

1.1 with_items迭代列表

ansibel支持迭代功能。例如,有一大堆要輸出的命令、一大堆要安裝的軟件包、一大堆要copy的文件等等。

例如,要安裝一堆軟件包。

---
    - hosts: localhost
      tasks: 
        - yum: name="{{item}}" state=installed
          with_items: 
            - pkg1
            - pkg2
            - pkg3

它會一個一個迭代到特殊變量"{{item}}"處。

再例如,指定一堆文件列表,然后使用grep搜索出給定文件列表中包含"www.example.com"字符串的文件:

---
    - hosts: localhost
      tasks: 
        - shell: grep -Rl "www\.example\.com" "{{item}}"
          with_items: 
            - file1
            - file2
            - file3
          register: match_file
        - debug: msg="{% for i in match_file.results %} {{i.stdout}} {% endfor %}"

注意,將with_items迭代后的結果注冊為變量時,其注冊結果也是列表式的,且其key為"results"。具體的結果比較長,可以使用debug模塊的var或msg參數觀察match_file變量的結果。

在上面,是使用for循環進行引用的。如果不使用for循環,那么就需要使用數組格式。例如,引用match_file中的第一和第二個結果。

 - debug: var=match_file.results[0].stdout
 - debug: var=match_file.results[1].stdout

顯然,不如循環引用更好,因為不知道match_file中到底有幾個匹配文件,也就不能確定match_file中的列表數量。

每個列表項中可能都包含一個或多個字典,既然with_items迭代的是列表項,那么肯定也能迭代列表中的各字典。

例如:

tasks:
    - command: echo {{ item }}
      with_items: [ 0, 2, 4, 6, 8, 10 ]
      register: num
    - debug: msg="{% for i in num.results %} {{i.stdout}} {% endfor %}"

再例如:

---
    - hosts: localhost
      tasks: 
        - shell: echo "name={{item.name}},age={{item.age}}"
          with_items: 
            - {name: zhangsan,age: 32}
            - {name: lisi,age: 33}
            - {name: wangwu,age: 35}
          register: who
        - debug: msg="{% for i in who.results %} {{i.stdout}} {% endfor %}"

1.2 with_dict迭代字典項

使用"with_dict"可以迭代字典項。迭代時,使用"item.key"表示字典的key,"item.value"表示字典的值。

例如:

---
    - hosts: localhost tasks: - debug: msg="{{item.key}} & {{item.value}}" with_dict: { address: 1,netmask: 2,gateway: 3 }

另一種情況,字典是已存儲好的。例如ansible facts中的ansible_eth0.ipv4,其內容如下:

"ipv4": {
    "address": "192.168.100.65",
    "netmask": "255.255.255.0",
    "gateway": "192.168.100.2"
}

這種情況下,with_dict處可以直接指定該字典的key。即:

---
    - hosts: localhost tasks: - debug: msg="{{item.key}} & {{item.value}}" with_dict: ansible_eth0.ipv4

再例如,直接引用playbook中定義的vars。

---
 - hosts: 192.168.100.65
   gather_facts: False
   vars:
     user: 
        longshuai_key: 
           name: longshuai
           gender: Male
        xiaofang_key: 
           name: xiaofang
           gender: Female
   tasks:
      - name: print hash loop var
        debug: msg="{{ item.key }} & {{ item.value.name }} & {{ item.value.gender }}"
        with_dict: "{{ user }}"

1.3 with_fileglob迭代文件

例如,拷貝一堆用通配符匹配出來的文件到各遠程主機上。

---
    - hosts: centos
      tasks: 
        - copy: src="{{item}}" dest=/tmp/
          with_fileglob:
            - /tmp/*.sh
            - /tmp/*.py

注意,通配符無法匹配"/",因此無法遞歸到子目錄中,也就無法迭代子目錄中的文件。

1.4 with_lines迭代行

with_lines很好用,可以將命令行的輸出結果按行迭代。

例如,find一堆文件出來,copy走。

---
    - hosts: localhost
      tasks:
        - copy: src="{{item}}" dest=/tmp/yaml
          with_lines:
            - find /tmp -type f -name "*.yml"

1.5 with_nested嵌套迭代

嵌套迭代是指多次迭代列表項。例如:

---
    - hosts: localhost tasks: - debug: msg="{{item[0]}} & {{item[1]}}" with_nested: - [a,b] - [1,2,3]

結果將得到"a & 1"、"a & 2"、"a & 3"、"b & 1"、"b & 2"和"b & 3"共6個結果。

2. 條件判斷

在ansible中,只有when可以實現條件判斷。

tasks: 
  - name: config the yum repo for centos 6
    yum_repository:
       name: epel
       description: epel
       baseurl: http://mirrors.aliyun.com/epel/6/$basearch/
       gpgcheck: no
    when: ansible_distribution_major_version == "6"

注意兩點:

  • when判斷的對象是task,所以和task在同一列表層次。它的判斷結果決定它所在task是否執行,而不是它下面的task是否執行。
  • when中引用變量的時候不需要加{{ }}符號。

此外,還支持各種邏輯組合。

tasks:

# 邏輯或
  - command: /sbin/shutdown -h now
    when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or
          (ansible_distribution == "Debian" and ansible_distribution_major_version == "7")

# 邏輯與
  - command: /sbin/shutdown -t now
    when:
      - ansible_distribution == "CentOS"
      - ansible_distribution_major_version == "6"

# 取反
  - command: /sbin/shutdown -t now
    when: not ansible_distribution == "CentOS"

還可以直接直接引用布爾值的變量。

---
    - hosts: localhost
      vars:
        epic: False

      tasks:
        - debug: msg="This certainly is epic!"
          when: not epic

此外,可以使用jinja2的defined來測試變量是否已定義,使用undefined可以取反表示未定義。例如:

tasks:
    - shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
      when: foo is defined

    - fail: msg="Bailing out. this play requires 'bar'"
      when: bar is undefined


免責聲明!

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



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