summaryrefslogtreecommitdiff
path: root/lib/chef/knife/core/subcommand_loader.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/knife/core/subcommand_loader.rb')
-rw-r--r--lib/chef/knife/core/subcommand_loader.rb52
1 files changed, 49 insertions, 3 deletions
diff --git a/lib/chef/knife/core/subcommand_loader.rb b/lib/chef/knife/core/subcommand_loader.rb
index f18bc6619e..0489c726b3 100644
--- a/lib/chef/knife/core/subcommand_loader.rb
+++ b/lib/chef/knife/core/subcommand_loader.rb
@@ -60,9 +60,13 @@ class Chef
# subcommand loader has been modified to load the plugins by using Kernel.load
# with the absolute path.
def gem_and_builtin_subcommands
- # search all gems for chef/knife/*.rb
- require 'rubygems'
- find_subcommands_via_rubygems
+ if have_plugin_manifest?
+ find_subcommands_via_manifest
+ else
+ # search all gems for chef/knife/*.rb
+ require 'rubygems'
+ find_subcommands_via_rubygems
+ end
rescue LoadError
find_subcommands_via_dirglob
end
@@ -71,6 +75,36 @@ class Chef
@subcommand_files ||= (gem_and_builtin_subcommands.values + site_subcommands).flatten.uniq
end
+ # If the user has created a ~/.chef/plugin_manifest.json file, we'll use
+ # that instead of inspecting the on-system gems to find the plugins. The
+ # file format is expected to look like:
+ #
+ # { "plugins": {
+ # "knife-ec2": {
+ # "paths": [
+ # "/home/alice/.rubymanagerthing/gems/knife-ec2-x.y.z/lib/chef/knife/ec2_server_create.rb",
+ # "/home/alice/.rubymanagerthing/gems/knife-ec2-x.y.z/lib/chef/knife/ec2_server_delete.rb"
+ # ]
+ # }
+ # }
+ # }
+ #
+ # Extraneous content in this file is ignored. This intentional so that we
+ # can adapt the file format for potential behavior changes to knife in
+ # the future.
+ def find_subcommands_via_manifest
+ # Format of subcommand_files is "relative_path" (something you can
+ # Kernel.require()) => full_path. The relative path isn't used
+ # currently, so we just map full_path => full_path.
+ subcommand_files = {}
+ plugin_manifest["plugins"].each do |plugin_name, plugin_manifest|
+ plugin_manifest["paths"].each do |cmd_path|
+ subcommand_files[cmd_path] = cmd_path
+ end
+ end
+ subcommand_files.merge(find_subcommands_via_dirglob)
+ end
+
def find_subcommands_via_dirglob
# The "require paths" of the core knife subcommands bundled with chef
files = Dir[File.expand_path('../../../knife/*.rb', __FILE__)]
@@ -93,6 +127,18 @@ class Chef
subcommand_files.merge(find_subcommands_via_dirglob)
end
+ def have_plugin_manifest?
+ ENV["HOME"] && File.exist?(plugin_manifest_path)
+ end
+
+ def plugin_manifest
+ Chef::JSONCompat.from_json(File.read(plugin_manifest_path))
+ end
+
+ def plugin_manifest_path
+ File.join(ENV['HOME'], '.chef', 'plugin_manifest.json')
+ end
+
private
def find_files_latest_gems(glob, check_load_path=true)