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

@api private

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

Public Instance Methods

==(other) click to toggle source
    # 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
all_manifests() click to toggle source
    # 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
dependencies_as_modules() click to toggle source
    # 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
has_external_facts?() click to toggle source
    # File lib/puppet/module.rb
334 def has_external_facts?
335   File.directory?(plugin_fact_directory)
336 end
has_hiera_conf?() click to toggle source
    # File lib/puppet/module.rb
302 def has_hiera_conf?
303   hiera_conf_file.nil? ? false : Puppet::FileSystem.exist?(hiera_conf_file)
304 end
has_metadata?() click to toggle source
    # 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
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
330 def has_translations?(locale)
331   return Puppet::FileSystem.exist?(File.join(locale_directory, locale))
332 end
hiera_conf_file() click to toggle source
    # 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
license_file() click to toggle source
    # 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
load_metadata() click to toggle source
    # 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
locale_directory() click to toggle source

@return [String]

    # File lib/puppet/module.rb
320 def locale_directory
321   subpath("locales")
322 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
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
metadata_file() click to toggle source
    # 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
modulepath() click to toggle source
    # File lib/puppet/module.rb
306 def modulepath
307   File.dirname(path) if path
308 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
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
plans() click to toggle source
    # 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
plans_directory() click to toggle source
    # File lib/puppet/module.rb
176 def plans_directory
177   subpath("plans")
178 end
plugin_directory() click to toggle source

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

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

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

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

   # File lib/puppet/module.rb
89 def puppetversion=(something)
90 end
read_metadata() click to toggle source
    # 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
required_by() click to toggle source
    # File lib/puppet/module.rb
360 def required_by
361   environment.module_requirements[self.forge_name] || {}
362 end
supports(name, version = nil) click to toggle source
    # File lib/puppet/module.rb
338 def supports(name, version = nil)
339   @supports ||= []
340   @supports << [name, version]
341 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
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
tasks() click to toggle source
    # 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
tasks_directory() click to toggle source
    # File lib/puppet/module.rb
143 def tasks_directory
144   subpath("tasks")
145 end
to_s() click to toggle source
    # File lib/puppet/module.rb
343 def to_s
344   result = "Module #{name}"
345   result += "(#{path})" if path
346   result
347 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
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
validate_puppet_version() click to toggle source

@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

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