#! /usr/bin/perl
#
# $Id: check_gather.pl 7678 2012-08-02 18:34:45Z coelho $
#
# Copyright (c) 2012 Fabien Coelho MINES ParisTech
#
# GNU General Public License version 3, http://gnu.org/licences/gpl.txt
#
# Aggregate several nagios status checks into one.
# There is no dependency. Try "$0 --help" for help.
#
# See also:
# - "check_multi", although much less ambitious but much simpler.
# - "check_multiple", but just runs an external (shell) script rather
#    than providing an explicit list of commands.

use strict;
use warnings;

# if in doubt, provide help
if (@ARGV<3)
{
  print STDOUT
    "Aggregate several nagios status checks into one.\n",
    "Usage: $0 nn description /path/to/some/script [args...]\n",
    " - nn: expect exactly this many lines, 0 to disable\n",
    " - description: one liner that describes what is checked\n",
    " - script: execute nagios checks\n",
    "The provided script output is processed looking for line patterns like:\n",
    "  ... (OK|WARNING|CRITICAL|UNKNOWN): ...\n",
    "The exit status of the provided script should always be 0.\n",
    "A global nagios status is printed and returned in the end.\n";
  # this is not ok from nagios point of view
  exit 4;
}

my ($expect, $description, $script, @args) = @ARGV;

# return nagios status
sub done($$)
{
  my ($code, $message) = @_;
  my $status = 'ERROR';
  $status = 'OK' if $code == 0;
  $status = 'WARNING' if $code == 1;
  $status = 'CRITICAL' if $code == 2;
  $status = 'UNKNOWN' if $code == 3;
  print "$description $status: $message\n";
  exit $code;
}

# sanity checks
done 3, "expecting at least three arguments" unless @ARGV >= 3;
done 3, "expecting a number ($expect)" unless $expect =~ /^\d+$/;
done 3, "expecting a script ($script)" unless -f $script;
done 3, "expecting an executable script ($script)" unless -x $script;

# run script and aggragate status
my $gather = 0;
my $msg = '';
my $count = 0;
open(EXE, '-|', $script, @args) or done(3, "cannot execute script ($script)");
while (<EXE>)
{
  # count all lines?
  $count++;
  chomp;
  # status is gather from stdout
  if (/^[^:]*(OK|WARNING|CRITICAL|UNKNOWN):.*$/i)
  {
    my $code = $1;
    $gather = 1 if $gather<1 and $code =~ /WARNING/i;
    $gather = 2 if $gather<2 and $code =~ /CRITICAL/i;
    $gather = 3 if $gather<3 and $code =~ /UNKNOWN/i;
  }
  else
  {
    # in doubt
    $gather = 3;
  }
  $msg .= '/ ' . $_;
}
close(EXE) or done(3, "cannot close script ($script) or script error");

# return overall results
done 2, "got $count results, expecting $expect | $gather $msg"
  unless $expect==0 or $count == $expect;
done $gather, "$count results | $msg";
