class LicenseAcceptance::Acceptor
def self.check_and_persist(product_id, version, opts = {})
def self.check_and_persist(product_id, version, opts = {}) new(opts).check_and_persist(product_id, version) end
def self.check_and_persist!(product_id, version, opts = {})
def self.check_and_persist!(product_id, version, opts = {}) new(opts).check_and_persist!(product_id, version) end
def acceptance_value
have to know the precedence order between provided/environment/argument. Can just get back the value
Return the value that was matched ("accept", "accept-no-persist", etc.). Used by callers so they do not
def acceptance_value @acceptance_value end
def acceptance_value_provided?
def acceptance_value_provided? provided_strategy.value? || env_strategy.value? || arg_strategy.value? end
def accepted?
def accepted? provided_strategy.accepted? || env_strategy.accepted? || arg_strategy.accepted? end
def accepted_license_prompt?(product_relationship, missing_licenses)
def accepted_license_prompt?(product_relationship, missing_licenses) prompt_strategy.request(missing_licenses) do # We have to infer the acceptance value if they use the prompt to accept if config.persist @acceptance_value = ACCEPT file_strategy.persist(product_relationship, missing_licenses) else @acceptance_value = ACCEPT_NO_PERSIST [] end end end
def accepted_no_persist?
def accepted_no_persist? provided_strategy.no_persist? || env_strategy.no_persist? || arg_strategy.no_persist? end
def accepted_silent?
def accepted_silent? provided_strategy.silent? || env_strategy.silent? || arg_strategy.silent? end
def check_and_persist(product_id, version)
def check_and_persist(product_id, version) if accepted_no_persist? logger.debug("Chef License accepted with no persistence") @acceptance_value = ACCEPT_NO_PERSIST return true end product_relationship = product_reader.lookup(product_id, version) missing_licenses = file_strategy.accepted?(product_relationship) # They have already accepted all licenses and stored their acceptance in the persistent files if missing_licenses.empty? logger.debug("All licenses present") @acceptance_value = ACCEPT return true end if accepted? || accepted_silent? if config.persist errs = file_strategy.persist(product_relationship, missing_licenses) if errs.empty? output_num_persisted(missing_licenses.size) unless accepted_silent? else output_persist_failed(errs) end end @acceptance_value = accepted_silent? ? ACCEPT_SILENT : ACCEPT return true end if acceptance_value_provided? value = provided_strategy.value || env_strategy.value || arg_strategy.value output.puts("Unrecognized license acceptance value '#{value}', expected one of: '#{ACCEPT}', '#{ACCEPT_SILENT}', '#{ACCEPT_NO_PERSIST}'") raise LicenseNotAcceptedError.new(product_relationship.parent, missing_licenses) end return true if output.isatty && accepted_license_prompt?(product_relationship, missing_licenses) raise LicenseNotAcceptedError.new(product_relationship.parent, missing_licenses) end
def check_and_persist!(product_id, version)
wrapper. Apps with more complex logic (like logging to a logging engine) should call the non-bang version and
For applications that just need simple logic to handle a failed license acceptance flow we include this small
def check_and_persist!(product_id, version) check_and_persist(product_id, version) rescue LicenseNotAcceptedError => e output.puts "#{e.product.pretty_name} cannot execute without accepting the license" exit 172 end
def id_from_mixlib(mixlib_name)
Some callers only know about mixlib names so we need a way for them to get the product
def id_from_mixlib(mixlib_name) product = product_reader.lookup_by_mixlib(mixlib_name) return nil if product.nil? product.id end
def initialize(opts = {})
def initialize(opts = {}) @config = Config.new(opts) Logger.initialize(config.logger) @product_reader = ProductReader.new product_reader.read @env_strategy = Strategy::Environment.new(ENV) @file_strategy = Strategy::File.new(config) @arg_strategy = Strategy::Argument.new(ARGV) @prompt_strategy = Strategy::Prompt.new(config) @provided_strategy = Strategy::ProvidedValue.new(opts.fetch(:provided, nil)) @acceptance_value = nil end
def license_required?(mixlib_name, version)
def license_required?(mixlib_name, version) product = product_reader.lookup_by_mixlib(mixlib_name) return false if product.nil? # If they don't pass a version we assume they want latest # All versions in all channels require license acceptance return true if %w{latest unstable current stable}.include?(version.to_s) || version.nil? Gem::Version.new(version) >= Gem::Version.new(product.license_required_version) end
def output_num_persisted(count)
In the case where users accept with a command line argument or environment variable
def output_num_persisted(count) s = count > 1 ? "s" : "" output.puts <<~EOM #{Strategy::Prompt::BORDER} #{Strategy::Prompt::CHECK} #{count} product license#{s} accepted. #{Strategy::Prompt::BORDER} EOM end
def output_persist_failed(errs)
def output_persist_failed(errs) output.puts <<~EOM #{Strategy::Prompt::BORDER} #{Strategy::Prompt::CHECK} Product license accepted. Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")} #{Strategy::Prompt::BORDER} EOM end