Class: Puppet::Pops::Binder::Lookup

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/pops/binder/lookup.rb

Overview

This class is the backing implementation of the Puppet function ‘lookup’. See puppet/parser/functions/lookup.rb for documentation.

Defined Under Namespace

Classes: PrivateNotFoundMarker

Class Method Summary collapse

Class Method Details

.lookup(scope, args) ⇒ Object

Parameters:

  • args (Array)

    array following the puppet function call conventions



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/puppet/pops/binder/lookup.rb', line 159

def self.lookup(scope, args)
  type_calculator = Puppet::Pops::Types::TypeCalculator.new
  options = parse_lookup_args(args)
  validate_options(options, type_calculator)
  names = [options[:name]].flatten
  type = options[:type]

  result_with_name = names.reduce([]) do |memo, name|
    break memo if !memo[1].nil?
    [name, search_for(scope, type, name, options)]
  end

  result = if result_with_name[1].nil?
    # not found, use default (which may be nil), the default is already type checked
    options[:default]
  else
    # injector.lookup is type-safe already do no need to type check the result
    result_with_name[1]
  end

  # If a block is given it is called with :undef passed as 'nil' since the lookup function
  # is available from 3x with --binder turned on, and the evaluation is always 4x.
  # TODO PUPPET4: Simply pass the value
  #
  result = if pblock = options[:pblock]
    result2 = case pblock.parameter_count
    when 1
      pblock.call(undef_as_nil(result))
    when 2
      pblock.call(result_with_name[ 0 ], undef_as_nil(result))
    else
      pblock.call(result_with_name[ 0 ], undef_as_nil(result), undef_as_nil(options[ :default ]))
    end

    # if the given result was returned, there is no need to type-check it again
    if !result2.equal?(result)
      t = type_calculator.infer(undef_as_nil(result2))
      if !type_calculator.assignable?(type, t)
        fail "the value produced by the given code block #{type_mismatch(type_calculator, type, t)}"
      end
    end
    result2
  else
    result
  end

  # Finally, the result if nil must be acceptable or an error is raised
  if is_nil_or_undef?(result) && !options[:accept_undef]
    fail_lookup(names)
  else
    # Since the function may be used without future parser being in effect, nil is not handled in a good
    # way, and should instead be turned into :undef.
    # TODO PUPPET4: Simply return the result
    #
    Puppet.future_parser? ? result : nil_as_undef(result)
  end
end

.parse_lookup_args(args) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/puppet/pops/binder/lookup.rb', line 6

def self.parse_lookup_args(args)
  options = {}
  pblock = if args[-1].respond_to?(:puppet_lambda)
    args.pop
  end

  case args.size
  when 1
    # name, or all options
    if args[ 0 ].is_a?(Hash)
      options = to_symbolic_hash(args[ 0 ])
    else
      options[ :name ] = args[ 0 ]
    end

  when 2
    # name and type, or name and options
    if args[ 1 ].is_a?(Hash)
      options = to_symbolic_hash(args[ 1 ])
      options[:name] = args[ 0 ] # silently overwrite option with given name
    else
      options[:name] = args[ 0 ]
      options[:type] = args[ 1 ]
    end

  when 3
    # name, type, default (no options)
    options[ :name ] = args[ 0 ]
    options[ :type ] = args[ 1 ]
    options[ :default ] = args[ 2 ]
  else
    raise Puppet::ParseError, "The lookup function accepts 1-3 arguments, got #{args.size}"
  end
  options[:pblock] = pblock
  options
end