license-acceptance 0.2.10 → 1.0.5

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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/config/product_info.toml +19 -10
  4. data/lib/license_acceptance/acceptor.rb +76 -36
  5. data/lib/license_acceptance/product.rb +10 -5
  6. data/lib/license_acceptance/product_reader.rb +22 -11
  7. data/lib/license_acceptance/strategy/argument.rb +44 -0
  8. data/lib/license_acceptance/strategy/base.rb +7 -0
  9. data/lib/license_acceptance/strategy/environment.rb +38 -0
  10. data/lib/license_acceptance/strategy/file.rb +103 -0
  11. data/lib/license_acceptance/strategy/prompt.rb +111 -0
  12. data/lib/license_acceptance/strategy/provided_value.rb +28 -0
  13. data/lib/license_acceptance/version.rb +1 -1
  14. data/spec/license_acceptance/acceptor_spec.rb +115 -94
  15. data/spec/license_acceptance/product_reader_spec.rb +21 -5
  16. data/spec/license_acceptance/product_spec.rb +4 -2
  17. data/spec/license_acceptance/strategy/argument_spec.rb +82 -0
  18. data/spec/license_acceptance/strategy/environment_spec.rb +76 -0
  19. data/spec/license_acceptance/{file_acceptance_spec.rb → strategy/file_spec.rb} +21 -15
  20. data/spec/license_acceptance/{prompt_acceptance_spec.rb → strategy/prompt_spec.rb} +6 -6
  21. data/spec/license_acceptance/strategy/provided_value_spec.rb +55 -0
  22. metadata +14 -11
  23. data/lib/license_acceptance/arg_acceptance.rb +0 -32
  24. data/lib/license_acceptance/env_acceptance.rb +0 -26
  25. data/lib/license_acceptance/file_acceptance.rb +0 -97
  26. data/lib/license_acceptance/prompt_acceptance.rb +0 -106
  27. data/spec/license_acceptance/arg_acceptance_spec.rb +0 -57
  28. data/spec/license_acceptance/env_acceptance_spec.rb +0 -65
