Class: Hiera::Backend::Role3_backend

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

Overview

This naming is required by puppet.

Instance Method Summary collapse

Constructor Details

#initialize(cache = nil) ⇒ Role3_backend

Returns a new instance of Role3_backend.



74
75
76
# File 'modules/wmflib/lib/hiera/backend/role3_backend.rb', line 74

def initialize(cache = nil)
  @cache = cache || Filecache.new
end

Instance Method Details

#get_path(_key, role, source, scope) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'modules/wmflib/lib/hiera/backend/role3_backend.rb', line 78

def get_path(_key, role, source, scope)
  config_section = :role

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

  # Variables for role::foo::bar will be searched in:
  # role/foo/bar.yaml
  # role/$::site/foo/bar.yaml
  # etc, depending on your hierarchy
  path = role.split('::').join('/')
  src = "role/#{source}/#{path}"

  # Use the datadir for the 'role' section of the config
  Backend.datafile(config_section, scope, src, "yaml")
end

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



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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
# File 'modules/wmflib/lib/hiera/backend/role3_backend.rb', line 132

def lookup(key, scope, order_override, resolution_type, context)
  Hiera.debug("Looking up #{key}")
  topscope_var = '_roles'
  resultset = nil
  throw(:no_such_key) unless scope.include?topscope_var
  roles = scope[topscope_var]
  throw(:no_such_key) if roles.nil?
  if Config.include?(:role_hierarchy)
    hierarchy = Config[:role_hierarchy]
  else
    hierarchy = nil
  end

  roles.keys.each do |role|
    Hiera.debug("Looking in hierarchy for role #{role}")
    answer = nil
    Backend.datasources(scope, order_override, hierarchy) do |source|
      yamlfile = get_path(key, role, source, scope)
      next if yamlfile.nil?
      Hiera.debug("Searching in file #{yamlfile} for #{key}")
      next unless File.exist?(yamlfile)

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

      next if data.nil? || data.empty?

      next unless data.include? key

      new_answer = Backend.parse_answer(data[key], scope, context)
      Hiera.debug("Found: #{key} =>  #{new_answer}")
      is_done, answer = merge_answer(new_answer, answer,
                                     resolution_type)
      break if is_done
    end
    # skip parsing if no answer was found.
    next if answer.nil?

    # Now we got one answer for this role, we can merge it with
    # what we got earlier.
    case resolution_type
    when :array
      resultset ||= []
      answer.each { |el| resultset.push(el) }
    when :hash, Hash
      rt = resolution_type
      # If we get :hash as a resolution_type, we will use the defaults.
      rt = nil if resolution_type == :hash

      resultset ||= {}
      resultset = Backend.merge_answer(answer, resultset, rt)
    else
      # We raise an exception if we have received conflicting results
      if resultset && answer != resultset
        raise Exception, "Conflicting value for #{key} found in role #{role}"
      else
        resultset = answer
      end
    end
  end
  if resultset.nil?
    Hiera.debug("No answer for #{key}!")
    throw(:no_such_key)
  end
  resultset
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.



126
127
128
129
130
# File 'modules/wmflib/lib/hiera/backend/role3_backend.rb', line 126

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

#merge_answer(new_answer, answer, resolution_type) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'modules/wmflib/lib/hiera/backend/role3_backend.rb', line 101

def merge_answer(new_answer, answer, resolution_type)
  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
    rt = resolution_type
    # If we get :hash as a resolution_type, we will use the defaults.
    rt = nil if resolution_type == :hash

    answer ||= {}
    answer = Backend.merge_answer(new_answer, answer, rt)
  else
    answer = new_answer
    return true, answer
  end

  [false, answer]
end