chef 11.10.0.alpha.1 → 11.10.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +57 -36
- data/distro/common/html/chef-client.8.html +4 -4
- data/distro/common/html/chef-expander.8.html +4 -4
- data/distro/common/html/chef-expanderctl.8.html +4 -4
- data/distro/common/html/chef-server-webui.8.html +4 -4
- data/distro/common/html/chef-server.8.html +4 -4
- data/distro/common/html/chef-shell.1.html +4 -4
- data/distro/common/html/chef-solo.8.html +4 -4
- data/distro/common/html/chef-solr.8.html +5 -5
- data/distro/common/html/knife-bootstrap.1.html +4 -4
- data/distro/common/html/knife-client.1.html +4 -4
- data/distro/common/html/knife-configure.1.html +4 -4
- data/distro/common/html/knife-cookbook-site.1.html +4 -4
- data/distro/common/html/knife-cookbook.1.html +4 -4
- data/distro/common/html/knife-data-bag.1.html +4 -4
- data/distro/common/html/knife-environment.1.html +4 -4
- data/distro/common/html/knife-exec.1.html +4 -4
- data/distro/common/html/knife-index.1.html +4 -4
- data/distro/common/html/knife-node.1.html +4 -4
- data/distro/common/html/knife-role.1.html +4 -4
- data/distro/common/html/knife-search.1.html +4 -4
- data/distro/common/html/knife-ssh.1.html +4 -4
- data/distro/common/html/knife-status.1.html +4 -4
- data/distro/common/html/knife-tag.1.html +4 -4
- data/distro/common/html/knife.1.html +4 -4
- data/distro/common/man/man1/knife-bootstrap.1 +58 -64
- data/distro/common/man/man1/knife-client.1 +19 -22
- data/distro/common/man/man1/knife-configure.1 +37 -46
- data/distro/common/man/man1/knife-cookbook-site.1 +14 -17
- data/distro/common/man/man1/knife-cookbook.1 +15 -18
- data/distro/common/man/man1/knife-data-bag.1 +14 -17
- data/distro/common/man/man1/knife-delete.1 +38 -47
- data/distro/common/man/man1/knife-deps.1 +39 -48
- data/distro/common/man/man1/knife-diff.1 +43 -52
- data/distro/common/man/man1/knife-download.1 +47 -53
- data/distro/common/man/man1/knife-edit.1 +32 -41
- data/distro/common/man/man1/knife-environment.1 +14 -17
- data/distro/common/man/man1/knife-exec.1 +52 -61
- data/distro/common/man/man1/knife-index-rebuild.1 +1 -61
- data/distro/common/man/man1/knife-list.1 +47 -59
- data/distro/common/man/man1/knife-node.1 +15 -18
- data/distro/common/man/man1/knife-raw.1 +28 -46
- data/distro/common/man/man1/knife-recipe-list.1 +1 -61
- data/distro/common/man/man1/knife-role.1 +19 -25
- data/distro/common/man/man1/knife-search.1 +53 -62
- data/distro/common/man/man1/knife-show.1 +36 -28
- data/distro/common/man/man1/knife-ssh.1 +55 -61
- data/distro/common/man/man1/knife-status.1 +34 -43
- data/distro/common/man/man1/knife-tag.1 +14 -17
- data/distro/common/man/man1/knife-upload.1 +47 -56
- data/distro/common/man/man1/knife-user.1 +17 -20
- data/distro/common/man/man1/knife-xargs.1 +60 -69
- data/lib/chef/application.rb +3 -1
- data/lib/chef/application/windows_service.rb +0 -1
- data/lib/chef/client.rb +41 -152
- data/lib/chef/config.rb +19 -23
- data/lib/chef/data_bag.rb +1 -1
- data/lib/chef/data_bag_item.rb +1 -1
- data/lib/chef/exceptions.rb +8 -0
- data/lib/chef/formatters/doc.rb +15 -0
- data/lib/chef/formatters/error_inspectors/api_error_formatting.rb +2 -1
- data/lib/chef/http.rb +18 -8
- data/lib/chef/http/authenticator.rb +4 -0
- data/lib/chef/http/cookie_manager.rb +3 -0
- data/lib/chef/http/decompressor.rb +4 -0
- data/lib/chef/http/json_input.rb +4 -0
- data/lib/chef/http/json_output.rb +4 -0
- data/lib/chef/http/validate_content_length.rb +94 -0
- data/lib/chef/knife.rb +0 -1
- data/lib/chef/knife/configure.rb +6 -6
- data/lib/chef/knife/cookbook_create.rb +2 -2
- data/lib/chef/knife/core/subcommand_loader.rb +49 -3
- data/lib/chef/knife/ssh.rb +34 -4
- data/lib/chef/mixin/path_sanity.rb +1 -0
- data/lib/chef/monologger.rb +1 -2
- data/lib/chef/node.rb +7 -0
- data/lib/chef/policy_builder.rb +49 -0
- data/lib/chef/policy_builder/expand_node_object.rb +230 -0
- data/lib/chef/policy_builder/policyfile.rb +338 -0
- data/lib/chef/provider/file.rb +15 -5
- data/lib/chef/provider/group.rb +6 -2
- data/lib/chef/provider/group/windows.rb +12 -2
- data/lib/chef/provider/http_request.rb +3 -2
- data/lib/chef/provider/package.rb +1 -0
- data/lib/chef/provider/package/aix.rb +1 -1
- data/lib/chef/provider/service/debian.rb +7 -2
- data/lib/chef/resource/file.rb +8 -1
- data/lib/chef/resource/package.rb +9 -0
- data/lib/chef/resource/service.rb +0 -1
- data/lib/chef/rest.rb +2 -0
- data/lib/chef/run_context.rb +1 -1
- data/lib/chef/util/file_edit.rb +1 -1
- data/lib/chef/util/windows/net_group.rb +7 -6
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/version.rb +31 -18
- data/spec/data/cookbooks/preseed/templates/default/preseed-template-variables.seed +1 -0
- data/spec/functional/resource/file_spec.rb +0 -1
- data/spec/functional/resource/group_spec.rb +96 -16
- data/spec/functional/resource/package_spec.rb +17 -0
- data/spec/functional/resource/user_spec.rb +2 -2
- data/spec/functional/win32/versions_spec.rb +39 -0
- data/spec/integration/client/client_spec.rb +27 -28
- data/spec/spec_helper.rb +2 -0
- data/spec/support/platform_helpers.rb +7 -1
- data/spec/support/shared/functional/file_resource.rb +83 -43
- data/spec/unit/application_spec.rb +7 -5
- data/spec/unit/client_spec.rb +10 -3
- data/spec/unit/config_spec.rb +0 -30
- data/spec/unit/cookbook_spec.rb +1 -0
- data/spec/unit/data_bag_item_spec.rb +8 -0
- data/spec/unit/data_bag_spec.rb +6 -0
- data/spec/unit/http_spec.rb +48 -0
- data/spec/unit/knife/core/subcommand_loader_spec.rb +77 -1
- data/spec/unit/knife/ssh_spec.rb +107 -0
- data/spec/unit/mixin/path_sanity_spec.rb +6 -0
- data/spec/unit/mixin/securable_spec.rb +77 -3
- data/spec/unit/monologger_spec.rb +45 -0
- data/spec/unit/node_spec.rb +16 -0
- data/spec/unit/policy_builder/expand_node_object_spec.rb +320 -0
- data/spec/unit/policy_builder/policyfile_spec.rb +399 -0
- data/spec/unit/policy_builder_spec.rb +26 -0
- data/spec/unit/provider/deploy_spec.rb +3 -0
- data/spec/unit/provider/group/windows_spec.rb +1 -0
- data/spec/unit/provider/http_request_spec.rb +23 -1
- data/spec/unit/provider/service/debian_service_spec.rb +50 -19
- data/spec/unit/recipe_spec.rb +4 -0
- data/spec/unit/resource/package_spec.rb +5 -0
- data/spec/unit/rest_spec.rb +375 -278
- data/spec/unit/run_context_spec.rb +4 -0
- metadata +96 -59
- checksums.yaml +0 -7
data/lib/chef/config.rb
CHANGED
@@ -127,26 +127,6 @@ class Chef
|
|
127
127
|
# properly.
|
128
128
|
configurable(:daemonize).writes_value { |v| v }
|
129
129
|
|
130
|
-
# Override the config dispatch to set the value of log_location configuration option
|
131
|
-
#
|
132
|
-
# === Parameters
|
133
|
-
# location<IO||String>:: Logging location as either an IO stream or string representing log file path
|
134
|
-
#
|
135
|
-
config_attr_writer :log_location do |location|
|
136
|
-
if location.respond_to? :sync=
|
137
|
-
location.sync = true
|
138
|
-
location
|
139
|
-
elsif location.respond_to? :to_str
|
140
|
-
begin
|
141
|
-
f = File.new(location.to_str, "a")
|
142
|
-
f.sync = true
|
143
|
-
rescue Errno::ENOENT
|
144
|
-
raise Chef::Exceptions::ConfigurationError, "Failed to open or create log file at #{location.to_str}"
|
145
|
-
end
|
146
|
-
f
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
130
|
# The root where all local chef object data is stored. cookbooks, data bags,
|
151
131
|
# environments are all assumed to be in separate directories under this.
|
152
132
|
# chef-solo uses these directories for input data. knife commands
|
@@ -299,6 +279,9 @@ class Chef
|
|
299
279
|
# logger is the primary mode of output, and the log level is set to :info
|
300
280
|
default :log_level, :auto
|
301
281
|
|
282
|
+
# Logging location as either an IO stream or string representing log file path
|
283
|
+
default :log_location, STDOUT
|
284
|
+
|
302
285
|
# Using `force_formatter` causes chef to default to formatter output when STDOUT is not a tty
|
303
286
|
default :force_formatter, false
|
304
287
|
|
@@ -310,7 +293,6 @@ class Chef
|
|
310
293
|
default :interval, nil
|
311
294
|
default :once, nil
|
312
295
|
default :json_attribs, nil
|
313
|
-
default :log_location, STDOUT
|
314
296
|
# toggle info level log items that can create a lot of output
|
315
297
|
default :verbose_logging, true
|
316
298
|
default :node_name, nil
|
@@ -338,6 +320,16 @@ class Chef
|
|
338
320
|
default :enable_reporting, true
|
339
321
|
default :enable_reporting_url_fatals, false
|
340
322
|
|
323
|
+
# Policyfile is an experimental feature where a node gets its run list and
|
324
|
+
# cookbook version set from a single document on the server instead of
|
325
|
+
# expanding the run list and having the server compute the cookbook version
|
326
|
+
# set based on environment constraints.
|
327
|
+
#
|
328
|
+
# Because this feature is experimental, it is not recommended for
|
329
|
+
# production use. Developent/release of this feature may not adhere to
|
330
|
+
# semver guidelines.
|
331
|
+
default :use_policyfile, false
|
332
|
+
|
341
333
|
# Set these to enable SSL authentication / mutual-authentication
|
342
334
|
# with the server
|
343
335
|
|
@@ -497,8 +489,12 @@ class Chef
|
|
497
489
|
|
498
490
|
default :fatal_windows_admin_check, false
|
499
491
|
else
|
500
|
-
|
501
|
-
|
492
|
+
# user/group cannot start with '-', '+' or '~'
|
493
|
+
# user/group cannot contain ':', ',' or non-space-whitespace or null byte
|
494
|
+
# everything else is allowed (UTF-8, spaces, etc) and we delegate to your O/S useradd program to barf or not
|
495
|
+
# copies: http://anonscm.debian.org/viewvc/pkg-shadow/debian/trunk/debian/patches/506_relaxed_usernames?view=markup
|
496
|
+
default :user_valid_regex, [ /^[^-+~:,\t\r\n\f\0]+[^:,\t\r\n\f\0]*$/ ]
|
497
|
+
default :group_valid_regex, [ /^[^-+~:,\t\r\n\f\0]+[^:,\t\r\n\f\0]*$/ ]
|
502
498
|
end
|
503
499
|
|
504
500
|
# returns a platform specific path to the user home dir
|
data/lib/chef/data_bag.rb
CHANGED
data/lib/chef/data_bag_item.rb
CHANGED
data/lib/chef/exceptions.rb
CHANGED
@@ -297,5 +297,13 @@ class Chef
|
|
297
297
|
# non-GET and non-HEAD request will thus raise an InvalidRedirect.
|
298
298
|
class InvalidRedirect < StandardError; end
|
299
299
|
|
300
|
+
# Raised when the content length of a download does not match the content
|
301
|
+
# length declared in the http response.
|
302
|
+
class ContentLengthMismatch < RuntimeError
|
303
|
+
def initialize(response_length, content_length)
|
304
|
+
super "Response body length #{response_length} does not match HTTP Content-Length header #{content_length}."
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
300
308
|
end
|
301
309
|
end
|
data/lib/chef/formatters/doc.rb
CHANGED
@@ -230,6 +230,21 @@ class Chef
|
|
230
230
|
@output.color("\n * Whyrun not supported for #{resource}, bypassing load.", :yellow)
|
231
231
|
end
|
232
232
|
|
233
|
+
# Called before handlers run
|
234
|
+
def handlers_start(handler_count)
|
235
|
+
puts "\nRunning handlers:"
|
236
|
+
end
|
237
|
+
|
238
|
+
# Called after an individual handler has run
|
239
|
+
def handler_executed(handler)
|
240
|
+
puts " - #{handler.class.name}"
|
241
|
+
end
|
242
|
+
|
243
|
+
# Called after all handlers have executed
|
244
|
+
def handlers_completed
|
245
|
+
puts "Running handlers complete\n"
|
246
|
+
end
|
247
|
+
|
233
248
|
# Called when a provider makes an assumption after a failed assertion
|
234
249
|
# in whyrun mode, in order to allow execution to continue
|
235
250
|
def whyrun_assumption(action, resource, message)
|
@@ -52,7 +52,8 @@ chef_server_url "#{server_url}"
|
|
52
52
|
node_name "#{username}"
|
53
53
|
client_key "#{api_key}"
|
54
54
|
|
55
|
-
If these settings are correct, your client_key may be invalid
|
55
|
+
If these settings are correct, your client_key may be invalid, or
|
56
|
+
you may have a chef user with the same client name as this node.
|
56
57
|
E
|
57
58
|
end
|
58
59
|
end
|
data/lib/chef/http.rb
CHANGED
@@ -165,18 +165,22 @@ class Chef
|
|
165
165
|
response, rest_request, return_value = send_http_request(method, url, headers, data) do |http_response|
|
166
166
|
if http_response.kind_of?(Net::HTTPSuccess)
|
167
167
|
tempfile = stream_to_tempfile(url, http_response)
|
168
|
-
if block_given?
|
169
|
-
begin
|
170
|
-
yield tempfile
|
171
|
-
ensure
|
172
|
-
tempfile && tempfile.close!
|
173
|
-
end
|
174
|
-
end
|
175
168
|
end
|
169
|
+
apply_stream_complete_middleware(http_response, rest_request, return_value)
|
176
170
|
end
|
177
|
-
|
171
|
+
|
172
|
+
return nil if response.kind_of?(Net::HTTPRedirection)
|
173
|
+
unless response.kind_of?(Net::HTTPSuccess)
|
178
174
|
response.error!
|
179
175
|
end
|
176
|
+
|
177
|
+
if block_given?
|
178
|
+
begin
|
179
|
+
yield tempfile
|
180
|
+
ensure
|
181
|
+
tempfile && tempfile.close!
|
182
|
+
end
|
183
|
+
end
|
180
184
|
tempfile
|
181
185
|
rescue Exception => e
|
182
186
|
log_failed_request(response, return_value) unless response.nil?
|
@@ -216,6 +220,12 @@ class Chef
|
|
216
220
|
end
|
217
221
|
end
|
218
222
|
|
223
|
+
def apply_stream_complete_middleware(response, rest_request, return_value)
|
224
|
+
middlewares.reverse.inject([response, rest_request, return_value]) do |res_data, middleware|
|
225
|
+
middleware.handle_stream_complete(*res_data)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
219
229
|
def log_failed_request(response, return_value)
|
220
230
|
return_value ||= {}
|
221
231
|
error_message = "HTTP Request Returned #{response.code} #{response.message}: "
|
@@ -69,6 +69,10 @@ class Chef
|
|
69
69
|
[http_response, rest_request, return_value]
|
70
70
|
end
|
71
71
|
|
72
|
+
def handle_stream_complete(http_response, rest_request, return_value)
|
73
|
+
[http_response, rest_request, return_value]
|
74
|
+
end
|
75
|
+
|
72
76
|
def decompress_body(response)
|
73
77
|
if gzip_disabled? || response.body.nil?
|
74
78
|
response.body
|
data/lib/chef/http/json_input.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Lamont Granquist (<lamont@getchef.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 Chef Software, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'pp'
|
20
|
+
require 'chef/log'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class HTTP
|
24
|
+
|
25
|
+
# Middleware that validates the Content-Length header against the downloaded number of bytes.
|
26
|
+
#
|
27
|
+
# This must run before the decompressor middleware, since otherwise we will count the uncompressed
|
28
|
+
# streamed bytes, rather than the on-the-wire compressed bytes.
|
29
|
+
class ValidateContentLength
|
30
|
+
|
31
|
+
class ContentLengthCounter
|
32
|
+
attr_accessor :content_length
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@content_length = 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_chunk(chunk)
|
39
|
+
@content_length += chunk.bytesize
|
40
|
+
chunk
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(opts={})
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_request(method, url, headers={}, data=false)
|
48
|
+
[method, url, headers, data]
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_response(http_response, rest_request, return_value)
|
52
|
+
unless http_response['content-length']
|
53
|
+
Chef::Log.debug("HTTP server did not include a Content-Length header in response, cannot identify truncated downloads.")
|
54
|
+
return [http_response, rest_request, return_value]
|
55
|
+
end
|
56
|
+
validate(response_content_length(http_response), http_response.body.bytesize)
|
57
|
+
return [http_response, rest_request, return_value]
|
58
|
+
end
|
59
|
+
|
60
|
+
def handle_stream_complete(http_response, rest_request, return_value)
|
61
|
+
if http_response['content-length'].nil?
|
62
|
+
Chef::Log.debug("HTTP server did not include a Content-Length header in response, cannot idenfity streamed download.")
|
63
|
+
elsif @content_length_counter.nil?
|
64
|
+
Chef::Log.debug("No content-length information collected for the streamed download, cannot identify streamed download.")
|
65
|
+
else
|
66
|
+
validate(response_content_length(http_response), @content_length_counter.content_length)
|
67
|
+
end
|
68
|
+
return [http_response, rest_request, return_value]
|
69
|
+
end
|
70
|
+
|
71
|
+
def stream_response_handler(response)
|
72
|
+
@content_length_counter = ContentLengthCounter.new
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def response_content_length(response)
|
77
|
+
if response['content-length'].is_a?(Array)
|
78
|
+
response['content-length'].first.to_i
|
79
|
+
else
|
80
|
+
response['content-length'].to_i
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate(content_length, response_length)
|
85
|
+
Chef::Log.debug "Content-Length header = #{content_length}"
|
86
|
+
Chef::Log.debug "Response body length = #{response_length}"
|
87
|
+
if response_length != content_length
|
88
|
+
raise Chef::Exceptions::ContentLengthMismatch.new(response_length, content_length)
|
89
|
+
end
|
90
|
+
true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/chef/knife.rb
CHANGED
data/lib/chef/knife/configure.rb
CHANGED
@@ -35,29 +35,29 @@ class Chef
|
|
35
35
|
option :repository,
|
36
36
|
:short => "-r REPO",
|
37
37
|
:long => "--repository REPO",
|
38
|
-
:description => "The path to
|
38
|
+
:description => "The path to the chef-repo"
|
39
39
|
|
40
40
|
option :initial,
|
41
41
|
:short => "-i",
|
42
42
|
:long => "--initial",
|
43
43
|
:boolean => true,
|
44
|
-
:description => "
|
44
|
+
:description => "Use to create a API client, typically an administrator client on a freshly-installed server"
|
45
45
|
|
46
46
|
option :admin_client_name,
|
47
47
|
:long => "--admin-client-name NAME",
|
48
|
-
:description => "The
|
48
|
+
:description => "The name of the client, typically the name of the admin client"
|
49
49
|
|
50
50
|
option :admin_client_key,
|
51
51
|
:long => "--admin-client-key PATH",
|
52
|
-
:description => "The path to the
|
52
|
+
:description => "The path to the private key used by the client, typically a file named admin.pem"
|
53
53
|
|
54
54
|
option :validation_client_name,
|
55
55
|
:long => "--validation-client-name NAME",
|
56
|
-
:description => "The validation
|
56
|
+
:description => "The name of the validation client, typically a client named chef-validator"
|
57
57
|
|
58
58
|
option :validation_key,
|
59
59
|
:long => "--validation-key PATH",
|
60
|
-
:description => "The
|
60
|
+
:description => "The path to the validation key used by the client, typically a file named validation.pem"
|
61
61
|
|
62
62
|
def configure_chef
|
63
63
|
# We are just faking out the system so that you can do this without a key specified
|
@@ -290,7 +290,7 @@ e.g.
|
|
290
290
|
|
291
291
|
Attributes
|
292
292
|
----------
|
293
|
-
TODO: List
|
293
|
+
TODO: List your cookbook attributes here.
|
294
294
|
|
295
295
|
e.g.
|
296
296
|
#### #{cookbook_name}::default
|
@@ -358,7 +358,7 @@ Requirements
|
|
358
358
|
toaster #{cookbook_name} needs toaster to brown your bagel.
|
359
359
|
|
360
360
|
Attributes
|
361
|
-
TODO: List
|
361
|
+
TODO: List your cookbook attributes here.
|
362
362
|
|
363
363
|
#{cookbook_name}
|
364
364
|
Key Type Description Default
|
@@ -60,9 +60,13 @@ class Chef
|
|
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
|
-
|
64
|
-
|
65
|
-
|
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 @@ class Chef
|
|
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 @@ class Chef
|
|
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)
|