Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Config::Merge(3)      User Contributed Perl Documentation     Config::Merge(3)

NAME
       Config::Merge - load a configuration directory tree containing YAML,
       JSON, XML, Perl,	INI or Config::General files

SYNOPSIS
	  OO style
	  -------------------------------------------------------
	  use Config::Merge();

	  my $config	= Config::Merge->new('/path/to/config');

	  @hosts	= $config->('db.hosts.session');
	  $hosts_ref	= $config->('db.hosts.session');
	  @cloned_hosts	= $config->clone('db.hosts.session');
	  -------------------------------------------------------

       OR

	  Functional style
	  -------------------------------------------------------
	  # On startup
	  use Config::Merge('My::Config' => '/path/to/config');

	  # Then, in any module	where you want to use the config
	  package My::Module;
	  use My::Config;

	  @hosts	= C('db.hosts.sesssion');
	  $hosts_ref	= C('db.hosts.sesssion');
	  @cloned_hosts	= My::Config::clone('db.hosts.session');
	  $config	= My::Config::object;
	  -------------------------------------------------------

       ADVANCED	USAGE

	  OO style
	  -------------------------------------------------------
	  my $config	= Config::Merge->new(
	      path	=> '/path/to/config',
	      skip	=> sub {} | regex | {} ,
	      is_local	=> sub {} | regex | {} ,
	      load_as	=> sub {} | regex ,
	      sort	=> sub {} ,
	      debug	=> 1 | 0
	  );
	  -------------------------------------------------------

	  Functional style
	  -------------------------------------------------------
	  use Config::Merge(
	      'My::Config' => '/path/to/config',
	      {
		  skip	    => sub {} |	regex |	{} ,
		  is_local  => sub {} |	regex |	{} ,
		  load_as   => sub {} |	regex ,
		  sort	    => sub {} ,
		  debug	    => 1 | 0
	      }
	  );

	  # Also, you can subclass these:

	    package My::Config;
	    sub	skip {
		...
	    }

	  -------------------------------------------------------

DESCRIPTION
       Config::Merge is	a configuration	module which has six goals:

       o   Flexible storage

	   Store all configuration in your format(s) of	choice (YAML, JSON,
	   INI,	XML, Perl, Config::General / Apache-style config) broken down
	   into	individual files in a configuration directory tree, for	easy
	   maintenance.
	    See	"CONFIG	TREE LAYOUT"

       o   Flexible access

	   Provide a simple, easy to read, concise way of accessing the
	   configuration values	(similar to Template). See "ACCESSING CONFIG
	   DATA"

       o   Minimal maintenance

	   Specify the location	of the configuration files only	once per
	   application,	so that	it requires minimal effort to relocate.	 See
	   "USING Config::Merge"

       o   Easy	to alter development environment

	   Provide a way for overriding	configuration values on	a development
	   machine, so that differences	between	the dev	environment and	the
	   live	environment do not get copied over accidentally.  See
	   "OVERRIDING CONFIG LOCALLY"

       o   Minimise memory use

	   Load	all config at startup so that (eg in the mod_perl environment)
	   the data is shared between all child	processes. See "MINIMISING
	   MEMORY USE"

       o   Flexible implementation

	   You may want	to use a different schema for your configuration
	   files, so you can pass in (or subclass) methods for determining how
	   your	files are merged.  See "ADVANCED USAGE".

USING "Config::Merge"
       There are two ways to use "Config::Merge":

       OO STYLE
	      use Config::Merge();
	      my $config    = Config::Merge->new('/path/to/config');

	      @hosts	    = $config->('db.hosts.session');
	      $hosts_ref    = $config->('db.hosts.session');
	      @cloned_hosts = $config->clone('db.hosts.session');

	   Also, see "ADVANCED USAGE".

       YOUR OWN	CONFIG CLASS (functional style)
	   The following code:

	      #	On startup
	      use Config::Merge('My::Config' =>	'/path/to/config');

	   o   auto-generates the class	"My::Config"

	   o   loads the configuration data in '/path/to/config'

	   o   creates the subs	"My::Config::C", "My::Config::clone" and
	       "My::Config::object".

	   Then	when you want your application to have access to your
	   configuration data, you add this (eg	in your	class "My::Module"):

	      package My::Module;
	      use My::Config;	    # Note, no ()

	   This	exports	the sub	"C" into your current package, which allows
	   you to access your configuation data	as follows:

	      @hosts	    = C('db.hosts.sesssion');
	      $hosts_ref    = C('db.hosts.sesssion');
	      @cloned_hosts = My::Config::clone('db.hosts.session');
	      $config	    = My::Config::object;

