Class: Chef::Knife::SubcommandLoader
- Inherits:
-
Object
- Object
- Chef::Knife::SubcommandLoader
- Defined in:
- lib/chef/knife/core/subcommand_loader.rb
Constant Summary collapse
- MATCHES_CHEF_GEM =
%r{/chef-[\d]+\.[\d]+\.[\d]+}.freeze
- MATCHES_THIS_CHEF_GEM =
%r{/chef-#{Chef::VERSION}/}.freeze
Instance Attribute Summary collapse
-
#chef_config_dir ⇒ Object
readonly
Returns the value of attribute chef_config_dir.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
Instance Method Summary collapse
- #find_subcommands_via_dirglob ⇒ Object
-
#find_subcommands_via_manifest ⇒ Object
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.
- #find_subcommands_via_rubygems ⇒ Object
-
#gem_and_builtin_subcommands ⇒ Object
Returns a Hash of paths to knife commands built-in to chef, or installed via gem.
- #have_plugin_manifest? ⇒ Boolean
-
#initialize(chef_config_dir, env = ENV) ⇒ SubcommandLoader
constructor
A new instance of SubcommandLoader.
-
#load_commands ⇒ Object
Load all the sub-commands.
- #plugin_manifest ⇒ Object
- #plugin_manifest_path ⇒ Object
-
#site_subcommands ⇒ Object
Returns an Array of paths to knife commands located in chef_config_dir/plugins/knife/ and ~/.chef/plugins/knife/.
- #subcommand_files ⇒ Object
Constructor Details
#initialize(chef_config_dir, env = ENV) ⇒ SubcommandLoader
31 32 33 34 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 31 def initialize(chef_config_dir, env=ENV) @chef_config_dir, @env = chef_config_dir, env @forced_activate = {} end |
Instance Attribute Details
#chef_config_dir ⇒ Object (readonly)
Returns the value of attribute chef_config_dir.
28 29 30 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 28 def chef_config_dir @chef_config_dir end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
29 30 31 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 29 def env @env end |
Instance Method Details
#find_subcommands_via_dirglob ⇒ Object
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 112 def find_subcommands_via_dirglob # The "require paths" of the core knife subcommands bundled with chef files = Dir[File.join(Chef::Util::PathHelper.escape_glob(File.('../../../knife', __FILE__)), '*.rb')] subcommand_files = {} files.each do |knife_file| rel_path = knife_file[/#{CHEF_ROOT}#{Regexp.escape(File::SEPARATOR)}(.*)\.rb/,1] subcommand_files[rel_path] = knife_file end subcommand_files end |
#find_subcommands_via_manifest ⇒ Object
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.
99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 99 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 |
#find_subcommands_via_rubygems ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 123 def find_subcommands_via_rubygems files = find_files_latest_gems 'chef/knife/*.rb' subcommand_files = {} files.each do |file| rel_path = file[/(#{Regexp.escape File.join('chef', 'knife', '')}.*)\.rb/, 1] # When not installed as a gem (ChefDK/appbundler in particular), AND # a different version of Chef is installed via gems, `files` will # include some files from the 'other' Chef install. If this contains # a knife command that doesn't exist in this version of Chef, we will # get a LoadError later when we try to require it. next if from_different_chef_version?(file) subcommand_files[rel_path] = file end subcommand_files.merge(find_subcommands_via_dirglob) end |
#gem_and_builtin_subcommands ⇒ Object
Returns a Hash of paths to knife commands built-in to chef, or installed via gem. If rubygems is not installed, falls back to globbing the knife directory. The Hash is of the form => “/absolute/path” – Note: the “right” way to load the plugins is to require the relative path, i.e.,
require 'chef/knife/command'
but we’re getting frustrated by bugs at every turn, and it’s slow besides. So subcommand loader has been modified to load the plugins by using Kernel.load with the absolute path.
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 66 def gem_and_builtin_subcommands 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 |
#have_plugin_manifest? ⇒ Boolean
142 143 144 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 142 def have_plugin_manifest? ENV["HOME"] && File.exist?(plugin_manifest_path) end |
#load_commands ⇒ Object
Load all the sub-commands
37 38 39 40 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 37 def load_commands subcommand_files.each { |subcommand| Kernel.load subcommand } true end |
#plugin_manifest ⇒ Object
146 147 148 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 146 def plugin_manifest Chef::JSONCompat.from_json(File.read(plugin_manifest_path)) end |
#plugin_manifest_path ⇒ Object
150 151 152 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 150 def plugin_manifest_path File.join(ENV['HOME'], '.chef', 'plugin_manifest.json') end |
#site_subcommands ⇒ Object
Returns an Array of paths to knife commands located in chef_config_dir/plugins/knife/ and ~/.chef/plugins/knife/
44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 44 def site_subcommands user_specific_files = [] if chef_config_dir user_specific_files.concat Dir.glob(File.("plugins/knife/*.rb", Chef::Util::PathHelper.escape_glob(chef_config_dir))) end # finally search ~/.chef/plugins/knife/*.rb user_specific_files.concat Dir.glob(File.join(Chef::Util::PathHelper.escape_glob(env['HOME'], '.chef', 'plugins', 'knife'), '*.rb')) if env['HOME'] user_specific_files end |
#subcommand_files ⇒ Object
78 79 80 |
# File 'lib/chef/knife/core/subcommand_loader.rb', line 78 def subcommand_files @subcommand_files ||= (gem_and_builtin_subcommands.values + site_subcommands).flatten.uniq end |