chef 12.1.2 → 12.2.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/lib/chef/application/client.rb +2 -2
  3. data/lib/chef/audit/audit_reporter.rb +1 -1
  4. data/lib/chef/audit/runner.rb +15 -2
  5. data/lib/chef/client.rb +1 -1
  6. data/lib/chef/config.rb +6 -4
  7. data/lib/chef/dsl/powershell.rb +29 -0
  8. data/lib/chef/exceptions.rb +18 -3
  9. data/lib/chef/formatters/doc.rb +2 -2
  10. data/lib/chef/knife/bootstrap.rb +2 -1
  11. data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
  12. data/lib/chef/knife/core/subcommand_loader.rb +13 -5
  13. data/lib/chef/knife/exec.rb +2 -1
  14. data/lib/chef/knife/ssh.rb +12 -2
  15. data/lib/chef/mixin/params_validate.rb +42 -19
  16. data/lib/chef/mixin/powershell_type_coercions.rb +82 -0
  17. data/lib/chef/mixin/windows_architecture_helper.rb +8 -0
  18. data/lib/chef/node.rb +1 -1
  19. data/lib/chef/platform/provider_mapping.rb +0 -107
  20. data/lib/chef/platform/query_helpers.rb +7 -0
  21. data/lib/chef/provider/batch.rb +2 -0
  22. data/lib/chef/provider/cron.rb +2 -0
  23. data/lib/chef/provider/cron/aix.rb +2 -0
  24. data/lib/chef/provider/cron/unix.rb +2 -0
  25. data/lib/chef/provider/deploy.rb +104 -87
  26. data/lib/chef/provider/dsc_resource.rb +157 -0
  27. data/lib/chef/provider/env.rb +2 -0
  28. data/lib/chef/provider/env/windows.rb +2 -0
  29. data/lib/chef/provider/git.rb +4 -0
  30. data/lib/chef/provider/group.rb +5 -5
  31. data/lib/chef/provider/group/dscl.rb +2 -0
  32. data/lib/chef/provider/group/groupmod.rb +2 -0
  33. data/lib/chef/provider/group/usermod.rb +2 -0
  34. data/lib/chef/provider/group/windows.rb +2 -0
  35. data/lib/chef/provider/mdadm.rb +2 -0
  36. data/lib/chef/provider/mount/windows.rb +2 -0
  37. data/lib/chef/provider/package/homebrew.rb +1 -1
  38. data/lib/chef/provider/package/openbsd.rb +49 -18
  39. data/lib/chef/provider/package/rubygems.rb +7 -2
  40. data/lib/chef/provider/powershell_script.rb +2 -0
  41. data/lib/chef/provider/service/macosx.rb +1 -2
  42. data/lib/chef/provider/user/dscl.rb +7 -1
  43. data/lib/chef/provider/user/windows.rb +2 -0
  44. data/lib/chef/providers.rb +1 -0
  45. data/lib/chef/recipe.rb +2 -0
  46. data/lib/chef/resource.rb +9 -0
  47. data/lib/chef/resource/batch.rb +2 -0
  48. data/lib/chef/resource/cron.rb +3 -3
  49. data/lib/chef/resource/deploy.rb +52 -217
  50. data/lib/chef/resource/dsc_resource.rb +83 -0
  51. data/lib/chef/resource/env.rb +2 -0
  52. data/lib/chef/resource/git.rb +1 -1
  53. data/lib/chef/resource/group.rb +2 -0
  54. data/lib/chef/resource/homebrew_package.rb +1 -1
  55. data/lib/chef/resource/lwrp_base.rb +0 -8
  56. data/lib/chef/resource/mdadm.rb +2 -0
  57. data/lib/chef/resource/mount.rb +2 -0
  58. data/lib/chef/resource/powershell_script.rb +2 -0
  59. data/lib/chef/resource/user.rb +2 -0
  60. data/lib/chef/resources.rb +1 -0
  61. data/lib/chef/run_context.rb +1 -1
  62. data/lib/chef/shell.rb +7 -5
  63. data/lib/chef/util/dsc/resource_store.rb +110 -0
  64. data/lib/chef/util/path_helper.rb +76 -0
  65. data/lib/chef/util/powershell/cmdlet.rb +41 -7
  66. data/lib/chef/util/powershell/cmdlet_result.rb +18 -3
  67. data/lib/chef/util/powershell/ps_credential.rb +38 -0
  68. data/lib/chef/version.rb +1 -1
  69. data/lib/chef/win32/api.rb +2 -0
  70. data/lib/chef/win32/api/crypto.rb +63 -0
  71. data/lib/chef/win32/api/installer.rb +1 -1
  72. data/lib/chef/win32/crypto.rb +49 -0
  73. data/lib/chef/workstation_config_loader.rb +4 -3
  74. data/spec/functional/file_content_management/deploy_strategies_spec.rb +1 -1
  75. data/spec/functional/resource/cookbook_file_spec.rb +1 -1
  76. data/spec/functional/resource/deploy_revision_spec.rb +35 -0
  77. data/spec/functional/resource/directory_spec.rb +1 -1
  78. data/spec/functional/resource/dsc_resource_spec.rb +93 -0
  79. data/spec/functional/resource/env_spec.rb +4 -3
  80. data/spec/functional/resource/file_spec.rb +1 -1
  81. data/spec/functional/resource/powershell_spec.rb +2 -1
  82. data/spec/functional/resource/remote_directory_spec.rb +1 -1
  83. data/spec/functional/resource/remote_file_spec.rb +1 -1
  84. data/spec/functional/resource/template_spec.rb +1 -1
  85. data/spec/functional/resource/user/dscl_spec.rb +1 -2
  86. data/spec/functional/resource/user/useradd_spec.rb +27 -13
  87. data/spec/functional/util/powershell/cmdlet_spec.rb +3 -3
  88. data/spec/functional/win32/crypto_spec.rb +57 -0
  89. data/spec/spec_helper.rb +3 -0
  90. data/spec/support/platform_helpers.rb +14 -0
  91. data/spec/support/shared/functional/securable_resource_with_reporting.rb +5 -5
  92. data/spec/unit/application/client_spec.rb +4 -4
  93. data/spec/unit/audit/audit_reporter_spec.rb +1 -1
  94. data/spec/unit/audit/runner_spec.rb +10 -0
  95. data/spec/unit/config_spec.rb +2 -8
  96. data/spec/unit/knife/bootstrap_spec.rb +20 -8
  97. data/spec/unit/knife/core/subcommand_loader_spec.rb +29 -29
  98. data/spec/unit/mixin/params_validate_spec.rb +75 -61
  99. data/spec/unit/mixin/powershell_type_coercions_spec.rb +72 -0
  100. data/spec/unit/platform/query_helpers_spec.rb +22 -0
  101. data/spec/unit/platform_spec.rb +0 -5
  102. data/spec/unit/provider/dsc_resource_spec.rb +84 -0
  103. data/spec/unit/provider/package/openbsd_spec.rb +105 -17
  104. data/spec/unit/provider/service/macosx_spec.rb +3 -3
  105. data/spec/unit/provider_resolver_spec.rb +132 -0
  106. data/spec/unit/recipe_spec.rb +4 -0
  107. data/spec/unit/resource/deploy_spec.rb +27 -0
  108. data/spec/unit/resource/dsc_resource_spec.rb +85 -0
  109. data/spec/unit/shell_spec.rb +1 -1
  110. data/spec/unit/util/dsc/resource_store.rb +76 -0
  111. data/spec/unit/util/powershell/ps_credential_spec.rb +37 -0
  112. data/spec/unit/workstation_config_loader_spec.rb +1 -1
  113. metadata +159 -186
