chef 11.16.2 → 11.16.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d77fa4692b75a7d21e00502347bbe9d5fd8cc22b
4
- data.tar.gz: 981eb98d54b3687af7f71b350596cedf63eea39b
3
+ metadata.gz: e2baecdd27415e458334b145590c6679023dd890
4
+ data.tar.gz: c0eea714604dad7549a052fa6b5f7f92e2d69719
5
5
  SHA512:
6
- metadata.gz: 8d50a9fbeaca0a02fa13a37e7cf2237ab3f9043401b8e7c6801ac65b36218fc5688693be3491e18f86a1a8fb23b639beeb8a181f6afa55b1abf338b795684b29
7
- data.tar.gz: 2035c100e01ed818b5ccd248dc987b0712dbf3e73b7a442f16169aac081e8aaaf478cc21f7486e9c8cbc77f81b62165c235b1f4a3ee0b97df74d2f9e9f0f9385
6
+ metadata.gz: 3e980d795b418fe8f8307b57beee2fe8db0ba6a7ee1b32bf85186c1c38e101479c54b9bba2629a10f3f1575289abad80cde84f85a0c20ad02ee874dc342f1e87
7
+ data.tar.gz: 40e039ba23e69e2f179defe5c72bbd4478fcc4a0fda5d16b64f0a5338226303af57855075013d720c487fdec73ad0604293efee314067761e58dcfca15b41124
@@ -31,6 +31,9 @@ class Chef
31
31
  # non-sensical.
32
32
  class FileSystemFileVendor < FileVendor
33
33
 
34
+ attr_reader :cookbook_name
35
+ attr_reader :repo_paths
36
+
34
37
  def initialize(manifest, *repo_paths)
35
38
  @cookbook_name = manifest[:cookbook_name]
36
39
  @repo_paths = repo_paths.flatten
@@ -24,15 +24,39 @@ class Chef
24
24
  # This class handles fetching of cookbook files based on specificity.
25
25
  class FileVendor
26
26
 
27
- def self.on_create(&block)
28
- @instance_creator = block
27
+ @vendor_class = nil
28
+ @initialization_options = nil
29
+
30
+ # Configures FileVendor to use the RemoteFileVendor implementation. After
31
+ # calling this, subsequent calls to create_from_manifest will return a
32
+ # RemoteFileVendor object initialized with the given http_client
33
+ def self.fetch_from_remote(http_client)
34
+ @vendor_class = RemoteFileVendor
35
+ @initialization_options = http_client
36
+ end
37
+
38
+ def self.fetch_from_disk(cookbook_paths)
39
+ @vendor_class = FileSystemFileVendor
40
+ @initialization_options = cookbook_paths
41
+ end
42
+
43
+ # Returns the implementation class that is currently configured, or `nil`
44
+ # if one has not been configured yet.
45
+ def self.vendor_class
46
+ @vendor_class
47
+ end
48
+
49
+ def self.initialization_options
50
+ @initialization_options
29
51
  end
30
52
 
31
53
  # Factory method that creates the appropriate kind of
32
54
  # Cookbook::FileVendor to serve the contents of the manifest
33
55
  def self.create_from_manifest(manifest)
34
- raise "Must call Chef::Cookbook::FileVendor.on_create before calling create_from_manifest factory" unless defined?(@instance_creator)
35
- @instance_creator.call(manifest)
56
+ if @vendor_class.nil?
57
+ raise "Must configure FileVendor to use a specific implementation before creating an instance"
58
+ end
59
+ @vendor_class.new(manifest, @initialization_options)
36
60
  end
37
61
 
38
62
  # Gets the on-disk location for the given cookbook file.
@@ -25,6 +25,9 @@ class Chef
25
25
  # if not available, loading them from the remote server.
26
26
  class RemoteFileVendor < FileVendor
27
27
 
28
+ attr_reader :rest
29
+ attr_reader :cookbook_name
30
+
28
31
  def initialize(manifest, rest)
29
32
  @manifest = manifest
30
33
  @cookbook_name = @manifest[:cookbook_name]
@@ -289,11 +289,26 @@ class Chef
289
289
  def retrying_http_errors(url)
290
290
  http_attempts = 0
291
291
  begin
292
- http_attempts += 1
293
-
294
- yield
295
-
292
+ loop do
293
+ http_attempts += 1
294
+ response, request, return_value = yield
295
+ # handle HTTP 50X Error
296
+ if response.kind_of?(Net::HTTPServerError)
297
+ if http_retry_count - http_attempts + 1 > 0
298
+ sleep_time = 1 + (2 ** http_attempts) + rand(2 ** http_attempts)
299
+ Chef::Log.error("Server returned error #{response.code} for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s")
300
+ sleep(sleep_time)
301
+ redo
302
+ end
303
+ end
304
+ return [response, request, return_value]
305
+ end
296
306
  rescue SocketError, Errno::ETIMEDOUT => e
307
+ if http_retry_count - http_attempts + 1 > 0
308
+ Chef::Log.error("Error connecting to #{url}, retry #{http_attempts}/#{http_retry_count}")
309
+ sleep(http_retry_delay)
310
+ retry
311
+ end
297
312
  e.message.replace "Error connecting to #{url} - #{e.message}"
