Class: Puppet::Node::Environment

Inherits:
Object
  • Object
show all
Includes:
Util::Cacher
Defined in:
lib/puppet/node/environment.rb

Overview

Puppet::Node::Environment acts as a container for all configuration that is expected to vary between environments.

## Global variables

The Puppet::Node::Environment uses a number of global variables.

### ‘$environment`

The ‘environment’ global variable represents the current environment that’s being used in the compiler.

## 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 calling Environment.root.

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 Parser::Functions.reset is called.

The root environment is also used as a fallback environment when the current environment has been requested by Environment.current requested and no environment was set by Environment.current=

Defined Under Namespace

Modules: Helper

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util::Cacher

extended, included

Constructor Details

#initialize(name) ⇒ Environment

Note:

new is overridden to return memoized objects, so this will not be invoked with the normal Ruby initialization semantics.

Instantiate a new environment

Parameters:

  • name (Symbol)

    The environment name



174
175
176
# File 'lib/puppet/node/environment.rb', line 174

def initialize(name)
  @name = name
end

Instance Attribute Details

#modulepathArray<String> (readonly)

Note:

This value is cached so that the filesystem doesn’t have to be re-enumerated every time this method is invoked, since that enumeration could be a costly operation and this method is called frequently. The cache expiry is determined by Puppet[:filetimeout].

Return all existent directories in the modulepath for this environment

Returns:

  • (Array<String>)

    All directories present in the modulepath

See Also:

  • Util::Cacher.cached_attr


242
243
244
245
246
# File 'lib/puppet/node/environment.rb', line 242

cached_attr(:modulepath, Puppet[:filetimeout]) do
  dirs = self[:modulepath].split(File::PATH_SEPARATOR)
  dirs = ENV["PUPPETLIB"].split(File::PATH_SEPARATOR) + dirs if ENV["PUPPETLIB"]
  validate_dirs(dirs)
end

#modulesArray<Puppet::Module> (readonly)

Note:

If multiple modules with the same name are present they will both be added, but methods like #module and #module_by_forge_name will return the first matching entry in this list.

Note:

This value is cached so that the filesystem doesn’t have to be re-enumerated every time this method is invoked, since that enumeration could be a costly operation and this method is called frequently. The cache expiry is determined by Puppet[:filetimeout].

Return all modules for this environment in the order they appear in the modulepath.

Returns:

See Also:

  • Util::Cacher.cached_attr


261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/puppet/node/environment.rb', line 261

cached_attr(:modules, Puppet[:filetimeout]) do
  module_references = []
  seen_modules = {}
  modulepath.each do |path|
    Dir.entries(path).each do |name|
      warn_about_mistaken_path(path, name)
      next if module_references.include?(name)
      if not seen_modules[name]
        module_references << {:name => name, :path => File.join(path, name)}
        seen_modules[name] = true
      end
    end
  end

  module_references.collect do |reference|
    begin
      Puppet::Module.new(reference[:name], reference[:path], self)
    rescue Puppet::Module::Error
      nil
    end
  end.compact
end

#nameObject (readonly)



155
156
157
# File 'lib/puppet/node/environment.rb', line 155

def name
  @name
end

Class Method Details

.clearObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Clear all memoized environments and the ‘current’ environment



146
147
148
149
# File 'lib/puppet/node/environment.rb', line 146

def self.clear
  @seen.clear
  $environment = nil
end

.currentPuppet::Node::Environment

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only used when a catalog is being compiled.

Retrieve the environment for the current thread

Returns:

  • (Puppet::Node::Environment)

    the currently set environment if one has been explicitly set, else it will return the ‘root’ environment



112
113
114
# File 'lib/puppet/node/environment.rb', line 112

def self.current
  $environment || root
end

.current=(env) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only set when a catalog is being compiled. Under normal This value is initially set in Parser::Compiler#environment

Note:

Setting this affects global state during catalog compilation, and changing the current environment during compilation can cause unexpected and generally very bad behaviors.

Set the environment for the current thread

Parameters:



128
129
130
# File 'lib/puppet/node/environment.rb', line 128

def self.current=(env)
  $environment = new(env)
end

.self.new(environment) ⇒ Puppet::Node::Environment .self.new(string) ⇒ Puppet::Node::Environment .self.newPuppet::Node::Environment

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.

Overloads:

Raises:

  • (ArgumentError)


89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/puppet/node/environment.rb', line 89

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.allocate
  obj.send :initialize, symbol
  @seen[symbol] = obj
end