@@ -0,0 +1,111 @@
1
+ require 'tty-prompt'
2
+ require 'pastel'
3
+ require "license_acceptance/logger"
4
+ require "license_acceptance/strategy/base"
5
+ require "timeout"
6
+
7
+ module LicenseAcceptance
8
+ module Strategy
9
+
10
+ # Interactive prompt for accepting and persistnce license acceptance, or failing with custom exit code
11
+ class Prompt < Base
12
+ include Logger
13
+
14
+ attr_reader :output
15
+
16
+ def initialize(config)
17
+ @output = config.output
18
+ end
19
+
20
+ WIDTH = 50.freeze
21
+ PASTEL = Pastel.new
22
+ BORDER = "+---------------------------------------------+".freeze
23
+ YES = PASTEL.green.bold("yes")
24
+ CHECK = PASTEL.green("✔")
25
+
26
+ def request(missing_licenses, &persist_callback)
27
+ logger.debug("Requesting a license for #{missing_licenses.map(&:id)}")
28
+ c = missing_licenses.size
29
+ s = c > 1 ? "s": ""
30
+
31
+ acceptance_question = "Do you accept the #{c} product license#{s} (#{YES}/no)?"
32
+ output.puts <<~EOM
33
+ #{BORDER}
34
+ Chef License Acceptance
35
+
36
+ Before you can continue, #{c} product license#{s}
37
+ must be accepted. View the license at
38
+ https://www.chef.io/end-user-license-agreement/
39
+
40
+ License#{s} that need accepting:
41
+ * #{missing_licenses.map(&:pretty_name).join("\n * ")}
42
+
43
+ #{acceptance_question}
44
+
45
+ EOM
46
+
47
+ if ask(output, c, s, persist_callback)
48
+ output.puts BORDER
49
+ return true
50
+ end
51
+
52
+ output.puts <<~EOM
53
+
54
+ If you do not accept this license you will
55
+ not be able to use Chef products.
56
+
57
+ #{acceptance_question}
58
+
59
+ EOM
60
+
61
+ answer = ask(output, c, s, persist_callback)
62
+ if answer != "yes"
63
+ output.puts BORDER
64
+ end
65
+ return answer
66
+ end
67
+
68
+ private
69
+
70
+ def ask(output, c, s, persist_callback)
71
+ logger.debug("Attempting to request interactive prompt on TTY")
72
+ prompt = TTY::Prompt.new(track_history: false, active_color: :bold, interrupt: :exit, output: output)
73
+
74
+ answer = "no"
75
+ begin
76
+ Timeout::timeout(60, PromptTimeout) do
77
+ answer = prompt.ask(">") do |q|
78
+ q.modify :down, :trim
79
+ q.required true
80
+ q.messages[:required?] = "You must enter 'yes' or 'no'"
81
+ q.validate /^\s*(yes|no)\s*$/i
82
+ q.messages[:valid?] = "You must enter 'yes' or 'no'"
83
+ end
84
+ end
85
+ rescue PromptTimeout
86
+ prompt.unsubscribe(prompt.reader)
87
+ output.puts "Prompt timed out. Use non-interactive flags or enter an answer within 60 seconds."
88
+ end
89
+
90
+ if answer == "yes"
91
+ output.puts
92
+ output.puts "Persisting #{c} product license#{s}..."
93
+ errs = persist_callback.call
94
+ if errs.empty?
95
+ output.puts "#{CHECK} #{c} product license#{s} persisted.\n\n"
96
+ else
97
+ output.puts <<~EOM
98
+ #{CHECK} #{c} product license#{s} accepted.
99
+ Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
100
+ EOM
101
+ end
102
+ return true
103
+ end
104
+ return false
105
+ end
106
+ end
107
+
108
+ class PromptTimeout < StandardError; end
109
+
110
+ end
111
+ end
@@ -0,0 +1,28 @@
1
+ require "license_acceptance/strategy/base"
2
+
3
+ module LicenseAcceptance
4
+ module Strategy
5
+
6
+ # Used for library consumers to parse their own form of acceptance (knife config, omnibus config, etc.) and pass it in
7
+ class ProvidedValue < Base
8
+ attr_reader :value
9
+
10
+ def initialize(value)
11
+ @value = value
12
+ end
13
+
14
+ def accepted?
15
+ value == ACCEPT
16
+ end
17
+
18
+ def silent?
19
+ value == ACCEPT_SILENT
20
+ end
21
+
22
+ def no_persist?
23
+ value == ACCEPT_NO_PERSIST
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module LicenseAcceptance
2
- VERSION = "0.2.10"
2
+ VERSION = "1.0.5"
3
3
  end
@@ -12,90 +12,109 @@ RSpec.describe LicenseAcceptance::Acceptor do
12
12
  d
13
13
  end
14
14
  let(:opts) { { output: output } }
15
+ let(:reader) { instance_double(LicenseAcceptance::ProductReader) }
15
16
  let(:acc) { LicenseAcceptance::Acceptor.new(opts) }
16
- let(:product) { "chef_client" }
17
+ let(:product) { instance_double(LicenseAcceptance::Product, id: "foo", pretty_name: "Foo") }
17
18
  let(:version) { "version" }
18
- let(:relationship) { instance_double(LicenseAcceptance::ProductRelationship) }
19
- let(:p1) { instance_double(LicenseAcceptance::Product) }
20
- let(:missing) { [p1] }
19
+ let(:relationship) { instance_double(LicenseAcceptance::ProductRelationship, parent: product) }
20
+ let(:missing) { [product] }
21
21
 
22
22
  describe "#check_and_persist!" do
23
- let(:err) { LicenseAcceptance::LicenseNotAcceptedError.new([product]) }
23
+ before do
24
+ expect(LicenseAcceptance::ProductReader).to receive(:new).and_return(reader)
25
+ expect(reader).to receive(:read)
26
+ end
27
+
28
+ let(:err) { LicenseAcceptance::LicenseNotAcceptedError.new(product, [product]) }
24
29
  it "outputs an error message to stdout and exits when license acceptance is declined" do
25
30
  expect(acc).to receive(:check_and_persist).and_raise(err)