298
313
  raise e
299
314
  rescue Errno::ECONNREFUSED
@@ -310,14 +325,6 @@ class Chef
310
325
  retry
311
326
  end
312
327
  raise Timeout::Error, "Timeout connecting to #{url}, giving up"
313
- rescue Net::HTTPFatalError => e
314
- if http_retry_count - http_attempts + 1 > 0
315
- sleep_time = 1 + (2 ** http_attempts) + rand(2 ** http_attempts)
316
- Chef::Log.error("Server returned error for #{url}, retrying #{http_attempts}/#{http_retry_count} in #{sleep_time}s")
317
- sleep(sleep_time)
318
- retry
319
- end
320
- raise
321
328
  end
322
329
  end
323
330
 
@@ -184,7 +184,7 @@ class Chef
184
184
 
185
185
  def cookbook_repo
186
186
  @cookbook_loader ||= begin
187
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, config[:cookbook_path]) }
187
+ Chef::Cookbook::FileVendor.fetch_from_disk(config[:cookbook_path])
188
188
  Chef::CookbookLoader.new(config[:cookbook_path])
189
189
  end
190
190
  end
@@ -0,0 +1,56 @@
1
+ #
2
+ # Author:: Adam Edwards (<adamed@opscode.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, 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
+
20
+ require 'chef/exceptions'
21
+ require 'chef/platform/query_helpers'
22
+ require 'chef/win32/error' if Chef::Platform.windows?
23
+ require 'chef/win32/api/system' if Chef::Platform.windows?
24
+
25
+ class Chef
26
+ module Mixin
27
+ module WindowsEnvHelper
28
+
29
+ if Chef::Platform.windows?
30
+ include Chef::ReservedNames::Win32::API::System
31
+ end
32
+
33
+ #see: http://msdn.microsoft.com/en-us/library/ms682653%28VS.85%29.aspx
34
+ HWND_BROADCAST = 0xffff
35
+ WM_SETTINGCHANGE = 0x001A
36
+ SMTO_BLOCK = 0x0001
37
+ SMTO_ABORTIFHUNG = 0x0002
38
+ SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
39
+
40
+ def broadcast_env_change
41
+ flags = SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG
42
+ SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, FFI::MemoryPointer.from_string('Environment').address, flags, 5000, nil)
43
+ end
44
+
45
+ def expand_path(path)
46
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms724265%28v=vs.85%29.aspx
47
+ # Max size of env block on windows is 32k
48
+ buf = 0.chr * 32 * 1024
49
+ if ExpandEnvironmentStringsA(path, buf, buf.length) == 0
50
+ Chef::ReservedNames::Win32::Error.raise!
51
+ end
52
+ buf.strip
53
+ end
54
+ end
55
+ end
56
+ end
@@ -56,13 +56,13 @@ class Chef
56
56
 
57
57
  def setup_run_context(specific_recipes=nil)
58
58
  if Chef::Config[:solo]
59
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, Chef::Config[:cookbook_path]) }
59
+ Chef::Cookbook::FileVendor.fetch_from_disk(Chef::Config[:cookbook_path])
60
60
  cl = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
61
61
  cl.load_cookbooks
62
62
  cookbook_collection = Chef::CookbookCollection.new(cl)
63
63
  run_context = Chef::RunContext.new(node, cookbook_collection, @events)
64
64
  else
65
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, api_service) }
65
+ Chef::Cookbook::FileVendor.fetch_from_remote(api_service)
66
66
  cookbook_hash = sync_cookbooks
67
67
  cookbook_collection = Chef::CookbookCollection.new(cookbook_hash)
68
68
  run_context = Chef::RunContext.new(node, cookbook_collection, @events)
@@ -154,10 +154,7 @@ class Chef
154
154
  end
155
155
 
156
156
  def setup_run_context(specific_recipes=nil)
157
- # TODO: This file vendor stuff is duplicated and initializing it with a
158
- # block traps a reference to this object in a global context which will
159
- # prevent it from getting GC'd. Simplify it.
160
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, api_service) }
157
+ Chef::Cookbook::FileVendor.fetch_from_remote(http_api)
161
158
  sync_cookbooks
162
159
  cookbook_collection = Chef::CookbookCollection.new(cookbooks_to_sync)
163
160
  run_context = Chef::RunContext.new(node, cookbook_collection, events)
@@ -16,13 +16,13 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'chef/win32/api/system' if RUBY_PLATFORM =~ /mswin|mingw32|windows/
19
+ require 'chef/mixin/windows_env_helper'
20
20
 
21
21
  class Chef
22
22
  class Provider
23
23
  class Env
24
24
  class Windows < Chef::Provider::Env
25
- include Chef::ReservedNames::Win32::API::System if RUBY_PLATFORM =~ /mswin|mingw32|windows/
25
+ include Chef::Mixin::WindowsEnvHelper
26
26
 
27
27
  def create_env
