license-acceptance 0.2.10 → 2.1.2

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +23 -1
  3. data/config/product_info.toml +41 -10
  4. data/lib/license_acceptance/acceptor.rb +103 -46
  5. data/lib/license_acceptance/cli_flags/mixlib_cli.rb +2 -2
  6. data/lib/license_acceptance/cli_flags/thor.rb +3 -3
  7. data/lib/license_acceptance/config.rb +6 -4
  8. data/lib/license_acceptance/product.rb +15 -8
  9. data/lib/license_acceptance/product_reader.rb +29 -14
  10. data/lib/license_acceptance/strategy/argument.rb +45 -0
  11. data/lib/license_acceptance/strategy/base.rb +7 -0
  12. data/lib/license_acceptance/strategy/environment.rb +39 -0
  13. data/lib/license_acceptance/strategy/file.rb +101 -0
  14. data/lib/license_acceptance/strategy/prompt.rb +111 -0
  15. data/lib/license_acceptance/strategy/provided_value.rb +31 -0
  16. data/lib/license_acceptance/version.rb +1 -1
  17. metadata +12 -135
  18. data/Gemfile.lock +0 -94
  19. data/Rakefile +0 -6
  20. data/lib/license_acceptance/arg_acceptance.rb +0 -32
  21. data/lib/license_acceptance/env_acceptance.rb +0 -26
  22. data/lib/license_acceptance/file_acceptance.rb +0 -97
  23. data/lib/license_acceptance/prompt_acceptance.rb +0 -106
  24. data/spec/license_acceptance/acceptor_spec.rb +0 -272
  25. data/spec/license_acceptance/arg_acceptance_spec.rb +0 -57
  26. data/spec/license_acceptance/cli_flags/mixlib_cli_spec.rb +0 -14
  27. data/spec/license_acceptance/cli_flags/thor_spec.rb +0 -14
  28. data/spec/license_acceptance/config_spec.rb +0 -111
  29. data/spec/license_acceptance/env_acceptance_spec.rb +0 -65
  30. data/spec/license_acceptance/file_acceptance_spec.rb +0 -121
  31. data/spec/license_acceptance/product_reader_spec.rb +0 -139
  32. data/spec/license_acceptance/product_spec.rb +0 -13
  33. data/spec/license_acceptance/prompt_acceptance_spec.rb +0 -100
  34. data/spec/spec_helper.rb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa15a0ed3a76f4f1bd60469de0b9f836f73f7db824da061e876bd95fb78a919b
4
- data.tar.gz: d31a667d3f45ed4455e613d6091f3635aeb6f76cfd40589f0a35e6108d022847
3
+ metadata.gz: d82f01f1176a863816de18e547817c501d796873019601fc84a6c01a2e97c713
4
+ data.tar.gz: eab594e87a7613d6126e124757f63f2acc35fcbf24485a50d84e96f2609c6f51
5
5
  SHA512:
6
- metadata.gz: 0a91aee2c874863a1bb217da59b9cf9f8345cc90f2f9e6e9420ca9bb792fbca3808a23131702b434a64321ae915c4973b640dd71d3b0da65002c456c56e14f1d
7
- data.tar.gz: 76433d31718bffa392e817f7a350aab605142dc5d2248c25f0349adde3ac23c0ce36f83130296900dd84b24a600049df04e4c3e8a325154446540dae0e7fbb0c
6
+ metadata.gz: c9ed6dd65f3fb274f110157fab725a9b2cc0b341aff313f38a4a30809fd19aaef0dd52d9eabeb95a8f1738c45fff0f3efdf39a9d681fb4b9ed3118b0eeb0090e
7
+ data.tar.gz: 3fe1ba49289e95c77ffc863deea1221bd418cb5a111262904349d4c92e3dc2a5a760e5c562175d0a167916c3f028bcf8d0a346e038e8b935a69aadc6d147f3f6
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.3.2"
10
+ gem "climate_control", "~> 0.2"
11
+ gem "mixlib-cli", "~> 2.1"
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
@@ -2,27 +2,58 @@
2
2
  title = "All known products that require license acceptance, and the mapping of parent to child relationships"
3
3
 
4
4
  [[products]]
5
- name = "chef-client"
6
- pretty_name = "Chef Client"
5
+ id = "infra-client"
6
+ pretty_name = "Chef Infra Client"
7
7
  hab_pkg_id = "chef/chef-client"
