设为首页 收藏本站
查看: 1032|回复: 0

[经验分享] ansible filter_plugins插件实现jinja2自定义filter过滤器

[复制链接]

尚未签到

发表于 2018-7-30 13:02:24 | 显示全部楼层 |阅读模式
#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 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 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
  
    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)
  

  
@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 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,
  
        }

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-543618-1-1.html 上篇帖子: ansible调用callbacks插件实现结果nosql输出回调 下篇帖子: 运维自动化之ansible playbook安装lnmp环境
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表