class Puppet::Util::Autoload
Autoload
paths, either based on names or all at once.
Attributes
Public Class Methods
@api private
# File lib/puppet/util/autoload.rb 59 def changed?(name, env) 60 name = cleanpath(name).chomp('.rb') 61 return true unless loaded.include?(name) 62 file, old_mtime = loaded[name] 63 return true unless file == get_file(name, env) 64 begin 65 old_mtime.to_i != File.mtime(file).to_i 66 rescue Errno::ENOENT 67 true 68 end 69 end
Normalize a path. This converts ALT_SEPARATOR to SEPARATOR on Windows and eliminates unnecessary parts of a path.
# File lib/puppet/util/autoload.rb 168 def cleanpath(path) 169 Pathname.new(path).cleanpath.to_s 170 end
@api private
# File lib/puppet/util/autoload.rb 119 def files_in_dir(dir, path) 120 dir = Pathname.new(File.expand_path(dir)) 121 Dir.glob(File.join(dir, path, "*.rb")).collect do |file| 122 Pathname.new(file).relative_path_from(dir).to_s 123 end 124 end
# File lib/puppet/util/autoload.rb 114 def files_to_load(path, env) 115 search_directories(env).map {|dir| files_in_dir(dir, path) }.flatten.uniq 116 end
@api private
# File lib/puppet/util/autoload.rb 134 def gem_directories 135 gem_source.directories 136 end
# File lib/puppet/util/autoload.rb 33 def gem_source 34 @gem_source ||= Puppet::Util::RubyGems::Source.new 35 end
Get the correct file to load for a given path returns nil if no file is found @api private
# File lib/puppet/util/autoload.rb 108 def get_file(name, env) 109 name = name + '.rb' unless name =~ /\.rb$/ 110 path = search_directories(env).find { |dir| Puppet::FileSystem.exist?(File.join(dir, name)) } 111 path and File.join(path, name) 112 end
Load a single plugin by name. We use 'load' here so we can reload a given plugin.
# File lib/puppet/util/autoload.rb 73 def load_file(name, env) 74 file = get_file(name.to_s, env) 75 return false unless file 76 begin 77 mark_loaded(name, file) 78 Kernel.load file 79 return true 80 rescue SystemExit,NoMemoryError 81 raise 82 rescue Exception => detail 83 message = _("Could not autoload %{name}: %{detail}") % { name: name, detail: detail } 84 Puppet.log_exception(detail, message) 85 raise Puppet::Error, message, detail.backtrace 86 end 87 end
# File lib/puppet/util/autoload.rb 89 def loadall(path, env) 90 # Load every instance of everything we can find. 91 files_to_load(path, env).each do |file| 92 name = file.chomp(".rb") 93 load_file(name, env) unless loaded?(name) 94 end 95 end
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 42 def loaded?(path) 43 path = cleanpath(path).chomp('.rb') 44 loaded.include?(path) 45 end
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. @api private
# File lib/puppet/util/autoload.rb 51 def mark_loaded(name, file) 52 name = cleanpath(name).chomp('.rb') 53 file = File.expand_path(file) 54 $LOADED_FEATURES << file unless $LOADED_FEATURES.include?(file) 55 loaded[name] = [file, File.mtime(file)] 56 end
@api private
# File lib/puppet/util/autoload.rb 127 def module_directories(env) 128 raise ArgumentError, "Autoloader requires an environment" unless env 129 130 Puppet::Util::ModuleDirectoriesAdapter.adapt(env).directories 131 end
# File lib/puppet/util/autoload.rb 175 def initialize(obj, path) 176 @path = path.to_s 177 raise ArgumentError, _("Autoload paths cannot be fully qualified") if Puppet::Util.absolute_path?(@path) 178 @object = obj 179 end
# File lib/puppet/util/autoload.rb 97 def reload_changed(env) 98 loaded.keys.each do |file| 99 if changed?(file, env) 100 load_file(file, env) 101 end 102 end 103 end
@api private
# File lib/puppet/util/autoload.rb 139 def search_directories(env) 140 # This is a little bit of a hack. Basically, the autoloader is being 141 # called indirectly during application bootstrapping when we do things 142 # such as check "features". However, during bootstrapping, we haven't 143 # yet parsed all of the command line parameters nor the config files, 144 # and thus we don't yet know with certainty what the module path is. 145 # This should be irrelevant during bootstrapping, because anything that 146 # we are attempting to load during bootstrapping should be something 147 # that we ship with puppet, and thus the module path is irrelevant. 148 # 149 # In the long term, I think the way that we want to handle this is to 150 # have the autoloader ignore the module path in all cases where it is 151 # not specifically requested (e.g., by a constructor param or 152 # something)... because there are very few cases where we should 153 # actually be loading code from the module path. However, until that 154 # happens, we at least need a way to prevent the autoloader from 155 # attempting to access the module path before it is initialized. For 156 # now we are accomplishing that by calling the 157 # "app_defaults_initialized?" method on the main puppet Settings object. 158 # --cprice 2012-03-16 159 if Puppet.settings.app_defaults_initialized? 160 gem_directories + module_directories(env) + $LOAD_PATH 161 else 162 gem_directories + $LOAD_PATH 163 end 164 end
Public Instance Methods
@api private
# File lib/puppet/util/autoload.rb 204 def changed?(name, env) 205 self.class.changed?(expand(name), env) 206 end
# File lib/puppet/util/autoload.rb 212 def expand(name) 213 ::File.join(@path, name.to_s) 214 end
# File lib/puppet/util/autoload.rb 208 def files_to_load(env) 209 self.class.files_to_load(@path, env) 210 end
# File lib/puppet/util/autoload.rb 181 def load(name, env) 182 self.class.load_file(expand(name), env) 183 end
Load all instances from a path of Autoload.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 195 def loadall(env) 196 self.class.loadall(@path, env) 197 end
# File lib/puppet/util/autoload.rb 199 def loaded?(name) 200 self.class.loaded?(expand(name)) 201 end