.rootPuppet::Node::Environment

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This is only used for handling functions that are not attached to a specific environment.

Returns:



139
140
141
# File 'lib/puppet/node/environment.rb', line 139

def self.root
  @root
end

Instance Method Details

#[](param) ⇒ Object

Return an environment-specific Puppet setting.

Parameters:

  • param (String, Symbol)

    The environment setting to look up

Returns:

  • (Object)

    The resolved setting value



163
164
165
# File 'lib/puppet/node/environment.rb', line 163

def [](param)
  Puppet.settings.value(param, self.name)
end

#check_for_reparseObject



371
372
373
374
375
# File 'lib/puppet/node/environment.rb', line 371

def check_for_reparse
  if @known_resource_types && @known_resource_types.require_reparse?
    @known_resource_types = nil
  end
end

#each_plugin_directory {|String| ... } ⇒ Object

Yields each modules’ plugin directory if the plugin directory (modulename/lib) is present on the filesystem.

Yields:

  • (String)

    Yields the plugin directory from each module to the block.



202
203
204
205
206
207
# File 'lib/puppet/node/environment.rb', line 202

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

#known_resource_typesPuppet::Resource::TypeCollection

Note:

The environment is loosely coupled with the Resource::TypeCollection class. While there is a 1:1 relationship between an environment and a TypeCollection instance, there is only one TypeCollection instance available at any given time. It is stored in ‘$known_resource_types`. `$known_resource_types` is accessed as an instance method, but is global to all environment variables.

The current global TypeCollection

Returns:



189
190
191
192
193
194
195
# File 'lib/puppet/node/environment.rb', line 189

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) ⇒ Puppet::Module?

Locate a module instance by the module name alone.

Parameters:

  • name (String)

    The module name

Returns:



215
216
217
# File 'lib/puppet/node/environment.rb', line 215

def module(name)
  modules.find {|mod| mod.name == name}
end

#module_by_forge_name(forge_name) ⇒ Puppet::Module?

Locate a module instance by the full forge name (EG authorname/module)

Parameters:

  • forge_name (String)

    The module name

Returns:



225
226
227
228
229
230
231
# File 'lib/puppet/node/environment.rb', line 225

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_requirementsHash<String, Array<Hash<String, String>>>

All module requirements for all modules in the environment modulepath

Examples:

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',
#     }
#   ]
# }
#

Returns:



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/puppet/node/environment.rb', line 349

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|
      deps[mod_dep['name']] ||= []
      dep_details = {
        'name'                => mod.forge_name,
        'version'             => mod.version,
        'version_requirement' => mod_dep['version_requirement']
      }
      deps[mod_dep['name']] << dep_details
    end
  end
  deps.each do |mod, mod_deps|
    deps[mod] = mod_deps.sort_by {|d| d['name']}
  end
  deps
end

#modules_by_pathHash<String, Array<Puppet::Module>>

Note:

This method changes the current working directory while enumerating the modules. This seems rather dangerous.

Modules broken out by directory in the modulepath

Returns:



307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/puppet/node/environment.rb', line 307

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

#to_sString

Returns The stringified value of the name instance variable.

Returns:

  • (String)

    The stringified value of the name instance variable



379
380
381
# File 'lib/puppet/node/environment.rb', line 379

def to_s
  name.to_s
end

#to_symSymbol

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

Returns The name value, cast to a string, then cast to a symbol.

Returns:

  • (Symbol)

    The name value, cast to a string, then cast to a symbol.



390
391
392
# File 'lib/puppet/node/environment.rb', line 390

def to_sym
  to_s.to_sym
end

#to_zaml(z) ⇒ Object

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.



401
402
403
# File 'lib/puppet/node/environment.rb', line 401

def to_zaml(z)
  self.to_s.to_zaml(z)
end

#validate_dirs(dirs) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Validate a list of file paths and return the paths that are directories on the filesystem

Parameters:

Returns:

  • (Array<String>)

    All file paths that exist and are directories



411
412
413
414
415
416
417
# File 'lib/puppet/node/environment.rb', line 411

def validate_dirs(dirs)
  dirs.collect do |dir|
    File.expand_path(dir)
  end.find_all do |p|
    FileTest.directory?(p)
  end
end

#warn_about_mistaken_path(path, name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generate a warning if the given directory in a module path entry is named lib.

Parameters:

  • path (String)

    The module directory containing the given directory

  • name (String)

    The directory name



290
291
292
293
294
295
296
# File 'lib/puppet/node/environment.rb', line 290

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