@@ -22,7 +22,7 @@ describe Chef::Resource::RemoteDirectory do
22
22
  include_context Chef::Resource::Directory
23
23
 
24
24
  let(:directory_base) { "directory_spec" }
25
- let(:default_mode) { ((0100777 - File.umask) & 07777).to_s(8) }
25
+ let(:default_mode) { (0777 & ~File.umask).to_s(8) }
26
26
 
27
27
  def create_resource
28
28
  cookbook_repo = File.expand_path(File.join(CHEF_SPEC_DATA, "cookbooks"))
@@ -52,7 +52,7 @@ describe Chef::Resource::RemoteFile do
52
52
  create_resource
53
53
  end
54
54
 
55
- let(:default_mode) { ((0100666 - File.umask) & 07777).to_s(8) }
55
+ let(:default_mode) { (0666 & ~File.umask).to_s(8) }
56
56
 
57
57
  context "when fetching files over HTTP" do
58
58
  before(:all) do
@@ -58,7 +58,7 @@ describe Chef::Resource::Template do
58
58
  create_resource
59
59
  end
60
60
 
61
- let(:default_mode) { ((0100666 - File.umask) & 07777).to_s(8) }
61
+ let(:default_mode) { (0666 & ~File.umask).to_s(8) }
62
62
 