28
28
  obj = env_obj(@new_resource.key_name)
@@ -33,7 +33,9 @@ class Chef
33
33
  end
34
34
  obj.variablevalue = @new_resource.value
35
35
  obj.put_
36
- ENV[@new_resource.key_name] = @new_resource.value
36
+ value = @new_resource.value
37
+ value = expand_path(value) if @new_resource.key_name.upcase == 'PATH'
38
+ ENV[@new_resource.key_name] = value
37
39
  broadcast_env_change
38
40
  end
39
41
 
@@ -60,17 +62,6 @@ class Chef
60
62
  end
61
63
  end
62
64
 
63
- #see: http://msdn.microsoft.com/en-us/library/ms682653%28VS.85%29.aspx
64
- HWND_BROADCAST = 0xffff
65
- WM_SETTINGCHANGE = 0x001A
66
- SMTO_BLOCK = 0x0001
67
- SMTO_ABORTIFHUNG = 0x0002
68
- SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
69
-
70
- def broadcast_env_change
71
- flags = SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG
72
- SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, FFI::MemoryPointer.from_string('Environment').address, flags, 5000, nil)
73
- end
74
65
  end
75
66
  end
76
67
  end
@@ -169,7 +169,7 @@ module Shell
169
169
 
170
170
  def rebuild_context
171
171
  @run_status = Chef::RunStatus.new(@node, @events)
172
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, Chef::Config[:cookbook_path]) }
172
+ Chef::Cookbook::FileVendor.fetch_from_disk(Chef::Config[:cookbook_path])
173
173
  cl = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
174
174
  cl.load_cookbooks
175
175
  cookbook_collection = Chef::CookbookCollection.new(cl)
@@ -201,7 +201,7 @@ module Shell
201
201
 
202
202
  def rebuild_context
203
203
  @run_status = Chef::RunStatus.new(@node, @events)
204
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::RemoteFileVendor.new(manifest, Chef::REST.new(Chef::Config[:server_url])) }
204
+ Chef::Cookbook::FileVendor.fetch_from_remote(Chef::REST.new(Chef::Config[:chef_server_url]))
205
205
  cookbook_hash = @client.sync_cookbooks
206
206
  cookbook_collection = Chef::CookbookCollection.new(cookbook_hash)
207
207
  @run_context = Chef::RunContext.new(node, cookbook_collection, @events)
@@ -17,7 +17,7 @@
17
17
 
18
18
  class Chef
19
19
  CHEF_ROOT = File.dirname(File.expand_path(File.dirname(__FILE__)))
20
- VERSION = '11.16.2'
20
+ VERSION = '11.16.4'
21
21
  end
22
22
 
23
23
  # NOTE: the Chef::Version class is defined in version_class.rb
@@ -200,6 +200,15 @@ LRESULT WINAPI SendMessageTimeout(
200
200
  safe_attach_function :SendMessageTimeoutW, [:HWND, :UINT, :WPARAM, :LPARAM, :UINT, :UINT, :PDWORD_PTR], :LRESULT
201
201
  safe_attach_function :SendMessageTimeoutA, [:HWND, :UINT, :WPARAM, :LPARAM, :UINT, :UINT, :PDWORD_PTR], :LRESULT
202
202
 
203
+ =begin
204
+ DWORD WINAPI ExpandEnvironmentStrings(
205
+ _In_ LPCTSTR lpSrc,
206
+ _Out_opt_ LPTSTR lpDst,
207
+ _In_ DWORD nSize
208
+ );
209
+ =end
210
+ safe_attach_function :ExpandEnvironmentStringsW, [:pointer, :pointer, :DWORD], :DWORD
211
+ safe_attach_function :ExpandEnvironmentStringsA, [:pointer, :pointer, :DWORD], :DWORD
203
212
  end
204
213
  end
205
214
  end
@@ -46,8 +46,11 @@ describe Chef::DSL::RebootPending, :windows_only do
46
46
 
47
47
  describe "reboot_pending?" do
48
48
 
49
- context "when there is nothing to indicate a reboot is pending" do
50
- it { expect(recipe.reboot_pending?).to be_false }
49
+ describe "when there is nothing to indicate a reboot is pending" do
50
+ it "should return false" do
51
+ pending "Found existing registry keys" unless registry_safe?
52
+ expect(recipe.reboot_pending?).to be_false
53
+ end
51
54
  end
52
55
 
53
56
  describe 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations' do
@@ -40,7 +40,7 @@ describe Chef::Resource::CookbookFile do
40
40
  # set up cookbook collection for this run to use, based on our
41
41
  # spec data.
42
42
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, 'cookbooks'))
43
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
43
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
44
44
  loader = Chef::CookbookLoader.new(cookbook_repo)
45
45
  loader.load_cookbooks
46
46
  cookbook_collection = Chef::CookbookCollection.new(loader)
