Puppet::Node::Environment acts as a container for all configuration that is expected to vary between environments.
## The root environment
In addition to normal environments that are defined by the user,there is a special ‘root’ environment. It is defined as an instance variable on the Puppet::Node::Environment metaclass. The environment name is `root` and can be accessed by looking up the `:root_environment` using {Puppet.lookup}.
The primary purpose of the root environment is to contain parser functions that are not bound to a specific environment. The main case for this is for logging functions. Logging functions are attached to the ‘root’ environment when {Puppet::Parser::Functions.reset} is called.
A special “null” environment
This environment should be used when there is no specific environment in effect.
@!attribute [r] #config_version
@api public @return [String] path to a script whose output will be added to report logs (optional)
@!attribute [r] manifest
@api public @return [String] path to the manifest file or directory.
@!attribute [r] name
@api public @return [Symbol] the human readable environment name that serves as the environment identifier
# File lib/puppet/node/environment.rb, line 503 def ==(other) return true if other.kind_of?(Puppet::Node::Environment) && self.name == other.name && self.full_modulepath == other.full_modulepath && self.manifest == other.manifest end
Checks if a reparse is required (cache of files is stale). This call does nothing unless files are being watched.
# File lib/puppet/node/environment.rb, line 464 def check_for_reparse if (Puppet[:code] != @parsed_code) || (watching? && @known_resource_types && @known_resource_types.require_reparse?) @parsed_code = nil @known_resource_types = nil end end
Checks to make sure that this environment did not have a manifest set in
its original environment.conf if Puppet is
configured with disable_per_environment_manifest set true. If
it did, the environment’s modules may not function as intended by the
original authors, and we may seek to halt a puppet compilation for a node
in this environment.
The only exception to this would be if the environment.conf manifest is an
exact, uninterpolated match for the current default_manifest
setting.
@return [Boolean] true if using directory environments, and
Puppet[:disable_per_environment_manifest] is true, and this environment's original environment.conf had a manifest setting that is not the Puppet[:default_manifest].
@api public
# File lib/puppet/node/environment.rb, line 254 def conflicting_manifest_settings? return false if Puppet[:environmentpath].empty? || !Puppet[:disable_per_environment_manifest] environment_conf = Puppet.lookup(:environments).get_conf(name) original_manifest = environment_conf.raw_setting(:manifest) !original_manifest.nil? && !original_manifest.empty? && original_manifest != Puppet[:default_manifest] end
Yields each modules’ plugin directory if the plugin directory (modulename/lib) is present on the filesystem.
@yield [String] Yields the plugin directory from each module to the block. @api public
# File lib/puppet/node/environment.rb, line 295 def each_plugin_directory(&block) modules.map(&:plugin_directory).each do |lib| lib = Puppet::Util::Autoload.cleanpath(lib) yield lib if File.directory?(lib) end end
@api public @return [Array<String>] All directories in the modulepath (even if they are not present on disk)
# File lib/puppet/node/environment.rb, line 225 def full_modulepath @modulepath end
@api private
# File lib/puppet/node/environment.rb, line 262 def future_parser? if @future_parser.nil? environment_conf = Puppet.lookup(:environments).get_conf(name) @future_parser = 'future' == (environment_conf.nil? ? Puppet[:parser] : environment_conf.parser) end @future_parser end
# File lib/puppet/node/environment.rb, line 512 def hash [self.class, name, full_modulepath, manifest].hash end
@api public @return [Puppet::Resource::TypeCollection] The current global TypeCollection
# File lib/puppet/node/environment.rb, line 282 def known_resource_types if @known_resource_types.nil? @known_resource_types = Puppet::Resource::TypeCollection.new(self) @known_resource_types.import_ast(perform_initial_import(), '') end @known_resource_types end
Locate a module instance by the module name alone.
@api public
@param name [String] The module name @return [Puppet::Module, nil] The module if found, else nil
# File lib/puppet/node/environment.rb, line 308 def module(name) modules.find {|mod| mod.name == name} end
Locate a module instance by the full forge name (EG authorname/module)
@api public
@param forge_name [String] The module name @return [Puppet::Module, nil] The module if found, else nil
# File lib/puppet/node/environment.rb, line 318 def module_by_forge_name(forge_name) author, modname = forge_name.split('/') found_mod = self.module(modname) found_mod and found_mod.forge_name == forge_name ? found_mod : nil end
All module requirements for all modules in the environment modulepath
@api public
@comment This has nothing to do with an environment. It seems like it was
stuffed into the first convenient class that vaguely involved modules.
@example
environment.module_requirements # => { # 'username/amodule' => [ # { # 'name' => 'username/moduledep', # 'version' => '1.2.3', # 'version_requirement' => '>= 1.0.0', # }, # { # 'name' => 'username/anotherdep', # 'version' => '4.5.6', # 'version_requirement' => '>= 3.0.0', # } # ] # } #
@return [Hash<String, Array<Hash<String, String>>>] See the method example
for an explanation of the return value.
# File lib/puppet/node/environment.rb, line 427 def module_requirements deps = {} modules.each do |mod| next unless mod.forge_name deps[mod.forge_name] ||= [] mod.dependencies and mod.dependencies.each do |mod_dep| dep_name = mod_dep['name'].tr('-', '/') (deps[dep_name] ||= []) << { 'name' => mod.forge_name, 'version' => mod.version, 'version_requirement' => mod_dep['version_requirement'] } end end deps.each do |mod, mod_deps| deps[mod] = mod_deps.sort_by { |d| d['name'] } end deps end
@api public @return [Array<String>] All directories present on disk in the modulepath
# File lib/puppet/node/environment.rb, line 217 def modulepath @modulepath.find_all do |p| Puppet::FileSystem.directory?(p) end end
Modules broken out by directory in the modulepath
@note This method changes the current working directory while enumerating
the modules. This seems rather dangerous.
@api public
@return [Hash<String, Array<Puppet::Module>>] A hash whose keys are file
paths, and whose values is an array of Puppet Modules for that path
# File lib/puppet/node/environment.rb, line 385 def modules_by_path modules_by_path = {} modulepath.each do |path| Dir.chdir(path) do module_names = Dir.glob('*').select do |d| FileTest.directory?(d) && (File.basename(d) =~ /\A\w+(-\w+)*\Z/) end modules_by_path[path] = module_names.sort.map do |name| Puppet::Module.new(name, File.join(path, name), self) end end end modules_by_path end
Creates a new Puppet::Node::Environment instance, overriding manfiest modulepath, or :#config_version from the passed settings if they were originally set from the commandline, or returns self if there is nothing to override.
@param settings [Puppet::Settings] an initialized puppet settings instance @return [Puppet::Node::Environment] new overridden environment or self if
there are no commandline changes from settings.
# File lib/puppet/node/environment.rb, line 161 def override_from_commandline(settings) overrides = {} if settings.set_by_cli?(:modulepath) overrides[:modulepath] = self.class.split_path(settings.value(:modulepath)) end if settings.set_by_cli?(:config_version) overrides[:config_version] = settings.value(:config_version) end if settings.set_by_cli?(:manifest) || (settings.set_by_cli?(:manifestdir) && settings.value(:manifest).start_with?(settings.value(:manifestdir))) overrides[:manifest] = settings.value(:manifest) end overrides.empty? ? self : self.override_with(overrides) end
Creates a new Puppet::Node::Environment instance, overriding any of the passed parameters.
@param env_params [Hash<{Symbol => String,Array<String>}>] new environment
parameters (:modulepath, :manifest, :config_version)
@return [Puppet::Node::Environment]
# File lib/puppet/node/environment.rb, line 146 def override_with(env_params) return self.class.create(name, env_params[:modulepath] || modulepath, env_params[:manifest] || manifest, env_params[:config_version] || config_version) end
@return [String] The stringified value of the `name` instance variable @api public
# File lib/puppet/node/environment.rb, line 473 def to_s name.to_s end
@return [Symbol] The `name` value, cast to a string, then cast to a symbol.
@api public
@note the `name` instance variable is a Symbol, but this casts the value
to a String and then converts it back into a Symbol which will needlessly create an object that needs to be garbage collected
# File lib/puppet/node/environment.rb, line 484 def to_sym to_s.to_sym end
Return only the environment name when serializing.
The only thing we care about when serializing an environment is its identity; everything else is ephemeral and should not be stored or transmitted.
@api public
# File lib/puppet/node/environment.rb, line 495 def to_zaml(z) self.to_s.to_zaml(z) end
Generate a warning if the given directory in a module path entry is named `lib`.
@api private
@param path [String] The module directory containing the given directory @param name [String] The directory name
# File lib/puppet/node/environment.rb, line 368 def warn_about_mistaken_path(path, name) if name == "lib" Puppet.debug("Warning: Found directory named 'lib' in module path ('#{path}/lib'); unless " + "you are expecting to load a module named 'lib', your module path may be set " + "incorrectly.") end end
Set a periodic watcher on the file, so we can tell if it has changed. If watching has been turned off, this call has no effect. @param file File instance or filename @api private
# File lib/puppet/node/environment.rb, line 455 def watch_file(file) if watching? known_resource_types.watch_file(file.to_s) end end
Turns watching of files on or off @param flag [TrueClass, FalseClass] if files should be watched or not @ api private
# File lib/puppet/node/environment.rb, line 136 def watching=(flag) @watching = flag end
Returns if files are being watched or not. @api private
# File lib/puppet/node/environment.rb, line 129 def watching? @watching end
Clear all memoized environments and the ‘current’ environment
@api private
# File lib/puppet/node/environment.rb, line 205 def self.clear seen.clear end
Create a new environment with the given name
@param name [Symbol] the name of the @param modulepath [Array<String>] the list of paths from which to load modules @param manifest [String] the path to the manifest for the environment or the constant Puppet::Node::Environment::NO_MANIFEST if there is none. @param #config_version [String] path to a script whose output will be added
to report logs (optional)
@return [Puppet::Node::Environment]
@api public
# File lib/puppet/node/environment.rb, line 84 def self.create(name, modulepath, manifest = NO_MANIFEST, config_version = nil) obj = self.allocate obj.send(:initialize, name, expand_dirs(extralibs() + modulepath), manifest == NO_MANIFEST ? manifest : File.expand_path(manifest), config_version) obj end
Retrieve the environment for the current process.
@note This should only used when a catalog is being compiled.
@api private
@return [Puppet::Node::Environment] the currently set environment if one
has been explicitly set, else it will return the '*root*' environment
# File lib/puppet/node/environment.rb, line 190 def self.current Puppet.deprecation_warning("Puppet::Node::Environment.current has been replaced by Puppet.lookup(:current_environment), see http://links.puppetlabs.com/current-env-deprecation") Puppet.lookup(:current_environment) end
Create a new environment with the given name, or return an existing one
The environment class memoizes instances so that attempts to instantiate an environment with the same name with an existing environment will return the existing environment.
@overload self.new(environment)
@param environment [Puppet::Node::Environment] @return [Puppet::Node::Environment] the environment passed as the param, this is implemented so that a calling class can use strings or environments interchangeably.
@overload self.new(string)
@param string [String, Symbol] @return [Puppet::Node::Environment] An existing environment if it exists, else a new environment with that name
@overload self.new()
@return [Puppet::Node::Environment] The environment as set by Puppet.settings[:environment]
@api public
# File lib/puppet/node/environment.rb, line 56 def self.new(name = nil) return name if name.is_a?(self) name ||= Puppet.settings.value(:environment) raise ArgumentError, "Environment name must be specified" unless name symbol = name.to_sym return seen[symbol] if seen[symbol] obj = self.create(symbol, split_path(Puppet.settings.value(:modulepath, symbol)), Puppet.settings.value(:manifest, symbol), Puppet.settings.value(:config_version, symbol)) seen[symbol] = obj end
Instantiate a new environment
@note {::new} is overridden to return memoized
objects, so this will not be invoked with the normal Ruby initialization semantics.
@param name [Symbol] The environment name
# File lib/puppet/node/environment.rb, line 116 def initialize(name, modulepath, manifest, config_version) @name = name @modulepath = modulepath @manifest = manifest @config_version = config_version # set watching to true for legacy environments - the directory based environment loaders will set this to # false for directory based environments after the environment has been created. @watching = true end
A “reference” to a remote environment. The created environment instance isn’t expected to exist on the local system, but is instead a reference to environment information on a remote system. For instance when a catalog is being applied, this will be used on the agent.
@note This does not provide access to the information of the remote environment’s modules, manifest, or anything else. It is simply a value object to pass around and use as an environment.
@param name [Symbol] The name of the remote environment
# File lib/puppet/node/environment.rb, line 105 def self.remote(name) create(name, [], NO_MANIFEST) end
@api private
# File lib/puppet/node/environment.rb, line 30 def self.seen @seen ||= {} end
# File lib/puppet/node/environment.rb, line 499 def self.split_path(path_string) path_string.split(File::PATH_SEPARATOR) end
@param [String] name Environment name to check for valid syntax. @return [Boolean] true if name is valid @api public
# File lib/puppet/node/environment.rb, line 198 def self.valid_name?(name) !!name.match(/\A\w+\Z/) end