63
63
  it_behaves_like "a file resource"
64
64
 
@@ -19,9 +19,8 @@ require 'spec_helper'
19
19
  require 'chef/mixin/shell_out'
20
20
 
21
21
  metadata = {
22
- :unix_only => true,
22
+ :mac_osx_only => true,
23
23
  :requires_root => true,
24
- :provider => {:user => Chef::Provider::User::Dscl},
25
24
  :not_supported_on_mac_osx_106 => true,
26
25
  }
27
26
 
@@ -32,6 +32,7 @@ end
32
32
 
33
33
  metadata = { :unix_only => true,
34
34
  :requires_root => true,
35
+ :not_supported_on_mac_osx => true,
35
36
  :provider => {:user => user_provider_for_platform}
36
37
  }
37
38
 
@@ -76,9 +77,22 @@ describe Chef::Provider::User::Useradd, metadata do
76
77
  end
77
78
  end
78
79
 
80
+ def try_cleanup
81
+ ['/home/cheftestfoo', '/home/cheftestbar'].each do |f|
82
+ FileUtils.rm_rf(f) if File.exists? f
83
+ end
84
+
85
+ ['cf-test'].each do |u|
86
+ r = Chef::Resource::User.new("DELETE USER", run_context)
87
+ r.username('cf-test')
88
+ r.run_action(:remove)
89
+ end
90
+ end
91
+
79
92
  before do
80
93
  # Silence shell_out live stream
81
94
  Chef::Log.level = :warn
95
+ try_cleanup
82
96
  end
83
97
 
84
98
  after do
@@ -386,18 +400,18 @@ describe Chef::Provider::User::Useradd, metadata do
386
400
  end
387
401
 
388
402
  context "and home directory is updated" do
389
- let(:existing_home) { "/home/foo" }
390
- let(:home) { "/home/bar" }
403
+ let(:existing_home) { "/home/cheftestfoo" }
404
+ let(:home) { "/home/cheftestbar" }
391
405
  it "ensures the home directory is set to the desired value" do
392
- expect(pw_entry.home).to eq("/home/bar")
406
+ expect(pw_entry.home).to eq("/home/cheftestbar")
393
407
  end
394
408
 
395
409
  context "and manage_home is enabled" do
396
410
  let(:existing_manage_home) { true }
397
411
  let(:manage_home) { true }
398
412
  it "moves the home directory to the new location" do
399
- expect(File).not_to exist("/home/foo")
400
- expect(File).to exist("/home/bar")
413
+ expect(File).not_to exist("/home/cheftestfoo")
414
+ expect(File).to exist("/home/cheftestbar")
401
415
  end
402
416
  end
403
417
 
@@ -409,19 +423,19 @@ describe Chef::Provider::User::Useradd, metadata do
409
423
  # Inconsistent behavior. See: CHEF-2205
410
424
  it "created the home dir b/c of CHEF-2205 so it still exists" do
411
425
  # This behavior seems contrary to expectation and non-convergent.
412
- expect(File).not_to exist("/home/foo")
413
- expect(File).to exist("/home/bar")
426
+ expect(File).not_to exist("/home/cheftestfoo")
427
+ expect(File).to exist("/home/cheftestbar")
414
428
  end
415
429
  elsif ohai[:platform] == "aix"
416
430
  it "creates the home dir in the desired location" do
417
- expect(File).not_to exist("/home/foo")
418
- expect(File).to exist("/home/bar")
431
+ expect(File).not_to exist("/home/cheftestfoo")
432
+ expect(File).to exist("/home/cheftestbar")
419
433
  end
420
434
  else
421
435
  it "does not create the home dir in the desired location (XXX)" do
422
436
  # This behavior seems contrary to expectation and non-convergent.
423
- expect(File).not_to exist("/home/foo")
424
- expect(File).not_to exist("/home/bar")
437
+ expect(File).not_to exist("/home/cheftestfoo")
438
+ expect(File).not_to exist("/home/cheftestbar")
425
439
  end
426
440
  end
427
441
  end
@@ -432,8 +446,8 @@ describe Chef::Provider::User::Useradd, metadata do
432
446
 
433
447
  it "leaves the old home directory around (XXX)" do
434
448
  # Would it be better to remove the old home?
