chef-apply 0.2.8 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,63 @@
1
+
2
+
3
+ module ChefApply
4
+ class TargetHost
5
+ module Linux
6
+ def omnibus_manifest_path
7
+ # TODO - if habitat install on target, this won't work
8
+ # Note that we can't use File::Join, because that will render for the
9
+ # CURRENT platform - not the platform of the target.
10
+ "/opt/chef/version-manifest.json"
11
+ end
12
+
13
+ def mkdir(path)
14
+ run_command!("mkdir -p #{path}")
15
+ end
16
+
17
+ def chown(path, owner)
18
+ owner ||= user()
19
+ run_command!("chown #{owner} '#{path}'")
20
+ nil
21
+ end
22
+
23
+ def make_temp_dir
24
+ # We will cache this so that we only
25
+ @tempdir ||= begin
26
+ res = run_command!("bash -c '#{MKTEMP_COMMAND}'")
27
+ res.stdout.chomp.strip
28
+ end
29
+ end
30
+
31
+ def install_package(target_package_path)
32
+ install_cmd = case File.extname(target_package_path)
33
+ when ".rpm"
34
+ "rpm -Uvh #{target_package_path}"
35
+ when ".deb"
36
+ "dpkg -i #{target_package_path}"
37
+ end
38
+ run_command!(install_cmd)
39
+ nil
40
+ end
41
+
42
+ def del_file(path)
43
+ run_command!("rm -rf #{path}")
44
+ end
45
+
46
+ def del_dir(path)
47
+ del_file(path)
48
+ end
49
+
50
+ def ws_cache_path
51
+ "/var/chef-workstation"
52
+ end
53
+
54
+ # Nothing to escape in a linux-based path
55
+ def normalize_path(path)
56
+ path
57
+ end
58
+
59
+ MKTEMP_COMMAND = "d=$(mktemp -d -p${TMPDIR:-/tmp} chef_XXXXXX); echo $d".freeze
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,62 @@
1
+
2
+ module ChefApply
3
+ class TargetHost
4
+ module Windows
5
+ def omnibus_manifest_path
6
+ # TODO - use a proper method to query the win installation path -
7
+ # currently we're assuming the default, but this can be customized
8
+ # at install time.
9
+ # A working approach is below - but it runs very slowly (~10s) in testing
10
+ # on a virtualbox windows vm:
11
+ # (over winrm) Get-WmiObject Win32_Product | Where {$_.Name -match 'Chef Client'}
12
+ # TODO - if habitat install on target, this won't work
13
+ "c:\\opscode\\chef\\version-manifest.json"
14
+ end
15
+
16
+ def mkdir(path)
17
+ run_command!("New-Item -ItemType Directory -Force -Path #{path}")
18
+ end
19
+
20
+ def chown(path, owner)
21
+ # This implementation left intentionally blank.
22
+ # To date, we have not needed chown functionality on windows;
23
+ # when/if that changes we'll need to implement it here.
24
+ nil
25
+ end
26
+
27
+ def make_temp_dir
28
+ @tmpdir ||= begin
29
+ res = run_command!(MKTEMP_COMMAND)
30
+ res.stdout.chomp.strip
31
+ end
32
+ end
33
+
34
+ def install_package(target_package_path)
35
+ # While powershell does not mind the mixed path separators \ and /,
36
+ # 'cmd.exe' definitely does - so we'll make the path cmd-friendly
37
+ # before running the command
38
+ cmd = "cmd /c msiexec /package #{target_package_path.tr("/", "\\")} /quiet"
39
+ run_command!(cmd)
40
+ nil
41
+ end
42
+
43
+ def del_file(path)
44
+ run_command!("If (Test-Path #{path}) { Remove-Item -Force -Path #{path} }")
45
+ end
46
+
47
+ def del_dir(path)
48
+ run_command!("Remove-Item -Recurse -Force –Path #{path}")
49
+ end
50
+
51
+ def ws_cache_path
52
+ '#{ENV[\'APPDATA\']}/chef-workstation'
53
+ end
54
+
55
+ MKTEMP_COMMAND = "$parent = [System.IO.Path]::GetTempPath();" +
56
+ "[string] $name = [System.Guid]::NewGuid();" +
57
+ "$tmp = New-Item -ItemType Directory -Path " +
58
+ "(Join-Path $parent $name);" +
59
+ "$tmp.FullName".freeze
60
+ end
61
+ end
62
+ end
@@ -16,5 +16,5 @@
16
16
  #