26
- expect { acc.check_and_persist!(product, version) }.to raise_error(SystemExit)
27
- expect(output.string).to match(/#{product}/)
31
+ expect { acc.check_and_persist!(product.id, version) }.to raise_error(SystemExit)
32
+ expect(output.string).to match(/#{product.pretty_name}/)
28
33
  end
29
34
  end
30
35
 
31
36
  describe "#check_and_persist" do
32
- let(:reader) { instance_double(LicenseAcceptance::ProductReader) }
33
- let(:file_acc) { instance_double(LicenseAcceptance::FileAcceptance) }
34
- let(:arg_acc) { instance_double(LicenseAcceptance::ArgAcceptance) }
35
- let(:prompt_acc) { instance_double(LicenseAcceptance::PromptAcceptance) }
36
- let(:env_acc) { instance_double(LicenseAcceptance::EnvAcceptance) }
37
+ let(:file_acc) { instance_double(LicenseAcceptance::Strategy::File) }
38
+ let(:arg_acc) { instance_double(LicenseAcceptance::Strategy::Argument) }
39
+ let(:prompt_acc) { instance_double(LicenseAcceptance::Strategy::Prompt) }
40
+ let(:env_acc) { instance_double(LicenseAcceptance::Strategy::Environment) }
41
+ let(:provided_acc) { instance_double(LicenseAcceptance::Strategy::ProvidedValue) }
37
42
 
38
43
  before do
39
44
  expect(LicenseAcceptance::ProductReader).to receive(:new).and_return(reader)
40
- expect(LicenseAcceptance::FileAcceptance).to receive(:new).and_return(file_acc)
41
- expect(LicenseAcceptance::ArgAcceptance).to receive(:new).and_return(arg_acc)
42
- expect(LicenseAcceptance::PromptAcceptance).to receive(:new).and_return(prompt_acc)
43
- expect(LicenseAcceptance::EnvAcceptance).to receive(:new).and_return(env_acc)
45
+ expect(LicenseAcceptance::Strategy::File).to receive(:new).and_return(file_acc)
46
+ expect(LicenseAcceptance::Strategy::Argument).to receive(:new).and_return(arg_acc)
47
+ expect(LicenseAcceptance::Strategy::Prompt).to receive(:new).and_return(prompt_acc)
48
+ expect(LicenseAcceptance::Strategy::Environment).to receive(:new).and_return(env_acc)
49
+ expect(LicenseAcceptance::Strategy::ProvidedValue).to receive(:new).and_return(provided_acc)
50
+
51
+ allow(provided_acc).to receive(:no_persist?).and_return(false)
52
+ allow(env_acc).to receive(:no_persist?).and_return(false)
53
+ allow(arg_acc).to receive(:no_persist?).and_return(false)
54
+ allow(provided_acc).to receive(:accepted?).and_return(false)
55
+ allow(env_acc).to receive(:accepted?).and_return(false)
56
+ allow(arg_acc).to receive(:accepted?).and_return(false)
57
+ allow(provided_acc).to receive(:silent?).and_return(false)
58
+ allow(env_acc).to receive(:silent?).and_return(false)
59
+ allow(arg_acc).to receive(:silent?).and_return(false)
60
+
61
+ expect(reader).to receive(:read)
62
+ end
63
+
64
+ describe "when accept-no-persist is provided from the caller" do
65
+ it "returns true" do
66
+ expect(provided_acc).to receive(:no_persist?).and_return(true)
67
+ expect(acc.check_and_persist(product, version)).to eq(true)
68
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT_NO_PERSIST)
69
+ end
44
70
  end
45
71
 
46
- describe "when check-no-persist environment variable is set" do
72
+ describe "when accept-no-persist environment variable is set" do
47
73
  it "returns true" do
48
74
  expect(env_acc).to receive(:no_persist?).and_return(true)
49
75
  expect(acc.check_and_persist(product, version)).to eq(true)
76
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT_NO_PERSIST)
50
77
  end
51
78
  end
52
79
 
53
- describe "when check-no-persist command line argument is set" do
80
+ describe "when accept-no-persist command line argument is set" do
54
81
  it "returns true" do
55
- expect(env_acc).to receive(:no_persist?).and_return(false)
56
82
  expect(arg_acc).to receive(:no_persist?).and_return(true)
57
83
  expect(acc.check_and_persist(product, version)).to eq(true)
84
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT_NO_PERSIST)
58
85
  end
