Ansible Tools Filter_plugins Plug-in How to implement JINJA2 custom filter filter

Source: Internet
Author: User
Tags base64 glob iterable json md5 rand readable ansible template

Objective:

What is Filter_plugins?  This word is broken down, filter! The person familiar with the jinja2 template, to know that he is a filter, can use Pyhton code to process strings in a template in a pipe way. The ansible template calls the JINJA2, which is known to all. This Filter_plugins plug-in code is designed to better handle strings and logical judgments in the JINJA2 template. Previously, I talked to Shen Zan about a template problem, really egg pain, always do not reach the data we want, at that time is to do a data statistics and RABBITMQ configuration, some places with the jinja2 template of their own syntax, to deal with is really laborious, with a multi-level {% set%} and various length. In fact, at first I wanted to use JINJA2 filter, the result did not see the corresponding document description. Originally also planned, in the tangle under Ansible template code, the JINJA2 filter into, if not successful, their external an API do processing. It seems that the people of ansible to do what they can think of.

These two days and then looked at the document, found that the list of plug-ins have a filter_plugins, and then looked at the following instructions, it is him!


Ansible supports the default built-in filter usage in JINJA2, which is part of the! Each of the specific features I do not say in detail, we will know the use of the test.

The code is as follows Copy Code
ABS (number)


Absolute





attr (obj, name)


Property








{{My_variable|default (' my_variable is not Defined ')}}


If there are no values, you can define the default





{% for item in mydict|dictsort%}


Sort the dict by key, case insensitive





{% for item in Mydict|dictsort (TRUE)%}


Sort the dict by key, case sensitive





{% for item in Mydict|dictsort (False, ' value ')%}


Sort the dict by key, case insensitive, sorted


Normally and ordered by value.


Escape (s)


Secure Code Patterns








A (SEQ)


First one





Float (value, default=0.0)


Floating-point type





Forceescape (value)


Force HTML Escape








Indent (S, width=4, Indentfirst=false)








{{Mytext|indent (2, True)}}








{{[1, 2, 3]|join (' | ')}}


-> 1|2|3





{{[1, 2, 3]|join}}}


-> 123








{{Users|join (', ', attribute= ' username ')}}








Last (SEQ)


Return to the last item of a sequence.





Length (object)


Return the number of items of a sequence or mapping.








Lower (s)


Convert a value to lowercase.











Random (seq)


Return a random item from the sequence.





Reject ()


Filters a sequence of objects by appying a test to the object and rejecting the ones with the test succeeding.





Example usage:





{{Numbers|reject (' odd ')}}


New in version 2.7.





Rejectattr ()


Filters a sequence of objects by appying A of "an" of "an", "an" and "rejecting" with The test succeeding.





{{users|rejectattr (' is_active ')}}


{users|rejectattr ("email", "None")}}


New in version 2.7.





Replace (s, old, new, Count=none)








{{"Hello World" |replace ("Hello", "Goodbye")}}


-> Goodbye World





{{"Aaaaargh" |replace ("a", "D ' Oh,", 2)}}


-> d ' Oh, d ' Oh, Aaargh





Round (value, precision=0, method= ' common ')








{{42.55|round}}}


-> 43.0


{{42.55|round (1, ' Floor ')}}


-> 42.5


Note this even if rounded to 0 precision, the a float is returned. If you are need a real integer, pipe it through int:





{{42.55|round|int}}}


-> 43


Safe (value)


Mark the value as safe which means the environment with automatic escaping enabled this variable won't be escape D.





Select ()


Filters a sequence of objects by appying a test to the object and only selecting the ones with the test succeeding.





Example usage:





{{Numbers|select (' odd ')}}


{{Numbers|select (' odd ')}}


New in version 2.7.





Selectattr ()








Example usage:





{{users|selectattr (' is_active ')}}


{users|selectattr ("email", "None")}}





{% for item in iterable|sort%}


...


{% ENDFOR%}


It is also possible to sort by (for example to sort by the date of object) by specifying the attribute par Ameter:





{% for item in Iterable|sort (attribute= ' date ')%}


...


{% ENDFOR%}