@@ -1,137 +1,183 @@
1
- #
2
- # Author:: Adam Edwards (<adamed@getchef.com>)
3
- # Copyright:: Copyright (c) 2014 Opscode, 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 'spec_helper'
20
-
21
- describe Chef::Resource::Env, :windows_only do
22
- context 'when running on Windows' do
23
- let(:chef_env_test_lower_case) { 'chefenvtest' }
24
- let(:chef_env_test_mixed_case) { 'chefENVtest' }
25
- let(:env_value1) { 'value1' }
26
- let(:env_value2) { 'value2' }
27
- let(:test_run_context) {
28
- node = Chef::Node.new
29
- node.default['platform'] = 'windows'
30
- node.default['platform_version'] = '6.1'
31
- empty_events = Chef::EventDispatch::Dispatcher.new
32
- Chef::RunContext.new(node, {}, empty_events)
33
- }
34
- let(:test_resource) {
35
- Chef::Resource::Env.new('unknown', test_run_context)
36
- }
37
-
38
- before(:each) do
39
- resource_lower = Chef::Resource::Env.new(chef_env_test_lower_case, test_run_context)
40
- resource_lower.run_action(:delete)
41
- resource_mixed = Chef::Resource::Env.new(chef_env_test_mixed_case, test_run_context)
42
- resource_mixed.run_action(:delete)
43
- end
44
-
45
- context "when the create action is invoked" do
46
- it 'should create an environment variable for action create' do
47
- expect(ENV[chef_env_test_lower_case]).to eq(nil)
48
- test_resource.key_name(chef_env_test_lower_case)
49
- test_resource.value(env_value1)
50
- test_resource.run_action(:create)
51
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
52
- end
53
-
54
- it "should modify an existing variable's value to a new value and preserve the original name and preseve the original variable's name" do
55
- test_resource.key_name(chef_env_test_lower_case)
56
- test_resource.value(env_value1)
57
- test_resource.run_action(:create)
58
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
59
- test_resource.value(env_value2)
60
- test_resource.run_action(:create)
61
- expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
62
- end
63
-
64
- it "should modify an existing variable's value to a new value if the variable name case differs from the existing variable" do
65
- test_resource.key_name(chef_env_test_lower_case)
66
- test_resource.value(env_value1)
67
- test_resource.run_action(:create)
68
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
69
- test_resource.key_name(chef_env_test_mixed_case)
70
- test_resource.value(env_value2)
71
- test_resource.run_action(:create)
72
- expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
73
- end
74
- end
75
-
76
- context "when the modify action is invoked" do
77
- it "should raise an exception for modify if the variable doesn't exist" do
78
- expect(ENV[chef_env_test_lower_case]).to eq(nil)
79
- test_resource.key_name(chef_env_test_lower_case)
80
- test_resource.value(env_value1)
81
- expect {test_resource.run_action(:modify) }.to raise_error(Chef::Exceptions::Env)
82
- end
83
-
84
- it "should modify an existing variable's value to a new value" do
85
- test_resource.key_name(chef_env_test_lower_case)
86
- test_resource.value(env_value1)
87
- test_resource.run_action(:create)
88
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
89
- test_resource.value(env_value2)
90
- test_resource.run_action(:modify)
91
- expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
92
- end
93
-
94
- # This examlpe covers Chef Issue #1754
95
- it "should modify an existing variable's value to a new value if the variable name case differs from the existing variable" do
96
- test_resource.key_name(chef_env_test_lower_case)
97
- test_resource.value(env_value1)
98
- test_resource.run_action(:create)
99
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
100
- test_resource.key_name(chef_env_test_mixed_case)
101
- test_resource.value(env_value2)
102
- test_resource.run_action(:modify)
103
- expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
104
- end
105
- end
106
-
107
- context "when the delete action is invoked" do
108
- it "should delete an environment variable" do
109
- test_resource.key_name(chef_env_test_lower_case)
110
- test_resource.value(env_value1)
111
- test_resource.run_action(:create)
112
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
113
- test_resource.run_action(:delete)
114
- expect(ENV[chef_env_test_lower_case]).to eq(nil)
115
- end
116
-
117
- it "should not raise an exception when a non-existent environment variable is deleted" do
118
- expect(ENV[chef_env_test_lower_case]).to eq(nil)
119
- test_resource.key_name(chef_env_test_lower_case)
120
- test_resource.value(env_value1)
121
- expect{test_resource.run_action(:delete)}.not_to raise_error
122
- expect(ENV[chef_env_test_lower_case]).to eq(nil)
123
- end
124
-
125
- it "should delete an existing variable's value to a new value if the specified variable name case differs from the existing variable" do
126
- test_resource.key_name(chef_env_test_lower_case)
127
- test_resource.value(env_value1)
128
- test_resource.run_action(:create)
129
- expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
130
- test_resource.key_name(chef_env_test_mixed_case)
131
- test_resource.run_action(:delete)
132
- expect(ENV[chef_env_test_lower_case]).to eq(nil)
133
- expect(ENV[chef_env_test_mixed_case]).to eq(nil)
134
- end
135
- end
136
- end
137
- end
1
+ #
2
+ # Author:: Adam Edwards (<adamed@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Opscode, 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 'spec_helper'
20
+
21
+ describe Chef::Resource::Env, :windows_only do
22
+ context 'when running on Windows' do
23
+ let(:chef_env_test_lower_case) { 'chefenvtest' }
24
+ let(:chef_env_test_mixed_case) { 'chefENVtest' }
25
+ let(:env_value1) { 'value1' }
26
+ let(:env_value2) { 'value2' }
27
+
28
+ let(:env_value_expandable) { '%SystemRoot%' }
29
+ let(:test_run_context) {
30
+ node = Chef::Node.new
31
+ node.default['platform'] = 'windows'
32
+ node.default['platform_version'] = '6.1'
33
+ empty_events = Chef::EventDispatch::Dispatcher.new
34
+ Chef::RunContext.new(node, {}, empty_events)
35
+ }
36
+ let(:test_resource) {
37
+ Chef::Resource::Env.new('unknown', test_run_context)
38
+ }
39
+
40
+ before(:each) do
41
+ resource_lower = Chef::Resource::Env.new(chef_env_test_lower_case, test_run_context)
42
+ resource_lower.run_action(:delete)
43
+ resource_mixed = Chef::Resource::Env.new(chef_env_test_mixed_case, test_run_context)
44
+ resource_mixed.run_action(:delete)
45
+ end
46
+
47
+ context "when the create action is invoked" do
48
+ it 'should create an environment variable for action create' do
49
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
50
+ test_resource.key_name(chef_env_test_lower_case)
51
+ test_resource.value(env_value1)
52
+ test_resource.run_action(:create)
53
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
54
+ end
55
+
56
+ it "should modify an existing variable's value to a new value" do
57
+ test_resource.key_name(chef_env_test_lower_case)
58
+ test_resource.value(env_value1)
59
+ test_resource.run_action(:create)
60
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
61
+ test_resource.value(env_value2)
62
+ test_resource.run_action(:create)
63
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
64
+ end
65
+
66
+ it "should modify an existing variable's value to a new value if the variable name case differs from the existing variable" do
67
+ test_resource.key_name(chef_env_test_lower_case)
68
+ test_resource.value(env_value1)
69
+ test_resource.run_action(:create)
70
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
71
+ test_resource.key_name(chef_env_test_mixed_case)
72
+ test_resource.value(env_value2)
73
+ test_resource.run_action(:create)
74
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
75
+ end
76
+
77
+ it 'should not expand environment variables if the variable is not PATH' do
78
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
79
+ test_resource.key_name(chef_env_test_lower_case)
80
+ test_resource.value(env_value_expandable)
81
+ test_resource.run_action(:create)
82
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value_expandable)
83
+ end
84
+ end
85
+
86
+ context "when the modify action is invoked" do
87
+ it "should raise an exception for modify if the variable doesn't exist" do
88
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
89
+ test_resource.key_name(chef_env_test_lower_case)
90
+ test_resource.value(env_value1)
91
+ expect {test_resource.run_action(:modify) }.to raise_error(Chef::Exceptions::Env)
92
+ end
93
+
94
+ it "should modify an existing variable's value to a new value" do
95
+ test_resource.key_name(chef_env_test_lower_case)
96
+ test_resource.value(env_value1)
97
+ test_resource.run_action(:create)
98
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
99
+ test_resource.value(env_value2)
100
+ test_resource.run_action(:modify)
101
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
102
+ end
103
+
104
+ # This examlpe covers Chef Issue #1754
105
+ it "should modify an existing variable's value to a new value if the variable name case differs from the existing variable" do
106
+ test_resource.key_name(chef_env_test_lower_case)
107
+ test_resource.value(env_value1)
108
+ test_resource.run_action(:create)
109
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
110
+ test_resource.key_name(chef_env_test_mixed_case)
111
+ test_resource.value(env_value2)
112
+ test_resource.run_action(:modify)
113
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value2)
114
+ end
115
+
116
+ it 'should not expand environment variables if the variable is not PATH' do
117
+ test_resource.key_name(chef_env_test_lower_case)
118
+ test_resource.value(env_value1)
119
+ test_resource.run_action(:create)
120
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
121
+ test_resource.value(env_value_expandable)
122
+ test_resource.run_action(:modify)
123
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value_expandable)
124
+ end
125
+
126
+ context 'when using PATH' do
127
+ let(:random_name) { Time.now.to_i }
128
+ let(:env_val) { "#{env_value_expandable}_#{random_name}"}
129
+ let(:path_before) { test_resource.provider_for_action(test_resource.action).env_value('PATH') }
130
+
131
+ it 'should expand PATH' do
132
+ path_before.should_not include(env_val)
133
+ test_resource.key_name('PATH')
134
+ test_resource.value("#{path_before};#{env_val}")
135
+ test_resource.run_action(:create)
136
+ ENV['PATH'].should_not include(env_val)
137
+ ENV['PATH'].should include("#{random_name}")
138
+ end
139
+
140
+ after(:each) do
141
+ # cleanup so we don't flood the path
142
+ test_resource.key_name('PATH')
143
+ test_resource.value(path_before)
144
+ test_resource.run_action(:create)
145
+ if test_resource.provider_for_action(test_resource.action).env_value('PATH') != path_before
146
+ raise 'Failed to cleanup after ourselves'
147
+ end
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ context "when the delete action is invoked" do
154
+ it "should delete an environment variable" do
155
+ test_resource.key_name(chef_env_test_lower_case)
156
+ test_resource.value(env_value1)
157
+ test_resource.run_action(:create)
158
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
159
+ test_resource.run_action(:delete)
160
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
161
+ end
162
+
163
+ it "should not raise an exception when a non-existent environment variable is deleted" do
164
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
165
+ test_resource.key_name(chef_env_test_lower_case)
166
+ test_resource.value(env_value1)
167
+ expect{test_resource.run_action(:delete)}.not_to raise_error
168
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
169
+ end
170
+
171
+ it "should delete an existing variable's value to a new value if the specified variable name case differs from the existing variable" do
172
+ test_resource.key_name(chef_env_test_lower_case)
173
+ test_resource.value(env_value1)
174
+ test_resource.run_action(:create)
175
+ expect(ENV[chef_env_test_lower_case]).to eq(env_value1)
176
+ test_resource.key_name(chef_env_test_mixed_case)
177
+ test_resource.run_action(:delete)
178
+ expect(ENV[chef_env_test_lower_case]).to eq(nil)
179
+ expect(ENV[chef_env_test_mixed_case]).to eq(nil)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -135,9 +135,7 @@ describe Chef::Resource::Package, metadata do
135
135
  cookbook_path = File.join(CHEF_SPEC_DATA, "cookbooks")