17
17
 
18
18
  module ChefApply
19
- VERSION = "0.2.8".freeze
19
+ VERSION = "0.2.13".freeze
20
20
  end
@@ -40,6 +40,7 @@ ARGUMENTS:
40
40
  you to specify which recipe to use from the cookbook.
41
41
 
42
42
  FLAGS:
43
+ --chef-license ACCEPTANCE Accept the license for this product and any contained products ('accept', 'accept-no-persist', or 'accept-silent')
43
44
  -c, --config PATH Location of config file. Default: $HOME/.chef-workstation/config.toml
44
45
  --cookbook-repo-paths PATH Comma separated list of cookbook repository paths.
45
46
  -h, --help Show help and usage for `chef-run`
@@ -56,34 +56,4 @@ RSpec.describe ChefApply::Action::Base do
56
56
  end
57
57
  end
58
58
 
59
- shared_examples "check path fetching" do
60
- [:chef_client, :cache_path, :read_chef_report, :delete_chef_report, :tempdir, :delete_folder].each do |path|
61
- it "correctly returns path #{path}" do
62
- expect(action.send(path)).to be_a(String)
63
- end
64
- end
65
- end
66
-
67
- describe "when connecting to a windows target" do
68
- include_examples "check path fetching"
69
-
70
- it "correctly returns chef run string" do
71
- expect(action.run_chef("a", "b", "c")).to eq(
72
- "Set-Location -Path a; " \
73
- "chef-client -z --config #{File.join("a", "b")} --recipe-url #{File.join("a", "c")} | Out-Null; " \
74
- "Set-Location C:/; " \
75
- "exit $LASTEXITCODE"
76
- )
77
- end
78
- end
79
-
80
- describe "when connecting to a non-windows target" do
81
- let(:family) { "linux" }
82
- include_examples "check path fetching"
83
-
84
- it "correctly returns chef run string" do
85
- expect(action.run_chef("a", "b", "c")).to eq("bash -c 'cd a; chef-client -z --config a/b --recipe-url a/c'")
86
- end
87
- end
88
-
89
59
  end
@@ -23,30 +23,33 @@ require "chef_apply/temp_cookbook"
23
23
 
24
24
  RSpec.describe ChefApply::Action::ConvergeTarget do
25
25
  let(:archive) { "archive.tgz" }
26
+ let(:cache_path) { "/var/chef-workstation" }
27
+ let(:platform_family) { "windows" }
28
+ let(:base_os) { :windows }
26
29
  let(:target_host) do
27
- p = double("platform", family: "windows")
28
- instance_double(ChefApply::TargetHost, platform: p)
30
+ p = double("platform", family: platform_family)
31
+ double(ChefApply::TargetHost,
32
+ platform: p, base_os: base_os, ws_cache_path: cache_path)
29
33
  end
30
34
  let(:local_policy_path) { "/local/policy/path/archive.tgz" }
31
35
  let(:opts) { { target_host: target_host, local_policy_path: local_policy_path } }
32
- subject(:action) { ChefApply::Action::ConvergeTarget.new(opts) }
36
+ subject { ChefApply::Action::ConvergeTarget.new(opts) }
33
37
 
38
+ before do
39
+ allow(target_host).to receive(:normalize_path) { |arg| arg }
40
+ end
34
41
  describe "#create_remote_policy" do
35
- let(:remote_folder) { "/tmp/foo" }
36
- let(:remote_archive) { File.join(remote_folder, File.basename(archive)) }
37
-
38
- before do
39
- end
42
+ let(:remote_archive) { File.join(cache_path, File.basename(archive)) }
40
43
 
41
44
  it "pushes it to the remote machine" do
42
45
  expect(target_host).to receive(:upload_file).with(local_policy_path, remote_archive)
43
- expect(subject.create_remote_policy(local_policy_path, remote_folder)).to eq(remote_archive)
46
+ expect(subject.create_remote_policy(local_policy_path, cache_path)).to eq(remote_archive)
44
47
  end
45
48
 
46
49
  it "raises an error if the upload fails" do
