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.
@@ -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
@@ -16,5 +16,5 @@
16
16
  #
17
17
 
18
18
  module ChefApply
19
- VERSION = "0.1.21"
19
+ VERSION = "0.1.27"
20
20
  end
@@ -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"
@@ -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
- allow(ChefApply::UI::Terminal).to receive(:render_job).and_yield(reporter)
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)
@@ -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 = [:first_run_tasks,
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
- subject(:printer) { ChefApply::UI::ErrorPrinter.new(wrapped_exception, nil) }
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
- it "formats the message" do
31
- expect(subject).to receive(:format_header).and_return "header"
32
- expect(subject).to receive(:format_body).and_return "body"
33
- expect(subject).to receive(:format_footer).and_return "footer"
34
- expect(subject.format_error).to eq "\nheader\n\nbody\nfooter\n"
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(:format_footer) do
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.render_job("a message") { |reporter| @ran = true }
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.21
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-08-09 00:00:00.000000000 Z
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