Class: Puppet::Pops::Lookup::LookupAdapter Private

Inherits:
DataAdapter show all
Defined in:
lib/puppet/pops/lookup/lookup_adapter.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Constant Summary collapse

LOOKUP_OPTIONS_PREFIX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

LOOKUP_OPTIONS + '.'
LOOKUP_OPTIONS_PATTERN_START =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'^'.freeze
HASH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'hash'.freeze
MERGE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'merge'.freeze
CONVERT_TO =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'convert_to'.freeze
NEW =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'new'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from DataAdapter

#[], #[]=, #include?

Methods inherited from Adaptable::Adapter

adapt, adapt_new, associate_adapter, clear, get, instance_var_name, self_attr_name, type_name

Constructor Details

#initialize(compiler) ⇒ LookupAdapter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of LookupAdapter.



26
27
28
29
30
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 26

def initialize(compiler)
  super()
  @compiler = compiler
  @lookup_options = {}
end

Class Method Details

.create_adapter(compiler) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



22
23
24
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 22

def self.create_adapter(compiler)
  new(compiler)
end

Instance Method Details

#convert_result(key, lookup_options, lookup_invocation, the_lookup) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Performs a possible conversion of the result of calling ‘the_lookup` lambda The conversion takes place if there is a ’convert_to’ key in the lookup_options If there is no conversion, the result of calling ‘the_lookup` is returned otherwise the successfully converted value. Errors are raised if the convert_to is faulty (bad type string, or if a call to new(T, <args>) fails.

Parameters:

  • key (String)

    The key to lookup

  • lookup_options (Hash)

    a hash of options

  • lookup_invocation (Invocation)

    the lookup invocation

  • the_lookup (Lambda)

    zero arg lambda that performs the lookup of a value

Returns:

  • (Object)

    the looked up value, or converted value if there was conversion



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 90

def convert_result(key, lookup_options, lookup_invocation, the_lookup)
  result = the_lookup.call
  convert_to = lookup_options[CONVERT_TO]
  return result if convert_to.nil?

  convert_to = convert_to.is_a?(Array) ? convert_to : [convert_to]
  if convert_to[0].is_a?(String)
    begin
      convert_to[0] = Puppet::Pops::Types::TypeParser.singleton.parse(convert_to[0])
    rescue StandardError => e
      raise Puppet::DataBinding::LookupError,
        _("Invalid data type in lookup_options for key '%{key}' could not parse '%{source}', error: '%{msg}") %
          { key: key, source: convert_to[0], msg: e.message}
    end
  end
  begin
    result = lookup_invocation.scope.call_function(NEW, [convert_to[0], result, *convert_to[1..-1]])
    # TRANSLATORS 'lookup_options', 'convert_to' and args_string variable should not be translated,
    args_string = Puppet::Pops::Types::StringConverter.singleton.convert(convert_to)
    lookup_invocation.report_text { _("Applying convert_to lookup_option with arguments %{args}") % { args: args_string } }
  rescue StandardError => e
    raise Puppet::DataBinding::LookupError,
      _("The convert_to lookup_option for key '%{key}' raised error: %{msg}") %
        { key: key, msg: e.message}
  end
  result
end

#extract_lookup_options_for_key(key, options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 238

def extract_lookup_options_for_key(key, options)
  return nil if options.nil?

  rk = key.root_key
  key_opts = options[0]
  unless key_opts.nil?
    key_opt = key_opts[rk]
    return key_opt unless key_opt.nil?
  end

  patterns = options[1]
  patterns.each_pair { |pattern, value| return value if pattern =~ rk } unless patterns.nil?
  nil
end

#global_hiera_config_pathPathname

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the full path of the hiera.yaml config file.

Returns:

  • (Pathname)

    the full path of the hiera.yaml config file



261
262
263
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 261

def global_hiera_config_path
  @global_hiera_config_path ||= Pathname.new(Puppet.settings[:hiera_config])
end

#global_only?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


272
273
274
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 272

def global_only?
  instance_variable_defined?(:@global_only) ? @global_only : false
end

#has_environment_data_provider?(lookup_invocation) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns ‘true` if an environment data provider version 5 is configured.