59
86
  end
60
87
 
61
88
  describe "when there are no missing licenses" do
62
89
  it "returns true" do
63
- expect(env_acc).to receive(:no_persist?).and_return(false)
64
- expect(arg_acc).to receive(:no_persist?).and_return(false)
65
- expect(reader).to receive(:read)
66
90
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
67
91
  expect(file_acc).to receive(:accepted?).with(relationship).and_return([])
68
92
  expect(acc.check_and_persist(product, version)).to eq(true)
93
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
69
94
  end
70
95
  end
71
96
 
72
97
  describe "when the user accepts as an environment variable" do
73
98
  it "returns true" do
74
- expect(env_acc).to receive(:no_persist?).and_return(false)
75
- expect(arg_acc).to receive(:no_persist?).and_return(false)
76
- expect(reader).to receive(:read)
77
99
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
78
100
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
79
- expect(env_acc).to receive(:accepted?).with(ENV).and_return(true)
80
- expect(env_acc).to receive(:silent?).with(ENV).and_return(false)
81
- expect(arg_acc).to receive(:silent?).with(ARGV).and_return(false)
101
+ expect(env_acc).to receive(:accepted?).and_return(true)
82
102
  expect(file_acc).to receive(:persist).with(relationship, missing).and_return([])
83
103
  expect(acc.check_and_persist(product, version)).to eq(true)
84
104
  expect(output.string).to match(/1 product license accepted./)
105
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
85
106
  end
86
107
 
87
108
  describe "when persist is set to false" do
88
109
  let(:opts) { { output: output, persist: false } }
89
110
 
90
111
  it "returns true" do
91
- expect(env_acc).to receive(:no_persist?).and_return(false)
92
- expect(arg_acc).to receive(:no_persist?).and_return(false)
93
- expect(reader).to receive(:read)
94
112
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
95
113
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
96
- expect(env_acc).to receive(:accepted?).with(ENV).and_return(true)
114
+ expect(env_acc).to receive(:accepted?).and_return(true)
97
115
  expect(acc.check_and_persist(product, version)).to eq(true)
98
116
  expect(output.string).to_not match(/accepted./)
117
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
99
118
  end
100
119
  end
101
120
 
@@ -103,67 +122,51 @@ RSpec.describe LicenseAcceptance::Acceptor do
103
122
  let(:opts) { { output: output } }
104
123
 
105
124
  it "returns true and silently persists the file" do
106
- expect(env_acc).to receive(:no_persist?).and_return(false)
107
- expect(arg_acc).to receive(:no_persist?).and_return(false)
108
- expect(reader).to receive(:read)
109
125
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
110
126
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
111
- expect(env_acc).to receive(:accepted?).with(ENV).and_return(false)
112
- expect(arg_acc).to receive(:accepted?).with(ARGV).and_return(false)
113
- expect(env_acc).to receive(:silent?).with(ENV).twice.and_return(true)
127
+ expect(env_acc).to receive(:silent?).times.exactly(3).and_return(true)
114
128
  expect(file_acc).to receive(:persist).with(relationship, missing).and_return([])
115
129
  expect(acc.check_and_persist(product, version)).to eq(true)
116
130
  expect(output.string).to be_empty
131
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT_SILENT)
117
132
  end
118
133
  end
119
134
 
120
135
  describe "when file persistance fails" do
121
136
  it "returns true" do
122
- expect(env_acc).to receive(:no_persist?).and_return(false)
123
- expect(arg_acc).to receive(:no_persist?).and_return(false)
124
- expect(reader).to receive(:read)
125
137
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
126
138
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
127
- expect(env_acc).to receive(:accepted?).with(ENV).and_return(true)
139
+ expect(env_acc).to receive(:accepted?).and_return(true)
128
140
  expect(file_acc).to receive(:persist).with(relationship, missing).and_return([StandardError.new("foo")])
129
141
  expect(acc.check_and_persist(product, version)).to eq(true)
130
142
  expect(output.string).to match(/Could not persist acceptance:/)
143
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
131
144
  end
132
145
  end
133
146
  end
134
147
 
135
148
  describe "when the user accepts as an arg" do
136
149
  it "returns true" do