8
- filename = "chef_client"
8
+ filename = "chef_infra_client"
9
+ mixlib_name = "chef"
10
+ license_required_version = "15"
9
11
 
10
12
  [[products]]
11
- name = "inspec"
12
- pretty_name = "InSpec"
13
+ id = "inspec"
14
+ pretty_name = "Chef InSpec"
13
15
  hab_pkg_id = "chef/inspec"
14
16
  filename = "inspec"
15
17
 
16
18
  [[products]]
17
- name = "supermarket"
19
+ id = "supermarket"
18
20
  pretty_name = "Supermarket"
19
21
  filename = "supermarket"
20
22
 
21
23
  [[products]]
22
- name = "chef-server"
23
- pretty_name = "Chef Server"
24
+ id = "infra-server"
25
+ pretty_name = "Chef Infra Server"
24
26
  hab_pkg_id = "chef/oc_erchef"
25
- filename = "chef_server"
27
+ filename = "chef_infra_server"
28
+
29
+ [[products]]
30
+ id = "push-jobs-server"
31
+ pretty_name = "Chef Push Jobs Server"
32
+ filename = "push_jobs_server"
33
+
34
+ [[products]]
35
+ id = "push-jobs-client"
36
+ pretty_name = "Chef Push Jobs Client"
37
+ filename = "push_jobs_client"
38
+
39
+ [[products]]
40
+ id = "chef-dk"
41
+ pretty_name = "Chef Development Kit"
42
+ filename = "chef_dk"
43
+ mixlib_name = "chefdk"
44
+ license_required_version = "4"
45
+
46
+ [[products]]
47
+ id = "chef-workstation"
48
+ pretty_name = "Chef Workstation"
49
+ filename = "chef_workstation"
50
+ mixlib_name = "chef-workstation"
51
+ license_required_version = "0.4"
26
52
 
27
53
  [relationships]
28
- "chef-client" = ["inspec"]
54
+ "infra-client" = ["inspec"]
55
+ "infra-server" = ["infra-client", "inspec"]
56
+ "push-jobs-server" = ["infra-client", "infra-server"]
57
+ "push-jobs-client" = ["infra-client"]
58
+ "chef-dk" = ["infra-client", "inspec"]
59
+ "chef-workstation" = ["infra-client", "inspec"]
@@ -1,28 +1,37 @@
1
- require "forwardable"
1
+ require "forwardable" unless defined?(Forwardable)
2
2
  require "license_acceptance/config"
3
3
  require "license_acceptance/logger"
4
4
  require "license_acceptance/product_reader"
5
5
  require "license_acceptance/product_relationship"
6
- require "license_acceptance/file_acceptance"
7
- require "license_acceptance/arg_acceptance"
8
- require "license_acceptance/prompt_acceptance"
9
- require "license_acceptance/env_acceptance"
6
+ require "license_acceptance/strategy/environment"
7
+ require "license_acceptance/strategy/file"
8
+ require "license_acceptance/strategy/argument"
9
+ require "license_acceptance/strategy/prompt"
10
+ require "license_acceptance/strategy/provided_value"
10
11
 
11
12
  module LicenseAcceptance
13
+
14
+ ACCEPT = "accept".freeze
15
+ ACCEPT_SILENT = "accept-silent".freeze
16
+ ACCEPT_NO_PERSIST = "accept-no-persist".freeze
17
+
12
18
  class Acceptor
13
19
  extend Forwardable
14
20
  include Logger
15
21
 
16
- attr_reader :config, :product_reader, :env_acceptance, :file_acceptance, :arg_acceptance, :prompt_acceptance
22
+ attr_reader :config, :product_reader, :env_strategy, :file_strategy, :arg_strategy, :prompt_strategy, :provided_strategy
17
23
 
18
- def initialize(opts={})
24
+ def initialize(opts = {})
19
25
  @config = Config.new(opts)
20
26
  Logger.initialize(config.logger)
21
27
  @product_reader = ProductReader.new
22
- @env_acceptance = EnvAcceptance.new
23
- @file_acceptance = FileAcceptance.new(config)
24
- @arg_acceptance = ArgAcceptance.new
25
- @prompt_acceptance = PromptAcceptance.new(config)
28
+ product_reader.read
29
+ @env_strategy = Strategy::Environment.new(ENV)
30
+ @file_strategy = Strategy::File.new(config)
31
+ @arg_strategy = Strategy::Argument.new(ARGV)
32
+ @prompt_strategy = Strategy::Prompt.new(config)
33
+ @provided_strategy = Strategy::ProvidedValue.new(opts.fetch(:provided, nil))
34
+ @acceptance_value = nil
26
35
  end