Parameters:

Returns:

  • (Boolean)

    ‘true` if an environment data provider version 5 is configured



255
256
257
258
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 255

def has_environment_data_provider?(lookup_invocation)
  ep = env_provider(lookup_invocation)
  ep.nil? ? false : ep.config(lookup_invocation).version >= 5
end

#lookup(key, lookup_invocation, merge) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Performs a lookup using global, environment, and module data providers. Merge the result using the given merge strategy. If the merge strategy is nil, then an attempt is made to find merge options in the ‘lookup_options` hash for an entry associated with the key. If no options are found, the no merge is performed and the first found entry is returned.

Parameters:

  • key (String)

    The key to lookup

  • lookup_invocation (Invocation)

    the lookup invocation

  • merge (MergeStrategy, String, Hash{String => Object}, nil)

    Merge strategy, merge strategy name, strategy and options hash, or nil (implies “first found”)

Returns:

  • (Object)

    the found object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 43

def lookup(key, lookup_invocation, merge)
  # The 'lookup_options' key is reserved and not found as normal data
  if key == LOOKUP_OPTIONS || key.start_with?(LOOKUP_OPTIONS_PREFIX)
    lookup_invocation.with(:invalid_key, LOOKUP_OPTIONS) do
      throw :no_such_key
    end
  end

  key = LookupKey.new(key)
  lookup_invocation.lookup(key, key.module_name) do
    if lookup_invocation.only_explain_options?
      catch(:no_such_key) { do_lookup(LookupKey::LOOKUP_OPTIONS, lookup_invocation, HASH) }
      nil
    else
      lookup_options = lookup_lookup_options(key, lookup_invocation) || {}

      if merge.nil?
        # Used cached lookup_options
        # merge = lookup_merge_options(key, lookup_invocation)
        merge = lookup_options[MERGE]
        lookup_invocation.report_merge_source(LOOKUP_OPTIONS) unless merge.nil?
      end
      convert_result(key.to_s, lookup_options, lookup_invocation, lambda do
        lookup_invocation.with(:data, key.to_s) do
          catch(:no_such_key) { return do_lookup(key, lookup_invocation, merge) }
          throw :no_such_key if lookup_invocation.global_only?
          key.dig(lookup_invocation, lookup_default_in_module(key, lookup_invocation))
        end
      end)
    end
  end
end

#lookup_default_in_module(key, lookup_invocation) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



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
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 171

def lookup_default_in_module(key, lookup_invocation)
  module_name = lookup_invocation.module_name

  # Do not attempt to do a lookup in a module unless the name is qualified.
  throw :no_such_key if module_name.nil?

  provider = module_provider(lookup_invocation, module_name)
  throw :no_such_key if provider.nil? || !provider.config(lookup_invocation).has_default_hierarchy?

  lookup_invocation.with(:scope, "Searching default_hierarchy of module \"#{module_name}\"") do
    merge_strategy = nil
    if merge_strategy.nil?
      @module_default_lookup_options ||= {}
      options = @module_default_lookup_options.fetch(module_name) do |k|
        meta_invocation = Invocation.new(lookup_invocation.scope)
        meta_invocation.lookup(LookupKey::LOOKUP_OPTIONS, k) do
          opts = nil
          lookup_invocation.with(:scope, "Searching for \"#{LookupKey::LOOKUP_OPTIONS}\"") do
            catch(:no_such_key) do
            opts = compile_patterns(
              validate_lookup_options(
                provider.key_lookup_in_default(LookupKey::LOOKUP_OPTIONS, meta_invocation, MergeStrategy.strategy(HASH)), k))
            end
          end
          @module_default_lookup_options[k] = opts
        end
      end
      lookup_options = extract_lookup_options_for_key(key, options)
      merge_strategy = lookup_options[MERGE] unless lookup_options.nil?
    end

    lookup_invocation.with(:scope, "Searching for \"#{key}\"") do
      provider.key_lookup_in_default(key, lookup_invocation, merge_strategy)
    end
  end
end

#lookup_global(key, lookup_invocation, merge_strategy) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



118
119
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
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 118

