blob: a18a37accd534ddf7befe0292c20f6259675db82 [file] [log] [blame]
Petr Michalecad441172017-09-18 17:18:10 +02001Escaping of References and Inventory Queries
2--------------------------------------------
3
4Reference and inventory queries can be escaped to produce literal strings, for example:
5
6.. code-block:: yaml
7
8 parameters:
9 colour: Blue
10 unescaped: The colour is ${colour}
11 escaped: The colour is \${colour}
12 double_escaped: The colour is \\${colour}
13
14
15This would produce:
16
17.. code-block:: yaml
18
19 parameters:
20 colour: Blue
21 unescaped: The colour is Blue
22 escaped: The colour is ${colour}
23 double_escaped: The colour is \Blue
24
25
26
27Ignore class not found
28----------------------
29
30At some cases (bootstrapping, development) it can be convenient to ignore some missing classes.
31To control the feature there are two options available:
32
33.. code-block:: yaml
34
35 ignore_class_notfound: False
Petr Michalec19324742017-09-18 17:32:24 +020036 ignore_class_regexp: ['.*']
Petr Michalecad441172017-09-18 17:18:10 +020037
38If you set regexp pattern to ``service.*`` all missing classes starting 'service.' will be logged with warning, but will not
39fail to return rendered reclass. Assuming all parameter interpolation passes.
40
41
42
43Merging Referenced Lists and Dictionaries
44-----------------------------------------
45
46Referenced lists or dicts can now be merged:
47
48.. code-block:: yaml
49
50 # nodes/test.yml
51 classes:
52 - test1
53 - test2
54 parameters:
55 one:
56 a: 1
57 b: 2
58 two:
59 c: 3
60 d: 4
61 three:
62 e: 5
63
64 # classes/test1.yml
65 parameters:
66 three: ${one}
67
68 # classes/test2.yml
69 parameters:
70 three: ${two}
71
72``running reclass.py --nodeinfo node1`` then gives:
73
74.. code-block:: yaml
75
76 parameters:
77 one:
78 a: 1
79 b: 2
80 three:
81 a: 1
82 b: 2
83 c: 3
84 d: 4
85 e: 5
86 two:
87 c: 3
88 d: 4
89
90This first sets the parameter three to the value of parameter one (class test1) then merges parameter two into
91parameter three (class test2) and finally merges the parameter three definition given in the node definition into
92the final value.
93
94
Petr Michalec0a3a3682018-03-28 15:30:15 +020095Allow override list and dicts by empty entity,None instead of merge
96-------------------------------------------------------------------
97
98With settings:
99
100.. code-block:: yaml
101
102 allow_none_override: True # default True
103
104 # note dict,list over None is allowed and not configurable
105
106Referenced lists or dicts can now be overriden by None or empty type of dict, list:
107
108.. code-block:: yaml
109
110 # nodes/test.yml
111 parameters:
112 one:
113 a: 1
114 b: 2
115 two: {}
116 three: None
117
118 # classes/test1.yml
119 parameters:
120 one: ${two}
121
122 # classes/test2.yml
123 parameters:
124 three: ${one}
125
Petr Michalecad441172017-09-18 17:18:10 +0200126
127Nested References
128-----------------
129
130References can now be nested, for example:
131
132.. code-block:: yaml
133
134 # nodes/node1.yml
135 parameters:
136 alpha:
137 one: ${beta:${alpha:two}}
138 two: a
139 beta:
140 a: 99
141
142``reclass.py --nodeinfo node1`` then gives:
143
144.. code-block:: yaml
145
146 parameters:
147 alpha:
148 one: 99
149 two: a
150 beta:
151 a: 99
152
153The ``${beta:${alpha:two}}`` construct first resolves the ``${alpha:two}`` reference to the value 'a', then resolves
154the reference ``${beta:a}`` to the value 99.
155
156
Andrew Pickforde0eb7b62018-03-16 08:45:42 +0100157Ignore overwritten missing references
158-------------------------
159
160Given the following classes:
161
162.. code-block:: yaml
163 # node1.yml
164 classes:
165 - class1
166 - class2
167 - class3
168
169 # class1.yml
170 parameters:
171 a: ${x}
172
173 # class2.yml
174 parameters:
175 a: ${y}
176
177 # class3.yml
178 parameters:
179 y: 1
180
181
182The parameter ``a`` only depends on the parameter ``y`` through the reference set in class2. The fact that the parameter ``x`` referenced
183in class1 is not defined does not affect the final value of the parameter ``a``. For such overwritten missing references by default a warning is
184printed but no error is raised, providing the final value of the parameter being evaluated is a scalar. If the final value is a dictionary or list
185an error will always be raised in the case of a missing reference.
186
187Default value is True to keep backward compatible behavior.
188
189.. code-block:: yaml
190
191 ignore_overwritten_missing_reference: True
192
Petr Michalecad441172017-09-18 17:18:10 +0200193
Andrew Pickfordffd77b42018-03-16 14:37:03 +0100194Print summary of missed references
195----------------------------------
196
197Instead of failing on the first undefinded reference error all missing reference errors are printed at once.
198
199.. code-block:: yaml
200 reclass --nodeinfo mynode
201 -> dontpanic
202 Cannot resolve ${_param:kkk}, at mkkek3:tree:to:fail, in yaml_fs:///test/classes/third.yml
203 Cannot resolve ${_param:kkk}, at mkkek3:tree:another:xxxx, in yaml_fs:///test/classes/third.yml
204 Cannot resolve ${_param:kkk}, at mykey2:tree:to:fail, in yaml_fs:///test/classes/third.yml
205
206.. code-block:: yaml
207
208 group_errors: True
209
210
Petr Michalec04132e72018-04-23 15:44:21 +0200211Use global classes
212------------------
213
214Allows specify regexp pattern for "global class".
215
216Normally, classes are loaded when first seen. Thus they are not evaluated later when hit 2nd time. Only way to override
217parameters they load is by another class.
218
219Global classes, recognized by regexp pattern, are always loaded when hit and thus their content might be
220understood as enforced, globally available and not to be overridden by other class, even deeper in hierarchy.
221
222To avoid pitfalls do not over-engineer your solution. By default global class regexp pattern is not set.
223
224
225Global class regexp setup:
226
227.. code-block:: yaml
228
229 #/etc/reclass/reclass-config.yml
230 global_class_regexp = ['.*global']
231
232
Andrew Pickford04cb20a2018-04-24 14:27:50 +0200233Use references in class names
234-----------------------------
235
236Allows to use references in the class names.
237
238References pointed to in class names cannot themselves reference another key, they should be simple strings.
239
240To avoid pitfalls do not over-engineer your class references. They should be used only for core conditions and only for them.
241A short example: `- system.wrodpress.db.${_class:database_backend}`.
242
243Best practices:
244- use references in class names always load your global class specification prior the reference is used.
245- structure your class references under parameters under one key (for example `_class`).
246- use class references as a kind of "context" or "global" available options you always know what they are set.
247
248Class referencing for existing reclass users. Frequently when constructing your models you had to load or not load some
249classes based on your setup. In most cases this lead to fork of a model or introducing kind of template generator (like cookiecutter) to
250create a model based on the base "context" or "global" variables. Class referencing is a simple way how to avoid
251"pre-processors" like this and if/else conditions around class section.
252
253
254Assuming following class setup:
255
256* node is loading `third.yml` class only
257
258
259Classes:
260
261.. code-block:: yaml
262 #/etc/reclass/classes/global.yml
263 parameters:
264 _class:
265 env:
266 override: 'env.dev'
267 lab:
268 name: default
269
270 #/etc/reclass/classes/lab/env/dev.yml
271 parameters:
272 lab:
273 name: dev
274
275 #/etc/reclass/classes/second.yml
276 classes:
277 - global
278 - lab.${_class:env:override}
279
280 #/etc/reclass/classes/third.yml
281 classes:
282 - global
283 - second
284
285
286Reclass --nodeinfo then returns:
287
288.. code-block:: yaml
289
290 ...
291 ...
292 applications: []
293 environment: base
294 exports: {}
295 classes:
Petr Michalec67e737c2018-04-25 09:44:02 +0200296 - global
Andrew Pickford04cb20a2018-04-24 14:27:50 +0200297 - lab.${_class:env:override}
298 - second
299 parameters:
300 _class:
301 env:
302 override: env.dev
303 lab:
304 name: dev
305 ...
306 ...
307
308
Petr Michalecad441172017-09-18 17:18:10 +0200309Inventory Queries
310-----------------
311
312Inventory querying works using a new key type - exports to hold values which other node definitions can read using a $[] query, for example with:
313
314.. code-block:: yaml
315
316 # nodes/node1.yml
317 exports:
318 test_zero: 0
319 test_one:
320 name: ${name}
321 value: 6
322 test_two: ${dict}
323
324 parameters:
325 name: node1
326 dict:
327 a: 1
328 b: 2
329 exp_value_test: $[ exports:test_two ]
330 exp_if_test0: $[ if exports:test_zero == 0 ]
331 exp_if_test1: $[ exports:test_one if exports:test_one:value == 7 ]
332 exp_if_test2: $[ exports:test_one if exports:test_one:name == self:name ]
333
334 # nodes/node2.yml
335 exports:
336 test_zero: 0
337 test_one:
338 name: ${name}
339 value: 7
340 test_two: ${dict}
341
342 parameters:
343 name: node2
344 dict:
345 a: 11
346 b: 22
347
348
349``running reclass.py --nodeinfo node1`` gives (listing only the exports and parameters):
350
351.. code-block:: yaml
352
353 exports:
354 test_one:
355 name: node1
356 value: 6
357 test_two:
358 a: 1
359 b: 2
360 parameters:
361 dict:
362 a: 1
363 b: 2
364 exp_if_test0:
365 - node1
366 - node2
367 exp_if_test1:
368 node2:
369 name: node2
370 value: 7
371 exp_if_test2:
372 node1:
373 name: node1
374 value: 6
375 exp_value_test:
376 node1:
377 a: 1
378 b: 2
379 node2:
380 a: 11
381 b: 22
382 name: node1
383
384
385Exports defined for a node can be a simple value or a reference to a parameter in the node definition.
Petr Michalecab9cac32017-09-18 17:35:54 +0200386The ``$[]`` inventory queries are calculated for simple value expressions, ``$[ exports:key ]``, by returning
387a dictionary with an element (``{ node_name: key value }``) for each node which defines 'key' in the exports
388section. For tests with a preceeding value, ``$[ exports:key if exports:test_key == test_value ]``, the
389element (``{ node_name: key value }``) is only added to the returned dictionary if the test_key defined in
Petr Michalecad441172017-09-18 17:18:10 +0200390the node exports section equals the test value. For tests without a preceeding value,
Petr Michalecab9cac32017-09-18 17:35:54 +0200391``$[ if exports:test_key == test_value ]``, a list of nodes which pass the test is returned. For either test
Petr Michalecad441172017-09-18 17:18:10 +0200392form the test value can either be a simple value or a node parameter. And as well as an equality test
Petr Michalecab9cac32017-09-18 17:35:54 +0200393a not equals test (``!=``) can also be used.
Petr Michalecad441172017-09-18 17:18:10 +0200394
395
396**Inventory query options**
397
398By default inventory queries only look at nodes in the same environment as the querying node. This can be
399overriden using the +AllEnvs option:
400
Petr Michalecab9cac32017-09-18 17:35:54 +0200401.. code-block:: yaml
402
Petr Michalecad441172017-09-18 17:18:10 +0200403 $[ +AllEnvs exports:test ]
404
405Any errors in rendering the export parameters for a node will give an error for the inventory query as a whole.
Petr Michalecab9cac32017-09-18 17:35:54 +0200406This can be overriden using the ``+IgnoreErrors`` option:
407
408.. code-block:: yaml
Petr Michalecad441172017-09-18 17:18:10 +0200409
410 $[ +IgnoreErrors exports:test ]
411
Petr Michalecab9cac32017-09-18 17:35:54 +0200412With the ``+IgnoreErrors`` option nodes which generate an error evaluating ``exports:test`` will be ignored.
Petr Michalecad441172017-09-18 17:18:10 +0200413
414Inventory query options can be combined:
415
Petr Michalecab9cac32017-09-18 17:35:54 +0200416.. code-block:: yaml
417
Petr Michalecad441172017-09-18 17:18:10 +0200418 $[ +AllEnvs +IgnoreErrors exports:test ]
419
420**Logical operators and/or**
421
422The logical operators and/or can be used in inventory queries:
423
Petr Michalecab9cac32017-09-18 17:35:54 +0200424.. code-block:: yaml
425
Petr Michalecad441172017-09-18 17:18:10 +0200426 $[ exports:test_value if exports:test_zero == 0 and exports:test_one == self:value ]
427
428The individual elements of the if statement are evaluated and combined with the logical operators starting from the
429left and working to the right.
430
431
432**Inventory query example**
433
434Defining a cluster of machines using an inventory query, for example to open access to a database server to a
435group of nodes. Given exports/parameters for nodes of the form:
436
437.. code-block:: yaml
438
Petr Michalecab9cac32017-09-18 17:35:54 +0200439 # for all nodes requiring access to the database server
440 exports:
441 host:
442 ip_address: aaa.bbb.ccc.ddd
443 cluster: _some_cluster_name_
Petr Michalecad441172017-09-18 17:18:10 +0200444
445.. code-block:: yaml
446
Petr Michalecab9cac32017-09-18 17:35:54 +0200447 # for the database server
448 parameters:
449 cluster_name: production-cluster
450 postgresql:
451 server:
452 clients: $[ exports:host:ip_address if exports:cluster == self:cluster_name ]
Petr Michalecad441172017-09-18 17:18:10 +0200453
Petr Michalecab9cac32017-09-18 17:35:54 +0200454This will generate a dictionary with an entry for node where the ``export:cluster`` key for a node is equal to the
455``parameter:cluster_name`` key of the node on which the inventory query is run on. Each entry in the generated dictionary
456will contain the value of the ``exports:host:ip_address`` key. The output dictionary (depending on node definitions)
Petr Michalecad441172017-09-18 17:18:10 +0200457would look like:
458
459.. code-block:: yaml
460
Petr Michalecab9cac32017-09-18 17:35:54 +0200461 node1:
462 ip_address: aaa.bbb.ccc.ddd
463 node2:
464 ip_address: www.xxx.yyy.zzz
Petr Michalecad441172017-09-18 17:18:10 +0200465
466For nodes where exports:cluster key is not defined or where the key is not equal to self:cluster_name no entry is made
467in the output dictionary.
468
469In practise the exports:cluster key can be set using a parameter reference:
470
471.. code-block:: yaml
472
Petr Michalecab9cac32017-09-18 17:35:54 +0200473 exports:
474 cluster: ${cluster_name}
475 parameters:
476 cluster_name: production-cluster
Petr Michalecad441172017-09-18 17:18:10 +0200477
478The above exports and parameter definitions could be put into a separate class and then included by nodes which require
479access to the database and included by the database server as well.