47
50
  expect(target_host).to receive(:upload_file).with(local_policy_path, remote_archive).and_raise("foo")
48
51
  err = ChefApply::Action::ConvergeTarget::PolicyUploadFailed
49
- expect { subject.create_remote_policy(local_policy_path, remote_folder) }.to raise_error(err)
52
+ expect { subject.create_remote_policy(local_policy_path, cache_path) }.to raise_error(err)
50
53
  end
51
54
  end
52
55
 
@@ -54,46 +57,78 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
54
57
 
55
58
  @closed = false # tempfile close indicator
56
59
  let(:remote_folder) { "/tmp/foo" }
57
- let(:remote_config) { "#{remote_folder}/workstation.rb" }
60
+ let(:remote_config_path) { "#{remote_folder}/workstation.rb" }
58
61
  # TODO - mock this, I think we're leaving things behind in /tmp in test runs.
59
62
  let!(:local_tempfile) { Tempfile.new }
60
63
 
64
+ before do
65
+ allow(Tempfile).to receive(:new).and_return(local_tempfile)
66
+ end
67
+
61
68
  it "pushes it to the remote machine" do
62
- expect(Tempfile).to receive(:new).and_return(local_tempfile)
63
- expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config)
64
- expect(subject.create_remote_config(remote_folder)).to eq(remote_config)
69
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path)
70
+ expect(subject.create_remote_config(remote_folder)).to eq(remote_config_path)
65
71
  # ensure the tempfile is deleted locally
66
72
  expect(local_tempfile.closed?).to eq(true)
67
73
  end
68
74
 
69
75
  it "raises an error if the upload fails" do
70
- expect(Tempfile).to receive(:new).and_return(local_tempfile)
71
- expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config).and_raise("foo")
76
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path).and_raise("foo")
72
77
  err = ChefApply::Action::ConvergeTarget::ConfigUploadFailed
73
78
  expect { subject.create_remote_config(remote_folder) }.to raise_error(err)
74
79
  # ensure the tempfile is deleted locally
75
80
  expect(local_tempfile.closed?).to eq(true)
76
81
  end
77
82
 
83
+ describe "when chef_license is configured" do
84
+ before do
85
+ ChefApply::Config.chef.chef_license = "accept-no-persist"
86
+ end
87
+
88
+ after do
89
+ ChefApply::Config.reset
90
+ end
91
+
92
+ it "creates a config file with chef_license set and quoted" do
93
+ expect(Tempfile).to receive(:new).and_return(local_tempfile)
94
+ expect(local_tempfile).to receive(:write).with(<<~EOM
95
+ local_mode true
96
+ color false
97
+ cache_path "#{cache_path}"
98
+ chef_repo_path "#{cache_path}"
99
+ require_relative "reporter"
100
+ reporter = ChefApply::Reporter.new
101
+ report_handlers << reporter
102
+ exception_handlers << reporter
103
+ chef_license "accept-no-persist"
104
+ EOM
105
+ )
106
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path)
107
+ expect(subject.create_remote_config(remote_folder)).to eq(remote_config_path)
108
+ expect(local_tempfile.closed?).to eq(true)
109
+ end
110
+ end
111
+
78
112
  describe "when target_level is left default" do
79
113
  before do
80
114
  ChefApply::Config.reset
81
115
  end
116
+ # TODO - this is a windows config, but we don't set windows?
82
117
  it "creates a config file without a specific log_level (leaving default for chef-client)" do
83
118
  expect(Tempfile).to receive(:new).and_return(local_tempfile)
84
119
  expect(local_tempfile).to receive(:write).with(<<~EOM
85
120
  local_mode true
86
121
  color false
87
- cache_path "\#{ENV['APPDATA']}/chef-workstation"
88
- chef_repo_path "\#{ENV['APPDATA']}/chef-workstation"
122
+ cache_path "#{cache_path}"
123
+ chef_repo_path "#{cache_path}"
89
124
  require_relative "reporter"
90
125
  reporter = ChefApply::Reporter.new
91
126
  report_handlers << reporter
92
127
  exception_handlers << reporter
93
128
  EOM
94
129
  )
