Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

snmp/redis.pl now handles multiple instances and has a config file #530

Merged
merged 2 commits into from
Jul 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 159 additions & 38 deletions snmp/redis.pl
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

=head1 NAME

redis.pl - LinbreNMS JSON extend for redis.
redis - LinbreNMS JSON extend for redis.

=head1 SYNOPSIS

logsize [B<-B>]
redis [B<-B>] [B<-c> <config file>]

redis [B<-v>|B<--version>]

redis [B<-h>|B<--help>]

=head1 SWITCHES

=head2 -c

Config file to use.

Default: /usr/local/etc/redis_extend.json

=head2 -B

Do not the return output via GZip+Base64.
Expand Down Expand Up @@ -38,6 +48,36 @@ =head1 SETUP
# if running it via cron
extend redis /usr/local/etc/snmp/redis.pl

If for multiple instances or the default of 'redis-cli info'
won't work, a config file will be needed. The config format
is JSON.

The config entries are as below.

- command :: If single instance, the command to use.
Type :: String
Default :: redis-cli

- instances :: A hash where the keys are the instances names
and the values for each key are the command to use.

The default config would be like below, which will be what is used
if no config file is specified/found.

{
"command": "redis-cli info"
}

For something with two instances, "foo" on port 6379 and "bar" on port 6380
it would be like below.

{
"instances": {
"foo": "redis-cli -p 6379",
"bar": "redis-cli -p 6380"
}
}

=cut

use warnings;
Expand All @@ -59,16 +99,39 @@ sub main::HELP_MESSAGE {
pod2usage( -exitval => 255, -verbose => 2, -output => \*STDOUT, );
}

sub return_the_data {
my $to_return = $_[0];
my $do_not_compress = $_[1];

my $to_return_string = encode_json($to_return);

if ($do_not_compress) {
print $to_return_string . "\n";
return;
}

my $toReturnCompressed;
gzip \$to_return_string => \$toReturnCompressed;
my $compressed = encode_base64($toReturnCompressed);
$compressed =~ s/\n//g;
$compressed = $compressed . "\n";
print $compressed;
} ## end sub return_the_data

my $return_json = {
error => 0,
errorString => '',
version => 1,
data => {},
version => 2,
data => { 'extend_errors' => [] },
};

#gets the options
my %opts = ();
getopts( 'Bhv', \%opts );
getopts( 'Bhvc:', \%opts );

if ( !defined( $opts{c} ) ) {
$opts{c} = '/usr/local/etc/redis_extend.json';
}

if ( $opts{v} ) {
main::VERSION_MESSAGE;
Expand All @@ -81,40 +144,98 @@ sub main::HELP_MESSAGE {
exit 256;
}

# ensure that $ENV{PATH} has has it
$ENV{PATH} = $ENV{PATH} . ':/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin';

my $output_raw = `redis-cli info 2> /dev/null`;
if ( $? != 0 ) {
$return_json->{error} = 1;
$return_json->{error} = 'redis-cli info exited non-zero';
print encode_json($return_json) . "\n";
}

$output_raw =~ s/\r//g;
my $section;
foreach my $line ( split( /\n/, $output_raw ) ) {
if ( $line ne '' && $line =~ /^# / ) {
$line =~ s/^# //;
$section = $line;
$return_json->{data}{$section} = {};
} elsif ( $line ne '' && defined($section) ) {
my ( $key, $value ) = split( /\:/, $line );
if ( defined($key) && defined($value) ) {
$return_json->{data}{$section}{$key} = $value;
my $single = 1;
my $config = { command => 'redis-cli info' };
if ( -f $opts{c} ) {
eval {
my $raw_config = read_file( $opts{c} );
$config = decode_json($raw_config);
if ( !defined( $config->{instances} ) ) {
if ( !defined( $config->{command} ) ) {
$config->{command} = 'redis-cli info';
}
} elsif ( ref( $config->{instances} ) ne 'HASH' ) {
die( '.instances is defined and is not a hash but ref type ' . ref( $config->{instances} ) );
} else {
$single = 0;
}
};
if ($@) {
push( @{ $return_json->{data}{extend_errors} }, $@ );
return_the_data( $return_json, $opts{B} );
exit 0;
}
} ## end foreach my $line ( split( /\n/, $output_raw ) )
} ## end if ( -f $opts{c} )

my $return_json_raw = encode_json($return_json);
if ( $opts{B} ) {
print $return_json_raw. "\n";
exit 0;
}
# ensure that $ENV{PATH} has has it
$ENV{PATH} = $ENV{PATH} . ':/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin';

my $toReturnCompressed;
gzip \$return_json_raw => \$toReturnCompressed;
my $compressed = encode_base64($toReturnCompressed);
$compressed =~ s/\n//g;
$compressed = $compressed . "\n";
print $compressed;
if ($single) {
my $command = $config->{command};
my $output_raw = `$command 2> /dev/null`;
if ( $? != 0 ) {
push(
@{ $return_json->{data}{extend_errors} },
'"' . $command . '" exited non-zero for with... ' . $output_raw
);
} else {
$output_raw =~ s/\r//g;
my $section;
foreach my $line ( split( /\n/, $output_raw ) ) {
if ( $line ne '' && $line =~ /^# / ) {
$line =~ s/^# //;
$section = $line;
$return_json->{data}{$section} = {};
} elsif ( $line ne '' && defined($section) ) {
my ( $key, $value ) = split( /\:/, $line );
if ( defined($key) && defined($value) ) {
$return_json->{data}{$section}{$key} = $value;
}
}
} ## end foreach my $line ( split( /\n/, $output_raw ) )
} ## end else [ if ( $? != 0 ) ]
} else {
my @instances = keys( %{ $config->{instances} } );
$return_json->{data}{instances} = {};
foreach my $instance (@instances) {
if ( ref( $config->{instances}{$instance} ) ne '' ) {
push(
@{ $return_json->{data}{extend_errors} },
'instance "' . $instance . '" is ref type ' . ref( $config->{instances}{$instance} )
);
} elsif ( $instance =~ /^[\-\_]/ ) {
push( @{ $return_json->{data}{extend_errors} }, 'instance "' . $instance . '" matches /^[\-\_]/' );
} elsif ( $instance =~ /[\-\_\n\s\"\']$/ ) {
push( @{ $return_json->{data}{extend_errors} },
'instance "' . $instance . '" matches /[\-\_\n\s\'\\\"]$/' );
} else {
my $command = $config->{instances}{$instance};
my $output_raw = `$command 2> /dev/null`;
if ( $? != 0 ) {
push(
@{ $return_json->{data}{extend_errors} },
'"' . $command . '" exited non-zero for instance "' . $instance . '" with... ' . $output_raw
);
} else {
$output_raw =~ s/\r//g;
my $section;
$return_json->{data}{instances}{$instance} = {};
foreach my $line ( split( /\n/, $output_raw ) ) {
if ( $line ne '' && $line =~ /^# / ) {
$line =~ s/^# //;
$section = $line;
$return_json->{data}{instances}{$instance}{$section} = {};
} elsif ( $line ne '' && defined($section) ) {
my ( $key, $value ) = split( /\:/, $line );
if ( defined($key) && defined($value) ) {
$return_json->{data}{instances}{$instance}{$section}{$key} = $value;
}
}
} ## end foreach my $line ( split( /\n/, $output_raw ) )
} ## end else [ if ( $? != 0 ) ]
} ## end else [ if ( ref( $config->{instances}{$instance} ...))]
} ## end foreach my $instance (@instances)
} ## end else [ if ($single) ]

return_the_data( $return_json, $opts{B} );
exit 0;
Loading