27
36
 
28
37
  def_delegator :@config, :output
@@ -30,100 +39,148 @@ module LicenseAcceptance
30
39
  # For applications that just need simple logic to handle a failed license acceptance flow we include this small
31
40
  # wrapper. Apps with more complex logic (like logging to a logging engine) should call the non-bang version and
32
41
  # handle the exception.
33
- def check_and_persist!(product_name, version)
34
- check_and_persist(product_name, version)
35
- rescue LicenseNotAcceptedError
36
- output.puts "#{product_name} cannot execute without accepting the license"
42
+ def check_and_persist!(product_id, version)
43
+ check_and_persist(product_id, version)
44
+ rescue LicenseNotAcceptedError => e
45
+ output.puts "#{e.product.pretty_name} cannot execute without accepting the license"
37
46
  exit 172
38
47
  end
39
48
 
40
- def check_and_persist(product_name, version)
49
+ def check_and_persist(product_id, version)
41
50
  if accepted_no_persist?
42
51
  logger.debug("Chef License accepted with no persistence")
52
+ @acceptance_value = ACCEPT_NO_PERSIST
43
53
  return true
44
54
  end
45
55
 
46
- product_reader.read
47
- product_relationship = product_reader.lookup(product_name, version)
56
+ product_relationship = product_reader.lookup(product_id, version)
48
57
 
49
- missing_licenses = file_acceptance.accepted?(product_relationship)
58
+ missing_licenses = file_strategy.accepted?(product_relationship)
50
59
 
51
60
  # They have already accepted all licenses and stored their acceptance in the persistent files
52
61
  if missing_licenses.empty?
53
62
  logger.debug("All licenses present")
63
+ @acceptance_value = ACCEPT
54
64
  return true
55
65
  end
56
66
 
57
67
  if accepted? || accepted_silent?
58
68
  if config.persist
59
- errs = file_acceptance.persist(product_relationship, missing_licenses)
69
+ errs = file_strategy.persist(product_relationship, missing_licenses)
60
70
  if errs.empty?
61
71
  output_num_persisted(missing_licenses.size) unless accepted_silent?
62
72
  else
63
73
  output_persist_failed(errs)
64
74
  end
65
75
  end
76
+ @acceptance_value = accepted_silent? ? ACCEPT_SILENT : ACCEPT
66
77
  return true
67
- elsif config.output.isatty && prompt_acceptance.request(missing_licenses) do
68
- if config.persist
69
- file_acceptance.persist(product_relationship, missing_licenses)
70
- else
71
- []
72
- end
78
+ end
79
+
80
+ if acceptance_value_provided?
81
+ value = provided_strategy.value || env_strategy.value || arg_strategy.value
82
+ output.puts("Unrecognized license acceptance value '#{value}', expected one of: '#{ACCEPT}', '#{ACCEPT_SILENT}', '#{ACCEPT_NO_PERSIST}'")
83
+ raise LicenseNotAcceptedError.new(product_relationship.parent, missing_licenses)
84
+ end
85
+
86
+ return true if output.isatty && accepted_license_prompt?(product_relationship, missing_licenses)
87
+
88
+ raise LicenseNotAcceptedError.new(product_relationship.parent, missing_licenses)
89
+ end
90
+
91
+ def self.check_and_persist!(product_id, version, opts = {})
92
+ new(opts).check_and_persist!(product_id, version)
93
+ end
94
+
95
+ def self.check_and_persist(product_id, version, opts = {})
96
+ new(opts).check_and_persist(product_id, version)
97
+ end
98
+
99
+ def accepted_license_prompt?(product_relationship, missing_licenses)
100
+ prompt_strategy.request(missing_licenses) do
101
+ # We have to infer the acceptance value if they use the prompt to accept
102
+ if config.persist
103
+ @acceptance_value = ACCEPT
104
+ file_strategy.persist(product_relationship, missing_licenses)
105
+ else
106
+ @acceptance_value = ACCEPT_NO_PERSIST
107
+ []
73
108
  end
74
- return true
75
- else
76
- raise LicenseNotAcceptedError.new(missing_licenses)
77
109
  end
