web-dev-qa-db-ja.com

Ansible Playbookにjinja 2で正規表現を使用する

こんにちは、私は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 %}

「サーバー」の値に基づいて、使用する証明書として評価したいと思います。つまり、ドメインに「思考」キーワードが含まれている場合はこれらの証明書を使用し、「スリープ」キーワードが含まれている場合はその証明書を使用します。

しかし、これをサポートするjinja2フィルターは見つかりませんでした。私を助けてください。私はいくつかのpythonコードを見つけ、それが動作することを確認しますが、jinja2テンプレートでpythonを使用するには?

13
thinkingmonster

だから長い間グーグルで、いくつかのブロガーの助けを借りて、ここに私の問題の最終的な解決策があります-

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

2。プレイブックのルートディレクトリ内にディレクトリを作成しました "filter_plugins" pythonでカスタムモジュールを作成し、このディレクトリ内にファイルを配置しました。pythonファイルの名前は何でも構いません。Mypythonコードは次のようになります。

 __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

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

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

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

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

したがって、部分文字列正規表現フィルターは必要ありません。ただし、より高度な正規表現の一致が必要な場合は、実際にはansibleで利用可能なフィルターareがあります- http://の正規表現フィルターを参照してくださいdocs.ansible.com/playbooks_filters.html#other-useful-filters -おもしろいことに、上記のマッチ構文はほぼ正確です。

Bereal's answer の場合は+1ですが、マップの形式でニースの代替を提供します。

13
Halberom

Ansible> 1.6で利用可能な「regex_replace」フィルターがあります。

その他の便利なフィルター 下にスクロールすると、これが表示されます。

バージョン1.6の新機能。

文字列内のテキストを正規表現で置き換えるには、「regex_replace」フィルターを使用します。

# convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}

# convert "foobar" to "bar"
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}

# convert "localhost:80" to "localhost, 80" using named groups
{{ 'localhost:80' | regex_replace('^(?P<Host>.+):(?P<port>\\d+)$', '\\g<Host>, \\g<port>') }}

そうは言っても、正規表現はこの特定の問題の解決策を見つけるには過剰です。

5
saranicole

Steve E.ヒントのおかげで、テンプレート条件に正規表現を追加する方法を見つけました。

{% if server | regex_search('thinking') %}
....
{% endif %}
4

Ansible 2.1には(現在)文書化されていないフィルターがいくつかあり、必要なことを実行できます。
Ansible plugins/filter.core.py

regex_searchフィルターは、文字列に対して正規表現を実行し、一致した結果を返します。これに似たものが機能し、Ansibleロールに含まれます。

{% set server = 'www.thinkingmonster.com' %}
{% if regexp_search(server, 'thinking') %}
   do something...
{% endif %}

regex_findallフィルターもあります。これは、regexの代わりにPython findall検索を実行します。

詳細については、元のプルリクエストを確認してください

2
Steve E.

これはかなりいですが、1.6の時点で動作します。

{% if server|regex_replace('.*thinking.*','matched') == 'matched' %}
  {% set ssl_certificate = 'akash' %}

{% Elif server|regex_replace('.*sleeping.*','matched') == 'matched' %}
   {% set ssl_certificate = 'akashthakur' %}
{% endif %}
2
Todd Lewis

私の知る限り、Ansibleの extra filters にもJinja2には組み込みのフィルターはありませんが、独自のフィルターを作成することは大したことではありません。

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 を追加する必要があります。これにより、テンプレートで上記の関数({{server|ssl_cert}}フィルタに名前を付ける場合ssl_cert)。

そうは言っても、テンプレートに渡されてそこで明示的に使用される単純な古い関数または単純な古い辞書は、この仕事により適しているかもしれません。

1
bereal