Skip to content

Instantly share code, notes, and snippets.

@manuq
Last active August 29, 2015 14:05
Show Gist options
  • Save manuq/eec269ce7ba00974f46e to your computer and use it in GitHub Desktop.
Save manuq/eec269ce7ba00974f46e to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby
# Utility for Puppet that outputs orphaned resources. Orphaned are
# resources that where at one point managed by Puppet, but they no
# longer are.
#
# We need to require Puppet because deserializing the report produces
# Puppet objects.
require 'optparse'
require 'yaml'
require 'puppet'
FILTERED_RESOURCES = ['Schedule[', 'File[/etc/puppet', 'File[/var/lib/puppet',
'File[/var/log/puppet', 'File[/var/run/puppet',
'configuration', 'Stage[main]', 'Class[Main]',
'Class[Settings]', 'Filebucket[puppet]']
# puppet config print lastrunreport
$report_path = "/var/lib/puppet/state/last_run_report.yaml"
# puppet config print lastrunfile
$summary_path = "/var/lib/puppet/state/last_run_summary.yaml"
# puppet config print statefile
$state_path = "/var/lib/puppet/state/state.yaml"
METHODS = %w[report timestamps]
$method = "report"
OptionParser.new do |opts|
opts.banner = "Usage: orphaned.rb [options]"
opts.on('-m', '--method TYPE', "report or timestamps. Always used. Default: #{$method}", METHODS) { |m| $method = m }
opts.on('-t', '--state PATH', "Path to state.yaml. Default: #{$state_path}") { |p| $state_path = p }
opts.on('-r', '--report PATH', "Path to last_run_report.yaml. Used in method report. Default: #{$report_path}") { |p| $report_path = p }
opts.on('-s', '--summary PATH', "Path to last_run_summary.yaml. Used in method timestamps. Default: #{$summary_path}") { |p| $summary_path = p }
opts.on('-p', '--previous-report PATH', "Path to a previous last_run_report.yaml. If given, output has more detail.") { |p| $previous_report_path = p }
end.parse!
def parse_last_run(last_run_summary_data)
total = last_run_summary_data['time']['total']
seconds_last_run = last_run_summary_data['time']['last_run']
Time.at(seconds_last_run - total - 2)
end
def get_last_run(last_run_summary_path)
data = YAML.load_file(last_run_summary_path)
parse_last_run(data)
end
def parse_state_resources(state_data)
resources_data = state_data.select do |k, v|
not k.to_s.start_with?(*FILTERED_RESOURCES)
end
if resources_data.is_a? Array
resources_data.to_h
else
resources_data
end
end
def get_state_resources(state_path)
data = YAML.load_file(state_path)
parse_state_resources(data)
end
def parse_old_state_resources(state_data, last_run)
resources_data = parse_state_resources(state_data)
unmanaged_resources = []
resources_data.each do |k, v|
if v[:checked] < last_run
unmanaged_resources.push(k)
end
end
return unmanaged_resources
end
def get_old_state_resources(state_path, last_run)
data = YAML.load_file(state_path)
parse_old_state_resources(data, last_run)
end
def parse_report_resources(report_data)
resources_data = report_data.resource_statuses.select do |k, v|
not k.to_s.start_with?(*FILTERED_RESOURCES)
end
if resources_data.is_a? Array
resources_data.to_h
else
resources_data
end
end
def get_report_resources(report_path)
data = YAML.load_file(report_path)
parse_report_resources(data)
end
def get_orphans_using_timestamps(state_path, summary_path)
last_run = get_last_run(summary_path)
get_old_state_resources(state_path, last_run)
end
def get_orphans_using_report(state_path, report_path)
state_resources = get_state_resources(state_path)
report_resources = get_report_resources(report_path)
state_resources.keys - report_resources.keys
end
def print_detail(orphan_resources, previous_report_path)
previous_resources = get_report_resources(previous_report_path)
orphan_resources.each do |k|
puts k
if previous_resources.keys.include? k
puts previous_resources[k].to_yaml
end
end
end
if $method == 'report'
orphans = get_orphans_using_report($state_path, $report_path)
else
orphans = get_orphans_using_timestamps($state_path, $summary_path)
end
if $previous_report_path.nil?
puts orphans
else
print_detail(orphans, $previous_report_path)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment