chef 11.14.0.alpha.3-x86-mingw32 → 11.14.0.alpha.4-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +140 -99
  3. data/lib/chef/application.rb +80 -2
  4. data/lib/chef/application/apply.rb +1 -0
  5. data/lib/chef/application/client.rb +5 -0
  6. data/lib/chef/application/knife.rb +4 -0
  7. data/lib/chef/application/windows_service.rb +1 -0
  8. data/lib/chef/chef_fs/parallelizer/parallel_enumerable.rb +6 -4
  9. data/lib/chef/config.rb +5 -3
  10. data/lib/chef/exceptions.rb +2 -0
  11. data/lib/chef/http/basic_client.rb +1 -0
  12. data/lib/chef/knife.rb +1 -0
  13. data/lib/chef/platform/provider_mapping.rb +7 -0
  14. data/lib/chef/provider/env/windows.rb +2 -0
  15. data/lib/chef/provider/group/usermod.rb +1 -1
  16. data/lib/chef/provider/mount/solaris.rb +233 -0
  17. data/lib/chef/provider/package/apt.rb +9 -0
  18. data/lib/chef/provider/package/windows.rb +3 -0
  19. data/lib/chef/providers.rb +1 -0
  20. data/lib/chef/resource/mount.rb +6 -1
  21. data/lib/chef/util/path_helper.rb +94 -0
  22. data/lib/chef/version.rb +1 -1
  23. data/spec/functional/application_spec.rb +58 -0
  24. data/spec/functional/resource/mount_spec.rb +14 -11
  25. data/spec/integration/client/client_spec.rb +11 -0
  26. data/spec/integration/knife/common_options_spec.rb +9 -0
  27. data/spec/unit/application_spec.rb +157 -0
  28. data/spec/unit/http/basic_client_spec.rb +42 -0
  29. data/spec/unit/provider/env/windows_spec.rb +67 -0
  30. data/spec/unit/provider/group/usermod_spec.rb +2 -1
  31. data/spec/unit/provider/mount/mount_spec.rb +3 -3
  32. data/spec/unit/provider/mount/solaris_spec.rb +646 -0
  33. data/spec/unit/provider/package/apt_spec.rb +5 -0
  34. data/spec/unit/provider/package/windows_spec.rb +6 -0
  35. data/spec/unit/resource_reporter_spec.rb +2 -2
  36. data/spec/unit/util/path_helper_spec.rb +136 -0
  37. metadata +23 -16
@@ -0,0 +1,94 @@
1
+ #
2
+ # Author:: Bryan McLellan <btm@loftninjas.org>
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
+
19
+ require 'chef/platform'
20
+ require 'chef/exceptions'
21
+
22
+ class Chef
23
+ class Util
24
+ class PathHelper
25
+ # Maximum characters in a standard Windows path (260 including drive letter and NUL)
26
+ WIN_MAX_PATH = 259
27
+
28
+ def self.validate_path(path)
29
+ if Chef::Platform.windows?
30
+ unless printable?(path)
31
+ msg = "Path '#{path}' contains non-printable characters. Check that backslashes are escaped with another backslash (e.g. C:\\\\Windows) in double-quoted strings."
32
+ Chef::Log.error(msg)
33
+ raise Chef::Exceptions::ValidationFailed, msg
34
+ end
35
+
36
+ if windows_max_length_exceeded?(path)
37
+ Chef::Log.debug("Path '#{path}' is longer than #{WIN_MAX_PATH}, prefixing with'\\\\?\\'")
38
+ path.insert(0, "\\\\?\\")
39
+ end
40
+ end
41
+
42
+ path
43
+ end
44
+
45
+ def self.windows_max_length_exceeded?(path)
46
+ # Check to see if paths without the \\?\ prefix are over the maximum allowed length for the Windows API
47
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
48
+ unless path =~ /^\\\\?\\/
49
+ if path.length > WIN_MAX_PATH
50
+ return true
51
+ end
52
+ end
53
+
54
+ false
55
+ end
56
+
57
+ def self.printable?(string)
58
+ # returns true if string is free of non-printable characters (escape sequences)
59
+ # this returns false for whitespace escape sequences as well, e.g. \n\t
60
+ if string =~ /[^[:print:]]/
61
+ false
62
+ else
63
+ true
64
+ end
65
+ end
66
+
67
+ # Produces a comparable path.
68
+ def self.canonical_path(path, add_prefix=true)
69
+ # Rather than find an equivalent for File.absolute_path on 1.8.7, just bail out
70
+ raise NotImplementedError, "This feature is not supported on Ruby versions < 1.9" if RUBY_VERSION.to_f < 1.9
71
+
72
+ # First remove extra separators and resolve any relative paths
73
+ abs_path = File.absolute_path(path)
74
+
75
+ if Chef::Platform.windows?
76
+ # Add the \\?\ API prefix on Windows unless add_prefix is false
77
+ # Downcase on Windows where paths are still case-insensitive
78
+ abs_path.gsub!(::File::SEPARATOR, ::File::ALT_SEPARATOR)
79
+ if add_prefix && abs_path !~ /^\\\\?\\/
80
+ abs_path.insert(0, "\\\\?\\")
81
+ end
82
+
83
+ abs_path.downcase!
84
+ end
85
+
86
+ abs_path
87
+ end
88
+
89
+ def self.paths_eql?(path1, path2)
90
+ canonical_path(path1) == canonical_path(path2)
91
+ end
92
+ end
93
+ end
94
+ end
data/lib/chef/version.rb CHANGED
@@ -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.14.0.alpha.3'
20
+ VERSION = '11.14.0.alpha.4'
21
21
  end
