class Puppet::Parser::Methods::Environment

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.

Constants

NONE

A special “null” environment

This environment should be used when there is no specific environment in effect.

NO_MANIFEST

Attributes

config_version[R]

@!attribute [r] #config_version

@api public
@return [String] path to a script whose output will be added to report logs
  (optional)
manifest[R]

@!attribute [r] manifest

@api public
@return [String] path to the manifest file or directory.
name[R]

@!attribute [r] name

@api public
@return [Symbol] the human readable environment name that serves as the
  environment identifier

Public Instance Methods

==(other) click to toggle source
# 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
Also aliased as: eql?
[](param) click to toggle source

Return an environment-specific Puppet setting.

@api public

@param param [String, Symbol] The environment setting to look up @return [Object] The resolved setting value

# File lib/puppet/node/environment.rb, line 276
def [](param)
  Puppet.settings.value(param, self.name)
end
check_for_reparse() click to toggle source

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

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
each_plugin_directory() { |lib| ... } click to toggle source

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
eql?(other) click to toggle source
Alias for: ==
full_modulepath() click to toggle source

@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
future_parser?() click to toggle source

@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
hash() click to toggle source
# File lib/puppet/node/environment.rb, line 512
def hash
  [self.class, name, full_modulepath, manifest].hash
end
known_resource_types() click to toggle source

@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
module(name) click to toggle source

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

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

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

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

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

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

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

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

@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
to_zaml(z) click to toggle source

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
warn_about_mistaken_path(path, name) click to toggle source

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

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
watching=(flag) click to toggle source

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

Returns if files are being watched or not. @api private

# File lib/puppet/node/environment.rb, line 129
def watching?
  @watching
end

Public Class Methods

clear() click to toggle source

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(name, modulepath, manifest = NO_MANIFEST, config_version = nil) click to toggle source

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

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
new(name = nil) click to toggle source

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
new(name, modulepath, manifest, config_version) click to toggle source

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

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

@api private

# File lib/puppet/node/environment.rb, line 30
def self.seen
  @seen ||= {}
end
split_path(path_string) click to toggle source
# File lib/puppet/node/environment.rb, line 499
def self.split_path(path_string)
  path_string.split(File::PATH_SEPARATOR)
end
valid_name?(name) click to toggle source

@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