Changed in version 2.6:the attribute parameter is added.





String (object)


Make a string Unicode if it isn ' t already. That way a markup string isn't converted back to Unicode.








Upper (s)


Convert a value to uppercase.





UrlEncode (value)


Escape strings for use in URLs (uses UTF-8 encoding). It accepts both dictionaries and regular strings as as. pairwise iterables.





WordCount (s)


Number


Here is the code that implements the custom JINJA2 filter. Inside has already implemented the call Ansible's template, may use the filter filter.

The code is as follows Copy Code
#xiaorui. cc





Import Base64


Import JSON


Import Os.path


Import Yaml


Import types


Import Pipes


Import Glob


Import re


Import operator as Py_operator


From ansible Import Errors


From ansible.utils import md5s


From distutils.version import looseversion, strictversion


From random import Systemrandom


From jinja2.filters import Environmentfilter





def to_nice_yaml (*a, **kw):


' Make verbose, human readable yaml '


Return Yaml.safe_dump (*a, indent=4, Allow_unicode=true, Default_flow_style=false, **kw)





Def To_json (A, *args, **kw):


"Convert the value to JSON" "


Return Json.dumps (A, *args, **kw)





Def To_nice_json (A, *args, **kw):


' Make verbose, human readable JSON '


Return Json.dumps (A, indent=4, Sort_keys=true, *args, **kw)





Def failed (*a, **kw):


' Test If task result yields failed '


item = a[0]


If Type (item)!= dict:


Raise errors. Ansiblefiltererror ("|failed expects a dictionary")


rc = item.get (' RC ', 0)


Failed = Item.get (' failed ', False)


If RC!= 0 or failed:


Return True


Else


Return False





def success (*a, **kw):


' Test If task result yields success '


Return not failed (*a, **kw)





def changed (*a, **kw):


' Test If task result yields changed '


item = a[0]


If Type (item)!= dict:


Raise errors. Ansiblefiltererror ("|changed expects a dictionary")


If not ' changed ' in item:


Changed = False


if (' Results ' in Item # Some modules return a ' results ' key


and type (item[' results ']) = = List


and type (item[' results '][0]) = = Dict):


For result in item[' results ']:


Changed = changed or Result.get (' changed ', False)


Else


Changed = Item.get (' changed ', False)


Return changed





def skipped (*a, **kw):


' Test If task result yields skipped '


item = a[0]


If Type (item)!= dict:


Raise errors. Ansiblefiltererror ("|skipped expects a dictionary")


skipped = Item.get (' skipped ', False)


Return skipped





def mandatory (a):


' Make a variable mandatory '


Try


A


Except Nameerror:


Raise errors. Ansiblefiltererror (' mandatory variable not defined. ')


Else


Return a





def bool (a):


' Return a bool to the ARG '


If a is None or type (a) = = bool:


Return a


If type (a) in types. Stringtypes:


A = A.lower ()


If a in [' Yes ', ' on ', ' 1 ', ' true ', 1]:


Return True


Else


Return False





DEF quote (a):


"' return it argument quoted for shell usage '"


Return Pipes.quote (a)





def fileglob (pathname):


' Return list of matched files for Glob '


return Glob.glob (pathname)





def regex (value= ', pattern= ', Ignorecase=false, match_type= ' search '):


' Expose ' re ' as a Boolean filter using the ' Search ' method by default.


This is likely only useful for ' search ' and ' match ' which already


have their own filters.


