license-acceptance 1.0.11 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +23 -1
- data/config/product_info.toml +1 -1
- data/lib/license_acceptance/acceptor.rb +28 -25
- data/lib/license_acceptance/cli_flags/mixlib_cli.rb +2 -2
- data/lib/license_acceptance/cli_flags/thor.rb +3 -3
- data/lib/license_acceptance/config.rb +5 -4
- data/lib/license_acceptance/product.rb +8 -6
- data/lib/license_acceptance/product_reader.rb +7 -3
- data/lib/license_acceptance/strategy/argument.rb +4 -3
- data/lib/license_acceptance/strategy/environment.rb +3 -2
- data/lib/license_acceptance/strategy/file.rb +8 -8
- data/lib/license_acceptance/strategy/prompt.rb +23 -23
- data/lib/license_acceptance/version.rb +1 -1
- metadata +6 -132
- data/Gemfile.lock +0 -94
- data/Rakefile +0 -6
- data/spec/license_acceptance/acceptor_spec.rb +0 -301
- data/spec/license_acceptance/cli_flags/mixlib_cli_spec.rb +0 -14
- data/spec/license_acceptance/cli_flags/thor_spec.rb +0 -14
- data/spec/license_acceptance/config_spec.rb +0 -111
- data/spec/license_acceptance/product_reader_spec.rb +0 -155
- data/spec/license_acceptance/product_spec.rb +0 -15
- data/spec/license_acceptance/strategy/argument_spec.rb +0 -82
- data/spec/license_acceptance/strategy/environment_spec.rb +0 -76
- data/spec/license_acceptance/strategy/file_spec.rb +0 -127
- data/spec/license_acceptance/strategy/prompt_spec.rb +0 -100
- data/spec/license_acceptance/strategy/provided_value_spec.rb +0 -55
- data/spec/spec_helper.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eee8ab3bdb6b370c3b0c2dddb7a86f22cea5240eae5df17e58e4c367fc08a0fe
|
4
|
+
data.tar.gz: 7f25c5f59f833808115dead1157b33f09c9fe4e4000c3c4e70dee586466d74a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef3af6247b87811c3796838e707d47b153c7828160a4dee699b3e95f2bef534c055fa34e828548a7e0dc9830b146014c2a8a7a4ac2cca4d94388e180d4fa5581
|
7
|
+
data.tar.gz: aa6d132e77ecfb95a8c4e263d29d7731a44f2c8d40d4cd7eeb48fbf8964c5a9e807c6cde3fec5f757af3cb9de2e5fbfc1e8d60c5729598f204fa2829d6e1c42c
|
data/Gemfile
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in license-acceptance.gemspec
|
6
6
|
gemspec
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem "chefstyle", "1.2.1"
|
10
|
+
gem "climate_control", "~> 0.2"
|
11
|
+
gem "mixlib-cli", "~> 1.7"
|
12
|
+
gem "rake", ">= 10.1.0"
|
13
|
+
gem "rspec", "~> 3.0"
|
14
|
+
gem "thor", ">= 0.20", "< 2.0" # validate 2.0 when it ships
|
15
|
+
end
|
16
|
+
|
17
|
+
group :docs do
|
18
|
+
gem "yard"
|
19
|
+
gem "redcarpet"
|
20
|
+
gem "github-markup"
|
21
|
+
end
|
22
|
+
|
23
|
+
group :debug do
|
24
|
+
gem "pry"
|
25
|
+
gem "pry-byebug"
|
26
|
+
gem "pry-stack_explorer", "~> 0.4.0" # pin until we drop ruby < 2.6
|
27
|
+
gem "rb-readline"
|
28
|
+
end
|
data/config/product_info.toml
CHANGED
@@ -52,7 +52,7 @@ license_required_version = "0.4"
|
|
52
52
|
|
53
53
|
[relationships]
|
54
54
|
"infra-client" = ["inspec"]
|
55
|
-
"infra-server" = ["infra-client"]
|
55
|
+
"infra-server" = ["infra-client", "inspec"]
|
56
56
|
"push-jobs-server" = ["infra-client", "infra-server"]
|
57
57
|
"push-jobs-client" = ["infra-client"]
|
58
58
|
"chef-dk" = ["infra-client", "inspec"]
|
@@ -11,9 +11,9 @@ require "license_acceptance/strategy/provided_value"
|
|
11
11
|
|
12
12
|
module LicenseAcceptance
|
13
13
|
|
14
|
-
ACCEPT = "accept"
|
15
|
-
ACCEPT_SILENT = "accept-silent"
|
16
|
-
ACCEPT_NO_PERSIST = "accept-no-persist"
|
14
|
+
ACCEPT = "accept".freeze
|
15
|
+
ACCEPT_SILENT = "accept-silent".freeze
|
16
|
+
ACCEPT_NO_PERSIST = "accept-no-persist".freeze
|
17
17
|
|
18
18
|
class Acceptor
|
19
19
|
extend Forwardable
|
@@ -21,7 +21,7 @@ module LicenseAcceptance
|
|
21
21
|
|
22
22
|
attr_reader :config, :product_reader, :env_strategy, :file_strategy, :arg_strategy, :prompt_strategy, :provided_strategy
|
23
23
|
|
24
|
-
def initialize(opts={})
|
24
|
+
def initialize(opts = {})
|
25
25
|
@config = Config.new(opts)
|
26
26
|
Logger.initialize(config.logger)
|
27
27
|
@product_reader = ProductReader.new
|
@@ -74,28 +74,28 @@ module LicenseAcceptance
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
@acceptance_value = accepted_silent? ? ACCEPT_SILENT : ACCEPT
|
77
|
-
|
77
|
+
true
|
78
78
|
elsif config.output.isatty && prompt_strategy.request(missing_licenses) do
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
79
|
+
# We have to infer the acceptance value if they use the prompt to accept
|
80
|
+
if config.persist
|
81
|
+
@acceptance_value = ACCEPT # rubocop: disable Lint/AssignmentInCondition
|
82
|
+
file_strategy.persist(product_relationship, missing_licenses)
|
83
|
+
else
|
84
|
+
@acceptance_value = ACCEPT_NO_PERSIST # rubocop: disable Lint/AssignmentInCondition
|
85
|
+
[]
|
87
86
|
end
|
88
|
-
|
87
|
+
end
|
88
|
+
true
|
89
89
|
else
|
90
90
|
raise LicenseNotAcceptedError.new(product_relationship.parent, missing_licenses)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def self.check_and_persist!(product_id, version, opts={})
|
94
|
+
def self.check_and_persist!(product_id, version, opts = {})
|
95
95
|
new(opts).check_and_persist!(product_id, version)
|
96
96
|
end
|
97
97
|
|
98
|
-
def self.check_and_persist(product_id, version, opts={})
|
98
|
+
def self.check_and_persist(product_id, version, opts = {})
|
99
99
|
new(opts).check_and_persist(product_id, version)
|
100
100
|
end
|
101
101
|
|
@@ -104,7 +104,9 @@ module LicenseAcceptance
|
|
104
104
|
product = product_reader.lookup_by_mixlib(mixlib_name)
|
105
105
|
return false if product.nil?
|
106
106
|
# If they don't pass a version we assume they want latest
|
107
|
-
|
107
|
+
# All versions in all channels require license acceptance
|
108
|
+
return true if %w{latest unstable current stable}.include?(version.to_s) || version.nil?
|
109
|
+
|
108
110
|
Gem::Version.new(version) >= Gem::Version.new(product.license_required_version)
|
109
111
|
end
|
110
112
|
|
@@ -113,6 +115,7 @@ module LicenseAcceptance
|
|
113
115
|
def id_from_mixlib(mixlib_name)
|
114
116
|
product = product_reader.lookup_by_mixlib(mixlib_name)
|
115
117
|
return nil if product.nil?
|
118
|
+
|
116
119
|
product.id
|
117
120
|
end
|
118
121
|
|
@@ -140,20 +143,20 @@ module LicenseAcceptance
|
|
140
143
|
# In the case where users accept with a command line argument or environment variable
|
141
144
|
# we still want to output the fact that the filesystem was changed.
|
142
145
|
def output_num_persisted(count)
|
143
|
-
s = count > 1 ? "s": ""
|
146
|
+
s = count > 1 ? "s" : ""
|
144
147
|
output.puts <<~EOM
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
+
#{Strategy::Prompt::BORDER}
|
149
|
+
#{Strategy::Prompt::CHECK} #{count} product license#{s} accepted.
|
150
|
+
#{Strategy::Prompt::BORDER}
|
148
151
|
EOM
|
149
152
|
end
|
150
153
|
|
151
154
|
def output_persist_failed(errs)
|
152
155
|
output.puts <<~EOM
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
#{Strategy::Prompt::BORDER}
|
157
|
+
#{Strategy::Prompt::CHECK} Product license accepted.
|
158
|
+
Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
|
159
|
+
#{Strategy::Prompt::BORDER}
|
157
160
|
EOM
|
158
161
|
end
|
159
162
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
begin
|
2
|
-
require
|
3
|
-
rescue
|
2
|
+
require "thor"
|
3
|
+
rescue
|
4
4
|
raise "Must have thor gem installed to use this mixin"
|
5
5
|
end
|
6
6
|
|
@@ -12,7 +12,7 @@ module LicenseAcceptance
|
|
12
12
|
def self.included(klass)
|
13
13
|
klass.class_option :chef_license,
|
14
14
|
type: :string,
|
15
|
-
desc:
|
15
|
+
desc: "Accept the license for this product and any contained products: accept, accept-no-persist, accept-silent"
|
16
16
|
end
|
17
17
|
|
18
18
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "logger"
|
2
2
|
|
3
3
|
module LicenseAcceptance
|
4
4
|
class Config
|
5
5
|
attr_accessor :output, :logger, :license_locations, :persist_location, :persist
|
6
6
|
|
7
|
-
def initialize(opts={})
|
7
|
+
def initialize(opts = {})
|
8
8
|
@output = opts.fetch(:output, $stdout)
|
9
9
|
@logger = opts.fetch(:logger, ::Logger.new(IO::NULL))
|
10
10
|
@license_locations = opts.fetch(:license_locations, default_license_locations)
|
@@ -21,7 +21,7 @@ module LicenseAcceptance
|
|
21
21
|
|
22
22
|
def default_license_locations
|
23
23
|
if windows?
|
24
|
-
root = ENV.fetch("SYSTEMDRIVE","C:")
|
24
|
+
root = ENV.fetch("SYSTEMDRIVE", "C:")
|
25
25
|
l = [ File.join(root, "chef/accepted_licenses/") ]
|
26
26
|
unless is_root?
|
27
27
|
# Look through a list of possible user locations and pick the first one that exists
|
@@ -32,6 +32,7 @@ module LicenseAcceptance
|
|
32
32
|
possible_dirs << ENV["HOMESHARE"] + ENV["HOMEPATH"] if ENV["HOMESHARE"] && ENV["HOMEPATH"]
|
33
33
|
possible_dirs << ENV["USERPROFILE"] if ENV["USERPROFILE"]
|
34
34
|
raise NoValidEnvironmentVar if possible_dirs.empty?
|
35
|
+
|
35
36
|
possible_dirs.each do |possible_dir|
|
36
37
|
if Dir.exist?(possible_dir)
|
37
38
|
full_possible_dir = File.join(possible_dir, ".chef/accepted_licenses/")
|
@@ -42,7 +43,7 @@ module LicenseAcceptance
|
|
42
43
|
end
|
43
44
|
else
|
44
45
|
l = [ "/etc/chef/accepted_licenses/" ]
|
45
|
-
l << File.join(ENV[
|
46
|
+
l << File.join(ENV["HOME"], ".chef/accepted_licenses/") unless is_root?
|
46
47
|
end
|
47
48
|
l
|
48
49
|
end
|
@@ -14,14 +14,16 @@ module LicenseAcceptance
|
|
14
14
|
|
15
15
|
def ==(other)
|
16
16
|
return false if other.class != Product
|
17
|
+
|
17
18
|
if other.id == id &&
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
other.pretty_name == pretty_name &&
|
20
|
+
other.filename == filename &&
|
21
|
+
other.mixlib_name == mixlib_name &&
|
22
|
+
other.license_required_version == license_required_version
|
23
|
+
return true
|
23
24
|
end
|
24
|
-
|
25
|
+
|
26
|
+
false
|
25
27
|
end
|
26
28
|
|
27
29
|
end
|
@@ -18,7 +18,7 @@ module LicenseAcceptance
|
|
18
18
|
toml = Tomlrb.load_file(location, symbolize_keys: false)
|
19
19
|
raise InvalidProductInfo.new(location) if toml.empty? || toml["products"].nil? || toml["relationships"].nil?
|
20
20
|
|
21
|
-
|
21
|
+
toml["products"].each do |product|
|
22
22
|
products[product["id"]] = Product.new(
|
23
23
|
product["id"], product["pretty_name"],
|
24
24
|
product["filename"], product["mixlib_name"],
|
@@ -26,7 +26,7 @@ module LicenseAcceptance
|
|
26
26
|
)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
29
|
+
toml["relationships"].each do |parent_id, children|
|
30
30
|
parent = products[parent_id]
|
31
31
|
raise UnknownParent.new(parent_id) if parent.nil?
|
32
32
|
# Its fine to not have a relationship entry, but not fine to have
|
@@ -34,9 +34,11 @@ module LicenseAcceptance
|
|
34
34
|
if children.nil? || children.empty? || !children.is_a?(Array)
|
35
35
|
raise NoChildRelationships.new(parent)
|
36
36
|
end
|
37
|
+
|
37
38
|
children.map! do |child_id|
|
38
39
|
child = products[child_id]
|
39
40
|
raise UnknownChild.new(child_id) if child.nil?
|
41
|
+
|
40
42
|
child
|
41
43
|
end
|
42
44
|
relationships[parent] = children
|
@@ -52,6 +54,7 @@ module LicenseAcceptance
|
|
52
54
|
if ENV["CHEF_LICENSE_PRODUCT_INFO"]
|
53
55
|
return ENV["CHEF_LICENSE_PRODUCT_INFO"]
|
54
56
|
end
|
57
|
+
|
55
58
|
File.absolute_path(File.join(__FILE__, "../../../config/product_info.toml"))
|
56
59
|
end
|
57
60
|
|
@@ -60,9 +63,10 @@ module LicenseAcceptance
|
|
60
63
|
raise UnknownProduct.new(parent_id)
|
61
64
|
end
|
62
65
|
children = relationships.fetch(parent_product, [])
|
63
|
-
|
66
|
+
unless parent_version.is_a? String
|
64
67
|
raise ProductVersionTypeError.new(parent_version)
|
65
68
|
end
|
69
|
+
|
66
70
|
ProductRelationship.new(parent_product, children, parent_version)
|
67
71
|
end
|
68
72
|
|
@@ -30,14 +30,15 @@ module LicenseAcceptance
|
|
30
30
|
if argv.include?("--chef-license=#{sought}")
|
31
31
|
return true
|
32
32
|
end
|
33
|
+
|
33
34
|
i = argv.index("--chef-license")
|
34
35
|
unless i.nil?
|
35
|
-
val = argv[i+1]
|
36
|
-
if val
|
36
|
+
val = argv[i + 1]
|
37
|
+
if !val.nil? && val.downcase == sought
|
37
38
|
return true
|
38
39
|
end
|
39
40
|
end
|
40
|
-
|
41
|
+
false
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
@@ -27,10 +27,11 @@ module LicenseAcceptance
|
|
27
27
|
private
|
28
28
|
|
29
29
|
def look_for_value(sought)
|
30
|
-
if env[
|
30
|
+
if env["CHEF_LICENSE"] && env["CHEF_LICENSE"].downcase == sought
|
31
31
|
return true
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
|
+
false
|
34
35
|
end
|
35
36
|
|
36
37
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "date"
|
2
|
+
require "yaml"
|
3
|
+
require "fileutils"
|
4
|
+
require "etc"
|
5
5
|
require "license_acceptance/logger"
|
6
6
|
require "license_acceptance/strategy/base"
|
7
7
|
|
@@ -49,7 +49,7 @@ module LicenseAcceptance
|
|
49
49
|
parent_version = product_relationship.parent_version
|
50
50
|
root_dir = config.persist_location
|
51
51
|
|
52
|
-
|
52
|
+
unless Dir.exist?(root_dir)
|
53
53
|
begin
|
54
54
|
FileUtils.mkdir_p(root_dir)
|
55
55
|
rescue StandardError => e
|
@@ -70,7 +70,7 @@ module LicenseAcceptance
|
|
70
70
|
errs << err unless err.nil?
|
71
71
|
end
|
72
72
|
end
|
73
|
-
|
73
|
+
errs
|
74
74
|
end
|
75
75
|
|
76
76
|
private
|
@@ -91,11 +91,11 @@ module LicenseAcceptance
|
|
91
91
|
contents = Hash[contents.map { |k, v| [k.to_s, v] }]
|
92
92
|
license_file << YAML.dump(contents)
|
93
93
|
end
|
94
|
-
|
94
|
+
nil
|
95
95
|
rescue StandardError => e
|
96
96
|
msg = "Could not persist license to #{path}"
|
97
97
|
logger.info "#{msg}\n\t#{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
98
|
-
|
98
|
+
e
|
99
99
|
end
|
100
100
|
|
101
101
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "tty-prompt"
|
2
|
+
require "pastel"
|
3
3
|
require "license_acceptance/logger"
|
4
4
|
require "license_acceptance/strategy/base"
|
5
5
|
require "timeout"
|
@@ -7,7 +7,7 @@ require "timeout"
|
|
7
7
|
module LicenseAcceptance
|
8
8
|
module Strategy
|
9
9
|
|
10
|
-
# Interactive prompt for accepting and
|
10
|
+
# Interactive prompt for accepting and persistence license acceptance, or failing with custom exit code
|
11
11
|
class Prompt < Base
|
12
12
|
include Logger
|
13
13
|
|
@@ -17,30 +17,30 @@ module LicenseAcceptance
|
|
17
17
|
@output = config.output
|
18
18
|
end
|
19
19
|
|
20
|
-
WIDTH = 50
|
20
|
+
WIDTH = 50
|
21
21
|
PASTEL = Pastel.new
|
22
22
|
BORDER = "+---------------------------------------------+".freeze
|
23
23
|
YES = PASTEL.green.bold("yes")
|
24
|
-
CHECK
|
24
|
+
CHECK = PASTEL.green("✔")
|
25
25
|
|
26
26
|
def request(missing_licenses, &persist_callback)
|
27
27
|
logger.debug("Requesting a license for #{missing_licenses.map(&:id)}")
|
28
28
|
c = missing_licenses.size
|
29
|
-
s = c > 1 ? "s": ""
|
29
|
+
s = c > 1 ? "s" : ""
|
30
30
|
|
31
31
|
acceptance_question = "Do you accept the #{c} product license#{s} (#{YES}/no)?"
|
32
32
|
output.puts <<~EOM
|
33
|
-
|
34
|
-
|
33
|
+
#{BORDER}
|
34
|
+
Chef License Acceptance
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
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
39
|
|
40
|
-
|
41
|
-
|
40
|
+
License#{s} that need accepting:
|
41
|
+
* #{missing_licenses.map(&:pretty_name).join("\n * ")}
|
42
42
|
|
43
|
-
|
43
|
+
#{acceptance_question}
|
44
44
|
|
45
45
|
EOM
|
46
46
|
|
@@ -51,10 +51,10 @@ module LicenseAcceptance
|
|
51
51
|
|
52
52
|
output.puts <<~EOM
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
If you do not accept this license you will
|
55
|
+
not be able to use Chef products.
|
56
56
|
|
57
|
-
|
57
|
+
#{acceptance_question}
|
58
58
|
|
59
59
|
EOM
|
60
60
|
|
@@ -62,7 +62,7 @@ module LicenseAcceptance
|
|
62
62
|
if answer != "yes"
|
63
63
|
output.puts BORDER
|
64
64
|
end
|
65
|
-
|
65
|
+
answer
|
66
66
|
end
|
67
67
|
|
68
68
|
private
|
@@ -73,12 +73,12 @@ module LicenseAcceptance
|
|
73
73
|
|
74
74
|
answer = "no"
|
75
75
|
begin
|
76
|
-
Timeout
|
76
|
+
Timeout.timeout(60, PromptTimeout) do
|
77
77
|
answer = prompt.ask(">") do |q|
|
78
78
|
q.modify :down, :trim
|
79
79
|
q.required true
|
80
80
|
q.messages[:required?] = "You must enter 'yes' or 'no'"
|
81
|
-
q.validate
|
81
|
+
q.validate(/^\s*(yes|no)\s*$/i)
|
82
82
|
q.messages[:valid?] = "You must enter 'yes' or 'no'"
|
83
83
|
end
|
84
84
|
end
|
@@ -95,13 +95,13 @@ module LicenseAcceptance
|
|
95
95
|
output.puts "#{CHECK} #{c} product license#{s} persisted.\n\n"
|
96
96
|
else
|
97
97
|
output.puts <<~EOM
|
98
|
-
|
99
|
-
|
98
|
+
#{CHECK} #{c} product license#{s} accepted.
|
99
|
+
Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
|
100
100
|
EOM
|
101
101
|
end
|
102
102
|
return true
|
103
103
|
end
|
104
|
-
|
104
|
+
false
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|