#!/usr/bin/perl
##########################################################################
# $Id$
##########################################################################
# $Log$
########################################################
## Copyright (c) 2011 Nathan Crawford
## Covered under the included MIT/X-Consortium License:
##    http://www.opensource.org/licenses/mit-license.php
## All modifications and contributions by other persons to
## this script are assumed to have been donated to the
## Logwatch project and thus assume the above copyright
## and licensing terms.  If you want to make contributions
## under your own copyright or a different license this
## must be explicitly stated in the contribution and the
## Logwatch project reserves the right to not accept such
## contributions.  If you have made significant
## contributions to this script and want to claim
## copyright please contact logwatch-devel@logwatch.org.
#########################################################

# Detail level
$Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;

# Config
my $offline = $ENV{'puppet_offline_ok'};

# Init counters
$FailedRuns = 0;
$SuccessfulRuns = 0;
$ResourceFailures = 0;
$DependencyFailures = 0;

while (defined($ThisLine = <STDIN>)) {
   chomp($ThisLine);
   if ( 
      ($ThisLine =~ /Using cached catalog/) or
      ($ThisLine =~ /Caching catalog for /) or
      ($ThisLine =~ /Caching node for /) or
      ($ThisLine =~ /Caught TERM; calling stop/) or
      ($ThisLine =~ /[sS]hutting down/) or
      ($ThisLine =~ /Reopening log files/) or
      ($ThisLine =~ /Starting Puppet client version /) or
      ($ThisLine =~ /Restarting with.+puppetd/) or
      ($ThisLine =~ /Caught HUP; calling restart/) or
      ($ThisLine =~ /Skipping because of failed dependencies/) or
      ($ThisLine =~ /Failed to generate additional resources/) or
      ($ThisLine =~ /Could not evaluate: getaddrinfo: Name or service not known/) or
      ($ThisLine =~ /replacing from source .+ with contents /) or
      ($ThisLine =~ /Starting catalog run/) or
      ($ThisLine =~ /Applying configuration version/) or
      ($ThisLine =~ /Loading facts in/) or
      ($ThisLine =~ /Retrieving plugin/) or
      ($ThisLine =~ /FileBucket adding/)
   ) {
      # Ignore
   } elsif (($reason) = ($ThisLine =~ /Could not retrieve catalog from remote server: (.*)/)) {
      if ($reason == "getaddrinfo: Name or service not known" && $offline) {
         $FailedRuns--;
      } else {
         $CatalogFailures{$reason}++;
      }
   } elsif ($ThisLine =~ /Finished catalog run in [0-9]+\.[0-9]+ seconds/) {
      $SuccessfulRuns++;
   } elsif ($ThisLine =~ /skipping run/) {
      $FailedRuns++;
   } elsif ($ThisLine =~ /File\[(.+)\].+checksum changed/) {
      $ChangedFiles{$1}++;
   } elsif ($ThisLine =~ /File\[(.+)\].+content changed/) {
      $ChangedFiles{$1}++;
   } elsif (($File, $Content) = $ThisLine =~ /\(\/File\[(.+)\]\/content\) #012(.*)/) {
      $Content =~ s/#011/\t/g;
      $Content =~ s/#012/\n        /g;
      $ChangedFilesContent{$File} .= $Content;
   } elsif ($ThisLine =~ /File\[(.+)\].+created/) {
      $CreatedFiles{$1}++;
   } elsif ($ThisLine =~ /File\[(.+)\].+removed/) {
      $RemovedFiles{$1}++;
   } elsif (($fileinfo) = ($ThisLine =~ /Filebucketed (.*)/)) {
      $FileBucketed{$1}++;
   } elsif (
      ($ThisLine =~ /Failed to retrieve current state of resource/) or
      ($ThisLine =~ /Package.+ensure.+Could not find package/) or
      ($ThisLine =~ /File\[.+\].+ Could not describe /) or
      ($ThisLine =~ /File\[.+\].+ No specified sources exist/)
   ) {
      $ResourceFailures++;
   } elsif ($ThisLine =~ /Package\[(.+)\].+ensure changed/) {
      $ChangedPackages{$1}++;
   } elsif ($ThisLine =~ /Package\[(.+)\].+ensure\) created/) {
      $InstalledPackages{$1}++;
   } elsif ($ThisLine =~ /Package\[(.+)\].+ensure\) removed/) {
      $RemovedPackages{$1}++;
   } elsif ($ThisLine =~ /Exec\[(.+)\].+executed successfully/) {
      $ExecRuns{$1}++;
   } elsif ($ThisLine =~ /Exec\[(.+)\].+Triggering 'refresh' from [0-9]+ dependencies/) {
      $ExecRuns{$1}++;
   } elsif ($ThisLine =~ /Service\[(.+)\].+ensure changed \'.+\' to \'running\'/) {
      $ServiceStarts{$1}++;
   } elsif ($ThisLine =~ /Service\[(.+)\].+Triggering 'refresh' from [0-9]+ dependencies/) {
      $ServiceStarts{$1}++;
   } elsif ($ThisLine =~ /Dependency .+\[.+\] has [0-9]+ failure/) {
      $DependencyFailures++;
   } else {
      # Report any unmatched entries...
      $OtherList{$ThisLine}++;
   }
}

