class Puppet::Util::Autoload

Autoload paths, either based on names or all at once.

Attributes

object[RW]
objwarn[RW]
path[RW]
wrap[RW]

Public Instance Methods

changed?(name) click to toggle source
# File lib/puppet/util/autoload.rb, line 220
def changed?(name)
  self.class.changed?(expand(name))
end
expand(name) click to toggle source
# File lib/puppet/util/autoload.rb, line 228
def expand(name)
  ::File.join(@path, name.to_s)
end
files_to_load() click to toggle source
# File lib/puppet/util/autoload.rb, line 224
def files_to_load
  self.class.files_to_load(@path)
end
load(name, env = nil) click to toggle source
# File lib/puppet/util/autoload.rb, line 198
def load(name, env = nil)
  self.class.load_file(expand(name), env)
end
loadall(env = nil) click to toggle source

Load all instances from a path of ::search_directories matching the relative path this Autoloader was initialized with. For example, if we have created a Puppet::Util::Autoload for Puppet::Type::User with a path of ‘puppet/provider/user’, the ::search_directories path will be searched for all ruby files matching puppet/provider/user/*.rb and they will then be loaded from the first directory in the search path providing them. So earlier entries in the search path may shadow later entries.

This uses require, rather than load, so that already-loaded files don’t get reloaded unnecessarily.

# File lib/puppet/util/autoload.rb, line 212
def loadall(env = nil)
  self.class.loadall(@path, env)
end
loaded?(name) click to toggle source
# File lib/puppet/util/autoload.rb, line 216
def loaded?(name)
  self.class.loaded?(expand(name))
end

Public Class Methods

changed?(name) click to toggle source
# File lib/puppet/util/autoload.rb, line 42
def changed?(name)
  name = cleanpath(name).chomp('.rb')
  return true unless loaded.include?(name)
  file, old_mtime = loaded[name]
  environment = Puppet.lookup(:current_environment)
  return true unless file == get_file(name, environment)
  begin
    old_mtime.to_i != File.mtime(file).to_i
  rescue Errno::ENOENT
    true
  end
end
cleanpath(path) click to toggle source

Normalize a path. This converts ALT_SEPARATOR to SEPARATOR on Windows and eliminates unnecessary parts of a path.

# File lib/puppet/util/autoload.rb, line 169
def cleanpath(path)
  # There are two cases here because cleanpath does not handle absolute
  # paths correctly on windows (c:\ and c:/ are treated as distinct) but
  # we don't want to convert relative paths to absolute
  if Puppet::Util.absolute_path?(path)
    File.expand_path(path)
  else
    Pathname.new(path).cleanpath.to_s
  end
end
files_in_dir(dir, path) click to toggle source
# File lib/puppet/util/autoload.rb, line 97
def files_in_dir(dir, path)
  dir = Pathname.new(File.expand_path(dir))
  Dir.glob(File.join(dir, path, "*.rb")).collect do |file|
    Pathname.new(file).relative_path_from(dir).to_s
  end
end
files_to_load(path, env = nil) click to toggle source
# File lib/puppet/util/autoload.rb, line 93
def files_to_load(path, env = nil)
  search_directories(env).map {|dir| files_in_dir(dir, path) }.flatten.uniq
end
gem_directories() click to toggle source
# File lib/puppet/util/autoload.rb, line 159
def gem_directories
  gem_source.directories
end
gem_source() click to toggle source
# File lib/puppet/util/autoload.rb, line 18
def gem_source
  @gem_source ||= Puppet::Util::RubyGems::Source.new
end
get_file(name, env) click to toggle source

Get the correct file to load for a given path returns nil if no file is found

# File lib/puppet/util/autoload.rb, line 87
def get_file(name, env)
  name = name + '.rb' unless name =~ /\.rb$/
  path = search_directories(env).find { |dir| Puppet::FileSystem.exist?(File.join(dir, name)) }
  path and File.join(path, name)
end
libdirs() click to toggle source
# File lib/puppet/util/autoload.rb, line 149
def libdirs()
  # See the comments in #module_directories above.  Basically, we need to be careful not to try to access the
  # libdir before we know for sure that all of the settings have been initialized (e.g., during bootstrapping).
  if (Puppet.settings.app_defaults_initialized?)
    Puppet[:libdir].split(File::PATH_SEPARATOR)
  else
    []
  end
end
load_file(name, env) click to toggle source

Load a single plugin by name. We use ‘load’ here so we can reload a given plugin.

# File lib/puppet/util/autoload.rb, line 57
def load_file(name, env)
  file = get_file(name.to_s, env)
  return false unless file
  begin
    mark_loaded(name, file)
    Kernel.load file, @wrap
    return true
  rescue SystemExit,NoMemoryError
    raise
  rescue Exception => detail
    message = "Could not autoload #{name}: #{detail}"
    Puppet.log_exception(detail, message)
    raise Puppet::Error, message, detail.backtrace
  end
end
loadall(path, env = nil) click to toggle source
# File lib/puppet/util/autoload.rb, line 73
def loadall(path, env = nil)
  # Load every instance of everything we can find.
  files_to_load(path, env).each do |file|
    name = file.chomp(".rb")
    load_file(name, env) unless loaded?(name)
  end
end
loaded?(path) click to toggle source

Has a given path been loaded? This is used for testing whether a changed file should be loaded or just ignored. This is only used in network/client/master, when downloading plugins, to see if a given plugin is currently loaded and thus should be reloaded.

# File lib/puppet/util/autoload.rb, line 27
def loaded?(path)
  path = cleanpath(path).chomp('.rb')
  loaded.include?(path)
end
mark_loaded(name, file) click to toggle source

Save the fact that a given path has been loaded. This is so we can load downloaded plugins if they’ve already been loaded into memory.

# File lib/puppet/util/autoload.rb, line 35
def mark_loaded(name, file)
  name = cleanpath(name).chomp('.rb')
  ruby_file = name + ".rb"
  $LOADED_FEATURES << ruby_file unless $LOADED_FEATURES.include?(ruby_file)
  loaded[name] = [file, File.mtime(file)]
end
module_directories(env) click to toggle source
# File lib/puppet/util/autoload.rb, line 104
def module_directories(env)
  # We're using a per-thread cache of module directories so that we don't
  # scan the filesystem each time we try to load something. This is reset
  # at the beginning of compilation and at the end of an agent run.
  $env_module_directories ||= {}


  # This is a little bit of a hack.  Basically, the autoloader is being
  # called indirectly during application bootstrapping when we do things
  # such as check "features".  However, during bootstrapping, we haven't
  # yet parsed all of the command line parameters nor the config files,
  # and thus we don't yet know with certainty what the module path is.
  # This should be irrelevant during bootstrapping, because anything that
  # we are attempting to load during bootstrapping should be something
  # that we ship with puppet, and thus the module path is irrelevant.
  #
  # In the long term, I think the way that we want to handle this is to
  # have the autoloader ignore the module path in all cases where it is
  # not specifically requested (e.g., by a constructor param or
  # something)... because there are very few cases where we should
  # actually be loading code from the module path.  However, until that
  # happens, we at least need a way to prevent the autoloader from
  # attempting to access the module path before it is initialized.  For
  # now we are accomplishing that by calling the
  # "app_defaults_initialized?" method on the main puppet Settings object.
  # --cprice 2012-03-16
  if Puppet.settings.app_defaults_initialized?
    env ||= Puppet.lookup(:environments).get(Puppet[:environment])

    if env
      # if the app defaults have been initialized then it should be safe to access the module path setting.
      $env_module_directories[env] ||= env.modulepath.collect do |dir|
        Dir.entries(dir).reject { |f| f =~ /^\./ }.collect { |f| File.join(dir, f, "lib") }
      end.flatten.find_all do |d|
        FileTest.directory?(d)
      end
    else
      []
    end
  else
    # if we get here, the app defaults have not been initialized, so we basically use an empty module path.
    []
  end
end
new(obj, path, options = {}) click to toggle source
# File lib/puppet/util/autoload.rb, line 186
def initialize(obj, path, options = {})
  @path = path.to_s
  raise ArgumentError, "Autoload paths cannot be fully qualified" if Puppet::Util.absolute_path?(@path)
  @object = obj

  self.class[obj] = self

  set_options(options)

  @wrap = true unless defined?(@wrap)
end
reload_changed() click to toggle source
# File lib/puppet/util/autoload.rb, line 81
def reload_changed
  loaded.keys.each { |file| load_file(file, nil) if changed?(file) }
end
search_directories(env) click to toggle source
# File lib/puppet/util/autoload.rb, line 163
def search_directories(env)
  [gem_directories, module_directories(env), libdirs(), $LOAD_PATH].flatten
end