HI i am new to jinja2 and trying to use regular expression as shown below
{% if ansible_hostname == \'uat\' %}
{% set server = \'thinkingmonster.com\' %}
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 %}
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.
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 %}
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 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