22
22
 
23
23
  # NOTE: the Chef::Version class is defined in version_class.rb
@@ -0,0 +1,58 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'spec_helper'
19
+ require 'chef/mixin/shell_out'
20
+
21
+ describe Chef::Application do
22
+ include Chef::Mixin::ShellOut
23
+
24
+ before do
25
+ @original_argv = ARGV.dup
26
+ ARGV.clear
27
+ @original_env = ENV.to_hash
28
+ ENV.clear
29
+ @app = Chef::Application.new
30
+ end
31
+
32
+ after do
33
+ ARGV.replace(@original_argv)
34
+ ENV.clear
35
+ ENV.update(@original_env)
36
+ end
37
+
38
+ describe "when proxy options are set in config" do
39
+ before do
40
+ Chef::Config[:http_proxy] = "http://proxy.example.org:8080"
41
+ Chef::Config[:https_proxy] = nil
42
+ Chef::Config[:ftp_proxy] = nil
43
+ Chef::Config[:no_proxy] = nil
44
+
45
+ @app.configure_proxy_environment_variables
46
+ end
47
+
48
+ it "saves built proxy to ENV which shell_out can use" do
49
+ so = if windows?
50
+ shell_out("echo $env:http_proxy")
51
+ else
52
+ shell_out("echo $http_proxy")
53
+ end
54
+
55
+ so.stdout.should == "http://proxy.example.org:8080\n"
56
+ end
57
+ end
58
+ end
@@ -21,7 +21,7 @@ require 'chef/mixin/shell_out'
21
21
  require 'tmpdir'
22
22
 
23
23
  # run this test only for following platforms.
24
- include_flag = !(['ubuntu', 'centos', 'aix'].include?(ohai[:platform]))
24
+ include_flag = !(['ubuntu', 'centos', 'aix', 'solaris2'].include?(ohai[:platform]))
25
25
 
26
26
  describe Chef::Resource::Mount, :requires_root, :external => include_flag do
27
27
 
@@ -52,6 +52,9 @@ describe Chef::Resource::Mount, :requires_root, :external => include_flag do
52
52
  end
53
53
  fstype = "tmpfs"
54
54
  shell_out!("mkfs -q #{device} 512")
55
+ when "solaris2"
56
+ device = "swap"
57
+ fstype = "tmpfs"
55
58
  else
56
59
  end
57
60
  [device, fstype]
@@ -71,11 +74,10 @@ describe Chef::Resource::Mount, :requires_root, :external => include_flag do
71
74
  end
72
75
 