#######################################

if ($SuccessfulRuns > 0 && $Detail > 0) {
   print "\nSuccessful runs: $SuccessfulRuns\n";
}

if ($FailedRuns > 0) {
   print "\nFailed runs: $FailedRuns\n";
}

if (keys %CatalogFailures) {
   print "\nCould not retrieve catalog from remote server:\n";
   foreach $ThisOne (keys %CatalogFailures) {
      print "    $ThisOne: $CatalogFailures{$ThisOne} Time(s)\n";
   }
}

if (keys %CreatedFiles) {
   print "\nCreated files:\n";
   foreach $ThisOne (keys %CreatedFiles) {
      print "    $ThisOne: $CreatedFiles{$ThisOne} Time(s)\n";
   }
}

if (keys %ChangedFiles) {
   print "\nChanged files:\n";
   foreach $ThisOne (keys %ChangedFiles) {
      print "    $ThisOne: $ChangedFiles{$ThisOne} Time(s)\n";
      if (defined($ChangedFilesContent{$ThisOne}) and $Detail >= 3) {
         print "        $ChangedFilesContent{$ThisOne}\n";
      }
   }
}

if (keys %RemovedFiles) {
   print "\nRemoved files:\n";
   foreach $ThisOne (keys %RemovedFiles) {
      print "    $ThisOne: $RemovedFiles{$ThisOne} Time(s)\n";
   }
}

if (keys %FileBucketed and $Detail >= 5) {
   print "\nFileBucketed files:\n";
   foreach $ThisOne (keys %FileBucketed) {
      print "    $ThisOne\n";
   }
}

if (keys %InstalledPackages) {
   print "\nInstalled packages:\n";
   foreach $ThisOne (keys %InstalledPackages) {
      print "    $ThisOne: $InstalledPackages{$ThisOne} Time(s)\n";
   }
}

if (keys %ChangedPackages) {
   print "\nChanged packages:\n";
   foreach $ThisOne (keys %ChangedPackages) {
      print "    $ThisOne: $ChangedPackages{$ThisOne} Time(s)\n";
   }
}

if (keys %RemovedPackages) {
   print "\nRemoved packages:\n";
   foreach $ThisOne (keys %RemovedPackages) {
      print "    $ThisOne: $RemovedPackages{$ThisOne} Time(s)\n";
   }
}

if (keys %ExecRuns) {
   print "\nExec runs:\n";
   foreach $ThisOne (keys %ExecRuns) {
      print "    $ThisOne: $ExecRuns{$ThisOne} Time(s)\n";
   }
}

if (keys %ServiceStarts) {
   print "\nService starts:\n";
   foreach $ThisOne (keys %ServiceStarts) {
      print "    $ThisOne: $ServiceStarts{$ThisOne} Time(s)\n";
   }
}

if ($ResourceFailures > 0) {
   print "\nResource failures: $ResourceFailures\n";
}

if ($DependencyFailures > 0) {
   print "\nDependency failures: $DependencyFailures\n";
}

if (keys %OtherList) {
   print "\n**Unmatched Entries**\n";
   foreach $ThisOne (keys %OtherList) {
      print "    $ThisOne: $OtherList{$ThisOne} Time(s)\n";
   }
}

exit(0);

# vi: shiftwidth=3 tabstop=3 syntax=perl et

