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