ansible filter_plugins插件实现jinja2自定义filter过滤器

简介:

前言:


   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的文章,请移步到 http://xiaorui.cc


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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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, 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
safe(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过滤器。

原文: http://rfyiamcool.blog.51cto.com/1030776/1440686 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#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  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,
         }



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


原文: http://rfyiamcool.blog.51cto.com/1030776/1440686 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
this is ceshi
{%  set  list1 = [1,2,3,4,5,6,7,8,9,10] %}
 
{%  for  in  list1 %}
     {{ i  }}
{% endfor %}
{{ list1|to_nice_yaml }}
 
{%  set  list2 = [ 'k_1' , 'k_2' , 'k_3' ] %}
 
to_replace .....
 
{%  for  in  list2 %}
     {{ i|to_replace  }}
{% endfor %}


wKioL1PL7xnAJwxpAAMl37ayClo826.jpg


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

wKioL1PL7yOyvBxdAAJylh0LJAQ496.jpg

原文: http://rfyiamcool.blog.51cto.com/1030776/1440686 


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





 本文转自 rfyiamcool 51CTO博客,原文链接:http://blog.51cto.com/rfyiamcool/1440686,如需转载请自行联系原作者


相关文章
uniapp自定义过滤器filter.js
uniapp自定义过滤器filter.js
120 0
|
监控 安全 Java
【JavaWeb】 三大组件之过滤器 Filter
过滤器(Filter)是Java Web应用中的一种组件,它在请求到达Servlet或JSP之前或者响应送回客户端之前,对请求和响应进行预处理和后处理操作。通过使用过滤器,可以对请求进行过滤,拦截请求,修改请求参数,在请求被处理之前进行一些预处理操作;同时也可以对响应进行过滤,对响应内容进行修改,添加一些额外的处理。
|
7月前
|
存储 API
使用Webpack的module.hot API来定义模块的热替换
使用Webpack的`module.hot` API实现模块热替换,简单示例展示如何在`myModule`变化时执行回调。`module.hot.accept`接收模块路径和回调函数,当模块或其依赖变更时触发回调,用于执行更新逻辑。可通过`module.hot.data`保存和恢复状态以实现热替换时保持应用程序的状态。
|
7月前
|
JavaScript
webpack-devtool选项 --生成source-map便于开发调试(二)
webpack-devtool选项 --生成source-map便于开发调试(二)
221 0
|
Java 应用服务中间件 数据安全/隐私保护
JavaWeb 三大组件之 过滤器 Filter
JavaWeb 三大组件之 过滤器 Filter
89 0
|
存储 JSON UED
Flask框架之RESTful--参数验证--add_argument方法参数详解
参数验证的重要性,Flask-RESTful 参数验证方法,add_argument方法参数详解
Jinja2 中常用的过滤器
Jinja2 是 Python 中流行的模板引擎之一,具有可扩展性和灵活性。
HtmlWebpackPlugin(html-webpack-plugin)传入自定义参数到模板
HtmlWebpackPlugin(html-webpack-plugin)传入自定义参数到模板
252 0
|
XML Java 应用服务中间件
JavaWeb--快速入门Filter过滤器
JavaWeb--快速入门Filter过滤器
200 0
JavaWeb--快速入门Filter过滤器
|
JavaScript 前端开发
Vue中filter过滤器的使用方法
Vue中filter过滤器的使用方法
233 0