diff options
Diffstat (limited to 'lib/chef/knife/core/subcommand_loader.rb')
-rw-r--r-- | lib/chef/knife/core/subcommand_loader.rb | 52 |
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) |