Class: Hiera::Backend::Nuyaml3_backend

Inherits:
Object
  • Object
show all
Defined in:
modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb

Overview

This naming is required by puppet.

Instance Method Summary collapse

Constructor Details

#initialize(cache = nil) ⇒ Nuyaml3_backend

Returns a new instance of Nuyaml3_backend.



71
72
73
74
75
76
# File 'modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb', line 71

def initialize(cache = nil)
  require 'yaml'
  @cache = cache || Filecache.new
  config = Config[:nuyaml3]
  @expand_path = config[:expand_path] || []
end

Instance Method Details

#get_path(key, scope, source, context) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb', line 78

def get_path(key, scope, source, context)
  config_section = :nuyaml3
  # Special case: regex
  if %r{^regex/}.match(source)
    Hiera.debug("Regex match going on - using regex.yaml")
    return Backend.datafile(config_section, scope, 'regex', "yaml")
  end

  # Special case: 'netbox' repository.
  # We use a different datadir in this case.
  # Example: netbox/common will search in the common source
  # within the netbox datadir
  if %r{^netbox/(.*)} =~ source
    config_section = :netbox
    source = Regexp.last_match(1)
  end

  # Special case: 'private' repository.
  # We use a different datadir in this case.
  # Example: private/common will search in the common source
  # within the private datadir
  if %r{private/(.*)} =~ source
    config_section = :private3
    source = Regexp.last_match(1)
  end

  # Special case: 'secret' repository. This is practically labs only
  # We use a different datadir in this case.
  # Example: private/common will search in the common source
  # within the private datadir
  if %r{secret/(.*)} =~ source
    config_section = :secret3
    source = Regexp.last_match(1)
  end

  Hiera.debug("The source is: #{source}")
  # If the source is in the expand_path list, perform path
  # expansion. This is thought to allow large codebases to live
  # with fairly small yaml files as opposed to a very large one.
  # Example:
  # $apache::mpm::worker will be in common/apache/mpm.yaml
  paths = @expand_path.map{ |x| Backend.parse_string(x, scope, {}, context) }
  if paths.include? source
    namespaces = key.gsub(/^::/, '').split('::')
    namespaces.pop

    unless namespaces.empty?
      source += "/".concat(namespaces.join('/'))
    end
  end

  Backend.datafile(config_section, scope, source, "yaml")
end

#lookup(key, scope, order_override, resolution_type, context) ⇒ Object



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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb', line 161

def lookup(key, scope, order_override, resolution_type, context)
  answer = nil

  Hiera.debug("Looking up #{key}")

  Backend.datasources(scope, order_override) do |source|
    Hiera.debug("Loading info from #{source} for #{key}")

    yamlfile = get_path(key, scope, source, context)

    Hiera.debug("Searching for #{key} in #{yamlfile}")

    next if yamlfile.nil?

    Hiera.debug("Loading file #{yamlfile}")

    next unless File.exist?(yamlfile)

    data = @cache.read(yamlfile, Hash) do |content|
      YAML.load(content)
    end

    next if data.nil?

    if %r{regex/(.*)$} =~ source
      matchto = Regexp.last_match(1)
      new_answer = regex_lookup(key, matchto, data, scope, context)
    else
      new_answer = plain_lookup(key, data, scope, context)
    end

    next if new_answer.nil?
    # Extra logging that we found the key. This can be outputted
    # multiple times if the resolution type is array or hash but that
    # should be expected as the logging will then tell the user ALL the
    # places where the key is found.
    Hiera.debug("Found #{key} in #{source}")

    # for array resolution we just append to the array whatever
    # we find, we then go onto the next file and keep adding to
    # the array
    #
    # for priority searches we break after the first found data
    # item

    case resolution_type
    when :array
      raise Exception, "Hiera type mismatch: expected Array and got #{new_answer.class}" unless new_answer.kind_of?(Array) || new_answer.kind_of?(String)
      answer ||= []
      answer << new_answer
    when :hash, Hash
      raise Exception, "Hiera type mismatch: expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
      answer ||= {}
      rt = resolution_type
      # If we get :hash as a resolution_type, we will use the defaults.
      rt = nil if resolution_type == :hash

      answer = Backend.merge_answer(new_answer, answer, rt)
    else
      answer = new_answer
      break
    end
  end
  if answer.nil?
    Hiera.debug("No answer! #{key}")
    throw(:no_such_key)
  end
  answer
end

#lookup_with_segments(segments, scope, order_override, resolution_type, context) ⇒ Object

Hiera 3 supports “segmented lookup” by splitting keys on dots, to allow looking up values inside nested structures. In this case reconstruct the segmented key into its original form and perform a lookup.



155
156
157
158
159
# File 'modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb', line 155

def lookup_with_segments(segments, scope, order_override, resolution_type, context)
  Hiera.debug("Got a segmented key #{segments}")

  lookup(segments.join('.'), scope, order_override, resolution_type, context)
end

#plain_lookup(key, data, scope, context) ⇒ Object



132
133
134
135
# File 'modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb', line 132

def plain_lookup(key, data, scope, context)
    return nil unless data.include?(key)
    Backend.parse_answer(data[key], scope, {}, context)
end

#regex_lookup(key, matchon, data, scope, context) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'modules/wmflib/lib/hiera/backend/nuyaml3_backend.rb', line 137

def regex_lookup(key, matchon, data, scope, context)
  data.each do |label, datahash|
    r = datahash["__regex"]
    Hiera.debug("Scanning label #{label} for matches to '#{r}' in '#{matchon}' ")
    next unless r.match(matchon)
    Hiera.debug("Label #{label} matches; searching within it")
    next unless datahash.include?(key)
    return Backend.parse_answer(datahash[key], scope, {}, context)
  end
  return nil
rescue => detail
  Hiera.debug(detail)
  return nil
end