Skip to content

Instantly share code, notes, and snippets.

@intjonathan
Forked from jfryman/nagiosdb.rb
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save intjonathan/8814147 to your computer and use it in GitHub Desktop.
Save intjonathan/8814147 to your computer and use it in GitHub Desktop.
Update nagios configuration from puppetdb using stock puppet nagios_ resources.
#!/usr/bin/env ruby
#
# Nagios/PuppetDB config generator
# https://gist.github.com/jfryman/6290985
#
# 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 'https://your_puppetdb_server:8081'
format :json
OBJECTS = %w(
host
hostgroup
hostescalation
hostdependency
hostextinfo
service
servicegroup
serviceescalation
servicedependency
serviceextinfo
contact
contactgroup
timeperiod
command
)
TARGET='/etc/nagios/conf.d'
CONFDIR='/etc/nagios'
TMPDIR='/tmp/nagios/conf.d'
TMPCONFIG='/tmp/nagios/nagios_tmp.cfg'
LOCKFILE="/tmp/#{File.basename $0}.lock"
CANARY="/tmp/nagiosdb_ok"
NAGIOS_BIN='/usr/sbin/nagios'
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 TMPDIR
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', "Nagios_#{resource}"],
['=', ['node', 'active'], true],
['not',
['=', ['parameter', 'ensure'], 'absent']
],
]
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", TMPCONFIG
text = File.read(TMPCONFIG)
text.gsub!(/#{TARGET}/, "#{TMPDIR}")
File.write(TMPCONFIG, text)
nagios_validation = `#{NAGIOS_BIN} -v #{TMPCONFIG}`
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 TMPCONFIG
end
end
def self.reload_nagios
puts `/etc/init.d/nagios 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'])}.cfg", 'w') do |f|
my_params = self.filter_resource_params(r['parameters'])
my_params = self.simulate_name_from_title(o, r['title'], my_params)
my_params = Hash[my_params.sort]
body = my_params.map { |(k,v)|
"#{'%-35s' % k} #{v.respond_to?(:join) ? v.join(',') : v}"
}
f.write(<<-EOD
define #{o} {
#{body.join("\n ")}
}
EOD
)
end
end
end
end
def self.filter_resource_params(params)
params.reject do |(k,v)|
%w(audit before loglevel noop ensure
notify require schedule stage subscribe tag).include?(k)
end
end
def self.simulate_name_from_title(object_type, title, params)
unnamed_types = %w(service servicedependency hostdependency hostescalation
hostextinfo serviceextinfo)
if !unnamed_types.include?(object_type) && params['register'] != '0'
params["#{object_type}_name"] ||= title
end
params['name'] ||= title
return params
end
def self.nsync?
output = `diff -drupN #{TARGET} #{TMPDIR}`
if $? != 0
puts "Nagios Updates:"
puts "---------------"
puts
puts output
false
else
puts "Nagios configs are synced"
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