137
- expect(env_acc).to receive(:no_persist?).and_return(false)
138
- expect(arg_acc).to receive(:no_persist?).and_return(false)
139
- expect(reader).to receive(:read)
140
150
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
141
151
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
142
- expect(env_acc).to receive(:accepted?).and_return(false)
143
- expect(arg_acc).to receive(:accepted?).with(ARGV).and_return(true)
144
- expect(env_acc).to receive(:silent?).with(ENV).and_return(false)
145
- expect(arg_acc).to receive(:silent?).with(ARGV).and_return(false)
152
+ expect(arg_acc).to receive(:accepted?).and_return(true)
146
153
  expect(file_acc).to receive(:persist).with(relationship, missing).and_return([])
147
154
  expect(acc.check_and_persist(product, version)).to eq(true)
148
155
  expect(output.string).to match(/1 product license accepted./)
156
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
149
157
  end
150
158
 
151
159
  describe "when the silent option is used" do
152
160
  let(:opts) { { output: output } }
153
161
 
154
162
  it "returns true and silently persists the file" do
155
- expect(env_acc).to receive(:no_persist?).and_return(false)
156
- expect(arg_acc).to receive(:no_persist?).and_return(false)
157
- expect(reader).to receive(:read)
158
163
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
159
164
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
160
- expect(env_acc).to receive(:accepted?).and_return(false)
161
- expect(arg_acc).to receive(:accepted?).with(ARGV).and_return(false)
162
- expect(env_acc).to receive(:silent?).with(ENV).twice.and_return(false)
163
- expect(arg_acc).to receive(:silent?).with(ARGV).twice.and_return(true)
165
+ expect(arg_acc).to receive(:silent?).times.exactly(3).and_return(true)
164
166
  expect(file_acc).to receive(:persist).with(relationship, missing).and_return([])
165
167
  expect(acc.check_and_persist(product, version)).to eq(true)
166
168
  expect(output.string).to be_empty
169
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT_SILENT)
167
170
  end
168
171
  end
169
172
 
@@ -172,30 +175,24 @@ RSpec.describe LicenseAcceptance::Acceptor do
172
175
  let(:opts) { { output: output, persist: false } }
173
176
 
174
177
  it "returns true" do
175
- expect(env_acc).to receive(:no_persist?).and_return(false)
176
- expect(arg_acc).to receive(:no_persist?).and_return(false)
177
- expect(reader).to receive(:read)
178
178
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
179
179
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
180
- expect(env_acc).to receive(:accepted?).and_return(false)
181
- expect(arg_acc).to receive(:accepted?).with(ARGV).and_return(true)
180
+ expect(arg_acc).to receive(:accepted?).and_return(true)
182
181
  expect(acc.check_and_persist(product, version)).to eq(true)
183
182
  expect(output.string).to_not match(/accepted./)
183
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
184
184
  end
185
185
  end
186
186
 
187
187
  describe "when file persistance fails" do
188
188
  it "returns true" do
189
- expect(env_acc).to receive(:no_persist?).and_return(false)
190
- expect(arg_acc).to receive(:no_persist?).and_return(false)
191
- expect(reader).to receive(:read)
192
189
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
193
190
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
194
- expect(env_acc).to receive(:accepted?).and_return(false)
195
- expect(arg_acc).to receive(:accepted?).with(ARGV).and_return(true)
191
+ expect(arg_acc).to receive(:accepted?).and_return(true)
196
192
  expect(file_acc).to receive(:persist).with(relationship, missing).and_return([StandardError.new("bar")])
197
193
  expect(acc.check_and_persist(product, version)).to eq(true)
198
194
  expect(output.string).to match(/Could not persist acceptance:/)
195
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
199
196
  end
200
197
  end
201
198
  end
@@ -203,70 +200,94 @@ RSpec.describe LicenseAcceptance::Acceptor do
203
200
  describe "when the prompt is not a tty" do
204
201
  let(:opts) { { output: File.open(File::NULL, "w") } }
205
202
  it "raises a LicenseNotAcceptedError error" do
