module Puppet::ModuleTool::Shared

Public Instance Methods

add_module_name_constraints_to_graph(graph) click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
169 def add_module_name_constraints_to_graph(graph)
170   # Puppet modules are installed by "module name", but resolved by
171   # "full name" (including namespace).  So that we don't run into
172   # problems at install time, we should reject any solution that
173   # depends on multiple nodes with the same "module name".
174   graph.add_graph_constraint('PMT') do |nodes|
175     names = nodes.map { |x| x.dependency_names + [ x.name ] }.flatten
176     names = names.map { |x| x.tr('/', '-') }.uniq
177     names = names.map { |x| x[/-(.*)/, 1] }
178     names.length == names.uniq.length
179   end
180 end
annotated_version(mod, versions) click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
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
download_tarballs(graph, default_path, forge) click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
146 def download_tarballs(graph, default_path, forge)
147   graph.map do |release|
148     begin
149       if release[:tarball]
150         cache_path = Pathname(release[:tarball])
151       else
152         cache_path = forge.retrieve(release[:file])
153       end
154     rescue OpenURI::HTTPError => e
155       raise RuntimeError, _("Could not download module: %{message}") % { message: e.message }, e.backtrace
156     end
157 
158     [
159       { (release[:path] ||= default_path) => cache_path},
160       *download_tarballs(release[:dependencies], default_path, forge)
161     ]
162   end.flatten
163 end
forced?() click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
165 def forced?
166   options[:force]
167 end
get_local_constraints() click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
 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).tr('/', '-')
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.tr('/', '-')
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
get_remote_constraints(forge) click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
27 def get_remote_constraints(forge)
28   @remote   = Hash.new { |h,k| h[k] = { } }
29   @urls     = {}
30   @versions = Hash.new { |h,k| h[k] = [] }
31 
32   Puppet.notice _("Downloading from %{uri} ...") % { uri: forge.uri }
33   author, modname = Puppet::ModuleTool.username_and_modname_from(@module_name)
34   info = forge.remote_dependency_info(author, modname, @options[:version])
35   info.each do |pair|
36     mod_name, releases = pair
37     mod_name = mod_name.tr('/', '-')
38     releases.each do |rel|
39       semver = SemanticPuppet::Version.parse(rel['version']) rescue SemanticPuppet::Version::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.tr('/', '-')] = conditions
46       end
47     end
48   end
49 end
implicit_version(mod) click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
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
resolve_constraints(dependencies, source = [{:name => :you}], seen = {}, action = @action) click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
 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 forced?
 79       range = Puppet::Module.parse_range(@version) rescue Puppet::Module.parse_range('>= 0.0.0')
 80     else
 81       range = (@conditions[mod]).map do |r|
 82         Puppet::Module.parse_range(r[:dependency]) rescue Puppet::Module.parse_range('>= 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 !(forced? || @installed[mod].empty? || source.last[:name] == :you)
100       next if range === SemanticPuppet::Version.parse(@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     versions = @versions["#{mod}"].select { |h| range === h[:semver] }
111     valid_versions = versions.select { |x| x[:semver].special == '' }
112     valid_versions = versions if valid_versions.empty?
113 
114     version = valid_versions.last
115     unless version
116       req_module   = @module_name
117       req_versions = @versions["#{@module_name}"].map { |v| v[:semver] }
118       raise NoVersionsSatisfyError,
119         :requested_name    => req_module,
120         :requested_version => @version || annotated_version(req_module, req_versions),
121         :installed_version => @installed[@module_name].empty? ? nil : @installed[@module_name].first.version,
122         :dependency_name   => mod,
123         :conditions        => @conditions[mod],
124         :action            => @action
125     end
126 
127     seen[mod] = version
128 
129     {
130       :module           => mod,
131       :version          => version,
132       :action           => action,
133       :previous_version => @installed[mod].empty? ? nil : @installed[mod].first.version,
134       :file             => @urls["#{mod}@#{version[:vstring]}"],
135       :path             => action == :install ? @options[:target_dir] : (@installed[mod].empty? ? @options[:target_dir] : @installed[mod].first.modulepath),
136       :dependencies     => []
137     }
138   end.compact
139   dependencies.each do |mod|
140     deps = @remote["#{mod[:module]}@#{mod[:version][:vstring]}"].sort_by(&:first)
141     mod[:dependencies] = resolve_constraints(deps, source + [{ :name => mod[:module], :version => mod[:version][:vstring] }], seen, :install)
142   end unless @ignore_dependencies
143   return dependencies
144 end