Module: Puppet::Pops::Lookup::SubLookup

Included in:
DataHashFunctionProvider, Interpolation, LookupKey
Defined in:
lib/puppet/pops/lookup/sub_lookup.rb

Constant Summary collapse

SPECIAL =
/['"\.]/

Instance Method Summary collapse

Instance Method Details

#split_key(key) {|problem| ... } ⇒ Array<String>

Split key into segments. A segment may be a quoted string (both single and double quotes can be used) and the segment separator is the ‘.’ character. Whitespace will be trimmed off on both sides of each segment. Whitespace within quotes are not trimmed.

If the key cannot be parsed, this method will yield a string describing the problem to a one parameter block. The block must return an exception instance.

Parameters:

  • key (String)

    the string to split

Yield Parameters:

  • problem (String)

    the problem, i.e. ‘Syntax error’

Yield Returns:

  • (Exception)

    the exception to raise

Returns:

  • (Array<String>)

    the array of segments



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/puppet/pops/lookup/sub_lookup.rb', line 19

def split_key(key)
  return [key] if key.match(SPECIAL).nil?
  segments = key.split(/(\s*"[^"]+"\s*|\s*'[^']+'\s*|[^'".]+)/)
  if segments.empty?
    # Only happens if the original key was an empty string
    raise yield('Syntax error')
  elsif segments.shift == ''
    count = segments.size
    raise yield('Syntax error') unless count > 0

    segments.keep_if { |seg| seg != '.' }
    raise yield('Syntax error') unless segments.size * 2 == count + 1
    segments.map! do |segment|
      segment.strip!
      if segment.start_with?('"') || segment.start_with?("'")
        segment[1..-2]
      elsif segment =~ /^(:?[+-]?[0-9]+)$/
        segment.to_i
      else
        segment
      end
    end
  else
    raise yield('Syntax error')
  end
end

#sub_lookup(key, context, segments, value) ⇒ Object

Perform a sub-lookup using the given segments to access the given value. Each segment must be a string. A string consisting entirely of digits will be treated as an indexed lookup which means that the value that it is applied to must be an array. Other types of segments will expect that the given value is something other than a String that implements the ‘#[]’ method.

Parameters:

  • key (String)

    the original key (only used for error messages)

  • context (Context)

    The current lookup context

  • segments (Array<String>)

    the segments to use for lookup

  • value (Object)

    the value to access using the segments

Returns:

  • (Object)

    the value obtained when accessing the value



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/puppet/pops/lookup/sub_lookup.rb', line 58

def sub_lookup(key, context, segments, value)
  lookup_invocation = context.is_a?(Invocation) ? context : context.invocation
  lookup_invocation.with(:sub_lookup, segments) do
    segments.each do |segment|
      lookup_invocation.with(:segment, segment) do
        if value.nil?
          lookup_invocation.report_not_found(segment)
          throw :no_such_key
        end
        if segment.is_a?(Integer) && value.instance_of?(Array)
          unless segment >= 0 && segment < value.size
            lookup_invocation.report_not_found(segment)
            throw :no_such_key
          end
        else
          unless value.respond_to?(:'[]') && !(value.is_a?(Array) || value.instance_of?(String))
            raise Puppet::DataBinding::LookupError,
              _("Data Provider type mismatch: Got %{klass} when a hash-like object was expected to access value using '%{segment}' from key '%{key}'") %
                { klass: value.class.name, segment: segment, key: key }
          end
          unless value.include?(segment)
            lookup_invocation.report_not_found(segment)
            throw :no_such_key
          end
        end
        value = value[segment]
        lookup_invocation.report_found(segment, value)
      end
    end
    value
  end
end