blob: da9ce85b6fc8d96ea1e2647d526c72c649846187 [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
Bruno Binet5e65f3f2020-05-06 16:47:53 +020036 ignore_class_notfound_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
Andrew Pickford34d14452018-07-18 15:46:11 +0200127Constant Parameters
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200128--------------------------
129
Andrew Pickford34d14452018-07-18 15:46:11 +0200130Parameters can be labeled as constant by using the prefix ``=``
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200131
132.. code-block:: yaml
133
134 parameters:
135 =one: 1
136
Andrew Pickford34d14452018-07-18 15:46:11 +0200137If in the normal parameter merging a constant parameter would be changed then depending
138on the setting of ``strict_constant_parameters`` either an exception is raised (``strict_constant_parameters`` true)
139or the parameter is left unchanged and no notification or error is given (``strict_constant_parameters`` false)
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200140
141For example with:
142
143.. code-block:: yaml
144
145 # nodes/node1.yml
146 classes:
147 - first
148 - second
149
150 # classes/first.yml
151 parameters:
152 =one: 1
153
154 # classes/second.yml
155 parameters:
156 one: 2
157
Andrew Pickford34d14452018-07-18 15:46:11 +0200158``reclass.py --nodeinfo node1`` then gives an ''Attempt to change constant value'' error if ``strict_constant_parameters``
159is true or gives:
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200160
161.. code-block:: yaml
162
163 parameters:
164 alpha:
165 one: 1
166
Andrew Pickford34d14452018-07-18 15:46:11 +0200167if ``strict_constant_parameters`` is false
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200168
Andrew Pickford34d14452018-07-18 15:46:11 +0200169Default value for ``strict_constant_parameters`` is True
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200170
171.. code-block:: yaml
172
Andrew Pickford34d14452018-07-18 15:46:11 +0200173 strict_constant_parameters: True
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200174
175
Petr Michalecad441172017-09-18 17:18:10 +0200176Nested References
177-----------------
178
179References can now be nested, for example:
180
181.. code-block:: yaml
182
183 # nodes/node1.yml
184 parameters:
185 alpha:
186 one: ${beta:${alpha:two}}
187 two: a
188 beta:
189 a: 99
190
191``reclass.py --nodeinfo node1`` then gives:
192
193.. code-block:: yaml
194
195 parameters:
196 alpha:
197 one: 99
198 two: a
199 beta:
200 a: 99
201
202The ``${beta:${alpha:two}}`` construct first resolves the ``${alpha:two}`` reference to the value 'a', then resolves
203the reference ``${beta:a}`` to the value 99.
204
205
Andrew Pickforde0eb7b62018-03-16 08:45:42 +0100206Ignore overwritten missing references
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200207-------------------------------------
Andrew Pickforde0eb7b62018-03-16 08:45:42 +0100208
209Given the following classes:
210
211.. code-block:: yaml
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200212
Andrew Pickforde0eb7b62018-03-16 08:45:42 +0100213 # node1.yml
214 classes:
215 - class1
216 - class2
217 - class3
218
219 # class1.yml
220 parameters:
221 a: ${x}
222
223 # class2.yml
224 parameters:
225 a: ${y}
226
227 # class3.yml
228 parameters:
229 y: 1
230
Luis Buriolac04e1b02018-07-17 16:57:35 +0100231
Andrew Pickforde0eb7b62018-03-16 08:45:42 +0100232The parameter ``a`` only depends on the parameter ``y`` through the reference set in class2. The fact that the parameter ``x`` referenced
233in class1 is not defined does not affect the final value of the parameter ``a``. For such overwritten missing references by default a warning is
234printed 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
235an error will always be raised in the case of a missing reference.
236
237Default value is True to keep backward compatible behavior.
238
239.. code-block:: yaml
240
241 ignore_overwritten_missing_reference: True
242
Petr Michalecad441172017-09-18 17:18:10 +0200243
Andrew Pickfordffd77b42018-03-16 14:37:03 +0100244Print summary of missed references
245----------------------------------
246
247Instead of failing on the first undefinded reference error all missing reference errors are printed at once.
248
249.. code-block:: yaml
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200250
Andrew Pickfordffd77b42018-03-16 14:37:03 +0100251 reclass --nodeinfo mynode
252 -> dontpanic
253 Cannot resolve ${_param:kkk}, at mkkek3:tree:to:fail, in yaml_fs:///test/classes/third.yml
254 Cannot resolve ${_param:kkk}, at mkkek3:tree:another:xxxx, in yaml_fs:///test/classes/third.yml
255 Cannot resolve ${_param:kkk}, at mykey2:tree:to:fail, in yaml_fs:///test/classes/third.yml
256
257.. code-block:: yaml
258
259 group_errors: True
260
261
Andrew Pickford04cb20a2018-04-24 14:27:50 +0200262Use references in class names
263-----------------------------
264
265Allows to use references in the class names.
266
267References pointed to in class names cannot themselves reference another key, they should be simple strings.
268
269To avoid pitfalls do not over-engineer your class references. They should be used only for core conditions and only for them.
270A short example: `- system.wrodpress.db.${_class:database_backend}`.
271
272Best practices:
273- use references in class names always load your global class specification prior the reference is used.
274- structure your class references under parameters under one key (for example `_class`).
275- use class references as a kind of "context" or "global" available options you always know what they are set.
276
277Class referencing for existing reclass users. Frequently when constructing your models you had to load or not load some
278classes based on your setup. In most cases this lead to fork of a model or introducing kind of template generator (like cookiecutter) to
279create a model based on the base "context" or "global" variables. Class referencing is a simple way how to avoid
280"pre-processors" like this and if/else conditions around class section.
281
282
283Assuming following class setup:
284
285* node is loading `third.yml` class only
286
287
288Classes:
289
290.. code-block:: yaml
Andrew Pickforde3b114e2018-06-27 16:30:38 +0200291
Andrew Pickford04cb20a2018-04-24 14:27:50 +0200292 #/etc/reclass/classes/global.yml
293 parameters:
294 _class:
295 env:
296 override: 'env.dev'
297 lab:
298 name: default
299
300 #/etc/reclass/classes/lab/env/dev.yml
301 parameters:
302 lab:
303 name: dev
304
305 #/etc/reclass/classes/second.yml
306 classes:
307 - global
308 - lab.${_class:env:override}
309
310 #/etc/reclass/classes/third.yml
311 classes:
312 - global
313 - second
314
315
316Reclass --nodeinfo then returns:
317
318.. code-block:: yaml
319
320 ...
321 ...
322 applications: []
323 environment: base
324 exports: {}
325 classes:
Petr Michalec67e737c2018-04-25 09:44:02 +0200326 - global
Andrew Pickford04cb20a2018-04-24 14:27:50 +0200327 - lab.${_class:env:override}
328 - second
329 parameters:
330 _class:
331 env:
332 override: env.dev
333 lab:
334 name: dev
335 ...
336 ...
337
338
Petr Michalecd2762b02018-09-05 14:01:52 +0200339Load classes with relative names
340--------------------------------
341
342Load referenced class from a relative location to the current class.
Martin Polreich767b7722018-10-08 10:57:30 +0200343To load class from relative location start the class uri with "." or ".." char.
Petr Michalecd2762b02018-09-05 14:01:52 +0200344The only supported reference is to nested tree structure below the current class.
345
346You are allowed to use syntax for relative uri to required class on any place on your model (first class loaded, init.yml, regular class .yml).
347
348The feature is expected to improve flexibility while sharing classes between your models.
349
Martin Polreich5a2f9da2018-10-11 14:25:56 +0200350Please mpte that you can't use '..' without any calss following. If you want simply up in the sctructure, type in '..init'.
351
Petr Michalecd2762b02018-09-05 14:01:52 +0200352It's a new feature use it with care and mind that using "relative syntax" lower traceability of
353your pillar composition.
354
Martin Polreich767b7722018-10-08 10:57:30 +0200355Example usage of relative class name using '.' and '..':
Petr Michalecd2762b02018-09-05 14:01:52 +0200356
357.. code-block:: yaml
358
359 #/etc/reclass/classes/component/defaults.yml
360 classes:
361 component:
362 config:
363 a: b
364
365.. code-block:: yaml
366
367 #/etc/reclass/classes/component/init.yml
368 classes:
369 - .defaults
370
Martin Polreich767b7722018-10-08 10:57:30 +0200371.. code-block:: yaml
372
373 #/etc/reclass/classes/component/configuration/init.yml
374 classes:
375 - ..defaults
376
Petr Michalecd2762b02018-09-05 14:01:52 +0200377
Petr Michalecad441172017-09-18 17:18:10 +0200378Inventory Queries
379-----------------
380
381Inventory querying works using a new key type - exports to hold values which other node definitions can read using a $[] query, for example with:
382
383.. code-block:: yaml
384
385 # nodes/node1.yml
386 exports:
387 test_zero: 0
388 test_one:
389 name: ${name}
390 value: 6
391 test_two: ${dict}
392
393 parameters:
394 name: node1
395 dict:
396 a: 1
397 b: 2
398 exp_value_test: $[ exports:test_two ]
399 exp_if_test0: $[ if exports:test_zero == 0 ]
400 exp_if_test1: $[ exports:test_one if exports:test_one:value == 7 ]
401 exp_if_test2: $[ exports:test_one if exports:test_one:name == self:name ]
402
403 # nodes/node2.yml
404 exports:
405 test_zero: 0
406 test_one:
407 name: ${name}
408 value: 7
409 test_two: ${dict}
410
411 parameters:
412 name: node2
413 dict:
414 a: 11
415 b: 22
416
417
418``running reclass.py --nodeinfo node1`` gives (listing only the exports and parameters):
419
420.. code-block:: yaml
421
422 exports:
423 test_one:
424 name: node1
425 value: 6
426 test_two:
427 a: 1
428 b: 2
429 parameters:
430 dict:
431 a: 1
432 b: 2
433 exp_if_test0:
434 - node1
435 - node2
436 exp_if_test1:
437 node2:
438 name: node2
439 value: 7
440 exp_if_test2:
441 node1:
442 name: node1
443 value: 6
444 exp_value_test:
445 node1:
446 a: 1
447 b: 2
448 node2:
449 a: 11
450 b: 22
451 name: node1
452
453
454Exports 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 +0200455The ``$[]`` inventory queries are calculated for simple value expressions, ``$[ exports:key ]``, by returning
456a dictionary with an element (``{ node_name: key value }``) for each node which defines 'key' in the exports
457section. For tests with a preceeding value, ``$[ exports:key if exports:test_key == test_value ]``, the
458element (``{ node_name: key value }``) is only added to the returned dictionary if the test_key defined in
Petr Michalecad441172017-09-18 17:18:10 +0200459the node exports section equals the test value. For tests without a preceeding value,
Petr Michalecab9cac32017-09-18 17:35:54 +0200460``$[ 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 +0200461form 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 +0200462a not equals test (``!=``) can also be used.
Petr Michalecad441172017-09-18 17:18:10 +0200463
464
465**Inventory query options**
466
467By default inventory queries only look at nodes in the same environment as the querying node. This can be
468overriden using the +AllEnvs option:
469
Petr Michalecab9cac32017-09-18 17:35:54 +0200470.. code-block:: yaml
471
Petr Michalecad441172017-09-18 17:18:10 +0200472 $[ +AllEnvs exports:test ]
473
474Any 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 +0200475This can be overriden using the ``+IgnoreErrors`` option:
476
477.. code-block:: yaml
Petr Michalecad441172017-09-18 17:18:10 +0200478
479 $[ +IgnoreErrors exports:test ]
480
Petr Michalecab9cac32017-09-18 17:35:54 +0200481With the ``+IgnoreErrors`` option nodes which generate an error evaluating ``exports:test`` will be ignored.
Petr Michalecad441172017-09-18 17:18:10 +0200482
483Inventory query options can be combined:
484
Petr Michalecab9cac32017-09-18 17:35:54 +0200485.. code-block:: yaml
486
Petr Michalecad441172017-09-18 17:18:10 +0200487 $[ +AllEnvs +IgnoreErrors exports:test ]
488
489**Logical operators and/or**
490
491The logical operators and/or can be used in inventory queries:
492
Petr Michalecab9cac32017-09-18 17:35:54 +0200493.. code-block:: yaml
494
Petr Michalecad441172017-09-18 17:18:10 +0200495 $[ exports:test_value if exports:test_zero == 0 and exports:test_one == self:value ]
496
497The individual elements of the if statement are evaluated and combined with the logical operators starting from the
498left and working to the right.
499
500
501**Inventory query example**
502
503Defining a cluster of machines using an inventory query, for example to open access to a database server to a
504group of nodes. Given exports/parameters for nodes of the form:
505
506.. code-block:: yaml
507
Petr Michalecab9cac32017-09-18 17:35:54 +0200508 # for all nodes requiring access to the database server
509 exports:
510 host:
511 ip_address: aaa.bbb.ccc.ddd
512 cluster: _some_cluster_name_
Petr Michalecad441172017-09-18 17:18:10 +0200513
514.. code-block:: yaml
515
Petr Michalecab9cac32017-09-18 17:35:54 +0200516 # for the database server
517 parameters:
518 cluster_name: production-cluster
519 postgresql:
520 server:
521 clients: $[ exports:host:ip_address if exports:cluster == self:cluster_name ]
Petr Michalecad441172017-09-18 17:18:10 +0200522
Petr Michalecab9cac32017-09-18 17:35:54 +0200523This will generate a dictionary with an entry for node where the ``export:cluster`` key for a node is equal to the
524``parameter:cluster_name`` key of the node on which the inventory query is run on. Each entry in the generated dictionary
525will contain the value of the ``exports:host:ip_address`` key. The output dictionary (depending on node definitions)
Petr Michalecad441172017-09-18 17:18:10 +0200526would look like:
527
528.. code-block:: yaml
529
Petr Michalecab9cac32017-09-18 17:35:54 +0200530 node1:
531 ip_address: aaa.bbb.ccc.ddd
532 node2:
533 ip_address: www.xxx.yyy.zzz
Petr Michalecad441172017-09-18 17:18:10 +0200534
535For nodes where exports:cluster key is not defined or where the key is not equal to self:cluster_name no entry is made
536in the output dictionary.
537
538In practise the exports:cluster key can be set using a parameter reference:
539
540.. code-block:: yaml
541
Petr Michalecab9cac32017-09-18 17:35:54 +0200542 exports:
543 cluster: ${cluster_name}
544 parameters:
545 cluster_name: production-cluster
Petr Michalecad441172017-09-18 17:18:10 +0200546
547The above exports and parameter definitions could be put into a separate class and then included by nodes which require
548access to the database and included by the database server as well.
Luis Buriolac04e1b02018-07-17 16:57:35 +0100549
550
Luis Buriola96d7ace2018-07-22 22:00:02 +0100551Compose node name
Luis Buriolac04e1b02018-07-17 16:57:35 +0100552---------------------------
553
554Nodes can be defined in subdirectories. However, node names (filename) must be unique across all subdirectories.
555
556For example, the following file structure is invalid:
557
558.. code-block:: yaml
559
560 inventory/nodes/prod/mysql.yml
561 inventory/nodes/staging/mysql.yml
562
563With setting:
564
565.. code-block:: yaml
566
Luis Buriola96d7ace2018-07-22 22:00:02 +0100567 compose_node_name: True # default False
Luis Buriolac04e1b02018-07-17 16:57:35 +0100568
569This adds the subfolder to the node name and the structure above can then be used. It generates the following reclass objects:
570
571.. code-block:: yaml
572
573 nodes:
574 prod.mysql:
575 ...
576 staging.mysql:
577 ...
Luis Buriolaa7bfd742018-07-23 10:43:46 +0100578
579If the subfolder path starts with the underscore character ``_``, then the subfolder path is NOT added to the node name.
Andrew Pickford424769f2018-09-25 14:12:58 +0200580
581
582Git storage type
583----------------
584
585Reclass node and class yaml files can be read from a remote git repository with the yaml_git storage type. Use nodes_uri and
586classes_uri to define the git repos to use for nodes and classes. These can be the same repo.
587
588For salt masters using ssh connections the private and public keys must be readable by the salt daemon, which requires the
589private key NOT be password protected. For stand alone reclass using ssh connections if the privkey and pubkey options
590are not defined then any in memory key (from ssh-add) will be used.
591
592Salt master reclass config example:
593
594.. code-block:: yaml
595
596 storage_type:yaml_git
597 nodes_uri:
598 # branch to use
599 branch: master
600
601 # cache directory (default: ~/.reclass/git/cache)
602 cache_dir: /var/cache/reclass/git
603
604 # lock directory (default: ~/.reclass/git/lock)
605 lock_dir: /var/cache/reclass/lock
606
607 # private key for ssh connections (no default, but will used keys stored
608 # by ssh-add in memory if privkey and pubkey are not set)
609 privkey: /root/salt_rsa
610 # public key for ssh connections
611 pubkey: /root/salt_rsa.pub
612
613 repo: git+ssh://gitlab@remote.server:salt/nodes.git
614
615 classes_uri:
616 # branch to use or __env__ to use the branch matching the node
617 # environment name
618 branch: __env__
619
620 # cache directory (default: ~/.reclass/git/cache)
621 cache_dir: /var/cache/reclass/git
622
623 # lock directory (default: ~/.reclass/git/lock)
624 lock_dir: /var/cache/reclass/lock
625
626 # private key for ssh connections (no default, but will used keys stored
627 # by ssh-add in memory if privkey and pubkey are not set)
628 privkey: /root/salt_rsa
629 # public key for ssh connections
630 pubkey: /root/salt_rsa.pub
631
632 # branch/env overrides for specific branches
633 env_overrides:
634 # prod env uses master branch
635 - prod:
636 branch: master
637 # use master branch for nodes with no environment defined
638 - none:
639 branch: master
640
641 repo: git+ssh://gitlab@remote.server:salt/site.git
642
643 # root directory of the class hierarcy in git repo
644 # defaults to root directory of git repo if not given
645 root: classes
646
647
648Mixed storage type
649------------------
650
651Use a mixture of storage types.
652
653Salt master reclass config example, which by default uses yaml_git storage but overrides the location for
654classes for the pre-prod environment to use a directory on the local disc:
655
656.. code-block:: yaml
657
658 storage_type: mixed
659 nodes_uri:
660 # storage type to use
661 storage_type: yaml_git
662
663 # yaml_git storage options
664 branch: master
665 cache_dir: /var/cache/reclass/git
666 lock_dir: /var/cache/reclass/lock
667 privkey: /root/salt_rsa
668 pubkey: /root/salt_rsa.pub
669 repo: git+ssh://gitlab@remote.server:salt/nodes.git
670
671 classes_uri:
672 # storage type to use
673 storage_type: yaml_git
674
675 # yaml_git storage options
676 branch: __env__
677 cache_dir: /var/cache/reclass/git
678 lock_dir: /var/cache/reclass/lock
679 privkey: /root/salt_rsa
680 pubkey: /root/salt_rsa.pub
681 repo: git+ssh://gitlab@remote.server:salt/site.git
682 root: classes
683
684 env_overrides:
685 - prod:
686 branch: master
687 - none:
688 branch: master
689 - pre-prod:
690 # override storage type for this environment
691 storage_type: yaml_fs
692 # options for yaml_fs storage type
693 uri: /srv/salt/env/pre-prod/classes