jinja 2 で ansible playbooks に regex を使用する。

HI 私はjinja2の初心者で、以下のような正規表現を使おうとしています。

{% if ansible_hostname == 'uat' %}
   {% set server = 'thinkingmonster.com' %}

{% else %}
   {% set server = 'define yourself' %}
{% endif %}

{% if {{ server }} match('*thinking*') %}
  {% set ssl_certificate = 'akash' %}

{% elif {{ server }} match( '*sleeping*')%}
   {% set ssl_certificate = 'akashthakur' %}
{% endif %}

の値に基づいて、どの証明書を使用するかを評価したいと思います。 例えば、もしドメインが "thinking" キーワードを含んでいれば、これらの証明書を使用し、もし "sleeping" キーワードを含んでいれば、その証明書を使用します。

しかし、これをサポートするjinja2フィルターが見つかりませんでした。 Pythonのコードをいくつか見つけ、確かにそれは動作しますが、jinja2テンプレートでPythonを使用するにはどうすればよいですか?

Jinja2 は単純な 'in' 比較で非常に簡単に substr チェックができます。

{% set server = 'www.thinkingmonster.com' %}
{% if 'thinking' in server %}
   do something...
{% endif %}

そのため、部分文字列の正規表現フィルタは必要ありません。 しかし、より高度な正規表現マッチングをしたいのであれば、ansibleで利用できるフィルタがあります。http://docs.ansible.com/playbooks_filters.html#other-useful-filters の regex filters を見てください。面白いことに、上記のマッチ構文はほぼ正確です。

Bereal's answer](https://stackoverflow.com/a/30413899/2947502)には+1, マップという形で素晴らしい代替手段を提供してくれています。

解説 (0)
ソリューション

そこで、長い間ググって、何人かのブロガーの助けを借りて、私の問題に対する最終的な解決策をご紹介します:-)

1. Jinja2には、サブストリングや正規表現を見つけるためのフィルタがないので、唯一の解決策はカスタムフィルタを作成することでした。私は以下のステップに従って、私の問題を解決しました。

2. playbookのルートディレクトリ内に、"filter_plugins"というディレクトリを作り、pythonでカスタムモジュールを書き、そのファイルをこのディレクトリに配置しました。pythonのファイル名は何でもいいです。私のpythonのコードは以下のような感じです。

 __author__ = 'akthakur'
class FilterModule(object):
    ''' Custom filters are loaded by FilterModule objects '''

    def filters(self):
        ''' Filter Module objects return a dict mapping filter names to filter functions. '''
        return {
            'substr': self.substr,
        }

        ''' def substr(self, check,checkin):
        return value1+value2'''
    def substr(self,check,checkin):
         if check in checkin:
            return True
         else:
            return False

3. このファイルが作成されると、新しいフィルタ "substr" が使用できるようになり、以下のようにテンプレート内で使用できるようになります。

{% if 5==5 %}
 {% set server = 'www.thinkingmonster.com' %}
{% endif %}
{% if 'thinking' | substr(server) %}
   {% set ssl_cert = 'abc.crt'%}
{% endif %}
解説 (1)

私の知る限りでは、Jinja2にもAnsibleのextra filtersにもそのための組み込みフィルタはありませんが、自分で作るのはたいしたことではありません。

certs = {'.*thinking.*': 'akash', '.*sleeping.*': 'akashthakur'}
def map_regex(value, mapping=certs):
    for k, v in mapping.items():
        if re.match(k, value):
            return v 

次に、Ansible に filter plugin を追加して、テンプレートで上記の関数を使用するようにします (フィルター名を ssl_cert とすると `{server|ssl_cert}} のようになります)。

とはいえ、テンプレートに渡され、そこで明示的に使用される古い関数や古い辞書は、この仕事にもっとフィットするかもしれません。

解説 (0)