95
- expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config)
96
- expect(subject.create_remote_config(remote_folder)).to eq(remote_config)
130
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path)
131
+ expect(subject.create_remote_config(remote_folder)).to eq(remote_config_path)
97
132
  expect(local_tempfile.closed?).to eq(true)
98
133
  end
99
134
  end
@@ -112,8 +147,8 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
112
147
  expect(local_tempfile).to receive(:write).with(<<~EOM
113
148
  local_mode true
114
149
  color false
115
- cache_path "\#{ENV['APPDATA']}/chef-workstation"
116
- chef_repo_path "\#{ENV['APPDATA']}/chef-workstation"
150
+ cache_path "#{cache_path}"
151
+ chef_repo_path "#{cache_path}"
117
152
  require_relative "reporter"
118
153
  reporter = ChefApply::Reporter.new
119
154
  report_handlers << reporter
@@ -121,8 +156,8 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
121
156
  log_level :info
122
157
  EOM
123
158
  )
124
- expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config)
125
- expect(subject.create_remote_config(remote_folder)).to eq(remote_config)
159
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path)
160
+ expect(subject.create_remote_config(remote_folder)).to eq(remote_config_path)
126
161
  expect(local_tempfile.closed?).to eq(true)
127
162
  end
128
163
  end
@@ -142,8 +177,8 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
142
177
  expect(local_tempfile).to receive(:write).with(<<~EOM
143
178
  local_mode true
144
179
  color false
145
- cache_path "\#{ENV['APPDATA']}/chef-workstation"
146
- chef_repo_path "\#{ENV['APPDATA']}/chef-workstation"
180
+ cache_path "#{cache_path}"
181
+ chef_repo_path "#{cache_path}"
147
182
  require_relative "reporter"
148
183
  reporter = ChefApply::Reporter.new
149
184
  report_handlers << reporter
@@ -154,8 +189,8 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
154
189
  data_collector.organization "Chef Workstation"
155
190
  EOM
156
191
  )
157
- expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config)
158
- expect(subject.create_remote_config(remote_folder)).to eq(remote_config)
192
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path)
193
+ expect(subject.create_remote_config(remote_folder)).to eq(remote_config_path)
159
194
  # ensure the tempfile is deleted locally
160
195
  expect(local_tempfile.closed?).to eq(true)
161
196
  end
@@ -172,16 +207,16 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
172
207
  expect(local_tempfile).to receive(:write).with(<<~EOM
173
208
  local_mode true
174
209
  color false
175
- cache_path "\#{ENV['APPDATA']}/chef-workstation"
176
- chef_repo_path "\#{ENV['APPDATA']}/chef-workstation"
210
+ cache_path "#{cache_path}"
211
+ chef_repo_path "#{cache_path}"
177
212
  require_relative "reporter"
178
213
  reporter = ChefApply::Reporter.new
179
214
  report_handlers << reporter
180
215
  exception_handlers << reporter
181
216
  EOM
182
217
  )
183
- expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config)
184
- expect(subject.create_remote_config(remote_folder)).to eq(remote_config)
218
+ expect(target_host).to receive(:upload_file).with(local_tempfile.path, remote_config_path)
219
+ expect(subject.create_remote_config(remote_folder)).to eq(remote_config_path)
185
220
  # ensure the tempfile is deleted locally
186
221
  expect(local_tempfile.closed?).to eq(true)
187
222
  end
@@ -232,7 +267,7 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
232
267
  let!(:cert2) { FileUtils.touch(File.join(certs_dir, "2.pem"))[0] }
233
268
 
234
269
  it "uploads the local certs" do
235
- expect(target_host).to receive(:mkdir).with(remote_tcd)
270
+ expect(target_host).to receive(:make_directory).with(remote_tcd)
236
271
  expect(target_host).to receive(:upload_file).with(cert1, File.join(remote_tcd, File.basename(cert1)))
237
272
  expect(target_host).to receive(:upload_file).with(cert2, File.join(remote_tcd, File.basename(cert2)))
238
273
  subject.upload_trusted_certs(remote_folder)
@@ -256,21 +291,24 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
256
291
  let(:remote_handler) { "#{remote_folder}/reporter.rb" }
257
292
  let(:tmpdir) { remote_folder }
258
293
  before do
