using regex in jinja 2 for ansible playbooks

后端 未结 7 2052
北海茫月
北海茫月 2020-12-31 06:37

HI i am new to jinja2 and trying to use regular expression as shown below

{% if ansible_hostname == \'uat\' %}
   {% set server = \'thinkingmonster.com\' %}
         


        
相关标签:
7条回答
  • 2020-12-31 06:44

    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.

    0 讨论(0)
  • 2020-12-31 06:44

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

    {% if server | regex_search('thinking') %}
    ....
    {% endif %}
    
    0 讨论(0)
  • 2020-12-31 06:44

    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.

    0 讨论(0)
  • 2020-12-31 06:48

    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 %}
    
    0 讨论(0)
  • 2020-12-31 06:59

    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.

    0 讨论(0)
  • 2020-12-31 07:03

    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

    0 讨论(0)
提交回复
热议问题