435
- expect(File).to exist("/home/foo")
436
- expect(File).not_to exist("/home/bar")
449
+ expect(File).to exist("/home/cheftestfoo")
450
+ expect(File).not_to exist("/home/cheftestbar")
437
451
  end
438
452
  end
439
453
  end
@@ -19,7 +19,7 @@
19
19
  require 'chef/json_compat'
20
20
  require File.expand_path('../../../../spec_helper', __FILE__)
21
21
 
22
- describe Chef::Util::Powershell::Cmdlet, :windows_only do
22
+ describe Chef::Util::Powershell::Cmdlet, :windows_powershell_dsc_only do
23
23
  before(:all) do
24
24
  ohai = Ohai::System.new
25
25
  ohai.load_plugins
@@ -88,7 +88,7 @@ describe Chef::Util::Powershell::Cmdlet, :windows_only do
88
88
 
89
89
  context "when returning json" do
90
90
  let(:cmd_output_format) { :json }
91
- it "returns json format data", :windows_powershell_dsc_only do
91
+ it "returns json format data" do
92
92
  result = cmdlet_alias_requires_switch_or_argument.run({},{},'ls')
93
93
  expect(result.succeeded?).to eq(true)
94
94
  expect(lambda{Chef::JSONCompat.parse(result.return_value)}).not_to raise_error
@@ -97,7 +97,7 @@ describe Chef::Util::Powershell::Cmdlet, :windows_only do
97
97
 
98
98
  context "when returning Ruby objects" do
99
99
  let(:cmd_output_format) { :object }
100
- it "returns object format data", :windows_powershell_dsc_only do
100
+ it "returns object format data" do
101
101
  result = simple_cmdlet.run({},{:cwd => etc_directory}, 'hosts')
102
102
  expect(result.succeeded?).to eq(true)
103
103
  data = result.return_value
@@ -0,0 +1,57 @@
1
+ #
2
+ # Author:: Jay Mundrawala(<jdm@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
+ require 'spec_helper'
20
+ if Chef::Platform.windows?
21
+ require 'chef/win32/crypto'
22
+ end
23
+
24
+ describe 'Chef::ReservedNames::Win32::Crypto', :windows_only do
25
+ describe '#encrypt' do
26
+ before(:all) do
27
+ ohai_reader = Ohai::System.new
28
+ ohai_reader.all_plugins("platform")
29
+
30
+ new_node = Chef::Node.new
31
+ new_node.consume_external_attrs(ohai_reader.data,{})
32
+
33
+ events = Chef::EventDispatch::Dispatcher.new
34
+
35
+ @run_context = Chef::RunContext.new(new_node, {}, events)
36
+ end
37
+
38
+ let (:plaintext) { 'p@assword' }
39
+
40
+ it 'can be decrypted by powershell' do
41
+ encrypted = Chef::ReservedNames::Win32::Crypto.encrypt(plaintext)
42
+ resource = Chef::Resource::WindowsScript::PowershellScript.new("Powershell resource functional test", @run_context)
43
+ resource.code <<-EOF
44
+ $encrypted = '#{encrypted}' | ConvertTo-SecureString
45
+ $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($encrypted)
46
+ $plaintext = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
47
+ if ($plaintext -ne '#{plaintext}') {
48
+ Write-Error 'Got: ' $plaintext
49
+ exit 1
50
+ }
51
+ exit 0
52
+ EOF
53
+ resource.returns(0)
54
+ resource.run_action(:run)
55
+ end
56
+ end
57
+ end
@@ -110,10 +110,13 @@ RSpec.configure do |config|
110
110
  # Tests that randomly fail, but may have value.
111
111
  config.filter_run_excluding :volatile => true
112
112
  config.filter_run_excluding :volatile_on_solaris => true if solaris?
113
+ config.filter_run_excluding :volatile_from_verify => false
113
114
 
114
115
  # Add jruby filters here
115
116
  config.filter_run_excluding :windows_only => true unless windows?
116
117
  config.filter_run_excluding :not_supported_on_mac_osx_106 => true if mac_osx_106?
118
+ config.filter_run_excluding :not_supported_on_mac_osx=> true if mac_osx?
119
+ config.filter_run_excluding :mac_osx_only=> true if !mac_osx?
117
120
  config.filter_run_excluding :not_supported_on_win2k3 => true if windows_win2k3?
118
121
  config.filter_run_excluding :not_supported_on_solaris => true if solaris?
119
122
  config.filter_run_excluding :win2k3_only => true unless windows_win2k3?
@@ -88,6 +88,20 @@ def mac_osx_106?
88
88
  false
