[pkg-nagios-changes] [Git][nagios-team/pkg-libmonitoring-livestatus-perl][upstream] New upstream version 0.84
Bas Couwenberg
gitlab at salsa.debian.org
Fri Dec 18 04:45:36 GMT 2020
Bas Couwenberg pushed to branch upstream at Debian Nagios Maintainer Group / pkg-libmonitoring-livestatus-perl
Commits:
c9b09bdc by Bas Couwenberg at 2020-12-18T05:33:22+01:00
New upstream version 0.84
- - - - -
19 changed files:
- Changes
- MANIFEST
- META.yml
- Makefile.PL
- inc/Module/AutoInstall.pm
- inc/Module/Install.pm
- inc/Module/Install/AutoInstall.pm
- inc/Module/Install/Base.pm
- inc/Module/Install/Can.pm
- inc/Module/Install/Fetch.pm
- inc/Module/Install/Include.pm
- inc/Module/Install/Makefile.pm
- inc/Module/Install/Metadata.pm
- inc/Module/Install/Win32.pm
- inc/Module/Install/WriteAll.pm
- lib/Monitoring/Livestatus.pm
- lib/Monitoring/Livestatus/INET.pm
- lib/Monitoring/Livestatus/UNIX.pm
- + t/085-json_xs.t
Changes:
=====================================
Changes
=====================================
@@ -1,5 +1,12 @@
Revision history for Perl extension Monitoring::Livestatus.
+0.84 Tue Dec 15 16:53:44 CET 2020
+ - add support for command response
+ - remove alarm handler, timeouts should be handled in the calling module
+
+0.82 Sat Nov 10 12:11:31 CET 2018
+ - add tls support for tcp livestatus connections
+
0.80 Fri Jan 26 08:24:00 CET 2018
- support ipv6 connections
- change to Cpanel::JSON::XS
=====================================
MANIFEST
=====================================
@@ -16,11 +16,12 @@ lib/Monitoring/Livestatus.pm
lib/Monitoring/Livestatus/INET.pm
lib/Monitoring/Livestatus/UNIX.pm
Makefile.PL
-MANIFEST This list of files
+MANIFEST
META.yml
README
t/01-Monitoring-Livestatus-basic_tests.t
t/02-Monitoring-Livestatus-internals.t
+t/085-json_xs.t
t/20-Monitoring-Livestatus-test_socket.t
t/21-Monitoring-Livestatus-INET.t
t/22-Monitoring-Livestatus-UNIX.t
=====================================
META.yml
=====================================
@@ -8,7 +8,7 @@ configure_requires:
ExtUtils::MakeMaker: 6.59
distribution_type: module
dynamic_config: 1
-generated_by: 'Module::Install version 1.17'
+generated_by: 'Module::Install version 1.19'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -21,8 +21,8 @@ no_index:
- t
requires:
Cpanel::JSON::XS: 0
- Digest::MD5: 0
Encode: 0
+ IO::Select: 0
IO::Socket::IP: 0
IO::Socket::UNIX: 0
Test::More: '0.87'
@@ -33,4 +33,4 @@ resources:
homepage: http://search.cpan.org/dist/Monitoring-Livestatus/
license: http://dev.perl.org/licenses/
repository: http://github.com/sni/Monitoring-Livestatus
-version: '0.80'
+version: '0.84'
=====================================
Makefile.PL
=====================================
@@ -16,7 +16,7 @@ resources(
requires 'IO::Socket::UNIX';
requires 'IO::Socket::IP';
-requires 'Digest::MD5';
+requires 'IO::Select';
requires 'Test::More' => '0.87';
requires 'utf8';
requires 'Encode';
=====================================
inc/Module/AutoInstall.pm
=====================================
@@ -8,7 +8,7 @@ use ExtUtils::MakeMaker ();
use vars qw{$VERSION};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
}
# special map on pre-defined feature sets
=====================================
inc/Module/Install.pm
=====================================
@@ -31,7 +31,7 @@ BEGIN {
# This is not enforced yet, but will be some time in the next few
# releases once we can make sure it won't clash with custom
# Module::Install extensions.
- $VERSION = '1.17';
+ $VERSION = '1.19';
# Storage for the pseudo-singleton
$MAIN = undef;
=====================================
inc/Module/Install/AutoInstall.pm
=====================================
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/Base.pm
=====================================
@@ -4,7 +4,7 @@ package Module::Install::Base;
use strict 'vars';
use vars qw{$VERSION};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
}
# Suspend handler for "redefined" warnings
=====================================
inc/Module/Install/Can.pm
=====================================
@@ -8,7 +8,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/Fetch.pm
=====================================
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/Include.pm
=====================================
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/Makefile.pm
=====================================
@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/Metadata.pm
=====================================
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/Win32.pm
=====================================
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
=====================================
inc/Module/Install/WriteAll.pm
=====================================
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.17';
+ $VERSION = '1.19';
@ISA = qw{Module::Install::Base};
$ISCORE = 1;
}
=====================================
lib/Monitoring/Livestatus.pm
=====================================
@@ -4,15 +4,15 @@ use 5.006;
use strict;
use warnings;
use Data::Dumper qw/Dumper/;
-use Carp qw/carp croak confess/;
-use Digest::MD5 qw(md5_hex);
+use Carp qw/carp confess/;
use Cpanel::JSON::XS ();
use Storable qw/dclone/;
+use IO::Select ();
-use Monitoring::Livestatus::INET qw//;
-use Monitoring::Livestatus::UNIX qw//;
+use Monitoring::Livestatus::INET ();
+use Monitoring::Livestatus::UNIX ();
-our $VERSION = '0.80';
+our $VERSION = '0.84';
# list of allowed options
@@ -158,6 +158,11 @@ sub new {
'deepcopy' => undef, # copy result set to avoid errors with tied structures
'retries_on_connection_error' => 3, # retry x times to connect
'retry_interval' => 1, # retry after x seconds
+ # tls options
+ 'cert' => undef,
+ 'key' => undef,
+ 'ca_file' => undef,
+ 'verify' => undef,
};
my %old_key = (
@@ -181,12 +186,12 @@ sub new {
$self->{$opt_key} = $options{$opt_key};
}
else {
- croak("unknown option: $opt_key");
+ confess("unknown option: $opt_key");
}
}
if($self->{'verbose'} && !defined $self->{'logger'}) {
- croak('please specify a logger object when using verbose mode');
+ confess('please specify a logger object when using verbose mode');
}
# setting a general timeout?
@@ -295,11 +300,10 @@ sub selectall_arrayref {
if(!defined $result) {
$result = &_send($self, $statement, $opt);
- return $result if $ENV{'THRUK_SELECT'};
if(!defined $result) {
return unless $self->{'errors_are_fatal'};
- croak("got undef result for: $statement");
+ confess("got undef result for: $statement");
}
}
@@ -380,7 +384,7 @@ sub selectall_hashref {
$opt->{'slice'} = 1;
- croak('key is required for selectall_hashref') if !defined $key_field;
+ confess('key is required for selectall_hashref') if !defined $key_field;
my $result = $self->selectall_arrayref($statement, $opt);
@@ -391,7 +395,7 @@ sub selectall_hashref {
}
elsif(!defined $row->{$key_field}) {
my %possible_keys = keys %{$row};
- croak("key $key_field not found in result set, possible keys are: ".join(', ', sort keys %possible_keys));
+ confess("key $key_field not found in result set, possible keys are: ".join(', ', sort keys %possible_keys));
} else {
$indexed{$row->{$key_field}} = $row;
}
@@ -580,7 +584,7 @@ sub selectscalar_value {
errors_are_fatal()
errors_are_fatal($value)
-Enable or disable fatal errors. When enabled the module will croak on any error.
+Enable or disable fatal errors. When enabled the module will confess on any error.
returns the current setting if called without new value
@@ -692,14 +696,9 @@ sub peer_name {
returns a uniq key for this peer
-when using multiple backends, a list of all keys is returned in list context
-
=cut
sub peer_key {
my($self) = @_;
-
- if(!defined $self->{'key'}) { $self->{'key'} = md5_hex($self->peer_addr.' '.$self->peer_name); }
-
return $self->{'key'};
}
@@ -819,7 +818,6 @@ sub _send {
my $send = "$statement\n$header";
$self->{'logger'}->debug('> '.Dumper($send)) if $self->{'verbose'};
($status,$msg,$body) = &_send_socket($self, $send);
- return([$status, $opt, $keys]) if $ENV{'THRUK_SELECT'};
if($self->{'verbose'}) {
#$self->{'logger'}->debug("got:");
#$self->{'logger'}->debug(Dumper(\@erg));
@@ -841,7 +839,7 @@ sub _send {
}
$self->{'logger'}->error($status.' - '.$Monitoring::Livestatus::ErrorMessage." in query:\n".$statement) if $self->{'verbose'};
if($self->{'errors_are_fatal'}) {
- croak('ERROR '.$status.' - '.$Monitoring::Livestatus::ErrorMessage." in query:\n".$statement."\n");
+ confess('ERROR '.$status.' - '.$Monitoring::Livestatus::ErrorMessage." in query:\n".$statement."\n");
}
return;
}
@@ -875,7 +873,7 @@ sub _send {
my $message = 'ERROR '.$@." in text: '".$body."'\" for statement: '$statement'\n";
$self->{'logger'}->error($message) if $self->{'verbose'};
if($self->{'errors_are_fatal'}) {
- croak($message);
+ confess($message);
}
return({ keys => [], result => []});
}
@@ -884,7 +882,7 @@ sub _send {
my $message = "ERROR undef result for text: '".$body."'\" for statement: '$statement'\n";
$self->{'logger'}->error($message) if $self->{'verbose'};
if($self->{'errors_are_fatal'}) {
- croak($message);
+ confess($message);
}
return({ keys => [], result => []});
}
@@ -980,12 +978,11 @@ sub _open {
########################################
sub _close {
- my($self, $sock) = @_;
- undef $self->{'sock'};
+ my($self) = @_;
+ my $sock = delete $self->{'sock'};
return($self->{'CONNECTOR'}->_close($sock));
}
-
########################################
=head1 QUERY OPTIONS
@@ -1091,16 +1088,15 @@ sub _send_socket {
my $retries = 0;
my($status, $msg, $recv, $sock);
+ # closing a socket sends SIGPIPE to reader
+ # https://riptutorial.com/posix/example/17424/handle-sigpipe-generated-by-write---in-a-thread-safe-manner
+ local $SIG{PIPE} = 'IGNORE';
+
# try to avoid connection errors
eval {
- local $SIG{PIPE} = sub {
- die('broken pipe');
- };
-
if($self->{'retries_on_connection_error'} <= 0) {
($sock, $msg, $recv) = &_send_socket_do($self, $statement);
return($sock, $msg, $recv) if $msg;
- return $sock if $ENV{'THRUK_SELECT'};
($status, $msg, $recv) = &_read_socket_do($self, $sock, $statement);
return($status, $msg, $recv);
}
@@ -1109,7 +1105,6 @@ sub _send_socket {
$retries++;
($sock, $msg, $recv) = &_send_socket_do($self, $statement);
return($status, $msg, $recv) if $msg;
- return $sock if $ENV{'THRUK_SELECT'};
($status, $msg, $recv) = &_read_socket_do($self, $sock, $statement);
$self->{'logger'}->debug('query status '.$status) if $self->{'verbose'};
if($status == 491 or $status == 497 or $status == 500) {
@@ -1124,15 +1119,14 @@ sub _send_socket {
if(defined $@ and $@ =~ /broken\ pipe/mx) {
($sock, $msg, $recv) = &_send_socket_do($self, $statement);
return($status, $msg, $recv) if $msg;
- return $sock if $ENV{'THRUK_SELECT'};
return(&_read_socket_do($self, $sock, $statement));
}
- croak($@) if $self->{'errors_are_fatal'};
+ confess($@) if $self->{'errors_are_fatal'};
}
$status = $sock unless $status;
- return $sock if $ENV{'THRUK_SELECT'};
- croak($msg) if($status >= 400 and $self->{'errors_are_fatal'});
+ $msg =~ s/^$status:\s+//gmx;
+ confess($status.": ".$msg) if($status >= 400 and $self->{'errors_are_fatal'});
return($status, $msg, $recv);
}
@@ -1140,10 +1134,10 @@ sub _send_socket {
########################################
sub _send_socket_do {
my($self, $statement) = @_;
- my $sock = $self->_open() or return(491, $self->_get_error(491, $!), $!);
+ my $sock = $self->_open() or return(491, $self->_get_error(491, $@ || $!), $@ || $!);
utf8::decode($statement);
utf8::encode($statement);
- print $sock $statement or return($self->_socket_error($statement, $sock, 'write to socket failed: '.$!));
+ print $sock $statement or return($self->_socket_error($statement, $sock, 'write to socket failed: '.($@ || $!)));
print $sock "\n";
return $sock;
}
@@ -1153,9 +1147,22 @@ sub _read_socket_do {
my($self, $sock, $statement) = @_;
my($recv,$header);
- # COMMAND statements never return something
+ # COMMAND statements might return a error message
if($statement && $statement =~ m/^COMMAND/mx) {
- return('201', $self->_get_error(201), undef);
+ shutdown($sock, 1);
+ my $s = IO::Select->new();
+ $s->add($sock);
+ if($s->can_read(0.5)) {
+ $recv = <$sock>;
+ }
+ if($recv) {
+ chomp($recv);
+ if($recv =~ m/^(\d+):\s*(.*)$/mx) {
+ return($1, $recv, undef);
+ }
+ return('400', $self->_get_error(400), $recv);
+ }
+ return('200', $self->_get_error(200), undef);
}
$sock->read($header, 16) or return($self->_socket_error($statement, $sock, 'reading header from socket failed, check your livestatus logfile: '.$!));
@@ -1180,14 +1187,14 @@ sub _read_socket_do {
$remaining = $remaining -$length;
if($remaining < $length) { $length = $remaining; }
}
- $recv = $json_decoder->incr_parse or return($self->_socket_error($statement, $sock, 'reading body from socket failed: '.$json_decoder->incr_text.$json_decoder->incr_reset));
+ $recv = $json_decoder->incr_parse or return($self->_socket_error($statement, $sock, 'reading remaining '.$length.' bytes from socket failed: '.$!));
$json_decoder->incr_reset;
} else {
$sock->read($recv, $content_length) or return($self->_socket_error($statement, $sock, 'reading body from socket failed'));
}
}
- $self->_close($sock) unless $self->{'keepalive'};
+ $self->_close() unless $self->{'keepalive'};
if($status >= 400 && $recv) {
$msg .= ' - '.$recv;
}
@@ -1208,7 +1215,7 @@ sub _socket_error {
if($self->{'retries_on_connection_error'} <= 0) {
if($self->{'errors_are_fatal'}) {
- croak($message);
+ confess($message);
}
else {
carp($message);
@@ -1382,7 +1389,7 @@ Errorhandling can be done like this:
$ml->errors_are_fatal(0);
my $hosts = $ml->selectall_arrayref("GET hosts");
if($Monitoring::Livestatus::ErrorCode) {
- croak($Monitoring::Livestatus::ErrorMessage);
+ confess($Monitoring::Livestatus::ErrorMessage);
}
=cut
@@ -1398,6 +1405,7 @@ sub _get_error {
'403' => 'The request is incomplete.',
'404' => 'The target of the GET has not been found (e.g. the table).',
'405' => 'A non-existing column was being referred to',
+ '413' => 'Maximum response size reached',
'452' => 'internal livestatus error',
'490' => 'no query',
'491' => 'failed to connect',
@@ -1410,6 +1418,7 @@ sub _get_error {
'498' => 'header is not exactly 16byte long',
'499' => 'not a valid header (no content-length)',
'500' => 'socket error',
+ '502' => 'backend connection proxy error',
};
confess('non existant error code: '.$code) if !defined $codes->{$code};
@@ -1477,7 +1486,7 @@ sub _get_peer {
}
# check if we got a peer
- croak('please specify a peer');
+ confess('please specify a peer');
}
=====================================
lib/Monitoring/Livestatus/INET.pm
=====================================
@@ -5,7 +5,7 @@ use strict;
use warnings;
use IO::Socket::IP ();
use Socket qw(IPPROTO_TCP TCP_NODELAY);
-use Carp qw/confess croak/;
+use Carp qw/confess/;
=head1 NAME
@@ -39,6 +39,10 @@ sub new {
bless $self, $class;
confess('not a scalar') if ref $self->{'peer'} ne '';
+ if(($self->{'peer'}//$self->{'server'}) =~ m|^tls://|mx) {
+ require IO::Socket::SSL;
+ }
+
return $self;
}
@@ -53,30 +57,42 @@ sub _open {
my $self = shift;
my $sock;
- my $remaining = alarm($self->{'connect_timeout'});
+ my $options = {
+ PeerAddr => $self->{'peer'},
+ Type => IO::Socket::IP::SOCK_STREAM,
+ Timeout => $self->{'connect_timeout'},
+ };
+
+ my $tls = 0;
+ my $peer_addr = $self->{'peer'};
+ if($peer_addr =~ s|tls://||mx) {
+ $options->{'PeerAddr'} = $peer_addr;
+ $options->{'SSL_cert_file'} = $self->{'cert'};
+ $options->{'SSL_key_file'} = $self->{'key'};
+ $options->{'SSL_ca_file'} = $self->{'ca_file'};
+ $options->{'SSL_verify_mode'} = 0 if(defined $self->{'verify'} && $self->{'verify'} == 0);
+ $tls = 1;
+ }
+
eval {
- local $SIG{'ALRM'} = sub { die("connection timeout"); };
- $sock = IO::Socket::IP->new(
- PeerAddr => $self->{'peer'},
- Type => IO::Socket::IP::SOCK_STREAM,
- Timeout => $self->{'connect_timeout'},
- );
+ if($tls) {
+ $sock = IO::Socket::SSL->new(%{$options});
+ } else {
+ $sock = IO::Socket::IP->new(%{$options});
+ }
if(!defined $sock || !$sock->connected()) {
- my $msg = "failed to connect to $self->{'peer'}: $!";
+ my $msg = "failed to connect to $peer_addr: $!";
if($self->{'errors_are_fatal'}) {
- croak($msg);
+ confess($msg);
}
$Monitoring::Livestatus::ErrorCode = 500;
$Monitoring::Livestatus::ErrorMessage = $msg;
- alarm(0);
return;
}
setsockopt($sock, IPPROTO_TCP, TCP_NODELAY, 1);
};
- alarm(0);
- alarm($remaining) if $remaining;
if($@) {
$Monitoring::Livestatus::ErrorCode = 500;
=====================================
lib/Monitoring/Livestatus/UNIX.pm
=====================================
@@ -4,7 +4,7 @@ use parent 'Monitoring::Livestatus';
use strict;
use warnings;
use IO::Socket::UNIX ();
-use Carp qw/confess croak/;
+use Carp qw/confess/;
=head1 NAME
@@ -54,32 +54,29 @@ sub _open {
if(!-S $self->{'peer'}) {
my $msg = "failed to open socket $self->{'peer'}: $!";
if($self->{'errors_are_fatal'}) {
- croak($msg);
+ confess($msg);
}
$Monitoring::Livestatus::ErrorCode = 500;
$Monitoring::Livestatus::ErrorMessage = $msg;
return;
}
my $sock;
- my $remaining = alarm($self->{'connect_timeout'});
eval {
- local $SIG{'ALRM'} = sub { die("connection timeout"); };
$sock = IO::Socket::UNIX->new(
Peer => $self->{'peer'},
Type => IO::Socket::UNIX::SOCK_STREAM,
+ Timeout => $self->{'connect_timeout'},
);
if(!defined $sock || !$sock->connected()) {
my $msg = "failed to connect to $self->{'peer'}: $!";
if($self->{'errors_are_fatal'}) {
- croak($msg);
+ confess($msg);
}
$Monitoring::Livestatus::ErrorCode = 500;
$Monitoring::Livestatus::ErrorMessage = $msg;
return;
}
};
- alarm(0);
- alarm($remaining) if $remaining;
if($@) {
$Monitoring::Livestatus::ErrorCode = 500;
=====================================
t/085-json_xs.t
=====================================
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+use Test::More;
+
+plan skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to a true value to run.' unless $ENV{TEST_AUTHOR};
+
+open(my $ph, '-|', 'bash -c "find ./lib ./t -type f" 2>&1') or die('find failed: '.$!);
+while(<$ph>) {
+ my $line = $_;
+ chomp($line);
+ check_json_xs($line);
+}
+done_testing();
+
+
+sub check_json_xs {
+ my($file) = @_;
+ ok($file, $file);
+ my $out = `grep -n JSON::XS "$file" | grep -v Cpanel::JSON::XS`;
+ if($out) {
+ fail($file." uses JSON::XS instead of Cpanel::JSON::XS");
+ }
+ return;
+}
View it on GitLab: https://salsa.debian.org/nagios-team/pkg-libmonitoring-livestatus-perl/-/commit/c9b09bdcc2572aaa8df5169c41897e272ef6d537
--
View it on GitLab: https://salsa.debian.org/nagios-team/pkg-libmonitoring-livestatus-perl/-/commit/c9b09bdcc2572aaa8df5169c41897e272ef6d537
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-nagios-changes/attachments/20201218/01d38b9c/attachment-0001.html>
More information about the pkg-nagios-changes
mailing list