73
76
  # platform specific validations.
74
- def mount_should_exists(mount_point, device, fstype = nil, options = nil)
77
+ def mount_should_exist(mount_point, device, fstype = nil, options = nil)
75
78
  validation_cmd = "mount | grep #{mount_point} | grep #{device} "
76
79
  validation_cmd << " | grep #{fstype} " unless fstype.nil?
77
80
  validation_cmd << " | grep #{options.join(',')} " unless options.nil? || options.empty?
78
- puts "validation_cmd = #{validation_cmd}"
79
81
  expect(shell_out(validation_cmd).exitstatus).to eq(0)
80
82
  end
81
83
 
@@ -87,6 +89,8 @@ describe Chef::Resource::Mount, :requires_root, :external => include_flag do
87
89
  case ohai[:platform]
88
90
  when 'aix'
89
91
  mount_config = "/etc/filesystems"
92
+ when 'solaris2'
93
+ mount_config = "/etc/vfstab"
90
94
  else
91
95
  mount_config = "/etc/fstab"
92
96
  end
@@ -119,7 +123,7 @@ describe Chef::Resource::Mount, :requires_root, :external => include_flag do
119
123
  provider
120
124
  end
121
125
 
122
- def current_resource
126
+ let(:current_resource) do
123
127
  provider.load_current_resource
124
128
  provider.current_resource
125
129
  end
@@ -138,7 +142,6 @@ describe Chef::Resource::Mount, :requires_root, :external => include_flag do
138
142
  end
139
143
  end
140
144
  end
141
-
142
145
  end
143
146
 
144
147
  after(:all) do
@@ -156,28 +159,28 @@ describe Chef::Resource::Mount, :requires_root, :external => include_flag do
156
159
  current_resource.mounted.should be_false
157
160
  new_resource.run_action(:mount)
158
161
  new_resource.should be_updated
159
- mount_should_exists(new_resource.mount_point, new_resource.device)
162
+ mount_should_exist(new_resource.mount_point, new_resource.device)
160
163
  end
161
-
162
164
  end
163
165
 
164
- describe "when the filesystem should be remounted and the resource supports remounting" do
166
+ # don't run the remount tests on solaris2 (tmpfs does not support remount)
167
+ describe "when the filesystem should be remounted and the resource supports remounting", :external => ohai[:platform] == "solaris2" do
165
168
  it "should remount the filesystem if it is mounted" do
166
169
  new_resource.run_action(:mount)
167
- mount_should_exists(new_resource.mount_point, new_resource.device)
170
+ mount_should_exist(new_resource.mount_point, new_resource.device)
168
171
 
169
172
  new_resource.supports[:remount] = true
170
173
  new_resource.options "rw,log=NULL" if ohai[:platform] == 'aix'
171
174
  new_resource.run_action(:remount)
172
175
 
173
- mount_should_exists(new_resource.mount_point, new_resource.device, nil, (ohai[:platform] == 'aix') ? new_resource.options : nil)
176
+ mount_should_exist(new_resource.mount_point, new_resource.device, nil, (ohai[:platform] == 'aix') ? new_resource.options : nil)
174
177
  end
175
178
  end
176
179
 
177
180
  describe "when the target state is a unmounted filesystem" do
178
181
  it "should umount the filesystem if it is mounted" do
179
182
  new_resource.run_action(:mount)
180
- mount_should_exists(new_resource.mount_point, new_resource.device)
183
+ mount_should_exist(new_resource.mount_point, new_resource.device)
181
184
 
182
185
  new_resource.run_action(:umount)
183
186
  mount_should_not_exists(new_resource.mount_point)
@@ -206,6 +206,17 @@ EOM
206
206
  result.error!
207
207
  end
208
208
 
209
+ it "should not print SSL warnings when running in local-mode" do
210
+ file 'config/client.rb', <<EOM
211
+ chef_server_url 'http://omg.com/blah'
212
+ cookbook_path "#{path_to('cookbooks')}"
213
+ EOM
214
+
215
+ result = shell_out("#{chef_client} -c \"#{path_to('config/client.rb')}\" -o 'x::default' --local-mode", :cwd => chef_dir)
216
+ result.stdout.should_not include("SSL validation of HTTPS requests is disabled.")
217
+ result.error!
218
+ end
219
+
209
220
  it "should complete with success when passed -z and --chef-zero-port" do
