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'