chef-apply 0.2.8 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|