210
221
  file 'config/client.rb', <<EOM
211
222
  chef_server_url 'http://omg.com/blah'
@@ -50,6 +50,15 @@ describe 'knife common options' do
50
50
  end
51
51
  end
52
52
 
53
+ context 'And chef_zero.host is 0.0.0.0' do
54
+ before(:each) { Chef::Config.chef_zero.host = '0.0.0.0' }
55
+
56
+ it 'knife raw /nodes/x should retrieve the role' do
57
+ knife('raw /nodes/x').should_succeed /"name": "x"/
58
+ Chef::Config.chef_server_url.should == 'http://0.0.0.0:8889'
59
+ end
60
+ end
61
+
53
62
  context 'and there is a private key' do
54
63
  file 'mykey.pem', <<EOM
55
64
  -----BEGIN RSA PRIVATE KEY-----
@@ -39,6 +39,7 @@ describe Chef::Application do
39
39
  @app = Chef::Application.new
40
40
  @app.stub(:configure_chef).and_return(true)
41
41
  @app.stub(:configure_logging).and_return(true)
42
+ @app.stub(:configure_proxy_environment_variables).and_return(true)
42
43
  end
43
44
 
44
45
  it "should configure chef" do
@@ -51,6 +52,10 @@ describe Chef::Application do
51
52
  @app.reconfigure
52
53
  end
53
54
 
55
+ it "should configure environment variables" do
56
+ @app.should_receive(:configure_proxy_environment_variables).and_return(true)
57
+ @app.reconfigure
58
+ end
54
59
  end
55
60
 
56
61
  describe Chef::Application do
@@ -235,6 +240,158 @@ describe Chef::Application do
235
240
  end
236
241
  end
237
242
 
