Skip to content

Instantly share code, notes, and snippets.

@dhoer
Created December 12, 2013 18:19
Show Gist options
  • Save dhoer/7932740 to your computer and use it in GitHub Desktop.
Save dhoer/7932740 to your computer and use it in GitHub Desktop.
Adds version info to knife deps output. Kudos to bjbishop for providing this hack.
require 'chef/chef_fs/knife'
class Chef
class Knife
class Deps < Chef::ChefFS::Knife
banner "knife deps PATTERN1 [PATTERNn]"
category "path-based"
deps do
require 'chef/chef_fs/file_system'
require 'chef/run_list'
end
option :recurse,
:long => '--[no-]recurse',
:boolean => true,
:description => "List dependencies recursively (default: true). Only works with --tree."
option :tree,
:long => '--tree',
:boolean => true,
:description => "Show dependencies in a visual tree. May show duplicates."
option :remote,
:long => '--remote',
:boolean => true,
:description => "List dependencies on the server instead of the local filesystem"
attr_accessor :exit_code
def run
if config[:recurse] == false && !config[:tree]
ui.error "--no-recurse requires --tree"
exit(1)
end
config[:recurse] = true if config[:recurse].nil?
@root = config[:remote] ? chef_fs : local_fs
dependencies = {}
pattern_args.each do |pattern|
Chef::ChefFS::FileSystem.list(@root, pattern).each do |entry|
if config[:tree]
print_dependencies_tree(entry, dependencies)
else
print_flattened_dependencies(entry, dependencies)
end
end
end
exit exit_code if exit_code
end
def print_flattened_dependencies(entry, dependencies)
if !dependencies[entry.path]
dependencies[entry.path] = get_dependencies(entry)
dependencies[entry.path].each do |child|
child_entry = Chef::ChefFS::FileSystem.resolve_path(@root, child)
print_flattened_dependencies(child_entry, dependencies)
end
output "#{entry.chef_object.metadata.name} (#{entry.chef_object.metadata.version})" #bjbishop hack
end
end
def print_dependencies_tree(entry, dependencies, printed = {}, depth = 0)
dependencies[entry.path] = get_dependencies(entry) if !dependencies[entry.path]
output "#{' '*depth}#{entry.chef_object.metadata.name} (#{entry.chef_object.metadata.version})" #bjbishop hack
if !printed[entry.path] && (config[:recurse] || depth == 0)
printed[entry.path] = true
dependencies[entry.path].each do |child|
child_entry = Chef::ChefFS::FileSystem.resolve_path(@root, child)
print_dependencies_tree(child_entry, dependencies, printed, depth+1)
end
end
end
def get_dependencies(entry)
begin
if entry.parent && entry.parent.path == '/cookbooks'
return entry.chef_object.metadata.dependencies.keys.map { |cookbook| "/cookbooks/#{cookbook}" }
elsif entry.parent && entry.parent.path == '/nodes'
node = JSON.parse(entry.read, :create_additions => false)
result = []
if node['chef_environment'] && node['chef_environment'] != '_default'
result << "/environments/#{node['chef_environment']}.json"
end
if node['run_list']
result += dependencies_from_runlist(node['run_list'])
end
result
elsif entry.parent && entry.parent.path == '/roles'
role = JSON.parse(entry.read, :create_additions => false)
result = []
if role['run_list']
dependencies_from_runlist(role['run_list']).each do |dependency|
result << dependency if !result.include?(dependency)
end
end
if role['env_run_lists']
role['env_run_lists'].each_pair do |env, run_list|
dependencies_from_runlist(run_list).each do |dependency|
result << dependency if !result.include?(dependency)
end
end
end
result
elsif !entry.exists?
raise Chef::ChefFS::FileSystem::NotFoundError.new(entry)
else
[]
end
rescue Chef::ChefFS::FileSystem::NotFoundError => e
ui.error "#{format_path(e.entry)}: No such file or directory"
self.exit_code = 2
[]
end
end
def dependencies_from_runlist(run_list)
chef_run_list = Chef::RunList.new
chef_run_list.reset!(run_list)
chef_run_list.map do |run_list_item|
case run_list_item.type
when :role
"/roles/#{run_list_item.name}.json"
when :recipe
if run_list_item.name =~ /(.+)::[^:]*/
"/cookbooks/#{$1}"
else
"/cookbooks/#{run_list_item.name}"
end
else
raise "Unknown run list item type #{run_list_item.type}"
end
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment