module Puppet::Pops::Lookup::Interpolation
Adds support for interpolation expressions. The expressions may contain keys that uses dot-notation to further navigate into hashes and arrays
@api public
Constants
- EMPTY_INTERPOLATIONS
- QUOTED_KEY
Matches a key that is quoted using a matching pair of either single or double quotes.
Public Instance Methods
interpolate(value, context, allow_methods)
click to toggle source
@param value [Object] The value to interpolate @param context [Context] The current lookup context @param allow_methods [Boolean] `true` if interpolation expression that contains lookup methods are allowed @return [Object] the result of resolving all interpolations in the given value @api public
# File lib/puppet/pops/lookup/interpolation.rb 17 def interpolate(value, context, allow_methods) 18 case value 19 when String 20 value.index('%{').nil? ? value : interpolate_string(value, context, allow_methods) 21 when Array 22 value.map { |element| interpolate(element, context, allow_methods) } 23 when Hash 24 result = {} 25 value.each_pair { |k, v| result[interpolate(k, context, allow_methods)] = interpolate(v, context, allow_methods) } 26 result 27 else 28 value 29 end 30 end
Private Instance Methods
fail(issue, args = EMPTY_HASH)
click to toggle source
# File lib/puppet/pops/lookup/interpolation.rb 149 def fail(issue, args = EMPTY_HASH) 150 raise Puppet::DataBinding::LookupError.new( 151 issue.format(args), nil, nil, nil, nil, issue.issue_code) 152 end
get_method_and_data(data, allow_methods)
click to toggle source
# File lib/puppet/pops/lookup/interpolation.rb 137 def get_method_and_data(data, allow_methods) 138 match = data.match(/^(\w+)\((?:["]([^"]+)["]|[']([^']+)['])\)$/) 139 if match 140 fail(Issues::HIERA_INTERPOLATION_METHOD_SYNTAX_NOT_ALLOWED) unless allow_methods 141 key = match[1].to_sym 142 data = match[2] || match[3] # double or single qouted 143 else 144 key = :scope 145 end 146 [key, data] 147 end
interpolate_method(method_key)
click to toggle source
# File lib/puppet/pops/lookup/interpolation.rb 72 def interpolate_method(method_key) 73 @@interpolate_methods ||= begin 74 global_lookup = lambda do |key, lookup_invocation, _| 75 scope = lookup_invocation.scope 76 if scope.is_a?(Hiera::Scope) && !lookup_invocation.global_only? 77 # "unwrap" the Hiera::Scope 78 scope = scope.real 79 end 80 lookup_invocation.with_scope(scope) do |sub_invocation| 81 sub_invocation.lookup(key) { Lookup.lookup(key, nil, '', true, nil, sub_invocation) } 82 end 83 end 84 scope_lookup = lambda do |key, lookup_invocation, subject| 85 segments = split_key(key) { |problem| Puppet::DataBinding::LookupError.new("#{problem} in string: #{subject}") } 86 root_key = segments.shift 87 value = lookup_invocation.with(:scope, 'Global Scope') do 88 ovr = lookup_invocation.override_values 89 if ovr.include?(root_key) 90 lookup_invocation.report_found_in_overrides(root_key, ovr[root_key]) 91 else 92 scope = lookup_invocation.scope 93 val = scope[root_key] 94 if val.nil? && !nil_in_scope?(scope, root_key) 95 defaults = lookup_invocation.default_values 96 if defaults.include?(root_key) 97 lookup_invocation.report_found_in_defaults(root_key, defaults[root_key]) 98 else 99 nil 100 end 101 else 102 lookup_invocation.report_found(root_key, val) 103 end 104 end 105 end 106 unless value.nil? || segments.empty? 107 found = nil; 108 catch(:no_such_key) { found = sub_lookup(key, lookup_invocation, segments, value) } 109 value = found; 110 end 111 lookup_invocation.remember_scope_lookup(key, root_key, segments, value) 112 value 113 end 114 115 { 116 :lookup => global_lookup, 117 :hiera => global_lookup, # this is just an alias for 'lookup' 118 :alias => global_lookup, # same as 'lookup' but expression must be entire string and result is not subject to string substitution 119 :scope => scope_lookup, 120 :literal => lambda { |key, _, _| key } 121 }.freeze 122 end 123 interpolate_method = @@interpolate_methods[method_key] 124 fail(Issues::HIERA_INTERPOLATION_UNKNOWN_INTERPOLATION_METHOD, :name => method_key) unless interpolate_method 125 interpolate_method 126 end
interpolate_string(subject, context, allow_methods)
click to toggle source
# File lib/puppet/pops/lookup/interpolation.rb 46 def interpolate_string(subject, context, allow_methods) 47 lookup_invocation = context.is_a?(Invocation) ? context : context.invocation 48 lookup_invocation.with(:interpolate, subject) do 49 subject.gsub(/%\{([^\}]*)\}/) do |match| 50 expr = $1 51 # Leading and trailing spaces inside an interpolation expression are insignificant 52 expr.strip! 53 value = nil 54 unless EMPTY_INTERPOLATIONS[expr] 55 method_key, key = get_method_and_data(expr, allow_methods) 56 is_alias = method_key == :alias 57 58 # Alias is only permitted if the entire string is equal to the interpolate expression 59 fail(Issues::HIERA_INTERPOLATION_ALIAS_NOT_ENTIRE_STRING) if is_alias && subject != match 60 value = interpolate_method(method_key).call(key, lookup_invocation, subject) 61 62 # break gsub and return value immediately if this was an alias substitution. The value might be something other than a String 63 return value if is_alias 64 65 value = lookup_invocation.check(method_key == :scope ? "scope:#{key}" : key) { interpolate(value, lookup_invocation, allow_methods) } 66 end 67 value.nil? ? '' : value 68 end 69 end 70 end
nil_in_scope?(scope, key)
click to toggle source
Because the semantics of Puppet::Parser::Scope#include?
differs from Hash#include?
# File lib/puppet/pops/lookup/interpolation.rb 129 def nil_in_scope?(scope, key) 130 if scope.is_a?(Hash) 131 scope.include?(key) 132 else 133 scope.exist?(key) 134 end 135 end