1Config::Model::Manual::UMsoedrelCCCoornnetfaritigib:ou:ntMIeonddterPloe:dr:ulMcatDniouocanul(m:3e:)nMtoadteiloCnreationIntroduction(3)
2
3
4
6 Config::Model::Manual::ModelCreationIntroduction - Introduction to
7 model creation with Config::Model
8
10 version 2.141
11
13 This page describes how to write a simple configuration model. Creation
14 of more complex models are described in Creating a model with advanced
15 features.
16
17 Note that this document shows a lot of Perl data structure to highlight
18 the content of a model. A Perl data structure is very similar to a JSON
19 structure. The only thing you need to know are:
20
21 • Curly braces "{ ... }" contain a dictionary of key, value pairs (a
22 "hash" in Perl land))
23
24 • Square brackets "[ ... ]" contain a list of items ("array" or
25 "list" in Perl land)
26
28 configuration file
29 Text file where configuration data are stored. This configuration
30 file is used by an application -- the target application
31
32 configuration tree
33 The semantic content of the configuration file stored in a tree
34 representation
35
36 configuration model
37 Structure and constraints of the configuration tree. Like a schema
38 for the configuration tree
39
40 target application
41 The application that uses the configuration file. The application
42 can be of type "system" (i.e. the configuration file is located in
43 "/etc"), "user" (i.e. the configuration file is located in a user
44 directory like "~/.config") or "application" (the configuration
45 file is in or below the current directory)
46
47 end user
48 User of the target application
49
50 application developer
51 Target application developer
52
53 model developer
54 People developing the configuration model. Not necessarily the
55 application developer
56
58 Most configuration files are actually organized mostly as a tree
59 structure. Depending on the syntax of the file, this structure may be
60 obvious to see (e.g. for XML, Apache) or not so obvious ("Xorg" syntax,
61 INI syntax).
62
63 For some files like "approx.conf" or "adduser.conf", this tree
64 structure is quite flat. It looks much like a rake than a tree, but
65 still, it's a tree.
66
67 For instance, this "approx.conf":
68
69 $pdiffs 1
70 $max_wait 14
71 debian http://ftp.fr.debian.org/debian
72
73 can have this tree representation:
74
75 root
76 |--pdiff=1
77 |--max_wait=14
78 `--distrib(debian)=http://ftp.fr.debian.org/debian
79
80 Other configuration files like "apache2.conf" or "xorg.conf" have a
81 structure that look more like a tree.
82
83 For instance, consider this "xorg.conf" snippet:
84
85 Section "Device"
86 Identifier "Device0"
87 Driver "nvidia"
88 EndSection
89
90 Section "Screen"
91 Identifier "Screen0"
92 Device "Device0"
93 Option "AllowGLXWithComposite" "True"
94 Option "DynamicTwinView" "True"
95 SubSection "Display"
96 Depth 24
97 EndSubSection
98 EndSection
99
100 Knowing that Xorg.conf can have several Device or Screen sections
101 identified by their "Identifiers", the configuration can be represented
102 in this tree as:
103
104 root
105 |--Device(Device0)
106 | `--Driver=nvidia
107 `--Screen(Screen0)
108 |--Device=Device0
109 |--Option
110 | |--AllowGLXWithComposite=True
111 | `--DynamicTwinView=True
112 `--Display
113 `--Depth=24
114
115 One may argue that some "Xorg" parameter refer to others (i.e."Device"
116 and "Monitor" value in "Screen" section) and so they cannot be
117 represented as a tree. That's right, there are some more complex
118 relations that are added to the tree structure. This will be covered in
119 more details when dealing with complex models.
120
121 In some other case, the structure of a tree is not fixed. For instance,
122 "Device" options in "Xorg.conf" are different depending on the value of
123 the "Device Driver". In this case, the structure of the configuration
124 tree must be adapted (morphed) depending on a parameter value.
125
126 Just like XML data can have Schema to validate their content, the
127 configuration tree structure needs to have its own schema to validate
128 its content. Since the tree structure cannot be represented as a static
129 tree without reference, XML like schema are not enough to validate
130 configuration data.
131
132 Config::Model provides a kind of schema for configuration data that
133 takes care of the cross references mentioned above and of the dynamic
134 nature of the configuration tree required for "Xorg" (and others).
135
137 A configuration model defines the configuration tree structure:
138
139 • A model defines one or more configuration class
140
141 • At least one class is required to define the configuration tree
142 root
143
144 • Each class contains several elements. An element can be:
145
146 • A leaf to represent one configuration parameter
147
148 • A list of hash of leaves to represent several parameter
149
150 • A node to hold a node of a configuration tree
151
152 • A list or hash of nodes
153
154 These basic relations enable to define the main parts of a
155 configuration tree.
156
157 If we refer to the "approx.conf" example mentioned above, one only
158 class is required (let's say the "Approx" class). This class must
159 contain (see approx.conf man page):
160
161 • A boolean leaf for "pdiff" (1 if not specified)
162
163 • An integer leaf for "max_wait" (10 seconds unless specified
164 otherwise)
165
166 • A hash of string leaves for "distrib" (no default).
167
168 A configuration model is stored this way by Config::Model:
169
170 {
171 name => 'Approx',
172 element => [
173 pdiffs => {
174 type => 'leaf',
175 value_type => 'boolean',
176 upstream_default => '1'
177 },
178 max_wait => {
179 type => 'leaf',
180 value_type => 'integer',
181 upstream_default => '10'
182 },
183 distributions'=> {
184 type => 'hash',
185 index_type => 'string' ,
186 cargo => {
187 value_type => 'uniline',
188 type => 'leaf',
189 },
190 }
191 ]
192 }
193
194 The "Xorg" example leads to a slightly more complex model with several
195 classes:
196
197 • "Xorg" (root class)
198
199 • "Xorg::Device"
200
201 • "Xorg::Screen"
202
203 • "Xorg::Screen::Option" for the Screen options
204
205 • "Xorg::Screen::Display" for the"Display" subsection
206
207 The root class is declared this way:
208
209 {
210 name => 'Xorg',
211 element => [
212 Device => {
213 type => 'hash',
214 index_type => 'string'
215 cargo => {
216 type => 'node',
217 config_class_name => 'Xorg::Device'
218 },
219 },
220 Screen => {
221 type => 'hash',
222 index_type => 'string'
223 cargo => {
224 type => 'node',
225 config_class_name => 'Xorg::Screen'
226 },
227 },
228 ]
229 }
230
231 The"Xorg::Screen" class is:
232
233 {
234 name => 'Xorg::Screen',
235 element => [
236 Device => {
237 type' => 'leaf',
238 value_type => 'uniline',
239 },
240 Display => {
241 type => 'hash',
242 index_type => 'integer'
243 cargo => {
244 type => 'node',
245 config_class_name => 'Xorg::Screen::Display'
246 },
247 }
248 Option => {
249 type => 'node',
250 config_class_name => 'Xorg::Screen::Option'
251 },
252 ]
253 }
254
255 It's now time to detail how the elements of a class are constructed.
256
258 To define the required configuration classes, you should read the
259 documentation of the target application to :
260
261 • Find the structure of the configuration tree
262
263 • Identify configuration parameters, their constraints and relations
264
265 Last but not least, you should also find several valid examples of your
266 application configuration. These examples can be used as non-regression
267 tests and to verify that the application documentation was understood.
268
270 Configuration class declaration
271 Since writing the data structure shown below is not fun (even with
272 Perl), you are encouraged to use the model editor provided by cme using
273 "cme meta edit" command (provided by Config::Model::Itself). This
274 commands provides a GUI to create or update your model.
275
276 When saving, "cme" writes the data structure in the correct directory.
277
278 Configuration class declaration (the hard way)
279 In summary, configuration documentation is translated in a format
280 usable by Config::Model:
281
282 • The structure is translated into configuration classes
283
284 • Configuration parameters are translated into elements
285
286 • Constraints are translated into element attributes
287
288 All models files must be written in a specific directory. For instance,
289 for model "Xorg", you must create "./lib/Config/Model/models/Xorg.pl".
290 Other classes like "Xorg::Screen" can be stored in their own file
291 "./lib/Config/Model/models/Xorg/Screen.pl" or included in "Xorg.pl"
292
293 A model file is a Perl file containing an array for hash ref. Each Hash
294 ref contains a class declaration:
295
296 [ { name => 'Xorg', ... } , { name => 'Xorg::Screen', ... } ] ;
297
298 A class can have the following parameters:
299
300 • name: mandatory name of the class
301
302 • class_description: Description of the configuration class.
303
304 • generated_by: Mention with a descriptive string if this class was
305 generated by a program. This parameter is currently reserved for
306 "Config::Model::Itself" model editor.
307
308 • include: Include element description from another class.
309
310 For more details, see "Configuration_Model" in Config::Model.
311
312 For instance:
313
314 $ cat lib/Config/Model/models/Xorg.pl
315 [
316 {
317 name => 'Xorg',
318 class_description => 'Top level Xorg configuration.',
319 include => [ 'Xorg::ConfigDir'],
320 element => [
321 Files => {
322 type => 'node',
323 description => 'File pathnames',
324 config_class_name => 'Xorg::Files'
325 },
326 # snip
327 ]
328 },
329 {
330 name => 'Xorg::DRI',
331 element => [
332 Mode => {
333 type => 'leaf',
334 value_type => 'uniline',
335 description => 'DRI mode, usually set to 0666'
336 }
337 ]
338 }
339 ];
340
341 Common attributes for all elements
342 This first set of attributes helps the user by providing guidance (with
343 "level" and "status") and documentation ("summary" and "description").
344
345 All elements (simple or complex) can have the following attributes:
346
347 • "description": full length description of the attribute
348
349 • "summary": one line summary of the above description
350
351 • "level": is "important", "normal" or "hidden". The level is used to
352 set how configuration data is presented to the user in browsing
353 mode. Important elements are shown to the user no matter what.
354 hidden elements are explained with the warp notion.
355
356 • "status": is "obsolete", "deprecated" or "standard" (default).
357 Warnings are shown when using a deprecated element and an exception
358 is raised when an obsolete element is used.
359
360 See "Configuration_class" in Config::Model for details.
361
362 Leaf elements
363 Leaf element is the most common type to represent configuration data.
364 A leaf element represents a specific configuration parameter.
365
366 In more details, a leaf element have the following attributes (See
367 "Value_model_declaration" in Config::Model::Value doc):
368
369 type
370 Set to "leaf" (mandatory)
371
372 value_type
373 Either "boolean", "integer", "number", "enum", "string", "uniline"
374 (i.e. a string without "\n") (mandatory)
375
376 min Minimum value (for "integer" or "number")
377
378 max Maximum value (for "integer" or "number")
379
380 choice
381 Possible values for an enum
382
383 mandatory
384 Whether the value is mandatory or not
385
386 default
387 Default value that must be written in the configuration file
388
389 upstream_default
390 Default value that is known by the target application and thus does
391 not need to be written in the configuration file.
392
393 To know which attributes to use, you should read the documentation of
394 the target application.
395
396 For instance, "AddressFamily" parameter (sshd_config(5)) is specified
397 with: Specifies which address family should be used by sshd(8). Valid
398 arguments are "any", "inet" (use IPv4 only), or "inet6" (use IPv6
399 only). The default is "any".
400
401 For Config::Model, "AddressFamily" is a type "leaf" element, value_type
402 "enum" and the application falls back to "any" if this parameter is
403 left blank in "sshd_config" file.
404
405 Thus the model of this element is :
406
407 AddressFamily => {
408 type => 'leaf',
409 value_type => 'enum',
410 upstream_default => 'any',
411 description => 'Specifies which address family should be used by sshd(8).',
412 choice => [ 'any', 'inet', 'inet6' ]
413 }
414
415 Simple list or hash element
416 Some configuration parameters are in fact a list or a hash of
417 parameters. For instance, "approx.conf" can feature a list of remote
418 repositories:
419
420 # remote repositories
421 debian http://ftp.fr.debian.org/debian
422 multimedia http://www.debian-multimedia.org
423
424 These repositorie URLs must be stored as a hash where the key is debian
425 or multimedia and the associated value is a URL. But this hash must
426 have something which is not explicit in "approx.conf" file: a parameter
427 name. Approx man page mentions that: The name/value pairs [not
428 beginning with '$' are used to map distribution names to remote
429 repositories.. So let's use "distribution" as a parameter name.
430
431 The example is stored this way in the configuration tree:
432
433 root
434 |--distribution(debian)=http://ftp.fr.debian.org/debian
435 `--distribution(multimedia)=http://www.debian-multimedia.org
436
437 The model needs to declare that "distribution" is:
438
439 • a type "hash" parameter
440
441 • the hash key is a string
442
443 • the values of the hash are of type "leaf" and value_type "uniline"
444
445 distribution => {
446 type => 'hash',
447 index_type => 'string',
448 cargo => {
449 type => 'leaf',
450 value_type => 'uniline',
451 },
452 summary => 'remote repositories',
453 description => 'The other name/value pairs are ...',
454 }
455
456 For more details on list and hash elements, see hash or list model
457 declaration man page.
458
459 node element
460 A node element is necessary if the configuration file has more than a
461 list of variable. In this case, the tree is deeper than a rake and a
462 node element if necessary to provide a new node within the tree.
463
464 In the Xorg example above, the options of "Xorg::Screen" need their own
465 sub-branch in the tree:
466
467 Screen(Screen0)
468 `--Option
469 |--AllowGLXWithComposite=True
470 `--DynamicTwinView=True
471
472 For this, a new dedicated class is necessary>Xorg::Screen::Option> (see
473 its declaration above). This new class must be tied to the Screen class
474 with a node element.
475
476 A node element has the following parameters:
477
478 • type (set to "node")
479
480 • the name of the configuration class name (>config_class_name>)
481
482 So the "Option" node element is declared with:
483
484 Option => {
485 type => 'node',
486 config_class_name => 'Xorg::Screen::Option'
487 },
488
489 Hash or list of nodes
490 Some configuration files can feature a set of rather complex
491 configuration entities. For instance "Xorg.pl" can feature several
492 Screen or Device definitions. These definitions are identified by the
493 "Identifier" parameter:
494
495 Section "Device"
496 Identifier "Device0"
497 Driver "nvidia"
498 BusID "PCI:3:0:1"
499 EndSection
500
501 Section "Screen"
502 Identifier "Screen0"
503 Device "Device0"
504 DefaultDepth 24
505 EndSection
506
507 The Xorg configuration tree features 2 elements (Screen and Device)
508 that use the Identifier parameters as hash keys:
509
510 root
511 |--Device(Device0)
512 | |--Driver=nvidia
513 | `--BusId=PCI:3:0:1
514 `--Screen(Screen0)
515 |--Device=Device0
516 `--DefaultDepth=24
517
518 And the Xorg model must define these 2 parameters as "hash". The cargo
519 of this hash is of type "node" and refers to 2 different configuration
520 classes, one for "Device" ("Xorg::Device") and one for "Screen"
521 ("Xorg::Screen"):
522
523 {
524 name => 'Xorg',
525 element => [
526 Device => {
527 type => 'hash',
528 index_type => 'string'
529 cargo => {
530 type => 'node',
531 config_class_name => 'Xorg::Device'
532 },
533 },
534 Screen => {
535 type => 'hash',
536 index_type => 'string'
537 cargo => {
538 type => 'node',
539 config_class_name => 'Xorg::Screen'
540 },
541 },
542 ]
543 }
544
546 Both Perl/Tk and Curses interfaces feature a configuration wizard
547 generated from a configuration model.
548
549 The wizard works by exploring the configuration tree and stopping on
550 each important element and on each error (mostly missing mandatory
551 parameter).
552
553 When designing a model, you have to ponder for each element:
554
555 • The importance level of the parameter (important, normal or
556 hidden). "level" is used to set how configuration data is presented
557 to the user in wizard and browsing mode. Important elements are
558 shown in the wizard. hidden elements are explained with the warp
559 notion in Creating a model with advanced features.
560
562 Once the model is specified, Config::Model can generate a nice user
563 interface, but there's still no way to load or write the configuration
564 file.
565
566 For Config::Model to read the file, the model designer must declare in
567 the model how to read and write the file (the read/write backend).
568
569 The read/write functionality is provided by a class inheriting
570 "Config::Model::Backend::Any" class like
571 "Config::Model::Backend::IniFile"
572
573 The name of the backend parameter must match the backend class name
574 without "Config::Model::Backend". As syntactic sugar, lower case
575 backend name are transformed into upper case to match the backend class
576 name.
577
578 E.g.
579
580 Yaml -> Config::Model::Backend::Yaml
581 plain_file -> Config::Model::Backend::PlainFile
582 ini_file -> Config::Model::Backend::IniFile
583
584 With the backend name, the following parameters must be defined:
585
586 config_dir
587 The configuration directory
588
589 file
590 Config file name (optional). defaults to
591 "<config_class_name>.[pl|ini|cds]"
592
593 rw_config => { backend => 'ini_file' ,
594 config_dir => '/etc/cfg_dir',
595 file => 'cfg_file.ini',
596 },
597
598 See Config::Model::Backend::IniFile for details
599
600 Note that these parameters can also be set with the graphical
601 configuration model editor ("cme meta edit").
602
603 "rw_config" can also have custom parameters that are passed verbatim to
604 "Config::Model::Backend::Foo" methods:
605
606 rw_config => {
607 backend => 'my_backend',
608 config_dir => '/etc/cfg_dir',
609 my_param => 'my_value',
610 }
611
612 This "Config::Model::Backend::MyBackend" class is expected to inherit
613 Config::Model::Backend::Any and provide the following methods:
614
615 new
616 read
617 write
618
619 Their signatures are explained in Config::Model::BackendMgr doc on
620 plugin backends
621
623 • More complex models: Config::Model::Manual::ModelCreationAdvanced
624
625 • Config::Model::Manual::ModelForUpgrade: Writing a model for
626 configuration upgrades
627
628 • Configuration upgrades within Debian packages
629 <http://wiki.debian.org/PackageConfigUpgrade>
630
632 Feel free to send comments and suggestion about this page at
633
634 config-model-users at lists dot sourceforge dot net.
635
637 Dominique Dumont <ddumont at cpan.org>
638
640 Dominique Dumont
641
643 This software is Copyright (c) 2005-2021 by Dominique Dumont.
644
645 This is free software, licensed under:
646
647 The GNU Lesser General Public License, Version 2.1, February 1999
648
649
650
651perl v5.32.1 Config:2:0M2o1d-e0l1:-:2M7anual::ModelCreationIntroduction(3)