Class: Puppet::Node::Environment
- 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.
## 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 Parser::Functions.reset is called.
Constant Summary collapse
- NO_MANIFEST =
:no_manifest
Instance Attribute Summary collapse
- #config_version ⇒ Object readonly
- #manifest ⇒ Object readonly
-
#modules ⇒ Array<Puppet::Module>
readonly
Return all modules for this environment in the order they appear in the modulepath.
- #name ⇒ Object readonly
Class Method Summary collapse
-
.clear ⇒ Object
private
Clear all memoized environments and the ‘current’ environment.
-
.create(name, modulepath, manifest = NO_MANIFEST, config_version = nil) ⇒ Puppet::Node::Environment
Create a new environment with the given name.
-
.current ⇒ Puppet::Node::Environment
private
Retrieve the environment for the current process.
-
.new(name = nil) ⇒ Object
Create a new environment with the given name, or return an existing one.
-
.remote(name) ⇒ Object
A “reference” to a remote environment.
- .seen ⇒ Object private
- .split_path(path_string) ⇒ Object
-
.valid_name?(name) ⇒ Boolean
True if name is valid.
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
-
#[](param) ⇒ Object
Return an environment-specific Puppet setting.
-
#check_for_reparse ⇒ Object
Checks if a reparse is required (cache of files is stale).
-
#conflicting_manifest_settings? ⇒ Boolean
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. -
#each_plugin_directory {|String| ... } ⇒ Object
Yields each modules’ plugin directory if the plugin directory (modulename/lib) is present on the filesystem.
-
#full_modulepath ⇒ Array<String>
All directories in the modulepath (even if they are not present on disk).
- #hash ⇒ Object
-
#initialize(name, modulepath, manifest, config_version) ⇒ Environment
constructor
Instantiate a new environment.
-
#known_resource_types ⇒ Puppet::Resource::TypeCollection
The current global TypeCollection.
-
#module(name) ⇒ Puppet::Module?
Locate a module instance by the module name alone.
-
#module_by_forge_name(forge_name) ⇒ Puppet::Module?
Locate a module instance by the full forge name (EG authorname/module).
-
#module_requirements ⇒ Hash<String, Array<Hash<String, String>>>
All module requirements for all modules in the environment modulepath.
-
#modulepath ⇒ Array<String>
All directories present on disk in the modulepath.
-
#modules_by_path ⇒ Hash<String, Array<Puppet::Module>>
Modules broken out by directory in the modulepath.
-
#override_from_commandline(settings) ⇒ Puppet::Node::Environment
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.
-
#override_with(env_params) ⇒ Puppet::Node::Environment
Creates a new Puppet::Node::Environment instance, overriding any of the passed parameters.
-
#to_s ⇒ String
The stringified value of the ‘name` instance variable.
-
#to_sym ⇒ Symbol
The ‘name` value, cast to a string, then cast to a symbol.
-
#to_zaml(z) ⇒ Object
Return only the environment name when serializing.
-
#warn_about_mistaken_path(path, name) ⇒ Object
private
Generate a warning if the given directory in a module path entry is named ‘lib`.
-
#watch_file(file) ⇒ Object
private
Set a periodic watcher on the file, so we can tell if it has changed.
-
#watching=(flag) ⇒ Object
Turns watching of files on or off @ api private.
-
#watching? ⇒ Boolean
private
Returns if files are being watched or not.
Methods included from Util::Cacher
Constructor Details
#initialize(name, modulepath, manifest, config_version) ⇒ Environment
new is overridden to return memoized objects, so this will not be invoked with the normal Ruby initialization semantics.
Instantiate a new environment
116 117 118 119 120 121 122 123 124 |
# 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 |
Instance Attribute Details
#config_version ⇒ Object (readonly)
238 239 240 |
# File 'lib/puppet/node/environment.rb', line 238 def config_version @config_version end |
#manifest ⇒ Object (readonly)
232 233 234 |
# File 'lib/puppet/node/environment.rb', line 232 def manifest @manifest end |
#modules ⇒ Array<Puppet::Module> (readonly)
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.
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`.
Return all modules for this environment in the order they appear in the modulepath.
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/puppet/node/environment.rb', line 330 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 |
#name ⇒ Object (readonly)
213 214 215 |
# File 'lib/puppet/node/environment.rb', line 213 def name @name end |
Class Method Details
.clear ⇒ 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.
Clear all memoized environments and the ‘current’ environment
205 206 207 |
# File 'lib/puppet/node/environment.rb', line 205 def self.clear seen.clear end |
.create(name, modulepath, manifest = NO_MANIFEST, config_version = nil) ⇒ Puppet::Node::Environment
Create a new environment with the given name
the constant Puppet::Node::Environment::NO_MANIFEST if there is none.
84 85 86 87 88 89 90 91 92 |
# 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, (extralibs() + modulepath), manifest == NO_MANIFEST ? manifest : File.(manifest), config_version) obj end |
.current ⇒ Puppet::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 should only used when a catalog is being compiled.
Retrieve the environment for the current process.
190 191 192 193 |
# 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 |
.self.new(environment) ⇒ Puppet::Node::Environment .self.new(string) ⇒ Puppet::Node::Environment .self.new ⇒ Puppet::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.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# 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 |
.remote(name) ⇒ Object
This does not provide access to the information of the remote
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.
environment’s modules, manifest, or anything else. It is simply a value object to pass around and use as an environment.
105 106 107 |
# File 'lib/puppet/node/environment.rb', line 105 def self.remote(name) create(name, [], NO_MANIFEST) end |
.seen ⇒ 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.
30 31 32 |
# File 'lib/puppet/node/environment.rb', line 30 def self.seen @seen ||= {} end |
.split_path(path_string) ⇒ Object
490 491 492 |
# File 'lib/puppet/node/environment.rb', line 490 def self.split_path(path_string) path_string.split(File::PATH_SEPARATOR) end |
.valid_name?(name) ⇒ Boolean
Returns true if name is valid.
198 199 200 |
# File 'lib/puppet/node/environment.rb', line 198 def self.valid_name?(name) !!name.match(/\A\w+\Z/) end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
494 495 496 497 498 499 |
# File 'lib/puppet/node/environment.rb', line 494 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 |
#[](param) ⇒ Object
Return an environment-specific Puppet setting.
267 268 269 |
# File 'lib/puppet/node/environment.rb', line 267 def [](param) Puppet.settings.value(param, self.name) end |
#check_for_reparse ⇒ Object
Checks if a reparse is required (cache of files is stale). This call does nothing unless files are being watched.
455 456 457 458 459 460 |
# File 'lib/puppet/node/environment.rb', line 455 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? ⇒ Boolean
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.
254 255 256 257 258 259 |
# 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 {|String| ... } ⇒ Object
Yields each modules’ plugin directory if the plugin directory (modulename/lib) is present on the filesystem.
286 287 288 289 290 291 |
# File 'lib/puppet/node/environment.rb', line 286 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 |
#full_modulepath ⇒ Array<String>
Returns All directories in the modulepath (even if they are not present on disk).
225 226 227 |
# File 'lib/puppet/node/environment.rb', line 225 def full_modulepath @modulepath end |
#hash ⇒ Object
503 504 505 |
# File 'lib/puppet/node/environment.rb', line 503 def hash [self.class, name, full_modulepath, manifest].hash end |
#known_resource_types ⇒ Puppet::Resource::TypeCollection
Returns The current global TypeCollection.
273 274 275 276 277 278 279 |
# File 'lib/puppet/node/environment.rb', line 273 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.
299 300 301 |
# File 'lib/puppet/node/environment.rb', line 299 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)
309 310 311 312 313 314 315 |
# File 'lib/puppet/node/environment.rb', line 309 def module_by_forge_name(forge_name) , modname = forge_name.split('/') found_mod = self.module(modname) found_mod and found_mod.forge_name == forge_name ? found_mod : nil end |
#module_requirements ⇒ Hash<String, Array<Hash<String, String>>>
All module requirements for all modules in the environment modulepath
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
# File 'lib/puppet/node/environment.rb', line 418 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 ⇒ Array<String>
Returns All directories present on disk in the modulepath.
217 218 219 220 221 |
# File 'lib/puppet/node/environment.rb', line 217 def modulepath @modulepath.find_all do |p| Puppet::FileSystem.directory?(p) end end |
#modules_by_path ⇒ Hash<String, Array<Puppet::Module>>
This method changes the current working directory while enumerating the modules. This seems rather dangerous.
Modules broken out by directory in the modulepath
376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/puppet/node/environment.rb', line 376 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) ⇒ Puppet::Node::Environment
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.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# 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) ⇒ Puppet::Node::Environment
Creates a new Puppet::Node::Environment instance, overriding any of the passed parameters.
146 147 148 149 150 151 |
# 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 ⇒ String
Returns The stringified value of the ‘name` instance variable.
464 465 466 |
# File 'lib/puppet/node/environment.rb', line 464 def to_s name.to_s end |
#to_sym ⇒ Symbol
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.
475 476 477 |
# File 'lib/puppet/node/environment.rb', line 475 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.
486 487 488 |
# File 'lib/puppet/node/environment.rb', line 486 def to_zaml(z) self.to_s.to_zaml(z) 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`.
359 360 361 362 363 364 365 |
# File 'lib/puppet/node/environment.rb', line 359 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) ⇒ 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.
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.
446 447 448 449 450 |
# File 'lib/puppet/node/environment.rb', line 446 def watch_file(file) if watching? known_resource_types.watch_file(file.to_s) end end |
#watching=(flag) ⇒ Object
Turns watching of files on or off @ api private
136 137 138 |
# File 'lib/puppet/node/environment.rb', line 136 def watching=(flag) @watching = flag end |
#watching? ⇒ Boolean
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.
Returns if files are being watched or not.
129 130 131 |
# File 'lib/puppet/node/environment.rb', line 129 def watching? @watching end |