89
89
  end
90
90
 
91
+ def mac_osx?
92
+ if File.exists? "/usr/bin/sw_vers"
93
+ result = ShellHelpers.shell_out("/usr/bin/sw_vers")
94
+ result.stdout.each_line do |line|
95
+ if line =~ /^ProductName:\sMac OS X.*$/
96
+ return true
97
+ end
98
+ end
99
+ end
100
+
101
+ false
102
+ end
103
+
104
+
91
105
  # detects if the hardware is 64-bit (evaluates to true in "WOW64" mode in a 32-bit app on a 64-bit system)
92
106
  def windows64?
93
107
  windows? && ( ENV['PROCESSOR_ARCHITECTURE'] == 'AMD64' || ENV['PROCESSOR_ARCHITEW6432'] == 'AMD64' )
@@ -35,7 +35,7 @@ shared_examples_for "a securable resource with reporting" do
35
35
  # Default mode varies based on implementation. Providers that use a tempfile
36
36
  # will default to 0600. Providers that use File.open will default to 0666 -
37
37
  # umask
38
- # let(:default_mode) { ((0100666 - File.umask) & 07777).to_s(8) }
38
+ # let(:default_mode) { (0666 & ~File.umask).to_s(8) }
39
39
 
40
40
  describe "reading file security metadata for reporting on unix", :unix_only => true do
41
41
  # According to POSIX standard created files get either the
@@ -185,7 +185,7 @@ shared_examples_for "a securable resource with reporting" do
185
185
  # TODO: most stable way to specify?
186
186
  expect(current_resource.owner).to eq(Etc.getpwuid(Process.uid).name)
187
187
  expect(current_resource.group).to eq(@expected_group_name)
188
- expect(current_resource.mode).to eq("0#{((0100666 - File.umask) & 07777).to_s(8)}")
188
+ expect(current_resource.mode).to eq("0#{(0666 & ~File.umask).to_s(8)}")
189
189
  end
190
190
  end
191
191
 
@@ -239,8 +239,8 @@ shared_examples_for "a securable resource with reporting" do
239
239
  end
240
240
 
241
241
  context "and mode is specified as a String" do
242
- let(:default_create_mode) { (0100666 - File.umask) }
243
- let(:expected_mode) { "0#{(default_create_mode & 07777).to_s(8)}" }
242
+ let(:default_create_mode) { 0666 & ~File.umask }
243
+ let(:expected_mode) { "0#{default_create_mode.to_s(8)}" }
244
244
 
245
245
  before do
246
246
  resource.mode(expected_mode)
@@ -252,7 +252,7 @@ shared_examples_for "a securable resource with reporting" do
252
252
  end
253
253
 
254
254
  context "and mode is specified as an Integer" do
255
- let(:set_mode) { (0100666 - File.umask) & 07777 }
255
+ let(:set_mode) { 0666 & ~File.umask }
256
256
  let(:expected_mode) { "0#{set_mode.to_s(8)}" }
257
257
 
258
258
  before do
@@ -305,7 +305,7 @@ describe Chef::Application::Client, "run_application", :unix_only do
305
305
  allow(Chef::Daemon).to receive(:daemonize).and_return(true)
306
306
  end
307
307
 
308
- it "should exit hard with exitstatus 3" do
308
+ it "should exit hard with exitstatus 3", :volatile do
309
309
  pid = fork do
310
310
  @app.run_application
311
311
  end
@@ -320,9 +320,9 @@ describe Chef::Application::Client, "run_application", :unix_only do
320
320
  end
321
321
  expect(@pipe[0].gets).to eq("started\n")
322
322
  Process.kill("TERM", pid)
323
- Process.wait
324
- sleep 1 # Make sure we give the converging child process enough time to finish
325
- expect(IO.select([@pipe[0]], nil, nil, 0)).not_to be_nil
323
+ Process.wait(pid)
324
+ # The timeout value needs to be large enough for the child process to finish
325
+ expect(IO.select([@pipe[0]], nil, nil, 15)).not_to be_nil
326
326
  expect(@pipe[0].gets).to eq("finished\n")
327
327
  end
328
328
  end
@@ -203,7 +203,7 @@ describe Chef::Audit::AuditReporter do
203
203
  it "doesn't send reports" do
204
204
  expect(reporter).to receive(:auditing_enabled?).and_return(true)
205
205
  expect(reporter).to receive(:run_status).and_return(nil)