259
- expect(target_host).to receive(:mktemp).and_return(tmpdir)
294
+ expect(target_host).to receive(:temp_dir).and_return(tmpdir)
295
+ expect(subject).to receive(:create_remote_policy).with(local_policy_path, remote_folder).and_return(remote_archive)
296
+ expect(subject).to receive(:create_remote_config).with(remote_folder).and_return(remote_config)
297
+ expect(subject).to receive(:create_remote_handler).with(remote_folder).and_return(remote_handler)
298
+ expect(subject).to receive(:upload_trusted_certs).with(remote_folder)
260
299
  end
261
300
  let(:result) { double("command result", exit_status: 0, stdout: "") }
262
301
 
263
302
  it "runs the converge and reports back success" do
264
- expect(action).to receive(:create_remote_policy).with(local_policy_path, remote_folder).and_return(remote_archive)
265
- expect(action).to receive(:create_remote_config).with(remote_folder).and_return(remote_config)
266
- expect(action).to receive(:create_remote_handler).with(remote_folder).and_return(remote_handler)
267
- expect(action).to receive(:upload_trusted_certs).with(remote_folder)
268
- expect(target_host).to receive(:run_command).with(/chef-client.+#{archive}/).and_return(result)
269
- expect(target_host).to receive(:run_command!)
270
- .with("#{subject.delete_folder} #{remote_folder}")
271
- .and_return(result)
303
+ # Note we're only ensuring the command looks the same as #run_chef_cmd - we verify that run_chef_cmd
304
+ # is correct in its own test elsewhere in this file
305
+ expect(target_host).to receive(:run_command).with(subject.run_chef_cmd(remote_folder,
306
+ "workstation.rb",
307
+ "archive.tgz")).and_return result
308
+ expect(target_host).to receive(:del_dir).with(remote_folder).and_return result
309
+
272
310
  [:running_chef, :success].each do |n|
273
- expect(action).to receive(:notify).with(n)
311
+ expect(subject).to receive(:notify).with(n)
274
312
  end
275
313
  subject.perform_action
276
314
  end
@@ -279,16 +317,12 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
279
317
  let(:result) { double("command result", exit_status: 35) }
280
318
 
281
319
  it "runs the converge and reports back reboot" do
282
- expect(action).to receive(:create_remote_policy).with(local_policy_path, remote_folder).and_return(remote_archive)
283
- expect(action).to receive(:create_remote_config).with(remote_folder).and_return(remote_config)
284
- expect(action).to receive(:create_remote_handler).with(remote_folder).and_return(remote_handler)
285
- expect(action).to receive(:upload_trusted_certs).with(remote_folder)
286
- expect(target_host).to receive(:run_command).with(/chef-client.+#{archive}/).and_return(result)
287
- expect(target_host).to receive(:run_command!)
288
- .with("#{subject.delete_folder} #{remote_folder}")
289
- .and_return(result)
320
+ expect(target_host).to receive(:run_command).with(subject.run_chef_cmd(remote_folder,
321
+ "workstation.rb",
322
+ "archive.tgz")).and_return result
323
+ expect(target_host).to receive(:del_dir).with(remote_folder).and_return result
290
324
  [:running_chef, :reboot].each do |n|
291
- expect(action).to receive(:notify).with(n)
325
+ expect(subject).to receive(:notify).with(n)
292
326
  end
293
327
  subject.perform_action
294
328
  end
@@ -296,7 +330,7 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
296
330
 
297
331
  context "when command fails" do
298
332
  let(:result) { double("command result", exit_status: 1, stdout: "", stderr: "") }
299
- let(:report_result) { double("report result", exit_status: 0, stdout: '{ "exception": "thing" }') }
333
+ let(:report_result) { '{ "exception": "thing" }' }
300
334
  let(:exception_mapper) { double("mapper") }
301
335
  before do
302
336
  expect(ChefApply::Errors::CCRFailureMapper).to receive(:new)
@@ -304,41 +338,64 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
304
338
  end
305
339
 
306
340
  it "reports back failure and reads the remote report" do
307
- expect(action).to receive(:create_remote_policy).with(local_policy_path, remote_folder).and_return(remote_archive)
308
- expect(action).to receive(:create_remote_config).with(remote_folder).and_return(remote_config)
309
- expect(action).to receive(:create_remote_handler).with(remote_folder).and_return(remote_handler)
310
- expect(action).to receive(:upload_trusted_certs).with(remote_folder)
311
- expect(target_host).to receive(:run_command).with(/chef-client.+#{archive}/).and_return(result)
312
- expect(target_host).to receive(:run_command!)
313
- .with("#{subject.delete_folder} #{remote_folder}")
341
+ expect(target_host).to receive(:run_command).with(subject.run_chef_cmd(remote_folder,
342
+ "workstation.rb",
343
+ "archive.tgz")).and_return result
344
+ expect(target_host).to receive(:del_dir).with(remote_folder).and_return result
314
345
  [:running_chef, :converge_error].each do |n|
315
- expect(action).to receive(:notify).with(n)
346
+ expect(subject).to receive(:notify).with(n)
316
347
  end
317
- expect(target_host).to receive(:run_command).with(subject.read_chef_report).and_return(report_result)
318
- expect(target_host).to receive(:run_command!).with(subject.delete_chef_report)
348
+ expect(target_host).to receive(:fetch_file_contents).with(subject.chef_report_path).and_return(report_result)
349
+ expect(target_host).to receive(:del_file).with(subject.chef_report_path)
319
350
  expect(exception_mapper).to receive(:raise_mapped_exception!)
320
351
  subject.perform_action
321
352
  end
322
353
 
323
354
  context "when remote report cannot be read" do
324
- let(:report_result) { double("report result", exit_status: 1, stdout: "", stderr: "") }
355
+ let(:report_result) { nil }
325
356
  it "reports back failure" do
326
- expect(action).to receive(:create_remote_policy).with(local_policy_path, remote_folder).and_return(remote_archive)
327
- expect(action).to receive(:create_remote_config).with(remote_folder).and_return(remote_config)
328
- expect(action).to receive(:create_remote_handler).with(remote_folder).and_return(remote_handler)
329
- expect(action).to receive(:upload_trusted_certs).with(remote_folder)
330
- expect(target_host).to receive(:run_command).with(/chef-client.+#{archive}/).and_return(result)
331
- expect(target_host).to receive(:run_command!)
332
- .with("#{subject.delete_folder} #{remote_folder}")
357
+ expect(target_host).to receive(:run_command).with(subject.run_chef_cmd(remote_folder,
358
+ "workstation.rb",
359
+ "archive.tgz")).and_return result
360
+ expect(target_host).to receive(:del_dir).with(remote_folder).and_return result
333
361
  [:running_chef, :converge_error].each do |n|
334
- expect(action).to receive(:notify).with(n)
362
+ expect(subject).to receive(:notify).with(n)
335
363
  end
336
- expect(target_host).to receive(:run_command).with(subject.read_chef_report).and_return(report_result)
364
+ expect(target_host).to receive(:fetch_file_contents).with(subject.chef_report_path).and_return(report_result)
337
365
  expect(exception_mapper).to receive(:raise_mapped_exception!)
338
366
  subject.perform_action
339
367
  end
340
368
  end
341
369
  end
370
+
371
+ end
372
+
373
+ context "#run_chef_cmd" do
374
+ describe "when connecting to a windows target" do
375
+ let(:base_os) { :windows }
376
+ # BOOTSTRAP TODO - can't find these examples anywhere - not sure how this was passing
377
+ # include_examples "check path fetching"
378
+
379
+ it "correctly returns chef run string" do
380
+ expect(subject.run_chef_cmd("a", "b", "c")).to eq(
381
+ "Set-Location -Path a; " \
382
+ "chef-client -z --config #{File.join("a", "b")} --recipe-url #{File.join("a", "c")} | Out-Null; " \
383
+ "Set-Location C:/; " \
384
+ "exit $LASTEXITCODE"
385
+ )
386
+ end
387
+ end
388
+
389
+ describe "when connecting to a non-windows target" do
390
+ let(:base_os) { :linux }
391
+ # BOOTSTRAP TODO - can't find these examples anywhere - not sure how this was passing
392
+ # include_examples "check path fetching"
393
+
394
+ it "correctly returns chef run string" do
395
+ expect(subject.run_chef_cmd("a", "b", "c")).to eq("bash -c 'cd a; chef-client -z --config a/b --recipe-url a/c'")
396
+ end
397
+ end
398
+
342
399
  end
343
400
 
344
401
  end