CONFIG TREE LAYOUT
       Config::Merge reads the data from any number (and type) of config files
       stored in a directory tree. File	names and directory names are used as
       keys in the configuration hash.

       It uses file extensions to decide what type of data the file contains,
       so:

	   YAML		   : .yaml .yml
	   JSON		   : .json .jsn
	   XML		   : .xml
	   INI		   : .ini
	   Perl		   : .perl .pl
	   Config::General : .conf .cnf

       When loading your config	data, Config::Merge starts at the directory
       specified at startup (see "USING	Config::Merge")	and looks through all
       the sub-directories for files ending in one of the above	extensions.

       The name	of the file or subdirectory is used as the first key.  So:

	   global/
	       db.yaml:
		   username : admin
		   hosts:
			    - host1
			    - host2
		   password:
		     host1:   password1
		     host2:   password2

       would be	loaded as :

	   $Config = {
	      global =>	{
		  db =>	{
		      username => 'admin',
		      password => { host1 => 'password1', host2	=> 'password2'},
		      hosts    => ['host1','host2'],
		  }
	      }
	   }

       Subdirectories are processed before the current directory, so you can
       have a directory	and a config file with the same	name, and the values
       will be merged into a single hash, so for instance, you can have:

	   confdir:
	      syndication/
	      --data_types/
		--traffic.yaml
		--headlines.yaml
	      --data_types.ini
	      syndication.conf

       The config items	in syndication.conf will be added to (or overwrite)
       the items loaded	into the syndication namespace via the subdirectory
       called syndication.

OVERRIDING CONFIG LOCALLY
       The situation often arises where	it is necessary	to specify different
       config values on	different machines. For	instance, the database host on
       a dev machine may be different from the host on the live	application.
       Also, see "ADVANCED USAGE" which	provides you with other	means to merge
       local data.

       Instead of changing this	data during dev	and then having	to remember to
       change it back before putting the new code live,	we have	a mechanism
       for overriding config locally in	a "local.*" file and then, as long as
       that file never gets uploaded to	live, you are protected.

       You can put a file called "local.*" (where * is any of the recognised
       extensions) in any sub-directory, and the data in this file will	be
       merged with the existing	data.

       Just make sure that the "local.*" files are never checked into your
       live code.

       For instance, if	we have:

	   confdir:
	       db.yaml
	       local.yaml

       and db.yaml has :

	   connections:
	       default_settings:
		   host:       localhost
		   table:      abc
		   password:   123

       And in local.yaml:

	   db:
	       connections:
		   default_settings:
		       password:   456

       the resulting configuration will	look like this:

	   db:
	       connections:
		   default_settings:
		       host:	   localhost
		       table:	   abc
		       password:   456

ACCESSING CONFIG DATA
       All configuration data is loaded	into a single hash, eg:

	   $config = {
	       db    =>	{
		   hosts  => {
		       session	=> ['host1','host2','host3'],
		       images	=> ['host1','host2','host3'],
		       etc...
		   }
	       }
	   }

       If you want to access it	via standard Perl dereferences,	you can	just
       ask for the hash:

	   OO:
	      $data_ref	 = $config->();
	      $hosts_ref = $data_ref->{db}{hosts}{session};
	      $host_1	 = $data_ref->{db}{hosts}{session}[0];

	   Functional:
	      $data_ref	 = C();
	      $hosts_ref = $data_ref->{db}{hosts}{session};
	      $host_1	 = $data_ref->{db}{hosts}{session}[0];

       However,	"Config::Merge"	also provides an easy to read dot-notation in
       the style of Template Toolkit: "('key1.key2.keyn')".

       A key can be the	key of a hash or the index of an array.	The return
       value is	context	sensitive, so if called	in list	context, a hash	ref or
       array ref will be dereferenced.

	   OO:
	      @hosts	 = $config->('db.hosts.session');
	      $hosts_ref = $config->('db.hosts.session');
	      $host_1	 = $config->('db.hosts.session.0');

	   Functional:
	      @hosts	 = C('db.hosts.session');
	      $hosts_ref = C('db.hosts.session');
	      $host_1	 = C('db.hosts.session.0');

       These lookups are memo'ised, so lookups are fast.

       If the specified	key is not found, then an error	is thrown.

