1Config::Model::Manual::UMsoedrelCCCoornnetfaritigib:ou:ntMIeonddterPloe:dr:ulMcatDniouocanul(m:3e:)nMtoadteiloCnreationIntroduction(3)
2
3
4

NAME

6       Config::Model::Manual::ModelCreationIntroduction - Introduction to
7       model creation with Config::Model
8

VERSION

10       version 2.150
11

Introduction

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

Some definitions

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

What is a configuration tree?

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

What is a model?

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

Model analysis

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

Model declaration

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

Configuration wizard

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

Reading configuration files

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

SEE ALSO

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

Feedback welcome

632       Feel free to send comments and suggestion about this page at
633
634        config-model-users at lists dot sourceforge dot net.
635

AUTHORS

637       Dominique Dumont <ddumont at cpan.org>
638

AUTHOR

640       Dominique Dumont
641
643       This software is Copyright (c) 2005-2022 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.34.1               Config:2:0M2o2d-e0l5:-:0M9anual::ModelCreationIntroduction(3)
Impressum