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.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/config/product_info.toml +19 -10
- data/lib/license_acceptance/acceptor.rb +76 -36
- data/lib/license_acceptance/product.rb +10 -5
- data/lib/license_acceptance/product_reader.rb +22 -11
- data/lib/license_acceptance/strategy/argument.rb +44 -0
- data/lib/license_acceptance/strategy/base.rb +7 -0
- data/lib/license_acceptance/strategy/environment.rb +38 -0
- data/lib/license_acceptance/strategy/file.rb +103 -0
- data/lib/license_acceptance/strategy/prompt.rb +111 -0
- data/lib/license_acceptance/strategy/provided_value.rb +28 -0
- data/lib/license_acceptance/version.rb +1 -1
- data/spec/license_acceptance/acceptor_spec.rb +115 -94
- data/spec/license_acceptance/product_reader_spec.rb +21 -5
- data/spec/license_acceptance/product_spec.rb +4 -2
- data/spec/license_acceptance/strategy/argument_spec.rb +82 -0
- data/spec/license_acceptance/strategy/environment_spec.rb +76 -0
- data/spec/license_acceptance/{file_acceptance_spec.rb → strategy/file_spec.rb} +21 -15
- data/spec/license_acceptance/{prompt_acceptance_spec.rb → strategy/prompt_spec.rb} +6 -6
- data/spec/license_acceptance/strategy/provided_value_spec.rb +55 -0
- metadata +14 -11
- data/lib/license_acceptance/arg_acceptance.rb +0 -32
- data/lib/license_acceptance/env_acceptance.rb +0 -26
- data/lib/license_acceptance/file_acceptance.rb +0 -97
- data/lib/license_acceptance/prompt_acceptance.rb +0 -106
- data/spec/license_acceptance/arg_acceptance_spec.rb +0 -57
- 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
|
|
@@ -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) { "
|
|
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(:
|
|
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
|
-
|
|
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(:
|
|
33
|
-
let(:
|
|
34
|
-
let(:
|
|
35
|
-
let(:
|
|
36
|
-
let(:
|
|
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::
|
|
41
|
-
expect(LicenseAcceptance::
|
|
42
|
-
expect(LicenseAcceptance::
|
|
43
|
-
expect(LicenseAcceptance::
|
|
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
|
|
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
|
|
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?).
|
|
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?).
|
|
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(:
|
|
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?).
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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) { {"
|
|
11
|
-
let(:p2) { {"
|
|
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["
|
|
14
|
-
let(:product2) { LicenseAcceptance::Product.new(p2["
|
|
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("
|
|
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.
|
|
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
|