class Puppet::Parser::Scope
This class is part of the internal parser/evaluator/compiler functionality of Puppet
. It is passed between the various classes that participate in evaluation. None of its methods are API except those that are clearly marked as such.
@api public
Constants
- BUILT_IN_VARS
Variables that always exist with nil value even if not set
- EMPTY_HASH
- RESERVED_VARIABLE_NAMES
- TYPENAME_CLASS
- TYPENAME_NODE
- UNCAUGHT_THROW_EXCEPTION
The exception raised when a throw is uncaught is different in different versions of ruby. In >=2.2.0 it is UncaughtThrowError (which did not exist prior to this)
- UNDEFINED_VARIABLES_KIND
- VARNAME_FACTS
- VARNAME_SERVER_FACTS
- VARNAME_TRUSTED
Attributes
Hash of hashes of default values per type name
Public Class Methods
Initialize our new scope. Defaults to having no parent.
# File lib/puppet/parser/scope.rb 373 def initialize(compiler, source: nil, resource: nil) 374 if compiler.is_a? Puppet::Parser::AbstractCompiler 375 @compiler = compiler 376 else 377 raise Puppet::DevError, _("you must pass a compiler instance to a new scope object") 378 end 379 380 @source = source 381 @resource = resource 382 383 extend_with_functions_module 384 385 # The symbol table for this scope. This is where we store variables. 386 # @symtable = Ephemeral.new(nil, true) 387 @symtable = LocalScope.new(nil) 388 389 @ephemeral = [ MatchScope.new(@symtable, nil) ] 390 391 # All of the defaults set for types. It's a hash of hashes, 392 # with the first key being the type, then the second key being 393 # the parameter. 394 @defaults = Hash.new { |dhash,type| 395 dhash[type] = {} 396 } 397 398 # The table for storing class singletons. This will only actually 399 # be used by top scopes and node scopes. 400 @class_scopes = {} 401 end
Coerce value to a number, or return `nil` if it isn't one.
# File lib/puppet/parser/scope.rb 327 def self.number?(value) 328 case value 329 when Numeric 330 value 331 when /^-?\d+(:?\.\d+|(:?\.\d+)?e\d+)$/ 332 value.to_f 333 when /^0x[0-9a-f]+$/i 334 value.to_i(16) 335 when /^0[0-7]+$/ 336 value.to_i(8) 337 when /^-?\d+$/ 338 value.to_i 339 else 340 nil 341 end 342 end
Is the value true? This allows us to control the definition of truth in one place.
# File lib/puppet/parser/scope.rb 315 def self.true?(value) 316 case value 317 when '' 318 false 319 when :undef 320 false 321 else 322 !!value 323 end 324 end
Public Instance Methods
Retrieves the variable value assigned to the name given as an argument. The name must be a String, and namespace can be qualified with '::'. The value is looked up in this scope, its parent scopes, or in a specific visible named scope.
@param varname [String] the name of the variable (may be a qualified name using `(ns'::')*varname` @param options [Hash] Additional options, not part of api. @return [Object] the value assigned to the given varname @see []=
@api public
# File lib/puppet/parser/scope.rb 553 def [](varname, options = EMPTY_HASH) 554 lookupvar(varname, options) 555 end
Sets the variable value of the name given as an argument to the given value. The value is set in the current scope and may shadow a variable with the same name in a visible outer scope. It is illegal to re-assign a variable in the same scope. It is illegal to set a variable in some other scope/namespace than the scope passed to a method.
@param varname [String] The variable name to which the value is assigned. Must not contain `::` @param value [String] The value to assign to the given variable name. @param options [Hash] Additional options, not part of api and no longer used.
@api public
# File lib/puppet/parser/scope.rb 868 def []=(varname, value, _ = nil) 869 setvar(varname, value) 870 end
Returns true if the given name is bound in the current (most nested) scope for assignments.
# File lib/puppet/parser/scope.rb 308 def bound?(name) 309 # Do not look in ephemeral (match scope), the semantics is to answer if an assignable variable is bound 310 effective_symtable(false).bound?(name) 311 end
Calls a 3.x or 4.x function by name with arguments given in an array using the 4.x calling convention and returns the result. Note that it is the caller's responsibility to rescue the given ArgumentError and provide location information to aid the user find the problem. The problem is otherwise reported against the source location that invoked the function that ultimately called this method.
@return [Object] the result of the called function @raise ArgumentError if the function does not exist
# File lib/puppet/parser/scope.rb 1100 def call_function(func_name, args, &block) 1101 Puppet::Pops::Parser::EvaluatingParser.new.evaluator.external_call_function(func_name, args, self, &block) 1102 end
Alias for `compiler.catalog`
# File lib/puppet/parser/scope.rb 37 def catalog 38 @compiler.catalog 39 end
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.
# File lib/puppet/parser/scope.rb 417 def class_scope(klass) 418 # They might pass in either the class or class name 419 k = klass.respond_to?(:name) ? klass.name : klass 420 @class_scopes[k] || (parent && parent.class_scope(k)) 421 end
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.
# File lib/puppet/parser/scope.rb 405 def class_set(name, scope) 406 if parent 407 parent.class_set(name, scope) 408 else 409 @class_scopes[name] = scope 410 end 411 end
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.
# File lib/puppet/parser/scope.rb 695 def define_settings(type, params) 696 table = @defaults[type] 697 698 # if we got a single param, it'll be in its own array 699 params = [params] unless params.is_a?(Array) 700 701 params.each { |param| 702 if table.include?(param.name) 703 raise Puppet::ParseError.new(_("Default already defined for %{type} { %{param} }; cannot redefine") % { type: type, param: param.name }, param.file, param.line) 704 end 705 table[param.name] = param 706 } 707 end
Return the effective “table” for setting variables. This method returns the first ephemeral “table” that acts as a local scope, or this scope's symtable. If the parameter `use_ephemeral` is true, the “top most” ephemeral “table” will be returned (irrespective of it being a match scope or a local scope).
@param use_ephemeral [Boolean] whether the top most ephemeral (of any kind) should be used or not
# File lib/puppet/parser/scope.rb 847 def effective_symtable(use_ephemeral) 848 s = @ephemeral[-1] 849 return s || @symtable if use_ephemeral 850 851 while s && !s.is_local_scope?() 852 s = s.parent 853 end 854 s || @symtable 855 end
The enclosing scope (topscope or nodescope) of this scope. The enclosing scopes are produced when a class or define is included at some point. The parent scope of the included class or define becomes the scope in which it was included. The chain of parent scopes is followed until a node scope or the topscope is found
@return [Puppet::Parser::Scope] The scope or nil if there is no enclosing scope
# File lib/puppet/parser/scope.rb 575 def enclosing_scope 576 if has_enclosing_scope? 577 if parent.is_topscope? || parent.is_nodescope? 578 parent 579 else 580 parent.enclosing_scope 581 end 582 end 583 end
Alias for `compiler.environment`
# File lib/puppet/parser/scope.rb 32 def environment 33 @compiler.environment 34 end
# File lib/puppet/parser/scope.rb 1001 def ephemeral_from(match, file = nil, line = nil) 1002 case match 1003 when Hash 1004 # Create local scope ephemeral and set all values from hash 1005 new_ephemeral(true) 1006 match.each {|k,v| setvar(k, v, :file => file, :line => line, :ephemeral => true) } 1007 # Must always have an inner match data scope (that starts out as transparent) 1008 # In 3x slightly wasteful, since a new nested scope is created for a match 1009 # (TODO: Fix that problem) 1010 new_ephemeral(false) 1011 else 1012 raise(ArgumentError,_("Invalid regex match data. Got a %{klass}") % { klass: match.class }) unless match.is_a?(MatchData) 1013 # Create a match ephemeral and set values from match data 1014 new_match_scope(match) 1015 end 1016 end
# File lib/puppet/parser/scope.rb 914 def ephemeral_level 915 @ephemeral.size 916 end
Returns true if the variable of the given name is set to any value (including nil)
@return [Boolean] if variable exists or not
# File lib/puppet/parser/scope.rb 283 def exist?(name) 284 # Note !! ensure the answer is boolean 285 !! if name =~ /^(.*)::(.+)$/ 286 class_name = $1 287 variable_name = $2 288 return true if class_name == '' && BUILT_IN_VARS.include?(variable_name) 289 290 # lookup class, but do not care if it is not evaluated since that will result 291 # in it not existing anyway. (Tests may run with just scopes and no evaluated classes which 292 # will result in class_scope for "" not returning topscope). 293 klass = find_hostclass(class_name) 294 other_scope = klass.nil? ? nil : class_scope(klass) 295 if other_scope.nil? 296 class_name == '' ? compiler.topscope.exist?(variable_name) : false 297 else 298 other_scope.exist?(variable_name) 299 end 300 else 301 next_scope = inherited_scope || enclosing_scope 302 effective_symtable(true).include?(name) || next_scope && next_scope.exist?(name) || BUILT_IN_VARS.include?(name) 303 end 304 end
@api private
# File lib/puppet/parser/scope.rb 1024 def find_builtin_resource_type(type) 1025 raise Puppet::DevError, _("Scope#find_builtin_resource_type() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead") 1026 end
@api private
# File lib/puppet/parser/scope.rb 1029 def find_defined_resource_type(type) 1030 raise Puppet::DevError, _("Scope#find_defined_resource_type() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead") 1031 end
# File lib/puppet/parser/scope.rb 348 def find_definition(name) 349 environment.known_resource_types.find_definition(name) 350 end
# File lib/puppet/parser/scope.rb 352 def find_global_scope() 353 # walk upwards until first found node_scope or top_scope 354 if is_nodescope? || is_topscope? 355 self 356 else 357 next_scope = inherited_scope || enclosing_scope 358 if next_scope.nil? 359 # this happens when testing, and there is only a single test scope and no link to any 360 # other scopes 361 self 362 else 363 next_scope.find_global_scope() 364 end 365 end 366 end
# File lib/puppet/parser/scope.rb 344 def find_hostclass(name) 345 environment.known_resource_types.find_hostclass(name) 346 end
@api private
# File lib/puppet/parser/scope.rb 1019 def find_resource_type(type) 1020 raise Puppet::DevError, _("Scope#find_resource_type() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead") 1021 end
# File lib/puppet/parser/scope.rb 368 def findresource(type, title = nil) 369 @compiler.catalog.resource(type, title) 370 end
@api private
# File lib/puppet/parser/scope.rb 630 def get_local_variable(name) 631 @ephemeral.last[name] 632 end
# File lib/puppet/parser/scope.rb 634 def handle_not_found(class_name, variable_name, position, reason = nil) 635 unless Puppet[:strict_variables] 636 # Do not issue warning if strict variables are on, as an error will be raised by variable_not_found 637 location = if position[:lineproc] 638 Puppet::Util::Errors.error_location_with_space(nil, position[:lineproc].call) 639 else 640 Puppet::Util::Errors.error_location_with_space(position[:file], position[:line]) 641 end 642 variable_not_found("#{class_name}::#{variable_name}", "#{reason}#{location}") 643 return nil 644 end 645 variable_not_found("#{class_name}::#{variable_name}", reason) 646 end
@api private
# File lib/puppet/parser/scope.rb 625 def has_local_variable?(name) 626 @ephemeral.last.include?(name) 627 end
Returns true if the variable of the given name has a non nil value. TODO: This has vague semantics - does the variable exist or not?
use ['name'] to get nil or value, and if nil check with exist?('name') this include? is only useful because of checking against the boolean value false.
# File lib/puppet/parser/scope.rb 272 def include?(name) 273 catch(:undefined_variable) { 274 return ! self[name].nil? 275 } 276 false 277 end
The class scope of the inherited thing of this scope's resource.
@return [Puppet::Parser::Scope] The scope or nil if there is not an inherited scope
# File lib/puppet/parser/scope.rb 560 def inherited_scope 561 if resource && resource.type == TYPENAME_CLASS && !resource.resource_type.parent.nil? 562 qualified_scope(resource.resource_type.parent) 563 else 564 nil 565 end 566 end
# File lib/puppet/parser/scope.rb 585 def is_classscope? 586 resource && resource.type == TYPENAME_CLASS 587 end
Check if the given value is a known default for the given type
# File lib/puppet/parser/scope.rb 457 def is_default?(type, key, value) 458 defaults_for_type = @defaults[type] 459 unless defaults_for_type.nil? 460 default_param = defaults_for_type[key] 461 return true if !default_param.nil? && value == default_param.value 462 end 463 !parent.nil? && parent.is_default?(type, key, value) 464 end
# File lib/puppet/parser/scope.rb 589 def is_nodescope? 590 resource && resource.type == TYPENAME_NODE 591 end
# File lib/puppet/parser/scope.rb 593 def is_topscope? 594 equal?(@compiler.topscope) 595 end
@api private
# File lib/puppet/parser/scope.rb 598 def lookup_qualified_variable(fqn, options) 599 table = @compiler.qualified_variables 600 val = table[fqn] 601 return val if !val.nil? || table.include?(fqn) 602 603 # not found - search inherited scope for class 604 leaf_index = fqn.rindex('::') 605 unless leaf_index.nil? 606 leaf_name = fqn[ (leaf_index+2)..-1 ] 607 class_name = fqn[ 0, leaf_index ] 608 begin 609 qs = qualified_scope(class_name) 610 unless qs.nil? 611 return qs.get_local_variable(leaf_name) if qs.has_local_variable?(leaf_name) 612 iscope = qs.inherited_scope 613 return lookup_qualified_variable("#{iscope.source.name}::#{leaf_name}", options) unless iscope.nil? 614 end 615 rescue RuntimeError => e 616 # because a failure to find the class, or inherited should be reported against given name 617 return handle_not_found(class_name, leaf_name, options, e.message) 618 end 619 end 620 # report with leading '::' by using empty class_name 621 return handle_not_found('', fqn, options) 622 end
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.
The lookupdefaults searches in the the order:
* inherited * contained (recursive) * self
# File lib/puppet/parser/scope.rb 434 def lookupdefaults(type) 435 values = {} 436 437 # first collect the values from the parents 438 if parent 439 parent.lookupdefaults(type).each { |var,value| 440 values[var] = value 441 } 442 end 443 444 # then override them with any current values 445 # this should probably be done differently 446 if @defaults.include?(type) 447 @defaults[type].each { |var,value| 448 values[var] = value 449 } 450 end 451 452 values 453 end
Look up a defined type.
# File lib/puppet/parser/scope.rb 467 def lookuptype(name) 468 # This happens a lot, avoid making a call to make a call 469 krt = environment.known_resource_types 470 krt.find_definition(name) || krt.find_hostclass(name) 471 end
Lookup a variable within this scope using the Puppet
language's scoping rules. Variables can be qualified using just as in a manifest.
@param [String] name the variable name to lookup @param [Hash] hash of options, only internal code should give this @param [Boolean] if resolution is of the leaf of a qualified name - only internal code should give this @return Object
the value of the variable, or if not found; nil if `strict_variables` is false, and thrown :undefined_variable otherwise
@api public
# File lib/puppet/parser/scope.rb 491 def lookupvar(name, options = EMPTY_HASH) 492 unless name.is_a? String 493 raise Puppet::ParseError, _("Scope variable name %{name} is a %{klass}, not a string") % { name: name.inspect, klass: name.class } 494 end 495 496 # If name has '::' in it, it is resolved as a qualified variable 497 unless (idx = name.index('::')).nil? 498 # Always drop leading '::' if present as that is how the values are keyed. 499 return lookup_qualified_variable(idx == 0 ? name[2..-1] : name, options) 500 end 501 502 # At this point, search is for a non qualified (simple) name 503 table = @ephemeral.last 504 val = table[name] 505 return val unless val.nil? && !table.include?(name) 506 507 next_scope = inherited_scope || enclosing_scope 508 if next_scope 509 next_scope.lookupvar(name, options) 510 else 511 variable_not_found(name) 512 end 513 end
Merge all settings for the given env_name into this scope @param env_name [Symbol] the name of the environment @param set_in_this_scope [Boolean] if the settings variables should also be set in this instance of scope
# File lib/puppet/parser/scope.rb 712 def merge_settings(env_name, set_in_this_scope=true) 713 settings = Puppet.settings 714 table = effective_symtable(false) 715 global_table = compiler.qualified_variables 716 all_local = {} 717 settings.each_key do |name| 718 next if :name == name 719 key = name.to_s 720 value = transform_setting(settings.value_sym(name, env_name)) 721 if set_in_this_scope 722 table[key] = value 723 end 724 all_local[key] = value 725 # also write the fqn into global table for direct lookup 726 global_table["settings::#{key}"] = value 727 end 728 # set the 'all_local' - a hash of all settings 729 global_table["settings::all_local"] = all_local 730 nil 731 end
# File lib/puppet/parser/scope.rb 1034 def method_missing(method, *args, &block) 1035 method.to_s =~ /^function_(.*)$/ 1036 name = $1 1037 super unless name 1038 super unless Puppet::Parser::Functions.function(name) 1039 # In odd circumstances, this might not end up defined by the previous 1040 # method, so we might as well be certain. 1041 if respond_to? method 1042 send(method, *args) 1043 else 1044 raise Puppet::DevError, _("Function %{name} not defined despite being loaded!") % { name: name } 1045 end 1046 end
TODO: Who calls this?
# File lib/puppet/parser/scope.rb 919 def new_ephemeral(local_scope = false) 920 if local_scope 921 @ephemeral.push(LocalScope.new(@ephemeral.last)) 922 else 923 @ephemeral.push(MatchScope.new(@ephemeral.last, nil)) 924 end 925 end
Nests a match data scope
# File lib/puppet/parser/scope.rb 997 def new_match_scope(match_data) 998 @ephemeral.push(MatchScope.new(@ephemeral.last, match_data)) 999 end
Create a new scope and set these options.
# File lib/puppet/parser/scope.rb 683 def newscope(options = {}) 684 compiler.newscope(self, options) 685 end
# File lib/puppet/parser/scope.rb 687 def parent_module_name 688 return nil unless @parent && @parent.source 689 @parent.source.module_name 690 end
Pop ephemeral scopes up to level and return them
@param level [Integer] a positive integer @return [Array] the removed ephemeral scopes @api private
# File lib/puppet/parser/scope.rb 903 def pop_ephemerals(level) 904 @ephemeral.pop(@ephemeral.size - level) 905 end
Push ephemeral scopes onto the ephemeral scope stack @param ephemeral_scopes [Array] @api private
# File lib/puppet/parser/scope.rb 910 def push_ephemerals(ephemeral_scopes) 911 ephemeral_scopes.each { |ephemeral_scope| @ephemeral.push(ephemeral_scope) } unless ephemeral_scopes.nil? 912 end
To be removed when enough time has passed after puppet 5.0.0 @api private
# File lib/puppet/parser/scope.rb 1050 def resolve_type_and_titles(type, titles) 1051 raise Puppet::DevError, _("Scope#resolve_type_and_title() is no longer supported, use Puppet::Pops::Evaluator::Runtime3ResourceSupport instead") 1052 end
# File lib/puppet/parser/scope.rb 810 def set_facts(hash) 811 setvar('facts', deep_freeze(hash), :privileged => true) 812 end
Sets match data in the most nested scope (which always is a MatchScope
), it clobbers match data already set there
# File lib/puppet/parser/scope.rb 992 def set_match_data(match_data) 993 @ephemeral.last.match_data = match_data 994 end
# File lib/puppet/parser/scope.rb 814 def set_server_facts(hash) 815 setvar('server_facts', deep_freeze(hash), :privileged => true) 816 end
# File lib/puppet/parser/scope.rb 806 def set_trusted(hash) 807 setvar('trusted', deep_freeze(hash), :privileged => true) 808 end
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.
It's preferred that you use self[]= instead of this; only use this
when you need to set options.
# File lib/puppet/parser/scope.rb 761 def setvar(name, value, options = EMPTY_HASH) 762 if name =~ /^[0-9]+$/ 763 raise Puppet::ParseError.new(_("Cannot assign to a numeric match result variable '$%{name}'") % { name: name }) # unless options[:ephemeral] 764 end 765 unless name.is_a? String 766 raise Puppet::ParseError, _("Scope variable name %{name} is a %{class_type}, not a string") % { name: name.inspect, class_type: name.class } 767 end 768 769 # Check for reserved variable names 770 if (name == VARNAME_TRUSTED || name == VARNAME_FACTS) && !options[:privileged] 771 raise Puppet::ParseError, _("Attempt to assign to a reserved variable name: '%{name}'") % { name: name } 772 end 773 774 # Check for server_facts reserved variable name 775 if name == VARNAME_SERVER_FACTS && !options[:privileged] 776 raise Puppet::ParseError, _("Attempt to assign to a reserved variable name: '%{name}'") % { name: name } 777 end 778 779 table = effective_symtable(options[:ephemeral]) 780 if table.bound?(name) 781 error = Puppet::ParseError.new(_("Cannot reassign variable '$%{name}'") % { name: name }) 782 error.file = options[:file] if options[:file] 783 error.line = options[:line] if options[:line] 784 raise error 785 end 786 787 table[name] = value 788 789 # Assign the qualified name in the environment 790 # Note that Settings scope has a source set to Boolean true. 791 # 792 # Only meaningful to set a fqn globally if table to assign to is the top of the scope's ephemeral stack 793 if @symtable.equal?(table) 794 if is_topscope? 795 # the scope name is '::' 796 compiler.qualified_variables[name] = value 797 elsif source.is_a?(Puppet::Resource::Type) && source.type == :hostclass 798 # the name is the name of the class 799 sourcename = source.name 800 compiler.qualified_variables["#{sourcename}::#{name}"] = value 801 end 802 end 803 value 804 end
Returns a Hash containing all variables and their values, optionally (and by default) including the values defined in parent. Local values shadow parent values. Ephemeral
scopes for match results ($0 - $n) are not included. Optionally include the variables that are explicitly set to `undef`.
# File lib/puppet/parser/scope.rb 667 def to_hash(recursive = true, include_undef = false) 668 if recursive and has_enclosing_scope? 669 target = enclosing_scope.to_hash(recursive) 670 if !(inherited = inherited_scope).nil? 671 target.merge!(inherited.to_hash(recursive)) 672 end 673 else 674 target = Hash.new 675 end 676 677 # add all local scopes 678 @ephemeral.last.add_entries_to(target, include_undef) 679 target 680 end
Used mainly for logging
# File lib/puppet/parser/scope.rb 873 def to_s 874 # As this is used for logging, this should really not be done in this class at all... 875 return "Scope(#{@resource})" unless @resource.nil? 876 877 # For logging of function-scope - it is now showing the file and line. 878 detail = Puppet::Pops::PuppetStack.top_of_stack 879 return "Scope()" if detail.empty? 880 881 # shorten the path if possible 882 path = detail[0] 883 env_path = nil 884 env_path = environment.configuration.path_to_env unless (environment.nil? || environment.configuration.nil?) 885 # check module paths first since they may be in the environment (i.e. they are longer) 886 module_path = environment.full_modulepath.detect {|m_path| path.start_with?(m_path) } 887 if module_path 888 path = "<module>" + path[module_path.length..-1] 889 elsif env_path && path && path.start_with?(env_path) 890 path = "<env>" + path[env_path.length..-1] 891 end 892 # Make the output appear as "Scope(path, line)" 893 "Scope(#{[path, detail[1]].join(', ')})" 894 end
Transforms references to classes to the form suitable for lookup in the compiler.
Makes names passed in the names array absolute if they are relative.
Transforms Class[] and Resource[] type references to class name or raises an error if a Class[] is unspecific, if a Resource is not a 'class' resource, or if unspecific (no title).
@param names [Array<String>] names to (optionally) make absolute @return [Array<String>] names after transformation
# File lib/puppet/parser/scope.rb 1067 def transform_and_assert_classnames(names) 1068 names.map do |name| 1069 case name 1070 when NilClass 1071 raise ArgumentError, _("Cannot use undef as a class name") 1072 when String 1073 raise ArgumentError, _("Cannot use empty string as a class name") if name.empty? 1074 name.sub(/^([^:]{1,2})/, '::\1') 1075 1076 when Puppet::Resource 1077 assert_class_and_title(name.type, name.title) 1078 name.title.sub(/^([^:]{1,2})/, '::\1') 1079 1080 when Puppet::Pops::Types::PClassType 1081 #TRANSLATORS "Class" and "Type" are Puppet keywords and should not be translated 1082 raise ArgumentError, _("Cannot use an unspecific Class[] Type") unless name.class_name 1083 name.class_name.sub(/^([^:]{1,2})/, '::\1') 1084 1085 when Puppet::Pops::Types::PResourceType 1086 assert_class_and_title(name.type_name, name.title) 1087 name.title.sub(/^([^:]{1,2})/, '::\1') 1088 end.downcase 1089 end 1090 end
# File lib/puppet/parser/scope.rb 473 def undef_as(x,v) 474 if v.nil? or v == :undef 475 x 476 else 477 v 478 end 479 end
# File lib/puppet/parser/scope.rb 522 def variable_not_found(name, reason=nil) 523 # Built in variables and numeric variables always exist 524 if BUILT_IN_VARS.include?(name) || name =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME 525 return nil 526 end 527 begin 528 throw(:undefined_variable, reason) 529 rescue UNCAUGHT_THROW_EXCEPTION 530 case Puppet[:strict] 531 when :off 532 # do nothing 533 when :warning 534 Puppet.warn_once(UNDEFINED_VARIABLES_KIND, _("Variable: %{name}") % { name: name }, 535 _("Undefined variable '%{name}'; %{reason}") % { name: name, reason: reason } ) 536 when :error 537 raise ArgumentError, _("Undefined variable '%{name}'; %{reason}") % { name: name, reason: reason } 538 end 539 end 540 nil 541 end
Execute given block in global scope with no ephemerals present
@yieldparam [Scope] global_scope the global and ephemeral less scope @return [Object] the return of the block
@api private
# File lib/puppet/parser/scope.rb 933 def with_global_scope(&block) 934 find_global_scope.without_ephemeral_scopes(&block) 935 end
Execute given block and ensure that ephemeral level is restored
@return [Object] the return of the block
@api private
# File lib/puppet/parser/scope.rb 981 def with_guarded_scope 982 elevel = ephemeral_level 983 begin 984 yield 985 ensure 986 pop_ephemerals(elevel) 987 end 988 end
Execute given block with a ephemeral scope containing the given variables @api private
# File lib/puppet/parser/scope.rb 939 def with_local_scope(scope_variables) 940 local = LocalScope.new(@ephemeral.last) 941 scope_variables.each_pair { |k, v| local[k] = v } 942 @ephemeral.push(local) 943 begin 944 yield(self) 945 ensure 946 @ephemeral.pop 947 end 948 end
Nests a parameter scope @param [String] callee_name the name of the function, template, or resource that defines the parameters @param [Array<String>] param_names list of parameter names @yieldparam [ParameterScope] param_scope the nested scope @api private
# File lib/puppet/parser/scope.rb 968 def with_parameter_scope(callee_name, param_names) 969 param_scope = ParameterScope.new(@ephemeral.last, callee_name, param_names) 970 with_guarded_scope do 971 @ephemeral.push(param_scope) 972 yield(param_scope) 973 end 974 end
Execute given block with all ephemeral popped from the ephemeral stack
@api private
# File lib/puppet/parser/scope.rb 953 def without_ephemeral_scopes 954 save_ephemeral = @ephemeral 955 begin 956 @ephemeral = [ @symtable ] 957 yield(self) 958 ensure 959 @ephemeral = save_ephemeral 960 end 961 end
Private Instance Methods
# File lib/puppet/parser/scope.rb 1106 def assert_class_and_title(type_name, title) 1107 if type_name.nil? || type_name == '' 1108 #TRANSLATORS "Resource" is a class name and should not be translated 1109 raise ArgumentError, _("Cannot use an unspecific Resource[] where a Resource['class', name] is expected") 1110 end 1111 unless type_name =~ /^[Cc]lass$/ 1112 #TRANSLATORS "Resource" is a class name and should not be translated 1113 raise ArgumentError, _("Cannot use a Resource[%{type_name}] where a Resource['class', name] is expected") % { type_name: type_name } 1114 end 1115 if title.nil? 1116 #TRANSLATORS "Resource" is a class name and should not be translated 1117 raise ArgumentError, _("Cannot use an unspecific Resource['class'] where a Resource['class', name] is expected") 1118 end 1119 end
Deeply freezes the given object. The object and its content must be of the types: Array, Hash, Numeric, Boolean, Regexp, NilClass, or String. All other types raises an Error. (i.e. if they are assignable to Puppet::Pops::Types::Data type).
# File lib/puppet/parser/scope.rb 822 def deep_freeze(object) 823 case object 824 when Array 825 object.each {|v| deep_freeze(v) } 826 object.freeze 827 when Hash 828 object.each {|k, v| deep_freeze(k); deep_freeze(v) } 829 object.freeze 830 when NilClass, Numeric, TrueClass, FalseClass 831 # do nothing 832 when String 833 object.freeze 834 else 835 raise Puppet::Error, _("Unsupported data type: '%{klass}'") % { klass: object.class } 836 end 837 object 838 end
# File lib/puppet/parser/scope.rb 1121 def extend_with_functions_module 1122 root = Puppet.lookup(:root_environment) 1123 extend Puppet::Parser::Functions.environment_module(root) 1124 extend Puppet::Parser::Functions.environment_module(environment) if environment != root 1125 end
# File lib/puppet/parser/scope.rb 648 def has_enclosing_scope? 649 ! parent.nil? 650 end
# File lib/puppet/parser/scope.rb 653 def qualified_scope(classname) 654 klass = find_hostclass(classname) 655 raise _("class %{classname} could not be found") % { classname: classname } unless klass 656 kscope = class_scope(klass) 657 raise _("class %{classname} has not been evaluated") % { classname: classname } unless kscope 658 kscope 659 end
# File lib/puppet/parser/scope.rb 733 def transform_setting(val) 734 if val.is_a?(String) || val.is_a?(Numeric) || true == val || false == val || nil == val 735 val 736 elsif val.is_a?(Array) 737 val.map {|entry| transform_setting(entry) } 738 elsif val.is_a?(Hash) 739 result = {} 740 val.each {|k,v| result[transform_setting(k)] = transform_setting(v) } 741 result 742 else 743 # not ideal, but required as there are settings values that are special 744 :undef == val ? nil : val.to_s 745 end 746 end