class Puppet::Module
Support for modules
Constants
- FILETYPES
Attributes
Public Class Methods
Find and return the module
that path
belongs to. If path
is absolute, or if there is no module whose name is the first component of path
, return nil
# File lib/puppet/module.rb 34 def self.find(modname, environment = nil) 35 return nil unless modname 36 # Unless a specific environment is given, use the current environment 37 env = environment ? Puppet.lookup(:environments).get!(environment) : Puppet.lookup(:current_environment) 38 env.module(modname) 39 end
# File lib/puppet/module.rb 41 def self.is_module_directory?(name, path) 42 # it must be a directory 43 fullpath = File.join(path, name) 44 return false unless Puppet::FileSystem.directory?(fullpath) 45 return is_module_directory_name?(name) 46 end
# File lib/puppet/module.rb 48 def self.is_module_directory_name?(name) 49 # it must match an installed module name according to forge validator 50 return true if name =~ /^[a-z][a-z0-9_]*$/ 51 return false 52 end
# File lib/puppet/module.rb 54 def self.is_module_namespaced_name?(name) 55 # it must match the full module name according to forge validator 56 return true if name =~ /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/ 57 return false 58 end
# File lib/puppet/module.rb 71 def initialize(name, path, environment) 72 @name = name 73 @path = path 74 @environment = environment 75 76 assert_validity 77 load_metadata 78 79 @absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(manifests) 80 end
@api private
# File lib/puppet/module.rb 61 def self.parse_range(range) 62 SemanticPuppet::VersionRange.parse(range) 63 end
Public Instance Methods
# File lib/puppet/module.rb 440 def ==(other) 441 self.name == other.name && 442 self.version == other.version && 443 self.path == other.path && 444 self.environment == other.environment 445 end
# File lib/puppet/module.rb 279 def all_manifests 280 return [] unless Puppet::FileSystem.exist?(manifests) 281 282 Dir.glob(File.join(manifests, '**', '*.pp')) 283 end
# File lib/puppet/module.rb 346 def dependencies_as_modules 347 dependent_modules = [] 348 dependencies and dependencies.each do |dep| 349 _, dep_name = dep["name"].split('/') 350 found_module = environment.module(dep_name) 351 dependent_modules << found_module if found_module 352 end 353 354 dependent_modules 355 end
# File lib/puppet/module.rb 331 def has_external_facts? 332 File.directory?(plugin_fact_directory) 333 end
# File lib/puppet/module.rb 299 def has_hiera_conf? 300 hiera_conf_file.nil? ? false : Puppet::FileSystem.exist?(hiera_conf_file) 301 end
# File lib/puppet/module.rb 96 def has_metadata? 97 begin 98 load_metadata 99 @metadata.is_a?(Hash) && !@metadata.empty? 100 rescue Puppet::Module::MissingMetadata 101 false 102 end 103 end
Returns true if the module has translation files for the given locale. @param [String] locale the two-letter language code to check
for translations
@return true if the module has a directory for the locale, false
false otherwise
# File lib/puppet/module.rb 327 def has_translations?(locale) 328 return Puppet::FileSystem.exist?(File.join(locale_directory, locale)) 329 end
# File lib/puppet/module.rb 292 def hiera_conf_file 293 unless defined?(@hiera_conf_file) 294 @hiera_conf_file = path.nil? ? nil : File.join(path, Puppet::Pops::Lookup::HieraConfig::CONFIG_FILE_NAME) 295 end 296 @hiera_conf_file 297 end
# File lib/puppet/module.rb 208 def license_file 209 return @license_file if defined?(@license_file) 210 211 return @license_file = nil unless path 212 @license_file = File.join(path, "License") 213 end
# File lib/puppet/module.rb 234 def load_metadata 235 return if instance_variable_defined?(:@metadata) 236 237 @metadata = data = read_metadata 238 return if data.empty? 239 240 @forge_name = data['name'].tr('-', '/') if data['name'] 241 242 [:source, :author, :version, :license, :dependencies].each do |attr| 243 value = data[attr.to_s] 244 raise MissingMetadata, "No #{attr} module metadata provided for #{self.name}" if value.nil? 245 246 if attr == :dependencies 247 unless value.is_a?(Array) 248 raise MissingMetadata, "The value for the key dependencies in the file metadata.json of the module #{self.name} must be an array, not: '#{value}'" 249 end 250 value.each do |dep| 251 name = dep['name'] 252 dep['name'] = name.tr('-', '/') unless name.nil? 253 dep['version_requirement'] ||= '>= 0.0.0' 254 end 255 end 256 257 send(attr.to_s + "=", value) 258 end 259 end
@return [String]
# File lib/puppet/module.rb 317 def locale_directory 318 subpath("locales") 319 end
Return the list of manifests matching the given glob pattern, defaulting to 'init.pp' for empty modules.
# File lib/puppet/module.rb 263 def match_manifests(rest) 264 if rest 265 wanted_manifests = wanted_manifests_from(rest) 266 searched_manifests = wanted_manifests.glob.reject { |f| FileTest.directory?(f) } 267 else 268 searched_manifests = [] 269 end 270 271 # (#4220) Always ensure init.pp in case class is defined there. 272 init_manifest = manifest("init.pp") 273 if !init_manifest.nil? && !searched_manifests.include?(init_manifest) 274 searched_manifests.unshift(init_manifest) 275 end 276 searched_manifests 277 end
# File lib/puppet/module.rb 285 def metadata_file 286 return @metadata_file if defined?(@metadata_file) 287 288 return @metadata_file = nil unless path 289 @metadata_file = File.join(path, "metadata.json") 290 end
# File lib/puppet/module.rb 303 def modulepath 304 File.dirname(path) if path 305 end
This is a re-implementation of the Filetypes singular type method (e.g. `manifest('my/manifest.pp')`. We don't implement the full filetype “API” for plans.
# File lib/puppet/module.rb 192 def plan_file(name) 193 # If 'file' is nil then they're asking for the base path. 194 # This is used for things like fileserving. 195 if name 196 full_path = File.join(plans_directory, name) 197 else 198 full_path = plans_directory 199 end 200 201 if Puppet::FileSystem.exist?(full_path) 202 return full_path 203 else 204 return nil 205 end 206 end
# File lib/puppet/module.rb 175 def plans_directory 176 subpath("plans") 177 end
Find all plugin directories. This is used by the Plugins fileserving mount.
# File lib/puppet/module.rb 308 def plugin_directory 309 subpath("lib") 310 end
# File lib/puppet/module.rb 312 def plugin_fact_directory 313 subpath("facts.d") 314 end
@deprecated The puppetversion module metadata field is no longer used.
# File lib/puppet/module.rb 83 def puppetversion 84 nil 85 end
@deprecated The puppetversion module metadata field is no longer used.
# File lib/puppet/module.rb 88 def puppetversion=(something) 89 end
# File lib/puppet/module.rb 215 def read_metadata 216 md_file = metadata_file 217 md_file.nil? ? {} : Puppet::Util::Json.load(File.read(md_file, :encoding => 'utf-8')) 218 rescue Errno::ENOENT 219 {} 220 rescue Puppet::Util::Json::ParseError => e 221 #TRANSLATORS 'metadata.json' is a specific file name and should not be translated. 222 msg = _("%{name} has an invalid and unparsable metadata.json file. The parse error: %{error}") % { name: name, error: e.message } 223 case Puppet[:strict] 224 when :off 225 Puppet.debug(msg) 226 when :warning 227 Puppet.warning(msg) 228 when :error 229 raise FaultyMetadata, msg 230 end 231 {} 232 end
# File lib/puppet/module.rb 357 def required_by 358 environment.module_requirements[self.forge_name] || {} 359 end
# File lib/puppet/module.rb 335 def supports(name, version = nil) 336 @supports ||= [] 337 @supports << [name, version] 338 end
This is a re-implementation of the Filetypes singular type method (e.g. `manifest('my/manifest.pp')`. We don't implement the full filetype “API” for tasks since tasks don't map 1:1 onto files.
# File lib/puppet/module.rb 159 def task_file(name) 160 # If 'file' is nil then they're asking for the base path. 161 # This is used for things like fileserving. 162 if name 163 full_path = File.join(tasks_directory, name) 164 else 165 full_path = tasks_directory 166 end 167 168 if Puppet::FileSystem.exist?(full_path) 169 return full_path 170 else 171 return nil 172 end 173 end
# File lib/puppet/module.rb 142 def tasks_directory 143 subpath("tasks") 144 end
# File lib/puppet/module.rb 340 def to_s 341 result = "Module #{name}" 342 result += "(#{path})" if path 343 result 344 end
Identify and mark unmet dependencies. A dependency will be marked unmet for the following reasons:
* not installed and is thus considered missing * installed and does not meet the version requirements for this module * installed and doesn't use semantic versioning
Returns a list of hashes representing the details of an unmet dependency.
Example:
[ { :reason => :missing, :name => 'puppetlabs-mysql', :version_constraint => 'v0.0.1', :mod_details => { :installed_version => '0.0.1' } :parent => { :name => 'puppetlabs-bacula', :version => 'v1.0.0' } } ]
# File lib/puppet/module.rb 387 def unmet_dependencies 388 unmet_dependencies = [] 389 return unmet_dependencies unless dependencies 390 391 dependencies.each do |dependency| 392 name = dependency['name'] 393 version_string = dependency['version_requirement'] || '>= 0.0.0' 394 395 dep_mod = begin 396 environment.module_by_forge_name(name) 397 rescue 398 nil 399 end 400 401 error_details = { 402 :name => name, 403 :version_constraint => version_string.gsub(/^(?=\d)/, "v"), 404 :parent => { 405 :name => self.forge_name, 406 :version => self.version.gsub(/^(?=\d)/, "v") 407 }, 408 :mod_details => { 409 :installed_version => dep_mod.nil? ? nil : dep_mod.version 410 } 411 } 412 413 unless dep_mod 414 error_details[:reason] = :missing 415 unmet_dependencies << error_details 416 next 417 end 418 419 if version_string 420 begin 421 required_version_semver_range = self.class.parse_range(version_string) 422 actual_version_semver = SemanticPuppet::Version.parse(dep_mod.version) 423 rescue ArgumentError 424 error_details[:reason] = :non_semantic_version 425 unmet_dependencies << error_details 426 next 427 end 428 429 unless required_version_semver_range.include? actual_version_semver 430 error_details[:reason] = :version_mismatch 431 unmet_dependencies << error_details 432 next 433 end 434 end 435 end 436 437 unmet_dependencies 438 end
@deprecated The puppetversion module metadata field is no longer used.
# File lib/puppet/module.rb 92 def validate_puppet_version 93 return 94 end
Private Instance Methods
# File lib/puppet/module.rb 466 def assert_validity 467 if !Puppet::Module.is_module_directory_name?(@name) && !Puppet::Module.is_module_namespaced_name?(@name) 468 raise InvalidName, _(<<-ERROR_STRING).chomp % { name: @name } 469 Invalid module name '%{name}'; module names must match either: 470 An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or- 471 A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/ 472 ERROR_STRING 473 end 474 end
# File lib/puppet/module.rb 462 def subpath(type) 463 File.join(path, type) 464 end
# File lib/puppet/module.rb 449 def wanted_manifests_from(pattern) 450 begin 451 extended = File.extname(pattern).empty? ? "#{pattern}.pp" : pattern 452 relative_pattern = Puppet::FileSystem::PathPattern.relative(extended) 453 rescue Puppet::FileSystem::PathPattern::InvalidPattern => error 454 raise Puppet::Module::InvalidFilePattern.new( 455 "The pattern \"#{pattern}\" to find manifests in the module \"#{name}\" " + 456 "is invalid and potentially unsafe.", error) 457 end 458 459 relative_pattern.prefix_with(@absolute_path_to_manifests) 460 end