def lookup_global(key, lookup_invocation, merge_strategy)
  # hiera_xxx will always use global_provider regardless of data_binding_terminus setting
  terminus = lookup_invocation.hiera_xxx_call? ? :hiera : Puppet[:data_binding_terminus]
  case terminus
  when :hiera, 'hiera'
    provider = global_provider(lookup_invocation)
    throw :no_such_key if provider.nil?
    provider.key_lookup(key, lookup_invocation, merge_strategy)
  when :none, 'none', '', nil
    # If global lookup is disabled, immediately report as not found
    lookup_invocation.report_not_found(key)
    throw :no_such_key
  else
    lookup_invocation.with(:global, terminus) do
      catch(:no_such_key) do
        return lookup_invocation.report_found(key, Puppet::DataBinding.indirection.find(key.root_key,
          {:environment => environment, :variables => lookup_invocation.scope, :merge => merge_strategy}))
      end
      lookup_invocation.report_not_found(key)
      throw :no_such_key
    end
  end
rescue Puppet::DataBinding::LookupError => detail
  raise detail unless detail.issue_code.nil?
  error = Puppet::Error.new(_("Lookup of key '%{key}' failed: %{detail}") % { key: lookup_invocation.top_key, detail: detail.message })
  error.set_backtrace(detail.backtrace)
  raise error
end

#lookup_in_environment(key, lookup_invocation, merge_strategy) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



147
148
149
150
151
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 147

def lookup_in_environment(key, lookup_invocation, merge_strategy)
  provider = env_provider(lookup_invocation)
  throw :no_such_key if provider.nil?
  provider.key_lookup(key, lookup_invocation, merge_strategy)
end

#lookup_in_module(key, lookup_invocation, merge_strategy) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 153

def lookup_in_module(key, lookup_invocation, merge_strategy)
  module_name = lookup_invocation.module_name

  # Do not attempt to do a lookup in a module unless the name is qualified.
  throw :no_such_key if module_name.nil?

  provider = module_provider(lookup_invocation, module_name)
  if provider.nil?
    if environment.module(module_name).nil?
      lookup_invocation.report_module_not_found(module_name)
    else
      lookup_invocation.report_module_provider_not_found(module_name)
    end
    throw :no_such_key
  end
  provider.key_lookup(key, lookup_invocation, merge_strategy)
end

#lookup_lookup_options(key, lookup_invocation) ⇒ String, ...

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retrieve the lookup options that match the given ‘name`.

Parameters:

Returns:

  • (String, Hash, nil)

    The found lookup options or nil



225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 225

def lookup_lookup_options(key, lookup_invocation)
  module_name = key.module_name

  # Retrieve the options for the module. We use nil as a key in case we have no module
  if !@lookup_options.include?(module_name)
    options = retrieve_lookup_options(module_name, lookup_invocation, MergeStrategy.strategy(HASH))
    @lookup_options[module_name] = options
  else
    options = @lookup_options[module_name]
  end
  extract_lookup_options_for_key(key, options)
end

#lookup_merge_options(key, lookup_invocation) ⇒ String, ...

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retrieve the merge options that match the given ‘name`.

Parameters:

  • key (LookupKey)

    The key for which we want merge options

  • lookup_invocation (Invocation)

    the lookup invocation

Returns:

  • (String, Hash, nil)

    The found merge options or nil



214
215
216
217
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 214

def lookup_merge_options(key, lookup_invocation)
  lookup_options = lookup_lookup_options(key, lookup_invocation)
  lookup_options.nil? ? nil : lookup_options[MERGE]
end

#set_global_hiera_config_path(path) ⇒ LookupAdapter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns self.

Parameters:

  • path (String)

    the absolute path name of the global hiera.yaml file.

Returns:



267
268
269
270
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 267

def set_global_hiera_config_path(path)
  @global_hiera_config_path = Pathname.new(path)
  self
end

#set_global_onlyLookupAdapter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Instructs the lookup framework to only perform lookups in the global layer

Returns:



278
279
280
281
# File 'lib/puppet/pops/lookup/lookup_adapter.rb', line 278

def set_global_only
  @global_only = true
  self
end