chef-apply 0.1.21 → 0.1.27
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 +31 -28
- data/i18n/en.yml +11 -0
- data/i18n/errors/en.yml +286 -171
- data/lib/chef_apply/action/converge_target.rb +11 -1
- data/lib/chef_apply/cli.rb +7 -2
- data/lib/chef_apply/config.rb +3 -1
- data/lib/chef_apply/startup.rb +23 -0
- data/lib/chef_apply/target_host.rb +6 -0
- data/lib/chef_apply/text.rb +10 -2
- data/lib/chef_apply/text/error_translation.rb +69 -0
- data/lib/chef_apply/ui/error_printer.rb +20 -22
- data/lib/chef_apply/ui/plain_text_element.rb +4 -1
- data/lib/chef_apply/ui/plain_text_header.rb +46 -0
- data/lib/chef_apply/ui/terminal.rb +25 -34
- data/lib/chef_apply/ui/terminal/job.rb +39 -0
- data/lib/chef_apply/version.rb +1 -1
- data/spec/unit/action/converge_target_spec.rb +52 -0
- data/spec/unit/cli_spec.rb +9 -3
- data/spec/unit/startup_spec.rb +42 -1
- data/spec/unit/text/error_translation_spec.rb +105 -0
- data/spec/unit/ui/error_printer_spec.rb +38 -14
- data/spec/unit/ui/terminal_spec.rb +4 -1
- metadata +6 -2
@@ -0,0 +1,39 @@
|
|
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
|
+
module ChefApply
|
19
|
+
module UI
|
20
|
+
class Terminal
|
21
|
+
class Job
|
22
|
+
attr_reader :proc, :prefix, :target_host, :exception
|
23
|
+
def initialize(prefix, target_host, &block)
|
24
|
+
@proc = block
|
25
|
+
@prefix = prefix
|
26
|
+
@target_host = target_host
|
27
|
+
@error = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def run(reporter)
|
31
|
+
@proc.call(reporter)
|
32
|
+
rescue => e
|
33
|
+
reporter.error(e.to_s)
|
34
|
+
@exception = e
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/chef_apply/version.rb
CHANGED
@@ -75,6 +75,58 @@ RSpec.describe ChefApply::Action::ConvergeTarget do
|
|
75
75
|
expect(local_tempfile.closed?).to eq(true)
|
76
76
|
end
|
77
77
|
|
78
|
+
describe "when target_level is left default" do
|
79
|
+
before do
|
80
|
+
ChefApply::Config.reset
|
81
|
+
end
|
82
|
+
it "creates a config file without a specific log_level (leaving default for chef-client)" do
|
83
|
+
expect(Tempfile).to receive(:new).and_return(local_tempfile)
|
84
|
+
expect(local_tempfile).to receive(:write).with(<<~EOM
|
85
|
+
local_mode true
|
86
|
+
color false
|
87
|
+
cache_path "\#{ENV['APPDATA']}/chef-workstation"
|
88
|
+
chef_repo_path "\#{ENV['APPDATA']}/chef-workstation"
|
89
|
+
require_relative "reporter"
|
90
|
+
reporter = ChefApply::Reporter.new
|
91
|
+
report_handlers << reporter
|
92
|
+
exception_handlers << reporter
|
93
|
+
EOM
|
94
|
+
)
|
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)
|
97
|
+
expect(local_tempfile.closed?).to eq(true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "when target_level is set to a value" do
|
102
|
+
before do
|
103
|
+
ChefApply::Config.log.target_level = "info"
|
104
|
+
end
|
105
|
+
|
106
|
+
after do
|
107
|
+
ChefApply::Config.reset
|
108
|
+
end
|
109
|
+
|
110
|
+
it "creates a config file with the log_level set to the right value" do
|
111
|
+
expect(Tempfile).to receive(:new).and_return(local_tempfile)
|
112
|
+
expect(local_tempfile).to receive(:write).with(<<~EOM
|
113
|
+
local_mode true
|
114
|
+
color false
|
115
|
+
cache_path "\#{ENV['APPDATA']}/chef-workstation"
|
116
|
+
chef_repo_path "\#{ENV['APPDATA']}/chef-workstation"
|
117
|
+
require_relative "reporter"
|
118
|
+
reporter = ChefApply::Reporter.new
|
119
|
+
report_handlers << reporter
|
120
|
+
exception_handlers << reporter
|
121
|
+
log_level :info
|
122
|
+
EOM
|
123
|
+
)
|
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)
|
126
|
+
expect(local_tempfile.closed?).to eq(true)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
78
130
|
describe "when data_collector is set in config" do
|
79
131
|
before do
|
80
132
|
ChefApply::Config.data_collector.url = "dc.url"
|
data/spec/unit/cli_spec.rb
CHANGED
@@ -293,13 +293,19 @@ RSpec.describe ChefApply::CLI do
|
|
293
293
|
let(:temp_cookbook) { double(ChefApply::TempCookbook) }
|
294
294
|
let(:archive_file_location) { "/path/to/archive" }
|
295
295
|
let(:args) { [] }
|
296
|
-
before do
|
297
|
-
|
298
|
-
end
|
296
|
+
# before do
|
297
|
+
# allow(ChefApply::UI::Terminal).to receive(:render_job).and_yield(reporter)
|
298
|
+
# end
|
299
299
|
|
300
300
|
it "generates the cookbook and local policy" do
|
301
|
+
expect(ChefApply::UI::Terminal).to receive(:render_job) do |initial_msg, job|
|
302
|
+
job.run(reporter)
|
303
|
+
end
|
301
304
|
expect(subject).to receive(:generate_temp_cookbook)
|
302
305
|
.with(args, reporter).and_return temp_cookbook
|
306
|
+
expect(ChefApply::UI::Terminal).to receive(:render_job) do |initial_msg, job|
|
307
|
+
job.run(reporter)
|
308
|
+
end
|
303
309
|
expect(subject).to receive(:generate_local_policy)
|
304
310
|
.with(reporter).and_return archive_file_location
|
305
311
|
subject.render_cookbook_setup(args)
|
data/spec/unit/startup_spec.rb
CHANGED
@@ -25,7 +25,8 @@ RSpec.describe ChefApply::Startup do
|
|
25
25
|
|
26
26
|
describe "#run" do
|
27
27
|
it "performs ordered startup tasks and invokes the CLI" do
|
28
|
-
ordered_messages = [:
|
28
|
+
ordered_messages = [:verify_not_in_chefdk,
|
29
|
+
:first_run_tasks,
|
29
30
|
:setup_workstation_user_directories,
|
30
31
|
:setup_error_handling,
|
31
32
|
:load_config,
|
@@ -37,6 +38,7 @@ RSpec.describe ChefApply::Startup do
|
|
37
38
|
end
|
38
39
|
subject.run()
|
39
40
|
end
|
41
|
+
|
40
42
|
context "when errors happen" do
|
41
43
|
let(:error) { nil }
|
42
44
|
let(:error_text) { ChefApply::Text.cli.error }
|
@@ -90,6 +92,16 @@ RSpec.describe ChefApply::Startup do
|
|
90
92
|
end
|
91
93
|
end
|
92
94
|
|
95
|
+
context "when a UnsupportedInstallation exception is raised" do
|
96
|
+
let(:error) { ChefApply::Startup::UnsupportedInstallation.new }
|
97
|
+
|
98
|
+
it "shows the correct error" do
|
99
|
+
expected_text = error_text.unsupported_installation
|
100
|
+
expect(ChefApply::UI::Terminal).to receive(:output).with(expected_text)
|
101
|
+
subject.run
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
93
105
|
context "when a Tomlrb::ParserError is raised" do
|
94
106
|
let(:msg) { "Parse failed." }
|
95
107
|
let(:error) { Tomlrb::ParseError.new(msg) }
|
@@ -102,12 +114,40 @@ RSpec.describe ChefApply::Startup do
|
|
102
114
|
end
|
103
115
|
end
|
104
116
|
end
|
117
|
+
|
105
118
|
describe "#init_terminal" do
|
106
119
|
it "initializees the terminal for stdout" do
|
107
120
|
expect(ChefApply::UI::Terminal).to receive(:init).with($stdout)
|
108
121
|
subject.init_terminal
|
109
122
|
end
|
110
123
|
end
|
124
|
+
|
125
|
+
describe "#verify_not_in_chefdk" do
|
126
|
+
before do
|
127
|
+
allow(subject).to receive(:script_path).and_return script_path
|
128
|
+
end
|
129
|
+
|
130
|
+
context "when chef-run has been loaded from a *nix chefdk path" do
|
131
|
+
let(:script_path) { "/opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-apply/startup.rb" }
|
132
|
+
it "raises an UnsupportedInstallation error" do
|
133
|
+
expect { subject.verify_not_in_chefdk }.to raise_error(ChefApply::Startup::UnsupportedInstallation)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
context "when chef-run has been loaded from a Windows chefdk path" do
|
137
|
+
let(:script_path) { "C:\\chefdk\\embedded\\lib\\ruby\\gems\\2.5.0\\gems\\chef-apply\\startup.rb" }
|
138
|
+
it "raises an UnsupportedInstallation error" do
|
139
|
+
expect { subject.verify_not_in_chefdk }.to raise_error(ChefApply::Startup::UnsupportedInstallation)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when chef-run has been loaded from anywhere else" do
|
144
|
+
let(:script_path) { "/home/user1/dev/chef-apply" }
|
145
|
+
it "runs without error" do
|
146
|
+
subject.verify_not_in_chefdk
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
111
151
|
describe "#first_run_tasks" do
|
112
152
|
let(:first_run_complete) { true }
|
113
153
|
before do
|
@@ -122,6 +162,7 @@ RSpec.describe ChefApply::Startup do
|
|
122
162
|
subject.first_run_tasks
|
123
163
|
end
|
124
164
|
end
|
165
|
+
|
125
166
|
context "when first run has not already occurred" do
|
126
167
|
let(:first_run_complete) { false }
|
127
168
|
it "Performs required first-run tasks" do
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2017 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/text"
|
20
|
+
|
21
|
+
RSpec.describe ChefApply::Text::ErrorTranslation do
|
22
|
+
|
23
|
+
let(:display_defaults) do
|
24
|
+
{
|
25
|
+
decorations: true,
|
26
|
+
header: true,
|
27
|
+
footer: true,
|
28
|
+
stack: false,
|
29
|
+
log: false }
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:error_table) do
|
33
|
+
{ display_defaults: display_defaults,
|
34
|
+
TESTERROR: test_error } end
|
35
|
+
|
36
|
+
let(:test_error_text) { "This is a test error" }
|
37
|
+
let(:test_error) { {} }
|
38
|
+
|
39
|
+
subject { ChefApply::Text::ErrorTranslation }
|
40
|
+
let(:error_mock) do
|
41
|
+
double("R18n::Translated",
|
42
|
+
text: test_error_text ) end
|
43
|
+
let(:translation_mock) do
|
44
|
+
double("R18n::Translated",
|
45
|
+
TESTERROR: error_mock,
|
46
|
+
text: test_error_text ) end
|
47
|
+
before do
|
48
|
+
# Mock out the R18n portion - our methods care only that the key exists, and
|
49
|
+
# the test focus is on the display metadata.
|
50
|
+
allow(ChefApply::Text).to receive(:errors).and_return translation_mock
|
51
|
+
allow(ChefApply::Text).to receive(:_error_table).and_return(error_table)
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when some display attributes are specified" do
|
55
|
+
let(:test_error) { { display: { stack: true, log: true } } }
|
56
|
+
it "sets display attributes to specified values and defaults remaining" do
|
57
|
+
translation = subject.new("TESTERROR")
|
58
|
+
expect(translation.decorations).to be true
|
59
|
+
expect(translation.header).to be true
|
60
|
+
expect(translation.footer).to be true
|
61
|
+
expect(translation.stack).to be true
|
62
|
+
expect(translation.log).to be true
|
63
|
+
expect(translation.message).to eq test_error_text
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when all display attributes are specified" do
|
68
|
+
let(:test_error) do
|
69
|
+
{ display: { decorations: false, header: false,
|
70
|
+
footer: false, stack: true, log: true } } end
|
71
|
+
it "sets display attributes to specified values with no defaults" do
|
72
|
+
translation = subject.new("TESTERROR")
|
73
|
+
expect(translation.decorations).to be false
|
74
|
+
expect(translation.header).to be false
|
75
|
+
expect(translation.footer).to be false
|
76
|
+
expect(translation.stack).to be true
|
77
|
+
expect(translation.log).to be true
|
78
|
+
expect(translation.message).to eq test_error_text
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when no attributes for an error are specified" do
|
83
|
+
let(:test_error) { {} }
|
84
|
+
it "sets display attribute to default values and references the correct message" do
|
85
|
+
translation = subject.new("TESTERROR")
|
86
|
+
expect(translation.decorations).to be true
|
87
|
+
expect(translation.header).to be true
|
88
|
+
expect(translation.footer).to be true
|
89
|
+
expect(translation.stack).to be false
|
90
|
+
expect(translation.log).to be false
|
91
|
+
expect(translation.message).to eq test_error_text
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when invalid attributes for an error are specified" do
|
96
|
+
let(:test_error) { { display: { bad_value: true } } }
|
97
|
+
it "raises InvalidDisplayAttributes when invalid attributes are specified" do
|
98
|
+
expect { subject.new("TESTERROR") }
|
99
|
+
.to raise_error(ChefApply::Text::ErrorTranslation::InvalidDisplayAttributes) do |e|
|
100
|
+
expect(e.invalid_attrs).to eq({ bad_value: true })
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -17,21 +17,52 @@
|
|
17
17
|
|
18
18
|
require "spec_helper"
|
19
19
|
require "chef_apply/ui/error_printer"
|
20
|
+
require "chef_apply/text/error_translation"
|
20
21
|
require "chef_apply/errors/standard_error_resolver"
|
21
22
|
require "chef_apply/target_host"
|
22
23
|
|
23
24
|
RSpec.describe ChefApply::UI::ErrorPrinter do
|
25
|
+
|
24
26
|
let(:orig_exception) { StandardError.new("test") }
|
25
27
|
let(:target_host) { ChefApply::TargetHost.instance_for_url("mock://localhost") }
|
26
28
|
let(:wrapped_exception) { ChefApply::WrappedError.new(orig_exception, target_host) }
|
27
|
-
|
29
|
+
|
30
|
+
let(:show_footer) { true }
|
31
|
+
let(:show_log) { true }
|
32
|
+
let(:show_stack) { true }
|
33
|
+
let(:has_decorations) { true }
|
34
|
+
let(:show_header) { true }
|
35
|
+
let(:translation_mock) do
|
36
|
+
instance_double("ChefApply::Errors::ErrorTranslation",
|
37
|
+
footer: show_footer,
|
38
|
+
log: show_log,
|
39
|
+
stack: show_stack,
|
40
|
+
header: show_header,
|
41
|
+
decorations: has_decorations
|
42
|
+
)
|
43
|
+
end
|
44
|
+
subject { ChefApply::UI::ErrorPrinter.new(wrapped_exception, nil) }
|
45
|
+
|
46
|
+
before do
|
47
|
+
allow(ChefApply::Text::ErrorTranslation).to receive(:new).and_return translation_mock
|
48
|
+
end
|
28
49
|
|
29
50
|
context "#format_error" do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
51
|
+
|
52
|
+
context "and the message has decorations" do
|
53
|
+
let(:has_decorations) { true }
|
54
|
+
it "formats the message using the correct method" do
|
55
|
+
expect(subject).to receive(:format_decorated).and_return "decorated"
|
56
|
+
subject.format_error
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "and the message does not have decorations" do
|
61
|
+
let(:has_decorations) { false }
|
62
|
+
it "formats the message using the correct method" do
|
63
|
+
expect(subject).to receive(:format_undecorated).and_return "undecorated"
|
64
|
+
subject.format_error
|
65
|
+
end
|
35
66
|
end
|
36
67
|
end
|
37
68
|
|
@@ -116,21 +147,14 @@ RSpec.describe ChefApply::UI::ErrorPrinter do
|
|
116
147
|
end
|
117
148
|
|
118
149
|
context "#format_footer" do
|
119
|
-
let(:show_log) { true }
|
120
|
-
let(:show_stack) { true }
|
121
150
|
let(:formatter) do
|
122
151
|
ChefApply::UI::ErrorPrinter.new(wrapped_exception, nil)
|
123
152
|
end
|
124
153
|
|
125
|
-
subject
|
154
|
+
subject do
|
126
155
|
lambda { formatter.format_footer }
|
127
156
|
end
|
128
157
|
|
129
|
-
before do
|
130
|
-
allow(formatter).to receive(:show_log).and_return show_log
|
131
|
-
allow(formatter).to receive(:show_stack).and_return show_stack
|
132
|
-
end
|
133
|
-
|
134
158
|
context "when both log and stack wanted" do
|
135
159
|
let(:show_log) { true }
|
136
160
|
let(:show_stack) { true }
|
@@ -32,7 +32,10 @@ RSpec.describe ChefApply::UI::Terminal do
|
|
32
32
|
context "#render_job" do
|
33
33
|
it "executes the provided block" do
|
34
34
|
@ran = false
|
35
|
-
Terminal.
|
35
|
+
job = Terminal::Job.new("prefix", nil) do
|
36
|
+
@ran = true
|
37
|
+
end
|
38
|
+
Terminal.render_job("a message", job)
|
36
39
|
expect(@ran).to eq true
|
37
40
|
end
|
38
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-apply
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.27
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-cli
|
@@ -352,10 +352,13 @@ files:
|
|
352
352
|
- lib/chef_apply/telemeter/sender.rb
|
353
353
|
- lib/chef_apply/temp_cookbook.rb
|
354
354
|
- lib/chef_apply/text.rb
|
355
|
+
- lib/chef_apply/text/error_translation.rb
|
355
356
|
- lib/chef_apply/text/text_wrapper.rb
|
356
357
|
- lib/chef_apply/ui/error_printer.rb
|
357
358
|
- lib/chef_apply/ui/plain_text_element.rb
|
359
|
+
- lib/chef_apply/ui/plain_text_header.rb
|
358
360
|
- lib/chef_apply/ui/terminal.rb
|
361
|
+
- lib/chef_apply/ui/terminal/job.rb
|
359
362
|
- lib/chef_apply/version.rb
|
360
363
|
- spec/fixtures/custom_config.toml
|
361
364
|
- spec/integration/chef-run_spec.rb
|
@@ -386,6 +389,7 @@ files:
|
|
386
389
|
- spec/unit/telemeter/sender_spec.rb
|
387
390
|
- spec/unit/telemeter_spec.rb
|
388
391
|
- spec/unit/temp_cookbook_spec.rb
|
392
|
+
- spec/unit/text/error_translation_spec.rb
|
389
393
|
- spec/unit/ui/error_printer_spec.rb
|
390
394
|
- spec/unit/ui/terminal_spec.rb
|
391
395
|
- spec/unit/version_spec.rb
|