Ansible—— 41. playbook 操作技巧

1. ansible中使用python字符串

獲取a字符串的第3個字符,則可以使用"a[2]"獲取,索引從0開始

cat test.yml
- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a[2]}}"

a[2:5]獲取到a字符串的第3到第5個字符(不包含第6個字符)
a[:5]獲取到a字符串的第6個字符之前的所有字符(不包含第6個字符)
a[5:]獲取到a字符串的第6個字符之後的所有字符(包含第6個字符)
in和not in,也是python的字符串運算符

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "true"
    when: "'va' in a"

使用加號"+"連接兩個字符串

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
    b: "vbB67890"
  tasks:
  - debug:
      msg: "{{a+b}}"

使用乘號"*"連續的重複輸出字符串

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a*3}}"

使用find函數查找指定字符在字符串中的位置

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a.find('A1')}}"

當在字符串中沒有找到對應的字符時,find函數的返回值爲"-1",所以,我們也可以利用這一特性,判斷字符串中是否包含指定的字符

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "not found"
    when: a.find('A2') == -1

在使用find函數時,也可以指定查找範圍,find函數的語法是find(string,begin,end)
string是要查找的字符串,begin是起始位置,end是結束位置

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a.find('A1',1)}}"

2. 任務委派

在某些場景下,需要指定某個任務在特定的主機上執行,playbook中設置的目標主機是A、B、C三臺主機,playbook中一共有5個task,,其中第3個task需要在D主機上執行,而不是在A、B、C這三臺目標主機上執行,將第3個task單獨設置成一個play段,然後將這個play段的目標主機設置爲D,示意代碼如下:

- hosts: A,B,C
  tasks:
  - task1:
      ...
  - task2:
      ...
 
- hosts: D
  gather_facts: no
  tasks:
  - task3:
 
- hosts: A,B,C
  tasks:
  - task4:
      ...
  - task5:
      ...

任務委派可以讓某個任務在指定的主機上執 行,使用delegate_to關鍵字即可實現"任務委託"功能。

- hosts: test70,test71
  gather_facts: no
  tasks:
  - file:
      path: "/tmp/ttt"
      state: touch
 
  - file:
      path: "/tmp/delegate"
      state: touch
    delegate_to: test61
 
  - file:
      path: "/tmp/ttt1"
      state: touch

3. 在ansible主機上執行任務

默認情況下,task都會在目標主機上執行,但是在某些場景下,需要讓某個task在ansible主機上執行,而不是在目標主機上執行將"delegate_to"對應的主機設置成ansible主機解決這個問題,也可以使用"connection: local"來完成。

- hosts: test70,test61
  gather_facts: no
  tasks:
  - file:
      path: "/tmp/inAnsible"
      state: touch
    connection: local
 
  - file:
      path: "/tmp/test"
      state: touch

4. 設置某個task只運行一次

使用了get_url模塊,從網站上下載了這個包,但是由於目標主機中一共有5臺,所以,下載包的這個task會重複執行5次,示例如下:

- hosts: A,B,C,D,E
  gather_facts: no
  tasks:
  - get_url:
      url: "http://nexus.zsythink.net/repository/testraw/testfile/test.tar"
      dest: /tmp/
    connection: local
 
  - copy:
      src: "/tmp/test.tar"
      dest: "/tmp"

執行上例playbook,每個任務會針對每個目標主機都執行一遍,一共執行5遍,但是對於第一個task來說,沒有必要執行5 遍,因爲只要執行一遍,我需要的安裝包就會下載到ansible主機中,之後的4遍就沒必要執行了,如果執行上例playbook,由於 ansible具備冪等性,當第一個task執行一次後,之後執行的4次其實並沒有什麼實質性的操作,但是,當你的安裝包特別大、目標主機又特別多時,這 些多餘的操作會浪費一些時間,所以,完全沒有必要執行之後的4遍操作,藉助到"run_once"關鍵字 了,"run_once"關鍵字能讓對應的任務只運行一次,示例如下:

- hosts: A,B,C,D,E
  gather_facts: no
  tasks:
  - get_url:
      url: "http://nexus.zsythink.net/repository/testraw/testfile/test.tar"
      dest: /tmp/
    connection: local
    run_once: true
 
  - copy:
      src: "/tmp/test.tar"
      dest: "/tmp"

5. 向列表中追加項

直接將兩個列表相加,這樣兩個列表會合併成一個列表

- hosts: test71
  gather_facts: no
  vars:
   l1:
     - 1
     - 2
   l2:
     - a
     - b
     - 2
  tasks:
  - set_fact:
      l3: "{{ l1 + l2 }}"
  - debug:
      var: l3

