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 35 def self.find(modname, environment = nil) 36 return nil unless modname 37 # Unless a specific environment is given, use the current environment 38 env = environment ? Puppet.lookup(:environments).get!(environment) : Puppet.lookup(:current_environment) 39 env.module(modname) 40 end
# File lib/puppet/module.rb 42 def self.is_module_directory?(name, path) 43 # it must be a directory 44 fullpath = File.join(path, name) 45 return false unless Puppet::FileSystem.directory?(fullpath) 46 return is_module_directory_name?(name) 47 end
# File lib/puppet/module.rb 49 def self.is_module_directory_name?(name) 50 # it must match an installed module name according to forge validator 51 return true if name =~ /^[a-z][a-z0-9_]*$/ 52 return false 53 end
# File lib/puppet/module.rb 55 def self.is_module_namespaced_name?(name) 56 # it must match the full module name according to forge validator 57 return true if name =~ /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/ 58 return false 59 end
# File lib/puppet/module.rb 72 def initialize(name, path, environment) 73 @name = name 74 @path = path 75 @environment = environment 76 77 assert_validity 78 load_metadata 79 80 @absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(manifests) 81 end
@api private
# File lib/puppet/module.rb 62 def self.parse_range(range) 63 SemanticPuppet::VersionRange.parse(range) 64 end
Public Instance Methods
# File lib/puppet/module.rb 443 def ==(other) 444 self.name == other.name && 445 self.version == other.version && 446 self.path == other.path && 447 self.environment == other.environment 448 end
# File lib/puppet/module.rb 282 def all_manifests 283 return [] unless Puppet::FileSystem.exist?(manifests) 284 285 Dir.glob(File.join(manifests, '**', '*.pp')) 286 end
# File lib/puppet/module.rb 349 def dependencies_as_modules 350 dependent_modules = [] 351 dependencies and dependencies.each do |dep| 352 _, dep_name = dep["name"].split('/') 353 found_module = environment.module(dep_name) 354 dependent_modules << found_module if found_module 355 end 356 357 dependent_modules 358 end
# File lib/puppet/module.rb 334 def has_external_facts? 335 File.directory?(plugin_fact_directory) 336 end
# File lib/puppet/module.rb 302 def has_hiera_conf? 303 hiera_conf_file.nil? ? false : Puppet::FileSystem.exist?(hiera_conf_file) 304 end
# File lib/puppet/module.rb 97 def has_metadata? 98 begin 99 load_metadata 100 @metadata.is_a?(Hash) && !@metadata.empty? 101 rescue Puppet::Module::MissingMetadata 102 false 103 end 104 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 330 def has_translations?(locale) 331 return Puppet::FileSystem.exist?(File.join(locale_directory, locale)) 332 end
# File lib/puppet/module.rb 295 def hiera_conf_file 296 unless defined?(@hiera_conf_file) 297 @hiera_conf_file = path.nil? ? nil : File.join(path, Puppet::Pops::Lookup::HieraConfig::CONFIG_FILE_NAME) 298 end 299 @hiera_conf_file 300 end
# File lib/puppet/module.rb 209 def license_file 210 return @license_file if defined?(@license_file) 211 212 return @license_file = nil unless path 213 @license_file = File.join(path, "License") 214 end
# File lib/puppet/module.rb 237 def load_metadata 238 return if instance_variable_defined?(:@metadata) 239 240 @metadata = data = read_metadata 241 return if data.empty? 242 243 @forge_name = data['name'].tr('-', '/') if data['name'] 244 245 [:source, :author, :version, :license, :dependencies].each do |attr| 246 value = data[attr.to_s] 247 raise MissingMetadata, "No #{attr} module metadata provided for #{self.name}" if value.nil? 248 249 if attr == :dependencies 250 unless value.is_a?(Array) 251 raise MissingMetadata, "The value for the key dependencies in the file metadata.json of the module #{self.name} must be an array, not: '#{value}'" 252 end 253 value.each do |dep| 254 name = dep['name'] 255 dep['name'] = name.tr('-', '/') unless name.nil? 256 dep['version_requirement'] ||= '>= 0.0.0' 257 end 258 end 259 260 send(attr.to_s + "=", value) 261 end 262 end
@return [String]
# File lib/puppet/module.rb 320 def locale_directory 321 subpath("locales") 322 end
Return the list of manifests matching the given glob pattern, defaulting to 'init.pp' for empty modules.
# File lib/puppet/module.rb 266 def match_manifests(rest) 267 if rest 268 wanted_manifests = wanted_manifests_from(rest) 269 searched_manifests = wanted_manifests.glob.reject { |f| FileTest.directory?(f) } 270 else 271 searched_manifests = [] 272 end 273 274 # (#4220) Always ensure init.pp in case class is defined there. 275 init_manifest = manifest("init.pp") 276 if !init_manifest.nil? && !searched_manifests.include?(init_manifest) 277 searched_manifests.unshift(init_manifest) 278 end 279 searched_manifests 280 end
# File lib/puppet/module.rb 288 def metadata_file 289 return @metadata_file if defined?(@metadata_file) 290 291 return @metadata_file = nil unless path 292 @metadata_file = File.join(path, "metadata.json") 293 end
# File lib/puppet/module.rb 306 def modulepath 307 File.dirname(path) if path 308 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 193 def plan_file(name) 194 # If 'file' is nil then they're asking for the base path. 195 # This is used for things like fileserving. 196 if name 197 full_path = File.join(plans_directory, name) 198 else 199 full_path = plans_directory 200 end 201 202 if Puppet::FileSystem.exist?(full_path) 203 return full_path 204 else 205 return nil 206 end 207 end
# File lib/puppet/module.rb 180 def plans 181 return @plans if instance_variable_defined?(:@plans) 182 183 if Puppet::FileSystem.exist?(plans_directory) 184 @plans = Puppet::Module::Plan.plans_in_module(self) 185 else 186 @plans = [] 187 end 188 end
# File lib/puppet/module.rb 176 def plans_directory 177 subpath("plans") 178 end
Find all plugin directories. This is used by the Plugins fileserving mount.
# File lib/puppet/module.rb 311 def plugin_directory 312 subpath("lib") 313 end
# File lib/puppet/module.rb 315 def plugin_fact_directory 316 subpath("facts.d") 317 end
@deprecated The puppetversion module metadata field is no longer used.
# File lib/puppet/module.rb 84 def puppetversion 85 nil 86 end
@deprecated The puppetversion module metadata field is no longer used.
# File lib/puppet/module.rb 89 def puppetversion=(something) 90 end
# File lib/puppet/module.rb 216 def read_metadata 217 md_file = metadata_file 218 return {} if md_file.nil? 219 content = File.read(md_file, :encoding => 'utf-8') 220 content.empty? ? {} : Puppet::Util::Json.load(content) 221 rescue Errno::ENOENT 222 {} 223 rescue Puppet::Util::Json::ParseError => e 224 #TRANSLATORS 'metadata.json' is a specific file name and should not be translated. 225 msg = _("%{name} has an invalid and unparsable metadata.json file. The parse error: %{error}") % { name: name, error: e.message } 226 case Puppet[:strict] 227 when :off 228 Puppet.debug(msg) 229 when :warning 230 Puppet.warning(msg) 231 when :error 232 raise FaultyMetadata, msg 233 end 234 {} 235 end
# File lib/puppet/module.rb 360 def required_by 361 environment.module_requirements[self.forge_name] || {} 362 end
# File lib/puppet/module.rb 338 def supports(name, version = nil) 339 @supports ||= [] 340 @supports << [name, version] 341 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 160 def task_file(name) 161 # If 'file' is nil then they're asking for the base path. 162 # This is used for things like fileserving. 163 if name 164 full_path = File.join(tasks_directory, name) 165 else 166 full_path = tasks_directory 167 end 168 169 if Puppet::FileSystem.exist?(full_path) 170 return full_path 171 else 172 return nil 173 end 174 end
# File lib/puppet/module.rb 147 def tasks 148 return @tasks if instance_variable_defined?(:@tasks) 149 150 if Puppet::FileSystem.exist?(tasks_directory) 151 @tasks = Puppet::Module::Task.tasks_in_module(self) 152 else 153 @tasks = [] 154 end 155 end
# File lib/puppet/module.rb 143 def tasks_directory 144 subpath("tasks") 145 end
# File lib/puppet/module.rb 343 def to_s 344 result = "Module #{name}" 345 result += "(#{path})" if path 346 result 347 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 390 def unmet_dependencies 391 unmet_dependencies = [] 392 return unmet_dependencies unless dependencies 393 394 dependencies.each do |dependency| 395 name = dependency['name'] 396 version_string = dependency['version_requirement'] || '>= 0.0.0' 397 398 dep_mod = begin 399 environment.module_by_forge_name(name) 400 rescue 401 nil 402 end 403 404 error_details = { 405 :name => name, 406 :version_constraint => version_string.gsub(/^(?=\d)/, "v"), 407 :parent => { 408 :name => self.forge_name, 409 :version => self.version.gsub(/^(?=\d)/, "v") 410 }, 411 :mod_details => { 412 :installed_version => dep_mod.nil? ? nil : dep_mod.version 413 } 414 } 415 416 unless dep_mod 417 error_details[:reason] = :missing 418 unmet_dependencies << error_details 419 next 420 end 421 422 if version_string 423 begin 424 required_version_semver_range = self.class.parse_range(version_string) 425 actual_version_semver = SemanticPuppet::Version.parse(dep_mod.version) 426 rescue ArgumentError 427 error_details[:reason] = :non_semantic_version 428 unmet_dependencies << error_details 429 next 430 end 431 432 unless required_version_semver_range.include? actual_version_semver 433 error_details[:reason] = :version_mismatch 434 unmet_dependencies << error_details 435 next 436 end 437 end 438 end 439 440 unmet_dependencies 441 end
@deprecated The puppetversion module metadata field is no longer used.
# File lib/puppet/module.rb 93 def validate_puppet_version 94 return 95 end
Private Instance Methods
# File lib/puppet/module.rb 469 def assert_validity 470 if !Puppet::Module.is_module_directory_name?(@name) && !Puppet::Module.is_module_namespaced_name?(@name) 471 raise InvalidName, _(<<-ERROR_STRING).chomp % { name: @name } 472 Invalid module name '%{name}'; module names must match either: 473 An installed module name (ex. modulename) matching the expression /^[a-z][a-z0-9_]*$/ -or- 474 A namespaced module name (ex. author-modulename) matching the expression /^[a-zA-Z0-9]+[-][a-z][a-z0-9_]*$/ 475 ERROR_STRING 476 end 477 end
# File lib/puppet/module.rb 465 def subpath(type) 466 File.join(path, type) 467 end
# File lib/puppet/module.rb 452 def wanted_manifests_from(pattern) 453 begin 454 extended = File.extname(pattern).empty? ? "#{pattern}.pp" : pattern 455 relative_pattern = Puppet::FileSystem::PathPattern.relative(extended) 456 rescue Puppet::FileSystem::PathPattern::InvalidPattern => error 457 raise Puppet::Module::InvalidFilePattern.new( 458 "The pattern \"#{pattern}\" to find manifests in the module \"#{name}\" " + 459 "is invalid and potentially unsafe.", error) 460 end 461 462 relative_pattern.prefix_with(@absolute_path_to_manifests) 463 end