78
110
  end
79
111
 
80
- def self.check_and_persist!(product_name, version, opts={})
81
- new(opts).check_and_persist!(product_name, version)
112
+ # Check whether the specified product requires license acceptance for the given version.
113
+ def license_required?(mixlib_name, version)
114
+ product = product_reader.lookup_by_mixlib(mixlib_name)
115
+ return false if product.nil?
116
+ # If they don't pass a version we assume they want latest
117
+ # All versions in all channels require license acceptance
118
+ return true if %w{latest unstable current stable}.include?(version.to_s) || version.nil?
119
+
120
+ Gem::Version.new(version) >= Gem::Version.new(product.license_required_version)
121
+ end
122
+
123
+ # Some callers only know about mixlib names so we need a way for them to get the product
124
+ # id as this library knows it.
125
+ def id_from_mixlib(mixlib_name)
126
+ product = product_reader.lookup_by_mixlib(mixlib_name)
127
+ return nil if product.nil?
128
+
129
+ product.id
82
130
  end
83
131
 
84
- def self.check_and_persist(product_name, version, opts={})
85
- new(opts).check_and_persist(product_name, version)
132
+ # Return the value that was matched ("accept", "accept-no-persist", etc.). Used by callers so they do not
133
+ # have to know the precedence order between provided/environment/argument. Can just get back the value
134
+ # that was used. Value is only guaranteed to be set after calling check_and_persist.
135
+ def acceptance_value
136
+ @acceptance_value
86
137
  end
87
138
 
88
139
  def accepted?
89
- env_acceptance.accepted?(ENV) || arg_acceptance.accepted?(ARGV)
140
+ provided_strategy.accepted? || env_strategy.accepted? || arg_strategy.accepted?
90
141
  end
91
142
 
92
143
  # no-persist is silent too
93
144
  def accepted_no_persist?
94
- env_acceptance.no_persist?(ENV) || arg_acceptance.no_persist?(ARGV)
145
+ provided_strategy.no_persist? || env_strategy.no_persist? || arg_strategy.no_persist?
95
146
  end
96
147
 
97
148
  # persist but be silent like no-persist
98
149
  def accepted_silent?
99
- env_acceptance.silent?(ENV) || arg_acceptance.silent?(ARGV)
150
+ provided_strategy.silent? || env_strategy.silent? || arg_strategy.silent?
151
+ end
152
+
153
+ def acceptance_value_provided?
154
+ provided_strategy.value? || env_strategy.value? || arg_strategy.value?
100
155
  end
101
156
 
102
157
  # In the case where users accept with a command line argument or environment variable
103
158
  # we still want to output the fact that the filesystem was changed.
104
159
  def output_num_persisted(count)
105
- s = count > 1 ? "s": ""
160
+ s = count > 1 ? "s" : ""
106
161
  output.puts <<~EOM
107
- #{PromptAcceptance::BORDER}
108
- #{PromptAcceptance::CHECK} #{count} product license#{s} accepted.
109
- #{PromptAcceptance::BORDER}
162
+ #{Strategy::Prompt::BORDER}
163
+ #{Strategy::Prompt::CHECK} #{count} product license#{s} accepted.
164
+ #{Strategy::Prompt::BORDER}
110
165
  EOM
111
166
  end
112
167
 
113
168
  def output_persist_failed(errs)
114
169
  output.puts <<~EOM
115
- #{PromptAcceptance::BORDER}
116
- #{PromptAcceptance::CHECK} Product license accepted.
117
- Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
118
- #{PromptAcceptance::BORDER}
170
+ #{Strategy::Prompt::BORDER}
171
+ #{Strategy::Prompt::CHECK} Product license accepted.
172
+ Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
173
+ #{Strategy::Prompt::BORDER}
119
174
  EOM
120
175
  end
121
176
 
122
177
  end
123
178
 
124
179
  class LicenseNotAcceptedError < RuntimeError
125
- def initialize(missing_licenses)
126
- msg = "Missing licenses for the following:\n* " + missing_licenses.join("\n* ")
180
+ attr_reader :product
181
+ def initialize(product, missing_licenses)
182
+ @product = product
183
+ msg = "Missing licenses for the following:\n* " + missing_licenses.map(&:id).join("\n* ")
127
184
  super(msg)
128
185
  end
129
186
  end
@@ -1,6 +1,6 @@
1
1
  begin
