class Puppet::Module

Support for modules

Constants

FILETYPES

Attributes

author[RW]
dependencies[RW]
description[RW]
environment[RW]
forge_name[RW]
license[RW]
metadata[R]
name[R]
path[R]
plans[R]
project_page[RW]
source[RW]
summary[RW]
tasks[R]
version[RW]

Public Class Methods

find(modname, environment = nil) click to toggle source

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
is_module_directory?(name, path) click to toggle source
   # 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
is_module_directory_name?(name) click to toggle source
   # 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
is_module_namespaced_name?(name) click to toggle source
   # 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
new(name, path, environment) click to toggle source
   # 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
parse_range(range) click to toggle source

@api private

   # File lib/puppet/module.rb
61 def self.parse_range(range)
62   SemanticPuppet::VersionRange.parse(range)
63 end

Public Instance Methods

==(other) click to toggle source
    # 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
all_manifests() click to toggle source
    # 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
dependencies_as_modules() click to toggle source
    # 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
has_external_facts?() click to toggle source
    # File lib/puppet/module.rb
331 def has_external_facts?
332   File.directory?(plugin_fact_directory)
333 end
has_hiera_conf?() click to toggle source
    # File lib/puppet/module.rb
299 def has_hiera_conf?
300   hiera_conf_file.nil? ? false : Puppet::FileSystem.exist?(hiera_conf_file)
301 end
has_metadata?() click to toggle source
    # 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
has_translations?(locale) click to toggle source

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
hiera_conf_file() click to toggle source
    # 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
license_file() click to toggle source
    # 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
load_metadata() click to toggle source
    # 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
locale_directory() click to toggle source

@return [String]

    # File lib/puppet/module.rb
317 def locale_directory
318   subpath("locales")
319 end
match_manifests(rest) click to toggle source

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
metadata_file() click to toggle source
    # 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
modulepath() click to toggle source
    # File lib/puppet/module.rb
303 def modulepath
304   File.dirname(path) if path
305 end
plan_file(name) click to toggle source

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
plans_directory() click to toggle source
    # File lib/puppet/module.rb
175 def plans_directory
176   subpath("plans")
177 end
plugin_directory() click to toggle source

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
plugin_fact_directory() click to toggle source
    # File lib/puppet/module.rb
312 def plugin_fact_directory
313   subpath("facts.d")
314 end
puppetversion() click to toggle source

@deprecated The puppetversion module metadata field is no longer used.

   # File lib/puppet/module.rb
83 def puppetversion
84   nil
85 end
puppetversion=(something) click to toggle source

@deprecated The puppetversion module metadata field is no longer used.

   # File lib/puppet/module.rb
88 def puppetversion=(something)
89 end
read_metadata() click to toggle source
    # 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
required_by() click to toggle source
    # File lib/puppet/module.rb
357 def required_by
358   environment.module_requirements[self.forge_name] || {}
359 end
supports(name, version = nil) click to toggle source
    # File lib/puppet/module.rb
335 def supports(name, version = nil)
336   @supports ||= []
337   @supports << [name, version]
338 end
task_file(name) click to toggle source

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
tasks_directory() click to toggle source
    # File lib/puppet/module.rb
142 def tasks_directory
143   subpath("tasks")
144 end
to_s() click to toggle source
    # File lib/puppet/module.rb
340 def to_s
341   result = "Module #{name}"
342   result += "(#{path})" if path
343   result
344 end
unmet_dependencies() click to toggle source

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
validate_puppet_version() click to toggle source

@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

assert_validity() click to toggle source
    # 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
subpath(type) click to toggle source
    # File lib/puppet/module.rb
462 def subpath(type)
463   File.join(path, type)
464 end
wanted_manifests_from(pattern) click to toggle source
    # 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