summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--files/master/lastcheck.rb140
-rw-r--r--files/master/lastruncheck220
-rw-r--r--files/master/puppetlast26
-rw-r--r--manifests/puppetmaster.pp6
-rw-r--r--manifests/puppetmaster/checklastrun.pp19
-rw-r--r--manifests/puppetmaster/checklastrun/disable.pp3
6 files changed, 240 insertions, 174 deletions
diff --git a/files/master/lastcheck.rb b/files/master/lastcheck.rb
deleted file mode 100644
index f83ccde..0000000
--- a/files/master/lastcheck.rb
+++ /dev/null
@@ -1,140 +0,0 @@
-require 'rubygems'
-require 'active_support'
-require 'puppet/application'
-
-module Puppet::Lastcheck
- module Puppet::Lastcheck::Tests
- def self.included(klass)
- klass.extend ClassMethods
- end
- def self.tests
- @tests ||= {}
- end
- module ClassMethods
- def add_test(name, options={})
- include "Puppet::Lastcheck::Tests::#{name.to_s.classify}".constantize
- Puppet::Lastcheck::Tests.tests[name] = options
- attr_accessor "ignore_#{name}".to_sym
- option("--ignore-#{name.to_s.gsub(/_/,'-')}") do
- self.send("ignore_#{name}=", true)
- end
- end
- end
- module Util
- def facts_hosts
- return @facts_hosts if @facts_hosts
- require 'puppet/indirector/facts/yaml'
- @facts_hopsts = Puppet::Node::Facts.search("*").collect do |node|
- { :hostname => node.name, :expired => node.expired?, :timestamp => node.values[:_timestamp], :expiration => node.expiration }
- end
- end
- end
- end
-end
-
-module Puppet::Lastcheck::Tests::NoFact
- def analyze_no_facts
- signed_hosts.each{|host| add_failed_host(host,"No facts available") unless facts_hosts.any?{|fhost| fhost[:hostname] == host } }
- end
- def setup_no_facts
- Puppet::SSL::Host.ca_location = :only
- end
-
- private
- def signed_hosts
- ca.list
- end
-
- def ca
- @ca ||= Puppet::SSL::CertificateAuthority.new
- end
-end
-
-module Puppet::Lastcheck::Tests::ExpiredFact
- include Puppet::Lastcheck::Tests::Util
- def analyze_expired_facts
- facts_hosts.each{|host| add_failed_host(host[:hostname],"Expired at #{host[:expiration]}") if host[:expired] }
- end
-end
-module Puppet::Lastcheck::Tests::TimedOutFact
- include Puppet::Lastcheck::Tests::Util
- def analyze_timed_out_facts
- require 'time'
- facts_hosts.each{|host| add_failed_host(host[:hostname], "Last facts save at #{host[:timestamp]}") if Time.parse(host[:timestamp]) < (Time.now - @timeout) }
- end
-
- def setup_timed_out_facts
- if @timeout
- ignore_expired_facts ||= true
- end
- end
-end
-module Puppet::Lastcheck::Tests::Storedconfig
- def analyze_storedconfigs
- storedconfigs_hosts.each do |host|
- if !facts_hosts.any?{|fact_host| fact_host[:hostname] == host.name }
- add_failed_host(host.name, "In storedconfigs but no facts available!")
- elsif host.updated_at < (Time.now - @timeout)
- add_failed_host(host.name, "Last update in storedconfigs at #{host.updated_at}")
- end
- end
- end
-
- private
- def storedconfigs_hosts
- return @storedconfigs_hosts if @storedconfigs_hosts
- Puppet::Rails.connect
- @storedconfigs_hosts = Puppet::Rails::Host.all
- end
-end
-class Puppet::Application::Lastcheck < Puppet::Application
-
- should_parse_config
- run_mode :master
-
- include Puppet::Lastcheck::Tests
- add_test :no_facts
- add_test :expired_facts, :ignore_by_default => true
- add_test :timed_out_facts
- add_test :storedconfigs
-
- option("--timeout TIMEOUT") do |v|
- @timeout = v.to_i
- end
-
- def main
- Puppet::Lastcheck::Tests.tests.keys.each do |test|
- self.send("analyze_#{test}") unless self.send("ignore_#{test}")
- end
- print unless @failing_hosts.empty?
- end
-
- def setup
- exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
-
- Puppet::Util::Log.newdestination :console
- Puppet::Node::Facts.terminus_class = :yaml
-
- Puppet::Lastcheck::Tests.tests.keys.each do |test|
- self.send("ignore_#{test}=", Puppet::Lastcheck::Tests.tests[test][:ignore_by_default]||false) unless self.send("ignore_#{test}")
- self.send("setup_#{test}") if self.respond_to?("setup_#{test}")
- end
-
- @failing_hosts = {}
- unless @timeout
- @timeout = Puppet[:runinterval]
- end
- end
-
- private
- def print
- puts 'The following hosts are out of date:'
- puts '------------------------------------'
- @failing_hosts.keys.each{ |host| puts "#{host} - Reason: #{@failing_hosts[host][:reason]}" }
- end
-
- def add_failed_host(hostname,reason)
- @failing_hosts[hostname] = { :reason => reason } unless @failing_hosts[hostname]
- end
-
-end
diff --git a/files/master/lastruncheck b/files/master/lastruncheck
new file mode 100644
index 0000000..8e31601
--- /dev/null
+++ b/files/master/lastruncheck
@@ -0,0 +1,220 @@
+#!/usr/bin/env ruby
+require 'puppet/application'
+
+module Puppet::Lastcheck
+ module Puppet::Lastcheck::Tests
+ def self.included(klass)
+ klass.extend ClassMethods
+ end
+ def self.tests
+ @tests ||= {}
+ end
+ module ClassMethods
+ def add_test(name, options={})
+ include Puppet::Lastcheck::Tests.const_get(name.to_s.split('_').collect{|s| s.capitalize }.join(''))
+ Puppet::Lastcheck::Tests.tests[name] = options
+ attr_accessor "ignore_#{name}".to_sym
+ option("--ignore-#{name.to_s.gsub(/_/,'-')}") do
+ self.send("ignore_#{name}=", true)
+ end
+ end
+ end
+ module Util
+ def facts_hosts
+ return @facts_hosts if @facts_hosts
+ require 'puppet/indirector/facts/yaml'
+ @facts_hosts = Puppet::Node::Facts.search("*").collect do |node|
+ { :hostname => node.name, :expired => node.expired?, :timestamp => node.values[:_timestamp], :expiration => node.expiration }
+ end
+ end
+ end
+ end
+ module Puppet::Lastcheck::Reports
+ def self.included(klass)
+ klass.extend ClassMethods
+ end
+ def ordered_reports
+ @ordered_reports ||= Puppet::Lastcheck::Reports.reports.keys.sort{|a,b| Puppet::Lastcheck::Reports.reports[a][:priority] <=> Puppet::Lastcheck::Reports.reports[b][:priority] }
+ end
+
+ def self.reports
+ @reports ||= {}
+ end
+ module ClassMethods
+ def add_report(name, options={})
+ include Puppet::Lastcheck::Reports.const_get(name.to_s.split('_').collect{|s| s.capitalize }.join(''))
+ Puppet::Lastcheck::Reports.reports[name] = options
+ Puppet::Lastcheck::Reports.reports[name][:priority] ||= 100
+ attr_accessor "report_to_#{name}".to_sym
+ option("--report-to-#{name.to_s.gsub(/_/,'-')}") do
+ self.send("report_to_#{name}=", true)
+ end
+ end
+ end
+ end
+end
+
+module Puppet::Lastcheck::Tests::NoFacts
+ def analyze_no_facts
+ signed_hosts.each{|host| add_failed_host(host,"No facts available") unless facts_hosts.any?{|fhost| fhost[:hostname] == host } }
+ end
+ def setup_no_facts
+ Puppet::SSL::Host.ca_location = :only
+ end
+
+ private
+ def signed_hosts
+ ca.list
+ end
+
+ def ca
+ @ca ||= Puppet::SSL::CertificateAuthority.new
+ end
+end
+
+module Puppet::Lastcheck::Tests::ExpiredFacts
+ include Puppet::Lastcheck::Tests::Util
+ def analyze_expired_facts
+ facts_hosts.each{|host| add_failed_host(host[:hostname],"Expired at #{host[:expiration]}") if host[:expired] }
+ end
+end
+module Puppet::Lastcheck::Tests::TimedOutFacts
+ include Puppet::Lastcheck::Tests::Util
+ def analyze_timed_out_facts
+ require 'time'
+ facts_hosts.each{|host| add_failed_host(host[:hostname], "Last facts save at #{host[:timestamp]}") if Time.parse(host[:timestamp]) < (Time.now - @timeout) }
+ end
+
+ def setup_timed_out_facts
+ if @timeout
+ ignore_expired_facts ||= true
+ end
+ end
+end
+module Puppet::Lastcheck::Tests::Storedconfigs
+ def analyze_storedconfigs
+ storedconfigs_hosts.each do |host|
+ if !facts_hosts.any?{|fact_host| fact_host[:hostname] == host.name }
+ add_failed_host(host.name, "In storedconfigs but no facts available!")
+ elsif host.updated_at < (Time.now - @timeout)
+ add_failed_host(host.name, "Last update in storedconfigs at #{host.updated_at}")
+ end
+ end
+ end
+
+ private
+ def storedconfigs_hosts
+ return @storedconfigs_hosts if @storedconfigs_hosts
+ Puppet::Rails.connect
+ @storedconfigs_hosts = Puppet::Rails::Host.all
+ end
+end
+module Puppet::Lastcheck::Reports::Console
+ def deliver_report_to_console(failing_hosts)
+ unless failing_hosts.empty?
+ puts 'The following hosts are out of date:'
+ puts '------------------------------------'
+ host_length = 0
+ failing_hosts.keys.each{|host| host_length = host.length if host.length > host_length }
+ failing_hosts.keys.each{ |host| puts "#{pretty_puts(host,host_length)} - Reason: #{failing_hosts[host][:reason]}" }
+ 1
+ else
+ 0
+ end
+ end
+end
+module Puppet::Lastcheck::Reports::Nagios
+ def deliver_report_to_nagios(failing_hosts)
+ unless failing_hosts.empty?
+ puts "PUPPETLAST CRITICAL: #{failing_hosts.size} outdated hosts: #{failing_hosts.keys.join(',')}"
+ 2
+ else
+ puts "PUPPETLAST OK: No outdated hosts"
+ 0
+ end
+ end
+end
+#
+# = Synopsis
+#
+# Verifiying your puppet runs. Check different places to verify
+# whether your clients actually still runs successfully.
+# Also checks for left overs of legacy hosts.
+#
+# = Usage
+#
+# puppet lastcheck [-h|--help]
+class Puppet::Application::Lastcheck < Puppet::Application
+
+ should_parse_config
+ run_mode :master
+
+ include Puppet::Lastcheck::Tests
+ add_test :no_facts
+ add_test :expired_facts, :ignore_by_default => true
+ add_test :timed_out_facts
+ add_test :storedconfigs
+
+ include Puppet::Lastcheck::Reports
+ add_report :console, :priority => 50
+ add_report :nagios
+
+ option("--timeout TIMEOUT") do |v|
+ @timeout = v.to_i
+ end
+
+ option("--ignore-hosts HOSTS") do |v|
+ @ignore_hosts = v.split(',')
+ end
+
+ def main
+
+ Puppet::Lastcheck::Tests.tests.keys.each do |test|
+ self.send("analyze_#{test}") unless self.send("ignore_#{test}")
+ end
+ exitcode = 0
+ ordered_reports.each do |report|
+ if self.send("report_to_#{report}")
+ tmpexitcode = self.send("deliver_report_to_#{report}",@failing_hosts)
+ exitcode = tmpexitcode unless exitcode > 0
+ end
+ end
+ exit(exitcode)
+ end
+
+ def setup
+ exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
+
+ Puppet::Util::Log.newdestination :console
+ Puppet::Node::Facts.terminus_class = :yaml
+
+ Puppet::Lastcheck::Tests.tests.keys.each do |test|
+ self.send("ignore_#{test}=", Puppet::Lastcheck::Tests.tests[test][:ignore_by_default]||false) unless self.send("ignore_#{test}")
+ self.send("setup_#{test}") if self.respond_to?("setup_#{test}") and !self.send("ignore_#{test}")
+ end
+ report = nil
+ report_activated = false
+ ordered_reports.each do |report|
+ report_activated ||= self.send("report_to_#{report}")
+ end
+ self.report_to_console = true unless report_activated
+
+ @ignore_hosts = [] unless @ignore_hosts
+ @failing_hosts = {}
+ unless @timeout
+ @timeout = Puppet[:runinterval]
+ end
+ end
+
+ private
+
+ def add_failed_host(hostname,reason)
+ @failing_hosts[hostname] = { :reason => reason } unless (@failing_hosts[hostname] || @ignore_hosts.include?(hostname))
+ end
+
+ def pretty_puts(str,length)
+ sprintf("%0-#{length}s",str)
+ end
+end
+
+Puppet::Application.find('lastcheck').new.run
diff --git a/files/master/puppetlast b/files/master/puppetlast
deleted file mode 100644
index af2ca77..0000000
--- a/files/master/puppetlast
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env ruby
-# Puppetlast, a script to output the last check-in time of nodes. Also outputs the cached configuration state, if expired or not.
-#
-# AJ "Fujin" Christensen <aj@junglist.gen.nz>
-# changed by admin+puppet(at)immerda.ch to fit our needs
-#
-require 'puppet'
-require 'time'
-
-Puppet[:config] = "/etc/puppet/puppet.conf"
-Puppet.parse_config
-Puppet::Node::Facts.terminus_class = :yaml
-
-all = false
-timeout = 120
-ARGV.each do |arg|
- if arg.to_s == '--all'
- all = true
- else
- timeout = arg.to_i
- end
-end
-
-Puppet::Node::Facts.search("*").sort { |a,b| a.name <=> b.name }.each do |node|
- puts "#{node.name} #{node.expired? ? 'cached expired, ' : ''}last checked #{((Time.now - Time.parse(node.values[:_timestamp])) / 60).floor} minutes ago" if (((Time.now - Time.parse(node.values[:_timestamp])) / 60).floor > timeout or all)
-end
diff --git a/manifests/puppetmaster.pp b/manifests/puppetmaster.pp
index 36116b4..74df5e7 100644
--- a/manifests/puppetmaster.pp
+++ b/manifests/puppetmaster.pp
@@ -13,11 +13,11 @@ class puppet::puppetmaster inherits puppet {
include puppet::puppetmaster::base
- case $puppetmaster_checklastrun {
- '': { $puppetmaster_checklastrun = '40 10,22 * * *' }
+ case $puppetmaster_lastruncheck_cron {
+ '',undef: { $puppetmaster_lastruncheck_cron = '40 10,22 * * *' }
}
- if $puppetmaster_checklastrun {
+ if $puppetmaster_lastruncheck_cron {
include puppet::puppetmaster::checklastrun
} else {
include puppet::puppetmaster::checklastrun::disable
diff --git a/manifests/puppetmaster/checklastrun.pp b/manifests/puppetmaster/checklastrun.pp
index 1cf5311..72a97ce 100644
--- a/manifests/puppetmaster/checklastrun.pp
+++ b/manifests/puppetmaster/checklastrun.pp
@@ -1,11 +1,22 @@
class puppet::puppetmaster::checklastrun {
- file{"/usr/local/bin/puppetlast":
- source => [ "puppet:///modules/site-puppet/master/puppetlast",
- "puppet:///modules/puppet/master/puppetlast" ],
+ $puppet_lastruncheck_ignorehosts_str = $puppet_lastruncheck_ignorehosts ? {
+ '' => '',
+ undef => '',
+ default => "--ignore-hosts ${puppet_lastruncheck_ignorehosts}"
+ }
+
+ $puppet_lastruncheck_timeout_str = $puppet_lastruncheck_timeout ? {
+ '' => '',
+ undef => '',
+ default => "--timeout ${puppet_lastruncheck_timeout}"
+ }
+
+ file{"/usr/local/sbin/puppetlast":
+ source => [ "puppet:///modules/puppet/master/lastruncheck" ],
owner => root, group => 0, mode => 0700;
}
file{'/etc/cron.d/puppetlast.cron':
- content => "${puppetmaster_checklastrun} root /usr/local/bin/puppetlast ${puppetmaster_checklastrun_timeout}\n",
+ content => "${puppetmaster_lastruncheck_cron} root /usr/local/sbin/puppetlast ${puppet_lastruncheck_timeout_str} ${puppet_lastruncheck_ignorehosts_str} ${$puppet_lastruncheck_additionaloptions}\n",
require => File["/usr/local/bin/puppetlast"],
owner => root, group => 0, mode => 0644,
}
diff --git a/manifests/puppetmaster/checklastrun/disable.pp b/manifests/puppetmaster/checklastrun/disable.pp
index 47c0130..3fc91d0 100644
--- a/manifests/puppetmaster/checklastrun/disable.pp
+++ b/manifests/puppetmaster/checklastrun/disable.pp
@@ -1,5 +1,6 @@
class puppet::puppetmaster::checklastrun::disable inherits puppet::puppetmaster::checklastrun {
- File['/usr/local/bin/puppetlast']{
+ File['/usr/local/sbin/puppetlast']{
+ source => undef,
ensure => absent,
}
File['/etc/cron.d/puppetlast.cron']{