summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Carr <gonzai@users.sourceforge.net>2007-02-08 05:16:15 +0000
committerGavin Carr <gonzai@users.sourceforge.net>2007-02-08 05:16:15 +0000
commitd56d5a0d2d4b29ac2a296bc39a7b80862a7f7e8f (patch)
treee57286162e8f13f98e268ef44867e8f90af2ff3c
parent9692fb72f6f428dbed4e107dd83fa906854babff (diff)
downloadmonitoring-plugin-perl-d56d5a0d2d4b29ac2a296bc39a7b80862a7f7e8f.tar.gz
Add initial --default-opts implementation to Nagios::Plugin::Getopt.
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/Nagios-Plugin/trunk@1616 f882894a-f735-0410-b71e-b25c423dba1c
-rw-r--r--MANIFEST24
-rw-r--r--META.yml8
-rw-r--r--Makefile.PL8
-rw-r--r--lib/Nagios/Plugin/Getopt.pm162
4 files changed, 189 insertions, 13 deletions
diff --git a/MANIFEST b/MANIFEST
index 7fe300f..67bb306 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -12,9 +12,33 @@ t/Nagios-Plugin-Functions-01.t
12t/Nagios-Plugin-Functions-02.t 12t/Nagios-Plugin-Functions-02.t
13t/Nagios-Plugin-Getopt-01.t 13t/Nagios-Plugin-Getopt-01.t
14t/Nagios-Plugin-Getopt-02.t 14t/Nagios-Plugin-Getopt-02.t
15t/Nagios-Plugin-Getopt-03.t
15t/Nagios-Plugin-Performance.t 16t/Nagios-Plugin-Performance.t
16t/Nagios-Plugin-Range.t 17t/Nagios-Plugin-Range.t
17t/Nagios-Plugin-Threshold.t 18t/Nagios-Plugin-Threshold.t
19t/npg03/
20t/npg03/README
21t/npg03/expected/
22t/npg03/expected/00_basic
23t/npg03/expected/01_override1
24t/npg03/expected/02_override2
25t/npg03/expected/05_singlechar1
26t/npg03/expected/06_singlechar2
27t/npg03/expected/07_singlechar3
28t/npg03/expected/09_funnystuff
29t/npg03/expected/12_nosection_implicit
30t/npg03/input/
31t/npg03/input/00_basic
32t/npg03/input/01_override1
33t/npg03/input/02_override2
34t/npg03/input/05_singlechar1
35t/npg03/input/06_singlechar2
36t/npg03/input/07_singlechar3
37t/npg03/input/09_funnystuff
38t/npg03/input/12_nosection_implicit
39t/npg03/input/13_nosection_explicit_dies
40t/npg03/input/14_badsection_dies
41t/npg03/plugins.cfg
18lib/Nagios/Plugin.pm 42lib/Nagios/Plugin.pm
19lib/Nagios/Plugin/Performance.pm 43lib/Nagios/Plugin/Performance.pm
20lib/Nagios/Plugin/Range.pm 44lib/Nagios/Plugin/Range.pm
diff --git a/META.yml b/META.yml
index b60dfd5..8fd19e8 100644
--- a/META.yml
+++ b/META.yml
@@ -6,9 +6,13 @@ version_from: lib/Nagios/Plugin/Functions.pm
6installdirs: site 6installdirs: site
7requires: 7requires:
8 Carp: 0 8 Carp: 0
9 Class::Accessor: 0.22 9 Class::Accessor: 0
10 Params::Validate: 0.24 10 Params::Validate: 0
11 Test::More: 0.62 11 Test::More: 0.62
12 Config::Tiny: 0
13 File::Spec: 0
14 File::Basename:
15 IO::File:
12 16
13distribution_type: module 17distribution_type: module
14generated_by: ExtUtils::MakeMaker version 6.17 18generated_by: ExtUtils::MakeMaker version 6.17
diff --git a/Makefile.PL b/Makefile.PL
index f7f1131..63b36da 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -6,11 +6,15 @@ WriteMakefile(
6 NAME => 'Nagios::Plugin', 6 NAME => 'Nagios::Plugin',
7 VERSION_FROM => 'lib/Nagios/Plugin/Functions.pm', # finds $VERSION 7 VERSION_FROM => 'lib/Nagios/Plugin/Functions.pm', # finds $VERSION
8 PREREQ_PM => { 8 PREREQ_PM => {
9 Params::Validate => 0.24, 9 Params::Validate => 0,
10 Class::Accessor => 0.22, 10 Class::Accessor => 0,
11 Test::More => 0.62, 11 Test::More => 0.62,
12 Carp => 0, 12 Carp => 0,
13 Test::Exception => 0, 13 Test::Exception => 0,
14 Config::Tiny => 0,
15 File::Spec => 0,
16 File::Basename => 0,
17 IO::File => 0,
14 }, # e.g., Module::Name => 1.1 18 }, # e.g., Module::Name => 1.1
15 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 19 ($] >= 5.005 ? ## Add these new keywords supported since 5.005
16 (ABSTRACT_FROM => 'lib/Nagios/Plugin.pm', # retrieve abstract from module 20 (ABSTRACT_FROM => 'lib/Nagios/Plugin.pm', # retrieve abstract from module
diff --git a/lib/Nagios/Plugin/Getopt.pm b/lib/Nagios/Plugin/Getopt.pm
index bbf1fc9..806a6a0 100644
--- a/lib/Nagios/Plugin/Getopt.pm
+++ b/lib/Nagios/Plugin/Getopt.pm
@@ -10,12 +10,15 @@ use File::Basename;
10use Getopt::Long qw(:config no_ignore_case bundling); 10use Getopt::Long qw(:config no_ignore_case bundling);
11use Carp; 11use Carp;
12use Params::Validate qw(:all); 12use Params::Validate qw(:all);
13use Config::Tiny;
13use base qw(Class::Accessor); 14use base qw(Class::Accessor);
14 15
15use Nagios::Plugin::Functions; 16use Nagios::Plugin::Functions;
16use vars qw($VERSION); 17use vars qw($VERSION $DEFAULT_CONFIG_FILE);
17$VERSION = $Nagios::Plugin::Functions::VERSION; 18$VERSION = $Nagios::Plugin::Functions::VERSION;
18 19
20$DEFAULT_CONFIG_FILE = '/etc/nagios/plugins.cfg';
21
19# Standard defaults 22# Standard defaults
20my %DEFAULT = ( 23my %DEFAULT = (
21 timeout => 15, 24 timeout => 15,
@@ -36,6 +39,9 @@ my @ARGS = ({
36 spec => 'version|V', 39 spec => 'version|V',
37 help => "-V, --version\n Print version information", 40 help => "-V, --version\n Print version information",
38 }, { 41 }, {
42 spec => 'default-opts:s@',
43 help => "--default-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load default options (may repeat)",
44 }, {
39 spec => 'timeout|t=i', 45 spec => 'timeout|t=i',
40 help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)", 46 help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)",
41 default => $DEFAULT{timeout}, 47 default => $DEFAULT{timeout},
@@ -140,7 +146,7 @@ sub _process_specs_getopt_long
140 # Setup names and defaults 146 # Setup names and defaults
141 my $spec = $arg->{spec}; 147 my $spec = $arg->{spec};
142 # Use first arg as name (like Getopt::Long does) 148 # Use first arg as name (like Getopt::Long does)
143 $spec =~ s/=\w+$//; 149 $spec =~ s/[=:].*$//;
144 my $name = (split /\s*\|\s*/, $spec)[0]; 150 my $name = (split /\s*\|\s*/, $spec)[0];
145 $arg->{name} = $name; 151 $arg->{name} = $name;
146 if (defined $self->{$name}) { 152 if (defined $self->{$name}) {
@@ -182,6 +188,135 @@ sub _process_opts
182} 188}
183 189
184# ------------------------------------------------------------------------- 190# -------------------------------------------------------------------------
191# Default opts methods
192
193sub _load_config_section
194{
195 my $self = shift;
196 my ($section, $file, $flags) = @_;
197 $section ||= $self->{_attr}->{plugin};
198 $file ||= $DEFAULT_CONFIG_FILE;
199
200 $self->_die("Cannot find config file '$file'") if $flags->{fatal} && ! -f $file;
201
202 my $Config = Config::Tiny->read($file);
203 $self->_die("Cannot read config file '$file'") unless defined $Config;
204
205 $self->_die("Invalid section '$section' in config file '$file'")
206 if $flags->{fatal} && ! exists $Config->{$section};
207
208 return $Config->{$section};
209}
210
211# Helper method to setup a hash of spec definitions for _cmdline
212sub _setup_spec_index
213{
214 my $self = shift;
215 return if defined $self->{_spec};
216 $self->{_spec} = { map { $_->{name} => $_->{spec} } @{$self->{_args}} };
217}
218
219# Quote values that require it
220sub _cmdline_value
221{
222 my $self = shift;
223 local $_ = shift;
224 if (m/\s/ && (m/^[^"']/ || m/[^"']$/)) {
225 return qq("$_");
226 }
227 elsif ($_ eq '') {
228 return q("");
229 }
230 else {
231 return $_;
232 }
233}
234
235# Helper method to format key/values in $hash in a quasi-commandline format
236sub _cmdline
237{
238 my $self = shift;
239 my ($hash) = @_;
240 $hash ||= $self;
241
242 $self->_setup_spec_index;
243
244 my @args = ();
245 for my $key (sort keys %$hash) {
246 # Skip internal keys
247 next if $key =~ m/^_/;
248
249 # Skip defaults and internals
250 next if exists $DEFAULT{$key} && $hash->{$key} eq $DEFAULT{$key};
251 next if grep { $key eq $_ } qw(help usage version default-opts);
252 next unless defined $hash->{$key};
253
254 # Render arg
255 my $spec = $self->{_spec}->{$key} || '';
256 if ($spec =~ m/[=:].+$/) {
257 # Arg takes value - may be a scalar or an arrayref
258 for my $value (ref $hash->{$key} eq 'ARRAY' ? @{$hash->{$key}} : ( $hash->{$key} )) {
259 $value = $self->_cmdline_value($value);
260 if (length($key) > 1) {
261 push @args, sprintf "--%s=%s", $key, $value;
262 }
263 else {
264 push @args, "-$key", $value;
265 }
266 }
267 }
268
269 else {
270 # Flag - render long or short based on option length
271 push @args, (length($key) > 1 ? '--' : '-') . $key;
272 }
273 }
274
275 return wantarray ? @args : join(' ', @args);
276}
277
278# Process and load default-opts sections
279sub _process_default_opts
280{
281 my $self = shift;
282 my ($args) = @_;
283
284 my $defopts_list = $args->{'default-opts'};
285 my $defopts_explicit = 1;
286
287 # If no default_opts defined, force one implicitly
288 if (! $defopts_list) {
289 $defopts_list = [ '' ];
290 $defopts_explicit = 0;
291 }
292
293 my @sargs = ();
294 for my $defopts (@$defopts_list) {
295 $defopts ||= $self->{_attr}->{plugin};
296 my $section = $defopts;
297 my $file = '';
298
299 # Parse section@file
300 if ($defopts =~ m/^(\w*)@(.*?)\s*$/) {
301 $section = $1;
302 $file = $2;
303 }
304
305 # Load section args
306 my $shash = $self->_load_config_section($section, $file, { fatal => $defopts_explicit });
307
308 # Turn $shash into a series of commandline-like arguments
309 push @sargs, $self->_cmdline($shash);
310 }
311
312 # Reset ARGV to default-opts + original
313 @ARGV = ( @sargs, @{$self->{_attr}->{argv}} );
314
315 printf "[default-opts] %s %s\n", $self->{_attr}->{plugin}, join(' ', @ARGV)
316 if $args->{verbose} && $args->{verbose} >= 3;
317}
318
319# -------------------------------------------------------------------------
185# Public methods 320# Public methods
186 321
187# Define plugin argument 322# Define plugin argument
@@ -223,10 +358,21 @@ sub getopts
223 # Collate spec arguments for Getopt::Long 358 # Collate spec arguments for Getopt::Long
224 my @opt_array = $self->_process_specs_getopt_long; 359 my @opt_array = $self->_process_specs_getopt_long;
225 360
361 # Capture original @ARGV (for default-opts games)
362 $self->{_attr}->{argv} = [ @ARGV ];
363
226 # Call GetOptions using @opt_array 364 # Call GetOptions using @opt_array
227 my $ok = GetOptions($self, @opt_array); 365 my $args1 = {};
366 my $ok = GetOptions($args1, @opt_array);
367 # Invalid options - give usage message and exit
368 $self->_die($self->_usage) unless $ok;
228 369
229 # Invalid options - given usage message and exit 370 # Process default-opts
371 $self->_process_default_opts($args1);
372
373 # Call GetOptions again, this time including default-opts
374 $ok = GetOptions($self, @opt_array);
375 # Invalid options - give usage message and exit
230 $self->_die($self->_usage) unless $ok; 376 $self->_die($self->_usage) unless $ok;
231 377
232 # Process immediate options (possibly exiting) 378 # Process immediate options (possibly exiting)
@@ -264,6 +410,7 @@ sub _init
264 plugin => { default => $plugin }, 410 plugin => { default => $plugin },
265 blurb => 0, 411 blurb => 0,
266 extra => 0, 412 extra => 0,
413 'default-opts' => 0,
267 license => { default => $DEFAULT{license} }, 414 license => { default => $DEFAULT{license} },
268 timeout => { default => $DEFAULT{timeout} }, 415 timeout => { default => $DEFAULT{timeout} },
269 }); 416 });
@@ -295,11 +442,8 @@ __END__
295 442
296=head1 NAME 443=head1 NAME
297 444
298Nagios::Plugin::Getopt - OO perl module providing standardised argument processing for Nagios plugins 445Nagios::Plugin::Getopt - OO perl module providing standardised argument
299 446processing for Nagios plugins
300=head1 VERSION
301
302This documentation applies to version 0.01 of Nagios::Plugin::Getopt.
303 447
304 448
305=head1 SYNOPSIS 449=head1 SYNOPSIS