NAME
Config::Validator - schema based configuration validation
SYNOPSIS
use Config::Validator;
# simple usage
$validator = Config::Validator->new({ type => "list(integer)" });
$validator->validate([ 1, 2 ]); # OK
$validator->validate([ 1, 2.3 ]); # FAIL
$validator->validate({ 1, 2 }); # FAIL
# advanced usage
$validator = Config::Validator->new(
octet => {
type => "integer",
min => 0,
max => 255,
},
color => {
type => "struct",
fields => {
red => { type => "valid(octet)" },
green => { type => "valid(octet)" },
blue => { type => "valid(octet)" },
},
},
);
$validator->validate(
{ red => 23, green => 47, blue => 6 }, "color"); # OK
$validator->validate(
{ red => 23, green => 470, blue => 6 }, "color"); # FAIL
$validator->validate(
{ red => 23, green => 47, lbue => 6 }, "color"); # FAIL
DESCRIPTION
This module allows to perform schema based configuration validation.
The idea is to define in a schema what a valid data is. This schema can be used to create a validator object that can in turn be used to make sure that some data indeed conforms to the schema.
Although the primary focus is on "configuration" (for instance as provided by modules like Config::General) and, to a lesser extent, "options" (for instance as provided by modules like Getopt::Long), this module can in fact validate any data structure.
METHODS
The following methods are available:
- new([OPTIONS])
-
return a new Config::Validator object (class method)
- validate(DATA[, NAME])
-
validate the given data using the named schema (or the default schema if the name is not given)
- options([NAME])
-
convert the named schema (or the default schema if the name is not given) to a list of Getopt::Long compatible options
FUNCTIONS
The following functions are available:
- string2hash(STRING)
-
convert a string of space separated key=value pairs into a hash or hash reference
- hash2string(HASH)
-
convert a hash or hash reference into a string of space separated key=value pairs
SCHEMAS
A schema is simply a structure (i.e. a hash reference) with the following fields (all of them being optional except the first one):
- type
-
the type of the thing to validate (see the "TYPES" section for the complete list); this can also be a list of possible types (e.g.
integer
orundef
) - subtype
-
for an homogeneous list or table, the schema of its elements
- fields
-
for a structure, a table of the allowed fields, in the form: field name => corresponding schema
- optional
-
for a structure field, it indicates that the field is optional
- min
-
the minimum length/size, only for some types (integer, number, string, list and table)
- max
-
the maximum length/size, only for some types (integer, number, string, list and table)
- match
-
a regular expression used to validate a string or table keys
- check
-
a code reference allowing to run user-supplied code to further validate the data
As an example, the following schema describe what a valid schema is:
{
type => "struct",
fields => {
type => { type => "list?(valid(type))" },
subtype => { type => "valid(schema)", optional => "true" },
fields => { type => "table(valid(schema))", optional => "true" },
optional => { type => "boolean", optional => "true" },
min => { type => "number", optional => "true" },
max => { type => "number", optional => "true" },
match => { type => "regexp", optional => "true" },
check => { type => "code", optional => "true" },
},
}
NAMED SCHEMAS
For convenience and self-reference, schemas can be named.
To use named schemas, give them along with their names to the new() method:
$validator = Config::Validator->new(
name1 => { ... schema1 ... },
name2 => { ... schema2 ... },
);
You can then refer to them in the validate() method:
$validator->validate($data, "name1");
If you don't need named schemas, you can use the simpler form:
$validator = Config::Validator->new({ ... schema ... });
$validator->validate($data);
TYPES
Here are the different types that can be used:
- anything
-
really anything, including undef
- undef
-
the undefined value
- undefined
-
synonym for
undef
- defined
-
anything but undef
- string
-
any string (in fact, anything that is defined and not a reference)
- boolean
-
either
true
orfalse
- number
-
any number (this is tested using a regular expression)
- integer
-
any integer (this is tested using a regular expression)
- reference
-
any reference, blessed or not
- ref(*)
-
synonym for
reference
- blessed
-
any blessed reference
- object
-
synonym for
blessed
- isa(*)
-
synonym for
blessed
- unblessed
-
any reference which is not blessed
- code
-
a code reference
- regexp
-
a compiled regular expression
- list
-
an homogeneous list
- list(X)
-
idem but with the given subtype
- list?(X)
-
shortcut for either
X
orlist(X)
- table
-
an homogeneous table
- table(X)
-
idem but with the given subtype
- struct
-
a structure, i.e. a table with known keys
- ref(X)
-
a reference of the given kind
- isa(X)
-
an object of the given kind
- valid(X)
-
something valid according to the given named schema
EXAMPLES
CONFIGURATION VALIDATION
This module works well with Config::General. In particular, the list?(X)
type matches the way Config::General merges blocks.
For instance, one could use the following code:
use Config::General qw(ParseConfig);
use Config::Validator;
$validator = Config::Validator->new(
service => {
type => "struct",
fields => {
port => { type => "integer", min => 0, max => 65535 },
proto => { type => "string" },
},
},
host => {
type => "struct",
fields => {
name => { type => "string", match => qr/^\w+$/ },
service => { type => "list?(valid(service))" },
},
},
);
%cfg = ParseConfig(-ConfigFile => $path, -CComments => 0);
$validator->validate($cfg{host}, "host");
This would work with:
<host>
name = foo
<service>
port = 80
proto = http
</service>
</host>
where $cfg{host}{service}
is the service hash but also with:
<host>
name = foo
<service>
port = 80
proto = http
</service>
<service>
port = 443
proto = https
</service>
</host>
where $cfg{host}{service}
is the list of service hashes.
OPTIONS VALIDATION
This module interacts nicely with Getopt::Long: the options() method can be used to convert a schema into a list of Getopt::Long options.
Here is a simple example:
use Config::Validator;
use Getopt::Long qw(GetOptions);
use Pod::Usage qw(pod2usage);
$validator = Config::Validator->new({
type => "struct",
fields => {
debug => {
type => "boolean",
optional => "true",
},
proto => {
type => "string",
match => qr/^\w+$/,
},
port => {
type => "integer",
min => 0,
max => 65535,
},
},
});
@options = $validator->options();
GetOptions(\%cfg, @options) or pod2usage(2);
$validator->validate(\%cfg);
AUTHOR
Lionel Cons http://cern.ch/lionel.cons
Copyright CERN 2012