在jinja 2中使用regex作为ansible playbooks

时间:2015-05-23 14:05:09

标签: python regex jinja2 ansible ansible-playbook

我是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 %}

基于“服务器”的值,我想评估使用哪些证书。 即如果域包含“思考”关键字,则使用这些证书,如果它包含“sleeping”关键字,则使用该证书。

但是没有找到任何支持这个的jinja2过滤器。 请帮帮我。我找到了一些python代码,确定可以工作,但如何在jinja2模板中使用python?

7 个答案:

答案 0 :(得分:12)

Jinja2可以很容易地用简单的' in'进行子检查。比较,例如。

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

因此,您的子字符串正则表达式过滤器并不是必需的。但是,如果你想要更高级的正则表达式匹配,那么 实际上是在ansible中可用的过滤器 - 请参阅http://docs.ansible.com/playbooks_filters.html#other-useful-filters中的正则表达式过滤器 - 有趣的是,上面的匹配语法几乎完全正确。< / p>

Bereal's answer +1,它以地图的形式提供了一个不错的选择。

答案 1 :(得分:5)

Ansible&gt; 1.6

中有一个“regex_replace”过滤器

Other Useful Filters 向下滚动,你会看到:

  

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>') }}

话虽这么说,正则表达式对于找到这个特定问题的解决方案是过度的。

答案 2 :(得分:4)

所以经过谷歌搜索很长一段时间后,在一些博主的帮助下,这是我问题的最终解决方案: -

1。 Jinja2没有任何用于查找子字符串或正则表达式的过滤器,因此唯一的解决方案是创建自定义过滤器。我按照以下步骤解决了我的问题。

2。在我的Playbook的根目录中,我创建了一个目录 &#34; filter_plugins&#34; 并写了一个自定义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。创建此文件后,我们全新的过滤器 &#34; substr&#34; 已准备就绪,可以使用在模板中使用,如下所示:

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

答案 3 :(得分:4)

感谢Steve E.提示,我已经想出了一种在模板条件下添加正则表达式的方法:

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

答案 4 :(得分:2)

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 过滤器,它执行Python findall搜索而不是正则表达式。

Review the original pull request for further information

答案 5 :(得分:2)

这是相当丑陋的,但它的工作原理是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 %}

答案 6 :(得分:1)

据我所知,在Ansja的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)。

也就是说,传递给模板并在那里明确使用的普通旧函数或普通旧字典可能更适合这项工作。