2
- require 'mixlib/cli'
3
- rescue => exception
2
+ require "mixlib/cli" unless defined?(Mixlib::CLI)
3
+ rescue
4
4
  raise "Must have mixlib-cli gem installed to use this mixin"
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
1
  begin
2
- require 'thor'
3
- rescue => exception
2
+ require "thor" unless defined?(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: 'Accept the license for this product and any contained products: accept, accept-no-persist, accept-silent'
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 'logger'
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,8 @@ module LicenseAcceptance
21
21
 
22
22
  def default_license_locations
23
23
  if windows?
24
- l = [ File.join(ENV["HOMEDRIVE"], "chef/accepted_licenses/") ]
24
+ root = ENV.fetch("SYSTEMDRIVE", "C:")
25
+ l = [ File.join(root, "chef/accepted_licenses/") ]
25
26
  unless is_root?
26
27
  # Look through a list of possible user locations and pick the first one that exists
27
28
  # copied from path_helper.rb in chef-config gem
@@ -31,6 +32,7 @@ module LicenseAcceptance
31
32
  possible_dirs << ENV["HOMESHARE"] + ENV["HOMEPATH"] if ENV["HOMESHARE"] && ENV["HOMEPATH"]
32
33
  possible_dirs << ENV["USERPROFILE"] if ENV["USERPROFILE"]
33
34
  raise NoValidEnvironmentVar if possible_dirs.empty?
35
+
34
36
  possible_dirs.each do |possible_dir|
35
37
  if Dir.exist?(possible_dir)
36
38
  full_possible_dir = File.join(possible_dir, ".chef/accepted_licenses/")
@@ -41,7 +43,7 @@ module LicenseAcceptance
41
43
  end
42
44
  else
43
45
  l = [ "/etc/chef/accepted_licenses/" ]
44
- l << File.join(ENV['HOME'], ".chef/accepted_licenses/") unless is_root?
46
+ l << File.join(ENV["HOME"], ".chef/accepted_licenses/") unless is_root?
45
47
  end
46
48
  l
47
49
  end
@@ -1,22 +1,29 @@
1
1
  module LicenseAcceptance
2
2
  class Product
3
3
 
4
- attr_reader :name, :pretty_name, :filename
4
+ attr_reader :id, :pretty_name, :filename, :mixlib_name, :license_required_version
5
5
 
6
- def initialize(name, pretty_name, filename)
7
- @name = name
6
+ def initialize(id, pretty_name, filename, mixlib_name, license_required_version)
7
+ # id is the internal representation of this product as license-acceptance knows it
8
+ @id = id
8
9
  @pretty_name = pretty_name
9
10
  @filename = filename
11
+ @mixlib_name = mixlib_name
12
+ @license_required_version = license_required_version
10
13
  end
11
14
 
12
15
  def ==(other)
13
16
  return false if other.class != Product
14
- if other.name == name &&
15
- other.pretty_name == pretty_name &&
16
- other.filename == filename
17
- return true
17
+
18
+ if other.id == id &&
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
18
24
  end
19
- return false
25
+
26
+ false
20
27
  end
21
28
 
22
29
  end
@@ -1,4 +1,4 @@
1
- require "tomlrb"
1
+ autoload :Tomlrb, "tomlrb"
2
2
  require "license_acceptance/logger"
3
3
  require "license_acceptance/product"
4
4
  require "license_acceptance/product_relationship"
@@ -18,21 +18,27 @@ 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
- for product in toml["products"]
22
- products[product["name"]] = Product.new(product["name"], product["pretty_name"], product["filename"])
21
+ toml["products"].each do |product|
22
+ products[product["id"]] = Product.new(
23
+ product["id"], product["pretty_name"],
24
+ product["filename"], product["mixlib_name"],
25
+ product["license_required_version"]
26
+ )
23
27
  end
24
28
 
25
- for parent_name, children in toml["relationships"]
26
- parent = products[parent_name]
27
- raise UnknownParent.new(parent_name) if parent.nil?
29
+ toml["relationships"].each do |parent_id, children|
30
+ parent = products[parent_id]
31
+ raise UnknownParent.new(parent_id) if parent.nil?
28
32
  # Its fine to not have a relationship entry, but not fine to have
29
33
  # a relationship where the children are nil or empty.
30
34
  if children.nil? || children.empty? || !children.is_a?(Array)
31
35
  raise NoChildRelationships.new(parent)
32
36
  end
33
- children.map! do |child_name|
34
- child = products[child_name]
35
- raise UnknownChild.new(child_name) if child.nil?
37
+
38
+ children.map! do |child_id|
39
+ child = products[child_id]
40
+ raise UnknownChild.new(child_id) if child.nil?
41
+
36
42
  child
37
43
  end
38
44
  relationships[parent] = children
@@ -48,20 +54,29 @@ module LicenseAcceptance
48
54
  if ENV["CHEF_LICENSE_PRODUCT_INFO"]
49
55
  return ENV["CHEF_LICENSE_PRODUCT_INFO"]
50
56
  end
57
+
51
58
  File.absolute_path(File.join(__FILE__, "../../../config/product_info.toml"))
52
59
  end
53
60
 
54
- def lookup(parent_name, parent_version)
55
- parent_product = products.fetch(parent_name) do
56
- raise UnknownProduct.new(parent_name)
61
+ def lookup(parent_id, parent_version)
62
+ parent_product = products.fetch(parent_id) do
63
+ raise UnknownProduct.new(parent_id)
57
64
  end
58
65
  children = relationships.fetch(parent_product, [])
59
- if !parent_version.is_a? String
66
+ unless parent_version.is_a? String
60
67
  raise ProductVersionTypeError.new(parent_version)
61
68
  end
69
+
62
70
  ProductRelationship.new(parent_product, children, parent_version)
63
71
  end
64
72
 
73
+ def lookup_by_mixlib(mixlib_name)
74
+ found_product = products.values.find(nil) do |p|
75
+ p.mixlib_name == mixlib_name
76
+ end
77
+ found_product
78
+ end
79
+
65
80
  end
66
81
 
67
82
  class UnknownProduct < RuntimeError
@@ -94,7 +109,7 @@ module LicenseAcceptance
94
109
 
95
110
  class NoChildRelationships < RuntimeError
96
111
  def initialize(product)
97
- msg = "No child relationships for #{product.name}, should be removed from product info or fixed"
112
+ msg = "No child relationships for #{product.id}, should be removed from product info or fixed"
98
113
  super(msg)
99
114
  end
100
115
  end
@@ -0,0 +1,45 @@
1
+ require "license_acceptance/strategy/base"
2
+
3
+ module LicenseAcceptance
4
+ module Strategy
5
+
6
+ # Look for acceptance values in the ARGV
7
+ class Argument < Base
8
+
9
+ FLAG = "--chef-license".freeze
10
+
11
+ attr_reader :argv
12
+
13
+ def initialize(argv)
14
+ @argv = argv
15
+ end
16
+
17
+ def accepted?
18
+ String(value).downcase == ACCEPT
19
+ end
20
+
21
+ def silent?
22
+ String(value).downcase == ACCEPT_SILENT
23
+ end
24
+
25
+ def no_persist?
26
+ String(value).downcase == ACCEPT_NO_PERSIST
27
+ end
28
+
29
+ def value?
30
+ argv.any? { |s| s == FLAG || s.start_with?("#{FLAG}=") }
31
+ end
32
+
33
+ def value
34
+ match = argv.detect { |s| s.start_with?("#{FLAG}=") }
35
+ return match.split("=").last if match
36
+
37
+ argv.each_cons(2) do |arg, value|
38
+ return value if arg == FLAG
39
+ end
40
+
41
+ nil
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ module LicenseAcceptance
2
+ module Strategy
3
+ class Base
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,39 @@
1
+ require "license_acceptance/strategy/base"
2
+
3
+ module LicenseAcceptance
4
+ module Strategy
5
+
6
+ # Look for acceptance values in the environment
7
+ class Environment < Base
8
+
9
+ ENV_KEY = "CHEF_LICENSE".freeze
10
+
11
+ attr_reader :env
12
+
13
+ def initialize(env)
14
+ @env = env
15
+ end
16
+
17
+ def accepted?
18
+ String(value).downcase == ACCEPT
19
+ end
20
+
21
+ def silent?
22
+ String(value).downcase == ACCEPT_SILENT
23
+ end
24
+
25
+ def no_persist?
26
+ String(value).downcase == ACCEPT_NO_PERSIST
27
+ end
28
+
29
+ def value?
30
+ env.key?(ENV_KEY)
31
+ end
32
+
33
+ def value
34
+ env[ENV_KEY]
35
+ end
36
+
37
+ end
38
+ end
39
+ end