136
136
  cl = Chef::CookbookLoader.new(cookbook_path)
137
137
  cl.load_cookbooks
138
- Chef::Cookbook::FileVendor.on_create do |manifest|
139
- Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_path)
140
- end
138
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_path)
141
139
  Chef::CookbookCollection.new(cl)
142
140
  end
143
141
 
@@ -26,7 +26,7 @@ describe Chef::Resource::RemoteDirectory do
26
26
 
27
27
  def create_resource
28
28
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
29
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
29
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
30
30
  node = Chef::Node.new
31
31
  cl = Chef::CookbookLoader.new(cookbook_repo)
32
32
  cl.load_cookbooks
@@ -37,7 +37,7 @@ describe Chef::Resource::Template do
37
37
 
38
38
  def create_resource
39
39
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
40
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
40
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
41
41
  cl = Chef::CookbookLoader.new(cookbook_repo)
42
42
  cl.load_cookbooks
43
43
  cookbook_collection = Chef::CookbookCollection.new(cl)
@@ -21,7 +21,8 @@ require 'chef/mixin/shell_out'
21
21
  metadata = {
22
22
  :unix_only => true,
23
23
  :requires_root => true,
24
- :provider => {:user => Chef::Provider::User::Dscl}
24
+ :provider => {:user => Chef::Provider::User::Dscl},
25
+ :not_supported_on_mac_osx_106 => true,
25
26
  }