206
- expect(env_acc).to receive(:no_persist?).and_return(false)
207
- expect(arg_acc).to receive(:no_persist?).and_return(false)
208
- expect(reader).to receive(:read)
209
203
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
210
204
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
211
- expect(env_acc).to receive(:accepted?).and_return(false)
212
- expect(arg_acc).to receive(:accepted?).and_return(false)
213
- expect(env_acc).to receive(:silent?).and_return(false)
214
- expect(arg_acc).to receive(:silent?).and_return(false)
215
205
  expect(prompt_acc).to_not receive(:request)
216
206
  expect { acc.check_and_persist(product, version) }.to raise_error(LicenseAcceptance::LicenseNotAcceptedError)
207
+ expect(acc.acceptance_value).to eq(nil)
217
208
  end
218
209
  end
219
210
 
220
211
  describe "when the user accepts with the prompt" do
221
212
  it "returns true" do
222
- expect(env_acc).to receive(:no_persist?).and_return(false)
223
- expect(arg_acc).to receive(:no_persist?).and_return(false)
224
- expect(reader).to receive(:read)
225
213
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
226
214
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
227
- expect(env_acc).to receive(:accepted?).and_return(false)
228
- expect(arg_acc).to receive(:accepted?).and_return(false)
229
- expect(env_acc).to receive(:silent?).and_return(false)
230
- expect(arg_acc).to receive(:silent?).and_return(false)
231
215
  expect(prompt_acc).to receive(:request).with(missing).and_yield.and_return(true)
232
216
  expect(file_acc).to receive(:persist).with(relationship, missing)
233
217
  expect(acc.check_and_persist(product, version)).to eq(true)
218
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT)
234
219
  end
235
220
 
236
221
  describe "when persist is set to false" do
237
222
  let(:opts) { { output: output, persist: false } }
238
223
 
239
224
  it "returns true" do
240
- expect(env_acc).to receive(:no_persist?).and_return(false)
241
- expect(arg_acc).to receive(:no_persist?).and_return(false)
242
- expect(reader).to receive(:read)
243
225
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
244
226
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
245
- expect(env_acc).to receive(:accepted?).and_return(false)
246
- expect(arg_acc).to receive(:accepted?).and_return(false)
247
- expect(env_acc).to receive(:silent?).and_return(false)
248
- expect(arg_acc).to receive(:silent?).and_return(false)
249
227
  expect(prompt_acc).to receive(:request).with(missing).and_yield.and_return(true)
250
228
  expect(acc.check_and_persist(product, version)).to eq(true)
229
+ expect(acc.acceptance_value).to eq(LicenseAcceptance::ACCEPT_NO_PERSIST)
251
230
  end
252
231
  end
253
232
  end
254
233
 
255
234
  describe "when the user declines with the prompt" do
256
235
  it "raises a LicenseNotAcceptedError error" do
257
- expect(env_acc).to receive(:no_persist?).and_return(false)
258
- expect(arg_acc).to receive(:no_persist?).and_return(false)
259
- expect(reader).to receive(:read)
260
236
  expect(reader).to receive(:lookup).with(product, version).and_return(relationship)
261
237
  expect(file_acc).to receive(:accepted?).with(relationship).and_return(missing)
262
- expect(env_acc).to receive(:accepted?).and_return(false)
263
- expect(arg_acc).to receive(:accepted?).and_return(false)
264
- expect(env_acc).to receive(:silent?).and_return(false)
265
- expect(arg_acc).to receive(:silent?).and_return(false)
266
238
  expect(prompt_acc).to receive(:request).with(missing).and_return(false)
267
239
  expect { acc.check_and_persist(product, version) }.to raise_error(LicenseAcceptance::LicenseNotAcceptedError)
240
+ expect(acc.acceptance_value).to eq(nil)
268
241
  end
269
242
  end
243
+ end
270
244
 
