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
170 def add_module_name_constraints_to_graph(graph)
171   # Puppet modules are installed by "module name", but resolved by
172   # "full name" (including namespace).  So that we don't run into
173   # problems at install time, we should reject any solution that
174   # depends on multiple nodes with the same "module name".
175   graph.add_graph_constraint('PMT') do |nodes|
176     names = nodes.map { |x| x.dependency_names + [ x.name ] }.flatten
177     names = names.map { |x| x.tr('/', '-') }.uniq
178     names = names.map { |x| x[/-(.*)/, 1] }
179     names.length == names.uniq.length
180   end
181 end
annotated_version(mod, versions) click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
60 def annotated_version(mod, versions)
61   if versions.empty?
62     return implicit_version(mod)
63   else
64     return "#{implicit_version(mod)}: #{versions.last}"
65   end
66 end
download_tarballs(graph, default_path, forge) click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
147 def download_tarballs(graph, default_path, forge)
148   graph.map do |release|
149     begin
150       if release[:tarball]
151         cache_path = Pathname(release[:tarball])
152       else
153         cache_path = forge.retrieve(release[:file])
154       end
155     rescue OpenURI::HTTPError => e
156       raise RuntimeError, _("Could not download module: %{message}") % { message: e.message }, e.backtrace
157     end
158 
159     [
160       { (release[:path] ||= default_path) => cache_path},
161       *download_tarballs(release[:dependencies], default_path, forge)
162     ]
163   end.flatten
164 end
forced?() click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
166 def forced?
167   options[:force]
168 end
get_local_constraints() click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
 6 def get_local_constraints
 7   @local      = Hash.new { |h,k| h[k] = { } }
 8   @conditions = Hash.new { |h,k| h[k] = [] }
 9   @installed  = Hash.new { |h,k| h[k] = [] }
10 
11   @environment.modules_by_path.values.flatten.each do |mod|
12     mod_name = (mod.forge_name || mod.name).tr('/', '-')
13     @installed[mod_name] << mod
14     d = @local["#{mod_name}@#{mod.version}"]
15     (mod.dependencies || []).each do |hash|
16       name, conditions = hash['name'], hash['version_requirement']
17       name = name.tr('/', '-')
18       d[name] = conditions
19       @conditions[name] << {
20         :module => mod_name,
21         :version => mod.version,
22         :dependency => conditions
23       }
24     end
25   end
26 end
get_remote_constraints(forge) click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
28 def get_remote_constraints(forge)
29   @remote   = Hash.new { |h,k| h[k] = { } }
30   @urls     = {}
31   @versions = Hash.new { |h,k| h[k] = [] }
32 
33   Puppet.notice _("Downloading from %{uri} ...") % { uri: forge.uri }
34   author, modname = Puppet::ModuleTool.username_and_modname_from(@module_name)
35   info = forge.remote_dependency_info(author, modname, @options[:version])
36   info.each do |pair|
37     mod_name, releases = pair
38     mod_name = mod_name.tr('/', '-')
39     releases.each do |rel|
40       semver = SemanticPuppet::Version.parse(rel['version']) rescue SemanticPuppet::Version::MIN
41       @versions[mod_name] << { :vstring => rel['version'], :semver => semver }
42       @versions[mod_name].sort! { |a, b| a[:semver] <=> b[:semver] }
43       @urls["#{mod_name}@#{rel['version']}"] = rel['file']
44       d = @remote["#{mod_name}@#{rel['version']}"]
45       (rel['dependencies'] || []).each do |name, conditions|
46         d[name.tr('/', '-')] = conditions
47       end
48     end
49   end
50 end
implicit_version(mod) click to toggle source
   # File lib/puppet/module_tool/shared_behaviors.rb
52 def implicit_version(mod)
53   return :latest if @conditions[mod].empty?
54   if @conditions[mod].all? { |c| c[:queued] || c[:module] == :you }
55     return :latest
56   end
57   return :best
58 end
resolve_constraints(dependencies, source = [{:name => :you}], seen = {}, action = @action) click to toggle source
    # File lib/puppet/module_tool/shared_behaviors.rb
 68 def resolve_constraints(dependencies, source = [{:name => :you}], seen = {}, action = @action)
 69   dependencies = dependencies.map do |mod, range|
 70     source.last[:dependency] = range
 71 
 72     @conditions[mod] << {
 73       :module     => source.last[:name],
 74       :version    => source.last[:version],
 75       :dependency => range,
 76       :queued     => true
 77     }
 78 
 79     if forced?
 80       range = Puppet::Module.parse_range(@version) rescue Puppet::Module.parse_range('>= 0.0.0')
 81     else
 82       range = (@conditions[mod]).map do |r|
 83         Puppet::Module.parse_range(r[:dependency]) rescue Puppet::Module.parse_range('>= 0.0.0')
 84       end.inject(&:&)
 85     end
 86 
 87     if @action == :install && seen.include?(mod)
 88       next if range === seen[mod][:semver]
 89 
 90       req_module   = @module_name
 91       req_versions = @versions["#{@module_name}"].map { |v| v[:semver] }
 92       raise InvalidDependencyCycleError,
 93         :module_name       => mod,
 94         :source            => (source + [{ :name => mod, :version => source.last[:dependency] }]),
 95         :requested_module  => req_module,
 96         :requested_version => @version || annotated_version(req_module, req_versions),
 97         :conditions        => @conditions
 98     end
 99 
100     if !(forced? || @installed[mod].empty? || source.last[:name] == :you)
101       next if range === SemanticPuppet::Version.parse(@installed[mod].first.version)
102       action = :upgrade
103     elsif @installed[mod].empty?
104       action = :install
105     end
106 
107     if action == :upgrade
108       @conditions.each { |_, conds| conds.delete_if { |c| c[:module] == mod } }
109     end
110 
111     versions = @versions["#{mod}"].select { |h| range === h[:semver] }
112     valid_versions = versions.select { |x| x[:semver].special == '' }
113     valid_versions = versions if valid_versions.empty?
114 
115     version = valid_versions.last
116     unless version
117       req_module   = @module_name
118       req_versions = @versions["#{@module_name}"].map { |v| v[:semver] }
119       raise NoVersionsSatisfyError,
120         :requested_name    => req_module,
121         :requested_version => @version || annotated_version(req_module, req_versions),
122         :installed_version => @installed[@module_name].empty? ? nil : @installed[@module_name].first.version,
123         :dependency_name   => mod,
124         :conditions        => @conditions[mod],
125         :action            => @action
126     end
127 
128     seen[mod] = version
129 
130     {
131       :module           => mod,
132       :version          => version,
133       :action           => action,
134       :previous_version => @installed[mod].empty? ? nil : @installed[mod].first.version,
135       :file             => @urls["#{mod}@#{version[:vstring]}"],
136       :path             => action == :install ? @options[:target_dir] : (@installed[mod].empty? ? @options[:target_dir] : @installed[mod].first.modulepath),
137       :dependencies     => []
138     }
139   end.compact
140   dependencies.each do |mod|
141     deps = @remote["#{mod[:module]}@#{mod[:version][:vstring]}"].sort_by(&:first)
142     mod[:dependencies] = resolve_constraints(deps, source + [{ :name => mod[:module], :version => mod[:version][:vstring] }], seen, :install)
143   end unless @ignore_dependencies
144   return dependencies
145 end