@@ -60,9 +60,13 @@ def site_subcommands
60
60
# subcommand loader has been modified to load the plugins by using Kernel.load
61
61
# with the absolute path.
62
62
def gem_and_builtin_subcommands
63
- # search all gems for chef/knife/*.rb
64
- require 'rubygems'
65
- find_subcommands_via_rubygems
63
+ if have_plugin_manifest?
64
+ find_subcommands_via_manifest
65
+ else
66
+ # search all gems for chef/knife/*.rb
67
+ require 'rubygems'
68
+ find_subcommands_via_rubygems
69
+ end
66
70
rescue LoadError
67
71
find_subcommands_via_dirglob
68
72
end
@@ -71,6 +75,36 @@ def subcommand_files
71
75
@subcommand_files ||= ( gem_and_builtin_subcommands . values + site_subcommands ) . flatten . uniq
72
76
end
73
77
78
+ # If the user has created a ~/.chef/plugin_manifest.json file, we'll use
79
+ # that instead of inspecting the on-system gems to find the plugins. The
80
+ # file format is expected to look like:
81
+ #
82
+ # { "plugins": {
83
+ # "knife-ec2": {
84
+ # "paths": [
85
+ # "/home/alice/.rubymanagerthing/gems/knife-ec2-x.y.z/lib/chef/knife/ec2_server_create.rb",
86
+ # "/home/alice/.rubymanagerthing/gems/knife-ec2-x.y.z/lib/chef/knife/ec2_server_delete.rb"
87
+ # ]
88
+ # }
89
+ # }
90
+ # }
91
+ #
92
+ # Extraneous content in this file is ignored. This intentional so that we
93
+ # can adapt the file format for potential behavior changes to knife in
94
+ # the future.
95
+ def find_subcommands_via_manifest
96
+ # Format of subcommand_files is "relative_path" (something you can
97
+ # Kernel.require()) => full_path. The relative path isn't used
98
+ # currently, so we just map full_path => full_path.
99
+ subcommand_files = { }
100
+ plugin_manifest [ "plugins" ] . each do |plugin_name , plugin_manifest |
101
+ plugin_manifest [ "paths" ] . each do |cmd_path |
102
+ subcommand_files [ cmd_path ] = cmd_path
103
+ end
104
+ end
105
+ subcommand_files . merge ( find_subcommands_via_dirglob )
106
+ end
107
+
74
108
def find_subcommands_via_dirglob
75
109
# The "require paths" of the core knife subcommands bundled with chef
76
110
files = Dir [ File . expand_path ( '../../../knife/*.rb' , __FILE__ ) ]
@@ -93,6 +127,18 @@ def find_subcommands_via_rubygems
93
127
subcommand_files . merge ( find_subcommands_via_dirglob )
94
128
end
95
129
130
+ def have_plugin_manifest?
131
+ ENV [ "HOME" ] && File . exist? ( plugin_manifest_path )
132
+ end
133
+
134
+ def plugin_manifest
135
+ Chef ::JSONCompat . from_json ( File . read ( plugin_manifest_path ) )
136
+ end
137
+
138
+ def plugin_manifest_path
139
+ File . join ( ENV [ 'HOME' ] , '.chef' , 'plugin_manifest.json' )
140
+ end
141
+
96
142
private
97
143
98
144
def find_files_latest_gems ( glob , check_load_path = true )
0 commit comments