Config::Layered - Layered config from files, command line, and other sources.
Config::Layered aims to make it easy for programmers, operations teams and those who run the programs to have the configuration methods they prefer with one simple interface.
By default options will be taken from the program source code itself, then -- if provided -- a configuration file, and finally command-line options.
By default options will be taken from the program source code itself, then merged -- if provided -- with a configuration file, then environment variables in the form of CONFIG_$OPTIONNAME and finally command-line options.
CONFIG_$OPTIONNAME
my $config = Config::Layered->load_config( file => "/etc/myapp", default => { verbose => 0, run => 1, input => "/tmp/to_process", output => "/tmp/done_processing", plugins => [ qw( process ) ] }, );
Given the above, the data structure would look like:
{ verbose => 0, run => 1, input => "/tmp/to_process", output => "/tmp/done_processing", plugins => [ qw( process ) ] }
Provided a file, /etc/myapp.yml with the line input: /tmp/pending_process the data structure would look like:
/etc/myapp.yml
input: /tmp/pending_process
{ verbose => 0, run => 1, input => "/tmp/pending_process", output => "/tmp/done_processing", plugins => [ qw( process ) ] }
Provided the command line arguments --norun --verbose --output /tmp/completed_process -- in addition to the configuration file above -- the data structure would look like:
--norun --verbose --output /tmp/completed_process
{ verbose => 1, run => 0, input => "/tmp/pending_process", output => "/tmp/completed_process", plugins => [ qw( process ) ] }
Provided the environment variable CONFIG_INPUT="/tmp/awaiting_process -- in addition to the configuration file above -- the data structure would look like:
CONFIG_INPUT="/tmp/awaiting_process
{ verbose => 1, run => 0, input => "/tmp/awaiting_process", output => "/tmp/completed_process", plugins => [ qw( process ) ] }
file
By default the file given here will be loaded by Config::Any and the data structure provided will be merged ontop of the default data structure.
Example:
file => "/etc/myapp",
This will atempt to load /etc/myapp as a stem in Config::Any, meanig files like /etc/myapp.yml, /etc/myapp.conf, /etc/myapp.ini and such will be checked for existence.
/etc/myapp
/etc/myapp.conf
/etc/myapp.ini
default
This is the default data structure that Config::Layered will load.
default => { verbose => 1, run => 0, },
The above data structure will have $config->{verbose} set to 1, and $config->{run} set to 0 if there are no configuration files, and no command line options used.
$config->{verbose}
$config->{run}
sources
A source returns an instance of configuration to merge with previously loaded sources. Following a source a specific configuration may be sent the to source.
Example
sources => [ 'ConfigAny', { file => "/etc/myapp }, 'Getopts' ]
In the above example, Config::Layered::Sources::ConfigAny will be loaded, and the following hashref will be sent to the source. This allows source-specific configuration to be used. For more information on creating a soure, see "CREATING A SOURCE".
merge
You may provide a method as a coderef that will be used to merge the data structures returned from a source together. By default the method used favors the newer sources that are loaded.
merge => sub { my ( $lhs, $rhs ) = @_; ... Do something with the data structures ... return $merged_data_structure; }
Each source provides its own documentation for source-specific options, please see the POD pages for the source you're interested in learning more about
Config::Layered::Source::ConfigAny is used for configuration files
Config::Layered::Source::ENV is used for environment variables
Config::Layered::Sources::Getopt is used for command-line options
If you would like to create your own source to provide a configuration method, the following documents the creation of a source. You can also check Config::Layered::Source::ConfigAny for a source that is used by default.
A source requires at least two methods, new and get_config.
new
get_config
The new method should take the following arguments and return an instance of itself:
$layered is the instance of Config::Layered which called it. You may look at all arguments given at construction of the instance.
$layered
$arguments is the source-specific configuration information. You should NOT parse $config->sources yourself, instead look at $arguments, and optionally fall-back to using information in $layered to make decisions.
$arguments
$config->sources
sub new { my ( $class, $layered, $args ) = @_; my $self = bless { layered => $layered, args => $args }, $class; return $self; }
The get_config method is given no arguments, and expected to return a hashref that is merged with previous sources, and will be merged over by future sources.
sub get_config { my ( $self ) = @_; # Load a specific file with Config::Any if ( exists $self->{args}->{file} ) { return Config::Any->load_file( { file => $self->{args}->{file} ); # Otherwise, load the global file with Config::Any } elsif ( exists $config->{layered}->{file} ) return Config::Any->load_file( { file => $self->{layered}->{file} ); } # No configuration file, our source is being ignored. return {}; }
Config::Layered will accept any constructor arguments and a source may look at $layered to check them. However, source instance specific arguments are also available. Both should be supported under the following reasoning:
Suppose that I would like to load a global file, but I would also like to merge arguments from a configuration file in my home directory. With only global arguments this isn't possible. With source-specific arguments, this is easily enabled:
my $config = Config::Layered->get_config( sources => [ 'ConfigAny', { file => "/etc/myapp" }, 'ConfigAny', { file => $ENV{"HOME"} . "/.myapp", ] , );
Global arguments are useful in the context that writing out the data structure for the default use-cases and single-use sources can be tedious.
Kaitlyn Parkhurst (SymKat) <symkat@symkat.com> (http://symkat.com/)
Copyright (c) 2012 the Config::Layered "AUTHOR" and "CONTRIBUTORS" as listed above.
This library is free software and may be distributed under the same terms as perl itself.
The latest version of this software is available at https://github.com/symkat/Config-Layered
2 POD Errors
The following errors were encountered while parsing the POD:
Unknown directive: =over4
'=item' outside of any '=over'
To install Config::Layered, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Config::Layered
CPAN shell
perl -MCPAN -e shell install Config::Layered
For more information on module installation, please visit the detailed CPAN module installation guide.