diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-03-04 06:12:18 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-03-04 06:12:18 +0000 |
commit | 9ce221b58ff8e5df3707cdf7d2272600da25a303 (patch) | |
tree | 92a2b4a6d815a95ae0639b14cb2373d5786b6eed /lib | |
parent | 26d529e6faaafa442e2b06093db1714f8f0b75bc (diff) | |
download | mangemanche-9ce221b58ff8e5df3707cdf7d2272600da25a303.tar.gz mangemanche-9ce221b58ff8e5df3707cdf7d2272600da25a303.tar.bz2 |
Add on-line documentation. Whitespace cleanup.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/App/Mangemanche.pm | 164 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command.pm | 21 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command/dbload.pm | 39 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command/ident.pm | 7 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command/inspect.pm | 11 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command/ipadd.pm | 5 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command/ipdel.pm | 4 | ||||
-rw-r--r-- | lib/App/Mangemanche/Command/nagios.pm | 17 | ||||
-rw-r--r-- | lib/Net/Ping903.pm | 25 |
9 files changed, 190 insertions, 103 deletions
diff --git a/lib/App/Mangemanche.pm b/lib/App/Mangemanche.pm index d719ecb..2bcbc44 100644 --- a/lib/App/Mangemanche.pm +++ b/lib/App/Mangemanche.pm @@ -17,30 +17,34 @@ sub new { my $class = shift; my $config_file; my $url; my $config = {}; GetOptions( - 'shorthelp|?' => sub { - pod2usage(-input => pod_where({-inc => 1}, $class), - -verbose => 99, - -sections => [qw(NAME SYNOPSIS COMMANDS)], - -exitstatus => 'NOEXIT'); + 'shorthelp|?' => sub { + pod2usage(-input => pod_where({-inc => 1}, $class), + -verbose => 99, + -sections => [qw(NAME SYNOPSIS COMMANDS)], + -exitstatus => 'NOEXIT'); $class->list_commands; exit(EX_OK); - }, - 'help' => sub { + }, + 'help' => sub { App::Mangemanche::Command::mandoc($class, basename($0)), - }, - 'usage' => sub { - pod2usage(-exitstatus => EX_OK, - -input => pod_where({-inc => 1}, $class), - -verbose => 0) }, - 'config|c=s' => \$config_file, - 'url|u=s' => \$url + 'usage' => sub { + pod2usage(-exitstatus => EX_OK, + -input => pod_where({-inc => 1}, $class), + -verbose => 0) + }, + 'version' => sub { + print "$0 version $VERSION\n"; + exit(EX_OK); + }, + 'config|c=s' => \$config_file, + 'url|u=s' => \$url ) or exit(EX_USAGE); if ($config_file) { if (-f $config_file) { $config = $class->readconfig($config_file); } else { @@ -61,24 +65,24 @@ sub new { unless ($config->{baseurl} =~ m{^https?://}) { $config->{baseurl} = "http://$url"; } my $agent = new Net::Ping903($config->{baseurl}); - + my $com = shift @ARGV; die "no command name\n" unless $com; my $modname = __PACKAGE__ . '::Command::' . $com; my $modpath = $modname; $modpath =~ s{::}{/}g; $modpath .= '.pm'; my $cmd; eval { require $modpath; - $cmd = $modname->new($com, $agent); + $cmd = $modname->new($com, $agent); }; if ($@) { if ($@ =~ /Can't locate $modpath/) { die "unknown command: $com\n" } die $@; @@ -111,63 +115,159 @@ sub list_commands { my $class = shift; my @classpath = (split(/::/, $class), 'Command'); print "\nAvailable commands are:\n"; foreach my $mod (sort map { - my $name = basename($_); + my $name = basename($_); if (exists($INC{File::Spec->catfile(@classpath,$name)})) { () } else { eval { require $_; }; - $name =~ s/\.pm$//; + $name =~ s/\.pm$//; $@ ? () : [$name, $_]; } } - map { - glob File::Spec->catfile($_, @classpath, '*.pm') - } @INC) { + map { + glob File::Spec->catfile($_, @classpath, '*.pm') + } @INC) { my $s; open(my $fh, '>', \$s); - pod2usage(-input => $mod->[1], + pod2usage(-input => $mod->[1], -output => $fh, - -verbose => 99, - -sections => ['NAME'], - -exitstatus => 'NOEXIT'); + -verbose => 99, + -sections => ['NAME'], + -exitstatus => 'NOEXIT'); close $fh; my (undef, $descr) = split("\n", $s||''); unless ($descr) { $descr = ' ' . $mod->[0] - } + } print "$descr\n"; } } 1; =head1 NAME -mangemanche - interface to B<ping903> daemon. - +mangemanche - remote management interface to B<ping903> daemon. + =head1 SYNOPSIS B<mangemanche> [B<-c> I<FILE>] [B<-u> I<FILE>] [B<--config=>I<FILE>] -[B<--url=>I<FILE>] +[B<--url=>I<FILE>] I<COMMAND> I<ARG>... B<mangemanche> [B<-?>] [B<--help>] -[B<--usage>] - +[B<--usage>] +[B<--version>] + =head1 DESCRIPTION +Mangemanche provides remote management facilities for the running B<ping903> +daemon. First non-optional argument specifies the name of the I<command> to +run. Arguments following it supply options and arguments to that command. + +Mangemanche reads the IP address and port number of the B<ping903> management +socket from its configuration file, F</etc/ping903.conf>. If the file does +not exist, the default port (B<localhost:8080>) is used. The location of +both can be overridden in the command line. + +If the server requests HTTP authorization, the program will look up the +authorization credentials in the B<.ping903.cred> file located in the +home directory. Refer to L<ping903.cred>(5) for a detailed description. + =head1 OPTIONS - +=over 4 + +=item B<-c>, B<--config=>I<FILE> + +Specifies alternative configuration file to use instead of +F</etc/ping903.conf>. + +=item B<-u>, B<--url=>I<FILE> + +Sets the URL of the B<ping903> management socket. + +=back + +=head2 Informative options + +Each of these options causes the program to display a particular piece of +information and exit with the zero status. Any other options and arguments +are ignored. + +=over 4 + +=item B<-?> + +Displays a short option reminder and lists the available commands with +their short descriptions. + +=item B<--help> + +Displays this manual page. + +=item B<--usage> + +Displays a terse command line usage summary. + +=item B<--version> + +Displays the program version and copyright information. + +=back + +=head1 COMMANDS + +This section summarizes the basic B<mangemanche> commands. Your installation +may provide more. Use B<mangemanche -?> to obtain the list of available +command. + +To see the manual for each particular command, run + + mangemanche COMMAND --help + +=head2 ident + +Displays B<ping903> server identification: package name, version number, +and main process PID. + +=head2 inspect + +Displays the actual B<ping903> server configuration. + +=head2 ipadd + +Adds a single IP to the mutable list of monitored IP addresses. + +=head2 ipdel + +Deletes a single IP from the mutable list of monitored IP addresses. + +=head2 nagios + +Extracts the list of monitored IP addresses from the Nagios configuration +and installs them in B<ping903>. + +=head2 dbload + +Load IP addresses from SQL database into B<ping903>. + +=head1 SEE ALSO + +L<ping903>(1), +L<ping903.conf>(5), +L<ping903.cred>(5). + +=cut diff --git a/lib/App/Mangemanche/Command.pm b/lib/App/Mangemanche/Command.pm index 9857652..45eacfb 100644 --- a/lib/App/Mangemanche/Command.pm +++ b/lib/App/Mangemanche/Command.pm @@ -19,13 +19,13 @@ our @EXPORT_OK = qw(EX_OK EX_FAIL EX_USAGE mandoc); our %EXPORT_TAGS = ( 'exit_codes' => [ qw(EX_OK EX_FAIL EX_USAGE) ] ); sub mandoc { my ($class, $name) = @_; - + my $input = pod_where({-inc => 1}, $class); unless ($name) { ($name = $class) =~ s/.*:://; } my $parser = Pod::Man->new(name => $name, center => 'Ping903 control command', @@ -44,31 +44,31 @@ sub new { $self->{options} = {}; $self->{optdef}{'shorthelp|?'} = sub { pod2usage(-message => $class->pod_usage_msg, -input => pod_where({-inc => 1}, $class), - -exitstatus => EX_OK) + -exitstatus => EX_OK) }; $self->{optdef}{help} = sub { mandoc($class); }; $self->{optdef}{usage} = sub { pod2usage(-exitstatus => EX_OK, - -verbose => 0, - -input => pod_where({-inc => 1}, $class)) + -verbose => 0, + -input => pod_where({-inc => 1}, $class)) }; foreach my $k (keys %opts) { if (ref($opts{$k}) eq 'CODE') { $self->{optdef}{$k} = sub { &{$opts{$k}}($self, @_ ) } - } elsif (ref($opts{$k})) { + } elsif (ref($opts{$k})) { $self->{optdef}{$k} = $opts{$k}; - } else { - $self->{optdef}{$k} = \$self->{options}{$opts{$k}} - } + } else { + $self->{optdef}{$k} = \$self->{options}{$opts{$k}} + } } $self; } sub run { my $self = shift; @@ -78,14 +78,14 @@ sub run { sub agent { shift->{agent} } sub option { my $self = shift; my $name = shift; if (defined(my $v = shift)) { - croak "too many arguments" if @_; - $self->{options}{$name} = $v; + croak "too many arguments" if @_; + $self->{options}{$name} = $v; } return $self->{options}{$name}; } sub pod_usage_msg { my ($class) = @_; @@ -127,7 +127,6 @@ sub abend { sub usage_error { my $self = shift; $self->abend(EX_USAGE, @_); } 1; - diff --git a/lib/App/Mangemanche/Command/dbload.pm b/lib/App/Mangemanche/Command/dbload.pm index c7ddf38..90188c8 100644 --- a/lib/App/Mangemanche/Command/dbload.pm +++ b/lib/App/Mangemanche/Command/dbload.pm @@ -6,37 +6,37 @@ use App::Mangemanche::Command ':exit_codes'; use JSON; use DBI; use File::Spec; sub new { my ($class, $com, $agent) = @_; - + my $self = bless $class->SUPER::new($com, $agent, 'D|driver=s' => 'driver', - 'd|database=s' => sub { + 'd|database=s' => sub { my $self = shift; push @{$self->{options}{connarg}}, "database=$_[1]"; - }, - 'h|host=s' => sub { + }, + 'h|host=s' => sub { my $self = shift; push @{$self->{options}{connarg}}, "host=$_[1]"; - }, - 'P|port=s' => sub { + }, + 'P|port=s' => sub { my $self = shift; push @{$self->{options}{connarg}}, "port=$_[1]"; }, - 'u|user=s' => 'dbuser', - 'p|password=s' => 'dbpass', - 'params=s' => 'dbparams', - 'defaults-file=s' => 'defaults-file', - 't|table=s' => 'table', - 'c|column=s' => 'column', - 'q|query=s' => 'query'); + 'u|user=s' => 'dbuser', + 'p|password=s' => 'dbpass', + 'params=s' => 'dbparams', + 'defaults-file=s' => 'defaults-file', + 't|table=s' => 'table', + 'c|column=s' => 'column', + 'q|query=s' => 'query'); $self->{options}{driver} = 'mysql'; - + $self; } sub run { my $self = shift; $self->SUPER::run; @@ -45,30 +45,30 @@ sub run { my $query = $self->option('query'); unless ($query) { $self->usage_error("--table option must be specified") unless $self->option('table'); $self->usage_error("--column option must be specified") unless $self->option('column'); - $query = qq{SELECT $self->{options}{column} FROM $self->{options}{table}}; + $query = qq{SELECT $self->{options}{column} FROM $self->{options}{table}}; } if (my $p = $self->option('dbparams')) { push @{$self->{options}{connarg}}, $p; } unless ($self->{options}{connarg}) { $self->usage_error('Database parameters not initialized. Please use the --database (optionally - --host and --port) option.'); - } + } if ($self->option('driver') eq 'mysql') { unless ($self->option('defaults-file')) { my $f = File::Spec->catfile($ENV{HOME}, '.my.cnf'); if (-f $f) { $self->option('defaults-file', $f); } - } + } } if (my $p = $self->option('defaults-file')) { push @{$self->{options}{connarg}}, ";mysql_read_default_file=$p"; } my $arg = join(':', ('DBI',$self->{options}{driver}, @@ -233,11 +233,6 @@ Display a detailed program manual. L<ping903>, L<DBI>, L<mangemache>. =cut - - - - - diff --git a/lib/App/Mangemanche/Command/ident.pm b/lib/App/Mangemanche/Command/ident.pm index a871b95..af86d83 100644 --- a/lib/App/Mangemanche/Command/ident.pm +++ b/lib/App/Mangemanche/Command/ident.pm @@ -33,26 +33,26 @@ sub run { =head1 NAME ident - display ping903 server identification =head1 SYNOPSIS -B<ident> +B<ident> [I<PARAM>] =head1 DESCRIPTION Queries the running instance of B<ping903> about identification parameters and prints them on screen. The identification parameters are: package name, package version an running instance PID. If given a single argument I<PARAM>, only the requested parameter is -displayed. +displayed. =head1 OPTIONS - + =head2 Informative options =over 4 =item B<-?> @@ -68,7 +68,6 @@ Display a detailed program manual. =back =head1 SEE ALSO L<ping903>(1), L<ping903.conf>(5). - diff --git a/lib/App/Mangemanche/Command/inspect.pm b/lib/App/Mangemanche/Command/inspect.pm index 81f1049..8ad4221 100644 --- a/lib/App/Mangemanche/Command/inspect.pm +++ b/lib/App/Mangemanche/Command/inspect.pm @@ -37,25 +37,25 @@ sub run { =head1 NAME inspect - inspect ping903 server configuration =head1 SYNOPSIS -B<inspect> +B<inspect> [I<PARAM>] =head1 DESCRIPTION Queries the running instance of B<ping903> about its configuration and prints it on screen in its configuration file format. If given a single argument I<PARAM>, only the requested configuration -parameter is displayed. +parameter is displayed. =head1 OPTIONS - + =head2 Informative options =over 4 =item B<-?> @@ -67,19 +67,18 @@ Display command line usage summary. =item B<--help> Display a detailed program manual. =back - + =head1 NOTES Depending on the B<ping903> server and the user settings, the configuration returned can be censored. The IP list is always formatted as a here-document, containing both immutable and mutable IPs from the server configuration. - + =head1 SEE ALSO L<ping903>(1), L<ping903.conf>(5). - diff --git a/lib/App/Mangemanche/Command/ipadd.pm b/lib/App/Mangemanche/Command/ipadd.pm index 53c48b6..7a68d82 100644 --- a/lib/App/Mangemanche/Command/ipadd.pm +++ b/lib/App/Mangemanche/Command/ipadd.pm @@ -5,13 +5,13 @@ use parent 'App::Mangemanche::Command'; use App::Mangemanche::Command ':exit_codes'; sub run { my $self = shift; $self->SUPER::run; $self->usage_error("required parameters missing") unless @ARGV == 1; - my $ip = shift @ARGV; + my $ip = shift @ARGV; unless ($self->agent->ipadd($ip)) { $self->abend(EX_FAIL, $self->agent->error_message); } } 1; @@ -47,11 +47,10 @@ Display a detailed program manual. =back =head1 SEE ALSO L<ping903>, -L<mangemache>, +L<mangemache>, L<ipdel>. =cut - diff --git a/lib/App/Mangemanche/Command/ipdel.pm b/lib/App/Mangemanche/Command/ipdel.pm index ef4005b..0671973 100644 --- a/lib/App/Mangemanche/Command/ipdel.pm +++ b/lib/App/Mangemanche/Command/ipdel.pm @@ -5,13 +5,13 @@ use parent 'App::Mangemanche::Command'; use App::Mangemanche::Command ':exit_codes'; sub run { my $self = shift; $self->SUPER::run; $self->usage_error("required parameters missing") unless @ARGV == 1; - my $ip = shift @ARGV; + my $ip = shift @ARGV; unless ($self->agent->ipdel($ip)) { $self->abend(EX_FAIL, $self->agent->error_message); } } 1; =head1 NAME @@ -46,10 +46,10 @@ Display a detailed program manual. =back =head1 SEE ALSO L<ping903>, -L<mangemache>, +L<mangemache>, L<ipadd>. =cut diff --git a/lib/App/Mangemanche/Command/nagios.pm b/lib/App/Mangemanche/Command/nagios.pm index 7e42d01..fc21a37 100644 --- a/lib/App/Mangemanche/Command/nagios.pm +++ b/lib/App/Mangemanche/Command/nagios.pm @@ -6,13 +6,13 @@ use App::Mangemanche::Command ':exit_codes'; use File::Spec; use File::Basename; use Nagios::Config; sub new { my ($class, $com, $agent) = @_; - + bless $class->SUPER::new($com, $agent, 'progname|p=s@' => 'prognames', 'config|c=s' => 'nagiosconf'); } sub run { @@ -65,43 +65,40 @@ nagios - extract monitored IP addresses from the Nagios configuration =head1 SYNOPSIS B<nagios> [B<-c> I<FILE>] [B<-p> I<PROG>] -[B<--config=>I<FILE>] +[B<--config=>I<FILE>] [B<--progname=>I<PROG>] =head1 DESCRIPTION Scans Nagios configuration for services that use B<ping903q> and extracts IP addresses of associated hosts. At the end of the run, the extracted addresses are posted to the mutable list of IP addresses monitored by -the running B<ping903> server. +the running B<ping903> server. Default nagios configuration file is F</etc/nagios/nagios.conf>. =head1 OPTIONS =over 4 =item B<-c>, B<--config=>I<FILE> Read Nagios configuration from I<FILE>. - + =item B<-p>, B<--progname=>I<PROG> Look for I<PROG> in addition to B<ping903q>. - + =back =head1 SEE ALSO L<ping903>, -L<mangemache>, +L<mangemache>, L<ipadd>, -L<ipdel>. +L<ipdel>. =cut - - - diff --git a/lib/Net/Ping903.pm b/lib/Net/Ping903.pm index 2ca2006..0c38d51 100644 --- a/lib/Net/Ping903.pm +++ b/lib/Net/Ping903.pm @@ -31,25 +31,25 @@ sub get_info_from_json { my $resp = $self->{ua}->get($url); $self->response($resp); unless ($resp->is_success) { $self->_set_error; return } - if (my $ctype = $resp->header('Content-Type')) { - if ($ctype ne 'application/json') { - $self->{error} = { + if (my $ctype = $resp->header('Content-Type')) { + if ($ctype ne 'application/json') { + $self->{error} = { message => 'Unsupported Content-Type in response' }; return; } } else { - $self->{error} = { + $self->{error} = { message => 'No Content-Type in response' }; - return; - } + return; + } return JSON->new->decode($resp->decoded_content); } sub error_message { my $self = shift; if ($self->{error} && exists($self->{error}{message})) { @@ -99,44 +99,43 @@ sub ipadd { my ($self, $ip) = @_; my $resp = $self->{ua}->put("$self->{baseurl}/config/ip-list/$ip"); $self->response($resp); if ($resp->is_success) { if ($resp->code != HTTP_CREATED) { $self->{error} = { message => 'Unexpected response code' }; - } + } } else { $self->_set_error } return $resp->is_success; } sub ipdel { my ($self, $ip) = @_; my $resp = $self->{ua}->delete("$self->{baseurl}/config/ip-list/$ip"); $self->response($resp); unless ($resp->is_success) { $self->_set_error; - } + } return $resp->is_success; } sub set_ip_list { my ($self, $lref) = @_; my $json_text = JSON->new->encode({ - 'mode' => 'replace', + 'mode' => 'replace', 'ip-list' => $lref }); - + my $resp = $self->{ua}->post("$self->{baseurl}/config/ip-list", 'Content-Type' => 'application/json', 'Content' => $json_text); $self->response($resp); unless ($resp->is_success) { $self->_set_error; - } + } return $resp->is_success; } - + 1; - |