不少狀況下,一個play是否執行會依賴於某個(些)變量的值,這個變量能夠來自自定義變量、facts,甚至是另外一個task的執行結果。html
ansible經過變量斷定task是否執行,咱們稱之爲task控制。docker
在我看來,ansible的控制語句帶來的最大的好處就是使部署代碼更加健壯,舉幾個例子:shell
ansible使用最頻繁的task控制語句就是「when」語句。apache
when語句能夠在task中直接使用,也能夠與include*、import*、roles、vars_files、incloud_vars等引入語句搭配使用。執行結果也比較通俗易懂,前者用來判斷task是否執行,後者用來判斷task是否引用。網絡
when語句引用變量時不用加「{{}}」。在when語句中,ansible將不帶引號的字符串認定爲變量,因此若是使用字符串記得加單(雙)引號。ide
對不一樣數據類型的判斷可使用不一樣的條件語句:函數
使用「==」:ui
tasks: - name: "shut down Debian flavored systems" command: /sbin/shutdown -t now when: ansible_facts['os_family'] == "Debian"
使用「is」:this
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 - command: /bin/something when: result is failed # In older versions of ansible use ``success``, now both are valid but succeeded uses the correct tense. - command: /bin/something_else when: result is succeeded - command: /bin/still/something_else when: result is skipped
使用「in」:spa
when: "'reticulating splines' in output"
使用運算符(記得使用「int」將參數轉爲整數類型):
tasks: - shell: echo "only on Red Hat 6, derivatives, and later" when: ansible_facts['lsb']['major_release']|int >= 6
直接判斷變量的True/False:
tasks: - shell: echo "This certainly is epic!" when: epic - shell: echo "This certainly isn't epic!" when: not epic
多個條件判斷語句結合:
tasks: - name: "shut down CentOS 6 and Debian 7 systems" command: /sbin/shutdown -t now when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")
when語句的參數也支持列表,等價於「and」:
tasks: - name: "shut down CentOS 6 systems" command: /sbin/shutdown -t now when: - ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"
上面說到when語句能夠控制task是否被引用,例如當變量「output」包含字符串「reticulating splines」時再導入playbook「sometasks.yml」:
- import_tasks: tasks/sometasks.yml when: "'reticulating splines' in output"
其餘的導入語句import_playbook;include_tasks;import_role;include_role;roles等語句使用方法也相似上面的示例。
一樣,當task中使用「include_vars」語句導入變量文件時,也能夠控制其導入,格式與導入play相似,這裏就不舉例了。
比較特殊的,咱們能夠基於一個task的執行結果來判斷某個task是否執行,此時就用到了「register」語句。這裏列舉一個我在部署openshift時的例子:
遇到的問題:
部署harbor時,我想用「docker network connect」命令將harbor_harbor和ldapserver這兩個容器網絡打通,可是發現若是這兩個容器是已經關聯的狀態,再次執行playbook時拋報錯「Error response from daemon: service endpoint with name ldapserver already exists」這樣就不知足ansible的冪等性。
解決辦法:
第一個task是查詢harbor_harbor的網絡鏈接信息,並將其註冊爲一個變量「harbor_conn_info」:
- name: Get network harbor_harbor connection information shell: >
/usr/bin/docker network inspect harbor_harbor register: harbor_conn_info
上面示例中,變量「harbor_conn_info」是「/usr/bin/docker network inspect harbor_harbor」命令的執行結果,ansible從執行結果中查找「ldapserver」字符串,若是未查到(即find函數結果返回值爲-1)則執行「docker network connect」命令。
經過這個例子,說明ansible的控制語句可以使部署代碼知足最基本冪等性要求,也能使代碼更加健壯。
基於變量的控制語句是另一種task控制方式,不須要「when」語句,例如:
---
- hosts: all remote_user: root vars_files: - "vars/common.yml"
- [ "vars/{{ ansible_facts['os_family'] }}.yml", "vars/os_defaults.yml" ] tasks: - name: make sure apache is started service: name={{ apache }} state=started
歡迎你們關注個人公衆號: