Skip to content

Instantly share code, notes, and snippets.

@jfryman
Created August 21, 2013 06:33
Show Gist options
  • Save jfryman/6290985 to your computer and use it in GitHub Desktop.
Save jfryman/6290985 to your computer and use it in GitHub Desktop.
NagiosDB
#!/usr/bin/env ruby
#
# Nagios/PuppetDB config generator
#
# Based on concept from puppetdb-external-naginator
# https://github.com/favoretti/puppetdb-external-naginator
#
# Generates nagios configs from puppet(db) exported resources.
#
require 'rubygems'
require 'json'
require 'httparty'
require 'fileutils'
module Nagios
class PuppetDB
include HTTParty
base_uri 'WHERE_IS_DAT_PUPPETDB?!'
format :json
OBJECTS = %w(
host
hostgroup
hostescalation
hostdependency
hostextinfo
service
servicegroup
serviceescalation
servicedependency
serviceextinfo
contact
contactgroup
timeperiod
command
)
TARGET='/etc/nagios/objects'
CONFDIR='/etc/nagios3'
TMPDIR='/tmp/nagios/objects'
LOCKFILE="/tmp/#{File.basename $0}.lock"
CANARY="/tmp/nagiosdb_ok"
def self.lock
begin
File.open(LOCKFILE, File::RDWR|File::CREAT, 0644).flock(File::LOCK_EX)
rescue => e
puts "Something went horribly wrong while trying to setup a lock #{e}"
bailout 1
end
end
def self.unlock
begin
FileUtils.rm_rf LOCKFILE
rescue => e
puts "Something went horribly wrong while trying to remove a lock. #{e}"
bailout 1
end
end
def self.locked?
begin
File.exists? LOCKFILE
rescue => e
puts "Something went horribly wrong while trying to check if the lock exists. #{e}"
bailout 1
end
end
def self.search(endpoint, query = nil)
begin
options = Hash.new
options[:headers] = { 'Accept' => 'application/json' }
options[:query] = URI::encode("query=#{query}") if query
options[:timeout] = 30
get(endpoint, options)
rescue => e
puts "Something went horribly wrong while trying to search PuppetDB #{e}"
end
end
def self.setup
begin
FileUtils.rm_rf TMPDIR unless File.exists? TMPDIR
FileUtils.mkdir_p '/tmp/nagios/objects'
OBJECTS.each { |o| Dir.mkdir(File.join(TMPDIR, "#{o}.d")) }
rescue => e
puts "Something went horribly wrong while trying to setup nagios config sync. #{e}"
bailout 1
end
end
def self.teardown
FileUtils.rm_rf TMPDIR
end
def self.collect_resources(resource)
query = [
"and",
["=", "type", "File"],
["=", "exported", true],
["=", "tag", "nagios::object::#{resource}"],
["=", ["node", "active"], true]
]
self.search('/v2/resources', query.to_json)
end
def self.rsync(apply = true)
flags = '-avrc'
flags += 'n' unless apply
puts `rsync #{flags} --delete #{TMPDIR}/ #{TARGET}/`
`find #{TARGET} -type d | xargs chmod 755`
`find #{TARGET} -type f | grep .cfg | xargs chmod 444`
end
def self.valid_config?
begin
FileUtils.cp "#{CONFDIR}/nagios.cfg", "#{CONFDIR}/nagios_tmp.cfg"
text = File.read("#{CONFDIR}/nagios_tmp.cfg")
text.gsub!(/#{TARGET}/, "#{TMPDIR}")
File.open("#{CONFDIR}/nagios_tmp.cfg", "w") { |f| f.puts text }
nagios_validation = `/usr/sbin/nagios3 -v #{CONFDIR}/nagios_tmp.cfg`
if $? != 0
puts "You should checkout these errors:"
puts
puts nagios_validation
false
else
true
end
rescue => e
puts "Something went horribly wrong while trying to validate nagios config. #{e}"
bailout 1
ensure
FileUtils.rm_rf "#{CONFDIR}/nagios_tmp.cfg"
end
end
def self.reload_nagios
puts `/etc/init.d/nagios3 reload`
end
def self.assemble_configs
OBJECTS.each do |o|
resources = self.collect_resources(o)
resources.each do |r|
File.open("#{TMPDIR}/#{o}.d/#{File.basename(r['title'])}", 'w') { |f| f.write(r['parameters']['content']) }
end
end
end
def self.nsync?
output = `diff -drupN #{TARGET} #{TMPDIR}`
if $? != 0
puts "Nagios Updates:"
puts "---------------"
puts
puts output
false
else
puts "Nagios configs are NSync"
true
end
end
def self.update_canary
FileUtils.touch(CANARY)
end
def self.update_configs
if self.valid_config?
self.rsync
self.reload_nagios
else
bailout 1
end
end
def self.run(noop = false)
begin
unless self.locked?
self.lock
self.setup
self.assemble_configs
if noop
bailout 1 unless self.nsync?
update_canary
bailout 0
else
self.update_configs unless self.nsync?
update_canary
end
else
puts "Hold your horses, hoss. Shit be happening already..."
exit 1
end
bailout 0
rescue => e
puts "Something went horribly wrong while trying to do the needful. #{e}"
bailout 1
end
end
def self.bailout(exit_code)
self.unlock
self.teardown
exit exit_code
end
end
end
if ARGV.include?('noop')
Nagios::PuppetDB.run(true)
else
Nagios::PuppetDB.run
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment