Class: Puppet::Pops::Lookup::HieraConfig Private

Inherits:
Object
  • Object
show all
Includes:
Puppet::Pops::LabelProvider, LocationResolver
Defined in:
lib/puppet/pops/lookup/hiera_config.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.

Direct Known Subclasses

HieraConfigV3, HieraConfigV4, HieraConfigV5

Constant Summary collapse

CONFIG_FILE_NAME =

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.

'hiera.yaml'
KEY_NAME =

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.

'name'.freeze
KEY_VERSION =

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.

'version'.freeze
KEY_DATADIR =

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.

'datadir'.freeze
KEY_HIERARCHY =

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.

'hierarchy'.freeze
KEY_LOGGER =

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.

'logger'.freeze
KEY_OPTIONS =

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.

'options'.freeze
KEY_PATH =

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.

'path'.freeze
KEY_PATHS =

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.

'paths'.freeze
KEY_GLOB =

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.

'glob'.freeze
KEY_GLOBS =

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.

'globs'.freeze
KEY_URI =

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.

'uri'.freeze
KEY_URIS =

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.

'uris'.freeze
KEY_DEFAULTS =

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.

'defaults'.freeze
KEY_DATA_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.

DataHashFunctionProvider::TAG
KEY_LOOKUP_KEY =

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.

LookupKeyFunctionProvider::TAG
KEY_DATA_DIG =

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.

DataDigFunctionProvider::TAG
KEY_V3_DATA_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.

V3DataHashFunctionProvider::TAG
KEY_V3_LOOKUP_KEY =

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.

V3LookupKeyFunctionProvider::TAG
KEY_V3_BACKEND =

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.

V3BackendFunctionProvider::TAG
KEY_V4_DATA_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.

V4DataHashFunctionProvider::TAG
KEY_BACKEND =

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.

'backend'.freeze
KEY_EXTENSION =

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.

'extension'.freeze
FUNCTION_KEYS =

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.

[KEY_DATA_HASH, KEY_LOOKUP_KEY, KEY_DATA_DIG, KEY_V3_BACKEND]
ALL_FUNCTION_KEYS =

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.

FUNCTION_KEYS + [KEY_V4_DATA_HASH]
LOCATION_KEYS =

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.

[KEY_PATH, KEY_PATHS, KEY_GLOB, KEY_GLOBS, KEY_URI, KEY_URIS]
FUNCTION_PROVIDERS =

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.

{
  KEY_DATA_HASH => DataHashFunctionProvider,
  KEY_DATA_DIG => DataDigFunctionProvider,
  KEY_LOOKUP_KEY => LookupKeyFunctionProvider,
  KEY_V3_DATA_HASH => V3DataHashFunctionProvider,
  KEY_V3_BACKEND => V3BackendFunctionProvider,
  KEY_V3_LOOKUP_KEY => V3LookupKeyFunctionProvider,
  KEY_V4_DATA_HASH => V4DataHashFunctionProvider
}

Constants included from Puppet::Pops::LabelProvider

Puppet::Pops::LabelProvider::A, Puppet::Pops::LabelProvider::AN, Puppet::Pops::LabelProvider::SKIPPED_CHARACTERS, Puppet::Pops::LabelProvider::VOWELS

Constants included from SubLookup

SubLookup::SPECIAL

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Puppet::Pops::LabelProvider

#a_an, #a_an_uc, #article, #combine_strings, #label, #plural_s, #the, #the_uc

Methods included from LocationResolver

#expand_globs, #expand_uris, #resolve_paths

Methods included from Interpolation

#interpolate

Methods included from SubLookup

#split_key, #sub_lookup

Constructor Details

#initialize(config_root, config_path, loaded_config) ⇒ HieraConfig

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.

Creates a new HieraConfig from the given config_root. This is where the ‘lookup.yaml’ is expected to be found and is also the base location used when resolving relative paths.

Parameters:

  • config_path (Pathname)

    Absolute path to the configuration

  • loaded_config (Hash)

    the loaded configuration



157
158
159
160
161
162
163
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 157

def initialize(config_root, config_path, loaded_config)
  @config_root = config_root
  @config_path = config_path
  @loaded_config = loaded_config
  @config = validate_config(self.class.symkeys_to_string(@loaded_config))
  @data_providers = nil
end

Instance Attribute Details

#config_pathObject (readonly)

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.



150
151
152
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 150

def config_path
  @config_path
end

#versionObject (readonly)

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.



150
151
152
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 150

def version
  @version
end

Class Method Details

.config_exist?(config_root) ⇒ 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)


88
89
90
91
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 88

def self.config_exist?(config_root)
  config_path = config_root + CONFIG_FILE_NAME
  config_path.exist?
end

.create(lookup_invocation, config_path) ⇒ LookupConfiguration

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.

Creates a new HieraConfig from the given config_root. This is where the ‘hiera.yaml’ is expected to be found and is also the base location used when resolving relative paths.

Parameters:

  • lookup_invocation (Invocation)

    Invocation data containing scope, overrides, and defaults

  • config_path (Pathname)

    Absolute path to the configuration file

Returns:

  • (LookupConfiguration)

    the configuration



110
111
112
113
114
115
116
117
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
146
147
148
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 110

def self.create(lookup_invocation, config_path)
  if config_path.is_a?(Hash)
    config_path = nil
    loaded_config = config_path
  else
    config_root = config_path.parent
    if config_path.exist?
      env_context = EnvironmentContext.adapt(lookup_invocation.scope.compiler.environment)
      loaded_config = env_context.cached_file_data(config_path) do |content|
        parsed = YAML.load(content, config_path)

        # For backward compatibility, we must treat an empty file, or a yaml that doesn't
        # produce a Hash as Hiera version 3 default.
        if parsed.is_a?(Hash)
          parsed
        else
          Puppet.warning("#{config_path}: File exists but does not contain a valid YAML hash. Falling back to Hiera version 3 default config")
          HieraConfigV3::DEFAULT_CONFIG_HASH
        end
      end
    else
      config_path = nil
      loaded_config = HieraConfigV5::DEFAULT_CONFIG_HASH
    end
  end

  version = loaded_config[KEY_VERSION] || loaded_config[:version]
  version = version.nil? ? 3 : version.to_i
  case version
  when 5
    HieraConfigV5.new(config_root, config_path, loaded_config)
  when 4
    HieraConfigV4.new(config_root, config_path, loaded_config)
  when 3
    HieraConfigV3.new(config_root, config_path, loaded_config)
  else
    raise Puppet::DataBinding::LookupError, "#{@config_path}: This runtime does not support #{CONFIG_FILE_NAME} version '#{version}'"
  end
end

.symkeys_to_string(struct) ⇒ 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.



93
94
95
96
97
98
99
100
101
102
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 93

def self.symkeys_to_string(struct)
  case(struct)
  when Hash
    Hash[struct.map { |k,v| [k.to_s, symkeys_to_string(v)] }]
  when Array
    struct.map { |v| symkeys_to_string(v) }
  else
    struct
  end
end

.v4_function_config(config_root, function_name) ⇒ 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.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 70

def self.v4_function_config(config_root, function_name)
  unless Puppet[:strict] == :off
    Puppet.warn_once(:deprecation, 'legacy_provider_function',
      "Using of legacy data provider function '#{function_name}'. Please convert to a 'data_hash' function")
  end
  HieraConfigV5.new(config_root, nil,
    {
      KEY_VERSION => 5,
      KEY_HIERARCHY => [
        {
          KEY_NAME => "Legacy function '#{function_name}'",
          KEY_V4_DATA_HASH => function_name
        }
      ]
    }.freeze
  )
end

Instance Method Details

#configured_data_providers(lookup_invocation, parent_data_provider) ⇒ Array<DataProvider>

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 data providers for this config

Parameters:

  • lookup_invocation (Invocation)

    Invocation data containing scope, overrides, and defaults

  • parent_data_provider (DataProvider)

    The data provider that loaded this configuration

Returns:



170
171
172
173
174
175
176
177
178
179
180
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 170

