Class: Puppet::Parser::Scope
- Includes:
- Enumerable, Resource::TypeCollectionHelper, Util::Errors
- Defined in:
- lib/vendor/puppet/parser/scope.rb
Defined Under Namespace
Classes: Ephemeral
Constant Summary collapse
Instance Attribute Summary collapse
-
#base ⇒ Object
Returns the value of attribute base.
-
#compiler ⇒ Object
Returns the value of attribute compiler.
-
#keyword ⇒ Object
Returns the value of attribute keyword.
-
#namespaces ⇒ Object
readonly
Returns the value of attribute namespaces.
-
#parent ⇒ Object
Returns the value of attribute parent.
-
#resource ⇒ Object
Returns the value of attribute resource.
-
#source ⇒ Object
Returns the value of attribute source.
-
#top ⇒ Object
Returns the value of attribute top.
-
#translated ⇒ Object
Returns the value of attribute translated.
Class Method Summary collapse
-
.number?(value) ⇒ Boolean
Is the value a number?, return the correct object or nil if not a number.
-
.true?(value) ⇒ Boolean
Is the value true? This allows us to control the definition of truth in one place.
Instance Method Summary collapse
-
#add_namespace(ns) ⇒ Object
Add to our list of namespaces.
-
#catalog ⇒ Object
A demeterific shortcut to the catalog.
-
#class_scope(klass) ⇒ Object
Return the scope associated with a class.
-
#class_set(name, scope) ⇒ Object
Store the fact that we’ve evaluated a class, and store a reference to the scope in which it was evaluated, so that we can look it up later.
-
#dynamic_lookupvar(name, options = {}) ⇒ Object
Look up a variable.
-
#environment ⇒ Object
Remove this when rebasing.
-
#ephemeral?(name) ⇒ Boolean
is name an ephemeral variable?.
- #ephemeral_from(match, file = nil, line = nil) ⇒ Object
-
#ephemeral_include?(name) ⇒ Boolean
check if name exists in one of the ephemeral scope.
- #ephemeral_level ⇒ Object
- #find_builtin_resource_type(type) ⇒ Object
- #find_defined_resource_type(type) ⇒ Object
- #find_definition(name) ⇒ Object
- #find_hostclass(name) ⇒ Object
- #find_resource_type(type) ⇒ Object
- #findresource(string, name = nil) ⇒ Object
-
#host ⇒ Object
Proxy accessors.
-
#initialize(hash = {}) ⇒ Scope
constructor
Initialize our new scope.
-
#lookupdefaults(type) ⇒ Object
Collect all of the defaults set at any higher scopes.
-
#lookuptype(name) ⇒ Object
Look up a defined type.
-
#lookupvar(name, options = {}) ⇒ Object
Look up a variable with traditional scoping and then with new scoping.
- #method_missing(method, *args, &block) ⇒ Object
- #new_ephemeral ⇒ Object
-
#newscope(options = {}) ⇒ Object
Create a new scope and set these options.
- #parent_module_name ⇒ Object
- #resolve_type_and_titles(type, titles) ⇒ Object
-
#scope_path ⇒ Object
Return the list of scopes up to the top scope, ordered with our own first.
-
#setdefaults(type, params) ⇒ Object
Set defaults for a type.
-
#setvar(name, value, options = {}) ⇒ Object
Set a variable in the current scope.
-
#tags ⇒ Object
Return the tags associated with this scope.
-
#to_hash(recursive = true) ⇒ Object
Return a hash containing our variables and their values, optionally (and by default) including the values defined in our parent.
-
#to_s ⇒ Object
Used mainly for logging.
-
#twoscope_lookupvar(name, options = {}) ⇒ Object
Look up a variable.
- #undef_as(x, v) ⇒ Object
-
#unset_ephemeral_var(level = :all) ⇒ Object
remove ephemeral scope up to level.
-
#unsetvar(var) ⇒ Object
Undefine a variable; only used for testing.
Methods included from Util::Errors
#adderrorcontext, #devfail, #error_context, #exceptwrap, #fail
Methods included from Resource::TypeCollectionHelper
Constructor Details
#initialize(hash = {}) ⇒ Scope
Initialize our new scope. Defaults to having no parent.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/vendor/puppet/parser/scope.rb', line 120 def initialize(hash = {}) if hash.include?(:namespace) if n = hash[:namespace] @namespaces = [n] end hash.delete(:namespace) else @namespaces = [""] end hash.each { |name, val| method = name.to_s + "=" if self.respond_to? method self.send(method, val) else raise Puppet::DevError, "Invalid scope argument #{name}" end } extend_with_functions_module @tags = [] # The symbol table for this scope. This is where we store variables. @symtable = {} # the ephemeral symbol tables # those should not persist long, and are used for the moment only # for $0..$xy capture variables of regexes # this is actually implemented as a stack, with each ephemeral scope # shadowing the previous one @ephemeral = [ Ephemeral.new ] # All of the defaults set for types. It's a hash of hashes, # with the first key being the type, then the second key being # the parameter. @defaults = Hash.new { |dhash,type| dhash[type] = {} } # The table for storing class singletons. This will only actually # be used by top scopes and node scopes. @class_scopes = {} end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
457 458 459 460 461 462 463 464 465 466 467 468 |
# File 'lib/vendor/puppet/parser/scope.rb', line 457 def method_missing(method, *args, &block) method.to_s =~ /^function_(.*)$/ super unless $1 super unless Puppet::Parser::Functions.function($1) # In odd circumstances, this might not end up defined by the previous # method, so we might as well be certain. if respond_to? method send(method, *args) else raise Puppet::DevError, "Function #{$1} not defined despite being loaded!" end end |
Instance Attribute Details
#base ⇒ Object
Returns the value of attribute base.
22 23 24 |
# File 'lib/vendor/puppet/parser/scope.rb', line 22 def base @base end |
#compiler ⇒ Object
Returns the value of attribute compiler.
23 24 25 |
# File 'lib/vendor/puppet/parser/scope.rb', line 23 def compiler @compiler end |
#keyword ⇒ Object
Returns the value of attribute keyword.
22 23 24 |
# File 'lib/vendor/puppet/parser/scope.rb', line 22 def keyword @keyword end |
#namespaces ⇒ Object (readonly)
Returns the value of attribute namespaces.
25 26 27 |
# File 'lib/vendor/puppet/parser/scope.rb', line 25 def namespaces @namespaces end |
#parent ⇒ Object
Returns the value of attribute parent.
24 25 26 |
# File 'lib/vendor/puppet/parser/scope.rb', line 24 def parent @parent end |
#resource ⇒ Object
Returns the value of attribute resource.
21 22 23 |
# File 'lib/vendor/puppet/parser/scope.rb', line 21 def resource @resource end |
#source ⇒ Object
Returns the value of attribute source.
21 22 23 |
# File 'lib/vendor/puppet/parser/scope.rb', line 21 def source @source end |
#top ⇒ Object
Returns the value of attribute top.
23 24 25 |
# File 'lib/vendor/puppet/parser/scope.rb', line 23 def top @top end |
#translated ⇒ Object
Returns the value of attribute translated.
23 24 25 |
# File 'lib/vendor/puppet/parser/scope.rb', line 23 def translated @translated end |
Class Method Details
.number?(value) ⇒ Boolean
Is the value a number?, return the correct object or nil if not a number
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/vendor/puppet/parser/scope.rb', line 72 def self.number?(value) return nil unless value.is_a?(Fixnum) or value.is_a?(Bignum) or value.is_a?(Float) or value.is_a?(String) if value.is_a?(String) if value =~ /^-?\d+(:?\.\d+|(:?\.\d+)?e\d+)$/ return value.to_f elsif value =~ /^0x[0-9a-f]+$/i return value.to_i(16) elsif value =~ /^0[0-7]+$/ return value.to_i(8) elsif value =~ /^-?\d+$/ return value.to_i else return nil end end # it is one of Fixnum,Bignum or Float value end |
.true?(value) ⇒ Boolean
Is the value true? This allows us to control the definition of truth in one place.
67 68 69 |
# File 'lib/vendor/puppet/parser/scope.rb', line 67 def self.true?(value) (value != false and value != "" and value != :undef) end |
Instance Method Details
#add_namespace(ns) ⇒ Object
Add to our list of namespaces.
93 94 95 96 97 98 99 100 |
# File 'lib/vendor/puppet/parser/scope.rb', line 93 def add_namespace(ns) return false if @namespaces.include?(ns) if @namespaces == [""] @namespaces = [ns] else @namespaces << ns end end |
#catalog ⇒ Object
A demeterific shortcut to the catalog.
52 53 54 |
# File 'lib/vendor/puppet/parser/scope.rb', line 52 def catalog compiler.catalog end |
#class_scope(klass) ⇒ Object
Return the scope associated with a class. This is just here so that subclasses can set their parent scopes to be the scope of their parent class, and it’s also used when looking up qualified variables.
175 176 177 178 179 |
# File 'lib/vendor/puppet/parser/scope.rb', line 175 def class_scope(klass) # They might pass in either the class or class name k = klass.respond_to?(:name) ? klass.name : klass @class_scopes[k] || (parent && parent.class_scope(k)) end |
#class_set(name, scope) ⇒ Object
Store the fact that we’ve evaluated a class, and store a reference to the scope in which it was evaluated, so that we can look it up later.
166 167 168 169 |
# File 'lib/vendor/puppet/parser/scope.rb', line 166 def class_set(name, scope) return parent.class_set(name,scope) if parent @class_scopes[name] = scope end |
#dynamic_lookupvar(name, options = {}) ⇒ Object
Look up a variable. The simplest value search we do.
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/vendor/puppet/parser/scope.rb', line 266 def dynamic_lookupvar(name, = {}) table = ephemeral?(name) ? @ephemeral.last : @symtable # If the variable is qualified, then find the specified scope and look the variable up there instead. if name =~ /^(.*)::(.+)$/ begin qualified_scope($1).dynamic_lookupvar($2,) rescue RuntimeError => e location = ([:file] && [:line]) ? " at #{[:file]}:#{[:line]}" : '' warning "Could not look up qualified variable '#{name}'; #{e.}#{location}" :undefined end elsif ephemeral_include?(name) or table.include?(name) # We can't use "if table[name]" here because the value might be false table[name] elsif parent parent.dynamic_lookupvar(name,) else :undefined end end |
#environment ⇒ Object
Remove this when rebasing
103 104 105 |
# File 'lib/vendor/puppet/parser/scope.rb', line 103 def environment compiler.environment end |
#ephemeral?(name) ⇒ Boolean
is name an ephemeral variable?
420 421 422 |
# File 'lib/vendor/puppet/parser/scope.rb', line 420 def ephemeral?(name) name =~ /^\d+$/ end |
#ephemeral_from(match, file = nil, line = nil) ⇒ Object
432 433 434 435 436 437 438 439 440 441 |
# File 'lib/vendor/puppet/parser/scope.rb', line 432 def ephemeral_from(match, file = nil, line = nil) raise(ArgumentError,"Invalid regex match data") unless match.is_a?(MatchData) new_ephemeral setvar("0", match[0], :file => file, :line => line, :ephemeral => true) match.captures.each_with_index do |m,i| setvar("#{i+1}", m, :file => file, :line => line, :ephemeral => true) end end |
#ephemeral_include?(name) ⇒ Boolean
check if name exists in one of the ephemeral scope.
412 413 414 415 416 417 |
# File 'lib/vendor/puppet/parser/scope.rb', line 412 def ephemeral_include?(name) @ephemeral.reverse_each do |eph| return true if eph.include?(name) end false end |
#ephemeral_level ⇒ Object
424 425 426 |
# File 'lib/vendor/puppet/parser/scope.rb', line 424 def ephemeral_level @ephemeral.size end |
#find_builtin_resource_type(type) ⇒ Object
449 450 451 |
# File 'lib/vendor/puppet/parser/scope.rb', line 449 def find_builtin_resource_type(type) Puppet::Type.type(type.to_s.downcase.to_sym) end |
#find_defined_resource_type(type) ⇒ Object
453 454 455 |
# File 'lib/vendor/puppet/parser/scope.rb', line 453 def find_defined_resource_type(type) environment.known_resource_types.find_definition(namespaces, type.to_s.downcase) end |
#find_definition(name) ⇒ Object
111 112 113 |
# File 'lib/vendor/puppet/parser/scope.rb', line 111 def find_definition(name) known_resource_types.find_definition(namespaces, name) end |
#find_hostclass(name) ⇒ Object
107 108 109 |
# File 'lib/vendor/puppet/parser/scope.rb', line 107 def find_hostclass(name) known_resource_types.find_hostclass(namespaces, name) end |
#find_resource_type(type) ⇒ Object
443 444 445 446 447 |
# File 'lib/vendor/puppet/parser/scope.rb', line 443 def find_resource_type(type) # It still works fine without the type == 'class' short-cut, but it is a lot slower. return nil if ["class", "node"].include? type.to_s.downcase find_builtin_resource_type(type) || find_defined_resource_type(type) end |
#findresource(string, name = nil) ⇒ Object
115 116 117 |
# File 'lib/vendor/puppet/parser/scope.rb', line 115 def findresource(string, name = nil) compiler.findresource(string, name) end |
#host ⇒ Object
Proxy accessors
61 62 63 |
# File 'lib/vendor/puppet/parser/scope.rb', line 61 def host @compiler.node.name end |
#lookupdefaults(type) ⇒ Object
Collect all of the defaults set at any higher scopes. This is a different type of lookup because it’s additive – it collects all of the defaults, with defaults in closer scopes overriding those in later scopes.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/vendor/puppet/parser/scope.rb', line 185 def lookupdefaults(type) values = {} # first collect the values from the parents unless parent.nil? parent.lookupdefaults(type).each { |var,value| values[var] = value } end # then override them with any current values # this should probably be done differently if @defaults.include?(type) @defaults[type].each { |var,value| values[var] = value } end #Puppet.debug "Got defaults for %s: %s" % # [type,values.inspect] values end |
#lookuptype(name) ⇒ Object
Look up a defined type.
209 210 211 |
# File 'lib/vendor/puppet/parser/scope.rb', line 209 def lookuptype(name) find_definition(name) || find_hostclass(name) end |
#lookupvar(name, options = {}) ⇒ Object
Look up a variable with traditional scoping and then with new scoping. If the answers differ then print a deprecation warning.
227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/vendor/puppet/parser/scope.rb', line 227 def lookupvar(name, = {}) dynamic_value = dynamic_lookupvar(name,) twoscope_value = twoscope_lookupvar(name,) if dynamic_value != twoscope_value location = ([:file] && [:line]) ? " at #{[:file]}:#{[:line]}" : '' Puppet.deprecation_warning("Dynamic lookup of $#{name}#{location} is deprecated. For more information, see http://docs.puppetlabs.com/guides/scope_and_puppet.html. To see the change in behavior, use the --debug flag.") Puppet.debug("Currently $#{name} is #{dynamic_value.inspect}") Puppet.debug("In the future $#{name} will be #{twoscope_value == :undefined ? "undefined" : twoscope_value.inspect}") end dynamic_value end |
#new_ephemeral ⇒ Object
428 429 430 |
# File 'lib/vendor/puppet/parser/scope.rb', line 428 def new_ephemeral @ephemeral.push(Ephemeral.new(@ephemeral.last)) end |
#newscope(options = {}) ⇒ Object
Create a new scope and set these options.
309 310 311 |
# File 'lib/vendor/puppet/parser/scope.rb', line 309 def newscope( = {}) compiler.newscope(self, ) end |
#parent_module_name ⇒ Object
313 314 315 316 317 |
# File 'lib/vendor/puppet/parser/scope.rb', line 313 def parent_module_name return nil unless @parent return nil unless @parent.source @parent.source.module_name end |
#resolve_type_and_titles(type, titles) ⇒ Object
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/vendor/puppet/parser/scope.rb', line 470 def resolve_type_and_titles(type, titles) raise ArgumentError, "titles must be an array" unless titles.is_a?(Array) case type.downcase when "class" # resolve the titles titles = titles.collect do |a_title| hostclass = find_hostclass(a_title) hostclass ? hostclass.name : a_title end when "node" # no-op else # resolve the type resource_type = find_resource_type(type) type = resource_type.name if resource_type end return [type, titles] end |
#scope_path ⇒ Object
Return the list of scopes up to the top scope, ordered with our own first. This is used for looking up variables and defaults.
321 322 323 324 325 326 327 |
# File 'lib/vendor/puppet/parser/scope.rb', line 321 def scope_path if parent [self, parent.scope_path].flatten.compact else [self] end end |
#setdefaults(type, params) ⇒ Object
Set defaults for a type. The typename should already be downcased, so that the syntax is isolated. We don’t do any kind of type-checking here; instead we let the resource do it when the defaults are used.
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/vendor/puppet/parser/scope.rb', line 332 def setdefaults(type, params) table = @defaults[type] # if we got a single param, it'll be in its own array params = [params] unless params.is_a?(Array) params.each { |param| #Puppet.debug "Default for %s is %s => %s" % # [type,ary[0].inspect,ary[1].inspect] if table.include?(param.name) raise Puppet::ParseError.new("Default already defined for #{type} { #{param.name} }; cannot redefine", param.line, param.file) end table[param.name] = param } end |
#setvar(name, value, options = {}) ⇒ Object
Set a variable in the current scope. This will override settings in scopes above, but will not allow variables in the current scope to be reassigned.
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/vendor/puppet/parser/scope.rb', line 351 def setvar(name,value, = {}) table = [:ephemeral] ? @ephemeral.last : @symtable if table.include?(name) unless [:append] error = Puppet::ParseError.new("Cannot reassign variable #{name}") else error = Puppet::ParseError.new("Cannot append, variable #{name} is defined in this scope") end error.file = [:file] if [:file] error.line = [:line] if [:line] raise error end unless [:append] table[name] = value else # append case # lookup the value in the scope if it exists and insert the var table[name] = undef_as('',lookupvar(name)) # concatenate if string, append if array, nothing for other types case value when Array table[name] += value when Hash raise ArgumentError, "Trying to append to a hash with something which is not a hash is unsupported" unless value.is_a?(Hash) table[name].merge!(value) else table[name] << value end end end |
#tags ⇒ Object
Return the tags associated with this scope. It’s basically just our parents’ tags, plus our type. We don’t cache this value because our parent tags might change between calls.
385 386 387 |
# File 'lib/vendor/puppet/parser/scope.rb', line 385 def resource. end |
#to_hash(recursive = true) ⇒ Object
Return a hash containing our variables and their values, optionally (and by default) including the values defined in our parent. Local values shadow parent values.
290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/vendor/puppet/parser/scope.rb', line 290 def to_hash(recursive = true) target = parent.to_hash(recursive) if recursive and parent target ||= Hash.new @symtable.keys.each { |name| value = @symtable[name] if value == :undef target.delete(name) else target[name] = value end } target end |
#to_s ⇒ Object
Used mainly for logging
390 391 392 |
# File 'lib/vendor/puppet/parser/scope.rb', line 390 def to_s "Scope(#{@resource})" end |
#twoscope_lookupvar(name, options = {}) ⇒ Object
Look up a variable. The simplest value search we do.
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/vendor/puppet/parser/scope.rb', line 240 def twoscope_lookupvar(name, = {}) # Save the originating scope for the request [:origin] = self unless [:origin] table = ephemeral?(name) ? @ephemeral.last : @symtable if name =~ /^(.*)::(.+)$/ begin qualified_scope($1).twoscope_lookupvar($2, .merge({:origin => nil})) rescue RuntimeError => e location = ([:file] && [:line]) ? " at #{[:file]}:#{[:line]}" : '' warning "Could not look up qualified variable '#{name}'; #{e.}#{location}" :undefined end # If the value is present and either we are top/node scope or originating scope... elsif (ephemeral_include?(name) or table.include?(name)) and (compiler and self == compiler.topscope or (resource and resource.type == "Node") or self == [:origin]) table[name] elsif resource and resource.type == "Class" and parent_type = resource.resource_type.parent qualified_scope(parent_type).twoscope_lookupvar(name,.merge({:origin => nil})) elsif parent parent.twoscope_lookupvar(name, ) else :undefined end end |
#undef_as(x, v) ⇒ Object
213 214 215 |
# File 'lib/vendor/puppet/parser/scope.rb', line 213 def undef_as(x,v) (v == :undefined) ? x : (v == :undef) ? x : v end |
#unset_ephemeral_var(level = :all) ⇒ Object
remove ephemeral scope up to level
401 402 403 404 405 406 407 408 409 |
# File 'lib/vendor/puppet/parser/scope.rb', line 401 def unset_ephemeral_var(level=:all) if level == :all @ephemeral = [ Ephemeral.new ] else (@ephemeral.size - level).times do @ephemeral.pop end end end |
#unsetvar(var) ⇒ Object
Undefine a variable; only used for testing.
395 396 397 398 |
# File 'lib/vendor/puppet/parser/scope.rb', line 395 def unsetvar(var) table = ephemeral?(var) ? @ephemeral.last : @symtable table.delete(var) if table.include?(var) end |