|
NAMEConfig::Model - a framework to validate, migrate and edit configuration filesVERSIONversion 2.149SYNOPSISPerl program to use an existing modeluse Config::Model qw(cme); # load, modify and save popcon configuration file cme('popcon')->modify("PARTICIPATE=yes"); Command line to use an existing model# with App::Cme cme modify popcon 'PARTICIPATE=yes' Perl program with a custom modeluse Config::Model; # create new Model object my $model = Config::Model->new() ; # Config::Model object # create config model. A more complex model should be stored in a # file in lib/Config/Model/models. Then, run cme as explained below $model ->create_config_class ( name => "MiniModel", element => [ [qw/foo bar baz/ ] => { type => 'leaf', value_type => 'uniline' }, ], rw_config => { backend => 'IniFile', auto_create => 1, config_dir => '.', file => 'mini.ini', } ) ; # create instance (Config::Model::Instance object) my $instance = $model->instance (root_class_name => 'MiniModel'); # get configuration tree root my $cfg_root = $instance -> config_root ; # C::M:Node object # load some dummy data $cfg_root -> load("bar=BARV foo=FOOV baz=BAZV") ; # write new ini file $instance -> write_back; # now look for new mini.ini file un current directory Create a new model file and use it$ mkdir -p lib/Config/Model/models/ $ echo "[ { name => 'MiniModel', \ element => [ [qw/foo bar baz/ ] => { type => 'leaf', value_type => 'uniline' }, ], \ rw_config => { backend => 'IniFile', auto_create => 1, \ config_dir => '.', file => 'mini.ini', \ } \ } \ ] ; " > lib/Config/Model/models/MiniModel.pl # require App::Cme $ cme modify -try MiniModel -dev bar=BARV foo=FOOV baz=BAZV $ cat mini.ini Note that model creation is easier running "cme meta edit" with App::Cme and Config::Model::Itself. DESCRIPTIONConfig::Model enables a project developer to provide an interactive configuration editor (graphical, curses based or plain terminal) to users.To provide these tools, Config::Model needs:
With the elements above, Config::Model generates interactive configuration editors (with integrated help and data validation). These editors can be graphical (with Config::Model::TkUI), curses based (with Config::Model::CursesUI) or based on ReadLine. Smaller models targeted for configuration upgrades can also be created:
A command line is provided to perform configuration upgrade with a single command. How does this work ?Using this project, a typical configuration editor/validator/upgrader is made of 3 parts :GUI <--------> |---------------| CursesUI <---> | |---------| | | | Model | | ShellUI <----> | |---------| |<-----read-backend------- |-------------| | |----write-backend-------> | config file | FuseUI <-----> | Config::Model | |-------------| |---------------|
The important part is the configuration model used by the validation engine. This model can be created or modified with a graphical editor (Config::Model::Iself). Question you may ask yourselfDon't we already have some configuration validation tools ?You're probably thinking of tools like webmin. Yes, these tools exist and work fine, but they have their set of drawbacks.Usually, the validation of configuration data is done with a script which performs semantic validation and often ends up being quite complex (e.g. 2500 lines for Debian's xserver-xorg.config script which handles "xorg.conf" file). In most cases, the configuration model is expressed in instructions (whatever programming language is used) and interspersed with a lot of processing to handle the actual configuration data. What's the advantage of this project ?Config::Model projects provide a way to get a validation engine where the configuration model is completely separated from the actual processing instructions.A configuration model can be created and modified with the graphical interface provide by Config::Model::Itself. The model is saved in a declarative form (currently, a Perl data structure). Such a model is easier to maintain than a lot of code. The model specifies:
So, in the end:
What about the user interface ?Config::Model interface can be:
All these interfaces are generated from the configuration model. And configuration model can be created or modified with a graphical user interface (with "cme meta edit" once Config::Model::Itself is installed) What about configuration data storage ?Since the syntax of configuration files vary wildly form one application to another, people who want to use this framework may have to provide a dedicated parser/writer.To help with this task, this project provides writer/parsers for common format: INI style file and perl file. With the additional Config::Model::Backend::Augeas, Augeas library can be used to read and write some configuration files. See http://augeas.net for more details. Is there an example of a configuration model ?The "example" directory contains a configuration model example for "/etc/fstab" file. This example includes a small program that use this model to show some ways to extract configuration information.Mailing listsFor more question, please send a mail to:config-model-users at lists.sourceforge.net Suggested reads to startBeginners
Advanced
Mastersuse the source, LukeSTOPThe documentation below is quite detailed and is more a reference doc regarding "Config::Model" class.For an introduction to model creation, please check: Config::Model::Manual::ModelCreationIntroduction Storage backend, configuration reader and writerSee Config::Model::BackendMgr for detailsValidation engine"Config::Model" provides a way to get a validation engine from a set of rules. This set of rules is called the configuration model.User interfaceThe user interface uses some parts of the API to set and get configuration values. More importantly, a generic user interface needs to analyze the configuration model to be able to generate at run-time relevant configuration screens.A command line interface is provided in this module. Curses and Tk interfaces are provided by Config::Model::CursesUI and Config::Model::TkUI. Constructormy $model = Config::Model -> new ; creates an object to host your model. Constructor parameters
Configuration ModelTo validate a configuration tree, we must create a configuration model that defines all the properties of the validation engine you want to create.The configuration model is expressed in a declarative form (i.e. a Perl data structure which should be easier to maintain than a lot of code) Each configuration class may contain a set of:
The structure of your configuration tree is shaped by the a set of configuration classes that are used in node elements, The structure of the configuration data must be based on a tree structure. This structure has several advantages:
But using a tree has also some drawbacks:
Note: a configuration tree is a tree of objects. The model is declared with classes. The classes themselves have relations that closely match the relation of the object of the configuration tree. But the class need not to be declared in a tree structure (always better to reuse classes). But they must be declared as a DAG (directed acyclic graph). See also Directed acyclic graph on Wikipedia <http://en.wikipedia.org/wiki/Directed_acyclic_graph">More on DAGs> Each configuration class declaration specifies:
Each element specifies:
See Config::Model::Node for details on how to declare a configuration class. Example: $ cat lib/Config/Model/models/Xorg.pl [ { name => 'Xorg', class_description => 'Top level Xorg configuration.', include => [ 'Xorg::ConfigDir'], element => [ Files => { type => 'node', description => 'File pathnames', config_class_name => 'Xorg::Files' }, # snip ] }, { name => 'Xorg::DRI', element => [ Mode => { type => 'leaf', value_type => 'uniline', description => 'DRI mode, usually set to 0666' } ] } ]; Configuration instance methodsA configuration instance is created from a model and is the starting point of a configuration tree.instanceAn instance must be created with a model name (using the root class name) or an application name (as shown by "cme "list"" command).For example: my $model = Config::Model->new() ; $model->instance( application => 'approx'); Or: my $model = Config::Model->new() ; # note that the model class is slightly different compared to # application name $model->instance( root_class_name => 'Approx'); A custom configuration class can also be used with "root_class_name" parameter: my $model = Config::Model->new() ; # create_config_class is described below $model ->create_config_class ( name => "SomeRootClass", element => [ ... ] ) ; # instance name is 'default' my $inst = $model->instance (root_class_name => 'SomeRootClass'); You can create several separated instances from a model using "name" option: # instance name is 'default' my $inst = $model->instance ( root_class_name => 'SomeRootClass', name => 'test1' ); Usually, model files are loaded automatically using a path matching "root_class_name" (e.g. configuration class "Foo::Bar" is stored in "Foo/Bar.pl". You can choose to specify the file containing the model with "model_file" parameter. This is mostly useful for tests. The "instance" method can also retrieve an instance that has already been created: my $inst = $model->instance( name => 'test1' ); get_instanceRetrieve an existing instance using its name.my $inst = $model->get_instance('test1' ); has_instanceCheck if an instance name already existsmy $maybe = $model->has_instance('test1'); cmeThis method is syntactic sugar for short program. It creates a new "Config::Model" object and returns a new instance."cme" arguments are passed to "instance" method, except "force-load". Like cme command, "cme" functions accepts "force-load" parameters. When this argument is true, the instance is created with "check =" 'no'>. Hence bad values are stored in "cme" and must be corrected before saving back the data. Configuration classA configuration class is made of series of elements which are detailed in Config::Model::Node.Whatever its type (node, leaf,... ), each element of a node has several other properties:
Note that include may not clobber an existing read/write specification. create_config_classThis method creates configuration classes. The parameters are described above and are forwarded to Config::Model::Node constructor. See "Configuration class declaration" in Config::Model::Node for more details on configuration class parameters.Example: my $model = Config::Model -> new ; $model->create_config_class ( config_class_name => 'SomeRootClass', description => [ X => 'X-ray' ], level => [ 'tree_macro' => 'important' ] , class_description => "SomeRootClass description", element => [ ... ] ) ; For convenience, "level" and "description" parameters can also be declared within the element declaration: $model->create_config_class ( config_class_name => 'SomeRootClass', class_description => "SomeRootClass description", 'element' => [ tree_macro => { level => 'important'}, X => { description => 'X-ray', } , ] ) ; Load predeclared modelYou can also load predeclared model.load( <model_name> )This method opens the model directory and execute a ".pl" file containing the model declaration,This perl file must return an array ref to declare models. E.g.: [ [ name => 'Class_1', element => [ ... ] ], [ name => 'Class_2', element => [ ... ] ] ]; do not put "1;" at the end or "load" will not work When a model name contain a "::" (e.g "Foo::Bar"), "load" looks for a file named "Foo/Bar.pl". This method also searches in "Foo/Bar.d" directory for additional model information. Model snippet found there are loaded with augment_config_class. Returns a list containing the names of the loaded classes. For instance, if "Foo/Bar.pl" contains a model for "Foo::Bar" and "Foo::Bar2", "load" returns "( 'Foo::Bar' , 'Foo::Bar2' )". augment_config_class (name => '...', class_data )Enhance the feature of a configuration class. This method uses the same parameters as create_config_class. See "Model Plugin" in Config::Model::Manual::ModelCreationAdvanced for more details on creating model plugins.Model querymodelReturns a hash containing the model declaration of the passed model name. Do not modify the content of the returned data structure.my $cloned = $model->model('Foo'); get_model_cloneLike "model", returns a hash containing the model declaration of the passed model name, this time in a deep clone of the data structure.my $cloned = $model->get_model_clone('Foo'); generate_doc ( top_class_name , directory , [ \%done ] )Generate POD document for configuration class top_class_name and all classes used by top_class_name, and write them in specified directory."\%done" is an optional reference to a hash used to avoid writing twice the same documentation when this method is called several times. get_element_model( config_class_name , element)Return a hash containing the model declaration for the specified class and element.get_element_name( class => Foo )Get all names of the elements of class "Foo".get_element_propertyReturns the property of an element from the model.Parameters are:
list_class_elementReturns a string listing all the class and elements. Useful for debugging your configuration model.Error handlingErrors are handled with an exception mechanism.When a strongly typed Value object gets an authorized value, it raises an exception. If this exception is not caught, the programs exits. See Config::Model::Exception for details on the various exception classes provided with "Config::Model". LoggingSee "Logging" in cmeinitialize_log4perlThis method can be called to load Log::Log4perl configuration from "~/.log4config-model", or from "/etc/log4config-model.conf" files or from default configuration <https://github.com/dod38fr/config-model/blob/master/lib/Config/Model/log4perl.conf>.Accepts "verbose" parameter with a list of log classes that are added to the log4perl configuration read above. For instance, with "verbose => 'Loader'", log4perl is initialised with log4perl.logger.Verbose.Loader = INFO, PlainMsgOnScreen Likewise, with "verbose => [ 'Loader', 'Foo' ]", log4perl is initialised with: log4perl.logger.Verbose.Loader = INFO, PlainMsgOnScreen log4perl.logger.Verbose.Foo = INFO, PlainMsgOnScreen Currently, this module supports only "Loader" as verbose parameters. BUGSGiven Murphy's law, the author is fairly confident that you will find bugs or miss some features. Please report them to https://github.com/dod38fr/config-model/issues The author will be notified, and then you'll automatically be notified of progress on your bug.FEEDBACKFeedback from users are highly desired. If you find this module useful, please share your use cases, success stories with the author or with the config-model- users mailing list.PROJECT FOUNDERDominique Dumont, "ddumont@cpan.org"CREDITSContributors to this project are listed in alphabetical order:Harley Pig Ilya Arosov Jose Luis Perez Diez Krzysztof Tyszecki Mathieu Arnold Mohammad S Anwar Topi Miettinen Many thanks for your help SEE ALSOConfig::Model::Instance,<https://github.com/dod38fr/config-model/wiki> <https://github.com/dod38fr/config-model/wiki/Creating-models> Model elementsThe arrow shows inheritance between classes
command linecme.Read and write backends
Model utilities
Test framework
AUTHORDominique DumontCOPYRIGHT AND LICENSEThis software is Copyright (c) 2005-2022 by Dominique Dumont.This is free software, licensed under: The GNU Lesser General Public License, Version 2.1, February 1999 SUPPORTWebsitesThe following websites have more information about this module, and may be of help to you. As always, in addition to those websites please use your favorite search engine to discover more resources.
Bugs / Feature RequestsPlease report any bugs or feature requests by email to "ddumont at cpan.org", or through the web interface at <https://github.com/dod38fr/config-model/issues>. You will be automatically notified of any progress on the request by the system.Source CodeThe code is open to the world, and available for you to hack on. Please feel free to browse it and play with it, or whatever. If you want to contribute patches, please send me a diff or prod me to pull from your repository :)<http://github.com/dod38fr/config-model> git clone git://github.com/dod38fr/config-model.git
Visit the GSP FreeBSD Man Page Interface. |