# # Author:: Patrick Wright () # Copyright:: Copyright (c) 2015-2018 Chef Software, Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "product" require_relative "product_matrix" require_relative "util" require "mixlib/versioning" module Mixlib class Install class Options class InvalidOptions < ArgumentError; end attr_reader :options, :errors, :original_platform_version SUPPORTED_ARCHITECTURES = %w{ aarch64 armv7l i386 powerpc ppc64 ppc64le s390x sparc x86_64 } SUPPORTED_CHANNELS = [ :stable, :current, :unstable, ] SUPPORTED_PRODUCT_NAMES = PRODUCT_MATRIX.products SUPPORTED_SHELL_TYPES = [ :ps1, :sh, ] SUPPORTED_OPTIONS = [ :architecture, :channel, :platform, :platform_version, :product_name, :product_version, :shell_type, :platform_version_compatibility_mode, :include_metadata, :user_agent_headers, :install_command_options, ] SUPPORTED_WINDOWS_DESKTOP_VERSIONS = %w{10} SUPPORTED_WINDOWS_NANO_VERSIONS = %w{2016nano} def initialize(options) @options = options @errors = [] # Store original options in cases where we must remap @original_platform_version = options[:platform_version] resolve_platform_version_compatibility_mode! map_windows_versions! validate! end SUPPORTED_OPTIONS.each do |option| define_method option do options[option] || options[option.to_s] || default_options[option] end end def validate! validate_options! end def validate_options! validate_architecture validate_product_names validate_channels validate_shell_type validate_user_agent_headers validate_platform_options raise InvalidOptions, errors.join("\n") unless errors.empty? end def for_ps1? platform == "windows" || shell_type == :ps1 end alias_method :for_windows?, :for_ps1? def latest_version? product_version.to_sym == :latest end def partial_version? # If PartialSemVer is defined than the version of mixlib-versioning loaded can parse partial versions # Otherwise parsing a partial version will return nil is_partial = if defined?(Mixlib::Versioning::Format::PartialSemVer) # remove if there's a trailing period for mixlib-versioning compatibility options[:product_version] = product_version.chomp(".") if product_version.is_a? String Mixlib::Versioning.parse(product_version).is_a?(Mixlib::Versioning::Format::PartialSemVer) else !Mixlib::Versioning.parse(product_version) end !latest_version? && is_partial end def include_metadata? include_metadata.to_s == "true" end # # Set the platform info on the instance # info [Hash] # Hash with keys :platform, :platform_version and :architecture # def set_platform_info(info) options[:platform] = info[:platform] options[:platform_version] = info[:platform_version] options[:architecture] = info[:architecture] validate_options! end def platform_info { platform: options[:platform], platform_version: options[:platform_version], architecture: options[:architecture], } end # # Calling this method will give queries more of an opportunity to collect # compatible artifacts where there may not always be an exact match. # # This option is set to false by default. # - In cases where no platform options are configured it will set this option to true. # - In cases where all platform options are configured it will remain false UNLESS the option # has been configured to be true. # def resolve_platform_version_compatibility_mode! unless options[:platform_version_compatibility_mode] options[:platform_version_compatibility_mode] = true if platform_info.values.none? end end private def default_options { shell_type: :sh, platform_version_compatibility_mode: false, product_version: :latest, include_metadata: false, } end def validate_architecture unless architecture.nil? || SUPPORTED_ARCHITECTURES.include?(architecture) errors << <<-EOS Unknown architecture #{architecture}. Must be one of: #{SUPPORTED_ARCHITECTURES.join(", ")} EOS end end def validate_product_names unless SUPPORTED_PRODUCT_NAMES.include? product_name errors << <<-EOS Unknown product name #{product_name}. Must be one of: #{SUPPORTED_PRODUCT_NAMES.join(", ")} EOS end end def validate_channels unless SUPPORTED_CHANNELS.include? channel errors << <<-EOS Unknown channel #{channel}. Must be one of: #{SUPPORTED_CHANNELS.join(", ")} EOS end end def validate_shell_type unless SUPPORTED_SHELL_TYPES.include? shell_type errors << <<-EOS Unknown shell type. Must be one of: #{SUPPORTED_SHELL_TYPES.join(", ")} EOS end end def validate_user_agent_headers error = nil if user_agent_headers if user_agent_headers.is_a? Array user_agent_headers.each do |header| error = "user agent headers can not have spaces." if header.include?(" ") end else error = "user_agent_headers must be an Array." end end errors << error if error end def validate_platform_options unless all_or_none?(platform_info.values) errors << <<-EOS Must provide platform (-p), platform version (-l) and architecture (-a) when specifying any platform details EOS end end def map_windows_versions! return unless for_windows? options[:platform_version] = Util.map_windows_version(platform_version) end def all_or_none?(items) items.all? || items.compact.empty? end end end end