chef-apply 0.4.6 → 0.4.9
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 +1 -7
- data/chef-apply.gemspec +3 -3
- data/lib/chef_apply/version.rb +1 -1
- metadata +3 -38
- data/README.md +0 -62
- data/spec/fixtures/custom_config.toml +0 -2
- data/spec/integration/chef-run_spec.rb +0 -41
- data/spec/integration/fixtures/chef_help.out +0 -70
- data/spec/integration/fixtures/chef_version.out +0 -1
- data/spec/integration/spec_helper.rb +0 -55
- data/spec/spec_helper.rb +0 -154
- data/spec/support/matchers/output_to_terminal.rb +0 -36
- data/spec/unit/action/base_spec.rb +0 -60
- data/spec/unit/action/converge_target/ccr_failure_mapper_spec.rb +0 -106
- data/spec/unit/action/converge_target_spec.rb +0 -400
- data/spec/unit/action/generate_local_policy_spec.rb +0 -114
- data/spec/unit/action/generate_temp_cookbook/recipe_lookup_spec.rb +0 -122
- data/spec/unit/action/generate_temp_cookbook/temp_cookbook_spec.rb +0 -198
- data/spec/unit/action/generate_temp_cookbook_spec.rb +0 -73
- data/spec/unit/action/install_chef/minimum_chef_version_spec.rb +0 -90
- data/spec/unit/action/install_chef_spec.rb +0 -164
- data/spec/unit/cli/options_spec.rb +0 -75
- data/spec/unit/cli/validation_spec.rb +0 -81
- data/spec/unit/cli_spec.rb +0 -475
- data/spec/unit/config_spec.rb +0 -70
- data/spec/unit/file_fetcher_spec.rb +0 -40
- data/spec/unit/fixtures/multi-error.out +0 -2
- data/spec/unit/log_spec.rb +0 -37
- data/spec/unit/startup_spec.rb +0 -323
- data/spec/unit/target_host/linux_spec.rb +0 -57
- data/spec/unit/target_host/windows_spec.rb +0 -43
- data/spec/unit/target_host_spec.rb +0 -297
- data/spec/unit/target_resolver_spec.rb +0 -380
- data/spec/unit/telemeter/sender_spec.rb +0 -140
- data/spec/unit/telemeter_spec.rb +0 -191
- data/spec/unit/text/error_translation_spec.rb +0 -109
- data/spec/unit/ui/error_printer_spec.rb +0 -196
- data/spec/unit/ui/terminal_spec.rb +0 -119
- data/spec/unit/version_spec.rb +0 -31
@@ -1,90 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright:: Copyright (c) 2018 Chef Software Inc.
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require "chef_apply/action/install_chef/minimum_chef_version"
|
19
|
-
require "chef_apply/target_host"
|
20
|
-
require "spec_helper"
|
21
|
-
|
22
|
-
RSpec.describe ChefApply::Action::InstallChef::MinimumChefVersion do
|
23
|
-
let(:base_os) { :linux }
|
24
|
-
let(:version) { 14 }
|
25
|
-
let(:target) { instance_double(ChefApply::TargetHost, base_os: base_os, installed_chef_version: version) }
|
26
|
-
subject(:klass) { ChefApply::Action::InstallChef::MinimumChefVersion }
|
27
|
-
|
28
|
-
context "#check!" do
|
29
|
-
context "when chef is not already installed on target" do
|
30
|
-
before do
|
31
|
-
expect(target).to receive(:installed_chef_version)
|
32
|
-
.and_raise ChefApply::TargetHost::ChefNotInstalled.new
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should return :client_not_installed" do
|
36
|
-
actual = klass.check!(target, false)
|
37
|
-
expect(:client_not_installed).to eq(actual)
|
38
|
-
end
|
39
|
-
|
40
|
-
context "when config is set to check_only" do
|
41
|
-
it "raises ClientNotInstalled" do
|
42
|
-
expect do
|
43
|
-
klass.check!(target, true)
|
44
|
-
end.to raise_error(ChefApply::Action::InstallChef::MinimumChefVersion::ClientNotInstalled)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
%i{windows linux}.each do |os|
|
50
|
-
context "on #{os}" do
|
51
|
-
let(:base_os) { os }
|
52
|
-
[13, 14].each do |major_version|
|
53
|
-
context "when chef is already installed at the correct minimum Chef #{major_version} version" do
|
54
|
-
let(:version) { ChefApply::Action::InstallChef::MinimumChefVersion::CONSTRAINTS[os][major_version] }
|
55
|
-
it "should return :minimum_version_met" do
|
56
|
-
actual = klass.check!(target, false)
|
57
|
-
expect(:minimum_version_met).to eq(actual)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
installed_expected = {
|
65
|
-
windows: {
|
66
|
-
Gem::Version.new("12.1.1") => ChefApply::Action::InstallChef::MinimumChefVersion::Client13Outdated,
|
67
|
-
Gem::Version.new("13.9.0") => ChefApply::Action::InstallChef::MinimumChefVersion::Client13Outdated,
|
68
|
-
Gem::Version.new("14.3.37") => ChefApply::Action::InstallChef::MinimumChefVersion::Client14Outdated,
|
69
|
-
},
|
70
|
-
linux: {
|
71
|
-
Gem::Version.new("12.1.1") => ChefApply::Action::InstallChef::MinimumChefVersion::Client13Outdated,
|
72
|
-
Gem::Version.new("13.9.0") => ChefApply::Action::InstallChef::MinimumChefVersion::Client13Outdated,
|
73
|
-
Gem::Version.new("14.1.0") => ChefApply::Action::InstallChef::MinimumChefVersion::Client14Outdated,
|
74
|
-
},
|
75
|
-
}
|
76
|
-
%i{windows linux}.each do |os|
|
77
|
-
context "on #{os}" do
|
78
|
-
let(:base_os) { os }
|
79
|
-
installed_expected[os].each do |installed, expected|
|
80
|
-
context "when chef is already installed on target at version #{installed}" do
|
81
|
-
let(:version) { installed }
|
82
|
-
it "notifies of failure and takes no further action" do
|
83
|
-
expect { klass.check!(target, false) }.to raise_error(expected)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
@@ -1,164 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright:: Copyright (c) 2018 Chef Software Inc.
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require "spec_helper"
|
19
|
-
require "chef_apply/action/install_chef"
|
20
|
-
|
21
|
-
RSpec.describe ChefApply::Action::InstallChef do
|
22
|
-
let(:mock_os_name) { "linux" }
|
23
|
-
let(:mock_os_family) { "linux" }
|
24
|
-
let(:mock_os_release ) { "unknown" }
|
25
|
-
let(:mock_opts) do
|
26
|
-
{
|
27
|
-
name: mock_os_name,
|
28
|
-
family: mock_os_family,
|
29
|
-
release: mock_os_release,
|
30
|
-
arch: "x86_64",
|
31
|
-
}
|
32
|
-
end
|
33
|
-
let(:target_host) do
|
34
|
-
ChefApply::TargetHost.mock_instance("mock://user1:password1@localhost", mock_opts)
|
35
|
-
end
|
36
|
-
|
37
|
-
let(:reporter) do
|
38
|
-
ChefApply::MockReporter.new
|
39
|
-
end
|
40
|
-
|
41
|
-
subject(:install) do
|
42
|
-
ChefApply::Action::InstallChef.new(target_host: target_host,
|
43
|
-
reporter: reporter,
|
44
|
-
check_only: false)
|
45
|
-
end
|
46
|
-
|
47
|
-
context "#perform_action" do
|
48
|
-
context "when chef is already installed on target" do
|
49
|
-
it "notifies of success and takes no further action" do
|
50
|
-
expect(ChefApply::Action::InstallChef::MinimumChefVersion).to receive(:check!).with(install.target_host, false)
|
51
|
-
.and_return(:minimum_version_met)
|
52
|
-
expect(install).not_to receive(:perform_local_install)
|
53
|
-
install.perform_action
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context "when chef is not already installed on target" do
|
58
|
-
it "should invoke perform_local_install" do
|
59
|
-
expect(ChefApply::Action::InstallChef::MinimumChefVersion).to receive(:check!).with(install.target_host, false)
|
60
|
-
.and_return(:client_not_installed)
|
61
|
-
expect(install).to receive(:perform_local_install)
|
62
|
-
install.perform_action
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context "#perform_local_install" do
|
68
|
-
let(:artifact) { double("artifact") }
|
69
|
-
let(:package_url) { "https://chef.io/download/package/here" }
|
70
|
-
before do
|
71
|
-
allow(artifact).to receive(:url).and_return package_url
|
72
|
-
end
|
73
|
-
|
74
|
-
it "performs the steps necessary to perform an installation" do
|
75
|
-
expect(install).to receive(:lookup_artifact).and_return artifact
|
76
|
-
expect(install).to receive(:download_to_workstation).with(package_url) .and_return "/local/path"
|
77
|
-
expect(install).to receive(:upload_to_target).with("/local/path").and_return("/remote/path")
|
78
|
-
expect(target_host).to receive(:install_package).with("/remote/path")
|
79
|
-
|
80
|
-
install.perform_local_install
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context "#train_to_mixlib" do
|
85
|
-
let(:platform) { double }
|
86
|
-
before do
|
87
|
-
allow(platform).to receive(:release).and_return "1234"
|
88
|
-
allow(platform).to receive(:name).and_return "beos"
|
89
|
-
allow(platform).to receive(:arch).and_return "ppc"
|
90
|
-
end
|
91
|
-
|
92
|
-
context "when any flavor of windows" do
|
93
|
-
before do
|
94
|
-
allow(platform).to receive(:name).and_return "windows_10_pro_n"
|
95
|
-
end
|
96
|
-
|
97
|
-
it "sets platform name to 'windows'" do
|
98
|
-
mixlib_info = install.train_to_mixlib(platform)
|
99
|
-
expect(mixlib_info[:platform]).to eq "windows"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context "when redhat" do
|
104
|
-
before do
|
105
|
-
allow(platform).to receive(:name).and_return "redhat"
|
106
|
-
end
|
107
|
-
|
108
|
-
it "sets platform name to 'el'" do
|
109
|
-
mixlib_info = install.train_to_mixlib(platform)
|
110
|
-
expect(mixlib_info[:platform]).to eq "el"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
context "when centos" do
|
115
|
-
before do
|
116
|
-
allow(platform).to receive(:name).and_return "centos"
|
117
|
-
end
|
118
|
-
|
119
|
-
it "sets platform name to 'el'" do
|
120
|
-
mixlib_info = install.train_to_mixlib(platform)
|
121
|
-
expect(mixlib_info[:platform]).to eq "el"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
context "when suse" do
|
126
|
-
before do
|
127
|
-
allow(platform).to receive(:name).and_return "suse"
|
128
|
-
end
|
129
|
-
|
130
|
-
it "sets platform name to 'sles'" do
|
131
|
-
mixlib_info = install.train_to_mixlib(platform)
|
132
|
-
expect(mixlib_info[:platform]).to eq "sles"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
context "when amazon" do
|
136
|
-
before do
|
137
|
-
allow(platform).to receive(:name).and_return "amazon"
|
138
|
-
end
|
139
|
-
|
140
|
-
context "when amazon linux 1.x" do
|
141
|
-
before do
|
142
|
-
allow(platform).to receive(:release).and_return "2017.09"
|
143
|
-
end
|
144
|
-
|
145
|
-
it "sets platform name to 'amazon' and plaform_version to '6'" do
|
146
|
-
mixlib_info = install.train_to_mixlib(platform)
|
147
|
-
expect(mixlib_info[:platform]).to eq "el"
|
148
|
-
expect(mixlib_info[:platform_version]).to eq "6"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
context "when amazon linux 2.x" do
|
152
|
-
before do
|
153
|
-
allow(platform).to receive(:release).and_return "2"
|
154
|
-
end
|
155
|
-
|
156
|
-
it "sets platform name to 'amazon' and plaform_version to '7'" do
|
157
|
-
mixlib_info = install.train_to_mixlib(platform)
|
158
|
-
expect(mixlib_info[:platform]).to eq "el"
|
159
|
-
expect(mixlib_info[:platform_version]).to eq "7"
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright:: Copyright (c) 2018 Chef Software Inc.
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require "spec_helper"
|
19
|
-
require "mixlib/cli"
|
20
|
-
require "chef_apply/cli/options"
|
21
|
-
require "chef-config/config"
|
22
|
-
|
23
|
-
ChefApply::Config.load
|
24
|
-
|
25
|
-
module ChefApply
|
26
|
-
module CLIOptions
|
27
|
-
class TestClass
|
28
|
-
include Mixlib::CLI
|
29
|
-
include ChefApply::CLI::Options
|
30
|
-
end
|
31
|
-
|
32
|
-
def parse(argv)
|
33
|
-
parse_options(argv)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
RSpec.describe ChefApply::CLIOptions do
|
39
|
-
let(:klass) { ChefApply::CLIOptions::TestClass.new }
|
40
|
-
|
41
|
-
it "contains the specified options" do
|
42
|
-
expect(klass.options.keys).to eq(%i{
|
43
|
-
version
|
44
|
-
help
|
45
|
-
config_path
|
46
|
-
identity_file
|
47
|
-
ssl
|
48
|
-
ssl_verify
|
49
|
-
protocol
|
50
|
-
user
|
51
|
-
password
|
52
|
-
cookbook_repo_paths
|
53
|
-
install
|
54
|
-
sudo
|
55
|
-
sudo_command
|
56
|
-
sudo_password
|
57
|
-
sudo_options
|
58
|
-
})
|
59
|
-
end
|
60
|
-
|
61
|
-
it "persists certain CLI options back to the ChefApply::Config" do
|
62
|
-
# First we check the default value beforehand
|
63
|
-
expect(ChefApply::Config.connection.winrm.ssl).to eq(false)
|
64
|
-
expect(ChefApply::Config.connection.winrm.ssl_verify).to eq(true)
|
65
|
-
expect(ChefApply::Config.connection.default_protocol).to eq("ssh")
|
66
|
-
expect(ChefApply::Config.chef.cookbook_repo_paths).to_not be_empty
|
67
|
-
# Then we set the values and check they are changed
|
68
|
-
klass.parse_options(["--ssl", "--no-ssl-verify", "--protocol", "winrm", "--cookbook-repo-paths", "a,b"])
|
69
|
-
expect(ChefApply::Config.connection.winrm.ssl).to eq(true)
|
70
|
-
expect(ChefApply::Config.connection.winrm.ssl_verify).to eq(false)
|
71
|
-
expect(ChefApply::Config.connection.default_protocol).to eq("winrm")
|
72
|
-
expect(ChefApply::Config.chef.cookbook_repo_paths).to eq(%w{a b})
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "chef_apply/error"
|
3
|
-
require "chef_apply/cli/validation"
|
4
|
-
|
5
|
-
RSpec.describe ChefApply::CLI::Validation do
|
6
|
-
class Validator
|
7
|
-
include ChefApply::CLI::Validation
|
8
|
-
end
|
9
|
-
subject { Validator.new }
|
10
|
-
|
11
|
-
context "#validate_params" do
|
12
|
-
OptionValidationError = ChefApply::CLI::OptionValidationError
|
13
|
-
it "raises an error if not enough params are specified" do
|
14
|
-
params = [
|
15
|
-
[],
|
16
|
-
%w{one},
|
17
|
-
]
|
18
|
-
params.each do |p|
|
19
|
-
expect { subject.validate_params(p) }.to raise_error(OptionValidationError) do |e|
|
20
|
-
e.id == "CHEFVAL002"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
it "succeeds if the second command is a valid file path" do
|
26
|
-
params = %w{target /some/path}
|
27
|
-
expect(File).to receive(:exist?).with("/some/path").and_return true
|
28
|
-
expect { subject.validate_params(params) }.to_not raise_error
|
29
|
-
end
|
30
|
-
|
31
|
-
it "succeeds if the second argument looks like a cookbook name" do
|
32
|
-
params = [
|
33
|
-
%w{target cb},
|
34
|
-
%w{target cb::recipe},
|
35
|
-
]
|
36
|
-
params.each do |p|
|
37
|
-
expect { subject.validate_params(p) }.to_not raise_error
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
it "raises an error if the second argument is neither a valid path or a valid cookbook name" do
|
42
|
-
params = %w{target weird%name}
|
43
|
-
expect { subject.validate_params(params) }.to raise_error(OptionValidationError) do |e|
|
44
|
-
e.id == "CHEFVAL004"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
it "raises an error if properties are not specified as key value pairs" do
|
49
|
-
params = [
|
50
|
-
%w{one two three four},
|
51
|
-
%w{one two three four=value five six=value},
|
52
|
-
%w{one two three non.word=value},
|
53
|
-
]
|
54
|
-
params.each do |p|
|
55
|
-
expect { subject.validate_params(p) }.to raise_error(OptionValidationError) do |e|
|
56
|
-
e.id == "CHEFVAL003"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
describe "#properties_from_string" do
|
62
|
-
it "parses properties into a hash" do
|
63
|
-
provided = %w{key1=value key2=1 key3=true key4=FaLsE key5=0777 key6=https://some.website key7=num1and2digit key_8=underscore key9=127.0.0.1 key10=1. key11=1.1}
|
64
|
-
expected = {
|
65
|
-
"key1" => "value",
|
66
|
-
"key2" => 1,
|
67
|
-
"key3" => true,
|
68
|
-
"key4" => false,
|
69
|
-
"key5" => "0777",
|
70
|
-
"key6" => "https://some.website",
|
71
|
-
"key7" => "num1and2digit",
|
72
|
-
"key_8" => "underscore",
|
73
|
-
"key9" => "127.0.0.1",
|
74
|
-
"key10" => 1.0,
|
75
|
-
"key11" => 1.1,
|
76
|
-
}
|
77
|
-
expect(subject.properties_from_string(provided)).to eq(expected)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
data/spec/unit/cli_spec.rb
DELETED
@@ -1,475 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Copyright:: Copyright (c) 2018 Chef Software Inc.
|
3
|
-
# License:: Apache License, Version 2.0
|
4
|
-
#
|
5
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
-
# you may not use this file except in compliance with the License.
|
7
|
-
# You may obtain a copy of the License at
|
8
|
-
#
|
9
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
11
|
-
# Unless required by applicable law or agreed to in writing, software
|
12
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
-
# See the License for the specific language governing permissions and
|
15
|
-
# limitations under the License.
|
16
|
-
#
|
17
|
-
|
18
|
-
require "spec_helper"
|
19
|
-
require "chef_apply/cli"
|
20
|
-
require "chef_apply/error"
|
21
|
-
require "chef_apply/telemeter"
|
22
|
-
require "chef_apply/telemeter/sender"
|
23
|
-
require "chef_apply/ui/terminal"
|
24
|
-
require "chef_apply/action/generate_temp_cookbook"
|
25
|
-
require "chef_apply/action/generate_temp_cookbook/temp_cookbook"
|
26
|
-
|
27
|
-
require "chef-cli/ui"
|
28
|
-
|
29
|
-
RSpec.describe ChefApply::CLI do
|
30
|
-
subject { ChefApply::CLI.new(argv) }
|
31
|
-
let(:argv) { [] }
|
32
|
-
# TODO why isn't this mocked?
|
33
|
-
let(:telemetry) { ChefApply::Telemeter.instance }
|
34
|
-
|
35
|
-
before do
|
36
|
-
# Avoid messy object dumps in failures because subject is an object instance
|
37
|
-
allow(subject).to receive(:inspect).and_return("The subject instance")
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "run" do
|
41
|
-
before do
|
42
|
-
# Catch all of the calls by default, to prevent the various
|
43
|
-
# startup actions from actually occuring on the workstatoin.
|
44
|
-
allow(telemetry).to receive(:timed_run_capture).and_yield
|
45
|
-
allow(subject).to receive(:perform_run)
|
46
|
-
allow(telemetry).to receive(:commit)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "captures and commits the run to telemetry" do
|
50
|
-
expect(telemetry).to receive(:timed_run_capture)
|
51
|
-
expect(telemetry).to receive(:commit)
|
52
|
-
expect { subject.run }.to exit_with_code(0)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "calls perform_run" do
|
56
|
-
expect(subject).to receive(:perform_run)
|
57
|
-
expect { subject.run }.to exit_with_code(0)
|
58
|
-
end
|
59
|
-
|
60
|
-
context "perform_run raises WrappedError" do
|
61
|
-
let(:e) { ChefApply::WrappedError.new(RuntimeError.new("Test"), "host") }
|
62
|
-
|
63
|
-
it "prints the error and exits" do
|
64
|
-
expect(subject).to receive(:perform_run).and_raise(e)
|
65
|
-
expect(ChefApply::UI::ErrorPrinter).to receive(:show_error).with(e)
|
66
|
-
expect { subject.run }.to exit_with_code(1)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context "perform_run raises SystemExit" do
|
71
|
-
it "exits with same exit code" do
|
72
|
-
expect(subject).to receive(:perform_run).and_raise(SystemExit.new(99))
|
73
|
-
expect { subject.run }.to exit_with_code(99)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context "perform_run raises any other exception" do
|
78
|
-
let(:e) { Exception.new("test") }
|
79
|
-
|
80
|
-
it "exits with code 64" do
|
81
|
-
expect(subject).to receive(:perform_run).and_raise(e)
|
82
|
-
expect(ChefApply::UI::ErrorPrinter).to receive(:dump_unexpected_error).with(e)
|
83
|
-
expect { subject.run }.to exit_with_code(64)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "#perform_run" do
|
89
|
-
it "parses options" do
|
90
|
-
expect(subject).to receive(:parse_options).with(argv)
|
91
|
-
subject.perform_run
|
92
|
-
end
|
93
|
-
|
94
|
-
context "when any error is raised" do
|
95
|
-
let(:e) { RuntimeError.new("Test") }
|
96
|
-
before do
|
97
|
-
allow(subject).to receive(:parse_options).and_raise(e)
|
98
|
-
end
|
99
|
-
|
100
|
-
it "calls handle_perform_error" do
|
101
|
-
expect(subject).to receive(:handle_perform_error).with(e)
|
102
|
-
subject.perform_run
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "when argv is empty" do
|
107
|
-
let(:argv) { [] }
|
108
|
-
it "shows the help text" do
|
109
|
-
expect(subject).to receive(:show_help)
|
110
|
-
subject.perform_run
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
context "when help flags are passed" do
|
115
|
-
%w{-h --help}.each do |flag|
|
116
|
-
context flag do
|
117
|
-
let(:argv) { [flag] }
|
118
|
-
it "shows the help text" do
|
119
|
-
expect(subject).to receive(:show_help)
|
120
|
-
subject.perform_run
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
%w{-v --version}.each do |flag|
|
126
|
-
context flag do
|
127
|
-
let(:argv) { [flag] }
|
128
|
-
it "shows the help text" do
|
129
|
-
expect(subject).to receive(:show_version)
|
130
|
-
subject.perform_run
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "when arguments are provided" do
|
137
|
-
let(:argv) { ["hostname", "resourcetype", "resourcename", "someproperty=true"] }
|
138
|
-
let(:target_hosts) { [double("TargetHost")] }
|
139
|
-
before do
|
140
|
-
# parse_options sets `cli_argument` - because we stub out parse_options,
|
141
|
-
# later calls that rely on cli_arguments will fail without this.
|
142
|
-
allow(subject).to receive(:cli_arguments).and_return argv
|
143
|
-
end
|
144
|
-
|
145
|
-
context "and they are valid" do
|
146
|
-
it "creates the cookbook locally and converges it" do
|
147
|
-
expect(subject).to receive(:parse_options)
|
148
|
-
expect(subject).to receive(:check_license_acceptance)
|
149
|
-
expect(subject).to receive(:validate_params)
|
150
|
-
expect(subject).to receive(:resolve_targets).and_return target_hosts
|
151
|
-
expect(subject).to receive(:render_cookbook_setup)
|
152
|
-
expect(subject).to receive(:render_converge).with(target_hosts)
|
153
|
-
subject.perform_run
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe "#check_license_acceptance" do
|
160
|
-
let(:acceptance_value) { "accept-no-persist" }
|
161
|
-
let(:acceptor) { instance_double(LicenseAcceptance::Acceptor) }
|
162
|
-
|
163
|
-
before do
|
164
|
-
ChefApply::Config.reset
|
165
|
-
expect(LicenseAcceptance::Acceptor).to receive(:new).with(provided: ChefApply::Config.chef.chef_license).and_return(acceptor)
|
166
|
-
end
|
167
|
-
|
168
|
-
it "sets the config value to the acceptance value" do
|
169
|
-
expect(ChefApply::Config.chef.chef_license).to eq(nil)
|
170
|
-
expect(acceptor).to receive(:check_and_persist).with("infra-client", "latest")
|
171
|
-
expect(acceptor).to receive(:acceptance_value).and_return(acceptance_value)
|
172
|
-
subject.check_license_acceptance
|
173
|
-
expect(ChefApply::Config.chef.chef_license).to eq(acceptance_value)
|
174
|
-
end
|
175
|
-
|
176
|
-
describe "when the user does not accept the license" do
|
177
|
-
it "raises a LicenseCheckFailed error" do
|
178
|
-
expect(ChefApply::Config.chef.chef_license).to eq(nil)
|
179
|
-
expect(acceptor).to receive(:check_and_persist).with("infra-client", "latest").and_raise(LicenseAcceptance::LicenseNotAcceptedError.new(nil, []))
|
180
|
-
expect { subject.check_license_acceptance }.to raise_error(ChefApply::LicenseCheckFailed)
|
181
|
-
expect(ChefApply::Config.chef.chef_license).to eq(nil)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe "#connect_target" do
|
187
|
-
let(:host) { double("TargetHost", config: {}, user: "root" ) }
|
188
|
-
let(:reporter) { double("reporter", update: :ok, success: :ok) }
|
189
|
-
it "invokes do_connect with correct options" do
|
190
|
-
expect(subject).to receive(:do_connect)
|
191
|
-
.with(host, reporter)
|
192
|
-
subject.connect_target(host, reporter)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
describe "#generate_temp_cookbook" do
|
197
|
-
before do
|
198
|
-
allow(subject).to receive(:parsed_options).and_return({ cookbook_repo_paths: "/tmp" })
|
199
|
-
end
|
200
|
-
let(:temp_cookbook) { double("TempCookbook") }
|
201
|
-
let(:action) { double("generator", generated_cookbook: temp_cookbook) }
|
202
|
-
|
203
|
-
context "when a resource is provided" do
|
204
|
-
it "gets an action via GenerateTempCookbook.from_options and executes it " do
|
205
|
-
expect(ChefApply::Action::GenerateTempCookbook)
|
206
|
-
.to receive(:from_options)
|
207
|
-
.with(resource_type: "user",
|
208
|
-
resource_name: "test", resource_properties: {})
|
209
|
-
.and_return(action)
|
210
|
-
expect(action).to receive(:run)
|
211
|
-
expect(subject.generate_temp_cookbook(%w{user test}, nil)).to eq temp_cookbook
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
context "when a recipe specifier is provided" do
|
216
|
-
|
217
|
-
it "gets an action via GenerateTempCookbook.from_options and executes it" do
|
218
|
-
expect(ChefApply::Action::GenerateTempCookbook)
|
219
|
-
.to receive(:from_options)
|
220
|
-
.with(recipe_spec: "mycookbook::default", cookbook_repo_paths: "/tmp")
|
221
|
-
.and_return(action)
|
222
|
-
expect(action).to receive(:run)
|
223
|
-
subject.generate_temp_cookbook(["mycookbook::default"], nil)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
context "when generator posts event:" do
|
228
|
-
let(:reporter) { double("reporter") }
|
229
|
-
before do
|
230
|
-
expect(ChefApply::Action::GenerateTempCookbook)
|
231
|
-
.to receive(:from_options)
|
232
|
-
.and_return(action)
|
233
|
-
allow(action).to receive(:run) { |&block| block.call(event, event_args) }
|
234
|
-
end
|
235
|
-
|
236
|
-
context ":generating" do
|
237
|
-
let(:event) { :generating }
|
238
|
-
let(:event_args) { nil }
|
239
|
-
it "updates message text via reporter" do
|
240
|
-
expected_text = ChefApply::CLI::TS.generate_temp_cookbook.generating
|
241
|
-
expect(reporter).to receive(:update).with(expected_text)
|
242
|
-
subject.generate_temp_cookbook(%w{user jimbo}, reporter)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
context ":success" do
|
247
|
-
let(:event) { :success }
|
248
|
-
let(:event_args) { [ temp_cookbook ] }
|
249
|
-
it "indicates success via reporter and returns the cookbook" do
|
250
|
-
expected_text = ChefApply::CLI::TS.generate_temp_cookbook.success
|
251
|
-
expect(reporter).to receive(:success).with(expected_text)
|
252
|
-
expect(subject.generate_temp_cookbook(%w{user jimbo}, reporter))
|
253
|
-
.to eq temp_cookbook
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
describe "#generate_local_policy" do
|
260
|
-
let(:reporter) { double("reporter") }
|
261
|
-
let(:action) { double("GenerateLocalPolicy") }
|
262
|
-
let(:temp_cookbook) { instance_double("TempCookbook") }
|
263
|
-
let(:archive_file_location) { "/temp/archive.gz" }
|
264
|
-
|
265
|
-
before do
|
266
|
-
allow(subject).to receive(:temp_cookbook).and_return temp_cookbook
|
267
|
-
allow(action).to receive(:archive_file_location).and_return archive_file_location
|
268
|
-
end
|
269
|
-
it "creates a GenerateLocalPolicy action and executes it" do
|
270
|
-
expect(ChefApply::Action::GenerateLocalPolicy).to receive(:new)
|
271
|
-
.with(cookbook: temp_cookbook)
|
272
|
-
.and_return(action)
|
273
|
-
expect(action).to receive(:run)
|
274
|
-
subject.generate_local_policy(reporter)
|
275
|
-
end
|
276
|
-
|
277
|
-
context "when generator posts an event:" do
|
278
|
-
before do
|
279
|
-
expect(ChefApply::Action::GenerateLocalPolicy).to receive(:new)
|
280
|
-
.with(cookbook: temp_cookbook)
|
281
|
-
.and_return(action)
|
282
|
-
allow(action).to receive(:run) { |&block| block.call(event, event_args) }
|
283
|
-
end
|
284
|
-
|
285
|
-
context ":generating" do
|
286
|
-
let(:event) { :generating }
|
287
|
-
let(:event_args) { nil }
|
288
|
-
let(:expected_msg) { ChefApply::CLI::TS.generate_local_policy.generating }
|
289
|
-
it "updates message text correctly via reporter" do
|
290
|
-
expect(reporter).to receive(:update).with(expected_msg)
|
291
|
-
subject.generate_local_policy(reporter)
|
292
|
-
end
|
293
|
-
|
294
|
-
end
|
295
|
-
|
296
|
-
context ":exporting" do
|
297
|
-
let(:event) { :exporting }
|
298
|
-
let(:event_args) { nil }
|
299
|
-
let(:expected_msg) { ChefApply::CLI::TS.generate_local_policy.exporting }
|
300
|
-
it "updates message text correctly via reporter" do
|
301
|
-
expect(reporter).to receive(:update).with(expected_msg)
|
302
|
-
subject.generate_local_policy(reporter)
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
|
-
context ":success" do
|
307
|
-
let(:event) { :success }
|
308
|
-
let(:expected_msg) { ChefApply::CLI::TS.generate_local_policy.success }
|
309
|
-
let(:event_args) { [archive_file_location] }
|
310
|
-
it "indicates success via reporter and returns the archive file location" do
|
311
|
-
expect(reporter).to receive(:success).with(expected_msg)
|
312
|
-
expect(subject.generate_local_policy(reporter)).to eq archive_file_location
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
describe "#render_cookbook_setup" do
|
319
|
-
let(:reporter) { instance_double(ChefApply::StatusReporter) }
|
320
|
-
let(:temp_cookbook) { double(ChefApply::Action::GenerateTempCookbook::TempCookbook) }
|
321
|
-
let(:archive_file_location) { "/path/to/archive" }
|
322
|
-
let(:args) { [] }
|
323
|
-
# before do
|
324
|
-
# allow(ChefApply::UI::Terminal).to receive(:render_job).and_yield(reporter)
|
325
|
-
# end
|
326
|
-
|
327
|
-
it "generates the cookbook and local policy" do
|
328
|
-
expect(ChefApply::UI::Terminal).to receive(:render_job) do |initial_msg, job|
|
329
|
-
job.run(reporter)
|
330
|
-
end
|
331
|
-
expect(subject).to receive(:generate_temp_cookbook)
|
332
|
-
.with(args, reporter).and_return temp_cookbook
|
333
|
-
expect(ChefApply::UI::Terminal).to receive(:render_job) do |initial_msg, job|
|
334
|
-
job.run(reporter)
|
335
|
-
end
|
336
|
-
expect(subject).to receive(:generate_local_policy)
|
337
|
-
.with(reporter).and_return archive_file_location
|
338
|
-
subject.render_cookbook_setup(args)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
describe "#render_converge" do
|
343
|
-
|
344
|
-
let(:reporter) { instance_double(ChefApply::StatusReporter) }
|
345
|
-
let(:host1) { ChefApply::TargetHost.new("ssh://host1") }
|
346
|
-
let(:host2) { ChefApply::TargetHost.new("ssh://host2") }
|
347
|
-
let(:cookbook_type) { :resource } # || :recipe
|
348
|
-
let(:temp_cookbook) do
|
349
|
-
instance_double(ChefApply::Action::GenerateTempCookbook::TempCookbook,
|
350
|
-
descriptor: "resource[name]",
|
351
|
-
from: "resource")
|
352
|
-
end
|
353
|
-
let(:archive_file_location) { "/path/to/archive" }
|
354
|
-
|
355
|
-
before do
|
356
|
-
allow(subject).to receive(:temp_cookbook).and_return temp_cookbook
|
357
|
-
allow(subject).to receive(:archive_file_location).and_return archive_file_location
|
358
|
-
expected_header = ChefApply::CLI::TS.converge.header(2, temp_cookbook.descriptor, temp_cookbook.from)
|
359
|
-
allow(ChefApply::UI::Terminal).to receive(:render_parallel_jobs) do |header, jobs|
|
360
|
-
expect(header).to eq expected_header
|
361
|
-
jobs.each { |j| j.run(reporter) }
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
let(:target_hosts) { [host1, host2] }
|
366
|
-
it "connects, installs chef, and converges for each target" do
|
367
|
-
target_hosts.each do |host|
|
368
|
-
expect(subject).to receive(:connect_target).with(host, reporter)
|
369
|
-
expect(subject).to receive(:install).with(host, reporter)
|
370
|
-
expect(subject).to receive(:converge).with(reporter, archive_file_location, host)
|
371
|
-
end
|
372
|
-
subject.render_converge(target_hosts)
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
describe "#install" do
|
377
|
-
let(:upgrading) { false }
|
378
|
-
let(:target_host) { double("targethost", installed_chef_version: "14.0") }
|
379
|
-
let(:reporter) { double("reporter") }
|
380
|
-
let(:action) do
|
381
|
-
double("ChefApply::Actions::InstallChef",
|
382
|
-
upgrading?: upgrading,
|
383
|
-
version_to_install: "14.0")
|
384
|
-
end
|
385
|
-
|
386
|
-
it "updates status, creates an InstallChef action and executes it" do
|
387
|
-
expect(reporter)
|
388
|
-
.to receive(:update)
|
389
|
-
.with(ChefApply::CLI::TS.install_chef.verifying)
|
390
|
-
expect(ChefApply::Action::InstallChef).to receive(:new)
|
391
|
-
.with(target_host: target_host, check_only: false)
|
392
|
-
.and_return action
|
393
|
-
expect(action).to receive(:run)
|
394
|
-
subject.install(target_host, reporter)
|
395
|
-
end
|
396
|
-
|
397
|
-
context "when generator posts event:" do
|
398
|
-
let(:event_args) { nil }
|
399
|
-
let(:text_context) { ChefApply::Text.status.install_chef }
|
400
|
-
|
401
|
-
before do
|
402
|
-
allow(ChefApply::Action::InstallChef)
|
403
|
-
.to receive(:new).and_return action
|
404
|
-
allow(action)
|
405
|
-
.to receive(:run) { |&block| block.call(event, event_args) }
|
406
|
-
allow(reporter)
|
407
|
-
.to receive(:update).with(ChefApply::CLI::TS.install_chef.verifying)
|
408
|
-
end
|
409
|
-
|
410
|
-
context ":installing" do
|
411
|
-
let(:event) { :installing }
|
412
|
-
|
413
|
-
context "when installer is upgrading" do
|
414
|
-
let(:upgrading) { true }
|
415
|
-
it "reports the update correctly" do
|
416
|
-
expect(reporter).to receive(:update).with(text_context.upgrading(target_host.installed_chef_version, action.version_to_install))
|
417
|
-
subject.install(target_host, reporter)
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
context "when installer is installing clean" do
|
422
|
-
let(:upgrading) { false }
|
423
|
-
it "reports the update correctly" do
|
424
|
-
expect(reporter).to receive(:update).with(text_context.installing(action.version_to_install))
|
425
|
-
subject.install(target_host, reporter)
|
426
|
-
end
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
context ":uploading" do
|
431
|
-
let(:event) { :uploading }
|
432
|
-
it "reports the update correctly" do
|
433
|
-
expect(reporter).to receive(:update).with(text_context.uploading)
|
434
|
-
subject.install(target_host, reporter)
|
435
|
-
end
|
436
|
-
end
|
437
|
-
|
438
|
-
context ":downloading" do
|
439
|
-
let(:event) { :downloading }
|
440
|
-
it "reports the update correctly" do
|
441
|
-
expect(reporter).to receive(:update).with(text_context.downloading)
|
442
|
-
subject.install(target_host, reporter)
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
context ":already_installed" do
|
447
|
-
let(:event) { :already_installed }
|
448
|
-
it "reports the update correctly" do
|
449
|
-
expect(reporter).to receive(:update).with(text_context.already_present(target_host.installed_chef_version))
|
450
|
-
subject.install(target_host, reporter)
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
context ":install_complete" do
|
455
|
-
let(:event) { :install_complete }
|
456
|
-
context "when installer is upgrading" do
|
457
|
-
let(:upgrading) { true }
|
458
|
-
it "reports the update correctly" do
|
459
|
-
expect(reporter).to receive(:update).with(text_context.upgrade_success(target_host.installed_chef_version,
|
460
|
-
action.version_to_install))
|
461
|
-
subject.install(target_host, reporter)
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
context "when installer installing clean" do
|
466
|
-
let(:upgrading) { false }
|
467
|
-
it "reports the update correctly" do
|
468
|
-
expect(reporter).to receive(:update).with(text_context.install_success(target_host.installed_chef_version))
|
469
|
-
subject.install(target_host, reporter)
|
470
|
-
end
|
471
|
-
end
|
472
|
-
end
|
473
|
-
end
|
474
|
-
end
|
475
|
-
end
|