Python 在 jinja 2 中使用正则表达式作为 ansible playbooks
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30413616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using regex in jinja 2 for ansible playbooks
提问by thinkingmonster
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. Please help me.I found some python code and sure that can work but how to use python in jinja2 templates?
但没有发现任何支持这个的 jinja2 过滤器。请帮助我。我找到了一些 python 代码并且确定可以工作,但是如何在 jinja2 模板中使用 python?
采纳答案by thinkingmonster
So after googling for a long time and with the help of some bloggers here is the final solution to my problem:-
因此,经过长时间的谷歌搜索并在一些博主的帮助下,这里是我问题的最终解决方案:-
1.Jinja2 does not have any filter for finding sub-string or regexp, so the only solution was to create a custom filter. I followed the steps below to fix my problem.
1.Jinja2 没有任何用于查找子字符串或正则表达式的过滤器,因此唯一的解决方案是创建自定义过滤器。我按照以下步骤解决了我的问题。
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. The name of the python file can be anything. My python code looks as follows:
2.在我的剧本的根目录中,我创建了一个目录“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.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 %}
回答by bereal
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 pluginto Ansible, so that it will use the function above in templates (like {{server|ssl_cert}}
if you name the filter ssl_cert
).
然后你需要向Ansible添加一个过滤器插件,以便它在模板中使用上面的函数(就像{{server|ssl_cert}}
你命名过滤器一样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.
也就是说,传递给模板并在那里显式使用的普通旧函数或普通旧字典可能更适合这项工作。
回答by Halberom
Jinja2 can quite easily do substr checks with a simple 'in' comparison, e.g.
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 arein 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 answerthough, it gives a nice alternative in the form of a map.
不过,对于Bereal 的回答+1 ,它以地图的形式提供了一个不错的选择。
回答by saranicole
There is a "regex_replace" filter available in Ansible>1.6
Ansible>1.6 中有一个“regex_replace”过滤器可用
Other Useful FiltersScroll 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.
话虽如此,正则表达式对于找到解决这个特定问题的方法来说太过分了。
回答by Steve E.
There are some (currently) undocumented filters in Ansible 2.1 which may do what you need:
Ansible plugins/filter.core.py
Ansible 2.1 中有一些(目前)未记录的过滤器,它们可以满足您的需求:
Ansible plugins/filter.core.py
The regex_searchfilter will perform a regex on the string and return the resulting match. Something similar to this would work and be contained within an Ansible role:
该regex_search过滤器将在字符串进行正则表达式,并返回匹配结果。与此类似的内容将起作用并包含在 Ansible 角色中:
{% set server = 'www.thinkingmonster.com' %}
{% if regexp_search(server, 'thinking') %}
do something...
{% endif %}
There is also a regex_findallfilter which performs a Python findall search instead of regex.
还有一个regex_findall过滤器,它执行 Python findall 搜索而不是正则表达式。
回答by Todd Lewis
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 %}
回答by Alexander Svetkin
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 %}