Skip to content

Commit

Permalink
First complete working script commit for 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
J.B. Zimmerman committed Oct 7, 2011
1 parent 8f36d73 commit 3b94c0c
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 61 deletions.
8 changes: 0 additions & 8 deletions knife_audit_cookbook/README.rdoc

This file was deleted.

6 changes: 0 additions & 6 deletions knife_audit_cookbook/metadata.rb

This file was deleted.

32 changes: 0 additions & 32 deletions knife_audit_cookbook/recipes/default.rb

This file was deleted.

140 changes: 126 additions & 14 deletions lib/chef/knife/audit.rb
@@ -1,5 +1,5 @@
#
## Author:: Jacob Zimmermann (<jzimmerman@mdsol.com>)
## Author:: Jacob Zimmermann (<jbzimmerman91@gmail.com>)
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -36,6 +36,21 @@ class Audit < Chef::Knife
:long => "--show-nodelist",
:description => "Show all nodes running each cookbook"

option :all_cookbooks,
:short => "-a",
:long => "--all-cookbooks",
:description => "Show all cookbook references, including those from seen_recipes if available on nodes from helper cookbook"

option :totals,
:short => "-t",
:long => "--totals",
:description => "Show cookbook count totals for all node types"

option :install_cookbook,
:short => "-i",
:long => "--install-cookbook",
:description => "Install knife_audit helper cookbook into current chef cookbook directory"

def run

if @name_args.empty?
Expand All @@ -45,6 +60,27 @@ def run
end

self.config = Chef::Config.merge!(config)

# If :install_cookbook flag is set, just install the cookbook and return (exit).
if config[:install_cookbook]

unless config[:cookbook_path]
ui.msg("No cookbook path set in Chef config, cannot install cookbook.")
return
end

source_path = File.dirname(__FILE__) + "/knife_audit_cookbook"
dest_path = config[:cookbook_path].first + "/knife_audit"

if File.exist?(dest_path)
ui.msg("knife_audit cookbook already present in cookbook directory #{config[:cookbook_path].first} - aborting...")
else
FileUtils.copy_entry(source_path, dest_path)
ui.msg("knife-audit cookbook copied to Chef cookbook directory #{config[:cookbook_path].first}")
end

return
end

# 1) Get a list (hash, actually, with key of 'name') of cookbooks available on the current server/org
# unless we've been given a cookbook/cookbooks on the command line
Expand All @@ -71,8 +107,10 @@ def run

# add count => 0 to each cookbook hash
cookbook_list.each do |name,book|
book["count"] = 0
book["count"] = 0
book["seen_recipe_count"] = 0
book["nodes"] = []
book["seen_recipe_nodes"] = []
end


Expand All @@ -89,46 +127,120 @@ def run

# 3a) Get node's runlist

# using expand!.recipes catches multi-level roles (roles with roles with recipes, etc.)
recipes = node.expand!.recipes.to_a
# Check to see if we need the seen_recipes total or not; if no, skip.
# If yes use seen_recipes if it's available. If it's not available, fall back
# to the node.recipes contents.
if (config[:all_cookbooks] || config[:totals])
recipes = (node["knife_audit"] && node["knife_audit"]["seen_recipes"].keys) || node.expand!.recipes.to_a
if node["knife_audit"] && node["knife_audit"]["seen_recipes"]
node_seen_recipe_flag = true
end
else
# If not, use node.recipes. Using expand!.recipes catches multi-level roles
# (roles with roles with recipes, etc.)
recipes = node.expand!.recipes.to_a
end

node_cookbook_list = recipes.map{ |x| x.match(/[^\:]+/)[0] }.uniq

# 3b) For each cookbook in the node runlist, if it's in our cookbook array increment its count and
# add the node to its running node array

node_cookbook_list.each do |cookbook|
if cookbook_list.has_key?(cookbook)
# Up the cookbook count
cookbook_list[cookbook]["count"] += 1
# Add the node to the cookbook's nodes array
cookbook_list[cookbook]["nodes"] << node.name
if cookbook_list.has_key?(cookbook)
# Up the appropriate ookbook count and add node to appropriate nodes array
if node_seen_recipe_flag
cookbook_list[cookbook]["seen_recipe_count"] += 1
cookbook_list[cookbook]["seen_recipe_nodes"] << node.name
else
cookbook_list[cookbook]["count"] += 1
cookbook_list[cookbook]["nodes"] << node.name
end
end
end
node_seen_recipe_flag = false

end # step 3 iterate end

# 4) Output

format_cookbook_audit_list_for_display(cookbook_list).each do |line|
ui.msg(line)
unless config[:totals]
ui.msg("Cookbook audit from node runlists:")

format_cookbook_runlist_list_for_display(cookbook_list).each do |line|
ui.msg(line)
end
end

if config[:all_cookbooks]
puts("\n")

ui.msg("Cookbook audit from seen_recipes:")

format_cookbook_seenlist_list_for_display(cookbook_list).each do |line|
ui.msg(line)
end
end

if config[:totals]
puts("\n")

ui.msg("Cookbook audit totals - runlist-only nodes + seen_recipes:")

format_cookbook_totallist_list_for_display(cookbook_list).each do |line|
ui.msg(line)
end
end


end # 'run' def end


def format_cookbook_audit_list_for_display(item)
def format_cookbook_runlist_list_for_display(item)
key_length = item.empty? ? 0 : item.keys.map {|name| name.size }.max + 2
if config[:show_nodelist]
item.sort.map do |name, cookbook|
"#{name.ljust(key_length)} #{cookbook["count"]} [ #{cookbook["nodes"].join(' ')} ]"
"#{name.ljust(key_length)} #{cookbook["count"]} [ #{cookbook["nodes"].join(' ')} ]"
end
else
item.sort.map do |name, cookbook|
"#{name.ljust(key_length)} #{cookbook["count"]}"
end
end

end # format_cokbook_audit... def end
end # format_cokbook_runlist... def end

def format_cookbook_seenlist_list_for_display(item)
key_length = item.empty? ? 0 : item.keys.map {|name| name.size }.max + 2
if config[:show_nodelist]
item.sort.map do |name, cookbook|
"#{name.ljust(key_length)} #{cookbook["seen_recipe_count"]} [ #{cookbook["seen_recipe_nodes"].join(' ')} ]"
end
else
item.sort.map do |name, cookbook|
"#{name.ljust(key_length)} #{cookbook["seen_recipe_count"]}"
end
end

end # format_cokbook_seenlist... def end

def format_cookbook_totallist_list_for_display(item)
key_length = item.empty? ? 0 : item.keys.map {|name| name.size }.max + 2
if config[:show_nodelist]
item.sort.map do |name, cookbook|
cookbook_display = (cookbook["seen_recipe_nodes"] + cookbook["nodes"]).uniq
cookbook_count = cookbook["seen_recipe_count"] + cookbook["count"]
"#{name.ljust(key_length)} #{cookbook_count} [ #{cookbook_display.join(' ')} ]"
end
else
item.sort.map do |name, cookbook|
cookbook_count = cookbook["seen_recipe_count"] + cookbook["count"]
"#{name.ljust(key_length)} #{cookbook_count}"
end
end

end # format_cokbook_seenlist... def end



end #class end
Expand Down
2 changes: 1 addition & 1 deletion lib/knife-audit/version.rb
@@ -1,5 +1,5 @@
module Knife
module Audit
VERSION = "0.0.1"
VERSION = "0.2.0"
end
end

0 comments on commit 3b94c0c

Please sign in to comment.