lib/mixlib/install.rb in mixlib-install-0.7.1 vs lib/mixlib/install.rb in mixlib-install-0.8.0.alpha.0

- old
+ new

@@ -1,7 +1,8 @@ # # Author:: Thom May (<thom@chef.io>) +# Author:: Patrick Wright (<patrick@chef.io>) # Copyright:: Copyright (c) 2015 Chef, 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. @@ -14,202 +15,78 @@ # 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 "mixlib/install/util" -require "cgi" +require "mixlib/versioning" +require "mixlib/install/backend" +require "mixlib/install/options" +require "mixlib/install/generator" + module Mixlib class Install - attr_accessor :version - attr_accessor :powershell + attr_reader :options - attr_accessor :prerelease - - attr_accessor :nightlies - - attr_accessor :install_flags - - attr_accessor :endpoint - - attr_accessor :root - - attr_accessor :use_sudo - - attr_reader :sudo_command - - def sudo_command=(cmd) - if cmd.nil? - @use_sudo = false - else - @sudo_command = cmd - end + def initialize(options = {}) + @options = Options.new(options) end - attr_accessor :http_proxy - attr_accessor :https_proxy - - attr_accessor :omnibus_url - attr_accessor :install_msi_url - - VALID_INSTALL_OPTS = %w(omnibus_url - endpoint - http_proxy - https_proxy - install_flags - install_msi_url - nightlies - prerelease - project - root - use_sudo - sudo_command) - - def initialize(version, powershell = false, opts = {}) - @version = version || "latest" - @powershell = powershell - @http_proxy = nil - @https_proxy = nil - @install_flags = nil - @prerelease = false - @nightlies = false - @endpoint = "metadata" - @omnibus_url = "https://www.chef.io/chef/install.sh" - @use_sudo = true - @sudo_command = "sudo -E" - - @root = if powershell - "$env:systemdrive\\opscode\\chef" - else - "/opt/chef" - end - - parse_opts(opts) + # + # Fetch artifact metadata information + # + # @return [ArtifactInfo] fetched artifact data + # + def artifact_info + Backend.info(options) end + # + # Returns an install script for the given options + # + # @return [String] script for installing with given options + # def install_command - vars = if powershell - install_command_vars_for_powershell - else - install_command_vars_for_bourne - end - shell_code_from_file(vars) + Generator.install_command(options) end - private - - # Generates the install command variables for Bourne shell-based - # platforms. # - # @return [String] shell variable lines - # @api private - def install_command_vars_for_bourne - flags = %w[latest true nightlies].include?(version) ? "" : "-v #{CGI.escape(version)}" - flags << " " << "-n" if nightlies - flags << " " << "-p" if prerelease - flags << " " << install_flags if install_flags - - [ - shell_var("chef_omnibus_root", root), - shell_var("chef_omnibus_url", omnibus_url), - shell_var("install_flags", flags.strip), - shell_var("pretty_version", Util.pretty_version(version)), - shell_var("sudo_sh", sudo("sh")), - shell_var("version", version) - ].join("\n") - end - - # Generates the install command variables for PowerShell-based platforms. + # Returns the base installation directory for the given options # - # @param version [String] version string - # @param metadata_url [String] The metadata URL for the Chef Omnitruck API server - # @param omnibus_root [String] The base directory the project is installed to - # @return [String] shell variable lines - # @api private - def install_command_vars_for_powershell - [ - shell_var("chef_omnibus_root", root), - shell_var("msi", "$env:TEMP\\chef-#{version}.msi"), - ].tap { |vars| - if install_msi_url - vars << shell_var("chef_msi_url", install_msi_url) - else - vars << shell_var("chef_metadata_url", windows_metadata_url) - vars << shell_var("pretty_version", Util.pretty_version(version)) - vars << shell_var("version", version) - end - }.join("\n") - end - - def validate_opts!(opt) - err_msg = ["#{opt} is not a valid option", - "valid options are #{VALID_INSTALL_OPTS.join(' ')}"].join(',') - fail ArgumentError, err_msg unless VALID_INSTALL_OPTS.include?(opt.to_s) - end - - # rubocop:disable Metrics/MethodLength - def parse_opts(opts) - opts.each do |opt, setting| - validate_opts!(opt) - case opt.to_s - when 'project', 'endpoint' - self.endpoint = metadata_endpoint_from_project(setting) - else - send("#{opt.to_sym}=", setting) - end - end - end - - def shell_code_from_file(vars) - fn = File.join( - File.dirname(__FILE__), - %w[.. .. support], - "install_command" - ) - Util.shell_code_from_file(vars, fn, powershell, - http_proxy: http_proxy, https_proxy: https_proxy) - end - - # Builds a shell variable assignment string for the required shell type. + # @return [String] the installation directory for the project # - # @param name [String] variable name - # @param value [String] variable value - # @return [String] shell variable assignment - # @api private - def shell_var(name, value) - Util.shell_var(name, value, powershell) + def root + # TODO: Support root as "$env:systemdrive\\opscode\\chef" when on windows. + # This only works for chef and chefdk but they are the only projects + # we are supporting as of now. + "/opt/#{options.product_name}" end - # @return the correct Chef Omnitruck API metadata endpoint, based on project - def metadata_endpoint_from_project(project = nil) - if project.nil? || project.downcase == "chef" - "metadata" - else - "metadata-#{project.downcase}" + # + # Returns the current version of the installed product. + # Returns nil if the product is not installed. + # + def current_version + # Note that this logic does not work for products other than + # chef & chefdk since version-manifest is created under the + # install directory which can be different than the product name (e.g. + # chef-server -> /opt/opscode). But this is OK for now since + # chef & chefdk are the only supported products. + version_manifest_file = "/opt/#{options.product_name}/version-manifest.json" + if File.exist? version_manifest_file + JSON.parse(File.read(version_manifest_file))["build_version"] end end - def windows_metadata_url - base = if omnibus_url =~ %r{/install.sh$} - "#{File.dirname(omnibus_url)}/" - end - - url = "#{base}#{endpoint}" - url << "?p=windows&m=x86_64&pv=2008r2" # same package for all versions - url << "&v=#{CGI.escape(version.to_s.downcase)}" - url << "&prerelease=true" if prerelease - url << "&nightlies=true" if nightlies - url - end - - # Conditionally prefixes a command with a sudo command. # - # @param command [String] command to be prefixed - # @return [String] the command, conditionaly prefixed with sudo - # @api private - def sudo(script) - use_sudo ? "#{sudo_command} #{script}" : script + # Returns true if an upgradable version is available, false otherwise. + # + def upgrade_available? + return true if current_version.nil? + + available_ver = Mixlib::Versioning.parse(artifact_info.first.version) + current_ver = Mixlib::Versioning.parse(current_version) + (available_ver > current_ver) end end end