26
27
 
27
28
  describe "Chef::Resource::User with Chef::Provider::User::Dscl provider", metadata do
@@ -0,0 +1,78 @@
1
+ #--
2
+ # Author:: Daniel DeLeo (<dan@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 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
+ require 'spec_helper'
19
+
20
+ describe Chef::Cookbook::FileVendor do
21
+
22
+ let(:file_vendor_class) { Class.new(described_class) }
23
+
24
+ # A manifest is a Hash of the format defined by Chef::CookbookVersion#manifest
25
+ let(:manifest) { {:cookbook_name => "bob"} }
26
+
27
+ context "when configured to fetch files over http" do
28
+
29
+ let(:http) { double("Chef::REST") }
30
+
31
+ before do
32
+ file_vendor_class.fetch_from_remote(http)
33
+ end
34
+
35
+ it "sets the vendor class to RemoteFileVendor" do
36
+ expect(file_vendor_class.vendor_class).to eq(Chef::Cookbook::RemoteFileVendor)
37
+ end
38
+
39
+ it "sets the initialization options to the given http object" do
40
+ expect(file_vendor_class.initialization_options).to eq(http)
41
+ end
42
+
43
+ it "creates a RemoteFileVendor for a given manifest" do
44
+ file_vendor = file_vendor_class.create_from_manifest(manifest)
45
+ expect(file_vendor).to be_a_kind_of(Chef::Cookbook::RemoteFileVendor)
46
+ expect(file_vendor.rest).to eq(http)
47
+ expect(file_vendor.cookbook_name).to eq("bob")
48
+ end
49
+
50
+ end
51
+
52
+ context "when configured to load files from disk" do
53
+
54
+ let(:cookbook_path) { %w[/var/chef/cookbooks /var/chef/other_cookbooks] }
55
+
56
+ before do
57
+ file_vendor_class.fetch_from_disk(cookbook_path)
58
+ end
59
+
60
+ it "sets the vendor class to FileSystemFileVendor" do
61
+ expect(file_vendor_class.vendor_class).to eq(Chef::Cookbook::FileSystemFileVendor)
62
+ end
63
+
64
+ it "sets the initialization options to the given cookbook paths" do
65
+ expect(file_vendor_class.initialization_options).to eq(cookbook_path)
66
+ end
67
+
68
+ it "creates a FileSystemFileVendor for a given manifest" do
69
+ file_vendor = file_vendor_class.create_from_manifest(manifest)
70
+ expect(file_vendor).to be_a_kind_of(Chef::Cookbook::FileSystemFileVendor)
71
+ expect(file_vendor.cookbook_name).to eq("bob")
72
+ expect(file_vendor.repo_paths).to eq(cookbook_path)
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
@@ -76,7 +76,7 @@ describe Chef::Mixin::Template, "render_template" do
76
76
  describe "with a template resource" do
