简体   繁体   English

在Jinja 2中使用正则表达式制作有趣的剧本

[英]using regex in jinja 2 for ansible playbooks

HI i am new to jinja2 and trying to use regular expression as shown below 嗨,我是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 %}

based on the value of "server" i would like to evaluate as which certificates to use. 基于“服务器”的值,我想评估要使用的证书。 ie if domain contains "thinking" keyword then use these certificates and if it contains "sleeping" keyword then use that certificate. 即,如果域包含“ thinking”关键字,则使用这些证书,如果它包含“ sleeping”关键字,则使用该证书。

But didn't found any jinja2 filter supporting this. 但是没有找到任何支持它的jinja2过滤器。 Please help me.I found some python code and sure that can work but how to use python in jinja2 templates? 请帮帮我。我找到了一些python代码,确定可以正常工作,但是如何在jinja2模板中使用python?

Jinja2 can quite easily do substr checks with a simple 'in' comparison, eg Jinja2可以很容易地通过简单的“ in”比较进行substr检查,例如

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

So your substring regex filter isn't required. 因此,不需要您的子字符串正则表达式过滤器。 However if you want more advanced regex matching, then there are in fact filters available in ansible - see the regex filters in http://docs.ansible.com/playbooks_filters.html#other-useful-filters - funnily enough, your match syntax above is nearly exactly right. 但是如果你想要更高级的正则表达式匹配,那么实际上过滤器在ansible可用-见正则表达式过滤器http://docs.ansible.com/playbooks_filters.html#other-useful-filters -有趣的是,你的对手语法以上几乎完全正确。

+1 for Bereal's answer though, it gives a nice alternative in the form of a map. +1为Bereal的答案 ,它以地图的形式提供了一个不错的选择。

There is a "regex_replace" filter available in Ansible>1.6 Ansible> 1.6中提供了一个“ regex_replace”过滤器

Other Useful Filters Scroll down and you'll see this: 其他有用的过滤器向下滚动,您会看到以下信息:

New in version 1.6. 1.6版中的新功能。

To replace text in a string with regex, use the “regex_replace” filter: 要用正则表达式替换字符串中的文本,请使用“ 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>') }}

That being said, regex is overkill for finding a solution to this particular problem. 话虽这么说,正则表达式对于找到此特定问题的解决方案是过大的。

So after googling for a long time and with the help of some bloggers here is the final solution to my problem:- 因此,经过长时间的Google搜索并在一些博客作者的帮助下,这里是解决我的问题的最终方法:-

1. Jinja2 does not have any filter for finding sub-string or regexp, so the only solution was to create a custom filter. 1. Jinja2没有任何用于查找子字符串或正则表达式的过滤器,因此唯一的解决方案是创建自定义过滤器。 I followed the steps below to fix my problem. 我按照以下步骤解决了我的问题。

2. Inside the root directory of my playbook, I created a directory "filter_plugins" and wrote a custom module in python and placed the file inside this directory. 2.在我的剧本的根目录中,我创建了一个目录“ filter_plugins”,并使用python编写了一个自定义模块,并将文件放置在该目录中。 The name of the python file can be anything. python文件的名称可以是任何名称。 My python code looks as follows: 我的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. Once this file is created our brand new filter "substr" is ready to use and can be used inside templates as shown below: 3.创建此文件后,即可使用我们全新的过滤器“ substr” ,并且可以在模板内使用它,如下所示:

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

Thanks to Steve E. hint, I've figured out a way to add regex in a template condition: 多亏了Steve E.的提示,我找到了在模板条件中添加正则表达式的方法:

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

There are some (currently) undocumented filters in Ansible 2.1 which may do what you need: Ansible 2.1中有一些(当前)未记录的过滤器可以满足您的需要:
Ansible plugins/filter.core.py Ansible插件/filter.core.py

The regex_search filter will perform a regex on the string and return the resulting match. regex_search过滤器将对字符串执行正则表达式,并返回结果匹配项。 Something similar to this would work and be contained within an Ansible role: 与此类似的事情将起作用并包含在Ansible角色中:

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

There is also a regex_findall filter which performs a Python findall search instead of regex. 还有一个regex_findall过滤器,它执行Python findall搜索而不是regex。

Review the original pull request for further information 查看原始请求请求以获取更多信息

This is rather ugly, but it works as of 1.6. 这相当丑陋,但是从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 %}

To my knowledge, there is no builtin filter for that in Jinja2 neither among Ansible's extra filters , but it's not a big deal to make your own: 据我所知,在Jinja2中没有内置过滤器,在Ansible的额外过滤器中也没有,但是制作自己的没什么大不了的:

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

Then you'll need to add a filter plugin to Ansible, so that it will use the function above in templates (like {{server|ssl_cert}} if you name the filter ssl_cert ). 然后,您需要向Ansible添加过滤器插件 ,以便它将在模板中使用上面的功能(如果命名为ssl_cert则类似于{{server|ssl_cert}} )。

That said, a plain old function or a plain old dictionary that is passed to the templates and used there explicitly might fit this job better. 也就是说,传递给模板并在其中明确使用的普通函数或普通字典可能会更适合此工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM