chef-apply 0.1.17 → 0.1.18

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -7
  3. data/Gemfile.lock +176 -84
  4. data/chef-apply.gemspec +2 -2
  5. data/lib/chef_apply/version.rb +1 -1
  6. data/spec/fixtures/custom_config.toml +2 -0
  7. data/spec/integration/chef-run_spec.rb +41 -0
  8. data/spec/integration/fixtures/chef_help.out +69 -0
  9. data/spec/integration/fixtures/chef_version.out +1 -0
  10. data/spec/integration/spec_helper.rb +55 -0
  11. data/spec/spec_helper.rb +114 -0
  12. data/spec/support/matchers/output_to_terminal.rb +36 -0
  13. data/spec/unit/action/base_spec.rb +89 -0
  14. data/spec/unit/action/converge_target_spec.rb +292 -0
  15. data/spec/unit/action/generate_local_policy_spec.rb +114 -0
  16. data/spec/unit/action/generate_temp_cookbook_spec.rb +75 -0
  17. data/spec/unit/action/install_chef/base_spec.rb +234 -0
  18. data/spec/unit/action/install_chef_spec.rb +69 -0
  19. data/spec/unit/cli/options_spec.rb +75 -0
  20. data/spec/unit/cli/validation_spec.rb +78 -0
  21. data/spec/unit/cli_spec.rb +440 -0
  22. data/spec/unit/config_spec.rb +70 -0
  23. data/spec/unit/errors/ccr_failure_mapper_spec.rb +103 -0
  24. data/spec/unit/file_fetcher_spec.rb +40 -0
  25. data/spec/unit/fixtures/multi-error.out +2 -0
  26. data/spec/unit/log_spec.rb +37 -0
  27. data/spec/unit/recipe_lookup_spec.rb +122 -0
  28. data/spec/unit/startup_spec.rb +283 -0
  29. data/spec/unit/target_host_spec.rb +231 -0
  30. data/spec/unit/target_resolver_spec.rb +380 -0
  31. data/spec/unit/telemeter/sender_spec.rb +140 -0
  32. data/spec/unit/telemeter_spec.rb +191 -0
  33. data/spec/unit/temp_cookbook_spec.rb +199 -0
  34. data/spec/unit/ui/error_printer_spec.rb +173 -0
  35. data/spec/unit/ui/terminal_spec.rb +109 -0
  36. data/spec/unit/version_spec.rb +31 -0
  37. data/warning.txt +3 -0
  38. metadata +34 -2
@@ -0,0 +1,173 @@
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/ui/error_printer"
20
+ require "chef_apply/errors/standard_error_resolver"
21
+ require "chef_apply/target_host"
22
+
23
+ RSpec.describe ChefApply::UI::ErrorPrinter do
24
+ let(:orig_exception) { StandardError.new("test") }
25
+ let(:target_host) { ChefApply::TargetHost.instance_for_url("mock://localhost") }
26
+ let(:wrapped_exception) { ChefApply::WrappedError.new(orig_exception, target_host) }
27
+ subject(:printer) { ChefApply::UI::ErrorPrinter.new(wrapped_exception, nil) }
28
+
29
+ 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"
35
+ end
36
+ end
37
+
38
+ context "#format_body" do
39
+ RC = ChefApply::TargetHost
40
+ context "when exception is a ChefApply::Error" do
41
+ let(:result) { RemoteExecResult.new(1, "", "failed") }
42
+ let(:orig_exception) { RC::RemoteExecutionFailed.new("localhost", "test", result) }
43
+ it "invokes the right handler" do
44
+ expect(subject).to receive(:format_workstation_exception)
45
+ subject.format_body
46
+ end
47
+ end
48
+
49
+ context "when exception is a Train::Error" do
50
+ # These may expand as we find error-specific messaging we can provide to customers
51
+ # for more specific train exceptions
52
+ let(:orig_exception) { Train::Error.new("test") }
53
+ it "invokes the right handler" do
54
+ expect(subject).to receive(:format_train_exception)
55
+ subject.format_body
56
+ end
57
+ end
58
+
59
+ context "when exception is something else" do
60
+ # These may expand as we find error-specific messaging we can provide to customers
61
+ # for more specific general exceptions
62
+ it "invokes the right handler" do
63
+ expect(subject).to receive(:format_other_exception)
64
+ subject.format_body
65
+ end
66
+ end
67
+ end
68
+
69
+ context ".show_error" do
70
+ subject { ChefApply::UI::ErrorPrinter }
71
+ context "when handling a MultiJobFailure" do
72
+ it "recognizes it and invokes capture_multiple_failures" do
73
+ underlying_error = ChefApply::MultiJobFailure.new([])
74
+ error_to_process = ChefApply::Errors::StandardErrorResolver.wrap_exception(underlying_error)
75
+ expect(subject).to receive(:capture_multiple_failures).with(underlying_error)
76
+ subject.show_error(error_to_process)
77
+
78
+ end
79
+ end
80
+
81
+ context "when an error occurs in error handling" do
82
+ it "processes the new failure with dump_unexpected_error" do
83
+ error_to_raise = StandardError.new("this will be raised")
84
+ error_to_process = ChefApply::Errors::StandardErrorResolver.wrap_exception(StandardError.new("this is being shown"))
85
+ # Intercept a known call to raise an error
86
+ expect(ChefApply::UI::Terminal).to receive(:output).and_raise error_to_raise
87
+ expect(subject).to receive(:dump_unexpected_error).with(error_to_raise)
88
+ subject.show_error(error_to_process)
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ context ".capture_multiple_failures" do
95
+ subject { ChefApply::UI::ErrorPrinter }
96
+ let(:file_content_capture) { StringIO.new }
97
+ before do
98
+ allow(ChefApply::Config).to receive(:error_output_path).and_return "/dev/null"
99
+ allow(File).to receive(:open).with("/dev/null", "w").and_yield(file_content_capture)
100
+ end
101
+
102
+ it "should write a properly formatted error file" do
103
+ # TODO - add support for test-only i18n content, so that we don't have
104
+ # to rely on specific known error IDs that may change or be removed,
105
+ # and arent' directly relevant to the test at hand.
106
+ job1 = double("Job", target_host: double("TargetHost", hostname: "host1"),
107
+ exception: ChefApply::Error.new("CHEFUPL005"))
108
+ job2 = double("Job", target_host: double("TargetHost", hostname: "host2"),
109
+ exception: StandardError.new("Hello World"))
110
+
111
+ expected_content = File.read("spec/unit/fixtures/multi-error.out")
112
+ multifailure = ChefApply::MultiJobFailure.new([job1, job2] )
113
+ subject.capture_multiple_failures(multifailure)
114
+ expect(file_content_capture.string).to eq expected_content
115
+ end
116
+ end
117
+
118
+ context "#format_footer" do
119
+ let(:show_log) { true }
120
+ let(:show_stack) { true }
121
+ let(:formatter) do
122
+ ChefApply::UI::ErrorPrinter.new(wrapped_exception, nil)
123
+ end
124
+
125
+ subject(:format_footer) do
126
+ lambda { formatter.format_footer }
127
+ end
128
+
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
+ context "when both log and stack wanted" do
135
+ let(:show_log) { true }
136
+ let(:show_stack) { true }
137
+ assert_string_lookup("errors.footer.both")
138
+ end
139
+
140
+ context "when only log is wanted" do
141
+ let(:show_log) { true }
142
+ let(:show_stack) { false }
143
+ assert_string_lookup("errors.footer.log_only")
144
+ end
145
+
146
+ context "when only stack is wanted" do
147
+ let(:show_log) { false }
148
+ let(:show_stack) { true }
149
+ assert_string_lookup("errors.footer.stack_only")
150
+ end
151
+
152
+ context "when neither log nor stack wanted" do
153
+ let(:show_log) { false }
154
+ let(:show_stack) { false }
155
+ assert_string_lookup("errors.footer.neither")
156
+ end
157
+ end
158
+
159
+ context ".write_backtrace" do
160
+ let(:inst) { double(ChefApply::UI::ErrorPrinter) }
161
+ before do
162
+ allow(ChefApply::UI::ErrorPrinter).to receive(:new).and_return inst
163
+ end
164
+
165
+ let(:orig_args) { %w{test} }
166
+ it "formats and saves the backtrace" do
167
+ expect(inst).to receive(:add_backtrace_header).with(anything(), orig_args)
168
+ expect(inst).to receive(:add_formatted_backtrace)
169
+ expect(inst).to receive(:save_backtrace)
170
+ ChefApply::UI::ErrorPrinter.write_backtrace(wrapped_exception, orig_args)
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,109 @@
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/ui/terminal"
20
+
21
+ RSpec.describe ChefApply::UI::Terminal do
22
+ Terminal = ChefApply::UI::Terminal
23
+ # Lets send our Terminal output somewhere so it does not clutter the
24
+ # test output
25
+ Terminal.location = StringIO.new
26
+
27
+ it "correctly outputs a message" do
28
+ expect { Terminal.output("test") }
29
+ .to output("test\n").to_terminal
30
+ end
31
+
32
+ context "#render_job" do
33
+ it "executes the provided block" do
34
+ @ran = false
35
+ Terminal.render_job("a message") { |reporter| @ran = true }
36
+ expect(@ran).to eq true
37
+ end
38
+ end
39
+
40
+ context "#render_parallel_jobs" do
41
+ it "executes the provided job instances" do
42
+ @job1ran = false
43
+ @job2ran = false
44
+ job1 = Terminal::Job.new("prefix", nil) do
45
+ @job1ran = true
46
+ end
47
+ job2 = Terminal::Job.new("prefix", nil) do
48
+ @job2ran = true
49
+ end
50
+ Terminal.render_parallel_jobs("a message", [job1, job2])
51
+ expect(@job1ran).to eq true
52
+ expect(@job2ran).to eq true
53
+ end
54
+ end
55
+
56
+ describe ChefApply::UI::Terminal::Job do
57
+ subject { ChefApply::UI::Terminal::Job }
58
+ context "#exception" do
59
+ context "when no exception occurs in execution" do
60
+ context "and it's been invoked directly" do
61
+ it "exception is nil" do
62
+ job = subject.new("", nil) { 0 }
63
+ job.run(ChefApply::MockReporter.new)
64
+ expect(job.exception).to eq nil
65
+ end
66
+ end
67
+ context "and it's running in a thread alongside other jobs" do
68
+ it "exception is nil for each job" do
69
+ job1 = subject.new("", nil) { 0 }
70
+ job2 = subject.new("", nil) { 0 }
71
+ threads = []
72
+ threads << Thread.new { job1.run(ChefApply::MockReporter.new) }
73
+ threads << Thread.new { job2.run(ChefApply::MockReporter.new) }
74
+ threads.each(&:join)
75
+ expect(job1.exception).to eq nil
76
+ expect(job2.exception).to eq nil
77
+
78
+ end
79
+ end
80
+ end
81
+ context "when an exception occurs in execution" do
82
+ context "and it's been invoked directly" do
83
+ it "captures the exception in #exception" do
84
+ expected_exception = StandardError.new("exception 1")
85
+ job = subject.new("", nil) { |arg| raise expected_exception }
86
+ job.run(ChefApply::MockReporter.new)
87
+ expect(job.exception).to eq expected_exception
88
+ end
89
+ end
90
+
91
+ context "and it's running in a thread alongside other jobs" do
92
+ it "each job holds its own exception" do
93
+ e1 = StandardError.new("exception 1")
94
+ e2 = StandardError.new("exception 2")
95
+
96
+ job1 = subject.new("", nil) { |_| raise e1 }
97
+ job2 = subject.new("", nil) { |_| raise e2 }
98
+ threads = []
99
+ threads << Thread.new { job1.run(ChefApply::MockReporter.new) }
100
+ threads << Thread.new { job2.run(ChefApply::MockReporter.new) }
101
+ threads.each(&:join)
102
+ expect(job1.exception).to eq e1
103
+ expect(job2.exception).to eq e2
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,31 @@
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/version"
20
+
21
+ RSpec.describe ChefApply::VERSION do
22
+ subject(:version) do
23
+ ChefApply::VERSION
24
+ end
25
+
26
+ context "VERSION" do
27
+ it "returns the version" do
28
+ expect(Gem::Version.correct?(version)).to be_truthy
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ Chef Apply is not meant to be installed as a gem. It is meant to be installed
2
+ as part of the Chef Workstation omnibus package. Please download and install
3
+ that from https://downloads.chef.io/chef-dk/
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.17
4
+ version: 0.1.18
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-07-30 00:00:00.000000000 Z
11
+ date: 2018-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-cli
@@ -356,6 +356,38 @@ files:
356
356
  - lib/chef_apply/ui/plain_text_element.rb
357
357
  - lib/chef_apply/ui/terminal.rb
358
358
  - lib/chef_apply/version.rb
359
+ - spec/fixtures/custom_config.toml
360
+ - spec/integration/chef-run_spec.rb
361
+ - spec/integration/fixtures/chef_help.out
362
+ - spec/integration/fixtures/chef_version.out
363
+ - spec/integration/spec_helper.rb
364
+ - spec/spec_helper.rb
365
+ - spec/support/matchers/output_to_terminal.rb
366
+ - spec/unit/action/base_spec.rb
367
+ - spec/unit/action/converge_target_spec.rb
368
+ - spec/unit/action/generate_local_policy_spec.rb
369
+ - spec/unit/action/generate_temp_cookbook_spec.rb
370
+ - spec/unit/action/install_chef/base_spec.rb
371
+ - spec/unit/action/install_chef_spec.rb
372
+ - spec/unit/cli/options_spec.rb
373
+ - spec/unit/cli/validation_spec.rb
374
+ - spec/unit/cli_spec.rb
375
+ - spec/unit/config_spec.rb
376
+ - spec/unit/errors/ccr_failure_mapper_spec.rb
377
+ - spec/unit/file_fetcher_spec.rb
378
+ - spec/unit/fixtures/multi-error.out
379
+ - spec/unit/log_spec.rb
380
+ - spec/unit/recipe_lookup_spec.rb
381
+ - spec/unit/startup_spec.rb
382
+ - spec/unit/target_host_spec.rb
383
+ - spec/unit/target_resolver_spec.rb
384
+ - spec/unit/telemeter/sender_spec.rb
385
+ - spec/unit/telemeter_spec.rb
386
+ - spec/unit/temp_cookbook_spec.rb
387
+ - spec/unit/ui/error_printer_spec.rb
388
+ - spec/unit/ui/terminal_spec.rb
389
+ - spec/unit/version_spec.rb
390
+ - warning.txt
359
391
  homepage: https://github.com/chef/chef-apply
360
392
  licenses:
361
393
  - Apache-2.0