Ansible Filter Tips

Ansibleではfilterプラグインが使える。ストリーム処理の変換処理になっていて色々できる。 ドキュメントを写してもしょうもないので頻繁に使うものを少し抜粋して、最後によくある用途を並べておいく。

フィルター紹介

データフォーマット文字列の扱い

JSON,YAML 形式の文字列を生成したり(to_)変数に変換したり(from_)する。

12345
tasks:
- shell: cat /some/path/to/file.json
  register: result
- set_fact: myvar="{{ result.stdout | from_json }}"
- shell: "echo {{ myvar | to_nice_yaml(indent=8) }}"

ref.

変数定義

変数が定義されてない時に通常は Ansible の実行は失敗するが無視する様に ansible.cfg でディアクティベートできる。そんな時でも mandatory で定義されていることを強制したかったりする。 逆に定義されてない場合のデフォルト値を利用したい場合もある。

12
- shell: "echo {{ some_variable | default('default value') }}"
- shell: "echo {{ variable | mandatory }}"

ref.

JSONクエリ

JSON Query を使える。JMESPathに基づくクエリを json_query() に文字列として渡して使える。

12
- shell: "echo {{ item }}"
  with_items: "{{domain_definition|json_query('domain.cluster[*].name')}}"

ref.

IPアドレス

ipaddr,ipv4,ipv6 と形式がマッチしてるかでフィルタリングできる。引数にクエリを書くことで抜き出したり加工したりもできる。

123456
{% set ipv4_host = host_prefix | unique | ipv4('host/prefix') | first %}
iface eth0 inet static
    address   {{ ipv4_host | ipaddr('address') }}
    network   {{ ipv4_host | ipaddr('network') }}
    netmask   {{ ipv4_host | ipaddr('netmask') }}
    broadcast {{ ipv4_host | ipaddr('broadcast') }}

ref.

ファイルパス

ファイルパスを操作するフィルターも充実している。 basename,dirname,realpath,relpath などがある。

フィルター 用途
basename ファイル名を取得する
dirname ディレクトリ名を取得する
realpath リンク先のパスを取得する
relpath 引数に与えたパスからの相対パスを取得する

selectattr

selectattr でオブジェクト配列を細かくフィルタできる。 {{ objects | selectattr('key', 'none') }}のように使える。 第1引数でメンバ名を指定する。第2引数に Jinja2 のテストを指定する。 指定しない場合は第1引数で指定した値を論理値として評価して判断する。

12345
---
fruits:
  - { name: apple, option: true }
  - { name: orange, option: true }
  - { name: banana }
1234567
---
- hosts: all
  tasks:
    - debug:
      msg: "value {{ fruits
      | selectattr('option', 'defined')
      | map(attribute='name') }}"

ref.

map

配列の各要素の attribute の抽出やフィルターの適用を行える。フィルターが引数を取る場合は map の第2引数以降に指定する。

1234567
---
- hosts: all
  tasks:
    - debug:
      msg: "{{ fruits
      | map(attribute='name')
      | map('upper') }}"

ref.

文字列処理

regex_replace を使って文字列を変換するのは色々できて便利だった。 (?P<name>) で名前付きキャプチャも利用できる。

urlsplit フィルタを使うと URL の識別子を切り出せる。

12
- debug: # domain: host.name
    msg: "domain: {{ 'https://host.name/path/to?q=paper' | urlsplit('hostname') }}"

ref.

実例

filegrobを利用したbasenameの取得

キックスクリプトを Ansible で生成している。アプリケーションの範囲だからGradleで生成してパッケージにまとめた方が良い気がするけど、まだ Java 力がなくて見送っている。

12
java -cp {{ lookup('fileglob', 'preprocessor/lib/*.jar').split(",") | map('basename') | map('regex_replace', '(.*)', '$PROJ_ROOT/lib/\\1') | join(':') }} \
         {{ main_class }}

ref.

comments powered by Disqus