#!perl

=head1 NAME

sneck - a boopable LibreNMS JSON style SNMP extend for remotely running nagios style checks akin to NRPE

=head1 SYNOPSIS

sneck -u [B<-C> <cache file] [B<-f> <config file>] [B<-p>] [B<-i>]

sneck -c [B<-C> <cache file] [B<-b>]

sneck [B<-f> <config file>] [B<-p>] [B<-i>]

=head1 DESCRIPTION

For a description of the config file format and output,
please see L<Monitoring::Sneck>.

=head1 FLAGS

=head2 -f <config file>

The config file to use.

Default :: /usr/local/etc/sneck.conf

=head2 -p

Pretty it in a nicely formatted format.

=head2 -C <cache file>

The cache file to use.

Default :: /var/cache/sneck.cache

A secondary cache file based on this name
is also created. By default it is
/var/cache/sneck.cache.snmp and is used for
storing the compressed version.

=head2 -u

Update the cache file. Will also print the was written to it.

=head2 -c

Print the cache file. Please note that B<-p> or B<-i> won't affect
this as this flag only reads/prints the cache file.

=head2 -b

When used with B<-c>, it does optional LibreNMS style GZip+BASE64
style compression.

=head2 -i

Includes the config file used.

=cut

use strict;
use warnings;
use Getopt::Long       qw( GetOptions );
use File::Slurp        qw(read_file write_file);
use JSON               qw(encode_json);
use Monitoring::Sneck  ();
use MIME::Base64       qw(encode_base64);
use IO::Compress::Gzip qw(gzip);
use Pod::Usage         qw(pod2usage);

sub main::VERSION_MESSAGE {
	print 'sneck v. ' . $Monitoring::Sneck::VERSION . "\n";
	exit 255;
}

sub main::HELP_MESSAGE {
	pod2usage( -exitval => 255, -verbose => 2, -output => \*STDOUT, );
}

my $cache_file  = '/var/cache/sneck.cache';
my $config_file = '/usr/local/etc/sneck.conf';
my $update;
my $print_cache;
my $fallback;
my $help;
my $version;
my $pretty;
my $include;
my $compress;
Getopt::Long::Configure('no_ignore_case');
Getopt::Long::Configure('bundling');
GetOptions(
	'version' => \$version,
	'v'       => \$version,
	'help'    => \$help,
	'h'       => \$help,
	'c'       => \$print_cache,
	'f=s'     => \$config_file,
	'C=s'     => \$cache_file,
	'p'       => \$pretty,
	'u'       => \$update,
	'i'       => \$include,
	'b'       => \$compress,
);

# print version or help if requested
if ($help) {
	main::HELP_MESSAGE;
	exit 42;
}
if ($version) {
	main::VERSION_MESSAGE;
	exit 42;
}

# prints the cache and exit if requested
if ($print_cache) {
	if ($compress) {
		$cache_file = $cache_file . '.snmp';
	}

	if ( !-f $cache_file || !-r $cache_file ) {
		my $error = 'Cache file does not exist or is not readable "' . $cache_file . '"';
		my $possible_error
			= { error => 1, version => 1, errorString => $error, data => { alert => 1, alertString => $error } };
		print encode_json($possible_error) . "\n";
		exit 3;
	}
	my $cache = read_file($cache_file);

	print $cache;

	exit;
} ## end if ($print_cache)

my $sneck    = Monitoring::Sneck->new( { config => $config_file, include => $include } );
my $returned = $sneck->run;

# encode it and print it
my $json = JSON->new->utf8->canonical(1);
if ($pretty) {
	$json->pretty;
}
my $raw_json = $json->encode($returned);

my $compressed_string;
gzip \$raw_json => \$compressed_string;
my $compressed = encode_base64($compressed_string);
$compressed =~ s/\n//g;
$compressed = $compressed . "\n";
my $snmp = $raw_json;
if ( length($compressed) < length($raw_json) ) {
	$snmp = $compressed;
}

# non-pretty does not include a new line, so add it
if ( !$pretty ) {
	$raw_json = $raw_json . "\n";
}

print $raw_json;

if ($update) {
	write_file( $cache_file,           $raw_json );
	write_file( $cache_file . '.snmp', $snmp );
}
