~ubuntu-branches/ubuntu/quantal/puppet/quantal

« back to all changes in this revision

Viewing changes to lib/puppet/module_tool/shared_behaviors.rb

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-07-14 01:56:30 UTC
  • mfrom: (1.1.29) (3.1.43 sid)
  • Revision ID: package-import@ubuntu.com-20120714015630-ntj41rkvkq4zph4y
Tags: 2.7.18-1ubuntu1
* Resynchronise with Debian. (LP: #1023931) Remaining changes:
  - debian/puppetmaster-passenger.postinst: Make sure we error if puppet
    config print doesn't work
  - debian/puppetmaster-passenger.postinst: Ensure upgrades from
    <= 2.7.11-1 fixup passenger apache configuration.
* Dropped upstreamed patches:
  - debian/patches/CVE-2012-1906_CVE-2012-1986_to_CVE-2012-1989.patch
  - debian/patches/puppet-12844
  - debian/patches/2.7.17-Puppet-July-2012-CVE-fixes.patch
* Drop Build-Depends on ruby-rspec (in universe):
  - debian/control: remove ruby-rspec from Build-Depends
  - debian/patches/no-rspec.patch: make Rakefile work anyway if rspec
    isn't installed so we can use it in debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
module Puppet::ModuleTool::Shared
 
2
 
 
3
  include Puppet::ModuleTool::Errors
 
4
 
 
5
  def get_local_constraints
 
6
    @local      = Hash.new { |h,k| h[k] = { } }
 
7
    @conditions = Hash.new { |h,k| h[k] = [] }
 
8
    @installed  = Hash.new { |h,k| h[k] = [] }
 
9
 
 
10
    @environment.modules_by_path.values.flatten.each do |mod|
 
11
      mod_name = (mod.forge_name || mod.name).gsub('/', '-')
 
12
      @installed[mod_name] << mod
 
13
      d = @local["#{mod_name}@#{mod.version}"]
 
14
      (mod.dependencies || []).each do |hash|
 
15
        name, conditions = hash['name'], hash['version_requirement']
 
16
        name = name.gsub('/', '-')
 
17
        d[name] = conditions
 
18
        @conditions[name] << {
 
19
          :module => mod_name,
 
20
          :version => mod.version,
 
21
          :dependency => conditions
 
22
        }
 
23
      end
 
24
    end
 
25
  end
 
26
 
 
27
  def get_remote_constraints
 
28
    @remote   = Hash.new { |h,k| h[k] = { } }
 
29
    @urls     = {}
 
30
    @versions = Hash.new { |h,k| h[k] = [] }
 
31
 
 
32
    Puppet.notice "Downloading from #{Puppet::Forge.repository.uri} ..."
 
33
    author, modname = Puppet::ModuleTool.username_and_modname_from(@module_name)
 
34
    info = Puppet::Forge.remote_dependency_info(author, modname, @options[:version])
 
35
    info.each do |pair|
 
36
      mod_name, releases = pair
 
37
      mod_name = mod_name.gsub('/', '-')
 
38
      releases.each do |rel|
 
39
        semver = SemVer.new(rel['version'] || '0.0.0') rescue SemVer.MIN
 
40
        @versions[mod_name] << { :vstring => rel['version'], :semver => semver }
 
41
        @versions[mod_name].sort! { |a, b| a[:semver] <=> b[:semver] }
 
42
        @urls["#{mod_name}@#{rel['version']}"] = rel['file']
 
43
        d = @remote["#{mod_name}@#{rel['version']}"]
 
44
        (rel['dependencies'] || []).each do |name, conditions|
 
45
          d[name.gsub('/', '-')] = conditions
 
46
        end
 
47
      end
 
48
    end
 
49
  end
 
50
 
 
51
  def implicit_version(mod)
 
52
    return :latest if @conditions[mod].empty?
 
53
    if @conditions[mod].all? { |c| c[:queued] || c[:module] == :you }
 
54
      return :latest
 
55
    end
 
56
    return :best
 
57
  end
 
58
 
 
59
  def annotated_version(mod, versions)
 
60
    if versions.empty?
 
61
      return implicit_version(mod)
 
62
    else
 
63
      return "#{implicit_version(mod)}: #{versions.last}"
 
64
    end
 
65
  end
 
66
 
 
67
  def resolve_constraints(dependencies, source = [{:name => :you}], seen = {}, action = @action)
 
68
    dependencies = dependencies.map do |mod, range|
 
69
      source.last[:dependency] = range
 
70
 
 
71
      @conditions[mod] << {
 
72
        :module     => source.last[:name],
 
73
        :version    => source.last[:version],
 
74
        :dependency => range,
 
75
        :queued     => true
 
76
      }
 
77
 
 
78
      if @force
 
79
        range = SemVer[@version] rescue SemVer['>= 0.0.0']
 
80
      else
 
81
        range = (@conditions[mod]).map do |r|
 
82
          SemVer[r[:dependency]] rescue SemVer['>= 0.0.0']
 
83
        end.inject(&:&)
 
84
      end
 
85
 
 
86
      if @action == :install && seen.include?(mod)
 
87
        next if range === seen[mod][:semver]
 
88
 
 
89
        req_module   = @module_name
 
90
        req_versions = @versions["#{@module_name}"].map { |v| v[:semver] }
 
91
        raise InvalidDependencyCycleError,
 
92
          :module_name       => mod,
 
93
          :source            => (source + [{ :name => mod, :version => source.last[:dependency] }]),
 
94
          :requested_module  => req_module,
 
95
          :requested_version => @version || annotated_version(req_module, req_versions),
 
96
          :conditions        => @conditions
 
97
      end
 
98
 
 
99
      if !(@force || @installed[mod].empty? || source.last[:name] == :you)
 
100
        next if range === SemVer.new(@installed[mod].first.version)
 
101
        action = :upgrade
 
102
      elsif @installed[mod].empty?
 
103
        action = :install
 
104
      end
 
105
 
 
106
      if action == :upgrade
 
107
        @conditions.each { |_, conds| conds.delete_if { |c| c[:module] == mod } }
 
108
      end
 
109
 
 
110
      valid_versions = @versions["#{mod}"].select { |h| range === h[:semver] }
 
111
 
 
112
      unless version = valid_versions.last
 
113
        req_module   = @module_name
 
114
        req_versions = @versions["#{@module_name}"].map { |v| v[:semver] }
 
115
        raise NoVersionsSatisfyError,
 
116
          :requested_name    => req_module,
 
117
          :requested_version => @version || annotated_version(req_module, req_versions),
 
118
          :installed_version => @installed[@module_name].empty? ? nil : @installed[@module_name].first.version,
 
119
          :dependency_name   => mod,
 
120
          :conditions        => @conditions[mod],
 
121
          :action            => @action
 
122
      end
 
123
 
 
124
      seen[mod] = version
 
125
 
 
126
      {
 
127
        :module           => mod,
 
128
        :version          => version,
 
129
        :action           => action,
 
130
        :previous_version => @installed[mod].empty? ? nil : @installed[mod].first.version,
 
131
        :file             => @urls["#{mod}@#{version[:vstring]}"],
 
132
        :path             => action == :install ? @options[:target_dir] : (@installed[mod].empty? ? @options[:target_dir] : @installed[mod].first.modulepath),
 
133
        :dependencies     => []
 
134
      }
 
135
    end.compact
 
136
    dependencies.each do |mod|
 
137
      deps = @remote["#{mod[:module]}@#{mod[:version][:vstring]}"].sort_by(&:first)
 
138
      mod[:dependencies] = resolve_constraints(deps, source + [{ :name => mod[:module], :version => mod[:version][:vstring] }], seen, :install)
 
139
    end unless @ignore_dependencies
 
140
    return dependencies
 
141
  end
 
142
 
 
143
  def download_tarballs(graph, default_path)
 
144
    graph.map do |release|
 
145
      begin
 
146
        if release[:tarball]
 
147
          cache_path = Pathname(release[:tarball])
 
148
        else
 
149
          cache_path = Puppet::Forge.repository.retrieve(release[:file])
 
150
        end
 
151
      rescue OpenURI::HTTPError => e
 
152
        raise RuntimeError, "Could not download module: #{e.message}"
 
153
      end
 
154
 
 
155
      [
 
156
        { (release[:path] ||= default_path) => cache_path},
 
157
        *download_tarballs(release[:dependencies], default_path)
 
158
      ]
 
159
    end.flatten
 
160
  end
 
161
end