206
- expect(Chef::Log).to receive(:debug).with("Run failed before audits were initialized, not sending audit report to server")
206
+ expect(Chef::Log).to receive(:debug).with("Run failed before audit mode was initialized, not sending audit report to server")
207
207
  reporter.run_completed(node)
208
208
  end
209
209
 
@@ -36,6 +36,15 @@ describe Chef::Audit::Runner do
36
36
  RSpec::Core::Sandbox.sandboxed { ex.run }
37
37
  end
38
38
 
39
+ context "when we run in audit mode" do
40
+ let(:paths) { [ "/opt/chef/lib/chef/", 'C:\windows/here/lib/chef/' , "/opt/chef/extra/folders/lib/chef/"] }
41
+ it "excludes the current path from backtrace" do
42
+ paths.each do |path|
43
+ expect(runner.exclusion_pattern).to match(path)
44
+ end
45
+ end
46
+ end
47
+
39
48
  describe "#initialize" do
40
49
  it "correctly sets the run_context during initialization" do
41
50
  expect(runner.instance_variable_get(:@run_context)).to eq(run_context)
@@ -72,6 +81,7 @@ describe Chef::Audit::Runner do
72
81
 
73
82
  expect(RSpec.configuration.color).to eq(color)
74
83
  expect(RSpec.configuration.expose_dsl_globally?).to eq(false)
84
+ expect(RSpec.configuration.backtrace_exclusion_patterns).to include(runner.exclusion_pattern)
75
85
 
76
86
  expect(Specinfra.configuration.backend).to eq(:exec)
77
87
  end
@@ -360,18 +360,12 @@ describe Chef::Config do
360
360
  describe "Chef::Config[:user_home]" do
361
361
  it "should set when HOME is provided" do
362
362
  expected = to_platform("/home/kitten")
363
- allow(Chef::Config).to receive(:env).and_return({ 'HOME' => expected })
364
- expect(Chef::Config[:user_home]).to eq(expected)
365
- end
366
-
367
- it "should be set when only USERPROFILE is provided" do
368
- expected = to_platform("/users/kitten")
369
- allow(Chef::Config).to receive(:env).and_return({ 'USERPROFILE' => expected })
363
+ allow(Chef::Util::PathHelper).to receive(:home).and_return(expected)
370
364
  expect(Chef::Config[:user_home]).to eq(expected)
371
365
  end
372
366
 
373
367
  it "falls back to the current working directory when HOME and USERPROFILE is not set" do
374
- allow(Chef::Config).to receive(:env).and_return({})
368
+ allow(Chef::Util::PathHelper).to receive(:home).and_return(nil)
375
369
  expect(Chef::Config[:user_home]).to eq(Dir.pwd)
376
370
  end
377
371
  end
@@ -115,7 +115,7 @@ describe Chef::Knife::Bootstrap do
115
115
  end
116
116
 
117
117
  def configure_env_home
118
- ENV['HOME'] = "/env/home"
118
+ allow(Chef::Util::PathHelper).to receive(:home).with(".chef", "bootstrap", "example.erb").and_yield(env_home_template_path)
119
119
  end
120
120
 
121
121
  def configure_gem_files
@@ -123,15 +123,9 @@ describe Chef::Knife::Bootstrap do
123
123
  end
124
124
 
125
125
  before(:each) do
126
- @original_home = ENV['HOME']
127
- ENV['HOME'] = nil
128
126
  expect(File).to receive(:exists?).with(bootstrap_template).and_return(false)
129
127
  end
130
128
 
131
- after(:each) do
132
- ENV['HOME'] = @original_home
133
- end
134
-
135
129
  context "when file is available everywhere" do
136
130
  before do
137
131
  configure_chef_config_dir
@@ -161,7 +155,7 @@ describe Chef::Knife::Bootstrap do
161
155
  end
162
156
  end
163
157
 
164
- context "when file is available in ENV['HOME']" do
158
+ context "when file is available in home directory" do
165
159
  before do
166
160
  configure_chef_config_dir
167
161
  configure_env_home
@@ -178,9 +172,27 @@ describe Chef::Knife::Bootstrap do
178
172
  end
179
173
 
180
174
  context "when file is available in Gem files" do
