diff options
37 files changed, 553 insertions, 122 deletions
| @@ -1,10 +1,10 @@ | |||
| 1 | Revision history for Perl module Nagios::Plugin. | 1 | Revision history for Perl module Nagios::Plugin. |
| 2 | 2 | ||
| 3 | 0.16 ?? | 3 | 0.16 ?? |
| 4 | - perldoc updates to Performance, Threshold, and Range (Gavin) | 4 | - added automatic spec-to-help-text support to N::P::Getopt (Gavin) |
| 5 | - remove default use of Threshold from N::P::Performance (Gavin) | 5 | - added initial --extra-opts support to N::P::Getopt (Gavin) |
| 6 | - remove remaining Class::Struct usages from Threshold + Range (Gavin) | 6 | - removed default use of Threshold from N::P::Performance (Gavin) |
| 7 | - remove remaining Class::Struct usages from Performance (Gavin) | 7 | - removed remaining Class::Struct usages from Performance, Threshold, and Range (Gavin) |
| 8 | - fixed warnings when no uom specified for add_perfdata (Ton) | 8 | - fixed warnings when no uom specified for add_perfdata (Ton) |
| 9 | - added max_state function in N::P::Functions (Ton) | 9 | - added max_state function in N::P::Functions (Ton) |
| 10 | 10 | ||
| @@ -1,46 +1,56 @@ | |||
| 1 | Changes | 1 | Changes |
| 2 | Makefile.PL | 2 | Makefile.PL |
| 3 | MANIFEST | 3 | MANIFEST |
| 4 | META.yml | ||
| 4 | README | 5 | README |
| 5 | t/check_stuff.pl | 6 | lib/Nagios/Plugin.pm |
| 6 | t/check_stuff.t | 7 | lib/Nagios/Plugin/Performance.pm |
| 8 | lib/Nagios/Plugin/Range.pm | ||
| 9 | lib/Nagios/Plugin/Threshold.pm | ||
| 10 | lib/Nagios/Plugin/Functions.pm | ||
| 11 | lib/Nagios/Plugin/Getopt.pm | ||
| 12 | lib/Nagios/Plugin/ExitResult.pm | ||
| 7 | t/Nagios-Plugin-01.t | 13 | t/Nagios-Plugin-01.t |
| 8 | t/Nagios-Plugin-02.t | 14 | t/Nagios-Plugin-02.t |
| 9 | t/Nagios-Plugin-03.t | 15 | t/Nagios-Plugin-03.t |
| 10 | t/Nagios-Plugin-04.t | 16 | t/Nagios-Plugin-04.t |
| 11 | t/Nagios-Plugin-Functions-01.t | 17 | t/Nagios-Plugin-Functions-01.t |
| 12 | t/Nagios-Plugin-Functions-02.t | 18 | t/Nagios-Plugin-Functions-02.t |
| 19 | t/Nagios-Plugin-Functions-03.t | ||
| 13 | t/Nagios-Plugin-Getopt-01.t | 20 | t/Nagios-Plugin-Getopt-01.t |
| 14 | t/Nagios-Plugin-Getopt-02.t | 21 | t/Nagios-Plugin-Getopt-02.t |
| 15 | t/Nagios-Plugin-Getopt-03.t | 22 | t/Nagios-Plugin-Getopt-03.t |
| 23 | t/Nagios-Plugin-Getopt-04.t | ||
| 16 | t/Nagios-Plugin-Performance.t | 24 | t/Nagios-Plugin-Performance.t |
| 17 | t/Nagios-Plugin-Range.t | 25 | t/Nagios-Plugin-Range.t |
| 18 | t/Nagios-Plugin-Threshold.t | 26 | t/Nagios-Plugin-Threshold.t |
| 27 | t/check_stuff.pl | ||
| 28 | t/check_stuff.t | ||
| 19 | t/npg03/README | 29 | t/npg03/README |
| 20 | t/npg03/expected/00_basic | 30 | t/npg03/expected/00_basic |
| 31 | t/npg03/expected/00_noextra | ||
| 21 | t/npg03/expected/01_override1 | 32 | t/npg03/expected/01_override1 |
| 22 | t/npg03/expected/02_override2 | 33 | t/npg03/expected/02_override2 |
| 23 | t/npg03/expected/05_singlechar1 | 34 | t/npg03/expected/05_disk1 |
| 24 | t/npg03/expected/06_singlechar2 | 35 | t/npg03/expected/05_disk2 |
| 25 | t/npg03/expected/07_singlechar3 | 36 | t/npg03/expected/05_disk3 |
| 37 | t/npg03/expected/05_disk4 | ||
| 38 | t/npg03/expected/05_disk5 | ||
| 39 | t/npg03/expected/05_disk6 | ||
| 26 | t/npg03/expected/09_funnystuff | 40 | t/npg03/expected/09_funnystuff |
| 27 | t/npg03/expected/12_nosection_implicit | 41 | t/npg03/expected/12_nosection_implicit |
| 28 | t/npg03/input/00_basic | 42 | t/npg03/input/00_basic |
| 43 | t/npg03/input/00_noextra | ||
| 29 | t/npg03/input/01_override1 | 44 | t/npg03/input/01_override1 |
| 30 | t/npg03/input/02_override2 | 45 | t/npg03/input/02_override2 |
| 31 | t/npg03/input/05_singlechar1 | 46 | t/npg03/input/05_disk1 |
| 32 | t/npg03/input/06_singlechar2 | 47 | t/npg03/input/05_disk2 |
| 33 | t/npg03/input/07_singlechar3 | 48 | t/npg03/input/05_disk3 |
| 49 | t/npg03/input/05_disk4 | ||
| 50 | t/npg03/input/05_disk5 | ||
| 51 | t/npg03/input/05_disk6 | ||
| 34 | t/npg03/input/09_funnystuff | 52 | t/npg03/input/09_funnystuff |
| 35 | t/npg03/input/12_nosection_implicit | 53 | t/npg03/input/12_nosection_implicit |
| 36 | t/npg03/input/13_nosection_explicit_dies | 54 | t/npg03/input/13_nosection_explicit_dies |
| 37 | t/npg03/input/14_badsection_dies | 55 | t/npg03/input/14_badsection_dies |
| 38 | t/npg03/plugins.cfg | 56 | t/npg03/plugins.ini |
| 39 | lib/Nagios/Plugin.pm | ||
| 40 | lib/Nagios/Plugin/Performance.pm | ||
| 41 | lib/Nagios/Plugin/Range.pm | ||
| 42 | lib/Nagios/Plugin/Threshold.pm | ||
| 43 | lib/Nagios/Plugin/Functions.pm | ||
| 44 | lib/Nagios/Plugin/Getopt.pm | ||
| 45 | lib/Nagios/Plugin/ExitResult.pm | ||
| 46 | META.yml Module meta-data (added by MakeMaker) | ||
diff --git a/lib/Nagios/Plugin/Config.pm b/lib/Nagios/Plugin/Config.pm new file mode 100644 index 0000000..92193c2 --- /dev/null +++ b/lib/Nagios/Plugin/Config.pm | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | package Nagios::Plugin::Config; | ||
| 2 | |||
| 3 | use strict; | ||
| 4 | use Carp; | ||
| 5 | use File::Spec; | ||
| 6 | use base qw(Config::Tiny); | ||
| 7 | |||
| 8 | my $FILENAME1 = 'plugins.ini'; | ||
| 9 | my $FILENAME2 = 'nagios-plugins.ini'; | ||
| 10 | |||
| 11 | # Config paths ending in nagios (search for $FILENAME1) | ||
| 12 | my @NAGIOS_CONFIG_PATH = qw(/etc/nagios /usr/local/nagios/etc /usr/local/etc/nagios /etc/opt/nagios); | ||
| 13 | # Config paths not ending in nagios (search for $FILENAME2) | ||
| 14 | my @CONFIG_PATH = qw(/etc /usr/local/etc /etc/opt); | ||
| 15 | |||
| 16 | # Override Config::Tiny::read to default the filename, if not given | ||
| 17 | sub read | ||
| 18 | { | ||
| 19 | my $class = shift; | ||
| 20 | |||
| 21 | unless ($_[0]) { | ||
| 22 | SEARCH: { | ||
| 23 | if ($ENV{NAGIOS_CONFIG_PATH}) { | ||
| 24 | for (split /:/, $ENV{NAGIOS_CONFIG_PATH}) { | ||
| 25 | my $file = File::Spec->catfile($_, $FILENAME1); | ||
| 26 | unshift(@_, $file), last SEARCH if -f $file; | ||
| 27 | $file = File::Spec->catfile($_, $FILENAME2); | ||
| 28 | unshift(@_, $file), last SEARCH if -f $file; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | for (@NAGIOS_CONFIG_PATH) { | ||
| 32 | my $file = File::Spec->catfile($_, $FILENAME1); | ||
| 33 | unshift(@_, $file), last SEARCH if -f $file; | ||
| 34 | } | ||
| 35 | for (@CONFIG_PATH) { | ||
| 36 | my $file = File::Spec->catfile($_, $FILENAME2); | ||
| 37 | unshift(@_, $file), last SEARCH if -f $file; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | croak "Cannot find '$FILENAME1' or '$FILENAME2' in any standard location." unless $_[0]; | ||
| 42 | } | ||
| 43 | |||
| 44 | $class->SUPER::read( @_ ); | ||
| 45 | } | ||
| 46 | |||
| 47 | # Straight from Config::Tiny - only changes are repeated property key support | ||
| 48 | # Would be nice if we could just override the per-line handling ... | ||
| 49 | sub read_string | ||
| 50 | { | ||
| 51 | my $class = ref $_[0] ? ref shift : shift; | ||
| 52 | my $self = bless {}, $class; | ||
| 53 | return undef unless defined $_[0]; | ||
| 54 | |||
| 55 | # Parse the file | ||
| 56 | my $ns = '_'; | ||
| 57 | my $counter = 0; | ||
| 58 | foreach ( split /(?:\015{1,2}\012|\015|\012)/, shift ) { | ||
| 59 | $counter++; | ||
| 60 | |||
| 61 | # Skip comments and empty lines | ||
| 62 | next if /^\s*(?:\#|\;|$)/; | ||
| 63 | |||
| 64 | # Handle section headers | ||
| 65 | if ( /^\s*\[\s*(.+?)\s*\]\s*$/ ) { | ||
| 66 | # Create the sub-hash if it doesn't exist. | ||
| 67 | # Without this sections without keys will not | ||
| 68 | # appear at all in the completed struct. | ||
| 69 | $self->{$ns = $1} ||= {}; | ||
| 70 | next; | ||
| 71 | } | ||
| 72 | |||
| 73 | # Handle properties | ||
| 74 | if ( /^\s*([^=]+?)\s*=\s*(.*?)\s*$/ ) { | ||
| 75 | $self->{$ns}->{$1} = defined $self->{$ns}->{$1} ? | ||
| 76 | [ $self->{$ns}->{$1}, $2 ] : | ||
| 77 | $2; | ||
| 78 | next; | ||
| 79 | } | ||
| 80 | |||
| 81 | return $self->_error( "Syntax error at line $counter: '$_'" ); | ||
| 82 | } | ||
| 83 | |||
| 84 | $self; | ||
| 85 | } | ||
| 86 | |||
| 87 | sub write { croak "Write access not permitted" } | ||
| 88 | |||
| 89 | 1; | ||
| 90 | |||
| 91 | =head1 NAME | ||
| 92 | |||
| 93 | Nagios::Plugin::Config - read nagios plugin .ini style config files | ||
| 94 | |||
| 95 | =head1 SYNOPSIS | ||
| 96 | |||
| 97 | # Read given nagios plugin config file | ||
| 98 | $Config = Nagios::Plugin::Config->read( '/etc/nagios/plugins.ini' ); | ||
| 99 | |||
| 100 | # Search for and read default nagios plugin config file | ||
| 101 | $Config = Nagios::Plugin::Config->read(); | ||
| 102 | |||
| 103 | # Access sections and properties (returns scalars or arrayrefs) | ||
| 104 | $rootproperty = $Config->{_}->{rootproperty}; | ||
| 105 | $one = $Config->{section}->{one}; | ||
| 106 | $Foo = $Config->{section}->{Foo}; | ||
| 107 | |||
| 108 | =head1 DESCRIPTION | ||
| 109 | |||
| 110 | Nagios::Plugin::Config is a subclass of the excellent Config::Tiny, | ||
| 111 | with the following changes: | ||
| 112 | |||
| 113 | =over 4 | ||
| 114 | |||
| 115 | =item | ||
| 116 | |||
| 117 | Repeated keys are allowed within sections, returning lists instead of scalars | ||
| 118 | |||
| 119 | =item | ||
| 120 | |||
| 121 | Write functionality has been removed i.e. access is read only | ||
| 122 | |||
| 123 | =item | ||
| 124 | |||
| 125 | Nagios::Plugin::Config searches for a default nagios plugins file if no explicit | ||
| 126 | filename is given to C<read()>. The current standard locations checked are: | ||
| 127 | |||
| 128 | =over 4 | ||
| 129 | |||
| 130 | =item /etc/nagios/plugins.ini | ||
| 131 | |||
| 132 | =item /usr/local/nagios/etc/plugins.ini | ||
| 133 | |||
| 134 | =item /usr/local/etc/nagios /etc/opt/nagios/plugins.ini | ||
| 135 | |||
| 136 | =item /etc/nagios-plugins.ini | ||
| 137 | |||
| 138 | =item /usr/local/etc/nagios-plugins.ini | ||
| 139 | |||
| 140 | =item /etc/opt/nagios-plugins.ini | ||
| 141 | |||
| 142 | =back | ||
| 143 | |||
| 144 | To use a custom location, set a C<NAGIOS_CONFIG_PATH> environment variable | ||
| 145 | to the set of directories that should be checked. The first C<plugins.ini> or | ||
| 146 | C<nagios-plugins.ini> file found will be used. | ||
| 147 | |||
| 148 | =back | ||
| 149 | |||
| 150 | |||
| 151 | =head1 SEE ALSO | ||
| 152 | |||
| 153 | L<Config::Tiny>, L<Nagios::Plugin> | ||
| 154 | |||
| 155 | |||
| 156 | =head1 AUTHORS | ||
| 157 | |||
| 158 | This code is maintained by the Nagios Plugin Development Team: | ||
| 159 | L<http://nagiosplug.sourceforge.net>. | ||
| 160 | |||
| 161 | |||
| 162 | =head1 COPYRIGHT and LICENCE | ||
| 163 | |||
| 164 | Copyright (C) 2006-2007 by Nagios Plugin Development Team | ||
| 165 | |||
| 166 | This library is free software; you can redistribute it and/or modify | ||
| 167 | it under the same terms as Perl itself. | ||
| 168 | |||
| 169 | =cut | ||
| 170 | |||
diff --git a/lib/Nagios/Plugin/Functions.pm b/lib/Nagios/Plugin/Functions.pm index 526dbed..751251f 100644 --- a/lib/Nagios/Plugin/Functions.pm +++ b/lib/Nagios/Plugin/Functions.pm | |||
| @@ -46,6 +46,13 @@ our %STATUS_TEXT = reverse %ERRORS; | |||
| 46 | my $_fake_exit = 0; | 46 | my $_fake_exit = 0; |
| 47 | sub _fake_exit { @_ ? $_fake_exit = shift : $_fake_exit }; | 47 | sub _fake_exit { @_ ? $_fake_exit = shift : $_fake_exit }; |
| 48 | 48 | ||
| 49 | # Tweak default die handling: die is cool because it allows capturing both return codes and | ||
| 50 | # output via eval, but the Nagios Plugin Guidelines like STDOUT over STDERR | ||
| 51 | $SIG{__DIE__} = sub { | ||
| 52 | print STDOUT shift; | ||
| 53 | exit $!; | ||
| 54 | }; | ||
| 55 | |||
| 49 | sub get_shortname { | 56 | sub get_shortname { |
| 50 | my %arg = @_; | 57 | my %arg = @_; |
| 51 | 58 | ||
| @@ -390,7 +397,6 @@ This code is maintained by the Nagios Plugin Development Team: http://nagiosplug | |||
| 390 | Copyright (C) 2006 by Nagios Plugin Development Team | 397 | Copyright (C) 2006 by Nagios Plugin Development Team |
| 391 | 398 | ||
| 392 | This library is free software; you can redistribute it and/or modify | 399 | This library is free software; you can redistribute it and/or modify |
| 393 | it under the same terms as Perl itself, either Perl version 5.8.4 or, | 400 | it under the same terms as Perl itself. |
| 394 | at your option, any later version of Perl 5 you may have available. | ||
| 395 | 401 | ||
| 396 | =cut | 402 | =cut |
diff --git a/lib/Nagios/Plugin/Getopt.pm b/lib/Nagios/Plugin/Getopt.pm index 806a6a0..743bf7e 100644 --- a/lib/Nagios/Plugin/Getopt.pm +++ b/lib/Nagios/Plugin/Getopt.pm | |||
| @@ -10,15 +10,13 @@ use File::Basename; | |||
| 10 | use Getopt::Long qw(:config no_ignore_case bundling); | 10 | use Getopt::Long qw(:config no_ignore_case bundling); |
| 11 | use Carp; | 11 | use Carp; |
| 12 | use Params::Validate qw(:all); | 12 | use Params::Validate qw(:all); |
| 13 | use Config::Tiny; | ||
| 14 | use base qw(Class::Accessor); | 13 | use base qw(Class::Accessor); |
| 15 | 14 | ||
| 16 | use Nagios::Plugin::Functions; | 15 | use Nagios::Plugin::Functions; |
| 17 | use vars qw($VERSION $DEFAULT_CONFIG_FILE); | 16 | use Nagios::Plugin::Config; |
| 17 | use vars qw($VERSION); | ||
| 18 | $VERSION = $Nagios::Plugin::Functions::VERSION; | 18 | $VERSION = $Nagios::Plugin::Functions::VERSION; |
| 19 | 19 | ||
| 20 | $DEFAULT_CONFIG_FILE = '/etc/nagios/plugins.cfg'; | ||
| 21 | |||
| 22 | # Standard defaults | 20 | # Standard defaults |
| 23 | my %DEFAULT = ( | 21 | my %DEFAULT = ( |
| 24 | timeout => 15, | 22 | timeout => 15, |
| @@ -39,8 +37,8 @@ my @ARGS = ({ | |||
| 39 | spec => 'version|V', | 37 | spec => 'version|V', |
| 40 | help => "-V, --version\n Print version information", | 38 | help => "-V, --version\n Print version information", |
| 41 | }, { | 39 | }, { |
| 42 | spec => 'default-opts:s@', | 40 | spec => 'extra-opts:s@', |
| 43 | help => "--default-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load default options (may repeat)", | 41 | help => "--extra-opts=[<section>[@<config_file>]]\n Section and/or config_file from which to load extra options (may repeat)", |
| 44 | }, { | 42 | }, { |
| 45 | spec => 'timeout|t=i', | 43 | spec => 'timeout|t=i', |
| 46 | help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)", | 44 | help => "-t, --timeout=INTEGER\n Seconds before plugin times out (default: %s)", |
| @@ -77,6 +75,37 @@ sub _attr | |||
| 77 | $self->{_attr}->{$item} . "\n" . $extra; | 75 | $self->{_attr}->{$item} . "\n" . $extra; |
| 78 | } | 76 | } |
| 79 | 77 | ||
| 78 | # Turn argument spec into help-style output | ||
| 79 | sub _spec_to_help | ||
| 80 | { | ||
| 81 | my ($self, $spec, $label) = @_; | ||
| 82 | |||
| 83 | my ($opts, $type) = split /=/, $spec, 2; | ||
| 84 | my (@short, @long); | ||
| 85 | for (split /\|/, $opts) { | ||
| 86 | if (length $_ == 1) { | ||
| 87 | push @short, "-$_"; | ||
| 88 | } else { | ||
| 89 | push @long, "--$_"; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | my $help = join(', ', @short, @long); | ||
| 94 | if ($type) { | ||
| 95 | if ($label) { | ||
| 96 | $help .= '=' . $label; | ||
| 97 | } | ||
| 98 | else { | ||
| 99 | $help .= $type eq 'i' ? '=INTEGER' : '=STRING'; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | elsif ($label) { | ||
| 103 | carp "Label specified, but there's no type in spec '$spec'"; | ||
| 104 | } | ||
| 105 | $help .= "\n "; | ||
| 106 | return $help; | ||
| 107 | } | ||
| 108 | |||
| 80 | # Options output for plugin -h | 109 | # Options output for plugin -h |
| 81 | sub _options | 110 | sub _options |
| 82 | { | 111 | { |
| @@ -94,10 +123,29 @@ sub _options | |||
| 94 | 123 | ||
| 95 | my @options = (); | 124 | my @options = (); |
| 96 | for my $arg (@args, @defer) { | 125 | for my $arg (@args, @defer) { |
| 97 | if ($arg->{help} =~ m/%s/) { | 126 | my $help_array = ref $arg->{help} && ref $arg->{help} eq 'ARRAY' ? $arg->{help} : [ $arg->{help} ]; |
| 98 | push @options, sprintf($arg->{help}, $arg->{default} || ''); | 127 | my $label_array = $arg->{label} && ref $arg->{label} && ref $arg->{label} eq 'ARRAY' ? $arg->{label} : [ $arg->{label} ]; |
| 128 | my $help_string = ''; | ||
| 129 | for (my $i = 0; $i <= $#$help_array; $i++) { | ||
| 130 | my $help = $help_array->[$i]; | ||
| 131 | # Add spec arguments to help if not already there | ||
| 132 | if ($help =~ m/^\s*-/) { | ||
| 133 | $help_string .= $help; | ||
| 134 | } | ||
| 135 | else { | ||
| 136 | $help_string .= $self->_spec_to_help($arg->{spec}, $label_array->[$i]) . $help; | ||
| 137 | $help_string .= "\n " if $i < $#$help_array; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | # Add help_string to @options | ||
| 142 | if ($help_string =~ m/%s/) { | ||
| 143 | my $default = defined $arg->{default} ? $arg->{default} : ''; | ||
| 144 | # We only handle '%s' formats here, so escape everything else | ||
| 145 | $help_string =~ s/%(?!s)/%%/g; | ||
| 146 | push @options, sprintf($help_string, $default, $default, $default, $default); | ||
| 99 | } else { | 147 | } else { |
| 100 | push @options, $arg->{help}; | 148 | push @options, $help_string; |
| 101 | } | 149 | } |
| 102 | } | 150 | } |
| 103 | 151 | ||
| @@ -195,15 +243,12 @@ sub _load_config_section | |||
| 195 | my $self = shift; | 243 | my $self = shift; |
| 196 | my ($section, $file, $flags) = @_; | 244 | my ($section, $file, $flags) = @_; |
| 197 | $section ||= $self->{_attr}->{plugin}; | 245 | $section ||= $self->{_attr}->{plugin}; |
| 198 | $file ||= $DEFAULT_CONFIG_FILE; | ||
| 199 | |||
| 200 | $self->_die("Cannot find config file '$file'") if $flags->{fatal} && ! -f $file; | ||
| 201 | 246 | ||
| 202 | my $Config = Config::Tiny->read($file); | 247 | my $Config = Nagios::Plugin::Config->read($file); |
| 203 | $self->_die("Cannot read config file '$file'") unless defined $Config; | ||
| 204 | 248 | ||
| 249 | # TODO: is this check sane? Does --extra-opts=foo require a [foo] section? | ||
| 205 | $self->_die("Invalid section '$section' in config file '$file'") | 250 | $self->_die("Invalid section '$section' in config file '$file'") |
| 206 | if $flags->{fatal} && ! exists $Config->{$section}; | 251 | unless exists $Config->{$section}; |
| 207 | 252 | ||
| 208 | return $Config->{$section}; | 253 | return $Config->{$section}; |
| 209 | } | 254 | } |
| @@ -248,7 +293,7 @@ sub _cmdline | |||
| 248 | 293 | ||
| 249 | # Skip defaults and internals | 294 | # Skip defaults and internals |
| 250 | next if exists $DEFAULT{$key} && $hash->{$key} eq $DEFAULT{$key}; | 295 | next if exists $DEFAULT{$key} && $hash->{$key} eq $DEFAULT{$key}; |
| 251 | next if grep { $key eq $_ } qw(help usage version default-opts); | 296 | next if grep { $key eq $_ } qw(help usage version extra-opts); |
| 252 | next unless defined $hash->{$key}; | 297 | next unless defined $hash->{$key}; |
| 253 | 298 | ||
| 254 | # Render arg | 299 | # Render arg |
| @@ -275,44 +320,37 @@ sub _cmdline | |||
| 275 | return wantarray ? @args : join(' ', @args); | 320 | return wantarray ? @args : join(' ', @args); |
| 276 | } | 321 | } |
| 277 | 322 | ||
| 278 | # Process and load default-opts sections | 323 | # Process and load extra-opts sections |
| 279 | sub _process_default_opts | 324 | sub _process_extra_opts |
| 280 | { | 325 | { |
| 281 | my $self = shift; | 326 | my $self = shift; |
| 282 | my ($args) = @_; | 327 | my ($args) = @_; |
| 283 | 328 | ||
| 284 | my $defopts_list = $args->{'default-opts'}; | 329 | my $extopts_list = $args->{'extra-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 | 330 | ||
| 293 | my @sargs = (); | 331 | my @sargs = (); |
| 294 | for my $defopts (@$defopts_list) { | 332 | for my $extopts (@$extopts_list) { |
| 295 | $defopts ||= $self->{_attr}->{plugin}; | 333 | $extopts ||= $self->{_attr}->{plugin}; |
| 296 | my $section = $defopts; | 334 | my $section = $extopts; |
| 297 | my $file = ''; | 335 | my $file = ''; |
| 298 | 336 | ||
| 299 | # Parse section@file | 337 | # Parse section@file |
| 300 | if ($defopts =~ m/^(\w*)@(.*?)\s*$/) { | 338 | if ($extopts =~ m/^(\w*)@(.*?)\s*$/) { |
| 301 | $section = $1; | 339 | $section = $1; |
| 302 | $file = $2; | 340 | $file = $2; |
| 303 | } | 341 | } |
| 304 | 342 | ||
| 305 | # Load section args | 343 | # Load section args |
| 306 | my $shash = $self->_load_config_section($section, $file, { fatal => $defopts_explicit }); | 344 | my $shash = $self->_load_config_section($section, $file); |
| 307 | 345 | ||
| 308 | # Turn $shash into a series of commandline-like arguments | 346 | # Turn $shash into a series of commandline-like arguments |
| 309 | push @sargs, $self->_cmdline($shash); | 347 | push @sargs, $self->_cmdline($shash); |
| 310 | } | 348 | } |
| 311 | 349 | ||
| 312 | # Reset ARGV to default-opts + original | 350 | # Reset ARGV to extra-opts + original |
| 313 | @ARGV = ( @sargs, @{$self->{_attr}->{argv}} ); | 351 | @ARGV = ( @sargs, @{$self->{_attr}->{argv}} ); |
| 314 | 352 | ||
| 315 | printf "[default-opts] %s %s\n", $self->{_attr}->{plugin}, join(' ', @ARGV) | 353 | printf "[extra-opts] %s %s\n", $self->{_attr}->{plugin}, join(' ', @ARGV) |
| 316 | if $args->{verbose} && $args->{verbose} >= 3; | 354 | if $args->{verbose} && $args->{verbose} >= 3; |
| 317 | } | 355 | } |
| 318 | 356 | ||
| @@ -332,17 +370,19 @@ sub arg | |||
| 332 | help => 1, | 370 | help => 1, |
| 333 | default => 0, | 371 | default => 0, |
| 334 | required => 0, | 372 | required => 0, |
| 373 | label => 0, | ||
| 335 | }); | 374 | }); |
| 336 | } | 375 | } |
| 337 | 376 | ||
| 338 | # Positional args | 377 | # Positional args |
| 339 | else { | 378 | else { |
| 340 | my @args = validate_pos(@_, 1, 1, 0, 0); | 379 | my @args = validate_pos(@_, 1, 1, 0, 0, 0); |
| 341 | %args = ( | 380 | %args = ( |
| 342 | spec => $args[0], | 381 | spec => $args[0], |
| 343 | help => $args[1], | 382 | help => $args[1], |
| 344 | default => $args[2], | 383 | default => $args[2], |
| 345 | required => $args[3], | 384 | required => $args[3], |
| 385 | label => $args[4], | ||
| 346 | ); | 386 | ); |
| 347 | } | 387 | } |
| 348 | 388 | ||
| @@ -358,7 +398,7 @@ sub getopts | |||
| 358 | # Collate spec arguments for Getopt::Long | 398 | # Collate spec arguments for Getopt::Long |
| 359 | my @opt_array = $self->_process_specs_getopt_long; | 399 | my @opt_array = $self->_process_specs_getopt_long; |
| 360 | 400 | ||
| 361 | # Capture original @ARGV (for default-opts games) | 401 | # Capture original @ARGV (for extra-opts games) |
| 362 | $self->{_attr}->{argv} = [ @ARGV ]; | 402 | $self->{_attr}->{argv} = [ @ARGV ]; |
| 363 | 403 | ||
| 364 | # Call GetOptions using @opt_array | 404 | # Call GetOptions using @opt_array |
| @@ -367,10 +407,10 @@ sub getopts | |||
| 367 | # Invalid options - give usage message and exit | 407 | # Invalid options - give usage message and exit |
| 368 | $self->_die($self->_usage) unless $ok; | 408 | $self->_die($self->_usage) unless $ok; |
| 369 | 409 | ||
| 370 | # Process default-opts | 410 | # Process extra-opts |
| 371 | $self->_process_default_opts($args1); | 411 | $self->_process_extra_opts($args1); |
| 372 | 412 | ||
| 373 | # Call GetOptions again, this time including default-opts | 413 | # Call GetOptions again, this time including extra-opts |
| 374 | $ok = GetOptions($self, @opt_array); | 414 | $ok = GetOptions($self, @opt_array); |
| 375 | # Invalid options - give usage message and exit | 415 | # Invalid options - give usage message and exit |
| 376 | $self->_die($self->_usage) unless $ok; | 416 | $self->_die($self->_usage) unless $ok; |
| @@ -410,7 +450,7 @@ sub _init | |||
| 410 | plugin => { default => $plugin }, | 450 | plugin => { default => $plugin }, |
| 411 | blurb => 0, | 451 | blurb => 0, |
| 412 | extra => 0, | 452 | extra => 0, |
| 413 | 'default-opts' => 0, | 453 | 'extra-opts' => 0, |
| 414 | license => { default => $DEFAULT{license} }, | 454 | license => { default => $DEFAULT{license} }, |
| 415 | timeout => { default => $DEFAULT{timeout} }, | 455 | timeout => { default => $DEFAULT{timeout} }, |
| 416 | }); | 456 | }); |
| @@ -452,17 +492,16 @@ processing for Nagios plugins | |||
| 452 | 492 | ||
| 453 | # Instantiate object (usage is mandatory) | 493 | # Instantiate object (usage is mandatory) |
| 454 | $ng = Nagios::Plugin::Getopt->new( | 494 | $ng = Nagios::Plugin::Getopt->new( |
| 455 | usage => "Usage: %s -H <host> -w <warning_threshold> | 495 | usage => "Usage: %s -H <host> -w <warning> -c <critical>", |
| 456 | -c <critical threshold>", | 496 | version => '0.1', |
| 457 | version => '0.01', | ||
| 458 | url => 'http://www.openfusion.com.au/labs/nagios/', | 497 | url => 'http://www.openfusion.com.au/labs/nagios/', |
| 459 | blurb => 'This plugin tests various stuff.', | 498 | blurb => 'This plugin tests various stuff.', |
| 460 | ); | 499 | ); |
| 461 | 500 | ||
| 462 | # Add argument - named parameters (spec and help are mandatory) | 501 | # Add argument - named parameters (spec and help are mandatory) |
| 463 | $ng->arg( | 502 | $ng->arg( |
| 464 | spec => 'critical|c=s', | 503 | spec => 'critical|c=i', |
| 465 | help => qq(-c, --critical=INTEGER\n Exit with CRITICAL status if fewer than INTEGER foobars are free), | 504 | help => q(Exit with CRITICAL status if fewer than INTEGER foobars are free), |
| 466 | required => 1, | 505 | required => 1, |
| 467 | default => 10, | 506 | default => 10, |
| 468 | ); | 507 | ); |
| @@ -470,8 +509,8 @@ processing for Nagios plugins | |||
| 470 | # Add argument - positional parameters - arg spec, help text, | 509 | # Add argument - positional parameters - arg spec, help text, |
| 471 | # default value, required? (first two mandatory) | 510 | # default value, required? (first two mandatory) |
| 472 | $ng->arg( | 511 | $ng->arg( |
| 473 | 'warning|w=s', | 512 | 'warning|w=i', |
| 474 | qq(-w, --warning=INTEGER\n Exit with WARNING status if fewer than INTEGER foobars are free), | 513 | q(Exit with WARNING status if fewer than INTEGER foobars are free), |
| 475 | 5, | 514 | 5, |
| 476 | 1); | 515 | 1); |
| 477 | 516 | ||
| @@ -545,9 +584,10 @@ License text, included in the longer --help output (see below for an | |||
| 545 | example). By default, this is set to the standard nagios plugins | 584 | example). By default, this is set to the standard nagios plugins |
| 546 | GPL license text: | 585 | GPL license text: |
| 547 | 586 | ||
| 548 | This nagios plugin is free software, and comes with ABSOLUTELY NO WARRANTY. | 587 | This nagios plugin is free software, and comes with ABSOLUTELY |
| 549 | It may be used, redistributed and/or modified under the terms of the GNU | 588 | NO WARRANTY. It may be used, redistributed and/or modified under |
| 550 | General Public Licence (see http://www.fsf.org/licensing/licenses/gpl.txt). | 589 | the terms of the GNU General Public Licence (see |
| 590 | http://www.fsf.org/licensing/licenses/gpl.txt). | ||
| 551 | 591 | ||
| 552 | Provide your own to replace this text in the help output. | 592 | Provide your own to replace this text in the help output. |
| 553 | 593 | ||
| @@ -603,8 +643,8 @@ example: | |||
| 603 | -H, --hostname=ADDRESS | 643 | -H, --hostname=ADDRESS |
| 604 | Host name or IP address | 644 | Host name or IP address |
| 605 | -p, --ports=STRING | 645 | -p, --ports=STRING |
| 606 | Port numbers to check. Format: comma-separated, colons or hyphens for ranges, | 646 | Port numbers to check. Format: comma-separated, colons for ranges, |
| 607 | no spaces e.g. 8700:8705,8710-8715,8760 | 647 | no spaces e.g. 8700:8705,8710:8715,8760 |
| 608 | -t, --timeout=INTEGER | 648 | -t, --timeout=INTEGER |
| 609 | Seconds before plugin times out (default: 15) | 649 | Seconds before plugin times out (default: 15) |
| 610 | -v, --verbose | 650 | -v, --verbose |
| @@ -615,21 +655,25 @@ example: | |||
| 615 | 655 | ||
| 616 | You can define arguments for your plugin using the arg() method, which | 656 | You can define arguments for your plugin using the arg() method, which |
| 617 | supports both named and positional arguments. In both cases | 657 | supports both named and positional arguments. In both cases |
| 618 | the 'spec' and 'help' arguments are required, while the 'default' | 658 | the C<spec> and C<help> arguments are required, while the C<label>, |
| 619 | and 'required' arguments are optional: | 659 | C<default>, and C<required> arguments are optional: |
| 620 | 660 | ||
| 621 | # Define --hello argument (named parameters) | 661 | # Define --hello argument (named parameters) |
| 622 | $ng->arg( | 662 | $ng->arg( |
| 623 | spec => 'hello=s', | 663 | spec => 'hello|h=s', |
| 624 | help => "--hello\n Hello string", | 664 | help => "Hello string", |
| 625 | required => 1, | 665 | required => 1, |
| 626 | ); | 666 | ); |
| 627 | 667 | ||
| 628 | # Define --hello argument (positional parameters) | 668 | # Define --hello argument (positional parameters) |
| 629 | # Parameter order is 'spec', 'help', 'default', 'required?' | 669 | # Parameter order is 'spec', 'help', 'default', 'required?', 'label' |
| 630 | $ng->arg('hello=s', "--hello\n Hello string", undef, 1); | 670 | $ng->arg('hello|h=s', "Hello parameter (default %s)", 5, 1); |
| 671 | |||
| 672 | =over 4 | ||
| 631 | 673 | ||
| 632 | The 'spec' argument (the first argument in the positional variant) is a | 674 | =item spec |
| 675 | |||
| 676 | The C<spec> argument (the first argument in the positional variant) is a | ||
| 633 | L<Getopt::Long> argument specification. See L<Getopt::Long> for the details, | 677 | L<Getopt::Long> argument specification. See L<Getopt::Long> for the details, |
| 634 | but basically it is a series of one or more argument names for this argument | 678 | but basically it is a series of one or more argument names for this argument |
| 635 | (separated by '|'), suffixed with an '=<type>' indicator if the argument | 679 | (separated by '|'), suffixed with an '=<type>' indicator if the argument |
| @@ -651,24 +695,105 @@ and so on. The following are some examples: | |||
| 651 | 695 | ||
| 652 | =back | 696 | =back |
| 653 | 697 | ||
| 654 | The 'help' argument is a string displayed in the --help option list output. | 698 | =item help |
| 655 | If the string contains a '%s' it will be formatted via L<sprintf> with the | 699 | |
| 656 | 'default' as the argument i.e. | 700 | The C<help> argument is a string displayed in the --help option list output, |
| 701 | or it can be a list (an arrayref) of such strings, for multi-line help (see | ||
| 702 | below). | ||
| 703 | |||
| 704 | The help string is munged in two ways: | ||
| 705 | |||
| 706 | =over 4 | ||
| 707 | |||
| 708 | =item | ||
| 709 | |||
| 710 | First, if the help string does NOT begins with a '-' sign, it is prefixed | ||
| 711 | by an expanded form of the C<spec> argument. For instance, the following | ||
| 712 | hello argument: | ||
| 713 | |||
| 714 | $ng->arg( | ||
| 715 | spec => 'hello|h=s', | ||
| 716 | help => "Hello string", | ||
| 717 | ); | ||
| 718 | |||
| 719 | would be displayed in the help output as: | ||
| 720 | |||
| 721 | -h, --hello=STRING | ||
| 722 | Hello string | ||
| 723 | |||
| 724 | where the '-h, --hello=STRING' part is derived from the spec definition | ||
| 725 | (by convention with short args first, then long, then label/type, if any). | ||
| 726 | |||
| 727 | =item | ||
| 728 | |||
| 729 | Second, if the string contains a '%s' it will be formatted via | ||
| 730 | C<sprintf> with the 'default' as the argument i.e. | ||
| 657 | 731 | ||
| 658 | sprintf($help, $default) | 732 | sprintf($help, $default) |
| 659 | 733 | ||
| 660 | A gotcha is that standard percentage signs also need to be escaped | 734 | =back |
| 661 | (i.e. '%%') in this case. | 735 | |
| 736 | Multi-line help is useful in cases where an argument can be of different types | ||
| 737 | and you want to make this explicit in your help output e.g. | ||
| 738 | |||
| 739 | $ng->arg( | ||
| 740 | spec => 'warning|w=s', | ||
| 741 | help => [ | ||
| 742 | 'Exit with WARNING status if less than BYTES bytes of disk are free', | ||
| 743 | 'Exit with WARNING status if less than PERCENT of disk is free', | ||
| 744 | ], | ||
| 745 | label => [ 'BYTES', 'PERCENT%' ], | ||
| 746 | ); | ||
| 747 | |||
| 748 | would be displayed in the help output as: | ||
| 749 | |||
| 750 | -w, --warning=BYTES | ||
| 751 | Exit with WARNING status if less than BYTES bytes of disk are free | ||
| 752 | -w, --warning=PERCENT% | ||
| 753 | Exit with WARNING status if less than PERCENT of disk space is free | ||
| 754 | |||
| 755 | Note that in this case we've also specified explicit labels in another | ||
| 756 | arrayref corresponding to the C<help> one - if this had been omitted | ||
| 757 | the types would have defaulted to 'STRING', instead of 'BYTES' and | ||
| 758 | 'PERCENT%'. | ||
| 759 | |||
| 760 | |||
| 761 | =item label | ||
| 762 | |||
| 763 | The C<label> argument is a scalar or an arrayref (see 'Multi-line help' | ||
| 764 | description above) that overrides the standard type expansion when generating | ||
| 765 | help text from the spec definition. By default, C<spec=i> arguments are | ||
| 766 | labelled as C<=INTEGER> in the help text, and C<spec=s> arguments are labelled | ||
| 767 | as C<=STRING>. By supplying your own C<label> argument you can override these | ||
| 768 | standard 'INTEGER' and 'STRING' designations. | ||
| 769 | |||
| 770 | For multi-line help, you can supply an ordered list (arrayref) of labels to | ||
| 771 | match the list of help strings e.g. | ||
| 772 | |||
| 773 | label => [ 'BYTES', 'PERCENT%' ] | ||
| 662 | 774 | ||
| 663 | The 'default' argument is the default value to be given to this parameter | 775 | Any labels that are left as undef (or just omitted, if trailing) will just |
| 776 | use the default 'INTEGER' or 'STRING' designations e.g. | ||
| 777 | |||
| 778 | label => [ undef, 'PERCENT%' ] | ||
| 779 | |||
| 780 | |||
| 781 | =item default | ||
| 782 | |||
| 783 | The C<default> argument is the default value to be given to this parameter | ||
| 664 | if none is explicitly supplied. | 784 | if none is explicitly supplied. |
| 665 | 785 | ||
| 666 | The 'required' argument is a boolean used to indicate that this argument | 786 | |
| 787 | =item required | ||
| 788 | |||
| 789 | The C<required> argument is a boolean used to indicate that this argument | ||
| 667 | is mandatory (Nagios::Plugin::Getopt will exit with your usage message and | 790 | is mandatory (Nagios::Plugin::Getopt will exit with your usage message and |
| 668 | a 'Missing argument' indicator if any required arguments are not supplied). | 791 | a 'Missing argument' indicator if any required arguments are not supplied). |
| 669 | 792 | ||
| 793 | =back | ||
| 794 | |||
| 670 | Note that --help lists your arguments in the order they are defined, so | 795 | Note that --help lists your arguments in the order they are defined, so |
| 671 | you might want to order your arg() calls accordingly. | 796 | you should order your C<arg()> calls accordingly. |
| 672 | 797 | ||
| 673 | 798 | ||
| 674 | =head2 GETOPTS | 799 | =head2 GETOPTS |
| @@ -703,14 +828,14 @@ using their long variant names. | |||
| 703 | 828 | ||
| 704 | =head2 BUILTIN PROCESSING | 829 | =head2 BUILTIN PROCESSING |
| 705 | 830 | ||
| 706 | The getopts() method also handles processing of the immediate builtin | 831 | The C<getopts()> method also handles processing of the immediate builtin |
| 707 | arguments, namely --usage, --version, --help, as well as checking all | 832 | arguments, namely --usage, --version, --help, as well as checking all |
| 708 | required arguments have been supplied, so you don't have to handle | 833 | required arguments have been supplied, so you don't have to handle |
| 709 | those yourself. This means that your plugin will exit from the getopts() | 834 | those yourself. This means that your plugin will exit from the getopts() |
| 710 | call in these cases - if you want to catch that you can run getopts() | 835 | call in these cases - if you want to catch that you can run getopts() |
| 711 | within an eval{}. | 836 | within an eval{}. |
| 712 | 837 | ||
| 713 | getopts() also sets up a default ALRM timeout handler so you can use an | 838 | C<getopts()> also sets up a default ALRM timeout handler so you can use an |
| 714 | 839 | ||
| 715 | alarm $ng->timeout; | 840 | alarm $ng->timeout; |
| 716 | 841 | ||
| @@ -730,7 +855,7 @@ Gavin Carr <gavin@openfusion.com.au> | |||
| 730 | 855 | ||
| 731 | =head1 COPYRIGHT AND LICENSE | 856 | =head1 COPYRIGHT AND LICENSE |
| 732 | 857 | ||
| 733 | Copyright (C) 2006 by the Nagios Plugin Development Team. | 858 | Copyright (C) 2006-2007 by the Nagios Plugin Development Team. |
| 734 | 859 | ||
| 735 | This module is free software. It may be used, redistributed | 860 | This module is free software. It may be used, redistributed |
| 736 | and/or modified under either the terms of the Perl Artistic | 861 | and/or modified under either the terms of the Perl Artistic |
diff --git a/t/Nagios-Plugin-04.t b/t/Nagios-Plugin-04.t index 6f31b56..d88ad73 100644 --- a/t/Nagios-Plugin-04.t +++ b/t/Nagios-Plugin-04.t | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | 1 | ||
| 2 | # tests for toplevel access to Threshold and GetOpts stuff | 2 | # tests for toplevel access to Threshold and GetOpts stuff |
| 3 | # $Id$ | ||
| 4 | 3 | ||
| 5 | use strict; | 4 | use strict; |
| 6 | #use Test::More 'no_plan'; | 5 | #use Test::More 'no_plan'; |
diff --git a/t/Nagios-Plugin-Getopt-01.t b/t/Nagios-Plugin-Getopt-01.t index b708a5f..bad1367 100644 --- a/t/Nagios-Plugin-Getopt-01.t +++ b/t/Nagios-Plugin-Getopt-01.t | |||
| @@ -27,8 +27,8 @@ sub setup | |||
| 27 | 27 | ||
| 28 | # Add argument - named version | 28 | # Add argument - named version |
| 29 | $ng->arg( | 29 | $ng->arg( |
| 30 | spec => 'critical|c=s', | 30 | spec => 'critical|c=i', |
| 31 | help => qq(-c, --critical=INTEGER\n Exit with CRITICAL status if less than INTEGER foobars are free), | 31 | help => qq(Exit with CRITICAL status if less than INTEGER foobars are free), |
| 32 | required => 1, | 32 | required => 1, |
| 33 | ); | 33 | ); |
| 34 | 34 | ||
| @@ -104,6 +104,7 @@ like($@, qr/$PARAM{version}/, 'version info includes version'); | |||
| 104 | like($@, qr/$PARAM{url}/, 'version info includes url'); | 104 | like($@, qr/$PARAM{url}/, 'version info includes url'); |
| 105 | unlike($@, qr/Usage:/, 'no usage message'); | 105 | unlike($@, qr/Usage:/, 'no usage message'); |
| 106 | unlike($@, qr/Missing arg/, 'no missing arguments'); | 106 | unlike($@, qr/Missing arg/, 'no missing arguments'); |
| 107 | |||
| 107 | @ARGV = ( '--version' ); | 108 | @ARGV = ( '--version' ); |
| 108 | $ng = setup; | 109 | $ng = setup; |
| 109 | ok(! defined eval { $ng->getopts }, 'getopts died on version'); | 110 | ok(! defined eval { $ng->getopts }, 'getopts died on version'); |
| @@ -128,6 +129,7 @@ like($@, qr/--verbose/, 'help includes default options 2'); | |||
| 128 | like($@, qr/--warning/, 'help includes custom option 1'); | 129 | like($@, qr/--warning/, 'help includes custom option 1'); |
| 129 | like($@, qr/--critical/, 'help includes custom option 2'); | 130 | like($@, qr/--critical/, 'help includes custom option 2'); |
| 130 | unlike($@, qr/Missing arg/, 'no missing arguments'); | 131 | unlike($@, qr/Missing arg/, 'no missing arguments'); |
| 132 | |||
| 131 | @ARGV = ( '--help' ); | 133 | @ARGV = ( '--help' ); |
| 132 | $ng = setup; | 134 | $ng = setup; |
| 133 | ok(! defined eval { $ng->getopts }, 'getopts died on help'); | 135 | ok(! defined eval { $ng->getopts }, 'getopts died on help'); |
| @@ -140,6 +142,6 @@ like($@, qr/Usage:/, 'help includes usage message'); | |||
| 140 | like($@, qr/--version/, 'help includes default options 1'); | 142 | like($@, qr/--version/, 'help includes default options 1'); |
| 141 | like($@, qr/--verbose/, 'help includes default options 2'); | 143 | like($@, qr/--verbose/, 'help includes default options 2'); |
| 142 | like($@, qr/--warning/, 'help includes custom option 1'); | 144 | like($@, qr/--warning/, 'help includes custom option 1'); |
| 143 | like($@, qr/--critical/, 'help includes custom option 2'); | 145 | like($@, qr/-c, --critical=INTEGER/, 'help includes custom option 2, with expanded args'); |
| 144 | unlike($@, qr/Missing arg/, 'no missing arguments'); | 146 | unlike($@, qr/Missing arg/, 'no missing arguments'); |
| 145 | 147 | ||
diff --git a/t/Nagios-Plugin-Getopt-03.t b/t/Nagios-Plugin-Getopt-03.t index 9dc39da..557a2c6 100644 --- a/t/Nagios-Plugin-Getopt-03.t +++ b/t/Nagios-Plugin-Getopt-03.t | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # Nagios::Plugin::Getopt --default-opts tests | 1 | # Nagios::Plugin::Getopt --extra-opts tests |
| 2 | 2 | ||
| 3 | use strict; | 3 | use strict; |
| 4 | use File::Spec; | 4 | use File::Spec; |
| @@ -27,7 +27,8 @@ for my $efile (glob File::Spec->catfile($tdir, 'expected', '*')) { | |||
| 27 | } | 27 | } |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | $Nagios::Plugin::Getopt::DEFAULT_CONFIG_FILE = File::Spec->catfile($tdir, 'plugins.cfg'); | 30 | # Override NAGIOS_CONFIG_PATH to use our test plugins.ini file |
| 31 | $ENV{NAGIOS_CONFIG_PATH} = "/random/bogus/path:$tdir"; | ||
| 31 | 32 | ||
| 32 | my %PARAM = ( | 33 | my %PARAM = ( |
| 33 | version => '0.01', | 34 | version => '0.01', |
| @@ -56,14 +57,18 @@ my $arg = [ | |||
| 56 | { spec => 'S', help => '-S' }, | 57 | { spec => 'S', help => '-S' }, |
| 57 | { spec => 'H=s', help => '-H' }, | 58 | { spec => 'H=s', help => '-H' }, |
| 58 | { spec => 'p=s@', help => '-p' }, | 59 | { spec => 'p=s@', help => '-p' }, |
| 60 | { spec => 'path=s@', help => '--path' }, | ||
| 59 | { spec => 'username|u=s', help => '--username' }, | 61 | { spec => 'username|u=s', help => '--username' }, |
| 60 | { spec => 'password=s', help => '--password' }, | 62 | { spec => 'password=s', help => '--password' }, |
| 61 | { spec => 'critical=i', help => '--critical' }, | 63 | { spec => 'critical=s', help => '--critical' }, |
| 62 | { spec => 'warning=i', help => '--warning' }, | 64 | { spec => 'warning=s', help => '--warning' }, |
| 63 | { spec => 'expect=s', help => '--expect' }, | 65 | { spec => 'expect=s', help => '--expect' }, |
| 66 | { spec => 'units=s', help => '--units' }, | ||
| 64 | ]; | 67 | ]; |
| 65 | 68 | ||
| 66 | my %SKIP = map { $_ => 1 } qw(05_singlechar1 07_singlechar3); | 69 | #my %SKIP = map { $_ => 1 } qw(05_singlechar1 07_singlechar3); |
| 70 | #my %SKIP = map { $_ => 1 } qw(06_singlechar2); | ||
| 71 | my %SKIP = (); | ||
| 67 | 72 | ||
| 68 | # Process all test cases in $tdir/input | 73 | # Process all test cases in $tdir/input |
| 69 | my $glob = $ARGV[0] || '*'; | 74 | my $glob = $ARGV[0] || '*'; |
| @@ -82,7 +87,7 @@ for my $infile (glob File::Spec->catfile($tdir, 'input', $glob)) { | |||
| 82 | 87 | ||
| 83 | # Parse the options | 88 | # Parse the options |
| 84 | SKIP: { | 89 | SKIP: { |
| 85 | skip "Still discussing how overrides with multiple arguments should work ...", 1 if $SKIP{$infile}; | 90 | skip "Skipping ..." if $SKIP{$infile}; |
| 86 | 91 | ||
| 87 | @ARGV = @args; | 92 | @ARGV = @args; |
| 88 | eval { $ng->getopts }; | 93 | eval { $ng->getopts }; |
diff --git a/t/Nagios-Plugin-Getopt-04.t b/t/Nagios-Plugin-Getopt-04.t new file mode 100644 index 0000000..9092636 --- /dev/null +++ b/t/Nagios-Plugin-Getopt-04.t | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | # Nagios::Plugin::Getopt spec-to-help generation tests | ||
| 2 | |||
| 3 | use strict; | ||
| 4 | |||
| 5 | use Test::More tests => 11; | ||
| 6 | BEGIN { use_ok('Nagios::Plugin::Getopt') }; | ||
| 7 | |||
| 8 | my %PARAM = ( | ||
| 9 | version => '0.01', | ||
| 10 | usage => "Don't use this plugin!", | ||
| 11 | ); | ||
| 12 | |||
| 13 | sub setup | ||
| 14 | { | ||
| 15 | # Instantiate object | ||
| 16 | my $ng = Nagios::Plugin::Getopt->new(%PARAM); | ||
| 17 | ok($ng, 'constructor ok'); | ||
| 18 | |||
| 19 | # Positional args, no short arguments, INTEGER | ||
| 20 | $ng->arg('warning=i' => | ||
| 21 | qq(Exit with WARNING status if less than INTEGER foobars are free), | ||
| 22 | 5); | ||
| 23 | |||
| 24 | # Named args, long + short arguments, INTEGER | ||
| 25 | $ng->arg( | ||
| 26 | spec => 'critical|c=i', | ||
| 27 | help => qq(Exit with CRITICAL status if less than INTEGER foobars are free), | ||
| 28 | required => 1, | ||
| 29 | ); | ||
| 30 | |||
| 31 | # Named args, multiple short arguments, STRING, default expansion | ||
| 32 | $ng->arg( | ||
| 33 | spec => 'x|y|z=s', | ||
| 34 | help => qq(Foobar. Default: %s), | ||
| 35 | default => "XYZ", | ||
| 36 | ); | ||
| 37 | |||
| 38 | # Named args, multiple mixed, no label | ||
| 39 | $ng->arg( | ||
| 40 | spec => 'long|longer|longest|l', | ||
| 41 | help => qq(Long format), | ||
| 42 | ); | ||
| 43 | |||
| 44 | # Named args, long + short, explicit label | ||
| 45 | $ng->arg( | ||
| 46 | spec => 'hostname|H=s', | ||
| 47 | label => 'ADDRESS', | ||
| 48 | help => qq(Hostname), | ||
| 49 | ); | ||
| 50 | |||
| 51 | # Positional args, long only, explicit label | ||
| 52 | $ng->arg('avatar=s', 'Avatar', undef, undef, 'AVATAR'); | ||
| 53 | |||
| 54 | # Multiline help test, named args | ||
| 55 | $ng->arg( | ||
| 56 | spec => 'disk=s', | ||
| 57 | label => [ qw(BYTES PERCENT%), undef ], | ||
| 58 | help => [ | ||
| 59 | qq(Disk limit in BYTES), | ||
| 60 | qq(Disk limit in PERCENT), | ||
| 61 | qq(Disk limit in FOOBARS (Default: %s)), | ||
| 62 | ], | ||
| 63 | default => 1024, | ||
| 64 | ); | ||
| 65 | |||
| 66 | # Multiline help test, positional args | ||
| 67 | $ng->arg( | ||
| 68 | 'limit=s', | ||
| 69 | [ | ||
| 70 | qq(Limit in BYTES), | ||
| 71 | qq(Limit in PERCENT), | ||
| 72 | ], | ||
| 73 | undef, | ||
| 74 | undef, | ||
| 75 | [ undef, 'PERCENT%' ], | ||
| 76 | ); | ||
| 77 | |||
| 78 | return $ng; | ||
| 79 | } | ||
| 80 | |||
| 81 | my $ng; | ||
| 82 | |||
| 83 | @ARGV = ( '--help' ); | ||
| 84 | $ng = setup; | ||
| 85 | ok(! defined eval { $ng->getopts }, 'getopts died on help'); | ||
| 86 | like($@, qr/\n --warning=INTEGER/, 'warning ok'); | ||
| 87 | like($@, qr/\n -c, --critical=INTEGER/, 'critical ok'); | ||
| 88 | like($@, qr/\n -x, -y, -z=STRING\n Foobar. Default: XYZ\n/, 'x|y|z ok'); | ||
| 89 | like($@, qr/\n -l, --long, --longer, --longest\n Long format\n/, 'long ok'); | ||
| 90 | like($@, qr/\n -H, --hostname=ADDRESS\n Hostname\n/, 'hostname ok'); | ||
| 91 | like($@, qr/\n --avatar=AVATAR\n Avatar\n/, 'avatar ok'); | ||
| 92 | like($@, qr/\n --disk=BYTES\n Disk limit in BYTES\n --disk=PERCENT%\n Disk limit in PERCENT\n --disk=STRING\n Disk limit in FOOBARS \(Default: 1024\)\n/, 'disk multiline ok'); | ||
| 93 | like($@, qr/\n --limit=STRING\n Limit in BYTES\n --limit=PERCENT%\n Limit in PERCENT\n/, 'limit multiline ok'); | ||
| 94 | #print $@; | ||
| 95 | |||
diff --git a/t/npg03/README b/t/npg03/README index a19f263..3dbdaf8 100644 --- a/t/npg03/README +++ b/t/npg03/README | |||
| @@ -1,13 +1,15 @@ | |||
| 1 | Nagios-Plugin-Getopt-03.t automatically tests all cases defined in the 'input' directory | 1 | Nagios-Plugin-Getopt-03.t automatically tests all cases defined in |
| 2 | and expects the output to match the corresponding file in the 'expected' directory. To | 2 | the 'input' directory and expects the output to match the |
| 3 | define a new test case, just create a new file in the 'input' directory containing the | 3 | corresponding file in the 'expected' directory. To define a new test |
| 4 | input command line, and a corresponding file in the 'expected' directory containing | 4 | case, just create a new file in the 'input' directory containing the |
| 5 | what you think the expanded command line should be. Note that this expansion is normalised | 5 | input command line, and a corresponding file in the 'expected' |
| 6 | as follows: | 6 | directory containing what you think the expanded command line should |
| 7 | be. Note that this expansion is normalised as follows: | ||
| 7 | 8 | ||
| 8 | - command line arguments are reported in alphabetical order | 9 | - command line arguments are reported in alphabetical order |
| 9 | - extraneous white space is removed | 10 | - extraneous white space is removed |
| 10 | 11 | ||
| 11 | Also, if you use a completely new argument than those defined in Nagios-Plugin-Getopt-03.t | 12 | Also, if you use a completely new argument than those currently |
| 12 | you will need to define it there as well. | 13 | defined in Nagios-Plugin-Getopt-03.t you will need to define it |
| 14 | there as well. | ||
| 13 | 15 | ||
diff --git a/t/npg03/expected/00_noextra b/t/npg03/expected/00_noextra new file mode 100644 index 0000000..d649587 --- /dev/null +++ b/t/npg03/expected/00_noextra | |||
| @@ -0,0 +1 @@ | |||
| check_mysql -H localhost -S | |||
diff --git a/t/npg03/expected/05_disk1 b/t/npg03/expected/05_disk1 new file mode 100644 index 0000000..5570904 --- /dev/null +++ b/t/npg03/expected/05_disk1 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /tmp -p /home | |||
diff --git a/t/npg03/expected/05_disk2 b/t/npg03/expected/05_disk2 new file mode 100644 index 0000000..692890b --- /dev/null +++ b/t/npg03/expected/05_disk2 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /tmp -p /home -p /users | |||
diff --git a/t/npg03/expected/05_disk3 b/t/npg03/expected/05_disk3 new file mode 100644 index 0000000..5252b4e --- /dev/null +++ b/t/npg03/expected/05_disk3 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /tmp -p /var | |||
diff --git a/t/npg03/expected/05_disk4 b/t/npg03/expected/05_disk4 new file mode 100644 index 0000000..34b382e --- /dev/null +++ b/t/npg03/expected/05_disk4 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /tmp -p /var -p /home | |||
diff --git a/t/npg03/expected/05_disk5 b/t/npg03/expected/05_disk5 new file mode 100644 index 0000000..ae61e62 --- /dev/null +++ b/t/npg03/expected/05_disk5 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /var -p /tmp -p /home | |||
diff --git a/t/npg03/expected/05_disk6 b/t/npg03/expected/05_disk6 new file mode 100644 index 0000000..dc4870a --- /dev/null +++ b/t/npg03/expected/05_disk6 | |||
| @@ -0,0 +1 @@ | |||
| check_disk2 --critical=5% --path=/var --path=/home --path=/usr --units=GB --warning=10% | |||
diff --git a/t/npg03/expected/05_singlechar1 b/t/npg03/expected/05_singlechar1 deleted file mode 100644 index 13a3f9b..0000000 --- a/t/npg03/expected/05_singlechar1 +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | check_disk -p /home | ||
diff --git a/t/npg03/expected/06_singlechar2 b/t/npg03/expected/06_singlechar2 deleted file mode 100644 index 8f9df5e..0000000 --- a/t/npg03/expected/06_singlechar2 +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | check_disk -p /var | ||
diff --git a/t/npg03/expected/07_singlechar3 b/t/npg03/expected/07_singlechar3 deleted file mode 100644 index f4e6ed7..0000000 --- a/t/npg03/expected/07_singlechar3 +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | check_disk -p /home -p /users | ||
diff --git a/t/npg03/input/00_basic b/t/npg03/input/00_basic index 4c16788..f35f3c7 100644 --- a/t/npg03/input/00_basic +++ b/t/npg03/input/00_basic | |||
| @@ -1 +1 @@ | |||
| check_mysql -S --default-opts= --default-opts=more_options -H localhost | check_mysql -S --extra-opts= --extra-opts=more_options -H localhost | ||
diff --git a/t/npg03/input/00_noextra b/t/npg03/input/00_noextra new file mode 100644 index 0000000..4d8a8fc --- /dev/null +++ b/t/npg03/input/00_noextra | |||
| @@ -0,0 +1 @@ | |||
| check_mysql -S -H localhost | |||
diff --git a/t/npg03/input/01_override1 b/t/npg03/input/01_override1 index 9e051e9..f3cd232 100644 --- a/t/npg03/input/01_override1 +++ b/t/npg03/input/01_override1 | |||
| @@ -1 +1 @@ | |||
| check_mysql --username=admin --default-opts=more_options --warning=5 | check_mysql --username=admin --extra-opts=more_options --warning=5 | ||
diff --git a/t/npg03/input/02_override2 b/t/npg03/input/02_override2 index ceabe55..fa96ff7 100644 --- a/t/npg03/input/02_override2 +++ b/t/npg03/input/02_override2 | |||
| @@ -1 +1 @@ | |||
| check_mysql --default-opts= -u admin | check_mysql --extra-opts= -u admin | ||
diff --git a/t/npg03/input/05_disk1 b/t/npg03/input/05_disk1 new file mode 100644 index 0000000..5ccfe23 --- /dev/null +++ b/t/npg03/input/05_disk1 | |||
| @@ -0,0 +1 @@ | |||
| check_disk --extra-opts= -p /home | |||
diff --git a/t/npg03/input/05_disk2 b/t/npg03/input/05_disk2 new file mode 100644 index 0000000..53e36d9 --- /dev/null +++ b/t/npg03/input/05_disk2 | |||
| @@ -0,0 +1 @@ | |||
| check_disk --extra-opts= -p /home -p /users | |||
diff --git a/t/npg03/input/05_disk3 b/t/npg03/input/05_disk3 new file mode 100644 index 0000000..441accb --- /dev/null +++ b/t/npg03/input/05_disk3 | |||
| @@ -0,0 +1 @@ | |||
| check_disk --extra-opts=check_2_disks | |||
diff --git a/t/npg03/input/05_disk4 b/t/npg03/input/05_disk4 new file mode 100644 index 0000000..da9d810 --- /dev/null +++ b/t/npg03/input/05_disk4 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /home --extra-opts=check_2_disks | |||
diff --git a/t/npg03/input/05_disk5 b/t/npg03/input/05_disk5 new file mode 100644 index 0000000..9ba2d40 --- /dev/null +++ b/t/npg03/input/05_disk5 | |||
| @@ -0,0 +1 @@ | |||
| check_disk -p /home --extra-opts=check_2_disks_reprise | |||
diff --git a/t/npg03/input/05_disk6 b/t/npg03/input/05_disk6 new file mode 100644 index 0000000..c240d9c --- /dev/null +++ b/t/npg03/input/05_disk6 | |||
| @@ -0,0 +1 @@ | |||
| check_disk2 --warning=10% --critical=5% --extra-opts= --path=/usr | |||
diff --git a/t/npg03/input/05_singlechar1 b/t/npg03/input/05_singlechar1 deleted file mode 100644 index 1edb8bf..0000000 --- a/t/npg03/input/05_singlechar1 +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | check_disk --default-opts= -p /home | ||
diff --git a/t/npg03/input/06_singlechar2 b/t/npg03/input/06_singlechar2 deleted file mode 100644 index 24965c7..0000000 --- a/t/npg03/input/06_singlechar2 +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | check_disk --default-opts=check_2_disks | ||
diff --git a/t/npg03/input/07_singlechar3 b/t/npg03/input/07_singlechar3 deleted file mode 100644 index 0abc70f..0000000 --- a/t/npg03/input/07_singlechar3 +++ /dev/null | |||
| @@ -1 +0,0 @@ | |||
| 1 | check_disk --default-opts= -p /home -p /users | ||
diff --git a/t/npg03/input/09_funnystuff b/t/npg03/input/09_funnystuff index c2d6160..ab279d9 100644 --- a/t/npg03/input/09_funnystuff +++ b/t/npg03/input/09_funnystuff | |||
| @@ -1 +1 @@ | |||
| check_disk --default-opts=funny_stuff | check_disk --extra-opts=funny_stuff | ||
diff --git a/t/npg03/input/13_nosection_explicit_dies b/t/npg03/input/13_nosection_explicit_dies index 90aab51..f18660e 100644 --- a/t/npg03/input/13_nosection_explicit_dies +++ b/t/npg03/input/13_nosection_explicit_dies | |||
| @@ -1 +1 @@ | |||
| check_no_section --default-opts= -H localhost | check_no_section --extra-opts= -H localhost | ||
diff --git a/t/npg03/input/14_badsection_dies b/t/npg03/input/14_badsection_dies index 70815a9..6b1c20a 100644 --- a/t/npg03/input/14_badsection_dies +++ b/t/npg03/input/14_badsection_dies | |||
| @@ -1 +1 @@ | |||
| check_no_section --default-opts=bad_section | check_no_section --extra-opts=bad_section | ||
diff --git a/t/npg03/plugins.cfg b/t/npg03/plugins.ini index f893a21..2d3c551 100644 --- a/t/npg03/plugins.cfg +++ b/t/npg03/plugins.ini | |||
| @@ -14,6 +14,15 @@ p=/tmp | |||
| 14 | p=/tmp | 14 | p=/tmp |
| 15 | p=/var | 15 | p=/var |
| 16 | 16 | ||
| 17 | [check_2_disks_reprise] | ||
| 18 | p=/var | ||
| 19 | p=/tmp | ||
| 20 | |||
| 21 | [check_disk2] | ||
| 22 | path=/var | ||
| 23 | path=/home | ||
| 24 | units=GB | ||
| 25 | |||
| 17 | [funny_stuff] | 26 | [funny_stuff] |
| 18 | username="Ton Voon" | 27 | username="Ton Voon" |
| 19 | p= | 28 | p= |
