__________________
< template について書くよ >
------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Ansible というかほぼ Jinja2 なのだけれども、ちょいちょいググってしまうものをまとめてみます(これをまとめるまで知らなかったものもあります、たまにはドキュメントを見直すのが良いです)。
template module だけでなく task 定義で使う YAML 内でも使われています。
(Qiita の syntax highlight は Jinja にも対応しているのですね)
Ansible Managed
まずはこれ、つい使いたくなるけど罠があるので私は使わない。(Subversion の $Id$
は便利なのに)
http://docs.ansible.com/ansible/intro_configuration.html#ansible-managed
テンプレートファイルに
{{ ansible_managed }}
と書いておけば実行時に ansible.cfg などで設定したフォーマットにしたがって置換してくれます。いつ誰が更新したかとかを入れられます。
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
が、この機能は曲者で、ファイルに変更があったかどうかを比べるのにこの行まで含んでしまうから timestamp なんかを入れてしまった日には本来何も変更してないはずなのにファイルが入れ替えられてしまい。毎回 notify handler が発動してしまうという悲劇を産みます。気をつけましょう。
default
ansible のいつしかの version からデフォルトでは未定義の変数を参照するとエラーで終了してしまいますが、指定しない場合のデフォルト値を指定しておけば大丈夫ということで、特に何も指定がなければこの値ですよというのを指定します。
role
の default/main.yml
を使うという手もありますが、参照すべきファイルが増えるのは嬉しくないので単純な値ならこれで。
{{ some_variable | default('foo bar') }}
task の中で便利に使えるのが 1.8 で登場した default(ommit) ですね(と言ってもこれ書いてて知った)。
http://docs.ansible.com/ansible/playbooks_filters.html#omitting-undefined-variables-and-parameters に例がありますが、ファイルのパーミッションやオーナーなど、with_items でループ処理したい時、殆どは指定が不要なのにひとつだけ指定したいといった場合、それまでは全部の item に値をもたせるか、default でデフォルト値を設定する必要がありましたが、ommit
を使えば未定義の場合はその項目の指定自体がないことにできます。便利(実は今知った...)
リスト操作
min, max
http://docs.ansible.com/ansible/playbooks_filters.html#list-filters
リストの中の最小値、最大値を取り出してくれます
unique, union,...
http://docs.ansible.com/ansible/playbooks_filters.html#set-theory-filters
2つのリストの和とか差とか
random
http://docs.ansible.com/ansible/playbooks_filters.html#random-number-filter
リストの中からランダムに選択されます。 数字内のランダムな値、ステップ数を指定したランダムな値(100のうち10刻みでのランダムな値)とかを取り出せます。
cron モジュールとセットで、複数台のサーバーで同時に実行されるのを避ける場合に便利そうです。ドキュメントにも cron の例があります。
{{ 60 | random(step=5) }} * * * * /some/command
shuffle
http://docs.ansible.com/ansible/playbooks_filters.html#shuffle-filter
シャッフル
動作確認
- hosts: all
gather_facts: no
vars:
aaa:
- A
- B
- C
bbb:
- A
- B
- C
- X
- Y
- Z
ccc: [1,2,3,4,5]
ddd: [1,1,2,2,3,3,4,4,5,5]
eee: [1,2,3]
fff: [3,4,5]
tasks:
- debug: msg="[aaa] {{ aaa }}"
- debug: msg="[bbb] {{ bbb }}"
- debug: msg="[ccc] {{ ccc }}"
- debug: msg="[ddd] {{ ddd }}"
- debug: msg="[random] {{ aaa | random }}"
- debug: msg="[unique] {{ ddd | unique }}"
- debug: msg="[union1] {{ aaa | union(bbb) }}"
- debug: msg="[union2] {{ aaa | union(ccc) }}"
- debug: msg="[intersect] {{ bbb | intersect(aaa) }}"
- debug: msg="[difference] {{ bbb | difference(aaa) }}"
- debug: msg="[symmetric_difference] {{ eee | symmetric_difference(fff) }}"
- debug: msg="[max] {{ ccc | max}}"
- debug: msg="[min] {{ ccc | min}}"
- debug: msg="[shuffle] {{ bbb | shuffle}}"
を用意して
ansible-playbook -i localhost, test.yml
とすれば動作確認ができます。
計算
http://docs.ansible.com/ansible/playbooks_filters.html#math
べき乗や平方根、対数が使えるようです
その他のフィルター
IPアドレス関連やコメント用、ハッシュ処理などあるので確認してみてください。
http://docs.ansible.com/ansible/playbooks_filters.html
join は使う場面ありますよね
{{ list | join(" ") }}
この join するリストがシンプルなリストならこれで良いのですが
ハッシュ/ディクショナリのリストだった場合にどうするかというと
aaa:
- en: apple
ja: ringo
- en: orange
ja: mikan
- en: grape
ja: budou
という変数があって、en
だけや ja
だけを join したい場合は次のようにします
2つ繋げることもできるんです
{{ aaa | map(attribute='en') | join(',') }}
{{ aaa | map(attribute='ja') | join(',') }}
結果
apple,orange,grape
ringo,mikan,budou
map() については http://jinja.pocoo.org/docs/dev/templates/#map を。
Loop 処理
最後にループ処理です
task での Loop はこちらにいろいろ載ってます、ヘぇ、そんなのもあったんだぁという感じなので読んでみましょう。task
の with_xxx
には沢山の種類があって、when
は with_xxx
のそれぞれの値に対しても使えます。
http://docs.ansible.com/ansible/playbooks_loops.html
テンプレートファイル内での Loop 処理についてはこちら
http://jinja.pocoo.org/docs/dev/templates/
{% for item in items %}
{% if item.key1 == 'AAA' %}
{{ item.key1 }} {{ item.key2 }}
{% elif item.key1 == 'BBB' %}
...
{% else %}
...
{% endif %}
{% endfor %}
が基本でしょうか。if
, elif
, else
, endif
です。(いろんな言語使ってるといつも悩みますね、elif
のところ。あれどれだっけ?と)
Loop のアイテムごとに番号を振りたいと思ったら loop.index
(1から始まる), loop.index0
(0から始まる) という変数が使えます
最初と最後を示す loop.first
, loop.last
という Boolean 変数もあります
{% for item in items %}
{% if loop.first %}Begin{% endif %}
{{ loop.index }}: {{ item }}
{% if loop.last %}End{% endif %}
{% endfor %}
詳細はこちら
http://jinja.pocoo.org/docs/dev/templates/#list-of-control-structures
エスケープ
template ファイル内に {{
とか {%
が含まれる場合は raw
を使います
{% raw %}
...
{% endraw %}
まとめ
とりとめもなく書いてしまいましたが、また思いついたら書くことにします。
まだカレンダーに空きがあるようなので。