自動化運維工具Ansible之Playbooks的when語句

在使用ansible做自動化運維的時候,大多數情況下都執行某些任務的時候都需要依賴某個變量的值或者是上一個任務的執行結果。如,根據facts信息中的系統版本相關的信息來確定使用哪種包管理器安裝軟件。Ansible提供when語句,可以控制任務的執行流程。


一個很簡單的when語句的例子:


    tasks:
      - name: "shutdown Debian flavored systems"
        command: /sbin/shutdown -t now
        when: ansible_os_family == "Debian

表示當節點主機系統爲Debian的時候,執行關機操作。


在符合語句中也可以使用小括號:


    tasks:
      - name: "shutdown CentOS 6 and 7 systems"
        command: /sbin/shutdown -t now
        when: ansible_distribution == "CentOS" and
              (ansible_distribution_major_version == "6" or ansible_distribution_major_version == "7")


 在`when`語句中也可以使用過濾器。如,我們想跳過一個語句執行中的錯誤,但是後續的任務的執行需要由該任務是否成功執行決定:

    tasks:
      - command: /bin/false
        register: result
        ignore_errors: True
      - command: /bin/something
        when: result|failed
      - command: /bin/something_else
        when: result|success
      - command: /bin/still/something_else
        when: result|skipped

有時候需要將一個字符串的變量轉換爲整數來進行數字比較:

    tasks:
      - shell: echo "only on Red Hat 6, derivatives, and later"
        when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6

在playbooks和inventory中定義的變量都可以使用,如,需要根據一個變量的bool值決定是否執行該任務:


    vars:
      epic: true

 條件語句:

    tasks:
        - shell: echo "This certainly is epic!"
          when: epic



或:

    tasks:
        - shell: echo "This certainly isn't epic!"
          when: not epic

 如果引用的變量沒有被定義,使用Jinja2的`defined`測試,可以跳過或者是拋出錯誤:

    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 not defined

 當`when``with_items`一起使用的時候,每個項都會單獨被`when`語句處理:


    tasks:
        - command: echo {{ item }}
          with_items: [ 0, 2, 4, 6, 8, 10 ]
          when: item > 5

示例:


[root@web1 ~]# cat /etc/ansible/when.yml
    ---
    - hosts: webservers
      remote_user: root
      tasks:
       - command: echo {{ item }}
         with_items: [ 1,2,3,4,5,6,8,10]
         when: item > 5
    [root@web1 ~]# ansible-playbook /etc/ansible/when.yml
    
    PLAY [webservers] ************************************************************* 
    
    GATHERING FACTS *************************************************************** 
    ok: [192.168.1.65]
    
    TASK: [command echo {{ item }}] *********************************************** 
    skipping: [192.168.1.65] => (item=1)
    skipping: [192.168.1.65] => (item=2)
    skipping: [192.168.1.65] => (item=3)
    skipping: [192.168.1.65] => (item=4)
    skipping: [192.168.1.65] => (item=5)
    changed: [192.168.1.65] => (item=6)
    changed: [192.168.1.65] => (item=8)
    changed: [192.168.1.65] => (item=10)
    
    PLAY RECAP ******************************************************************** 
    192.168.1.65               : ok=2    changed=1    unreachable=0    failed=0


如果需要的話,也可以返回自定義的facts給控制節點。返回的自定義的facts變量也可以用作下個任務的執行條件:


    tasks:
        - name: gather site specific fact data
          action: site_facts
        - command: /usr/bin/thingy
          when: my_custom_fact_just_retrieved_from_the_remote_system == '1234'


在角色和包含中使用when



如果有多個任務都需要使用同一個條件語句控制。可以將這些任務打包到一個單獨的任務文件中,然後使用`include`包含和`when`條件語句。條件語句只對包含任務文件起作用,對包含playbook文件不起作用。指定的條件語句會作用到所包含的每個任務上:


 - include: tasks/sometasks.yml
      when: "'reticulating splines' in output"

角色中使用when

  - hosts: webservers
      roles:
         - { role: debian_stock_config, when: ansible_os_family == 'Debian' }


註冊變量

在playbook中將某個命令運行的結果保存起來,提供給後續任務使用。如,通過command模塊來判斷遠程節點上某個文件是否存在或者通過執行某個命令的獲取其返回結果,並保存起來,下個任務根據獲取的變量值來決定執行的具體操作。


register關鍵字可以將任務執行結果保存到一個變量中,該變量可以在模板或者playbooks文件中使用:

 - name: test play
      hosts: all
    
      tasks:
    
          - shell: cat /etc/motd
            register: motd_contents
    
          - shell: echo "motd contains the word hi"
            when: motd_contents.stdout.find('hi') != -1

 上邊中的例子中,通過註冊變量訪問返回的內容,`stdout`裏面保存了命令的標準輸出內容。註冊變量還可以使用在`with_items`中,如果其保存的內容可以轉換爲列表,或者內容本身就是個列表。如果命令的輸出本身就是列表,可以通過`stdout_lines`訪問:

 - name: registered variable usage as a with_items list
      hosts: all
    
      tasks:
    
          - name: retrieve the list of home directories
            command: ls /home
            register: home_dirs
    
          - name: add home dirs to the backup spooler
            file: path=/mnt/bkspool/{{ item }} src=/home/{{ item }} state=link
            with_items: home_dirs.stdout_lines
            # same as with_items: home_dirs.stdout.split()

示例:


[root@web1 ~]# cat /etc/ansible/rewith.yml
    ---
    - hosts: webservers
      remote_user: root
      tasks:
       - name: list of home dir
         command: ls /home
         register: home_dirs
       - name: add home dirs to the backup
         file: path=/tmp/back/{{ item }} src=/home/{{ item }} state=link
         with_items: home_dirs.stdout_lines
    [root@web1 ~]# ansible-playbook /etc/ansible/rewith.yml
    
    PLAY [webservers] ************************************************************* 
    
    GATHERING FACTS *************************************************************** 
    ok: [192.168.1.65]
    
    TASK: [list of home dir] ****************************************************** 
    changed: [192.168.1.65]
    
    TASK: [add home dirs to the backup] ******************************************* 
    changed: [192.168.1.65] => (item=1.sql)
    changed: [192.168.1.65] => (item=1youku.sql)
    changed: [192.168.1.65] => (item=liuzhenwei)
    changed: [192.168.1.65] => (item=tom)
    
    PLAY RECAP ******************************************************************** 
    192.168.1.65               : ok=3    changed=2    unreachable=0    failed=0 
    ###遠程節點
    [root@db2 ~]# ll /tmp/back
    total 0
    lrwxrwxrwx. 1 root root 11 Aug  4 14:37 1.sql -> /home/1.sql
    lrwxrwxrwx. 1 root root 16 Aug  4 14:37 1youku.sql -> /home/1youku.sql
    lrwxrwxrwx. 1 root root 16 Aug  4 14:37 liuzhenwei -> /home/liuzhenwei
    lrwxrwxrwx. 1 root root  9 Aug  4 14:37 tom -> /home/tom


在ansible中when語句的使用還是比較多的,它可以用來控制playbooks中任務的執行流程。類似於程序中的條件語句一樣,使得ansible可以更好的按照運維人員的意願來對遠程節點執行特定的操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章