chef 12.2.1-x86-mingw32 → 12.3.0.rc.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/win32-eventlog/Rakefile +10 -6
- data/lib/chef.rb +1 -0
- data/lib/chef/application/apply.rb +5 -0
- data/lib/chef/application/client.rb +10 -0
- data/lib/chef/application/knife.rb +5 -1
- data/lib/chef/application/solo.rb +5 -0
- data/lib/chef/chef_class.rb +130 -0
- data/lib/chef/client.rb +15 -7
- data/lib/chef/config.rb +13 -0
- data/lib/chef/event_loggers/windows_eventlog.rb +11 -5
- data/lib/chef/http.rb +13 -3
- data/lib/chef/http/basic_client.rb +21 -4
- data/lib/chef/http/socketless_chef_zero_client.rb +207 -0
- data/lib/chef/knife.rb +3 -0
- data/lib/chef/knife/bootstrap.rb +1 -1
- data/lib/chef/knife/core/status_presenter.rb +12 -11
- data/lib/chef/knife/ssh.rb +3 -1
- data/lib/chef/knife/status.rb +32 -7
- data/lib/chef/local_mode.rb +13 -3
- data/lib/chef/mixin/provides.rb +32 -0
- data/lib/chef/platform/provider_priority_map.rb +16 -7
- data/lib/chef/platform/resource_priority_map.rb +37 -0
- data/lib/chef/policy_builder/expand_node_object.rb +14 -0
- data/lib/chef/policy_builder/policyfile.rb +0 -1
- data/lib/chef/provider.rb +5 -20
- data/lib/chef/provider/package/rubygems.rb +4 -1
- data/lib/chef/provider/service/macosx.rb +66 -30
- data/lib/chef/provider_resolver.rb +10 -5
- data/lib/chef/resource.rb +5 -39
- data/lib/chef/resource/gem_package.rb +5 -0
- data/lib/chef/resource/link.rb +1 -1
- data/lib/chef/resource/macosx_service.rb +59 -0
- data/lib/chef/resource/remote_file.rb +0 -4
- data/lib/chef/resource_resolver.rb +101 -0
- data/lib/chef/rest.rb +4 -5
- data/lib/chef/search/query.rb +1 -1
- data/lib/chef/server_api.rb +1 -0
- data/lib/chef/version.rb +1 -1
- data/spec/data/lwrp/providers/buck_passer.rb +2 -1
- data/spec/data/lwrp/resources/bar.rb +1 -1
- data/spec/data/{big_json.json → nested.json} +2 -2
- data/spec/functional/event_loggers/windows_eventlog_spec.rb +14 -0
- data/spec/functional/resource/execute_spec.rb +1 -1
- data/spec/integration/client/client_spec.rb +12 -1
- data/spec/integration/client/ipv6_spec.rb +1 -1
- data/spec/integration/knife/common_options_spec.rb +3 -3
- data/spec/integration/recipes/lwrp_inline_resources_spec.rb +1 -1
- data/spec/integration/solo/solo_spec.rb +7 -5
- data/spec/unit/application/client_spec.rb +10 -0
- data/spec/unit/chef_class_spec.rb +91 -0
- data/spec/unit/client_spec.rb +13 -0
- data/spec/unit/http/basic_client_spec.rb +43 -6
- data/spec/unit/http/socketless_chef_zero_client_spec.rb +174 -0
- data/spec/unit/http_spec.rb +14 -0
- data/spec/unit/json_compat_spec.rb +7 -20
- data/spec/unit/knife/ssh_spec.rb +18 -0
- data/spec/unit/knife/status_spec.rb +69 -3
- data/spec/unit/knife_spec.rb +5 -0
- data/spec/unit/provider/package/rubygems_spec.rb +19 -0
- data/spec/unit/provider/service/macosx_spec.rb +230 -203
- data/spec/unit/provider_resolver_spec.rb +1 -0
- data/spec/unit/recipe_spec.rb +48 -0
- data/spec/unit/resource/link_spec.rb +15 -0
- data/spec/unit/resource_spec.rb +6 -6
- data/spec/unit/rest_spec.rb +9 -0
- data/spec/unit/search/query_spec.rb +24 -0
- data/spec/unit/shell_spec.rb +3 -1
- metadata +16 -9
- data/spec/data/big_json_plus_one.json +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91f2fc1f5461db9f00c5bb861ba643c8ecba728e
|
4
|
+
data.tar.gz: f520f5bbb0057bec905346f923dc3f6cabab4780
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5fdc2cbedacc39566ce05e9b4b448f992d7766eda5f5585d075437987db7058a675147d689a624c1b8f50416740c21643393713ce1fc06ebef0e1ca177969083
|
7
|
+
data.tar.gz: 010f4fae462cdeaf79d1bbbbd82bd7d01d19af19af6880b1e8d607ed8aae8bd44d6fa1ea9bfd99dd9a41a052ce1c05c4c7aa2dbaab55035925d3affdd807c0f4
|
data/ext/win32-eventlog/Rakefile
CHANGED
@@ -41,10 +41,14 @@ end
|
|
41
41
|
task :register => EVT_SHARED_OBJECT do
|
42
42
|
require 'win32/eventlog'
|
43
43
|
dll_file = File.expand_path(EVT_SHARED_OBJECT)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
44
|
+
begin
|
45
|
+
Win32::EventLog.add_event_source(
|
46
|
+
:source => "Application",
|
47
|
+
:key_name => "Chef",
|
48
|
+
:event_message_file => dll_file,
|
49
|
+
:category_message_file => dll_file
|
50
|
+
)
|
51
|
+
rescue Errno::EIO => e
|
52
|
+
puts "Skipping event log registration due to missing privileges: #{e}"
|
53
|
+
end
|
50
54
|
end
|
data/lib/chef.rb
CHANGED
@@ -85,6 +85,11 @@ class Chef::Application::Apply < Chef::Application
|
|
85
85
|
:default => !Chef::Platform.windows?,
|
86
86
|
:description => "Use colored output, defaults to enabled"
|
87
87
|
|
88
|
+
option :minimal_ohai,
|
89
|
+
:long => "--minimal-ohai",
|
90
|
+
:description => "Only run the bare minimum ohai plugins chef needs to function",
|
91
|
+
:boolean => true
|
92
|
+
|
88
93
|
attr_reader :json_attribs
|
89
94
|
|
90
95
|
def initialize
|
@@ -253,6 +253,16 @@ class Chef::Application::Client < Chef::Application
|
|
253
253
|
:description => "Enable audit-mode with `enabled`. Disable audit-mode with `disabled`. Skip converge and only perform audits with `audit-only`",
|
254
254
|
:proc => lambda { |mo| mo.gsub("-", "_").to_sym }
|
255
255
|
|
256
|
+
option :minimal_ohai,
|
257
|
+
:long => "--minimal-ohai",
|
258
|
+
:description => "Only run the bare minimum ohai plugins chef needs to function",
|
259
|
+
:boolean => true
|
260
|
+
|
261
|
+
option :listen,
|
262
|
+
:long => "--[no-]listen",
|
263
|
+
:description => "Whether a local mode (-z) server binds to a port",
|
264
|
+
:boolean => true
|
265
|
+
|
256
266
|
IMMEDIATE_RUN_SIGNAL = "1".freeze
|
257
267
|
|
258
268
|
attr_reader :chef_client_json
|
@@ -121,6 +121,11 @@ class Chef::Application::Knife < Chef::Application
|
|
121
121
|
:long => "--chef-zero-port PORT",
|
122
122
|
:description => "Port (or port range) to start chef-zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works."
|
123
123
|
|
124
|
+
option :listen,
|
125
|
+
:long => "--[no-]listen",
|
126
|
+
:description => "Whether a local mode (-z) server binds to a port",
|
127
|
+
:boolean => true
|
128
|
+
|
124
129
|
option :version,
|
125
130
|
:short => "-v",
|
126
131
|
:long => "--version",
|
@@ -129,7 +134,6 @@ class Chef::Application::Knife < Chef::Application
|
|
129
134
|
:proc => lambda {|v| puts "Chef: #{::Chef::VERSION}"},
|
130
135
|
:exit => 0
|
131
136
|
|
132
|
-
|
133
137
|
# Run knife
|
134
138
|
def run
|
135
139
|
Mixlib::Log::Formatter.show_time = false
|
@@ -180,6 +180,11 @@ class Chef::Application::Solo < Chef::Application
|
|
180
180
|
:description => "Set maximum duration to wait for another client run to finish, default is indefinitely.",
|
181
181
|
:proc => lambda { |s| s.to_i }
|
182
182
|
|
183
|
+
option :minimal_ohai,
|
184
|
+
:long => "--minimal-ohai",
|
185
|
+
:description => "Only run the bare minimum ohai plugins chef needs to function",
|
186
|
+
:boolean => true
|
187
|
+
|
183
188
|
attr_reader :chef_client_json
|
184
189
|
|
185
190
|
def initialize
|
@@ -0,0 +1,130 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Lamont Granquist (<lamont@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
# NOTE: This class is not intended for internal use by the chef-client code. Classes in
|
19
|
+
# chef-client should still have objects like the node and run_context injected into them
|
20
|
+
# via their initializers. This class is still global state and will complicate writing
|
21
|
+
# unit tests for internal Chef objects. It is intended to be used only by recipe code.
|
22
|
+
|
23
|
+
# NOTE: When adding require lines here you are creating tight coupling on a global that may be
|
24
|
+
# included in many different situations and ultimately that ends in tears with circular requires.
|
25
|
+
# Note the way that the run_context, provider_priority_map and resource_priority_map are "dependency
|
26
|
+
# injected" into this class by other objects and do not reference the class symbols in those files
|
27
|
+
# directly and we do not need to require those files here.
|
28
|
+
|
29
|
+
class Chef
|
30
|
+
class << self
|
31
|
+
|
32
|
+
#
|
33
|
+
# Public API
|
34
|
+
#
|
35
|
+
|
36
|
+
# Get the node object
|
37
|
+
#
|
38
|
+
# @return [Chef::Node] node object of the chef-client run
|
39
|
+
attr_reader :node
|
40
|
+
|
41
|
+
# Get the run context
|
42
|
+
#
|
43
|
+
# @return [Chef::RunContext] run_context of the chef-client run
|
44
|
+
attr_reader :run_context
|
45
|
+
|
46
|
+
# Get the array of providers associated with a resource_name for the current node
|
47
|
+
#
|
48
|
+
# @param resource_name [Symbol] name of the resource as a symbol
|
49
|
+
# @return [Array<Class>] Priority Array of Provider Classes to use for the resource_name on the node
|
50
|
+
def get_provider_priority_array(resource_name)
|
51
|
+
@provider_priority_map.get_priority_array(node, resource_name).dup
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get the array of resources associated with a resource_name for the current node
|
55
|
+
#
|
56
|
+
# @param resource_name [Symbol] name of the resource as a symbol
|
57
|
+
# @return [Array<Class>] Priority Array of Resource Classes to use for the resource_name on the node
|
58
|
+
def get_resource_priority_array(resource_name)
|
59
|
+
@resource_priority_map.get_priority_array(node, resource_name).dup
|
60
|
+
end
|
61
|
+
|
62
|
+
# Set the array of providers associated with a resource_name for the current node
|
63
|
+
#
|
64
|
+
# @param resource_name [Symbol] name of the resource as a symbol
|
65
|
+
# @param priority_array [Array<Class>] Array of Classes to set as the priority for resource_name on the node
|
66
|
+
# @param filter [Hash] Chef::Nodearray-style filter
|
67
|
+
# @return [Array<Class>] Modified Priority Array of Provider Classes to use for the resource_name on the node
|
68
|
+
def set_provider_priority_array(resource_name, priority_array, *filter)
|
69
|
+
@provider_priority_map.set_priority_array(resource_name, priority_array, *filter).dup
|
70
|
+
end
|
71
|
+
|
72
|
+
# Get the array of resources associated with a resource_name for the current node
|
73
|
+
#
|
74
|
+
# @param resource_name [Symbol] name of the resource as a symbol
|
75
|
+
# @param priority_array [Array<Class>] Array of Classes to set as the priority for resource_name on the node
|
76
|
+
# @param filter [Hash] Chef::Nodearray-style filter
|
77
|
+
# @return [Array<Class>] Modified Priority Array of Resource Classes to use for the resource_name on the node
|
78
|
+
def set_resource_priority_array(resource_name, priority_array, *filter)
|
79
|
+
@resource_priority_map.set_priority_array(resource_name, priority_array, *filter).dup
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Dependency Injection API (Private not Public)
|
84
|
+
# [ in the ruby sense these have to be public methods, but they are
|
85
|
+
# *NOT* for public consumption ]
|
86
|
+
#
|
87
|
+
|
88
|
+
# Sets the resource_priority_map
|
89
|
+
#
|
90
|
+
# @api private
|
91
|
+
# @param resource_priority_map [Chef::Platform::ResourcePriorityMap]
|
92
|
+
def set_resource_priority_map(resource_priority_map)
|
93
|
+
@resource_priority_map = resource_priority_map
|
94
|
+
end
|
95
|
+
|
96
|
+
# Sets the provider_priority_map
|
97
|
+
#
|
98
|
+
# @api private
|
99
|
+
# @param provider_priority_map [Chef::Platform::providerPriorityMap]
|
100
|
+
def set_provider_priority_map(provider_priority_map)
|
101
|
+
@provider_priority_map = provider_priority_map
|
102
|
+
end
|
103
|
+
|
104
|
+
# Sets the node object
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
# @param node [Chef::Node]
|
108
|
+
def set_node(node)
|
109
|
+
@node = node
|
110
|
+
end
|
111
|
+
|
112
|
+
# Sets the run_context object
|
113
|
+
#
|
114
|
+
# @api private
|
115
|
+
# @param run_context [Chef::RunContext]
|
116
|
+
def set_run_context(run_context)
|
117
|
+
@run_context = run_context
|
118
|
+
end
|
119
|
+
|
120
|
+
# Resets the internal state
|
121
|
+
#
|
122
|
+
# @api private
|
123
|
+
def reset!
|
124
|
+
@run_context = nil
|
125
|
+
@node = nil
|
126
|
+
@provider_priority_map = nil
|
127
|
+
@resource_priority_map = nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/lib/chef/client.rb
CHANGED
@@ -166,6 +166,13 @@ class Chef
|
|
166
166
|
if new_runlist = args.delete(:runlist)
|
167
167
|
@json_attribs["run_list"] = new_runlist
|
168
168
|
end
|
169
|
+
|
170
|
+
# these slurp in the resource+provider world, so be exceedingly lazy about requiring them
|
171
|
+
require 'chef/platform/provider_priority_map' unless defined? Chef::Platform::ProviderPriorityMap
|
172
|
+
require 'chef/platform/resource_priority_map' unless defined? Chef::Platform::ResourcePriorityMap
|
173
|
+
|
174
|
+
Chef.set_provider_priority_map(Chef::Platform::ProviderPriorityMap.instance)
|
175
|
+
Chef.set_resource_priority_map(Chef::Platform::ResourcePriorityMap.instance)
|
169
176
|
end
|
170
177
|
|
171
178
|
def configure_formatters
|
@@ -224,21 +231,21 @@ class Chef
|
|
224
231
|
end
|
225
232
|
|
226
233
|
# Instantiates a Chef::Node object, possibly loading the node's prior state
|
227
|
-
# when using chef-client. Delegates to policy_builder
|
228
|
-
#
|
234
|
+
# when using chef-client. Delegates to policy_builder. Injects the built node
|
235
|
+
# into the Chef class.
|
229
236
|
#
|
230
|
-
#
|
231
|
-
# Chef::Node:: The node object for this chef run
|
237
|
+
# @return [Chef::Node] The node object for this Chef run
|
232
238
|
def load_node
|
233
239
|
policy_builder.load_node
|
234
240
|
@node = policy_builder.node
|
241
|
+
Chef.set_node(@node)
|
242
|
+
node
|
235
243
|
end
|
236
244
|
|
237
245
|
# Mutates the `node` object to prepare it for the chef run. Delegates to
|
238
246
|
# policy_builder
|
239
247
|
#
|
240
|
-
#
|
241
|
-
# Chef::Node:: The updated node object
|
248
|
+
# @return [Chef::Node] The updated node object
|
242
249
|
def build_node
|
243
250
|
policy_builder.build_node
|
244
251
|
@run_status = Chef::RunStatus.new(node, events)
|
@@ -272,7 +279,8 @@ class Chef
|
|
272
279
|
end
|
273
280
|
|
274
281
|
def run_ohai
|
275
|
-
|
282
|
+
filter = Chef::Config[:minimal_ohai] ? %w[fqdn machinename hostname platform platform_version os os_version] : nil
|
283
|
+
ohai.all_plugins(filter)
|
276
284
|
@events.ohai_completed(node)
|
277
285
|
end
|
278
286
|
|
data/lib/chef/config.rb
CHANGED
@@ -305,6 +305,14 @@ class Chef
|
|
305
305
|
|
306
306
|
default :pid_file, nil
|
307
307
|
|
308
|
+
# Whether Chef Zero local mode should bind to a port. All internal requests
|
309
|
+
# will go through the socketless code path regardless, so the socket is
|
310
|
+
# only needed if other processes will connect to the local mode server.
|
311
|
+
#
|
312
|
+
# For compatibility this is set to true but it will be changed to false in
|
313
|
+
# the future.
|
314
|
+
default :listen, true
|
315
|
+
|
308
316
|
config_context :chef_zero do
|
309
317
|
config_strict_mode true
|
310
318
|
default(:enabled) { Chef::Config.local_mode }
|
@@ -333,6 +341,11 @@ class Chef
|
|
333
341
|
# This can be removed when audit-mode is enabled by default.
|
334
342
|
default :audit_mode, :disabled
|
335
343
|
|
344
|
+
# Chef only needs ohai to run the hostname plugin for the most basic
|
345
|
+
# functionality. If the rest of the ohai plugins are not needed (like in
|
346
|
+
# most of our testing scenarios)
|
347
|
+
default :minimal_ohai, false
|
348
|
+
|
336
349
|
# Policyfile is an experimental feature where a node gets its run list and
|
337
350
|
# cookbook version set from a single document on the server instead of
|
338
351
|
# expanding the run list and having the server compute the cookbook version
|
@@ -88,15 +88,21 @@ class Chef
|
|
88
88
|
#Exception message: %4
|
89
89
|
#Exception backtrace: %5
|
90
90
|
def run_failed(e)
|
91
|
+
data =
|
92
|
+
if @run_status
|
93
|
+
[@run_status.run_id,
|
94
|
+
@run_status.elapsed_time.to_s]
|
95
|
+
else
|
96
|
+
["UNKNOWN", "UNKNOWN"]
|
97
|
+
end
|
98
|
+
|
91
99
|
@eventlog.report_event(
|
92
100
|
:event_type => ::Win32::EventLog::ERROR_TYPE,
|
93
101
|
:source => SOURCE,
|
94
102
|
:event_id => RUN_FAILED_EVENT_ID,
|
95
|
-
:data => [
|
96
|
-
|
97
|
-
|
98
|
-
e.message,
|
99
|
-
e.backtrace.join("\n")]
|
103
|
+
:data => data + [e.class.name,
|
104
|
+
e.message,
|
105
|
+
e.backtrace.join("\n")]
|
100
106
|
)
|
101
107
|
end
|
102
108
|
|
data/lib/chef/http.rb
CHANGED
@@ -25,6 +25,7 @@ require 'tempfile'
|
|
25
25
|
require 'net/https'
|
26
26
|
require 'uri'
|
27
27
|
require 'chef/http/basic_client'
|
28
|
+
require 'chef/http/socketless_chef_zero_client'
|
28
29
|
require 'chef/monkey_patches/net_http'
|
29
30
|
require 'chef/config'
|
30
31
|
require 'chef/platform/query_helpers'
|
@@ -196,14 +197,18 @@ class Chef
|
|
196
197
|
|
197
198
|
def http_client(base_url=nil)
|
198
199
|
base_url ||= url
|
199
|
-
|
200
|
+
if chef_zero_uri?(base_url)
|
201
|
+
SocketlessChefZeroClient.new(base_url)
|
202
|
+
else
|
203
|
+
BasicClient.new(base_url, :ssl_policy => Chef::HTTP::APISSLPolicy)
|
204
|
+
end
|
200
205
|
end
|
201
206
|
|
202
207
|
protected
|
203
208
|
|
204
209
|
def create_url(path)
|
205
210
|
return path if path.is_a?(URI)
|
206
|
-
if path =~ /^(http|https):\/\//i
|
211
|
+
if path =~ /^(http|https|chefzero):\/\//i
|
207
212
|
URI.parse(path)
|
208
213
|
elsif path.nil? or path.empty?
|
209
214
|
URI.parse(@url)
|
@@ -292,7 +297,7 @@ class Chef
|
|
292
297
|
http_attempts += 1
|
293
298
|
response, request, return_value = yield
|
294
299
|
# handle HTTP 50X Error
|
295
|
-
if response.kind_of?(Net::HTTPServerError)
|
300
|
+
if response.kind_of?(Net::HTTPServerError) && !Chef::Config.local_mode
|
296
301
|
if http_retry_count - http_attempts + 1 > 0
|
297
302
|
sleep_time = 1 + (2 ** http_attempts) + rand(2 ** http_attempts)
|
298
303
|
Chef::Log.error("Server returned error #{response.code} for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s")
|
@@ -351,6 +356,11 @@ class Chef
|
|
351
356
|
|
352
357
|
private
|
353
358
|
|
359
|
+
def chef_zero_uri?(uri)
|
360
|
+
uri = URI.parse(uri) unless uri.respond_to?(:scheme)
|
361
|
+
uri.scheme == "chefzero"
|
362
|
+
end
|
363
|
+
|
354
364
|
def redirected_to(response)
|
355
365
|
return nil unless response.kind_of?(Net::HTTPRedirection)
|
356
366
|
# Net::HTTPNotModified is undesired subclass of Net::HTTPRedirection so test for this
|
@@ -97,7 +97,9 @@ class Chef
|
|
97
97
|
|
98
98
|
#adapted from buildr/lib/buildr/core/transports.rb
|
99
99
|
def proxy_uri
|
100
|
-
proxy = Chef::Config["#{url.scheme}_proxy"]
|
100
|
+
proxy = Chef::Config["#{url.scheme}_proxy"] ||
|
101
|
+
env["#{url.scheme.upcase}_PROXY"] || env["#{url.scheme}_proxy"]
|
102
|
+
|
101
103
|
# Check if the proxy string contains a scheme. If not, add the url's scheme to the
|
102
104
|
# proxy before parsing. The regex /^.*:\/\// matches, for example, http://.
|
103
105
|
proxy = if proxy.match(/^.*:\/\//)
|
@@ -105,7 +107,8 @@ class Chef
|
|
105
107
|
else
|
106
108
|
URI.parse("#{url.scheme}://#{proxy}")
|
107
109
|
end if String === proxy
|
108
|
-
|
110
|
+
no_proxy = Chef::Config[:no_proxy] || env['NO_PROXY'] || env['no_proxy']
|
111
|
+
excludes = no_proxy.to_s.split(/\s*,\s*/).compact
|
109
112
|
excludes = excludes.map { |exclude| exclude =~ /:\d+$/ ? exclude : "#{exclude}:*" }
|
110
113
|
return proxy unless excludes.any? { |exclude| File.fnmatch(exclude, "#{host}:#{port}") }
|
111
114
|
end
|
@@ -126,18 +129,32 @@ class Chef
|
|
126
129
|
Chef::Config
|
127
130
|
end
|
128
131
|
|
132
|
+
def env
|
133
|
+
ENV
|
134
|
+
end
|
135
|
+
|
129
136
|
def http_client_builder
|
130
137
|
http_proxy = proxy_uri
|
131
138
|
if http_proxy.nil?
|
132
139
|
Net::HTTP
|
133
140
|
else
|
134
141
|
Chef::Log.debug("Using #{http_proxy.host}:#{http_proxy.port} for proxy")
|
135
|
-
user =
|
136
|
-
pass =
|
142
|
+
user = http_proxy_user(http_proxy)
|
143
|
+
pass = http_proxy_pass(http_proxy)
|
137
144
|
Net::HTTP.Proxy(http_proxy.host, http_proxy.port, user, pass)
|
138
145
|
end
|
139
146
|
end
|
140
147
|
|
148
|
+
def http_proxy_user(http_proxy)
|
149
|
+
http_proxy.user || Chef::Config["#{url.scheme}_proxy_user"] ||
|
150
|
+
env["#{url.scheme.upcase}_PROXY_USER"] || env["#{url.scheme}_proxy_user"]
|
151
|
+
end
|
152
|
+
|
153
|
+
def http_proxy_pass(http_proxy)
|
154
|
+
http_proxy.password || Chef::Config["#{url.scheme}_proxy_pass"] ||
|
155
|
+
env["#{url.scheme.upcase}_PROXY_PASS"] || env["#{url.scheme}_proxy_pass"]
|
156
|
+
end
|
157
|
+
|
141
158
|
def configure_ssl(http_client)
|
142
159
|
http_client.use_ssl = true
|
143
160
|
ssl_policy.apply_to(http_client)
|
@@ -0,0 +1,207 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Daniel DeLeo (<dan@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
# Some portions of the code in this file are verbatim copies of code from the
|
20
|
+
# fakeweb project: https://github.com/chrisk/fakeweb
|
21
|
+
#
|
22
|
+
# fakeweb is distributed under the MIT license, which is copied below:
|
23
|
+
# ---
|
24
|
+
#
|
25
|
+
# Copyright 2006-2010 Blaine Cook, Chris Kampmeier, and other contributors
|
26
|
+
#
|
27
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
28
|
+
# a copy of this software and associated documentation files (the
|
29
|
+
# "Software"), to deal in the Software without restriction, including
|
30
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
31
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
32
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
33
|
+
# the following conditions:
|
34
|
+
|
35
|
+
# The above copyright notice and this permission notice shall be
|
36
|
+
# included in all copies or substantial portions of the Software.
|
37
|
+
|
38
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
39
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
40
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
41
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
42
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
43
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
44
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
45
|
+
|
46
|
+
require 'chef_zero/server'
|
47
|
+
|
48
|
+
class Chef
|
49
|
+
class HTTP
|
50
|
+
|
51
|
+
# HTTP Client class that talks directly to Zero via the Rack interface.
|
52
|
+
class SocketlessChefZeroClient
|
53
|
+
|
54
|
+
# This module is extended into Net::HTTP Response objects created from
|
55
|
+
# Socketless Chef Zero responses.
|
56
|
+
module ResponseExts
|
57
|
+
|
58
|
+
# Net::HTTP raises an error if #read_body is called with a block or
|
59
|
+
# file argument after the body has already been read from the network.
|
60
|
+
#
|
61
|
+
# Since we always set the body to the string response from Chef Zero
|
62
|
+
# and set the `@read` indicator variable, we have to patch this method
|
63
|
+
# or else streaming-style responses won't work.
|
64
|
+
def read_body(dest = nil, &block)
|
65
|
+
if dest
|
66
|
+
raise "responses from socketless chef zero can't be written to specific destination"
|
67
|
+
end
|
68
|
+
|
69
|
+
if block_given?
|
70
|
+
block.call(@body)
|
71
|
+
else
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
attr_reader :url
|
79
|
+
|
80
|
+
# copied verbatim from webrick (2-clause BSD License)
|
81
|
+
#
|
82
|
+
# HTTP status codes and descriptions
|
83
|
+
STATUS_MESSAGE = {
|
84
|
+
100 => 'Continue',
|
85
|
+
101 => 'Switching Protocols',
|
86
|
+
200 => 'OK',
|
87
|
+
201 => 'Created',
|
88
|
+
202 => 'Accepted',
|
89
|
+
203 => 'Non-Authoritative Information',
|
90
|
+
204 => 'No Content',
|
91
|
+
205 => 'Reset Content',
|
92
|
+
206 => 'Partial Content',
|
93
|
+
207 => 'Multi-Status',
|
94
|
+
300 => 'Multiple Choices',
|
95
|
+
301 => 'Moved Permanently',
|
96
|
+
302 => 'Found',
|
97
|
+
303 => 'See Other',
|
98
|
+
304 => 'Not Modified',
|
99
|
+
305 => 'Use Proxy',
|
100
|
+
307 => 'Temporary Redirect',
|
101
|
+
400 => 'Bad Request',
|
102
|
+
401 => 'Unauthorized',
|
103
|
+
402 => 'Payment Required',
|
104
|
+
403 => 'Forbidden',
|
105
|
+
404 => 'Not Found',
|
106
|
+
405 => 'Method Not Allowed',
|
107
|
+
406 => 'Not Acceptable',
|
108
|
+
407 => 'Proxy Authentication Required',
|
109
|
+
408 => 'Request Timeout',
|
110
|
+
409 => 'Conflict',
|
111
|
+
410 => 'Gone',
|
112
|
+
411 => 'Length Required',
|
113
|
+
412 => 'Precondition Failed',
|
114
|
+
413 => 'Request Entity Too Large',
|
115
|
+
414 => 'Request-URI Too Large',
|
116
|
+
415 => 'Unsupported Media Type',
|
117
|
+
416 => 'Request Range Not Satisfiable',
|
118
|
+
417 => 'Expectation Failed',
|
119
|
+
422 => 'Unprocessable Entity',
|
120
|
+
423 => 'Locked',
|
121
|
+
424 => 'Failed Dependency',
|
122
|
+
426 => 'Upgrade Required',
|
123
|
+
428 => 'Precondition Required',
|
124
|
+
429 => 'Too Many Requests',
|
125
|
+
431 => 'Request Header Fields Too Large',
|
126
|
+
500 => 'Internal Server Error',
|
127
|
+
501 => 'Not Implemented',
|
128
|
+
502 => 'Bad Gateway',
|
129
|
+
503 => 'Service Unavailable',
|
130
|
+
504 => 'Gateway Timeout',
|
131
|
+
505 => 'HTTP Version Not Supported',
|
132
|
+
507 => 'Insufficient Storage',
|
133
|
+
511 => 'Network Authentication Required',
|
134
|
+
}
|
135
|
+
|
136
|
+
STATUS_MESSAGE.values.each {|v| v.freeze }
|
137
|
+
STATUS_MESSAGE.freeze
|
138
|
+
|
139
|
+
def initialize(base_url)
|
140
|
+
@url = base_url
|
141
|
+
end
|
142
|
+
|
143
|
+
def host
|
144
|
+
@url.hostname
|
145
|
+
end
|
146
|
+
|
147
|
+
def port
|
148
|
+
@url.port
|
149
|
+
end
|
150
|
+
|
151
|
+
def request(method, url, body, headers, &handler_block)
|
152
|
+
request = req_to_rack(method, url, body, headers)
|
153
|
+
res = ChefZero::SocketlessServerMap.request(port, request)
|
154
|
+
|
155
|
+
net_http_response = to_net_http(res[0], res[1], res[2])
|
156
|
+
|
157
|
+
yield net_http_response if block_given?
|
158
|
+
|
159
|
+
[self, net_http_response]
|
160
|
+
end
|
161
|
+
|
162
|
+
def req_to_rack(method, url, body, headers)
|
163
|
+
body_str = body || ""
|
164
|
+
{
|
165
|
+
"SCRIPT_NAME" => "",
|
166
|
+
"SERVER_NAME" => "localhost",
|
167
|
+
"REQUEST_METHOD" => method.to_s.upcase,
|
168
|
+
"PATH_INFO" => url.path,
|
169
|
+
"QUERY_STRING" => url.query,
|
170
|
+
"SERVER_PORT" => url.port,
|
171
|
+
"HTTP_HOST" => "localhost:#{url.port}",
|
172
|
+
"rack.url_scheme" => "chefzero",
|
173
|
+
"rack.input" => StringIO.new(body_str),
|
174
|
+
}
|
175
|
+
end
|
176
|
+
|
177
|
+
def to_net_http(code, headers, chunked_body)
|
178
|
+
body = chunked_body.join('')
|
179
|
+
msg = STATUS_MESSAGE[code] or raise "Cannot determine HTTP status message for code #{code}"
|
180
|
+
response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
|
181
|
+
response.instance_variable_set(:@body, body)
|
182
|
+
headers.each do |name, value|
|
183
|
+
if value.respond_to?(:each)
|
184
|
+
value.each { |v| response.add_field(name, v) }
|
185
|
+
else
|
186
|
+
response[name] = value
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
response.instance_variable_set(:@read, true)
|
191
|
+
response.extend(ResponseExts)
|
192
|
+
response
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
|
197
|
+
def headers_extracted_from_options
|
198
|
+
options.reject {|name, _| KNOWN_OPTIONS.include?(name) }.map { |name, value|
|
199
|
+
[name.to_s.split("_").map { |segment| segment.capitalize }.join("-"), value]
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|