Ansible の vars 参照で使える小ネタ
もう 11 月も半ばですが 10 月分のブログとして書きます。怠惰w
特にネタがないので以前も書きましたが Ansible の小ネタ投稿にします。
今回は変数参照について。 Ansible というか Jinja2 の内容も混じってます、思いつくけどどう表現していいかわからないような検索しづらい系の小ネタ集めました。
動作検証したコードの方を見たい場合はこちらのリポジトリをどうぞ。
hash 内の値の参照
意外と簡単です。
yaml:
vars: foo: foo example_hash: foo: foo bar: bar ... tasks: - block: - debug: msg: "example_hash['foo'] is {{ example_hash['foo'] }}" - debug: msg: "example_hash[foo] is {{ example_hash[foo] }}"
出力:
"msg": "example_hash['foo'] is foo" "msg": "example_hash[foo] is foo"
上記のように key の部分が変数名でも問題ないですね。
環境変数の参照
例えば vars_prompt で入力値を参照する場合で、かつ、デフォルト値は環境変数の値にしたい場合は以下のような感じです。
yaml:
vars_prompt: - name: env_baz prompt: Please enter baz value default: "{{ lookup('env', 'BAZ') }}" private: no ... tasks: - block: - debug: msg: "env_baz is {{ env_baz }}"
出力1(環境変数あり実行 BAZ=baz
):
Please enter env_baz value [baz]: ... "msg": "env_baz is baz"
出力2(環境変数なし実行):
Please enter env_baz value []: mybaz ... "msg": "env_baz is mybaz"
コマンドラインオプションで vars と vars_prompt の上書き
vars も vars_prompt も -e
で上書きできるので
- 基本的に入力してもらいたいものは vars_prompt に
- 毎回入力してもらうほどじゃないけど一応上書き可能にしておきたいものは vars に
書くようにしましょう。
yaml:
vars: baz: baz ... vars_prompt: - name: baz_prompt prompt: Please enter baz_prompt value default: "default_baz" private: no ... tasks: - block: - debug: msg: "baz is {{ baz }}, baz_prompt is {{ baz_prompt }}"
出力1(実行オプションなし):
Please enter baz_prompt value [default_baz]: mybaz ... "msg": "baz is baz, baz_prompt is mybaz"
出力2(実行オプションあり -e "baz=mybaz" -e "baz_prompt=mybaz"
)
(promptも聞かれない) ... "msg": "baz is mybaz, baz_prompt is mybaz"
リストの特定の値の除外
filter で簡単にできます。
yaml:
vars: example_list: - rejected - one - two ... tasks: - block: - debug: msg: "filtered example_list is including {{ item }}" with_items: "{{ example_list | reject('search', 'rejected') | list }}"
出力:
"msg": "filtered example_list is including one" "msg": "filtered example_list is including two"
ポイントは | list
で generator object
から元のリスト形式に戻してあげることでしょうか。
リスト内に特定の値を持つ hash があるかどうかの判定
yaml:
vars: example_hash_list: - key: key_a value: aaa - key: key_b value: bbb - key: key_c value: ccc ... tasks: - block: - debug: msg: "example_hash_list is including key_c hash" when: example_hash_list | selectattr("key", "equalto", "key_c") | list | length > 0 - debug: msg: "example_hash_list is NOT including key_d hash" when: example_hash_list | selectattr("key", "equalto", "key_d") | list | length == 0
出力:
"msg": "example_hash_list is including key_c hash" "msg": "example_hash_list is NOT including key_d hash"
複数ホストの fact を一つの fact にまとめる
例として、複数のホストの中で最新のログを取得したい場合の playbook を紹介します。 alpine の docker image だと find コマンドで -printf
使えなかったので特に考えず(怠惰w) stretch 使いました。ちなみに hosts.ini などで ansible_python_interpreter
指定しないと動かないので python のパスに気をつけましょう。
yaml:
ansible-sandbox/playbook.example-container.yml at v0.0.1 · innossh/ansible-sandbox · GitHub
出力( /var/log/foo
にログがないのでサンプル実行として -e "log_dir=/tmp"
):
PLAY [containers] ********************************************************************************************************************************* TASK [find logs] ********************************************************************************************************************************** ok: [ansible-sandbox_echo1_1] ok: [ansible-sandbox_echo2_1] ... TASK [output the latest log] ********************************************************************************************************************** ok: [ansible-sandbox_echo1_1 -> localhost] => { "msg": { "host": "ansible-sandbox_echo1_1", "path": "/tmp/ansible_command_payload_4jqmi0in", "time": "Sun Nov 11 09:29:36 2018", "unix_time": 1541928576.260902 } } PLAY RECAP **************************************************************************************************************************************** ansible-sandbox_echo1_1 : ok=6 changed=0 unreachable=0 failed=0 ansible-sandbox_echo2_1 : ok=2 changed=0 unreachable=0 failed=0
ポイントは以下で
- block: - name: gather latest_log_jsons facts set_fact: latest_log_jsons: "{{ latest_log_jsons | default([]) + hostvars[item].latest_log_jsons_per_host }}" with_items: "{{ play_hosts }}" ... delegate_to: localhost run_once: True
delegate_to: localhost
run_once: True
でset_fact
タスクをローカルで一度だけ実行とするwith_items: "{{ play_hosts }}"
で対象のホスト分のループを回すhostvars[item].latest_log_jsons_per_host
の各ホストの値をlatest_log_jsons
に集約する- あとは
latest_log_jsons
リスト内の最新のログを取り出すだけ
のようにして複数ホストをまたいだ最新のログを取得しています。
以上、小ネタでした。また溜まったらネタがないときに書こう。