class Puppet::ModuleTool::Applications::Upgrader

Public Class Methods

new(name, forge, options) click to toggle source
# File lib/puppet/module_tool/applications/upgrader.rb, line 7
def initialize(name, forge, options)
  @action              = :upgrade
  @environment         = Puppet::Node::Environment.new(Puppet.settings[:environment])
  @module_name         = name
  @options             = options
  @force               = options[:force]
  @ignore_dependencies = options[:force] || options[:ignore_dependencies]
  @version             = options[:version]
  @forge               = forge
end

Public Instance Methods

run() click to toggle source
# File lib/puppet/module_tool/applications/upgrader.rb, line 18
def run
  begin
    results = { :module_name => @module_name }

    get_local_constraints

    if @installed[@module_name].length > 1
      raise MultipleInstalledError,
        :action            => :upgrade,
        :module_name       => @module_name,
        :installed_modules => @installed[@module_name].sort_by { |mod| @environment.modulepath.index(mod.modulepath) }
    elsif @installed[@module_name].empty?
      raise NotInstalledError,
        :action      => :upgrade,
        :module_name => @module_name
    end

    @module = @installed[@module_name].last
    results[:installed_version] = @module.version ? @module.version.sub(/^(?=\d)/, 'v') : nil
    results[:requested_version] = @version || (@conditions[@module_name].empty? ? :latest : :best)
    dir = @module.modulepath

    Puppet.notice "Found '#{@module_name}' (#{colorize(:cyan, results[:installed_version] || '???')}) in #{dir} ..."
    if !@options[:force] && @module.has_metadata? && @module.has_local_changes?
      raise LocalChangesError,
        :action            => :upgrade,
        :module_name       => @module_name,
        :requested_version => @version || (@conditions[@module_name].empty? ? :latest : :best),
        :installed_version => @module.version
    end

    begin
      get_remote_constraints(@forge)
    rescue => e
      raise UnknownModuleError, results.merge(:repository => @forge.uri)
    else
      raise UnknownVersionError, results.merge(:repository => @forge.uri) if @remote.empty?
    end

    if !@options[:force] && @versions["#{@module_name}"].last[:vstring].sub(/^(?=\d)/, 'v') == (@module.version || '0.0.0').sub(/^(?=\d)/, 'v')
      raise VersionAlreadyInstalledError,
        :module_name       => @module_name,
        :requested_version => @version || ((@conditions[@module_name].empty? ? 'latest' : 'best') + ": #{@versions["#{@module_name}"].last[:vstring].sub(/^(?=\d)/, 'v')}"),
        :installed_version => @installed[@module_name].last.version,
        :conditions        => @conditions[@module_name] + [{ :module => :you, :version => @version }]
    end

    @graph = resolve_constraints({ @module_name => @version })

    # This clean call means we never "cache" the module we're installing, but this
    # is desired since module authors can easily rerelease modules different content but the same
    # version number, meaning someone with the old content cached will be very confused as to why
    # they can't get new content.
    # Long term we should just get rid of this caching behavior and cleanup downloaded modules after they install
    # but for now this is a quick fix to disable caching
    Puppet::Forge::Cache.clean
    tarballs = download_tarballs(@graph, @graph.last[:path], @forge)

    unless @graph.empty?
      Puppet.notice 'Upgrading -- do not interrupt ...'
      tarballs.each do |hash|
        hash.each do |dir, path|
          Unpacker.new(path, @options.merge(:target_dir => dir)).run
        end
      end
    end

    results[:result] = :success
    results[:base_dir] = @graph.first[:path]
    results[:affected_modules] = @graph
  rescue VersionAlreadyInstalledError => e
    results[:result] = :noop
    results[:error] = {
      :oneline   => e.message,
      :multiline => e.multiline
    }
  rescue => e
    results[:error] = {
      :oneline => e.message,
      :multiline => e.respond_to?(:multiline) ? e.multiline : [e.to_s, e.backtrace].join("\n")
    }
  ensure
    results[:result] ||= :failure
  end

  return results
end