完整的jinja2說明文檔,請移步:http://docs.jinkan.org/docs/jinja2/
用于playbook中的jinja 2過濾器
更改數據格式,其結果是字符串
{{ some_variable | to_json }}
{{ some_variable | to_yaml }}
對于人類可讀的輸出
{{ some_variable | to_nice_json }}
{{ some_variable | to_nice_yaml }}
還可以增加參數( new in 2.2)
{{ some_variable | to_nice_json(indent=2) }}
{{ some_variable | to_nice_yaml(indent=8) }}
從json字符串讀取,其結果為json類型
{{ some_variable | from_json }}
從yaml字符串讀取,其結果為yaml類型
{{ some_variable | from_yaml }}
常用示例:
tasks:
- shell: cat /some/path/to/file.json
register: result
- set_fact: myvar="{{ result.stdout | from_json }}"
強制定義變量
如果變量未定義,則來自ansible和ansible.cfg的默認行為為失敗,但您可以將其關閉。
{{ variable | mandatory }}
使用未定義的變量
{{ result.cmd|default(5) }}
result.cmd 如果沒由定義的話,則其默認值為5
省略參數
- name: touch files with an optional mode
file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}}
with_items:
- path: /tmp/foo
- path: /tmp/bar
- path: /tmp/baz
mode: "0444"
對于列表中的前兩個文件,默認mode將由系統的umask確定,因為mode=parameter 不會發送到文件模塊,而最后得文件將接收mode=0444選項。
列表過濾
取最小的值
{{ list1 | min }}
取最大的值
{{ [3, 4, 2] | max }}
數據集過濾
對列表唯一過濾
{{ list1 | unique }}
對兩個列表去重合并
{{ list1 | union(list2) }}
對兩個列表做交集
{{ list1 | intersect(list2) }}
找到兩個列表差異部分(在list1 不在list2 的差異)
{{ list1 | difference(list2) }}
找到兩個列表都互相不在對方列表的部分
{{ list1 | symmetric_difference(list2) }}
隨機數過濾
從列表中隨機獲取元素
{{ ['a','b','c','d','e','f']|random }}
從0-59 的整數中隨機獲取一個數
{{ 59 |random}}
從0-100 中隨機獲取能被10 整除的數(可以理解為0 10 20 30 40 50 ...100 的隨機數)
{{ 100 |random(step=10) }}
從0-100 中隨機獲取1 開始步長為10 的數(可以理解為1 11 21 31 41...91 的隨機數)
{{ 100 |random(1, 10) }}
{{ 100 |random(start=1, step=10) }}
合并散列
{{ {'a':1, 'b':2}|combine({'b':3}) }}
結果
{'a':1, 'b':3}
支持遞歸合并
{{ {'a':{'foo':1, 'bar':2}, 'b':2}|combine({'a':{'bar':3, 'baz':4}}, recursive=True) }}
結果
{'a':{'foo':1, 'bar':3, 'baz':4}, 'b':2}
提取過濾器
{{ groups['x']|map('extract', hostvars, 'ec2_ip_address')|list }}
這需要組“x”中的主機列表,在hostvars中查找它們,然后查找結果中的ec2_ip_address。 最終結果是組“x”中的主機的IP地址列表。
注釋過濾器
{{ "Plain style (default)" | comment }}
輸出
#
# Plain style (default)
#
輸出各種語言的注釋風格
{{ "C style" | comment('c') }}
{{ "C block style" | comment('cblock') }}
{{ "Erlang style" | comment('erlang') }}
{{ "XML style" | comment('xml') }}
還可以自定義
{{ "Custom style" | comment('plain', prefix='#######\n#', postfix='#\n#######\n ###\n #') }}
正則匹配
when: ansible_os_family | match("Red[Hh]at" )
when: url | search("/users/.*/resources/.*")
** 其他的常用過濾**
為shell增加雙引號
- shell: echo {{ string_value | quote }}
根據True,False來返回值
{{ ('name' == 'John') | ternary('Mr','Ms') }}
列表轉換字符
{{ list | join(" ") }}
獲取路徑的文件名
{{ path | basename }}
windows平臺下獲取路徑的文件名
{{ path | win_basename }}
獲取路徑中的目錄
{{ path | dirname }}
獲取軟連接的真實路徑
{{ path | realpath }}
獲取文件名的名稱和擴展名
{{ path | splitext }}
base64編碼
{{ encoded | b64decode }}
{{ decoded | b64encode }}
從字符串創建UUID(1.9版中的新功能)
{{ hostname | to_uuid }}
將轉換為布爾類型,如"True" 字符串轉換為True
- debug: msg=test
when: some_string_value | bool
查看變量的python類型
{{ myvar | type }}
隨機列表過濾
給已存在的列表隨機排序
{{ ['a','b','c']|shuffle }} => ['c','a','b']
{{ ['a','b','c']|shuffle }} => ['b','c','a']
數學
獲取對數
{{ myvar | log }}
{{ myvar | log(10) }}
獲取n次冪
{{ myvar | pow(2) }}
{{ myvar | pow(5) }}
獲取平方根
{{ myvar | root }}
{{ myvar | root(5) }}
ip地址過濾
字符串轉ip地址
{{ myvar | ipaddr }}
字符串轉ip協議地址
{{ myvar | ipv4 }}
{{ myvar | ipv6 }}
從cidr中獲取地址信息
{{ '192.0.2.1/24' | ipaddr('address') }}
哈希過濾器
獲取字符串得hash值
{{ 'test1'|hash('sha1') }}
{{ 'test1'|hash('md5') }}
獲取字符串校驗和
{{ 'test2'|checksum }}
獲取sha512密碼哈希
{{ 'passwordsaresecret'|password_hash('sha512') }}
{{ 'secretpassword'|password_hash('sha256', 'mysecretsalt') }}
playbook中的測試
除了過濾器,所謂的“測試”也是可用的。測試可以用于對照普通表達式測試一個變量。 要測試一個變量或表達式,你要在變量后加上一個 is 以及測試的名稱。例如,要得出 一個值是否定義過,你可以用 name is defined ,這會根據 name 是否定義返回 true 或 false 。
測試也可以接受參數。如果測試只接受一個參數,你可以省去括號來分組它們。例如, 下面的兩個表達式做同樣的事情:
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
測試字符串
vars:
url: "http://example.com/users/foo/resources/bar"
tasks:
- shell: "msg='matched pattern 1'"
when: url | match("http://example.com/users/.*/resources/.*")
- debug: "msg='matched pattern 2'"
when: url | search("/users/.*/resources/.*")
- debug: "msg='matched pattern 3'"
when: url | search("/users/")
'match'需要在字符串中完全匹配,而'search'只需要匹配字符串的子集。匹配成功返回True,任務則執行。
版本比較
檢查ansible_distribution_version版本是否大于或等于'12 .04',條件成立返回True。
{{ ansible_distribution_version | version_compare('12.04', '>=') }}
進行嚴格的版本檢查
{{ sample_version_var | version_compare('1.0', operator='lt', strict=True) }}
可接受的運算符
<, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
包含測試
測試一個列表是否包含另一個列表。
vars:
a: [1,2,3,4,5]
b: [2,3]
tasks:
- debug: msg="A includes B"
when: a|issuperset(b)
- debug: msg="B is included in A"
when: b|issubset(a)
路徑測試
- debug: msg="path is a directory"
when: mypath|is_dir
- debug: msg="path is a file"
when: mypath|is_file
- debug: msg="path is a symlink"
when: mypath|is_link
- debug: msg="path already exists"
when: mypath|exists
- debug: msg="path is {{ (mypath|is_abs)|ternary('absolute','relative')}}"
- debug: msg="path is the same file as path2"
when: mypath|samefile(path2)
- debug: msg="path is a mount"
when: mypath|ismount
任務測試
以下playbook是檢查任務狀態的測試。
tasks:
- shell: /usr/bin/foo
register: result
ignore_errors: True
- debug: msg="it failed"
when: result|failed
- debug: msg="it changed"
when: result|changed
- debug: msg="it succeeded in Ansible >= 2.1"
when: result|succeeded
- debug: msg="it succeeded"
when: result|success
- debug: msg="it was skipped"
when: result|skipped
用于 jinja2 模版中的一些語法
變量
變量可以通過 過濾器 修改。過濾器與變量用管道符號( | )分割,并且也 可以用圓括號傳遞可選參數。多個過濾器可以鏈式調用,前一個過濾器的輸出會被作為 后一個過濾器的輸入。
下面2種方式效果是一樣的
{{ foo.bar }}
{{ foo['bar'] }}
如果變量或屬性不存在,會返回一個未定義值。
** 注釋**
要把模板中一行的部分注釋掉,默認使用 {# ... #} 注釋語法。
轉義
簡單的使用單引號進行轉義
對于較大的段落,使用raw進行轉義
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
包含 > 、 < 、 & 或 " 字符的變量,必須要手動轉義
{{ user.username|e }}
控制結構
控制結構指的是所有的那些可以控制程序流的東西 —— 條件(比如 if/elif/ekse )、 for 循環、以及宏和塊之類的東西。控制結構在默認語法中以 {% .. %} 塊的形式 出現。
For
遍歷序列
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
迭代字典
{% for key, value in my_dict.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>
{% endfor %}
循環 10 次迭代之后會終止處理
{% for user in users %}
{%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}
{% for user in users if loop.index <= 10 %}
{{ loop.index }}
{%- endfor %}
注:使用break
, 需要開啟輪詢控制. 具體是在ansible.cfg
的jinja2_extensions
變量加上jinja2.ext.loopcontrols
.
在一個 for 循環塊中你可以訪問這些特殊的變量:
變量 | 描述 |
---|---|
loop.index | 當前循環迭代的次數(從 1 開始) |
loop.index0 | 當前循環迭代的次數(從 0 開始) |
loop.revindex | 到循環結束需要迭代的次數(從 1 開始) |
loop.revindex0 | 到循環結束需要迭代的次數(從 0 開始) |
loop.first | 如果是第一次迭代,為 True 。 |
loop.last | 如果是最后一次迭代,為 True 。 |
loop.length | 序列中的項目數。 |
loop.cycle | 在一串序列間期取值的輔助函數。見下面的解釋。 |
if 語句
Jinja 中的 if 語句可比 Python 中的 if 語句。
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
** 過濾器**
過濾器段允許你在一塊模板數據上應用常規 Jinja2 過濾器。只需要把代碼用 filter 節包裹起來:
{% filter upper %}
This text becomes uppercase
{% endfilter %}
賦值
在代碼塊中,你也可以為變量賦值。在頂層的(塊、宏、循環之外)賦值是可導出的,即 可以從別的模板中導入。
賦值使用 set 標簽,并且可以為多個變量賦值:
{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}
** 表達式**
{% ... %}
用于執行諸如 for 循環 或賦值的語句
{{ ... }}
把表達式的結果打印到模板上
if 表達式
一般的語法是
<do something> if <something is true> else <do something else>
例如:
{{ '[%s]' % page.title if page.title is defined else 'undefined' }}
字面量
表達式最簡單的形式就是字面量。字面量表示諸如字符串和數值的 Python 對象。下面 的字面量是可用的:
字面量 | 說明 |
---|---|
"Hello World" | 雙引號或單引號中間的一切都是字符串。無論何時你需要在模板中使用一個字 符串(比如函數調用、過濾器或只是包含或繼承一個模板的參數),它們都是 有用的。 |
42/42.23 | 直接寫下數值就可以創建整數和浮點數。如果有小數點,則為浮點數,否則為 整數。記住在 Python 里, 42 和 42.0 是不一樣的。 |
['list','of','objects'] | 一對中括號括起來的東西是一個列表。列表用于存儲和迭代序列化的數據。 |
('tuple','of','values') | 元組與列表類似,只是你不能修改元組。如果元組中只有一個項,你需要以逗號 結尾它。元組通常用于表示兩個或更多元素的項。更多細節見上面的例子。 |
{dict':'of','key':'and','value':'pairs'} | Python 中的字典是一種關聯鍵和值的結構。鍵必須是唯一的,并且鍵必須只有一個 值。字典在模板中很少使用,罕用于諸如 xmlattr() 過濾器之類。 |
true/false | true 永遠是 true ,而 false 始終是 false 。 |
特殊常量 true 、 false 和 none 實際上是小寫的。因為這在過去會導致 混淆,過去 True擴展為一個被認為是 false 的未定義的變量。所有的這三個 常量也可以被寫成首字母大寫( True 、 False 和 None )。盡管如此, 為了一致性(所有的 Jinja 標識符是小寫的),你應該使用小寫的版本。
算術
Jinja 允許你用計算值。這在模板中很少用到,但是為了完整性允許其存在。支持下面的 運算符:
運算符 | 說明 |
---|---|
+ | 把兩個對象加到一起。通常對象是素質,但是如果兩者是字符串或列表,你可以用這 種方式來銜接它們。無論如何這不是首選的連接字符串的方式!連接字符串見 ~ 運算符。 {{ 1 + 1 }} 等于 2 。 |
- | 用第一個數減去第二個數。 {{ 3 - 2 }} 等于 1 。 |
/ | 對兩個數做除法。返回值會是一個浮點數。 {{ 1 / 2 }} 等于 {{ 0.5 }} 。 |
// | 對兩個數做除法,返回整數商。 {{ 20 // 7 }} 等于 2 。 |
% | 計算整數除法的余數。 {{ 11 % 7 }} 等于 4 。 |
* | 用右邊的數乘左邊的操作數。 {{ 2 * 2 }} 會返回 4 。也可以用于重 復一個字符串多次。 {{ ‘=’ * 80 }} 會打印 80 個等號的橫條。 |
** | 取左操作數的右操作數次冪。 {{ 2**3 }} 會返回 8 。 |
比較
比較符 | 說明 |
---|---|
== | 比較兩個對象是否相等。 |
!= | 比較兩個對象是否不等。 |
> | 如果左邊大于右邊,返回 true 。 |
>= | 如果左邊大于等于右邊,返回 true 。 |
< | 如果左邊小于右邊,返回 true 。 |
<= | 如果左邊小于等于右邊,返回 true 。 |
邏輯
對于 if 語句,在 for 過濾或 if 表達式中,它可以用于聯合多個表達式:
邏輯符 | 說明 |
---|---|
and | 如果左操作數和右操作數同為真,返回 true 。 |
or | 如果左操作數和右操作數有一個為真,返回 true 。 |
not | 對一個表達式取反(見下)。 |
(expr) | 表達式組。 |
is 和 in 運算符同樣支持使用中綴記法: foo is not bar 和 foo not in bar 而不是 not foois bar 和 not foo in bar 。所有的 其它表達式需要前綴記法 not (foo and bar) 。
其它運算符
下面的運算符非常有用,但不適用于其它的兩個分類:
運算符 | 說明 | |
---|---|---|
in | 運行序列/映射包含檢查。如果左操作數包含于右操作數,返回 true 。比如 {{ 1 in[1,2,3] }} 會返回 true 。 | |
is | 運行一個 測試 。 | |
應用一個 過濾器 。 | ||
~ | 把所有的操作數轉換為字符串,并且連接它們。 {{ "Hello " ~ name ~ "!" }} 會返回(假設 name 值為 ''John' ) Hello John! 。 | |
() | 調用一個可調用量:{{ post.render() }} 。在圓括號中,你可以像在 python 中一樣使用位置參數和關鍵字參數: {{ post.render(user, full=true) }} 。 | |
. / [] | 獲取一個對象的屬性。 |
更多文章請看 Ansible 專題文章總覽