175
+ before do
176
+ configure_chef_config_dir
177
+ configure_env_home
178
+ configure_gem_files
179
+
180
+ expect(File).to receive(:exists?).with(builtin_template_path).and_return(false)
181
+ expect(File).to receive(:exists?).with(chef_config_dir_template_path).and_return(false)
182
+ expect(File).to receive(:exists?).with(env_home_template_path).and_return(false)
183
+ expect(File).to receive(:exists?).with(gem_files_template_path).and_return(true)
184
+ end
185
+
186
+ it "should load the template from Gem files" do
187
+ expect(knife.find_template).to eq(gem_files_template_path)
188
+ end
189
+ end
190
+
191
+ context "when file is available in Gem files and home dir doesn't exist" do
181
192
  before do
182
193
  configure_chef_config_dir
183
194
  configure_gem_files
195
+ allow(Chef::Util::PathHelper).to receive(:home).with(".chef", "bootstrap", "example.erb").and_return(nil)
184
196
 
185
197
  expect(File).to receive(:exists?).with(builtin_template_path).and_return(false)
186
198
  expect(File).to receive(:exists?).with(chef_config_dir_template_path).and_return(false)
@@ -19,23 +19,29 @@
19
19
  require 'spec_helper'
20
20
 
21
21
  describe Chef::Knife::SubcommandLoader do
22
+ let(:loader) { Chef::Knife::SubcommandLoader.new(File.join(CHEF_SPEC_DATA, 'knife-site-subcommands')) }
23
+ let(:home) { File.join(CHEF_SPEC_DATA, 'knife-home') }
24
+ let(:plugin_dir) { File.join(home, '.chef', 'plugins', 'knife') }
25
+
22
26
  before do
23
27
  allow(Chef::Platform).to receive(:windows?) { false }
24
- @home = File.join(CHEF_SPEC_DATA, 'knife-home')
25
- @env = {'HOME' => @home}
26
- @loader = Chef::Knife::SubcommandLoader.new(File.join(CHEF_SPEC_DATA, 'knife-site-subcommands'), @env)
28
+ Chef::Util::PathHelper.class_variable_set(:@@home_dir, home)
29
+ end
30
+
31
+ after do
32
+ Chef::Util::PathHelper.class_variable_set(:@@home_dir, nil)
27
33
  end
28
34
 
29
35
  it "builds a list of the core subcommand file require paths" do
30
- expect(@loader.subcommand_files).not_to be_empty
31
- @loader.subcommand_files.each do |require_path|
36
+ expect(loader.subcommand_files).not_to be_empty
37
+ loader.subcommand_files.each do |require_path|
32
38
  expect(require_path).to match(/chef\/knife\/.*|plugins\/knife\/.*/)
33
39
  end
34
40
  end
35
41
 
36
42
  it "finds files installed via rubygems" do
37
- expect(@loader.find_subcommands_via_rubygems).to include('chef/knife/node_create')
38
- @loader.find_subcommands_via_rubygems.each {|rel_path, abs_path| expect(abs_path).to match(%r[chef/knife/.+])}
43
+ expect(loader.find_subcommands_via_rubygems).to include('chef/knife/node_create')
44
+ loader.find_subcommands_via_rubygems.each {|rel_path, abs_path| expect(abs_path).to match(%r[chef/knife/.+])}
39
45
  end
40
46
 
41
47
  it "finds files from latest version of installed gems" do
@@ -54,23 +60,23 @@ describe Chef::Knife::SubcommandLoader do
54
60
  expect(gems[0]).to receive(:full_gem_path).and_return('/usr/lib/ruby/gems/knife-ec2-0.5.12')
55
61
  expect(Dir).to receive(:[]).with('/usr/lib/ruby/gems/knife-ec2-0.5.12/lib/chef/knife/*.rb').and_return(gem_files)
56
62
  end
57
- expect(@loader).to receive(:find_subcommands_via_dirglob).and_return({})
58
- expect(@loader.find_subcommands_via_rubygems.values.select { |file| file =~ /knife-ec2/ }.sort).to eq(gem_files)
63
+ expect(loader).to receive(:find_subcommands_via_dirglob).and_return({})
64
+ expect(loader.find_subcommands_via_rubygems.values.select { |file| file =~ /knife-ec2/ }.sort).to eq(gem_files)
59
65
  end
60
66
 
61
67
  it "finds files using a dirglob when rubygems is not available" do
62
- expect(@loader.find_subcommands_via_dirglob).to include('chef/knife/node_create')
63
- @loader.find_subcommands_via_dirglob.each {|rel_path, abs_path| expect(abs_path).to match(%r[chef/knife/.+])}
68
+ expect(loader.find_subcommands_via_dirglob).to include('chef/knife/node_create')
69
+ loader.find_subcommands_via_dirglob.each {|rel_path, abs_path| expect(abs_path).to match(%r[chef/knife/.+])}
64
70
  end