77
77
  before :each do
78
78
  @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
79
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
79
+ Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo)
80
80
 
81
81
  @node = Chef::Node.new
82
82
  cl = Chef::CookbookLoader.new(@cookbook_repo)
@@ -19,49 +19,85 @@
19
19
  require 'spec_helper'
20
20
 
21
21
  describe Chef::Provider::Env::Windows, :windows_only do
22
- before do
23
- @node = Chef::Node.new
24
- @events = Chef::EventDispatch::Dispatcher.new
25
- @run_context = Chef::RunContext.new(@node, {}, @events)
26
- @new_resource = Chef::Resource::Env.new("CHEF_WINDOWS_ENV_TEST")
27
- @new_resource.value("foo")
28
- @provider = Chef::Provider::Env::Windows.new(@new_resource, @run_context)
29
- @provider.stub(:env_obj).and_return(double('null object').as_null_object)
30
- end
22
+ let(:node) { Chef::Node.new }
23
+ let(:events) {Chef::EventDispatch::Dispatcher.new }
24
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
31
25
 
32
- describe "action_create" do
33
- before do
34
- ENV.delete('CHEF_WINDOWS_ENV_TEST')
35
- @provider.key_exists = false
36
- end
26
+ context 'when environment variable is not PATH' do
27
+ let(:new_resource) {
28
+ new_resource = Chef::Resource::Env.new("CHEF_WINDOWS_ENV_TEST")
29
+ new_resource.value("foo")
30
+ new_resource
31
+ }
32
+ let(:provider) {
33
+ provider = Chef::Provider::Env::Windows.new(new_resource, run_context)
34
+ provider.stub(:env_obj).and_return(double('null object').as_null_object)
35
+ provider
36
+ }
37
37
 
38
- it "should update the ruby ENV object when it creates the key" do
39
- @provider.action_create
40
- expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql('foo')
41
- end
42
- end
38
+ describe "action_create" do
39
+ before do
40
+ ENV.delete('CHEF_WINDOWS_ENV_TEST')
41
+ provider.key_exists = false
42
+ end
43
43
 
44
- describe "action_modify" do
45
- before do
46
- ENV['CHEF_WINDOWS_ENV_TEST'] = 'foo'
44
+ it "should update the ruby ENV object when it creates the key" do
45
+ provider.action_create
46
+ expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql('foo')
47
+ end
47
48
  end
48
49
 
49
- it "should update the ruby ENV object when it updates the value" do
50
- @provider.should_receive(:compare_value).and_return(true)
51
- @new_resource.value("foobar")
52
- @provider.action_modify
53
- expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql('foobar')
50
+ describe "action_modify" do
51
+ before do
52
+ ENV['CHEF_WINDOWS_ENV_TEST'] = 'foo'
53
+ end
54
+
55
+ it "should update the ruby ENV object when it updates the value" do
56
+ provider.should_receive(:compare_value).and_return(true)
57
+ new_resource.value("foobar")
58
+ provider.action_modify
59
+ expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql('foobar')
60
+ end
61
+
62
+ describe "action_delete" do
63
+ before do
64
+ ENV['CHEF_WINDOWS_ENV_TEST'] = 'foo'
65
+ end
66
+
67
+ it "should update the ruby ENV object when it deletes the key" do
68
+ provider.action_delete
69
+ expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql(nil)
70
+ end
71
+ end
54
72
  end
55
73
  end
56
74
 
57
- describe "action_delete" do
58
- before do
59
- ENV['CHEF_WINDOWS_ENV_TEST'] = 'foo'
60
- end
75
+ context 'when environment is PATH' do
76
+ describe "for PATH" do
77
+ let(:system_root) {'%SystemRoot%'}
78
+ let(:system_root_value) { 'D:\Windows' }
79
+ let(:new_resource) {
80
+ new_resource = Chef::Resource::Env.new('PATH')
81
+ new_resource.value(system_root)
82
+ new_resource
83
+ }
84
+ let(:provider) {
85
+ provider = Chef::Provider::Env::Windows.new(new_resource, run_context)
86
+ provider.stub(:env_obj).and_return(double('null object').as_null_object)
87
+ provider
88
+ }
61
89
 
