using regex in jinja 2 for ansible playbooks

一曲冷凌霜 提交于 2019-11-29 03:46:47
Halberom

Jinja2 can quite easily do substr checks with a simple 'in' comparison, e.g.

{% 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.

+1 for Bereal's answer though, it gives a nice alternative in the form of a map.

There is a "regex_replace" filter available in Ansible>1.6

Other Useful Filters Scroll down and you'll see this:

New in version 1.6.

To replace text in a string with regex, use the “regex_replace” filter:

# 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.

Thanks to Steve E. hint, I've figured out a way to add regex in a template condition:

{% if server | regex_search('thinking') %}
....
{% endif %}
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.

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:

 __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:

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

There are some (currently) undocumented filters in Ansible 2.1 which may do what you need:
Ansible plugins/filter.core.py

The regex_search filter 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:

{% 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.

Review the original pull request for further information

This is rather ugly, but it works as of 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:

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).

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!