65
71
 
66
72
  it "finds user-specific subcommands in the user's ~/.chef directory" do
67
- expected_command = File.join(@home, '.chef', 'plugins', 'knife', 'example_home_subcommand.rb')
68
- expect(@loader.site_subcommands).to include(expected_command)
73
+ expected_command = File.join(home, '.chef', 'plugins', 'knife', 'example_home_subcommand.rb')
74
+ expect(loader.site_subcommands).to include(expected_command)
69
75
  end
70
76
 
71
77
  it "finds repo specific subcommands by searching for a .chef directory" do
72
78
  expected_command = File.join(CHEF_SPEC_DATA, 'knife-site-subcommands', 'plugins', 'knife', 'example_subcommand.rb')
73
- expect(@loader.site_subcommands).to include(expected_command)
79
+ expect(loader.site_subcommands).to include(expected_command)
74
80
  end
75
81
 
76
82
  # https://github.com/opscode/chef-dk/issues/227
@@ -137,25 +143,19 @@ describe Chef::Knife::SubcommandLoader do
137
143
  end
138
144
 
139
145
  before do
140
- expect(@loader).to receive(:find_files_latest_gems).with("chef/knife/*.rb").and_return(all_found_commands)
141
- expect(@loader).to receive(:find_subcommands_via_dirglob).and_return({})
146
+ expect(loader).to receive(:find_files_latest_gems).with("chef/knife/*.rb").and_return(all_found_commands)
147
+ expect(loader).to receive(:find_subcommands_via_dirglob).and_return({})
142
148
  end
143
149
 
144
150
  it "ignores commands from the non-matching gem install" do
145
- expect(@loader.find_subcommands_via_rubygems.values).to eq(expected_valid_commands)
151
+ expect(loader.find_subcommands_via_rubygems.values).to eq(expected_valid_commands)
146
152
  end
147
153
 
148
154
  end
149
155
 
150
156
  describe "finding 3rd party plugins" do
151
- let(:env_home) { "/home/alice" }
152
- let(:manifest_path) { env_home + "/.chef/plugin_manifest.json" }
153
-
154
- before do
155
- env_dup = ENV.to_hash
156
- allow(ENV).to receive(:[]) { |key| env_dup[key] }
157
- allow(ENV).to receive(:[]).with("HOME").and_return(env_home)
158
- end
157
+ let(:home) { "/home/alice" }
158
+ let(:manifest_path) { home + "/.chef/plugin_manifest.json" }
159
159
 
160
160
  context "when there is not a ~/.chef/plugin_manifest.json file" do
161
161
  before do
@@ -168,14 +168,14 @@ describe Chef::Knife::SubcommandLoader do
168
168
  else
169
169
  expect(Gem.source_index).to receive(:latest_specs).and_call_original
170
170
  end
171
- @loader.subcommand_files.each do |require_path|
171
+ loader.subcommand_files.each do |require_path|
172
172
  expect(require_path).to match(/chef\/knife\/.*|plugins\/knife\/.*/)
173
173
  end
174
174
  end
175
175
 
176
176
  context "and HOME environment variable is not set" do
177
177
  before do
178
- allow(ENV).to receive(:[]).with("HOME").and_return(nil)
178
+ allow(Chef::Util::PathHelper).to receive(:home).and_return(nil)
179
179
  end
180
180
 
181
181
  it "searches rubygems for plugins" do
@@ -184,7 +184,7 @@ describe Chef::Knife::SubcommandLoader do
184
184
  else
185
185
  expect(Gem.source_index).to receive(:latest_specs).and_call_original
186
186
  end
187
- @loader.subcommand_files.each do |require_path|
187
+ loader.subcommand_files.each do |require_path|
188
188
  expect(require_path).to match(/chef\/knife\/.*|plugins\/knife\/.*/)
189
189
  end
190
190
  end
@@ -215,7 +215,7 @@ describe Chef::Knife::SubcommandLoader do
215
215
 
216
216
  it "uses paths from the manifest instead of searching gems" do
217
217
  expect(Gem::Specification).not_to receive(:latest_specs).and_call_original
218
- expect(@loader.subcommand_files).to include(ec2_server_create_plugin)
218
+ expect(loader.subcommand_files).to include(ec2_server_create_plugin)
219
219
  end
220
220
 
221
221
  end