summaryrefslogtreecommitdiff
path: root/lib/chef/knife/deps.rb
diff options
context:
space:
mode:
authorjkeiser <jkeiser@opscode.com>2012-12-18 08:08:33 -0800
committerJohn Keiser <jkeiser@opscode.com>2013-06-07 13:12:13 -0700
commitaacbb12ceed58c5bda6586e79a637d459457f8e3 (patch)
treefdbb1b6fb39bacc630b41ca74b06a9d849fcfd73 /lib/chef/knife/deps.rb
parent20c26a8feb6b17a585a0f766e99474c6b0d822d5 (diff)
downloadchef-aacbb12ceed58c5bda6586e79a637d459457f8e3.tar.gz
Rename knife dependencies -> knife deps
Diffstat (limited to 'lib/chef/knife/deps.rb')
-rw-r--r--lib/chef/knife/deps.rb115
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/chef/knife/deps.rb b/lib/chef/knife/deps.rb
new file mode 100644
index 0000000000..489a166566
--- /dev/null
+++ b/lib/chef/knife/deps.rb
@@ -0,0 +1,115 @@
+require 'chef/chef_fs/knife'
+require 'chef/chef_fs/file_system'
+
+class Chef
+ class Knife
+ class Deps < Chef::ChefFS::Knife
+ banner "knife deps PATTERN1 [PATTERNn]"
+
+ common_options
+
+ 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"
+
+ def run
+ if config[:tree] && config[:recurse]
+ STDERR.puts "--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) do |entry|
+ if config[:tree]
+ print_dependencies_tree(entry, dependencies)
+ else
+ print_flattened_dependencies(entry, dependencies)
+ end
+ end
+ end
+ 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
+ puts format_path(entry.path)
+ end
+ end
+
+ def print_dependencies_tree(entry, dependencies, printed = {}, depth = 0)
+ dependencies[entry.path] = get_dependencies(entry) if !dependencies[entry.path]
+ puts "#{' '*depth}#{format_path(entry.path)}"
+ if !printed[entry.path] && (config[:recurse] || depth <= 1)
+ 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
+ object = entry.chef_object
+ rescue Chef::ChefFS::FileSystem::NotFoundError
+ STDERR.puts "#{result.path_for_printing}: No such file or directory"
+ return []
+ end
+ if !object
+ STDERR.puts "ERROR: #{entry} is not a Chef object!"
+ return []
+ end
+
+ if object.is_a?(Chef::CookbookVersion)
+ return object.metadata.dependencies.keys.map { |cookbook| "/cookbooks/#{cookbook}"}
+ elsif object.is_a?(Chef::Node)
+ return [ "/environments/#{object.chef_environment}.json" ] + dependencies_from_runlist(object.run_list)
+ elsif object.is_a?(Chef::Role)
+ result = []
+ object.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
+ return result
+ else
+ return []
+ end
+ end
+
+ def dependencies_from_runlist(run_list)
+ result = 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
+