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_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
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_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



144
145
146
147
148
149
150
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 144

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.



137
138
139
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 137

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.



137
138
139
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 137

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)


81
82
83
84
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 81

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

.create(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:

  • config_path (Pathname)

    Absolute path to the configuration file

Returns:

  • (LookupConfiguration)

    the configuration



102
103
104
105
106
107
108
109
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
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 102

def self.create(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?
      loaded_config = YAML.load_file(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.
      unless loaded_config.is_a?(Hash)
        Puppet.warning("#{config_path}: File exists but does not contain a valid YAML hash. Falling back to Hiera version 3 default config")
        loaded_config = HieraConfigV3::DEFAULT_CONFIG_HASH
      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.



86
87
88
89
90
91
92
93
94
95
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 86

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.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 63

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:



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

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.



183
184
185
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 183

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.



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 199

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.



195
196
197
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 195

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)


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

def scope_interpolations_stable?(lookup_invocation)
  scope = lookup_invocation.scope
  @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

#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.



187
188
189
# File 'lib/puppet/pops/lookup/hiera_config.rb', line 187

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