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

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.
float(value, default=0.0)
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') }}
Return the last item of a sequence.
Return the number of items of a sequence or mapping.
Convert a value to lowercase.
Return a random item from the sequence.
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.
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, aaargh
round(value, precision=0, method='common')
{{ 42.55|round }}
    -> 43.0
{{ 42.55|round(1, 'floor') }}
    -> 42.5
Note 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 }}
    -> 43
Mark the value as safe which means that in an environment with automatic escaping enabled this variable will not be escaped.
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.
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.
Make a string unicode if it isn’t already. That way a markup string is not converted back to unicode.
Convert a value to uppercase.
Escape strings for use in URLs (uses UTF-8 encoding). It accepts both dictionaries and regular strings as well as pairwise iterables.

下面是实现自定义的jinja2 filter的代码。 里面已经实现了调用ansible的template的时候,有可能会用到的filter过滤器。
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
        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)
        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 '''
    except NameError:
        raise errors.AnsibleFilterError('Mandatory variable not defined.')
        return a
def 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
        return False
def 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
        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 `` 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
        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
        Version = LooseVersion
    if operator in op_map:
        operator = op_map[operator]
        raise errors.AnsibleFilterError('Invalid operator type')
        method = getattr(py_operator, operator)
        return method(Version(str(value)), Version(str(version)))
    except Exception, e:
        raise errors.AnsibleFilterError('Version comparison: %s' % e)
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 only be used with integer values')
        return r.choice(end)
        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模板渲染数据的时候,就更加的方便了 !!!

大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!


电子邮件地址不会被公开。 必填项已用*标注