MINIMISING MEMORY USE
       The more	configuration data you load, the more memory you use. In order
       to keep the memory use as low as	possible for mod_perl (or other
       forking applications), the configuration	data should be loaded at
       startup in the parent process.

       As long as the data is never changed by the children, the configuration
       hash will be stored in shared memory, rather than there being a
       separate	copy in	each child process.

       (See
       <http://search.cpan.org/~pgollucci/mod_perl-2.0.3/docs/user/performance/mpm.pod>)

METHODS
       "new()"
	       $conf = Config::Merge->new($config_dir);

	   new() instantiates a	config object, loads the config	from the
	   directory specified,	and returns the	object.

       "C()"
	     $val = $config->C('key1.key2.keyn');
	     $val = $config->C('key1.key2.keyn',$hash_ref);

	   "Config::Merge" objects are overloaded so that this also works:

	     $val = $config->('key1.key2.keyn');
	     $val = $config->('key1.key2.keyn',$hash_ref);

	   Or, if used in the functional style (see "USING Config::Merge"):

	     $val = C('key1.key2.keyn');
	     $val = C('key1.key2.keyn',$hash_ref);

	   "key1" etc can be keys in a hash, or	indexes	of an array.

	   "C('key1.key2.keyn')" returns everything from "keyn"	down, so you
	   can use the return value just as you	would any normal Perl
	   variable.

	   The return values are context-sensitive, so if called in list
	   context, an array ref or hash ref will be returned as lists.
	   Scalar values, code refs, regexes and blessed objects will always
	   be returned as themselves.

	   So for example:

	     $password = C('database.main.password');
	     $regex    = C('database.main.password_regex');

	     @countries	= C('lists.countries');
	     $countries_array_ref = C('lists.countries');

	     etc

	   If called with a hash ref as	the second parameter, then that	hash
	   ref will be examined, rather	than the $config data.

       "clone()"
	   This	works exactly the same way as "C()" but	it performs a deep
	   clone of the	data before returning it.

	   This	means that the returned	data can be changed without affecting
	   the data stored in the $conf	object;

	   The data is deep cloned, using Storable, so the bigger the data,
	   the more performance	hit.  That said, Storable's dclone is very
	   fast.

       "register_loader()"
	       Config::Merge->register_loader( 'Config::Merge::XYZ');

	       Config::Merge->register_loader( 'Config::Merge::XYZ' => 'xyz','xxx');

	   By default, "Config::Merge" uses the	"Config::Any" plugins to
	   support YAML, JSON, INI, XML, Perl and Config::General
	   configuration files,	using the standard file	extensions to
	   recognise the file type. (See "CONFIG TREE LAYOUT").

	   If you would	like to	change the handler for an extension (eg, you
	   want	".conf"	and ".cnf" files to be treated as YAML), do the
	   following:

	       Config::Merge->register_loader ('Config::Any::YAML' => 'conf', 'cnf');

	   If you would	like to	add a new config style,	then your module
	   should have two methods: "extensions()" (which returns a list of
	   the extensions it handles), and "load()" which accepts the name of
	   the file to load, and returns a hash	ref containing the data	in the
	   file. See Config::Any for details.

	   Alternatively, you can specify the extensions when you load it:

	       Config::Merge->register_loader ('My::Merge' => 'conf', 'cnf');

       "load_config()"
	       $config->load_config();

	   Will	reload the config files	located	in the directory specified at
	   object creation (see	"new()").

	   BEWARE : If you are using this in a mod_perl	environment, you will
	   lose	the benefit of shared memory by	calling	this in	a child
	   process
	    - each child will have its own copy	of the data.  See "MINIMISING
	   MEMORY USE".

	   Returns the config hash ref.

       "clear_cache()"
	       $config->clear_cache();

	   Config data is generally not	supposed to be changed at runtime.
	   However, if you do make changes, you	may get	inconsistent results,
	   because lookups are cached.

	   For instance:

	       print $config->C('db.hosts.session');  #	Caches this lookup
	       > "host1	host2 host3"

	       $data = $config->C('db.hosts');
	       $data->{session}	= 123;

	       print $config->C('db.hosts.session'); # uses cached value
	       > "host1	host2 host3"

	       $config->clear_cache();
	       print $config->C('db.hosts.session'); # uses actual value
	       > "123"

       "import()"
	   "import()" will normally be called automatically when you "use
	   Config::Merge". However, you	may want to do this:

	       use Config::Merge();
	       Config::Merge->register_loader('My::Plugin' => 'ext');
	       Config::Merge->import('My::Config' => '/path/to/config/dir');

	   If called with two params: $config_class and	$config_dir, it
	   generates the new class (which inherits from	Config::Merge)
	   specified in	$config_class, creates a new object of that class and
	   creates 4 subs:

	   "C()"
		   As a	function:
		       C('keys...')

		   is the equivalent of:
		       $config->C('keys...');

	   "clone()"
		   As a	function:
		       clone('keys...')

		   is the equivalent of:
		       $config->clone('keys...');

	   "object()"
		   $config = My::Config->object();

	       Returns the $config object,

	   "import()"
	       When you	use your generated config class, it exports the	"C()"
	       sub into	your package:

		   use My::Config;
		   $hosts = C('db.hosts.session');

ADVANCED USAGE
       The items in the	section	allow you to customise how Config::Merge loads
       your data.  You may never need them.

       You can:

       o   Override array values

       o   Skip	the loading of parts of	your config tree

       o   Specify which files / dirs are local

       o   Specify how to translate a file / dir name into a key

       o   Change order	in which files are loaded

       o   See debug output

       Overriding array	values
	   Overriding hash values is easy, however arrays are more complex.
	   it may be simpler to	copy and paste and edit	the array you want to
	   change locally.

	   However, if your array is too long, and you want to make small
	   changes, then you can use the following:

	   In the main config:

	       {
		 cron => [qw( job1 job2	job3 job4)]
	       }

	   In the local	file

	       {
		 cron => {
		   '3'	=> 'newjob4',	   # changes 'job4' -> 'newjob4'

		   '!'	=> {		   # signals an	array override

			'-' => [1],	   # deletes 'job2'

			'+' => ['job5'],   # appends 'job5'

		     OR	'+' => {	   # inserts 'job3a' after 'job3'
			    2 => 'job3a'
			}
		   }
	       }

	   o   The override has	to be a	hash, with at least this structure
		"{ '!' => {} }"	to signal an array override

	   o   Any other keys with integers are	treated	as indexes and are
	       used to change the value	at that	index in the original array

	   o   The '-' key should contain an array ref,	with the indexes of
	       the elements to remove from the array.

	   o   If the '+' key contains an array	ref, then its contents are
	       appended	to the original	array.

	   o   If the '+' key contains a hash ref, then	each value is inserted
	       into the	original array at the index given in the key

	   o   Indexes are zero	based, just as in Perl.

       "skip()"
	       $c = Config::Merge->new(
		       path  =>	'/path/to/config',
		       skip  =>	qr/regex/,
				| [ qr/regex1/,	qr/regex2/...]
				| {  name1 => 1, name2 => 2}
				| sub {}
	       );

	   "skip()" allows you to skip the loading of parts of your config
	   tree.  For instance,	if you don't need a list of cron jobs when
	   running your	web server, you	can skip it.

	   The decision	is made	based on the path to that value, eg
	   'app.db.hosts' rather than on filenames. Also, the check is only
	   performed for each new directory or filename	- it doesn't check the
	   data	within each file.

	   To use "skip()", you	can either subclass it,	or pass	in a parameter
	   to new:

	   "qr/regex/" or "[qr/regex1/,	qr/regex2]"
	       Each regex will be checked against the key path,	and if it
	       matches then the	loading	of that	tree will be skipped

	   "{key_path => 1}"
	       If the key path exists in the hash, then	loading	will be
	       skipped

	   "sub	{}" or subclassed "skip"
		  sub {
		      my ($self,$key_path) = @_;
		      ...make decision...
		      return 1 | 0;
		  }

       "is_local()"
	       $c = Config::Merge->new(
		       path	=> '/path/to/config',
		       is_local	=> qr/regex/,
				   | [ qr/regex1/, qr/regex2/...]
				   | {	name1 => 1, name2 => 2}
				   | sub {}
	       );

	   "is_local()"	indicates whether a file or dir	should be considered
	   part	of the main config (and	thus loaded normally) or part of the
	   local config	(and thus merged into the main config).

	   The decision	is made	based on the name of the file /	dir, without
	   any extension.

	   To use "is_local()",	you can	either subclass	it, or pass in a
	   parameter to	new:

	   "qr/regex/" or "[qr/regex1/,	qr/regex2]"
	       Each regex will be checked against the file/dir name, and if it
	       matches then that tree will be merged

	   "{filename => 1, dirname => 1}"
	       If the file/dir name exists in the hash,	then that tree will be
	       merged

	   "sub	{}" or subclassed "is_local"
		  sub {
		      my ($self,$name) = @_;
		      ...make decision...
		      return 1 | 0;
		  }

	   See "EXAMPLE	USING is_local() AND load_as()".

       "load_as()"
	       $c = Config::Merge->new(
		       path	=> '/path/to/config',
		       load_as	=> qr/(regex)/,
				   | sub {}
	       );

	   "load_as()" returns the name	of the key to use when loading the
	   file	/ dir. By default, it returns the $name	for main config	files,
	   or '' for local files.

	   The decision	is made	based on the name of the file /	dir, without
	   any extension.

	   If "load_as()" returns an empty string, then	each key in the
	   file/tree is	merged separately. This	is how the "local.*" files
	   work	by default.  See "OVERRIDING CONFIG LOCALLY".

	   For instance:

	      main.yaml:
		key1:  value
		key2:  value

	      db.yaml:
		key3:  value
		key4:  value

	      local.yaml:
		main:
		   key1: new_value
		db:
		   key4: new_value

	   To use "load_as()", you can either subclass it, or pass in a
	   parameter to	new:

	   "qr/(regex)/"
	       The regex will be checked against the file/dir name, and	if it
	       matches then it returns the string captured in the regex,
	       otherwise it returns the	original name.

	   "sub	{}" or subclassed "is_local"
		  sub {
		      my ($self,$name,$is_local) = @_;
		      ...make decision...
		      return 'string';	 # string is used as the keyname
		      return '';	 # acts	like local.* (see above)
		      return undef;	 # don't load this file/dir
		  }

	   Also, see "EXAMPLE USING is_local() AND load_as()".

       EXAMPLE USING "is_local()" AND "load_as()"
	   For instance, instead of using "local.*" files, you may want	to
	   keep	versioned copies of local configs for different	machines, and
	   so use:

	      app.yaml
	      app-(dev1.domain.com).yaml
	      app-(dev2.domain.com).yaml

	   You would implement this as follows:

	       my $config = Config::Merge->new(
		   path	       => '/path/to/config',

		   # If	matches	'xxx-(yyy)'
		   is_local    => sub {
		       my ( $self, $name ) = @_;
		       return $name=~/-	[(] .+ [)]/x ? 1 : 0;
		   },

		   # If	local and matches 'xxx-(hostname)', return xxx
		   load_as => sub {
		       my ( $self, $name, $is_local ) =	@_;
		       if ($is_local) {
			   if (	$name=~/(.*) - [(] ($hostname) [)] /x )	{
			       return  $1;
			   }
			   return undef;
		       }
		       return $name;
		   }
	       );

	   See "examples/advanced.pl" for a working illustration.

       "sort()"
	       $c = Config::Merge->new(
		       path   => '/path/to/config',
		       sort   => sub {}
	       );

	   By default, directory entries are sorted alphabetically, with
	   directories before filenames.

	   This	would be the order for these directory entries:

	     api/
	     api-(dev1)/
	     api.yaml
	     api-(dev1).yaml

	   To override this, you can subclass "sort()" or pass it in as	a
	   parameter to	new:

	      sub {
		  my ($self,$names_array_ref) =	@_
		  ...sort...
		  return $names_array_ref;
	      }

       "debug()"
	       my $config = Config::Merge->new(
		   path	       => '/path/to/config',
		   debug       => 1 | 0
	       );

	   If "debug" is true, then Config::Merge prints out an	explanation of
	   what	it is doing on STDERR.

SEE ALSO
       Storable, Config::Any, Config::Any::YAML, Config::Any::JSON,
       Config::Any::INI, Config::Any::XML, Config::Any::General

THANKS
       Thanks to Hasanuddin Tamir [HASANT] for vacating	the Config::Merge
       namespace, which	allowed	me to rename Config::Loader to the more
       meaningful Config::Merge.

       His version of Config::Merge can	be found in
       <http://backpan.cpan.org/modules/by-authors/id/H/HA/HASANT/>.

       Thanks to Joel Bernstein	and Brian Cassidy for the interface to the
       various configuration modules. Also to Ewan Edwards for his suggestions
       about how to make Config::Merge more flexible.

BUGS
       No bugs have been reported.

       Please report any bugs or feature requests to
       <http://github.com/clintongormley/ConfigMerge/issues>.

AUTHOR
       Clinton Gormley,	<clinton@traveljury.com>

COPYRIGHT
       Copyright (C) 2007-2010 by Clinton Gormley

LICENSE
       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself, either Perl	version	5.8.7 or, at
       your option, any	later version of Perl 5	you may	have available.

perl v5.24.1			  2014-08-25		      Config::Merge(3)

NAME | SYNOPSIS | DESCRIPTION | USING "Config::Merge" | CONFIG TREE LAYOUT | OVERRIDING CONFIG LOCALLY | ACCESSING CONFIG DATA | MINIMISING MEMORY USE | METHODS | ADVANCED USAGE | SEE ALSO | THANKS | BUGS | AUTHOR | COPYRIGHT | LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Config::Merge&sektion=3&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help