Optconfig - Configure and parse command-line options
# Invoking an optconfig program
program [options] arguments...
--config=file Use file for configuration
--verbose Produce verbose output
--dry-run Do a dry run (don't change things)
--version Print program version number
--help Print usage message
--debug Produce debugging output
Some programs will have options specific to them
# In optconfig program
use Optconfig;
# Configuration is read from
my $opt = Optconfig->new('domain', { 'force!' => 0,
'logfile=s' => '/var/log/foo',
'define=s%' });
unlink($filefoo) if $opt->{'force'};
open(my $fh, '>', $opt->{'logfile'}) and print $fh, "Message\n";
for my $key (keys %{$opt->{'define'}}) {
print "$key = $opt->{'define'}->{$key}\n";
}
The Optconfig module looks in various places for its configuration. It will read configuration from one of $HOME/.domain
, /usr/local/etc/domain.conf
and the configuration file (if any) specified with the --config command-line option.
The whole configuration is read from the file (even if the option spec doesn't contain those configuration items), and values can be overridden by command-line options specified in the option spec.
There is a standard set of options you can pass (or configure in a config file) to Optconfig programs.
- --config=file
-
Optconfig reads the configuration in the named file. The configuration file format is JSON. If it can't read this file, it complains. If no --config option is specified, it will search for a configuration file in the standard locations as listed above. If it finds a file, it reads it and sets config values accordingly, then overrides or merges these values with the ones on the command line.
Some options can be specified multiple times. For example, a --define option might allow you to define more than one key; or a --host option might allow you to define more than one host. If these options appear in the configuration file and the command line, their values are added to by the command line value For example, if you have a configuration file with the following contents:
{ "define": { "name": "bob", "home": "/home/bob" } "host": [ "wiki.ppops.net", "tickets.ppops.net" ] }
And you pass
--define mail=bob@proofpoint.com
--host=mail.ppops.net
into the command, the resulting configuration will be:{ "define": { "mail": "bob@proofpoint.com", "name": "bob", "home": "/home/bob" }, "host": [ "mail.ppops.net", "wiki.ppops.net", "tickets.ppops.net" ] }
Note how the command-line value for
--host
is prepended to the list. - --verbose
-
Produce verbose output. You can specify this a number of times indicating increased verbosity.
- --dry-run
-
The command will print what it would have done, but won't change anything in databases or on disk.
- --version
-
Print the program version.
- --help
-
Print a help message.
- --debug
-
Producing debugging output. You can specify this a number of times indicating increased debugging output volume.
- config=s
-
The config file is a string. You don't have to do anything with it.
- verbose+
-
The 'verbose' option value is a number indicating the verbosity level. You can test this and/or use the vrb() method.
- debug+
-
The 'debug' option value is a number indicating the level. You can test this and/or use the vrb() method.
- dry-run!
-
This is a boolean indicating whether a dry run is happening. You need to test this when performing operations that would change persistent data. For example:
my $sth = $dbh->prepare("DROP TABLE $tab"); $opt->vrb(1, "Dropping table users"); $sth->execute() unless $opt->{'dry-run'}; $sth->finish();
- version
-
Define a global variable $VERSION and Optconfig will print it out.
- help
-
If your program has a pod page with a SYNOPSIS section, Optconfig will print it out.
- new($domain, \%options)
-
Parse command-line options and configuration files using $domain.
Each pair in the option hash is composed of an option specifer and a default value. The option specifier is exactly that given in the Getopt::Long module.
- vrb($level, $msg, ...)
-
Prints verbose output if the --verbose level is at or greater than the verbosity mentioned. Thus, if you specify a level of 1, the message will be printed if the user has specified
--verbose
. If you specify a level of 3, the user will have to pass--verbose --verbose --verbose
to see it. - dbg($level, $msg, ...)
-
Similar to vrb(), but uses the value of the
--debug
option and prints a tag indicating the domain.
When consulting a configuration file, Optconfig should check the options for adherence to the optspec, and it doesn't. This could result in unclear failures in the program where the wrong type is configured (for example, a scalar for a list).
There's no easy way to "empty out" an already-configured list or map value from the configuration. In the example above, there's no combination of command-line options that would result in a one-element list for the 'host' option.
When Optconfig is merging the command-line options into the configuration, it is affected by the type of the existing option value (from the configuration file) whereas it should honor only the optspec.
Jeremy Brinkley, <jbrinkley@proofpoint.com>
- showconfig