243
+ describe "when configuring environment variables" do
244
+ def configure_proxy_environment_variables_stubs
245
+ @app.stub(:configure_http_proxy).and_return(true)
246
+ @app.stub(:configure_https_proxy).and_return(true)
247
+ @app.stub(:configure_ftp_proxy).and_return(true)
248
+ @app.stub(:configure_no_proxy).and_return(true)
249
+ end
250
+
251
+ shared_examples_for "setting ENV['http_proxy']" do
252
+ before do
253
+ Chef::Config[:http_proxy] = http_proxy
254
+ end
255
+
256
+ it "should set ENV['http_proxy']" do
257
+ @app.configure_proxy_environment_variables
258
+ @env['http_proxy'].should == "http://#{address}:#{port}"
259
+ end
260
+
261
+ describe "when Chef::Config[:http_proxy_user] is set" do
262
+ before do
263
+ Chef::Config[:http_proxy_user] = "username"
264
+ end
265
+
266
+ it "should set ENV['http_proxy'] with the username" do
267
+ @app.configure_proxy_environment_variables
268
+ @env['http_proxy'].should == "http://username@#{address}:#{port}"
269
+ end
270
+
271
+ context "when :http_proxy_user contains '@' and/or ':'" do
272
+ before do
273
+ Chef::Config[:http_proxy_user] = "my:usern@me"
274
+ end
275
+
276
+ it "should set ENV['http_proxy'] with the escaped username" do
277
+ @app.configure_proxy_environment_variables
278
+ @env['http_proxy'].should == "http://my%3Ausern%40me@#{address}:#{port}"
279
+ end
280
+ end
281
+
282
+ describe "when Chef::Config[:http_proxy_pass] is set" do
283
+ before do
284
+ Chef::Config[:http_proxy_pass] = "password"
285
+ end
286
+
287
+ it "should set ENV['http_proxy'] with the password" do
288
+ @app.configure_proxy_environment_variables
289
+ @env['http_proxy'].should == "http://username:password@#{address}:#{port}"
290
+ end
291
+
292
+ context "when :http_proxy_pass contains '@' and/or ':'" do
293
+ before do
294
+ Chef::Config[:http_proxy_pass] = ":P@ssword101"
295
+ end
296
+
297
+ it "should set ENV['http_proxy'] with the escaped password" do
298
+ @app.configure_proxy_environment_variables
299
+ @env['http_proxy'].should == "http://username:%3AP%40ssword101@#{address}:#{port}"
300
+ end
301
+ end
302
+ end
303
+ end
304
+
305
+ describe "when Chef::Config[:http_proxy_pass] is set (but not Chef::Config[:http_proxy_user])" do
306
+ before do
307
+ Chef::Config[:http_proxy_user] = nil
308
+ Chef::Config[:http_proxy_pass] = "password"
309
+ end
310
+
311
+ it "should set ENV['http_proxy']" do
312
+ @app.configure_proxy_environment_variables
313
+ @env['http_proxy'].should == "http://#{address}:#{port}"
314
+ end
315
+ end
316
+ end
317
+
318
+ describe "when configuring ENV['http_proxy']" do
319
+ before do
320
+ @env = {}
321
+ @app.stub(:env).and_return(@env)
322
+
323
+ @app.stub(:configure_https_proxy).and_return(true)
324
+ @app.stub(:configure_ftp_proxy).and_return(true)
325
+ @app.stub(:configure_no_proxy).and_return(true)
326
+ end
327
+
328
+ describe "when Chef::Config[:http_proxy] is not set" do
329
+ before do
330
+ Chef::Config[:http_proxy] = nil
331
+ end
332
+
333
+ it "should not set ENV['http_proxy']" do
334
+ @app.configure_proxy_environment_variables
335
+ @env.should == {}
336
+ end
337
+ end
338
+
339
+ describe "when Chef::Config[:http_proxy] is set" do
340
+ context "when given an FQDN" do
341
+ let(:address) { "proxy.example.org" }
342
+ let(:port) { 8080 }
343
+ let(:http_proxy) { "http://#{address}:#{port}" }
344
+
345
+ it_should_behave_like "setting ENV['http_proxy']"
346
+ end
347
+
348
+ context "when given an IP" do
349
+ let(:address) { "127.0.0.1" }
350
+ let(:port) { 22 }
351
+ let(:http_proxy) { "http://#{address}:#{port}" }
352
+
353
+ it_should_behave_like "setting ENV['http_proxy']"
354
+ end
355
+
356
+ context "when given an IPv6" do
357
+ let(:address) { "[2001:db8::1]" }
358
+ let(:port) { 80 }
359
+ let(:http_proxy) { "http://#{address}:#{port}" }
360
+
361
+ it_should_behave_like "setting ENV['http_proxy']"
362
+ end
363
+
364
+ context "when given without including http://" do
365
+ let(:address) { "proxy.example.org" }
366
+ let(:port) { 8181 }
367
+ let(:http_proxy) { "#{address}:#{port}" }
368
+
369
+ it_should_behave_like "setting ENV['http_proxy']"
370
+ end
371
+
372
+ context "when given the full proxy in :http_proxy only" do
373
+ before do
374
+ Chef::Config[:http_proxy] = "http://username:password@proxy.example.org:2222"
375
+ Chef::Config[:http_proxy_user] = nil
376
+ Chef::Config[:http_proxy_pass] = nil
377
+ end
378
+
379
+ it "should set ENV['http_proxy']" do
380
+ @app.configure_proxy_environment_variables
381
+ @env['http_proxy'].should == Chef::Config[:http_proxy]
382
+ end
383
+ end
384
+
385
+ context "when the config options aren't URI compliant" do
386
+ it "raises Chef::Exceptions::BadProxyURI" do
387
+ Chef::Config[:http_proxy] = "http://proxy.bad_example.org/:8080"
388
+ expect { @app.configure_proxy_environment_variables }.to raise_error(Chef::Exceptions::BadProxyURI)
389
+ end
390
+ end
391
+ end
392
+ end
393
+ end
394
+
238
395
  describe "class method: fatal!" do
239
396
  before do
240
397
  STDERR.stub(:puts).with("FATAL: blah").and_return(true)