62
- it "should update the ruby ENV object when it deletes the key" do
63
- @provider.action_delete
64
- expect(ENV['CHEF_WINDOWS_ENV_TEST']).to eql(nil)
90
+ before do
91
+ stub_const('ENV', {'PATH' => ''})
92
+ end
93
+
94
+ it "replaces Windows system variables" do
95
+ provider.should_receive(:compare_value).and_return(true)
96
+ provider.should_receive(:expand_path).with(system_root).and_return(system_root_value)
97
+ provider.action_modify
98
+ expect(ENV['PATH']).to eql(system_root_value)
99
+ end
65
100
  end
101
+
66
102
  end
67
103
  end
@@ -339,7 +339,7 @@ describe Chef::Provider::Package do
339
339
  describe "when given a response file" do
340
340
  before(:each) do
341
341
  @cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
342
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
342
+ Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo)
343
343
 
344
344
  @node = Chef::Node.new
345
345
  cl = Chef::CookbookLoader.new(@cookbook_repo)
@@ -35,7 +35,7 @@ describe Chef::Provider::RemoteDirectory do
35
35
  @resource.cookbook('openldap')
36
36
 
37
37
  @cookbook_repo = ::File.expand_path(::File.join(CHEF_SPEC_DATA, "cookbooks"))
38
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, @cookbook_repo) }
38
+ Chef::Cookbook::FileVendor.fetch_from_disk(@cookbook_repo)
39
39
 
40
40
  @node = Chef::Node.new
41
41
  cl = Chef::CookbookLoader.new(@cookbook_repo)
@@ -36,7 +36,7 @@ describe Chef::Provider::Template::Content do
36
36
 
37
37
  let(:run_context) do
38
38
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
39
- Chef::Cookbook::FileVendor.on_create { |manifest| Chef::Cookbook::FileSystemFileVendor.new(manifest, cookbook_repo) }
39
+ Chef::Cookbook::FileVendor.fetch_from_disk(cookbook_repo)
40
40
  cl = Chef::CookbookLoader.new(cookbook_repo)
41
41
  cl.load_cookbooks
42
42
  cookbook_collection = Chef::CookbookCollection.new(cl)
@@ -526,9 +526,12 @@ describe Chef::REST do
526
526
  http_response.stub(:read_body)
527
527
  http_response
528
528
  end
529
- it "throws an exception" do
529
+
530
+ it "retries then throws an exception" do
530
531
  rest.stub(:sleep)
531
532
  expect {rest.request(:GET, url)}.to raise_error(Net::HTTPFatalError)
533
+ count = Chef::Config[:http_retry_count]
534
+ expect(log_stringio.string).to match(Regexp.escape("ERROR: Server returned error 500 for #{url}, retrying #{count}/#{count}"))
532
535
  end
533
536
  end
534
537
  end
@@ -50,6 +50,7 @@ end
50
50
  describe Shell::ClientSession do
51
51
  before do
52
52
  Chef::Config[:shell_config] = { :override_runlist => [Chef::RunList::RunListItem.new('shell::override')] }
53
+ @chef_rest = double("Chef::REST")
53
54
  @session = Shell::ClientSession.instance
54
55
  @node = Chef::Node.build("foo")
55
56
  @session.node = @node
@@ -66,6 +67,7 @@ describe Shell::ClientSession do
66
67
  @expansion = Chef::RunList::RunListExpansion.new(@node.chef_environment, [])
67
68
 
68
69
  @node.run_list.should_receive(:expand).with(@node.chef_environment).and_return(@expansion)
70
+ Chef::REST.should_receive(:new).with(Chef::Config[:chef_server_url]).and_return(@chef_rest)
69
71
  @session.rebuild_context
70
72
  end
71
73
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.16.2
4
+ version: 11.16.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Jacob
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-17 00:00:00.000000000 Z
11
+ date: 2014-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-config
@@ -884,6 +884,7 @@ files:
884
884
  - lib/chef/mixin/template.rb
885
885
  - lib/chef/mixin/why_run.rb
886
886
  - lib/chef/mixin/windows_architecture_helper.rb
887
+ - lib/chef/mixin/windows_env_helper.rb
887
888
  - lib/chef/mixin/xml_escape.rb
888
889
  - lib/chef/mixins.rb
889
890
  - lib/chef/monkey_patches/file.rb
@@ -1563,6 +1564,7 @@ files:
1563
1564
  - spec/unit/config_fetcher_spec.rb
1564
1565
  - spec/unit/config_spec.rb
1565
1566
  - spec/unit/cookbook/chefignore_spec.rb
1567
+ - spec/unit/cookbook/file_vendor_spec.rb
1566
1568
  - spec/unit/cookbook/metadata_spec.rb
1567
1569
  - spec/unit/cookbook/synchronizer_spec.rb
1568
1570
  - spec/unit/cookbook/syntax_check_spec.rb
@@ -1928,7 +1930,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1928
1930
  version: '0'
1929
1931
  requirements: []
1930
1932
  rubyforge_project:
1931
- rubygems_version: 2.2.2
1933
+ rubygems_version: 2.4.1
1932
1934
  signing_key:
1933
1935
  specification_version: 4
1934
1936
  summary: A systems integration framework, built to bring the benefits of configuration