245
+ describe "#license_required?" do
246
+ let(:reader) { instance_double(LicenseAcceptance::ProductReader) }
247
+ let(:mixlib_name) { "chef" }
248
+ let(:version) { "15.0.0" }
249
+ let(:product) { instance_double(LicenseAcceptance::Product, id: "foo", license_required_version: "15.0.0") }
250
+
251
+ before do
252
+ expect(LicenseAcceptance::ProductReader).to receive(:new).and_return(reader)
253
+ expect(reader).to receive(:read)
254
+ end
255
+
256
+ it "returns false if no product can be found" do
257
+ expect(reader).to receive(:lookup_by_mixlib).with(mixlib_name).and_return nil
258
+ expect(acc.license_required?(mixlib_name, version)).to eq(false)
259
+ end
260
+
261
+ describe "when version is :latest" do
262
+ let(:version) { :latest }
263
+ it "returns true" do
264
+ expect(reader).to receive(:lookup_by_mixlib).with(mixlib_name).and_return product
265
+ expect(acc.license_required?(mixlib_name, version)).to eq(true)
266
+ end
267
+ end
268
+
269
+ describe "when version is nil" do
270
+ let(:version) { nil }
271
+ it "returns true" do
272
+ expect(reader).to receive(:lookup_by_mixlib).with(mixlib_name).and_return product
273
+ expect(acc.license_required?(mixlib_name, version)).to eq(true)
274
+ end
275
+ end
276
+
277
+ describe "when version is >= than required version" do
278
+ let(:version) { "15.0.0" }
279
+ it "returns true" do
280
+ expect(reader).to receive(:lookup_by_mixlib).with(mixlib_name).and_return product
281
+ expect(acc.license_required?(mixlib_name, version)).to eq(true)
282
+ end
283
+ end
284
+
285
+ describe "when version is < required version" do
286
+ let(:version) { "14.99.99" }
287
+ it "returns false" do
288
+ expect(reader).to receive(:lookup_by_mixlib).with(mixlib_name).and_return product
289
+ expect(acc.license_required?(mixlib_name, version)).to eq(false)
290
+ end
291
+ end
271
292
  end
272
293
  end
@@ -7,11 +7,11 @@ RSpec.describe LicenseAcceptance::ProductReader do
7
7
  let(:version) { "0.1.0" }
8
8
  let(:location) { "location" }
9
9
 
10
- let(:p1) { {"name" => "p1", "pretty_name" => "P1", "filename" => "f1"} }
11
- let(:p2) { {"name" => "p2", "pretty_name" => "P2", "filename" => "f2"} }
10
+ let(:p1) { {"id" => "p1", "pretty_name" => "P1", "filename" => "f1", "mixlib_name" => "p1m", "license_required_version" => "p1v"} }
11
+ let(:p2) { {"id" => "p2", "pretty_name" => "P2", "filename" => "f2", "mixlib_name" => "p2m", "license_required_version" => "p2v"} }
12
12
  # defined the `==` operator on Product for ease of comparison
13
- let(:product1) { LicenseAcceptance::Product.new(p1["name"], p1["pretty_name"], p1["filename"]) }
14
- let(:product2) { LicenseAcceptance::Product.new(p2["name"], p2["pretty_name"], p2["filename"]) }
13
+ let(:product1) { LicenseAcceptance::Product.new(p1["id"], p1["pretty_name"], p1["filename"], p1["mixlib_name"], p1["license_required_version"]) }
14
+ let(:product2) { LicenseAcceptance::Product.new(p2["id"], p2["pretty_name"], p2["filename"], p2["mixlib_name"], p2["license_required_version"]) }
15
15
  let(:r1) { {p1 => p2} }
16
16
  let(:toml) { {"products" => [p1, p2], "relationships" => {"p1" => ["p2"]}} }
17
17
 
@@ -114,7 +114,7 @@ RSpec.describe LicenseAcceptance::ProductReader do
114
114
  end
115
115
  end
116
116
 
117
- let(:nonya) { LicenseAcceptance::Product.new("nonya", "NonYa", "nofile") }
117
+ let(:nonya) { LicenseAcceptance::Product.new("nonya", "NonYa", "nofile", "no_mixlib", "no_version") }
118
118
  describe "when called on a product with no relationship" do
119
119
  before do
120
120
  reader.products = { "nonya" => nonya }
@@ -136,4 +136,20 @@ RSpec.describe LicenseAcceptance::ProductReader do
136
136
  end
137
137
  end
138
138
 