'''


If ignorecase:


Flags = Re. I


Else


Flags = 0


_re = Re.compile (pattern, flags=flags)


_bool = __builtins__.get (' bool ')


Return _bool (GetAttr (_re, Match_type, ' Search ') (value)





Def match (value, pattern= ', ignorecase=false):


' Perform a ' re.match ' returning a Boolean '


return Regex (value, pattern, ignorecase, ' match ')





def search (value, pattern= ', ignorecase=false):


' Perform a ' re.search ' returning a Boolean '


return Regex (value, pattern, ignorecase, ' search ')





def regex_replace (value= ', pattern= ', replacement= ', ignorecase=false):


' Perform a ' re.sub ' returning a string '





If not isinstance (value, basestring):


Value = str (value)





If ignorecase:


Flags = Re. I


Else


Flags = 0


_re = Re.compile (pattern, flags=flags)


Return _re.sub (replacement, value)





def unique (a):


return set (a)





def intersect (A, B):


return set (a). Intersection (b)





def difference (A, B):


return set (a). Difference (b)





Def symmetric_difference (A, B):


return set (a). Symmetric_difference (b)





Def union (A, B):


return set (a). Union (b)





def version_compare (value, version, operator= ' eq ', strict=false):


"' Perform a version comparison on a value '"


Op_map = {


' = = ': ' eq ', ' = ': ' eq ', ' welfare ': ' eq ',


' < ': ' lt ', ' lt ': ' Lt ',


' <= ': ' Le ', ' le ': ' Le ',


' > ': ' GT ', ' GT ': ' GT ',


' >= ': ' ge ', ' ge ': ' ge ',


'!= ': ' ne ', ' <> ': ' ne ', ' ne ': ' ne '


}





If strict:


Version = Strictversion


Else


Version = Looseversion





If operator in Op_map:


operator = Op_map[operator]


Else


Raise errors. Ansiblefiltererror (' Invalid operator type ')





Try


method = GetAttr (Py_operator, operator)


Return method (Version (str (value)), Version (str (version))


Except Exception, E:


Raise errors. Ansiblefiltererror (' Version comparison:%s '% e)





@environmentfilter


def rand (Environment, end, Start=none, Step=none):


R = Systemrandom ()


If Isinstance (end, (int, long)):


If not start:


Start = 0


If not step:


Step = 1


Return R.randrange (Start, end, step)


Elif hasattr (end, ' __iter__ '):


If Start or step:


Raise errors. Ansiblefiltererror (' Start and step can ' is used with integer values ')


return R.choice (end)


Else


Raise errors. Ansiblefiltererror (' Random can is used on sequences and integers ')





Class Filtermodule (object):


"' Ansible core jinja2 filters '"





def filters (self):


return {


# Base 64


' B64decode ': Base64.b64decode,


' B64encode ': Base64.b64encode,





# JSON


' To_json ': To_json,


' To_nice_json ': To_nice_json,


' From_json ': json.loads,





# YAML


' To_yaml ': Yaml.safe_dump,


' To_nice_yaml ': To_nice_yaml,


' From_yaml ': yaml.safe_load,





# path


' basename ': Os.path.basename,


' DirName ': Os.path.dirname,


' Expanduser ': Os.path.expanduser,


' Realpath ': Os.path.realpath,


' RelPath ': Os.path.relpath,





# Failure Testing


' Failed ': failed,


' Success ': Success,





# changed testing


' Changed ': Changed,





# Skip Testing


' Skipped ': Skipped,





# variable existence


' Mandatory ': mandatory,





# Value As Boolean


' BOOL ': bool,





# Quote string for Shell usage


' Quote ': quote,





# MD5 Hex Digest of string


' MD5 ': md5s,





# file Glob


' Fileglob ': Fileglob,





# regex


' Match ': match,


' Search ': Search,


' Regex ': Regex,


' Regex_replace ': regex_replace,





# list


' Unique ': unique,


' intersect ': intersect,


' Difference ': difference,


' Symmetric_difference ': symmetric_difference,


' Union ': union,





# version Comparison


' Version_compare ': Version_compare,





# random Numbers


' Random ': Rand,


}



The code for the template, this is just a test. The variables inside the template are not introduced from the outside, they are the variables I set myself.

  code is as follows copy code
this "Ceshi"
{% Set list1 = [1,2,3,4,5,6,7,8,9,10]%}
 
{% for I in list1%}
    {i }}
{% ENDFOR%}
{{List1|to_nice_yaml}}
 
{% Set list2 = [' K_1 ', ' k_2 ', ' k_3 ']%}
 
To_replace ...
 
{% for I list2%}
    {i|to_replace }}
{% endfor%}




Here is the result, and we can see that the two filters we're doing are successfully executed.



Ansible has a filter_plugins plug-in tool, in the use of JINJA2 template rendering data, it is more convenient!!!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.