Skip to content

Commit

Permalink
Add Hiera overrides
Browse files Browse the repository at this point in the history
It is possible to explode the Hiera overrides and generate a table in
the reference.
  • Loading branch information
ekohl committed Sep 28, 2022
1 parent 13f2953 commit 44a8de6
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lib/puppet-strings/hiera.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module PuppetStrings
module Hiera
require_relative 'hiera/hierarchy_data_path'
require_relative 'hiera/data'

def self.load_config
PuppetStrings::Hiera::Data.new('hiera.yaml')
end
end
end
95 changes: 95 additions & 0 deletions lib/puppet-strings/hiera/data.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# frozen_string_literal: true

module PuppetStrings::Hiera
class Data
attr_reader :config_path, :data_paths

def initialize(config_path)
@config_path = config_path
@data_paths = []

load_config
end

def files
@files ||= begin
result = {}

data_paths.each do |dp|
dp.matches.each do |file, interpolations|
unless result.key?(file)
result[file] = interpolations
end
end
end

result
end
end

# @return [Hash[String, Hash[String, Any]]]
# Full variable (class::var) -> filename: value
def overrides
@overrides ||= begin
overrides = {}

files.each_key do |file|
data = YAML.load(File.read(file))
data.each do |key, value|
overrides[key] ||= {}
overrides[key][file] = value
end
end

overrides
end
end

# @return [Hash[String, Hash[String, Any]]]
# variable -> filename: value
def for_class(class_name)
result = {}
overrides.each do |key, value|
override_class_name, _, variable = key.rpartition('::')
if override_class_name == class_name
result[variable] = value
end
end
result
end

def to_s
config_path
end

private

def load_config
return unless File.exist?(config_path)

config = YAML.load(File.read(config_path))

unless config['version'] == 5
raise "Unsupported version '#{config['version']}'"
end

hierarchy = config['hierarchy']
return unless hierarchy

hierarchy.each do |level|
data_hash = level['data_hash'] || config['defaults']['data_hash']
next unless data_hash == 'yaml_data'

datadir = level['datadir'] || config['defaults']['datadir']

if level['path']
data_paths << PuppetStrings::Hiera::HierarchyDataPath.new(datadir, level['path'])
elsif level['paths']
level['paths'].each do |path|
data_paths << PuppetStrings::Hiera::HierarchyDataPath.new(datadir, path)
end
end
end
end
end
end
63 changes: 63 additions & 0 deletions lib/puppet-strings/hiera/hierarchy_data_path.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true

module PuppetStrings::Hiera
class HierarchyDataPath
attr_reader :datadir, :path, :regex, :mapping

def initialize(datadir, path)
@datadir = datadir
@path = path
@regex, @mapping = HierarchyDataPath.path2regex(path)
end

def matches
result = {}

Dir.chdir(datadir) do
Dir['**'].each do |entry|
next unless File.file?(entry)

regex.match(entry) do |match|
full_path = File.join(datadir, entry)
interpolations = {}

mapping.each do |name, interpolation|
interpolations[interpolation] = match.named_captures[name]
end

result[full_path] = interpolations
end
end
end

result
end

def self.path2regex(path)
mapping = {}

intermediate_result = path

# First pass - intermediate replacements
path.scan(/%{[^}]+}/).each_with_index do |interpolation, i|
replacement = "X_INTERPOLATION_#{i}_X"
mapping[replacement] = interpolation[2..-2]
intermediate_result = intermediate_result.sub(interpolation, replacement)
end

# Second pass - escape any special chars
escaped = Regexp.escape(intermediate_result)

# Third pass - replacement intermediates with regex
mapping.each_key do |replacement|
escaped = escaped.sub(replacement, "(?<#{replacement}>.+)")
end

[Regexp.new(escaped), mapping]
end

def to_s
File.join(datadir, path)
end
end
end
12 changes: 12 additions & 0 deletions lib/puppet-strings/markdown/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ def defaults
@registry[:defaults] unless @registry[:defaults].nil?
end

# Overrides from Hiera
#
# Hiera overrides only apply to classes. Each entry is a tuple of the
# filename it's defined in, a mapping of interpolations that were applied
# in the filename and the value inside the file.
#
# @return [Array[Tuple[String, Hash[String, String], Any]]]
# Any overrides from Hiera.
def hiera_overrides
[]
end

# @return [Hash] information needed for the table of contents
def toc_info
{
Expand Down
18 changes: 18 additions & 0 deletions lib/puppet-strings/markdown/puppet_class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ def initialize(registry)
super(registry, 'class')
end

def hiera_overrides
@hiera_overrides ||= begin
hiera = PuppetStrings::Hiera.load_config
overrides = hiera.for_class(name)

result = {}

overrides.each do |variable, files|
result[variable] = files.map do |filename, value|
interpolations = hiera.files[filename]
[filename, interpolations, value]
end
end

result
end
end

def render
super(@template)
end
Expand Down
13 changes: 13 additions & 0 deletions lib/puppet-strings/markdown/templates/classes_and_defines.erb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ Options:
<% if defaults && defaults[param[:name]] -%>
Default value: `<%= defaults[param[:name]] %>`

<% end -%>
<% if hiera_overrides[param[:name]] -%>
<details>
<summary>Hiera overrides in a detailed table</summary>

| Filename | Interpolations | Value |
|----------|----------------|-------|
<% hiera_overrides[param[:name]].each do |filename, interpolations, value| -%>
| `<%= filename %>` | <%= interpolations.map { |i, v| "`#{i}`: `#{v}`" }.join("<br>") %> | `<%= value %>` |
<% end -%>

</details>

<% end -%>
<% end -%>
<% end -%>
1 change: 1 addition & 0 deletions lib/puppet-strings/yard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module PuppetStrings::Yard
require 'puppet-strings/yard/handlers'
require 'puppet-strings/yard/tags'
require 'puppet-strings/yard/parsers'
require 'puppet-strings/hiera'
require 'puppet-strings/monkey_patches/display_object_command'

# Sets up YARD for use with puppet-strings.
Expand Down
1 change: 1 addition & 0 deletions lib/puppet-strings/yard/code_objects/class.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def to_hash
hash[:docstring] = PuppetStrings::Yard::Util.docstring_to_hash(docstring)
defaults = Hash[*parameters.reject{ |p| p[1].nil? }.flatten]
hash[:defaults] = defaults unless defaults.nil? || defaults.empty?
#hash[:hiera_overrides] = hiera_overrides if hiera_overrides.any?
hash[:source] = source unless source.nil? || source.empty?
hash
end
Expand Down

0 comments on commit 44a8de6

Please sign in to comment.