search
LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

Ansibleでカスタムフィルタを使ってみる

はじめに

Ansibleではデータの整形や加工、変換をする際Jinja2の提供するフィルタを使うことができます。
しかし、jinja2の提供するbuilt in filters だけでは不十分であったり痒いところに手が届かないということが多々ありました。
その際、カスタムモジュールの作成で対応していたのですが、カスタムフィルタも自作できるということを知ったので色々試してみました。
フィルタについてはAnsible filter公式ドキュメントをご覧ください。

実行環境

$ ansible --version
ansible 2.9.13
python version = 3.8.5 (default, Jul 21 2020, 10:48:26) [Clang 11.0.3 (clang-1103.0.32.62)]

検証

ansible.cfgの設定

カスタムフィルタの配置箇所は個人専用、チーム用、プロジェクト用等、
使用用途によって変えると良いかと思います。

ansible.cfg
filter_plugins = [利用したいカスタムフィルタを配置したフルパス]/filter_plugins

カスタムフィルタ

ansible.cfgで指定したカスタムフィルタのパスにコードを配置。

filter_plugins/my_custom_filters.py
#!/usr/bin/python
from ansible.errors import AnsibleError

class FilterModule(object):
     def filters(self):
         return {
             # [Playbook内でしていするfilter名]: 関数名
             'square': self.square_int
         }

     def square_int(self, number):
         if type(number) is not int:
             raise AnsibleError('{}\'s type is {} not integer'.format(number,type(number)))
         number = number * number
         return number

Playbook

通常のbuiltinfilterと同様の記法で呼び出し。

site.yml
- hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: "{{ 5 | square }}"

実行結果

PLAY [localhost] *******************************************************************************************************************************************************************************************

TASK [debug] ***********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "25"
}

PLAY RECAP *************************************************************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

複数カスタムフィルタを作成したり、フィルタでパラメータを複数指定することもできます。

カスタムフィルタ

filter_plugins/my_custom_filters.py
#!/usr/bin/python
from ansible.errors import AnsibleError

class FilterModule(object):
     def filters(self):
         return {
            # [Playbook内でしていするfilter名]: 関数名
             'square': self.square_int,
             'total' : self.total
         }

     def square_int(self, number):
         if type(number) is not int:
             raise AnsibleError('{}\'s type is {} not integer'.format(number,type(number)))
         number = number * number
         return number

     def total(self, *args):
         total = 0
         for i in args:
             if type(i) is not int:
                 raise AnsibleError('{}\'s type is {} not integer'.format(i,type(i)))
             total = total + i
         return total

Playbook

site.yml
---
- hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: "{{ 5 | square }}"

    - debug:
        msg:
          - "{{ 1 | total(2,3) }}"
          - "{{ 1 | total(2,3,4,5) }}"

実行結果

PLAY [localhost] *******************************************************************************************************************************************************************************************

TASK [debug] ***********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "25"
}

TASK [debug] ***********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "6",
        "15"
    ]
}

PLAY RECAP *************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

最後に

assertモジュールと組み合わせて変数のチェックをしたりset_factモジュールと組み合わせて自在に変数定義したり色々応用がききます。
あまりAnsibleエンジン単体でカスタムフィルタを使う場面はないですが、他のサービスからAnsibleTowerのAPIをコールするときなど外部から変数を受け取る場合はアサーションやコンバージョンの機能が必要になる場面は多い印象です。
公式ドキュメントを読んでいるとまだまだ使いこなせていない機能がたくさんあるのでどんどん使っていきたいです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2