利用列表合併的這一特性,在列表中追加元素

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 1
     - 2
  tasks:
  - set_fact:
      tlist: "{{ tlist + ['a'] }}"
  - debug:
      var: tlist

使用jinja2的語法,完成上述追加元素的過程

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 1
     - 2
  tasks:
  - set_fact:
      tlist: "{% set tlist = tlist + ['a'] %}{{tlist}}"
  - debug:
      var: tlist

在python中,使用列表的extend()函數,也可以實現列表合併的效果,與使用"+"的效果完全相同,比如,將列表A和列表B合併,可以使用A.extend(B)

  • hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 1
     - 2
  tasks:
  - set_fact:
      tlist: "{{ tlist.extend([3,'a']) }}{{tlist}}"
  - debug:
      var: tlist

append()函數可以直接在列表中追加元素

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 1
     - 2
  tasks:
  - set_fact:
      tlist: "{{ tlist.append('a') }}{{tlist}}"
  - debug:
      var: tlist

append函數只是單純的將一個對象當做新元素追加到列表中,這個新元素可以時數值或者字符串,也可以是一個列表,或者字典。

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 1
     - 2
  tasks:
  - set_fact:
      tlist: "{{ tlist.append(['a','b']) }}{{tlist}}"
  - debug:
      var: tlist

6. 在列表中插入項

利用python的insert()函數,在list的指定位置插入新元素

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 11
     - 2
     - 11
  tasks:
  - set_fact:
      tlist: "{{ tlist.insert(1,'a') }}{{tlist}}"
  - debug:
      var: tlist

7. 從列表中刪除項

利用python的pop()函數,根據指定的索引刪除元素。在python中,pop()函數會根據索引刪除元素的同時,將被刪除的元素值作爲返回值。

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 11
     - 2
     - 'a'
     - 'b'
     - 3
  tasks:
  - debug:
      msg: "{{tlist.pop(2)}}"

利用pop()函數刪除列表中指定位置的元素

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 11
     - 2
     - 'a'
     - 'b'
     - 3
  tasks:
  - set_fact:
      tlist: "{{ [ tlist.pop(2),tlist ][1] }}"
  - debug:
      var: tlist

利用python的remove()函數,根據指定的值刪除元素(第一個與指定值匹配的元素會被刪除)

- hosts: test71
  gather_facts: no
  vars:
   tlist:
     - 11
     - 'b'
     - 'a'
     - 'b'
     - 3
  tasks:
  - set_fact:
      tlist: "{{ tlist.remove('b') }}{{tlist}}"
  - debug:
      var: tlist

利用jinja2的for循環,刪除列表中所有匹配到的項

- hosts: test71
  gather_facts: no
  vars:
    tlist:
    - 11
    - 'b'
    - 'a'
    - 'b'
    - 11
    - 'a11'
    - '1a'
    - '11'
  tasks:
  - set_fact:
      tlist: "{%for i in tlist%}{% if 11 in tlist%}{{tlist.remove(11)}}{%endif%}{%endfor%}{{tlist}}"
  - debug:
      var: tlist

如下寫法只適合所有元素都是字符串類型的列表,而且,如下寫法可以通過正則表達式,刪除掉所有匹配的元素

- hosts: test71
  gather_facts: no
  vars:
    tlist:
    - '11'
    - 'b'
    - '1a'
    - '1b'
    - 'c'
    - 'a1c'
    - 'b1'
  tasks:
  - set_fact:
      tlist: "{{ tlist | reject('search','1') | list }}"
  - debug:
      var: tlist

reject是jinja2中的一個內建的filter,search是 ansible實現的一個tests,list也是一個過濾器,上例通過將它們結合的方式,刪除了列表中所有符合條件的元素,使用這種方法有個前提條件, 就是列表中的所有元素都必須是字符串,當列表中的所有元素都是字符串時,使用這種方法,可以通過正則表達式靈活的刪除元素,比如,刪除所有’1’開頭的元素。

- hosts: test71
  gather_facts: no
  vars:
    tlist: ['11','b','1a','1b','c','a1c1','b11']
  tasks:
  - set_fact:
      tlist: "{{ tlist | reject('search','^1') | list }}"
  - debug:
      var: tlist
上例playbook執行後,debug輸出如下:
TASK [debug] ***********************
ok: [test71] => {
    "tlist": [
        "b",
        "c",
        "a1c1",
        "b11"
    ]
}

————Blueicex 2020/3/31 11:41 [email protected]

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