pf-tools/pf-tools: 12 new changesets
parmelan-guest at users.alioth.debian.org
parmelan-guest at users.alioth.debian.org
Wed Oct 20 15:09:26 UTC 2010
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/97881978be72
changeset: 894:97881978be72
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Fri Oct 15 18:31:45 2010 +0200
description:
Access to default and current $PF_CONFIG (and more tests).
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/a63e49f4160f
changeset: 895:a63e49f4160f
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Fri Oct 15 18:42:55 2010 +0200
description:
Remove all Get_source() in Load_conf() calls
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/6f41f34fabde
changeset: 896:6f41f34fabde
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Fri Oct 15 18:44:31 2010 +0200
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/34cf59f6c6d2
changeset: 897:34cf59f6c6d2
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Sat Oct 16 23:23:03 2010 +0200
description:
First test for Init_GLOBAL_NETCONFIG()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/76b283765f12
changeset: 898:76b283765f12
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Sat Oct 16 23:42:06 2010 +0200
description:
More tests for Init_GLOBAL_NETCONFIG()
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/d4b55376551d
changeset: 899:d4b55376551d
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Sun Oct 17 00:00:08 2010 +0200
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/6012ec3c955b
changeset: 900:6012ec3c955b
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Oct 18 15:47:29 2010 +0200
description:
Comment
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/e991a62a91db
changeset: 901:e991a62a91db
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Oct 18 16:19:46 2010 +0200
description:
Style
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/3c1d58fe98a5
changeset: 902:3c1d58fe98a5
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Oct 18 16:26:03 2010 +0200
description:
perltidy
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/57fef7a03458
changeset: 903:57fef7a03458
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Oct 18 16:34:11 2010 +0200
description:
Style / perltidy
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/d6f61d3da9f2
changeset: 904:d6f61d3da9f2
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Mon Oct 18 16:40:36 2010 +0200
description:
File::stat
details: http://hg.debian.org/hg/pf-tools/pf-tools/rev/211fa4ce94e6
changeset: 905:211fa4ce94e6
user: Thomas Parmelan <tom+pf-tools at ankh.fr.EU.org>
date: Wed Oct 20 17:07:06 2010 +0200
description:
Tests for Get_hosttype_from_hostname() and Get_config_for_hostname_on_site().
Allow empty (or comments-only) configuration files in parser_ini() (with test).
diffstat:
7 files changed, 42 insertions(+), 22 deletions(-)
debian/changelog | 1
lib/PFTools/Conf/Syntax.pm | 1
lib/PFTools/Parser.pm | 4 -
lib/PFTools/Structqueries.pm | 20 +++------
t/10.parse.t | 14 +++---
t/13.conf.cfg1/config-export/SITE/cbv4-pfds/CONFIG/include-distrib-custom | 21 ++++++++++
t/13.conf.cfg1/config-export/SITE/cbv4-pfds/CONFIG/include-spawn-common | 3 +
diffs (1613 lines):
diff -r 994c999ab677 -r 211fa4ce94e6 debian/changelog
--- a/debian/changelog Fri Oct 15 14:10:14 2010 +0200
+++ b/debian/changelog Wed Oct 20 17:07:06 2010 +0200
@@ -13,6 +13,8 @@
* Parser_ini() now removes trailing comments.
* Load_conf() now automagically resolves $file with Get_source(), using
$hash_subst->{'HOSTNAME'} as the hostname.
+ * Two new accessors: get_default_pf_config() and get_current_pf_config().
+ * Parse_ini() has been renamed to parse_ini().
[ Christophe Caillet ]
* use remove_tree with keep_root option instead of remove_tree + make_path
@@ -31,7 +33,7 @@
* using Module::Runtime for handling actions with a common API
* using Module::Runtime for handling packages functions with a common API
- -- Thomas Parmelan <tom at sitadelle.com> Mon, 11 Oct 2010 07:36:25 +0200
+ -- Thomas Parmelan <tom at sitadelle.com> Mon, 18 Oct 2010 16:18:42 +0200
pf-tools (1.0-1) unstable; urgency=low
diff -r 994c999ab677 -r 211fa4ce94e6 lib/PFTools/Conf.pm
--- a/lib/PFTools/Conf.pm Fri Oct 15 14:10:14 2010 +0200
+++ b/lib/PFTools/Conf.pm Wed Oct 20 17:07:06 2010 +0200
@@ -29,6 +29,7 @@
use Clone qw( clone );
use English qw( -no_match_vars ); # Avoids regex performance penalty
use Fcntl ':mode';
+use File::stat;
use Net::Domain qw( hostname hostdomain );
use Readonly;
use Storable;
@@ -38,7 +39,7 @@
use PFTools::Conf::Syntax;
use PFTools::Logger;
use PFTools::Net;
-use PFTools::Parser qw( Parser_ini );
+use PFTools::Parser qw( parse_ini );
use PFTools::Structqueries;
our @EXPORT = qw(
@@ -51,6 +52,8 @@
Retrieve_GLOBAL
Get_source
Get_config_for_hostname_on_site
+ get_default_pf_config
+ get_current_pf_config
);
our @EXPORT_OK = qw();
@@ -73,11 +76,11 @@
This hash describes the default configuration. Each key can be overrided from
the configuration file (the default configuration file is /etc/pf-tools.conf).
-FIXME: documentation!
+FIXME documentation!
=cut
-Readonly our $DEFAULT_PF_CONFIG => {
+Readonly my $DEFAULT_PF_CONFIG => {
'path' => {
'status_dir' => '/var/lib/pftools',
'distrib_dir' => '/distrib',
@@ -132,7 +135,7 @@
'hostname' => $HOST_CONFIG_REGEX,
'hosttype' => $HOSTTYPE_CONFIG_REGEX,
'deploy_hosts' => $DEPLOY_CONFIG_REGEX,
- 'network_fstype' => qr{(nfs|cifs)},
+ 'network_fstype' => qr{ (?:nfs|cifs) }xms,
},
'location' => {
'site' => q{},
@@ -140,7 +143,27 @@
},
};
-our $PF_CONFIG = {};
+my $PF_CONFIG = {};
+
+=head2 get_default_pf_config()
+
+Returns the default (and read-only) pf_config.
+
+=cut
+
+sub get_default_pf_config {
+ return $DEFAULT_PF_CONFIG;
+}
+
+=head2 get_current_pf_config()
+
+Returns the current (and writable) pf_config.
+
+=cut
+
+sub get_current_pf_config {
+ return $PF_CONFIG;
+}
=head2 Subst_vars( $text, $variables_ref )
@@ -183,21 +206,16 @@
croak qq{ERROR: $config_file: no such file};
}
- # FIXME use File::stat ?
- # FIXME stat or lstat ?
- my ( $dev, $ino, $mode, $nlink, $uid, $gid, @lstat_vars )
- = lstat($config_file);
+ my $st = stat $config_file;
- # FIXME: also check that $uid == 0 && $gid == 0 ?
- unless ( S_IMODE($mode) == 0600 && S_ISREG($mode) ) {
+ # FIXME also check that $uid == 0 && $gid == 0 ?
+ unless ( S_IMODE($st->mode) == 0600 and S_ISREG($st->mode) ) {
croak
qq{ERROR: weak rights for $config_file (check owner/group/mode)};
}
- my $conf_parsed = Parser_ini($config_file);
+ my $conf_parsed = parse_ini($config_file);
- # FIXME use Hash::Merge::Simple instead ?
- # (it would allow unknown sections/keys, is that a problem ?)
foreach my $section ( keys %{$DEFAULT_PF_CONFIG} ) {
next if !defined $conf_parsed->{$section};
foreach my $key ( keys %{ $DEFAULT_PF_CONFIG->{$section} } ) {
@@ -214,7 +232,7 @@
Initialize a hash structure with all the substitution variables needed
to handle $hostname (default: the local host).
-FIXME: The variables are NOT documented.
+FIXME document the variables
=cut
@@ -236,26 +254,27 @@
my $host_regex = $pf_config->{'regex'}->{'hostname'}
|| $HOST_CONFIG_REGEX;
- unless ( $hostname =~ m/$host_regex/ ) {
+ unless ( $hostname =~ m{ $host_regex }xms ) {
croak qq{ERROR: Invalid hostname $hostname};
}
chomp( my $os_release = qx{ /bin/uname -r } );
- my $hostnum = sprintf '%d', $+{HOSTDIGITS} || 0;
+ my $hostnum = sprintf '%d', $LAST_PAREN_MATCH{HOSTDIGITS} || 0;
my $ref_subst = {
HOSTNAME => $hostname,
DOMAINNAME => $domainname,
- HOSTTYPE => $hosttype || $+{HOSTTYPE},
- HOSTDIGITS => $+{HOSTDIGITS},
+ HOSTTYPE => $hosttype || $LAST_PAREN_MATCH{HOSTTYPE},
+ HOSTDIGITS => $LAST_PAREN_MATCH{HOSTDIGITS},
HOSTNUM => $hostnum,
- HOSTNODEINDEX => $+{HOSTNODEINDEX} || q{},
- HOSTCLUSTER => $+{HOSTDIGITS} . $+{HOSTNODEINDEX},
- POPNAME => $+{POPNAME} || q{},
- OS_RELEASE => $os_release,
- HOSTMINUTE => $hostnum % 60,
- HOSTHOUR => $hostnum % 24,
+ HOSTNODEINDEX => $LAST_PAREN_MATCH{HOSTNODEINDEX} || q{},
+ HOSTCLUSTER => $LAST_PAREN_MATCH{HOSTDIGITS}
+ . $LAST_PAREN_MATCH{HOSTNODEINDEX},
+ POPNAME => $LAST_PAREN_MATCH{POPNAME} || q{},
+ OS_RELEASE => $os_release,
+ HOSTMINUTE => $hostnum % 60,
+ HOSTHOUR => $hostnum % 24,
};
return $ref_subst;
@@ -269,7 +288,7 @@
Optional parameters $hostname, $hash_subst and $pf_config will be computed if
not specified.
-FIXME: The macros are NOT documented.
+FIXME document the macros
The variables are defined by $hash_subst (defaults to the result of
Init_SUBST()). See also Subst_vars().
@@ -294,7 +313,8 @@
}
my $vcs_work_dir = $pf_config->{'path'}->{'checkout_dir'}
- or croak q{ERROR: Undefined configuration parameter: path.checkout_dir};
+ or croak
+ q{ERROR: Undefined configuration parameter: path.checkout_dir};
my $module = $pf_config->{'vcs'}->{'module'}
or croak q{ERROR: Undefined configuration parameter: vcs.module};
@@ -330,7 +350,7 @@
Returns undef if empty or undefined arguments.
Croaks on other errors.
-FIXME: add more documentation here
+FIXME add more documentation here
=cut
@@ -353,47 +373,49 @@
}
if ( $context !~ m{ \A $ALLOWED_PARSING_CONTEXT \z }xms ) {
- croak qq{ERROR: Invalid context $context for file $file: doesn't match $ALLOWED_PARSING_CONTEXT};
+ croak
+ qq{ERROR: Invalid context $context for file $file: doesn't match $ALLOWED_PARSING_CONTEXT};
}
# Automagically resolve $file with Get_source()
- my $hostname = $hash_subst->{'HOSTNAME'}; # FIXME or croak ?
+ # NOTE: $hostname will default to localhost in Init_SUBST(), so there's no
+ # need to err if it is not defined here
+ my $hostname = $hash_subst->{'HOSTNAME'};
my $real_file = Get_source( $file, $hostname, $hash_subst, $pf_config );
- # this will croak() on error
- my $parsed = Parser_ini($real_file);
+ # This will properly croak() on error
+ my $parsed = parse_ini($real_file);
- my $select = $context eq 'config' ? 'action' : 'type'; # compute it only once
+ my $action_or_type
+ = $context eq 'config' ? 'action' : 'type'; # compute it only once
- # FIXME: some code factorization seems possible, but
+ # FIXME some code factorization seems possible, but
# proper tests are needed before changing things here.
if ( $context eq 'host' or $context eq 'model' ) {
if ( defined $parsed->{'hostgroup'}->{'model'} ) {
- $parsed->{'hostgroup'}->{'__model'} = Load_conf(
- Get_source( $parsed->{'hostgroup'}->{'model'}, q{}, $hash_subst, $pf_config), # FIXME auto
- $hash_subst,
- 'model',
- $pf_config
- );
+ $parsed->{'hostgroup'}->{'__model'}
+ = Load_conf(
+ $parsed->{'hostgroup'}->{'model'},
+ $hash_subst, 'model', $pf_config
+ );
}
}
else {
foreach my $section ( keys %{$parsed} ) {
- next if $section =~ m{ \A __ }xms; # skip "internal" sections
+ next if $section =~ m{ \A __ }xms; # skip "internal" sections
- if ( !defined $parsed->{$section}->{$select} ) {
- croak qq{Key $select must be defined in section $section from file $file};
+ my $section_type = $parsed->{$section}->{$action_or_type};
+ if ( !defined $section_type ) {
+ croak
+ qq{Key $action_or_type must be defined in section $section from file $file};
}
- my $section_type = $parsed->{$section}->{$select};
if ( $section_type eq 'include' ) {
-
- # We need to dive into deep ...
$parsed->{$section}->{'__content'}
= Load_conf(
- Get_source( $section, q{}, $hash_subst, $pf_config ), # FIXME auto
- $hash_subst, $context, $pf_config
+ $section, $hash_subst, $context,
+ $pf_config
);
}
}
@@ -404,54 +426,75 @@
# Basic checks
foreach my $section ( keys %{$parsed} ) {
- next if $section =~ m{ \A __ }xms; # skip "internal" sections
+ next if $section =~ m{ \A __ }xms; # skip "internal" sections
my $section_type;
if ( $context eq 'host' or $context eq 'model' ) {
unless ( $section =~ m{ \A ([^:]+) (?: :: (.+) )? \z }xms ) {
- croak qq{ERROR: Unable to compute section type for section $section};
+ croak
+ qq{ERROR: Unable to compute section type for section $section};
}
$section_type = $1;
+
# $iface_name = $2;
}
else {
- if ( !defined $parsed->{$section}->{$select} ) {
- croak qq{Key $select must be defined in section $section from file $file};
+ $section_type = $parsed->{$section}->{$action_or_type};
+ if ( !defined $section_type ) {
+ croak
+ qq{Key $action_or_type must be defined in section $section from file $file};
}
- $section_type = $parsed->{$section}->{$select};
}
- Chk_section_struct( $section, $section_type, $parsed->{$section},
- $context );
+ Chk_section_struct(
+ $section, $section_type, $parsed->{$section},
+ $context
+ );
}
return $parsed;
}
+
+=head2 Init_GLOBAL_NETCONFIG( $start_file, $hash_subst, $pf_config )
+
+Loads $start_file and returns the corresponding structure.
+
+=cut
sub Init_GLOBAL_NETCONFIG {
my ( $start_file, $hash_subst, $pf_config ) = @_;
return unless $start_file and $hash_subst;
- if ( !defined $pf_config ) {
- $pf_config = $PF_CONFIG;
+ $pf_config ||= $PF_CONFIG; # default
+
+ if ( ref $start_file ) {
+ croak q{ERROR: Invalid non-scalar $start_file};
+ }
+ if ( ref $hash_subst ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref $hash_subst};
+ }
+ if ( ref $pf_config ne 'HASH' ) {
+ croak q{ERROR: Invalid non-hashref $pf_config};
}
my $GLOBAL = { 'SITE' => { 'BY_NAME' => {}, } };
foreach my $ip_type ( 'ipv4', 'ipv6' ) {
- next if !$pf_config->{'features'}->{$ip_type};
- my $zone_key = ( $ip_type eq 'ipv6' ) ? 'ZONE6' : 'ZONE';
- my $dhcp_key = ( $ip_type eq 'ipv6' ) ? 'DHCP6' : 'DHCP';
+ next unless $pf_config->{'features'}->{$ip_type};
+
+ my $zone_key = $ip_type eq 'ipv6' ? 'ZONE6' : 'ZONE';
+ my $dhcp_key = $ip_type eq 'ipv6' ? 'DHCP6' : 'DHCP';
$GLOBAL->{$zone_key} = {
'BY_NAME' => {},
- 'BY_SITE' => {}
+ 'BY_SITE' => {},
};
$GLOBAL->{$dhcp_key} = { 'BY_SITE' => {} };
}
my $net_parsed
= Load_conf( $start_file, $hash_subst, 'network', $pf_config );
- my @sortnetkeys = sort { __Sort_net_section( $net_parsed, $a, $b ) }
+ my @sortnetkeys
+ = sort { __Sort_net_section( $net_parsed, $a, $b ) }
@{ $net_parsed->{'__sections_order'} };
foreach my $section (@sortnetkeys) {
if ( $net_parsed->{$section}->{'type'} eq 'zone' ) {
@@ -559,43 +602,68 @@
return $ret;
}
+=head2 Get_config_for_hostname_on_site( $hostname, $site, $hash_subst, $global_config, $pf_config )
+
+Returns the parsed configuration for $hostname on $site.
+
+=cut
+
sub Get_config_for_hostname_on_site {
my ( $hostname, $site, $hash_subst, $global_config, $pf_config ) = @_;
+ if (ref $hostname) {
+ croak q{ERROR: Invalid non-scalar $hostname};
+ }
+ if (not $hostname) {
+ croak q{ERROR: Invalid empty or undefined $hostname};
+ }
+
+ if (ref $site) {
+ croak q{ERROR: Invalid non-scalar $site};
+ }
+ if (not $site) {
+ croak q{ERROR: Invalid empty or undefined $site};
+ }
+
+ if (ref $hash_subst ne 'HASH') {
+ croak q{ERROR: Invalid non-hashref $hash_subst};
+ }
+
+ if (ref $global_config ne 'HASH') {
+ croak q{ERROR: Invalid non-hashref $global_config};
+ }
+
+ if (ref $pf_config ne 'HASH') {
+ croak q{ERROR: Invalid non-hashref $pf_config};
+ }
+
# Common configuration file e.g. update-common
my $global_host_conf = Load_conf(
- # FIXME test if the auto-Get_source() with $hash_subst->{'HOSTNAME}' is OK here
- Get_source(
- 'COMMON:/' . $pf_config->{'path'}->{'common_config'},
- $hostname, $hash_subst, $pf_config
- ),
+ 'COMMON:/' . $pf_config->{'path'}->{'common_config'},
$hash_subst,
'config',
$pf_config
);
my $hosttype
= Get_hosttype_from_hostname( $hostname, $global_config, $site );
- if ( !defined $hosttype ) {
- Abort(
- $CODE->{'UNDEF_KEY'},
- "Unable to get hosttype from hostname $hostname for getting hosttype configuration file"
- );
+ unless ($hosttype) {
+ croak qq{Unable to get hosttype from hostname $hostname};
}
# Hosttype configuration file e.g. update-<hosttype>
- my $hosttype_conf_file
- = __Get_config_path( $hosttype, $pf_config, $site );
+ my $hosttype_file = __Get_config_path( $hosttype, $pf_config, $site );
# Hostname configuration file e.g. update-<hostname>
- my $hostname_conf_file
- = __Get_config_path( $hostname, $pf_config, $site );
+ my $hostname_file = __Get_config_path( $hostname, $pf_config, $site );
- foreach my $file ( $hosttype_conf_file, $hostname_conf_file ) {
- next if !defined $file;
+ foreach my $file ( $hosttype_file, $hostname_file ) {
+ next unless $file;
+
my $config = Load_conf( $file, $hash_subst, 'config', $pf_config );
foreach my $section ( @{ $config->{'__sections_order'} } ) {
- push @{ $global_host_conf->{'__sections_order'} }, $section
- if !defined $global_host_conf->{$section};
+ unless ( $global_host_conf->{$section} ) {
+ push @{ $global_host_conf->{'__sections_order'} }, $section;
+ }
$global_host_conf->{$section} = $config->{$section};
}
}
@@ -612,7 +680,7 @@
=head2 __Get_config_path( $host_value, $pf_config, $site ) -- NOT EXPORTED
Given a host value (host name or host type) and a site, returns the path to the
-site-specific configuration file this host value if it exists, or to the
+site-specific configuration file for this host value if it exists, or to the
non-site-specific configuration file for this host value if it exists.
Returns an undefined value on invalid arguments or if no suitable find was
@@ -645,6 +713,7 @@
return;
}
+# FIXME doc and tests
sub __Merge_host_config {
my ( $hash_to_merge, $hash_subst ) = @_;
@@ -679,8 +748,7 @@
return $merge;
}
-# sub __Merge_other_context
-
+# FIXME doc and tests
sub __Merge_conf_includes {
my ( $hash_to_merge, $hash_subst, $context ) = @_;
diff -r 994c999ab677 -r 211fa4ce94e6 lib/PFTools/Conf/Host.pm
--- a/lib/PFTools/Conf/Host.pm Fri Oct 15 14:10:14 2010 +0200
+++ b/lib/PFTools/Conf/Host.pm Wed Oct 20 17:07:06 2010 +0200
@@ -28,7 +28,6 @@
use POSIX qw(ceil floor);
use PFTools::Conf::Syntax qw( $DEF_SECTIONS );
-use PFTools::Logger;
use PFTools::Net;
use PFTools::Structqueries;
@@ -620,23 +619,24 @@
# Checking path for PXE elements kernel, initrd ...
my $boot_def = $DEF_SECTIONS->{'host'}->{'boot'};
foreach my $key ( keys %{$boot_def} ) {
- next if( $key =~ m{\A MANDATORY}xms );
+ next if $key =~ m{ \A MANDATORY }xms;
my $value = $host2add->{'boot'}->{"$key\.$host_number"}
|| $host2add->{'boot'}->{$key};
unless ( $value ) {
- if ( $key =~ m{\A (console|cmdline) \Z}xms ) {
+ if ( $key =~ m{ \A (console|cmdline) \z }xms ) {
$value = ( $key eq 'console' )
? $site_part->{$key}
- : "";
+ : q{};
}
}
- next unless( $value );
- if (
- $key !~ m{\A (console|cdline) \Z}xms
- && ! -e $pf_config->{'path'}->{'tftp_dir'} . $value
- ) {
- Warn( $CODE->{'OPEN'},
- "$value in $pf_config->{'path'}->{'tftp_dir'} doesn't exist" );
+ next unless $value;
+
+ # FIXME this should be done on the deploy-host only
+ if ( $key !~ m{ \A (console|cmdline) \z }xms
+ && !-e $pf_config->{'path'}->{'tftp_dir'} . $value )
+ {
+ carp
+ qq{WARN: $value in $pf_config->{'path'}->{'tftp_dir'} doesn't exist};
}
$result->{$key} = $value;
}
diff -r 994c999ab677 -r 211fa4ce94e6 lib/PFTools/Conf/Syntax.pm
--- a/lib/PFTools/Conf/Syntax.pm Fri Oct 15 14:10:14 2010 +0200
+++ b/lib/PFTools/Conf/Syntax.pm Wed Oct 20 17:07:06 2010 +0200
@@ -1,4 +1,5 @@
package PFTools::Conf::Syntax;
+
#
# Copyright (C) 2010 Christophe Caillet <quadchris at free.fr>
#
@@ -297,7 +298,7 @@
'after_change' => 'undefined',
},
'filter-model' => {
- 'MANDATORY_KEYS' => [ 'filter' ],
+ 'MANDATORY_KEYS' => ['filter'],
'filter' => 'undefined',
},
'actiongroup' => {
@@ -331,9 +332,10 @@
croak qq{ERROR: Invalid section type $section_type};
}
- my ( $iface_type, $section_tmp);
+ my ( $iface_type, $section_tmp );
if ( $context eq 'host' or $context eq 'model' ) {
- unless ($section_name
+ unless (
+ $section_name
=~ m{
\A
\Q$section_type\E
@@ -354,6 +356,7 @@
croak qq{ERROR: Invalid section name $section_name};
}
$iface_type = $+{iftype};
+
# Clean key names by removing .default or .%HOSTNUM% suffix
foreach my $key ( keys %{$section_hash} ) {
my $new = $key;
@@ -375,31 +378,32 @@
}
last if $section_type eq 'hostgroup' and $context eq 'model';
if ( !defined $section_tmp->{$key} ) {
- croak qq{Mandatory key $key must be defined in section $section_name in context $context};
+ croak
+ qq{Mandatory key $key must be defined in section $section_name in context $context};
}
}
# Check all keys defined
foreach my $key ( keys %{$definition} ) {
next
- if $key eq 'MANDATORY_KEYS'
+ if $key eq 'MANDATORY_KEYS'
or $key =~ m{\A __}xms
- or $definition->{$key} eq 'undefined' # FIXME
- or !defined $section_tmp->{$key};
+ or $definition->{$key} eq 'undefined' # FIXME
+ or not defined $section_tmp->{$key};
my ( $tab_values, $key_name );
if ( $int_context eq 'host' ) {
$tab_values
= ( $key !~ /^@/ )
? [ $section_tmp->{$key}->{'VALUE'} ]
- : $section_tmp->{$key}->{'VALUE'};
+ : $section_tmp->{$key}->{'VALUE'};
$key_name = $section_tmp->{$key}->{'ORIG_NAME'};
}
else {
$tab_values
= ( $key !~ /^@/ )
? [ $section_tmp->{$key} ]
- : $section_tmp->{$key};
+ : $section_tmp->{$key};
$key_name = $key;
}
@@ -410,7 +414,8 @@
$value =~ s{\s* \z}{}xms;
if ( $value !~ m{ \A $definition->{$key} \z }xms ) {
- croak qq{Value '$value' for key $key_name in section $section_name doesn't match $definition->{$key}};
+ croak
+ qq{Value '$value' for key $key_name in section $section_name doesn't match $definition->{$key}};
}
}
}
diff -r 994c999ab677 -r 211fa4ce94e6 lib/PFTools/Parser.pm
--- a/lib/PFTools/Parser.pm Fri Oct 15 14:10:14 2010 +0200
+++ b/lib/PFTools/Parser.pm Wed Oct 20 17:07:06 2010 +0200
@@ -28,22 +28,26 @@
use PFTools::Logger;
-our @EXPORT_OK = qw( Parser_ini );
+our @EXPORT_OK = qw( parse_ini );
my $trailing_comment_regex = qr{ \s+ [#] .* \z }xms;
-sub Parser_ini {
+sub parse_ini {
my ($file) = @_;
return unless $file;
# Config::IniFiles never croaks (it only carps), so eval is useless :/
- my $parse = Config::IniFiles->new( -file => $file, -allowcontinue => 1 );
+ my $parse = Config::IniFiles->new(
+ -file => $file,
+ -allowcontinue => 1,
+ -allowempty => 1,
+ );
# @Config::IniFiles::errors is only used for parse errors
if (@Config::IniFiles::errors) {
croak "ERROR: Unable to parse $file: ",
- join( "\n", @Config::IniFiles::errors );
+ join "\n", @Config::IniFiles::errors;
}
if ( !$parse ) {
croak "ERROR: Unable to load $file";
@@ -62,18 +66,19 @@
# ..and .all keys starting with '@' must be arrays
elsif ( $key_name =~ m{ \A @ }xms and ref $value ne 'ARRAY' ) {
- $section->{$key_name} = [ $value ];
+ $section->{$key_name} = [$value];
}
# Second, remove trailing spaces in arrays...
if ( ref $section->{$key_name} eq 'ARRAY' ) {
- map { $_ =~ s{$trailing_comment_regex}{}; }
- @{ $section->{$key_name} };
+ foreach my $value ( @{ $section->{$key_name} } ) {
+ $value =~ s{$trailing_comment_regex}{}xms;
+ }
}
# ...and in scalars
else {
- $section->{$key_name} =~ s{$trailing_comment_regex}{};
+ $section->{$key_name} =~ s{$trailing_comment_regex}{}xms;
}
}
diff -r 994c999ab677 -r 211fa4ce94e6 lib/PFTools/Structqueries.pm
--- a/lib/PFTools/Structqueries.pm Fri Oct 15 14:10:14 2010 +0200
+++ b/lib/PFTools/Structqueries.pm Wed Oct 20 17:07:06 2010 +0200
@@ -84,21 +84,34 @@
return $global_config->{'SITE'}->{'BY_NAME'}->{$site}->{'zone'};
}
-#########################################################################
-#
-# STR Get_hosttype_from_hostname ( STR, STR, STR, STR, HASHREF )
-#
-# This function returns the hostname for a given model, number and node
-# Inputs :
-# - $hostname : string containing the model definition for building hostname
-# - $global_config : hashref containing the parsed global configuration
-# - $site : define here the site where hostname is defined
-#
-# Output :
-# Returns a string containing the hosttype or undef if hostname doesn't exist
-#
+=head2
+
+Get_hosttype_from_hostname ( $hostname, $global_config, $site )
+
+Returns the hosttype, or nothing.
+
+=cut
+
sub Get_hosttype_from_hostname {
my ( $hostname, $global_config, $site ) = @_;
+
+ if (not $hostname) {
+ croak q{ERROR: Invalid empty or undefined $hostname};
+ }
+ if (ref $hostname) {
+ croak q{ERROR: Invalid non-scalar $hostname};
+ }
+
+ if (not $global_config) {
+ croak q{ERROR: Invalid empty or undefined $global_config};
+ }
+ if (ref $global_config ne 'HASH') {
+ croak q{ERROR: Invalid non-hashref $global_config};
+ }
+
+ if ($site and ref $site) {
+ croak q{ERROR: Invalid non-scalar $site};
+ }
my $site_list = ( $site )
? [ $site ]
@@ -109,12 +122,14 @@
= $global_config->{'SITE'}->{'BY_NAME'}->{$site}->{'HOST'}
->{'BY_NAME'};
foreach my $hostclass ( keys %{$host_part} ) {
- return $hostclass if ( $hostclass eq $hostname );
+ return $hostclass if $hostclass eq $hostname;
+
foreach my $host ( keys %{ $host_part->{$hostclass} } ) {
- return $hostclass if ( $host eq $hostname );
+ return $hostclass if $host eq $hostname;
}
}
}
+
return;
}
diff -r 994c999ab677 -r 211fa4ce94e6 t/10.parse.t
--- a/t/10.parse.t Fri Oct 15 14:10:14 2010 +0200
+++ b/t/10.parse.t Wed Oct 20 17:07:06 2010 +0200
@@ -6,34 +6,37 @@
use Test::Exception;
use Test::More qw( no_plan );
-use PFTools::Parser qw( Parser_ini );
+use PFTools::Parser qw( parse_ini );
-can_ok( 'PFTools::Parser', qw( Parser_ini ) );
+can_ok( 'PFTools::Parser', qw( parse_ini ) );
-note('Testing PFTools::Parser::Parser_ini');
+note('Testing PFTools::Parser::parse_ini');
-ok !defined( Parser_ini() )
+ok !defined( parse_ini() )
=> 'Returns undef if no file specified';
-throws_ok { Parser_ini('/dev/null') }
- qr{\A ERROR: }xms
- => 'Dies on empty file';
+my $expected_cfg = {
+ '__sections_order' => [],
+};
-throws_ok { Parser_ini('/nonexistent.ini') }
+lives_and { is_deeply parse_ini('/dev/null'), $expected_cfg }
+ 'Lives on empty file and returns the correct hash';
+
+throws_ok { parse_ini('/nonexistent.ini') }
qr{\A ERROR: }xms
=> 'Dies on nonexistent file';
my $cfg;
-throws_ok { Parser_ini('t/10.parse.cfg1') }
+throws_ok { parse_ini('t/10.parse.cfg1') }
qr{\A ERROR: }xms
=> 'Dies on non-ini file';
my $file = 't/10.parse.cfg2';
-$cfg = Parser_ini($file);
+$cfg = parse_ini($file);
ok defined($cfg)
=> qq{Returns something on real ini file $file};
-my $expected_cfg = {
+$expected_cfg = {
'__sections_order' => [
'section1',
'section2',
@@ -97,7 +100,7 @@
},
};
$file = 't/13.conf.cfg1/etc/pf-tools.1.conf';
-$cfg = Parser_ini($file);
+$cfg = parse_ini($file);
is_deeply $cfg, $expected_cfg
=> qq{Returns the correct hash on real ini file $file}
or note explain $cfg;
diff -r 994c999ab677 -r 211fa4ce94e6 t/13.conf.cfg1/config-export/SITE/cbv4-pfds/CONFIG/include-distrib-custom
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/t/13.conf.cfg1/config-export/SITE/cbv4-pfds/CONFIG/include-distrib-custom Wed Oct 20 17:07:06 2010 +0200
@@ -0,0 +1,42 @@
+#
+# Custom distrib tools and config file
+
+
+[apt-utils]
+ action = apt-get
+
+[bzip2]
+ action = apt-get
+
+#
+# Config files for generating custom repositories
+[/etc/apt/apt-ftp-debian.conf]
+ depends = apt-utils
+ action = addfile
+ source = CONFIG:spawn%SECTIONNAME%
+ owner = root
+ group = root
+ mode = 0640
+ on_noaction = true
+ after_change = [ -x /usr/local/sbin/update-apt-ftparchive ] && /usr/local/sbin/update-apt-ftparchive debian
+
+[/etc/apt/apt-ftp-ubuntu.conf]
+ depends = apt-utils
+ action = addfile
+ source = CONFIG:spawn%SECTIONNAME%
+ owner = root
+ group = root
+ mode = 0640
+ on_noaction = true
+ after_change = [ -x /usr/local/sbin/update-apt-ftparchive ] && /usr/local/sbin/update-apt-ftparchive ubuntu
+
+[/usr/local/sbin/update-apt-ftparchive]
+ depends = /etc/apt/apt-ftp-debian.conf /etc/apt/apt-ftp-ubuntu.conf bzip2
+ action = addfile
+ source = CONFIG:spawn%SECTIONNAME%
+ owner = root
+ group = root
+ mode = 0750
+ on_noaction = /usr/local/sbin/update-apt-ftparchive
+ after_change = /usr/local/sbin/update-apt-ftparchive
+
diff -r 994c999ab677 -r 211fa4ce94e6 t/13.conf.cfg1/config-export/SITE/cbv4-pfds/CONFIG/include-spawn-common
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/t/13.conf.cfg1/config-export/SITE/cbv4-pfds/CONFIG/include-spawn-common Wed Oct 20 17:07:06 2010 +0200
@@ -0,0 +1,6 @@
+#
+# include-spawn-common
+#
+
+# (many things are here in real life)
+
diff -r 994c999ab677 -r 211fa4ce94e6 t/13.conf.t
--- a/t/13.conf.t Fri Oct 15 14:10:14 2010 +0200
+++ b/t/13.conf.t Wed Oct 20 17:07:06 2010 +0200
@@ -14,6 +14,7 @@
use Test::More qw( no_plan );
use PFTools::Conf;
+use PFTools::Structqueries;
########################################################################
note('Testing PFTools::Conf::__Sort_net_section');
@@ -24,7 +25,6 @@
is PFTools::Conf::__Sort_net_section( {}, 'foo', 'bar' ), 0
=> 'Returns 0 if invalid parsed_net arg';
-# FIXME add a more complex/complete test
my $parsed_net = {
foo => {
type => 'server',
@@ -49,13 +49,18 @@
note('Testing PFTools::Conf::Init_PF_CONFIG');
can_ok( 'PFTools::Conf', qw( Init_PF_CONFIG ) );
-my $default_pf_config = $PFTools::Conf::DEFAULT_PF_CONFIG;
+my $default_pf_config = get_default_pf_config();
ok defined $default_pf_config
- => '$PF_CONFIG defined';
+ => '$DEFAULT_PF_CONFIG defined';
ok ref $default_pf_config eq 'HASH'
- => '$PF_CONFIG is a hashref';
+ => '$DEFAULT_PF_CONFIG is a hashref';
ok keys %{$default_pf_config}
- => '$PF_CONFIG is a non-empty hashref';
+ => '$DEFAULT_PF_CONFIG is a non-empty hashref';
+
+my $current_pf_config = get_current_pf_config();
+is_deeply $current_pf_config, {}
+ => 'Empty $PF_CONFIG'
+ or note explain $current_pf_config;
my $config = Init_PF_CONFIG();
is_deeply $config, $default_pf_config
@@ -101,6 +106,11 @@
is_deeply $parsed_configuration, $expected_configuration
=> 'Correctly merges with the default configuration'
or note explain $parsed_configuration;
+
+$current_pf_config = get_current_pf_config();
+is_deeply $current_pf_config, $expected_configuration
+ => 'Correctly sets $PF_CONFIG'
+ or note explain $current_pf_config;
unlink $test_config_file
or die "unlink $test_config_file: $OS_ERROR";
@@ -689,8 +699,702 @@
or note explain $parsed_configuration;
-# FIXME contexts: config
-diag( qq{FIXME: add other files in $test_config_dir to test Load_conf() with real files and other contexts} );
+diag( qq{FIXME: add other files in $test_config_dir to test Load_conf() with real files and 'config' context} );
+
+
+########################################################################
+note('Testing PFTools::Conf::Init_GLOBAL_NETCONFIG');
+can_ok( 'PFTools::Conf', qw( Init_GLOBAL_NETCONFIG ) );
+
+ok !defined Init_GLOBAL_NETCONFIG()
+ => 'Returns undef if no args';
+
+ok !defined Init_GLOBAL_NETCONFIG( 'start_file' )
+ => 'Returns undef if only one arg';
+
+throws_ok { Init_GLOBAL_NETCONFIG( {}, {} ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] start_file }xms
+ => q{Dies if non-scalar $start_file};
+
+throws_ok { Init_GLOBAL_NETCONFIG( 'start_file', 'hash_subst' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] hash_subst }xms
+ => q{Dies if non-hashref $hash_subst};
+
+throws_ok { Init_GLOBAL_NETCONFIG( 'start_file', {}, 'pf_config' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] pf_config }xms
+ => q{Dies if non-hashref $pf_config};
+
+$parsed_configuration = Init_GLOBAL_NETCONFIG( q{COMMON:private-network}, $test_hash_subst, $test_pf_config );
+$expected_configuration = {
+ 'DHCP' => {
+ 'BY_SITE' => {
+ 'cbv4-pfds' => {
+ 'vlan-systeme' => {
+ 'cbv4-spawn' => {
+ 'cbv4-spawn01' => [
+ 'hardware ethernet 00:1e:c9:ff:42:0a;',
+ 'fixed-address 10.1.167.1;',
+ 'filename pxelinux.0;',
+ 'option domain-name-servers nsprivate.private,spawn.private;'
+ ],
+ 'cbv4-spawn00' => [
+ 'hardware ethernet 00:1e:c9:ff:08:e3;',
+ 'fixed-address 10.1.167.0;',
+ 'filename pxelinux.0;',
+ 'option domain-name-servers nsprivate.private,spawn.private;'
+ ]
+ },
+ 'netmask' => '255.255.0.0',
+ 'subnet' => '10.1.0.0'
+ }
+ },
+ 'cbv4' => {
+ 'vlan-systeme' => {
+ 'netmask' => '255.255.0.0',
+ 'subnet' => '10.1.0.0'
+ }
+ }
+ }
+ },
+ 'SITE' => {
+ 'EDGE' => [
+ 'cbv4'
+ ],
+ 'ROOT' => 'cbv4-pfds',
+ 'BY_NAME' => {
+ 'cbv4-pfds' => {
+ 'HOST' => {
+ 'BY_NAME' => {
+ 'vip-spawn' => {
+ 'nscache' => 'vip-spawn',
+ 'vip-deploy' => 'vip-spawn',
+ 'vip-spawn' => {
+ 'interfaces' => {
+ 'eth1' => {
+ 'ipv4' => '10.1.1.254/16',
+ 'vlan' => 'vlan-systeme'
+ },
+ 'eth0' => {
+ 'ipv4' => '192.168.1.99/24',
+ 'vlan' => 'vlan-pfds-ext'
+ }
+ },
+ 'deployment' => {
+ 'hosttype' => 'vip-spawn',
+ 'order' => '2',
+ 'hostname_model' => 'vip-spawn'
+ }
+ },
+ 'mf' => 'vip-spawn',
+ 'mirrors' => 'vip-spawn',
+ 'nsprivate' => 'vip-spawn',
+ 'cvs' => 'vip-spawn'
+ },
+ 'cbv4-spawn' => {
+ 'ntp01' => 'cbv4-spawn01',
+ 'ntp' => 'cbv4-spawn',
+ 'cbv4-spawn01' => {
+ 'dns' => {
+ 'resolver' =>
+ 'nsprivate.private,spawn.private'
+ },
+ 'boot' => {
+ 'kernel' =>
+ 'vmlinuz-2.6.26.5-universal-grm2.1.12',
+ 'pxefilename' => 'pxelinux.0',
+ 'console' => 'default'
+ },
+ 'interfaces' => {
+ 'eth4' => {
+ 'ipv4' => '10.3.1.42/24',
+ 'vlan' => 'vlan-admindsi'
+ },
+ 'eth5' => {
+ 'ipv4' => '10.3.2.42/24',
+ 'vlan' => 'vlan-middledsi'
+ },
+ 'bond0' => {
+ 'ipv4' => '192.168.1.98/24',
+ 'options' => 'miimon=100',
+ 'mode' => 'active-backup',
+ 'slaves' => 'eth2 eth3',
+ '@route' => [
+ 'default via 192.168.1.254'
+ ],
+ 'vlan' => 'vlan-pfds-ext'
+ },
+ 'eth0' => {
+ 'ipv4' => '10.1.167.1/16',
+ 'mac' => '00:1e:c9:ff:42:0a',
+ 'vlan' => 'vlan-systeme'
+ }
+ },
+ 'deployment' => {
+ 'dhcpvlan' => 'vlan-systeme',
+ 'hosttype' => 'cbv4-spawn',
+ 'arch' => 'amd64',
+ 'mode' => 'debian',
+ 'order' => '1',
+ 'distrib' => 'lenny',
+ 'hostname_model' => 'cbv4-spawn%%'
+ }
+ },
+ 'cbv4-spawn00' => {
+ 'dns' => {
+ 'resolver' =>
+ 'nsprivate.private,spawn.private'
+ },
+ 'boot' => {
+ 'kernel' =>
+ 'vmlinuz-2.6.26.5-universal-grm2.1.12',
+ 'pxefilename' => 'pxelinux.0',
+ 'console' => 'default'
+ },
+ 'interfaces' => {
+ 'eth4' => {
+ 'ipv4' => '10.3.1.41/24',
+ 'vlan' => 'vlan-admindsi'
+ },
+ 'eth5' => {
+ 'ipv4' => '10.3.2.41/24',
+ 'vlan' => 'vlan-middledsi'
+ },
+ 'bond0' => {
+ 'ipv4' => '192.168.1.97/24',
+ 'options' => 'miimon=100',
+ 'mode' => 'active-backup',
+ 'slaves' => 'eth2 eth3',
+ '@route' => [
+ 'default via 192.168.1.254'
+ ],
+ 'vlan' => 'vlan-pfds-ext'
+ },
+ 'eth0' => {
+ 'ipv4' => '10.1.167.0/16',
+ 'mac' => '00:1e:c9:ff:08:e3',
+ 'vlan' => 'vlan-systeme'
+ }
+ },
+ 'deployment' => {
+ 'dhcpvlan' => 'vlan-systeme',
+ 'hosttype' => 'cbv4-spawn',
+ 'arch' => 'amd64',
+ 'mode' => 'debian',
+ 'order' => '1',
+ 'distrib' => 'lenny',
+ 'hostname_model' => 'cbv4-spawn%%'
+ }
+ },
+ 'spawn00' => 'cbv4-spawn00',
+ 'spawn01' => 'cbv4-spawn01',
+ 'ntp00' => 'cbv4-spawn00',
+ 'spawn' => 'cbv4-spawn'
+ },
+ 'cbv4-pfds-filer' => {
+ 'cbv4-pfds-filer01' => {
+ 'interfaces' => {
+ 'eth0' => {
+ 'ipv4' => '10.1.2.1/16',
+ 'vlan' => 'vlan-systeme'
+ }
+ },
+ 'deployment' => {
+ 'hosttype' => 'cbv4-pfds-filer',
+ 'order' => '2',
+ 'hostname_model' => 'cbv4-pfds-filer%%'
+ }
+ },
+ 'cbv4-pfds-filer00' => {
+ 'interfaces' => {
+ 'eth0' => {
+ 'ipv4' => '10.1.2.0/16',
+ 'vlan' => 'vlan-systeme'
+ }
+ },
+ 'deployment' => {
+ 'hosttype' => 'cbv4-pfds-filer',
+ 'order' => '2',
+ 'hostname_model' => 'cbv4-pfds-filer%%'
+ }
+ }
+ }
+ },
+ '__hostclass_pxe' => [
+ 'cbv4-spawn'
+ ],
+ 'BY_ADDR' => {
+ '192.168.1.98/24' => 'cbv4-spawn01.vlan-pfds-ext',
+ '10.3.1.41/24' => 'cbv4-spawn00.vlan-admindsi',
+ '10.3.2.41/24' => 'cbv4-spawn00.vlan-middledsi',
+ '10.1.2.1/16' => 'cbv4-pfds-filer01.vlan-systeme',
+ '10.1.2.0/16' => 'cbv4-pfds-filer00.vlan-systeme',
+ '10.3.1.42/24' => 'cbv4-spawn01.vlan-admindsi',
+ '192.168.1.99/24' => 'vip-spawn.vlan-pfds-ext',
+ '10.1.167.0/16' => 'cbv4-spawn00.vlan-systeme',
+ '10.1.167.1/16' => 'cbv4-spawn01.vlan-systeme',
+ '10.3.2.42/24' => 'cbv4-spawn01.vlan-middledsi',
+ '192.168.1.97/24' => 'cbv4-spawn00.vlan-pfds-ext',
+ '10.1.1.254/16' => 'vip-spawn.vlan-systeme'
+ },
+ 'BY_MAC' => {
+ '00:1e:c9:ff:42:0a' =>
+ 'eth0.cbv4-spawn01.vlan-systeme',
+ '00:1e:c9:ff:08:e3' =>
+ 'eth0.cbv4-spawn00.vlan-systeme'
+ }
+ },
+ 'location' => 'Courbevoie',
+ 'zone' => 'private',
+ 'console' => 'default',
+ 'SERVICE' => {
+ 'BY_NAME' => {
+ 'admins' => [
+ 'CONFSITE_cbv4-pfds:/hostfile-cbv4-spawn'
+ ]
+ }
+ },
+ 'coment' => 'CBV4-PFDS root site',
+ 'room' => 'CBV4-PFDS Room Name',
+ 'state' => 'ROOT',
+ 'dhcpvlan' => 'vlan-systeme',
+ 'NETWORK' => {
+ 'BY_TAG' => {
+ '302' => 'vlan-admindsi',
+ '39' => 'vlan-pfds-int',
+ '40' => 'vlan-pfds-ext',
+ '372' => 'vlan-middledsi',
+ '13' => 'vlan-systeme'
+ },
+ 'BY_NAME' => {
+ 'vlan-admindsi' => {
+ 'network' => '10.3.1.0',
+ 'gateway' => '10.3.1.254',
+ 'tag' => 302,
+ 'netmask' => '255.255.255.0',
+ 'scope' => 'private'
+ },
+ 'vlan-pfds-ext' => {
+ 'network' => '192.168.1.0',
+ 'comment' => 'something really interesting',
+ 'gateway' => '192.168.1.254',
+ 'tag' => 40,
+ 'netmask' => '255.255.255.0',
+ 'scope' => 'public'
+ },
+ 'vlan-pfds-int' => {
+ 'network' => '10.2.0.0',
+ 'tag' => 39,
+ 'netmask' => '255.255.0.0',
+ 'scope' => 'private'
+ },
+ 'vlan-systeme' => {
+ 'network' => '10.1.0.0',
+ 'tag' => 13,
+ 'netmask' => '255.255.0.0',
+ 'scope' => 'private'
+ },
+ 'vlan-middledsi' => {
+ 'network' => '10.3.2.0',
+ 'gateway' => '10.3.2.254',
+ 'tag' => 372,
+ 'netmask' => '255.255.255.0',
+ 'scope' => 'private'
+ }
+ },
+ 'BY_ADDR' => {
+ '192.168.1.0/24' => 'vlan-pfds-ext',
+ '10.3.2.0/24' => 'vlan-middledsi',
+ '10.1.0.0/16' => 'vlan-systeme',
+ '10.3.1.0/24' => 'vlan-admindsi',
+ '10.2.0.0/16' => 'vlan-pfds-int'
+ }
+ },
+ 'type' => 'site'
+ },
+ 'cbv4' => {
+ 'HOST' => {
+ 'BY_NAME' => {},
+ 'BY_ADDR' => {},
+ 'BY_MAC' => {}
+ },
+ 'location' => 'Courbevoie',
+ 'zone' => 'private',
+ 'console' => 'default',
+ 'SERVICE' => {
+ 'BY_NAME' => {}
+ },
+ 'coment' => 'CBV4 POP',
+ 'room' => 'CBV4 Room Name',
+ 'state' => 'EDGE',
+ 'dhcpvlan' => 'vlan-systeme',
+ 'NETWORK' => {
+ 'BY_TAG' => {
+ '13' => 'vlan-systeme'
+ },
+ 'BY_NAME' => {
+ 'vlan-systeme' => {}
+ },
+ 'BY_ADDR' => {
+ '10.1.0.0/16' => 'vlan-systeme'
+ }
+ },
+ 'type' => 'site'
+ }
+ },
+ '__site_list' => [
+ 'cbv4-pfds',
+ 'cbv4'
+ ]
+ },
+ 'ZONE' => {
+ 'BY_NAME' => {
+ 'private' => {
+ 'BY_SITE' => {
+ 'cbv4-pfds' => {
+ 'vlan-admindsi' => {
+ 'broadcast' => 'A 10.3.1.255',
+ 'network' => 'A 10.3.1.0',
+ 'gateway' => 'A 10.3.1.254',
+ 'netmask' => 'A 255.255.255.0'
+ },
+ 'vip-spawn' => {
+ 'vip-spawn.vlan-pfds-ext' => 'A 192.168.1.99',
+ 'nscache' => 'CNAME vip-spawn.vlan-systeme',
+ 'vip-deploy' => 'CNAME vip-spawn.vlan-systeme',
+ 'mf' => 'CNAME vip-spawn.vlan-systeme',
+ 'mirrors' => 'CNAME vip-spawn.vlan-systeme',
+ 'vip-spawn.vlan-systeme' => 'A 10.1.1.254',
+ 'nsprivate' => 'CNAME vip-spawn.vlan-systeme',
+ 'cvs' => 'CNAME vip-spawn.vlan-systeme'
+ },
+ 'cbv4-spawn' => {
+ 'cbv4-spawn01.vlan-middledsi' => 'A 10.3.2.42',
+ 'cbv4-spawn00.vlan-middledsi' => 'A 10.3.2.41',
+ 'spawn00' => 'CNAME cbv4-spawn00.vlan-systeme',
+ 'cbv4-spawn01.vlan-pfds-ext' => 'A 192.168.1.98',
+ 'cbv4-spawn00.vlan-pfds-ext' => 'A 192.168.1.97',
+ 'cbv4-spawn01.vlan-admindsi' => 'A 10.3.1.42',
+ 'ntp00' => 'CNAME cbv4-spawn00.vlan-systeme',
+ 'ntp' => 'CNAME cbv4-spawn.vlan-systeme',
+ 'ntp01' => 'CNAME cbv4-spawn01.vlan-systeme',
+ 'cbv4-spawn00.vlan-admindsi' => 'A 10.3.1.41',
+ 'cbv4-spawn00.vlan-systeme' => 'A 10.1.167.0',
+ 'cbv4-spawn' => 'CNAME cbv4-spawn.vlan-systeme',
+ 'cbv4-spawn.vlan-systeme' => [
+ 'A 10.1.167.0',
+ 'A 10.1.167.1'
+ ],
+ 'spawn01' => 'CNAME cbv4-spawn01.vlan-systeme',
+ 'cbv4-spawn01.vlan-systeme' => 'A 10.1.167.1',
+ 'spawn' => 'CNAME cbv4-spawn.vlan-systeme'
+ },
+ 'cbv4-pfds-filer' => {
+ 'cbv4-pfds-filer00.vlan-systeme' => 'A 10.1.2.0',
+ 'cbv4-pfds-filer01.vlan-systeme' => 'A 10.1.2.1'
+ },
+ 'vlan-systeme' => {
+ 'broadcast' => 'A 10.1.255.255',
+ 'network' => 'A 10.1.0.0',
+ 'netmask' => 'A 255.255.0.0'
+ },
+ 'vlan-pfds-int' => {
+ 'broadcast' => 'A 10.2.255.255',
+ 'network' => 'A 10.2.0.0',
+ 'netmask' => 'A 255.255.0.0'
+ },
+ 'vlan-pfds-ext' => {
+ 'broadcast' => 'A 192.168.1.255',
+ 'network' => 'A 192.168.1.0',
+ 'gateway' => 'A 192.168.1.254',
+ 'netmask' => 'A 255.255.255.0'
+ },
+ 'vlan-middledsi' => {
+ 'broadcast' => 'A 10.3.2.255',
+ 'network' => 'A 10.3.2.0',
+ 'gateway' => 'A 10.3.2.254',
+ 'netmask' => 'A 255.255.255.0'
+ }
+ },
+ 'cbv4' => {
+ 'vlan-systeme' => {
+ 'broadcast' => 'A 10.1.255.255',
+ 'network' => 'A 10.1.0.0',
+ 'netmask' => 'A 255.255.0.0'
+ }
+ }
+ },
+ '__hostclass_order' => {
+ 'cbv4-pfds' => [
+ 'vip-spawn',
+ 'cbv4-pfds-filer',
+ 'cbv4-spawn'
+ ]
+ },
+ 'SOA' => {
+ '@ns' => [
+ 'deploy00.vlan-systeme.private.',
+ 'deploy01.vlan-systeme.private.'
+ ],
+ 'ttl' => '1D ; TTL (1 day)',
+ 'serial' => 'AUTO',
+ 'console' => 'ttyS0,115200n8',
+ '@mx' => [
+ '1 mf.private.',
+ '2 mf00.private.',
+ '2 mf01.private.'
+ ],
+ 'retry' => '1H ; Retry (1 hour)',
+ 'negttl' => '1H ; Negative TTL (1 hours)',
+ 'comment' => 'Internal management zone',
+ 'refresh' => '6H ; Refresh (6 hours)',
+ 'type' => 'zone',
+ 'mail' => 'dnsmaster at private',
+ 'soa' => 'Deploy00.private.',
+ 'expire' => '7D ; Expire (7 days)'
+ },
+ '__network_order' => {
+ 'cbv4-pfds' => [
+ 'vlan-systeme',
+ 'vlan-pfds-int',
+ 'vlan-pfds-ext',
+ 'vlan-admindsi',
+ 'vlan-middledsi'
+ ],
+ 'cbv4' => [
+ 'vlan-systeme'
+ ]
+ }
+ }
+ },
+ 'BY_SITE' => {
+ 'cbv4-pfds' => 'private',
+ 'cbv4' => 'private'
+ }
+ }
+};
+$expected_configuration->{'SITE'}{'BY_NAME'}{'cbv4'}{'NETWORK'}{'BY_NAME'}{'vlan-systeme'}
+ = $expected_configuration->{'SITE'}{'BY_NAME'}{'cbv4-pfds'}{'NETWORK'}{'BY_NAME'}
+ {'vlan-systeme'};
+
+is_deeply $parsed_configuration, $expected_configuration
+ => q{Returns the expected configuration hash}
+ or note explain $parsed_configuration;
+
+$parsed_configuration = Init_GLOBAL_NETCONFIG( q{COMMON:private-network}, $test_hash_subst );
+is_deeply $parsed_configuration, $expected_configuration
+ => q{Returns the expected configuration hash when no explicit $pf_config was given}
+ or note explain $parsed_configuration;
+
+
+########################################################################
+note('Testing PFTools::Structqueries::Get_hosttype_from_hostname');
+can_ok( 'PFTools::Structqueries', qw( Get_hosttype_from_hostname ) );
+
+my $global_config = $parsed_configuration;
+
+throws_ok { Get_hosttype_from_hostname() }
+ qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] undefined [ ] [\$] hostname }xms
+ => 'Dies if no hostname';
+
+throws_ok { Get_hosttype_from_hostname( {} ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
+ => q{Dies if non-scalar $hostname};
+
+throws_ok { Get_hosttype_from_hostname( 'hostname' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] undefined [ ] [\$] global_config }xms
+ => 'Dies if no global_config';
+
+throws_ok { Get_hosttype_from_hostname( 'hostname', 'global_config' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
+ => q{Dies if non-hashref $global_config};
+
+# $site is optional
+lives_ok { Get_hosttype_from_hostname( 'hostname', {} ) }
+ 'OK if no $site';
+
+throws_ok { Get_hosttype_from_hostname( 'hostname', {}, {} ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site }xms
+ => q{Dies if non-scalar $site};
+
+$parsed_configuration = Get_hosttype_from_hostname( 'cbv4-spawn00',
+ $global_config, 'cbv4-pfds' );
+is $parsed_configuration, q{cbv4-spawn}
+ => q{Returns the correct hosttype}
+ or diag explain $parsed_configuration;
+
+
+########################################################################
+note('Testing PFTools::Conf::Get_config_for_hostname_on_site');
+can_ok( 'PFTools::Conf', qw( Get_config_for_hostname_on_site ) );
+
+throws_ok { Get_config_for_hostname_on_site() }
+ qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] undefined [ ] [\$] hostname }xms
+ => 'Dies if no hostname';
+
+throws_ok { Get_config_for_hostname_on_site( {} ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] hostname }xms
+ => q{Dies if non-scalar $hostname};
+
+throws_ok { Get_config_for_hostname_on_site( 'hostname' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] empty [ ] or [ ] undefined [ ] [\$] site }xms
+ => 'Dies if no site';
+
+throws_ok { Get_config_for_hostname_on_site( 'hostname', {} ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-scalar [ ] [\$] site }xms
+ => q{Dies if non-scalar $site};
+
+throws_ok { Get_config_for_hostname_on_site( 'hostname', 'site', 'hash_subst' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] hash_subst }xms
+ => q{Dies if non-hashref $hash_subst};
+
+throws_ok { Get_config_for_hostname_on_site( 'hostname', 'site', {}, 'global_config' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] global_config }xms
+ => q{Dies if non-hashref $global_config};
+
+throws_ok { Get_config_for_hostname_on_site( 'hostname', 'site', {}, {}, 'pf_config' ) }
+ qr{ \A ERROR: [ ] Invalid [ ] non-hashref [ ] [\$] pf_config }xms
+ => q{Dies if non-hashref $pf_config};
+
+$parsed_configuration = Get_config_for_hostname_on_site(
+ 'cbv4-spawn00', 'cbv4-pfds', $test_hash_subst, $global_config,
+ $test_pf_config
+);
+
+$expected_configuration = {
+ '/etc/apache2/sites-available/default' => {
+ 'owner' => 'root',
+ 'source' => 'CONFIG:spawn%SECTIONNAME%',
+ 'mode' => '0644',
+ 'filter' => 'filter_privateresolve %SOURCE% %HOSTNAME% %DESTINATION%',
+ 'after_change' => '/etc/init.d/apache2 reload',
+ 'on_noaction' => 'true',
+ 'group' => 'root',
+ 'action' => 'addfile',
+ 'depends' => '/etc/apache2/ports.conf',
+ },
+ '/etc/apache2/ports.conf' => {
+ 'on_noaction' => 'true',
+ 'owner' => 'root',
+ 'source' => 'CONFIG:spawn%SECTIONNAME%',
+ 'group' => 'root',
+ 'mode' => '0644',
+ 'filter' => 'filter_privateresolve %SOURCE% %HOSTNAME% %DESTINATION%',
+ 'action' => 'addfile',
+ 'after_change' => '/etc/init.d/apache2 reload',
+ },
+ 'pf-tools' => {
+ 'action' => 'apt-get',
+ 'after_change' =>
+ 'echo "Re-run update-config"; killall -KILL update-config',
+ },
+ '/var/www/debian-backports' => {
+ 'source' => '/distrib/official-mirrors/debian-backports',
+ 'action' => 'addlink',
+ 'depends' => '/etc/apache2/sites-available/default /distrib',
+ },
+ '/var/www/debian' => {
+ 'source' => '/distrib/official-mirrors/debian',
+ 'action' => 'addlink',
+ 'depends' => '/etc/apache2/sites-available/default /distrib',
+ },
+ '/etc/apt/apt-ftp-ubuntu.conf' => {
+ 'on_noaction' => 'true',
+ 'owner' => 'root',
+ 'source' => 'CONFIG:spawn%SECTIONNAME%',
+ 'group' => 'root',
+ 'mode' => '0640',
+ 'action' => 'addfile',
+ 'after_change' =>
+ '[ -x /usr/local/sbin/update-apt-ftparchive ] && /usr/local/sbin/update-apt-ftparchive ubuntu',
+ 'depends' => 'apt-utils',
+ },
+ '/var/lib/cvs/repository' => {
+ 'source' => 'cbv4-pfds-filer00.vlan-systeme.private:/vol/volvcs/cvs',
+ 'options' => 'rw,nodev,tcp,nosuid,noexec,hard,intr,bg',
+ 'action' => 'addmount',
+ 'fstype' => 'nfs',
+ },
+ '__sections_order' => [
+ 'pf-tools',
+ 'apt-utils',
+ 'bzip2',
+ '/etc/apt/apt-ftp-debian.conf',
+ '/etc/apt/apt-ftp-ubuntu.conf',
+ '/usr/local/sbin/update-apt-ftparchive',
+ '/distrib',
+ '/var/lib/cvs/repository',
+ '/etc/apache2/ports.conf',
+ '/etc/apache2/sites-available/default',
+ '/var/www/debian',
+ '/var/www/debian-security',
+ '/var/www/debian-custom',
+ '/var/www/debian-backports',
+ 'dhcp',
+ ],
+ '/etc/apt/apt-ftp-debian.conf' => {
+ 'on_noaction' => 'true',
+ 'owner' => 'root',
+ 'source' => 'CONFIG:spawn%SECTIONNAME%',
+ 'group' => 'root',
+ 'mode' => '0640',
+ 'action' => 'addfile',
+ 'after_change' =>
+ '[ -x /usr/local/sbin/update-apt-ftparchive ] && /usr/local/sbin/update-apt-ftparchive debian',
+ 'depends' => 'apt-utils',
+ },
+ 'apt-utils' => {
+ 'action' => 'apt-get',
+ },
+ '/usr/local/sbin/update-apt-ftparchive' => {
+ 'on_noaction' => '/usr/local/sbin/update-apt-ftparchive',
+ 'owner' => 'root',
+ 'source' => 'CONFIG:spawn%SECTIONNAME%',
+ 'group' => 'root',
+ 'mode' => '0750',
+ 'action' => 'addfile',
+ 'after_change' => '/usr/local/sbin/update-apt-ftparchive',
+ 'depends' =>
+ '/etc/apt/apt-ftp-debian.conf /etc/apt/apt-ftp-ubuntu.conf bzip2',
+ },
+ '/var/www/debian-custom' => {
+ 'source' => '/distrib/debian-custom',
+ 'action' => 'addlink',
+ 'depends' => '/etc/apache2/sites-available/default /distrib',
+ },
+ 'bzip2' => {
+ 'action' => 'apt-get',
+ },
+ '/distrib' => {
+ 'source' =>
+ 'cbv4-pfds-filer00.vlan-systeme.private:/vol/volmirror/distrib',
+ 'options' => 'rw,nodev,tcp,nosuid,hard,intr,bg',
+ 'mode' => '0750',
+ 'action' => 'addmount',
+ 'fstype' => 'nfs',
+ },
+ 'dhcp' => {
+ 'on_noaction' =>
+ 'umask 022; mk_pxelinuxcfg GLOBAL:private-network /distrib/tftpboot/pxelinux.cfg/template',
+ 'action' => 'actiongroup',
+ 'after_change' =>
+ 'umask 022; mk_pxelinuxcfg GLOBAL:private-network /distrib/tftpboot/pxelinux.cfg/template && /etc/init.d/dhcp3-server restart',
+ },
+ '/var/www/debian-security' => {
+ 'source' => '/distrib/official-mirrors/debian-security',
+ 'action' => 'addlink',
+ 'depends' => '/etc/apache2/sites-available/default /distrib',
+ },
+};
+
+is_deeply $parsed_configuration, $expected_configuration
+ => q{Returns the expected configuration hash}
+ or note explain $parsed_configuration;
+
+
+
+#TODO: {
+# local $TODO = 'Depends on other, still failing, tests';
+#} # END TODO
remove_tree( q{/tmp/pf-test} );
More information about the pf-tools-commits
mailing list