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.
- checksums.yaml +4 -4
- data/Gemfile.lock +84 -63
- data/README.md +6 -0
- data/chef-apply.gemspec +1 -0
- data/i18n/errors/en.yml +11 -10
- data/lib/chef_apply/action/base.rb +0 -84
- data/lib/chef_apply/action/converge_target.rb +60 -24
- data/lib/chef_apply/action/install_chef.rb +99 -10
- data/lib/chef_apply/cli.rb +19 -1
- data/lib/chef_apply/config.rb +1 -0
- data/lib/chef_apply/error.rb +1 -0
- data/lib/chef_apply/errors/ccr_failure_mapper.rb +2 -2
- data/lib/chef_apply/target_host.rb +113 -73
- data/lib/chef_apply/target_host/linux.rb +63 -0
- data/lib/chef_apply/target_host/windows.rb +62 -0
- data/lib/chef_apply/version.rb +1 -1
- data/spec/integration/fixtures/chef_help.out +1 -0
- data/spec/unit/action/base_spec.rb +0 -30
- data/spec/unit/action/converge_target_spec.rb +130 -73
- data/spec/unit/action/install_chef_spec.rb +118 -23
- data/spec/unit/cli_spec.rb +32 -4
- data/spec/unit/target_host/linux_spec.rb +57 -0
- data/spec/unit/target_host/windows_spec.rb +43 -0
- data/spec/unit/target_host_spec.rb +130 -135
- data/spec/unit/ui/error_printer_spec.rb +1 -1
- metadata +27 -8
- data/lib/chef_apply/action/install_chef/base.rb +0 -117
- data/lib/chef_apply/action/install_chef/linux.rb +0 -37
- data/lib/chef_apply/action/install_chef/windows.rb +0 -54
- data/spec/unit/action/install_chef/base_spec.rb +0 -168
@@ -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
|
data/lib/chef_apply/version.rb
CHANGED
@@ -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:
|
28
|
-
|
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
|
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(:
|
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,
|
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,
|
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(:
|
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(
|
63
|
-
expect(
|
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(
|
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 "
|
88
|
-
chef_repo_path "
|
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,
|
96
|
-
expect(subject.create_remote_config(remote_folder)).to eq(
|
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 "
|
116
|
-
chef_repo_path "
|
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,
|
125
|
-
expect(subject.create_remote_config(remote_folder)).to eq(
|
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 "
|
146
|
-
chef_repo_path "
|
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,
|
158
|
-
expect(subject.create_remote_config(remote_folder)).to eq(
|
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 "
|
176
|
-
chef_repo_path "
|
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,
|
184
|
-
expect(subject.create_remote_config(remote_folder)).to eq(
|
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(:
|
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(:
|
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
|
-
|
265
|
-
|
266
|
-
expect(
|
267
|
-
|
268
|
-
|
269
|
-
expect(target_host).to receive(:
|
270
|
-
|
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(
|
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(
|
283
|
-
|
284
|
-
|
285
|
-
expect(
|
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(
|
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) {
|
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(
|
308
|
-
|
309
|
-
|
310
|
-
expect(
|
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(
|
346
|
+
expect(subject).to receive(:notify).with(n)
|
316
347
|
end
|
317
|
-
expect(target_host).to receive(:
|
318
|
-
expect(target_host).to receive(:
|
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) {
|
355
|
+
let(:report_result) { nil }
|
325
356
|
it "reports back failure" do
|
326
|
-
expect(
|
327
|
-
|
328
|
-
|
329
|
-
expect(
|
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(
|
362
|
+
expect(subject).to receive(:notify).with(n)
|
335
363
|
end
|
336
|
-
expect(target_host).to receive(:
|
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
|