def configured_data_providers(lookup_invocation, parent_data_provider)
  unless @data_providers && scope_interpolations_stable?(lookup_invocation)
    if @data_providers
      lookup_invocation.report_text { 'Hiera configuration recreated due to change of scope variables used in interpolation expressions' }
    end
    slc_invocation = ScopeLookupCollectingInvocation.new(lookup_invocation.scope)
    @data_providers = create_configured_data_providers(slc_invocation, parent_data_provider)
    @scope_interpolations = slc_invocation.scope_interpolations
  end
  @data_providers
end

#create_configured_data_providers(lookup_invocation, parent_data_provider) ⇒ 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.



202
203
204
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 202

def create_configured_data_providers(lookup_invocation, parent_data_provider)
  self.class.not_implemented(self, 'create_configured_data_providers')
end

#create_hiera3_backend_provider(name, backend, parent_data_provider, datadir, paths, hiera3_config) ⇒ 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.



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 218

def create_hiera3_backend_provider(name, backend, parent_data_provider, datadir, paths, hiera3_config)
  # Custom backend. Hiera v3 must be installed, it's logger configured, and it must be made aware of the loaded config
  require 'hiera'
  if Hiera::Config.instance_variable_defined?(:@config) && (current_config = Hiera::Config.instance_variable_get(:@config)).is_a?(Hash)
    current_config.each_pair do |key, val|
      case key
      when :hierarchy, :backends
        hiera3_config[key] = ([val] + [hiera3_config[key]]).flatten.uniq
      else
        hiera3_config[key] = val
      end
    end
  else
    if hiera3_config.include?(KEY_LOGGER)
      Hiera.logger = hiera3_config[KEY_LOGGER].to_s
    else
      Hiera.logger = 'puppet'
    end
  end

  unless Hiera::Interpolate.const_defined?(:PATCHED_BY_HIERA_5)
    # Replace the class methods 'hiera_interpolate' and 'alias_interpolate' with a method that wires back and performs global
    # lookups using the lookup framework. This is necessary since the classic Hiera is made aware only of custom backends.
    class << Hiera::Interpolate
      hiera_interpolate = Proc.new do |data, key, scope, extra_data, context|
        override = context[:order_override]
        invocation = Puppet::Pops::Lookup::Invocation.current
        unless override.nil? && invocation.global_only?
          invocation = Puppet::Pops::Lookup::Invocation.new(scope)
          invocation.set_global_only
          invocation.set_hiera_v3_location_overrides(override) unless override.nil?
        end
        Puppet::Pops::Lookup::LookupAdapter.adapt(scope.compiler).lookup(key, invocation, nil)
      end

      send(:remove_method, :hiera_interpolate)
      send(:remove_method, :alias_interpolate)
      send(:define_method, :hiera_interpolate, hiera_interpolate)
      send(:define_method, :alias_interpolate, hiera_interpolate)
    end
    Hiera::Interpolate.send(:const_set, :PATCHED_BY_HIERA_5, true)
  end

  Hiera::Config.instance_variable_set(:@config, hiera3_config)

  # Use a special lookup_key that delegates to the backend
  paths = nil if !paths.nil? && paths.empty?
  create_data_provider(name, parent_data_provider, KEY_V3_BACKEND, 'hiera_v3_data', { KEY_DATADIR => datadir, KEY_BACKEND => backend }, paths)
end

#nameObject

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.



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

def name
  "hiera configuration version #{version}"
end

#scope_interpolations_stable?(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:

  • (Boolean)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 182

def scope_interpolations_stable?(lookup_invocation)
  if @scope_interpolations.empty?
    true
  else
    scope = lookup_invocation.scope
    lookup_invocation.without_explain do
      @scope_interpolations.all? do |key, root_key, segments, old_value|
        value = scope[root_key]
        unless value.nil? || segments.empty?
          found = '';
          catch(:no_such_key) { found = sub_lookup(key, lookup_invocation, segments, value) }
          value = found;
        end
        old_value.eql?(value)
      end
    end
  end
end

#validate_config(config) ⇒ 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.



206
207
208
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 206

def validate_config(config)
  self.class.not_implemented(self, 'validate_config')
end