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