Skip to content

Commit

Permalink
Merge pull request #53 from betadots/issue-17
Browse files Browse the repository at this point in the history
Interpolate facts with a `facts.` or `trusted.` scope #17
  • Loading branch information
rwaffen authored Jun 3, 2022
2 parents 4541585 + 76d2dca commit 1c89d3e
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 43 deletions.
18 changes: 6 additions & 12 deletions app/models/hiera_data/interpolation.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class HieraData
module Interpolation
VARIABLE_REGEXP = /%{(::)?(facts|trusted)\.([^}]+)}/.freeze

module_function

Expand All @@ -8,19 +9,12 @@ def interpolate_globs(path:, datadir:)
end

def interpolate_facts(path:, facts:)
groups = path.scan(/%{([^}]+)}/)
groups.flatten!
groups.each { |x| x.gsub!(/^::/, '')}

resolved_path = path.dup

groups.each do |fact|
facts_value = facts.dig(*fact.split("."))
next unless facts_value
resolved_path.gsub!(/%{(::)?#{fact}}/, facts_value)
path.gsub(VARIABLE_REGEXP) do |variable_string|
_, _, scope, name = variable_string.match(VARIABLE_REGEXP).to_a
name = "trusted.#{name}" if scope == "trusted"
value = facts.dig(*name.split("."))
value || variable_string
end

resolved_path
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ defaults:
hierarchy:
- name: "Eyaml hierarchy"
paths:
- "nodes/%{::fqdn}.yaml"
- "role/%{::role}-%{::env}.yaml"
- "role/%{::role}.yaml"
- "zone/%{::zone}.yaml"
- "nodes/%{::facts.fqdn}.yaml"
- "role/%{::facts.role}-%{::facts.env}.yaml"
- "role/%{::facts.role}.yaml"
- "zone/%{::facts.zone}.yaml"
- "common.yaml"
8 changes: 4 additions & 4 deletions test/fixtures/files/puppet/environments/eyaml/hiera.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ defaults:

hierarchy:
- name: "Host specific"
path: "nodes/%{::fqdn}.yaml"
path: "nodes/%{::facts.fqdn}.yaml"

- name: "Per-datacenter business group data" # Uses custom facts.
paths:
- "role/%{::role}-%{::env}.yaml"
- "role/%{::role}.yaml"
- "zone/%{::zone}.yaml"
- "role/%{::facts.role}-%{::facts.env}.yaml"
- "role/%{::facts.role}.yaml"
- "zone/%{::facts.zone}.yaml"

- name: "Global data"
path: "common.yaml"
Expand Down
8 changes: 4 additions & 4 deletions test/fixtures/files/puppet/environments/globs/hiera.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ defaults:
hierarchy:
- name: "Eyaml hierarchy"
paths:
- "nodes/%{::fqdn}.yaml"
- "role/%{::role}-%{::env}.yaml"
- "role/%{::role}.yaml"
- "zone/%{::zone}.yaml"
- "nodes/%{::facts.fqdn}.yaml"
- "role/%{::facts.role}-%{::facts.env}.yaml"
- "role/%{::facts.role}.yaml"
- "zone/%{::facts.zone}.yaml"
- name: "Common"
globs:
- "common/*.yaml"
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ defaults:

hierarchy:
- name: "Host specific"
path: "nodes/%{::fqdn}.yaml"
path: "nodes/%{::facts.fqdn}.yaml"

- name: "Per-datacenter business group data" # Uses custom facts.
paths:
- "role/%{::role}-%{::env}.yaml"
- "role/%{::role}.yaml"
- "zone/%{::zone}.yaml"
- "role/%{::facts.role}-%{::facts.env}.yaml"
- "role/%{::facts.role}.yaml"
- "zone/%{::facts.zone}.yaml"

- name: "Global data"
path: "common.yaml"
Expand Down
8 changes: 4 additions & 4 deletions test/fixtures/files/puppet/environments/test/hiera.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ defaults:
hierarchy:
- name: "Eyaml hierarchy"
paths:
- "nodes/%{::fqdn}.yaml"
- "role/%{::role}-%{::env}.yaml"
- "role/%{::role}.yaml"
- "zone/%{::zone}.yaml"
- "nodes/%{::facts.fqdn}.yaml"
- "role/%{::facts.role}-%{::facts.env}.yaml"
- "role/%{::facts.role}.yaml"
- "zone/%{::facts.zone}.yaml"
- "common.yaml"
16 changes: 8 additions & 8 deletions test/models/hiera_data/hierarchy_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ class HieraData::HierarchyTest < ActiveSupport::TestCase
test "#paths returns all non-interpolated path names" do
hierarchy = HieraData::Hierarchy.new(raw_hash: raw_hash, base_path: ".")
expected_paths = [
"nodes/%{::fqdn}.yaml",
"role/%{::role}-%{::env}.yaml",
"role/%{::role}.yaml",
"zone/%{::zone}.yaml",
"nodes/%{::facts.fqdn}.yaml",
"role/%{::facts.role}-%{::facts.env}.yaml",
"role/%{::facts.role}.yaml",
"zone/%{::facts.zone}.yaml",
"common.yaml"
]
assert_equal expected_paths, hierarchy.paths
Expand Down Expand Up @@ -93,10 +93,10 @@ def raw_hash
{
"name" => "Yaml hierarchy",
"paths" => [
"nodes/%{::fqdn}.yaml",
"role/%{::role}-%{::env}.yaml",
"role/%{::role}.yaml",
"zone/%{::zone}.yaml",
"nodes/%{::facts.fqdn}.yaml",
"role/%{::facts.role}-%{::facts.env}.yaml",
"role/%{::facts.role}.yaml",
"zone/%{::facts.zone}.yaml",
"common.yaml"
]
}
Expand Down
36 changes: 33 additions & 3 deletions test/models/hiera_data/interpolation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,56 @@ class HieraData::InterpolationTest < ActiveSupport::TestCase
end

test "::interpolate_facts replaces facts with leading colons" do
path = "/test/%{::test_fact}/file"
path = "/test/%{::facts.test_fact}/file"
facts = {"test_fact" => "replaced"}
expected_result = "/test/replaced/file"

assert_equal expected_result, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end

test "::interpolate_facts replaces facts without leading colons" do
path = "/test/%{test_fact}/file"
path = "/test/%{facts.test_fact}/file"
facts = {"test_fact" => "replaced"}
expected_result = "/test/replaced/file"

assert_equal expected_result, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end

test "::interpolate_facts replaces facts with `trusted.` scope with leading colons" do
path = "/test/%{::trusted.test_fact}/file"
facts = {"trusted" => {"test_fact" => "replaced"}}
expected_result = "/test/replaced/file"

assert_equal expected_result, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end

test "::interpolate_facts replaces facts with `trusted.` scope without leading colons" do
path = "/test/%{trusted.test_fact}/file"
facts = {"trusted" => {"test_fact" => "replaced"}}
expected_result = "/test/replaced/file"

assert_equal expected_result, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end

test "::interpolate_facts replaces nested facts" do
path = "/test/%{nested.fact}/file"
path = "/test/%{facts.nested.fact}/file"
facts = {"nested" => {"fact" => "deep"}}
expected_result = "/test/deep/file"

assert_equal expected_result, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end

test "::interpolate_facts will not replace arbitrary variables with leading colons" do
path = "/test/%{::test_fact}/file"
facts = {"test_fact" => "replaced"}

assert_equal path, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end

test "::interpolate_facts will not replace arbitrary variables without leading colons" do
path = "/test/%{test_fact}/file"
facts = {"test_fact" => "replaced"}

assert_equal path, HieraData::Interpolation.interpolate_facts(path: path, facts: facts)
end
end

0 comments on commit 1c89d3e

Please sign in to comment.