博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ansible filter_plugins插件实现jinja2自定义filter过滤器
阅读量:7113 次
发布时间:2019-06-28

本文共 10777 字,大约阅读时间需要 35 分钟。

前言:

   filter_plugins是什么? 这个单词拆解下,filter !  熟悉jinja2模板的人,到知道他是过滤器,可以在模板中以管道的方式用pyhton的代码处理字符串。 ansible模板调用的是jinja2,这个大家都知道 。 这个filter_plugins插件代码,就是为了更好的处理jinja2模板中的字符串和逻辑判断的。 先前,我和沈灿讨论一个模板的问题,实在蛋疼的要命,总是达不到我们要的数据,当时是做一个数据的统计和rabbitmq的配置,有些地方用jinja2模板自身的语法,处理起来实在是费劲, 用了多级{% set %}和各种length 。 其实一开始我就想用jinja2的filter,结果没看到相应的文档说明。 原来还计划着,在纠结下ansible template的代码,把jinja2的过滤器搞进去,要是不成功,自己外置一个api做处理。 看来,ansible那帮人,把能想到的东西都给做了。

    这两天又看了下文档,发现讲插件的list里面有个filter_plugins,然后看了下说明,果然是他 ! 

更多的有关ansible的文章,请移步到 

ansible支持jinja2中默认的内置过滤器用法的,这些是一部分 ! 具体的每个功能我就不详细说了,大家自己测测就知道用途了。

abs(number)绝对值attr(obj, name)属性{
{ my_variable|default('my_variable is not defined') }}如果没有值,可以定义默认的{% 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)安全的代码模式first(seq)第一个float(value, default=0.0)浮点型forceescape(value)强制html转义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 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 test to an attribute of an object or the attribute and rejecting the ones 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, aaarghround(value, precision=0, method='common'){
{ 42.55|round }}    -> 43.0{
{ 42.55|round(1, 'floor') }}    -> 42.5Note that even if rounded to 0 precision, a float is returned. If you need a real integer, pipe it through int:{
{ 42.55|round|int }}    -> 43safe(value)Mark the value as safe which means that in an environment with automatic escaping enabled this variable will not be escaped.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 an attribute (for example to sort by the date of an object) by specifying the attribute parameter:{% for item in iterable|sort(attribute='date') %}    ...{% endfor %}Changed in version 2.6: The attribute parameter was added.string(object)Make a string unicode if it isn’t already. That way a markup string is not 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 well as pairwise iterables.wordcount(s)个数

下面是实现自定义的jinja2 filter的代码。 里面已经实现了调用ansible的template的时候,有可能会用到的filter过滤器。

原文:  

#xiaorui.ccimport base64import jsonimport os.pathimport yamlimport typesimport pipesimport globimport reimport operator as py_operatorfrom ansible import errorsfrom ansible.utils import md5sfrom distutils.version import LooseVersion, StrictVersionfrom random import SystemRandomfrom jinja2.filters import environmentfilterdef 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 Falsedef 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 changeddef 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 skippeddef mandatory(a):    ''' Make a variable mandatory '''    try:        a    except NameError:        raise errors.AnsibleFilterError('Mandatory variable not defined.')    else:        return adef bool(a):    ''' return a bool for 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 Falsedef quote(a):    ''' return its 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', 'eq': '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)@environmentfilterdef 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 only be used with integer values')        return r.choice(end)    else:        raise errors.AnsibleFilterError('random can only be 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,        }

模板的代码,这里只是做个测试而已。模板里面的变量不是从外面引入的,是我自己设的变量。

原文:  

this is 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 in list2 %}    {
{ i|to_replace  }}{% endfor %}

这里是结果,可以看到咱们搞的那两个过滤器成功执行了。 

原文:  

ansible有个filter_plugins插件利器,在使用jinja2模板渲染数据的时候,就更加的方便了 !!!

转载地址:http://swghl.baihongyu.com/

你可能感兴趣的文章
79. Word Search
查看>>
【Android】RxJava的使用(四)线程控制 —— Scheduler
查看>>
极限编程 (Extreme Programming) - 迭代计划 (Iterative Planning)
查看>>
小程序外卖购物车 直接就能用~
查看>>
Python版设计模式之监听者模式
查看>>
[Spring Security 5.2.0 翻译] 8 Architecture and Implementation
查看>>
使用 Sphinx 撰写技术文档并生成 PDF 总结
查看>>
Fastjson的基本使用方法大全
查看>>
SSH 超时设置
查看>>
React-setState杂记
查看>>
Dojo 如何测试 widget
查看>>
GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
查看>>
GoLand中的指针操作 * 和 &
查看>>
116. Populating Next Right Pointers in Each Node
查看>>
webpack 最简打包结果分析
查看>>
NLPIR:数据挖掘深度决定大数据应用价值
查看>>
laravel接入Consul
查看>>
Flex 布局教程
查看>>
GET和POST两种基本请求方法的区别
查看>>
Webpack4 学习笔记 - 01:webpack的安装和简单配置
查看>>