139
+ describe "::lookup_by_mixlib" do
140
+ before do
141
+ expect(reader).to receive(:get_location).and_return(location)
142
+ expect(Tomlrb).to receive(:load_file).with(location, symbolize_keys: false).and_return(toml)
143
+ reader.read
144
+ end
145
+
146
+ it "returns a Product successfully" do
147
+ expect(reader.lookup_by_mixlib("p1m")).to eq(product1)
148
+ end
149
+
150
+ it "returns nil for an unknown product" do
151
+ expect(reader.lookup_by_mixlib("foo")).to eq(nil)
152
+ end
153
+ end
154
+
139
155
  end
@@ -2,12 +2,14 @@ require "spec_helper"
2
2
  require "license_acceptance/product"
3
3
 
4
4
  RSpec.describe LicenseAcceptance::Product do
5
- let(:instance) { LicenseAcceptance::Product.new("name", "Pretty Name", "filename") }
5
+ let(:instance) { LicenseAcceptance::Product.new("id", "Pretty Name", "filename", "mixlib_name", "version") }
6
6
 
7
7
  it "can lookup the product attributes" do
8
- expect(instance.name).to eq("name")
8
+ expect(instance.id).to eq("id")
9
9
  expect(instance.pretty_name).to eq("Pretty Name")
10
10
  expect(instance.filename).to eq("filename")
11
+ expect(instance.mixlib_name).to eq("mixlib_name")
12
+ expect(instance.license_required_version).to eq("version")
11
13
  end
12
14
 
13
15
  end
@@ -0,0 +1,82 @@
1
+ require "spec_helper"
2
+ require "license_acceptance/strategy/argument"
3
+
4
+ RSpec.describe LicenseAcceptance::Strategy::Argument do
5
+ let(:acc) { LicenseAcceptance::Strategy::Argument.new(argv) }
6
+
7
+ describe "#accepted?" do
8
+ describe "when value is space seperated" do
9
+ let(:argv) { ["--chef-license", "accept"] }
10
+ it "returns true if the args contain the required flag with spaces" do
11
+ expect(acc.accepted?).to eq(true)
12
+ end
13
+ end
14
+
15
+ describe "when the value is equal seperated" do
16
+ let(:argv) { ["--chef-license=accept"] }
17
+ it "returns true if the args contain the required flag with equal" do
18
+ expect(acc.accepted?).to eq(true)
19
+ end
20
+ end
21
+
22
+ [ ["--chef-license"], ["--chef-license=foo"], ["--chef-license", "foo"] ].each do |v|
23
+ describe "when the value is #{v}" do
24
+ let(:argv) { v }
25
+ it "returns false if the args do not contain the required value" do
26
+ expect(acc.accepted?).to eq(false)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ describe "#silent?" do
33
+ describe "when value is space seperated" do
34
+ let(:argv) { ["--chef-license", "accept-silent"] }
35
+ it "returns true if the args contain the required flag with spaces" do
36
+ expect(acc.silent?).to eq(true)
37
+ end
38
+ end
39
+
40
+ describe "when the value is equal seperated" do
41
+ let(:argv) { ["--chef-license=accept-silent"] }
42
+ it "returns true if the args contain the required flag with equal" do
43
+ expect(acc.silent?).to eq(true)
44
+ end
45
+ end
46
+
47
+ [ ["--chef-license"], ["--chef-license=accept"], ["--chef-license", "accept"] ].each do |v|
48
+ describe "when the value is #{v}" do
49
+ let(:argv) { v }
50
+ it "returns false if the args do not contain the required value" do
51
+ expect(acc.silent?).to eq(false)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "#no_persist?" do
58
+ describe "when value is space seperated" do
59
+ let(:argv) { ["--chef-license", "accept-no-persist"] }
60
+ it "returns true if the args contain the required flag with spaces" do
61
+ expect(acc.no_persist?).to eq(true)
62
+ end
63
+ end
64
+
65
+ describe "when the value is equal seperated" do
66
+ let(:argv) { ["--chef-license=accept-no-persist"] }
67
+ it "returns true if the args contain the required flag with equal" do
68
+ expect(acc.no_persist?).to eq(true)
69
+ end
70
+ end
71
+
72
+ [ ["--chef-license"], ["--chef-license=accept"], ["--chef-license", "accept"] ].each do |v|
73
+ describe "when the value is #{v}" do
74
+ let(:argv) { v }
75
+ it "returns false if the args do not contain the required value" do
76
+ expect(acc.no_persist?).to eq(false)
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ end