hiera 1.3.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +47 -10
- data/bin/hiera +48 -31
- data/lib/hiera.rb +55 -3
- data/lib/hiera/backend.rb +124 -37
- data/lib/hiera/backend/json_backend.rb +9 -7
- data/lib/hiera/backend/yaml_backend.rb +9 -7
- data/lib/hiera/config.rb +1 -3
- data/lib/hiera/interpolate.rb +52 -16
- data/lib/hiera/util.rb +5 -5
- data/lib/hiera/version.rb +1 -1
- data/spec/spec_helper.rb +12 -0
- data/spec/unit/backend/json_backend_spec.rb +9 -9
- data/spec/unit/backend/yaml_backend_spec.rb +20 -15
- data/spec/unit/backend_spec.rb +186 -32
- data/spec/unit/config_spec.rb +15 -0
- data/spec/unit/fixtures/interpolate/config/hiera.yaml +6 -0
- data/spec/unit/fixtures/interpolate/data/niltest.yaml +2 -0
- data/spec/unit/fixtures/interpolate/data/recursive.yaml +3 -0
- data/spec/unit/fixtures/override/config/hiera.yaml +5 -0
- data/spec/unit/fixtures/override/data/alternate.yaml +1 -0
- data/spec/unit/fixtures/override/data/common.yaml +2 -0
- data/spec/unit/interpolate_spec.rb +36 -0
- data/spec/unit/util_spec.rb +4 -4
- metadata +17 -3
@@ -9,8 +9,9 @@ class Hiera
|
|
9
9
|
@cache = cache || Filecache.new
|
10
10
|
end
|
11
11
|
|
12
|
-
def lookup(key, scope, order_override, resolution_type)
|
12
|
+
def lookup(key, scope, order_override, resolution_type, context)
|
13
13
|
answer = nil
|
14
|
+
found = false
|
14
15
|
|
15
16
|
Hiera.debug("Looking up #{key} in JSON backend")
|
16
17
|
|
@@ -27,28 +28,29 @@ class Hiera
|
|
27
28
|
|
28
29
|
next if data.empty?
|
29
30
|
next unless data.include?(key)
|
31
|
+
found = true
|
30
32
|
|
31
33
|
# for array resolution we just append to the array whatever
|
32
34
|
# we find, we then goes onto the next file and keep adding to
|
33
35
|
# the array
|
34
36
|
#
|
35
37
|
# for priority searches we break after the first found data item
|
36
|
-
new_answer = Backend.parse_answer(data[key], scope)
|
37
|
-
case resolution_type
|
38
|
+
new_answer = Backend.parse_answer(data[key], scope, {}, context)
|
39
|
+
case resolution_type.is_a?(Hash) ? :hash : resolution_type
|
38
40
|
when :array
|
39
|
-
raise Exception, "Hiera type mismatch: expected Array and got #{new_answer.class}" unless new_answer.kind_of? Array or new_answer.kind_of? String
|
41
|
+
raise Exception, "Hiera type mismatch for key '#{key}': expected Array and got #{new_answer.class}" unless new_answer.kind_of? Array or new_answer.kind_of? String
|
40
42
|
answer ||= []
|
41
43
|
answer << new_answer
|
42
44
|
when :hash
|
43
|
-
raise Exception, "Hiera type mismatch: expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
|
45
|
+
raise Exception, "Hiera type mismatch for key '#{key}': expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
|
44
46
|
answer ||= {}
|
45
|
-
answer = Backend.merge_answer(new_answer,answer)
|
47
|
+
answer = Backend.merge_answer(new_answer, answer, resolution_type)
|
46
48
|
else
|
47
49
|
answer = new_answer
|
48
50
|
break
|
49
51
|
end
|
50
52
|
end
|
51
|
-
|
53
|
+
throw :no_such_key unless found
|
52
54
|
return answer
|
53
55
|
end
|
54
56
|
end
|
@@ -8,8 +8,9 @@ class Hiera
|
|
8
8
|
@cache = cache || Filecache.new
|
9
9
|
end
|
10
10
|
|
11
|
-
def lookup(key, scope, order_override, resolution_type)
|
11
|
+
def lookup(key, scope, order_override, resolution_type, context)
|
12
12
|
answer = nil
|
13
|
+
found = false
|
13
14
|
|
14
15
|
Hiera.debug("Looking up #{key} in YAML backend")
|
15
16
|
|
@@ -20,6 +21,7 @@ class Hiera
|
|
20
21
|
|
21
22
|
next if data.empty?
|
22
23
|
next unless data.include?(key)
|
24
|
+
found = true
|
23
25
|
|
24
26
|
# Extra logging that we found the key. This can be outputted
|
25
27
|
# multiple times if the resolution type is array or hash but that
|
@@ -32,22 +34,22 @@ class Hiera
|
|
32
34
|
# the array
|
33
35
|
#
|
34
36
|
# for priority searches we break after the first found data item
|
35
|
-
new_answer = Backend.parse_answer(data[key], scope)
|
36
|
-
case resolution_type
|
37
|
+
new_answer = Backend.parse_answer(data[key], scope, {}, context)
|
38
|
+
case resolution_type.is_a?(Hash) ? :hash : resolution_type
|
37
39
|
when :array
|
38
|
-
raise Exception, "Hiera type mismatch: expected Array and got #{new_answer.class}" unless new_answer.kind_of? Array or new_answer.kind_of? String
|
40
|
+
raise Exception, "Hiera type mismatch for key '#{key}': expected Array and got #{new_answer.class}" unless new_answer.kind_of? Array or new_answer.kind_of? String
|
39
41
|
answer ||= []
|
40
42
|
answer << new_answer
|
41
43
|
when :hash
|
42
|
-
raise Exception, "Hiera type mismatch: expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
|
44
|
+
raise Exception, "Hiera type mismatch for key '#{key}': expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
|
43
45
|
answer ||= {}
|
44
|
-
answer = Backend.merge_answer(new_answer,answer)
|
46
|
+
answer = Backend.merge_answer(new_answer, answer, resolution_type)
|
45
47
|
else
|
46
48
|
answer = new_answer
|
47
49
|
break
|
48
50
|
end
|
49
51
|
end
|
50
|
-
|
52
|
+
throw :no_such_key unless found
|
51
53
|
return answer
|
52
54
|
end
|
53
55
|
|
data/lib/hiera/config.rb
CHANGED
@@ -54,9 +54,7 @@ class Hiera::Config
|
|
54
54
|
begin
|
55
55
|
require "deep_merge"
|
56
56
|
rescue LoadError
|
57
|
-
Hiera
|
58
|
-
Hiera.warn "Must have 'deep_merge' gem installed."
|
59
|
-
@config[:merge_behavior] = :native
|
57
|
+
raise Hiera::Error, "Must have 'deep_merge' gem installed for the configured merge_behavior."
|
60
58
|
end
|
61
59
|
end
|
62
60
|
end
|
data/lib/hiera/interpolate.rb
CHANGED
@@ -1,30 +1,57 @@
|
|
1
1
|
require 'hiera/backend'
|
2
2
|
require 'hiera/recursive_guard'
|
3
3
|
|
4
|
+
|
5
|
+
class Hiera::InterpolationInvalidValue < StandardError; end
|
6
|
+
|
4
7
|
class Hiera::Interpolate
|
5
8
|
class << self
|
6
9
|
INTERPOLATION = /%\{([^\}]*)\}/
|
7
|
-
METHOD_INTERPOLATION = /%\{(scope|hiera)\(['"]([^"']*)["']\)\}/
|
10
|
+
METHOD_INTERPOLATION = /%\{(scope|hiera|literal|alias)\(['"]([^"']*)["']\)\}/
|
8
11
|
|
9
|
-
def interpolate(data, scope, extra_data)
|
12
|
+
def interpolate(data, scope, extra_data, context)
|
10
13
|
if data.is_a?(String)
|
11
14
|
# Wrapping do_interpolation in a gsub block ensures we process
|
12
15
|
# each interpolation site in isolation using separate recursion guards.
|
16
|
+
context ||= {}
|
17
|
+
new_context = context.clone
|
18
|
+
new_context[:recurse_guard] ||= Hiera::RecursiveGuard.new
|
13
19
|
data.gsub(INTERPOLATION) do |match|
|
14
|
-
do_interpolation(match,
|
20
|
+
interp_val = do_interpolation(match, scope, extra_data, new_context)
|
21
|
+
|
22
|
+
# Get interp method in case we are aliasing
|
23
|
+
if data.is_a?(String) && (match = data.match(INTERPOLATION))
|
24
|
+
interpolate_method, key = get_interpolation_method_and_key(data)
|
25
|
+
else
|
26
|
+
interpolate_method = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
if ( (interpolate_method == :alias_interpolate) and (!interp_val.is_a?(String)) )
|
30
|
+
if data.match("^#{INTERPOLATION}$")
|
31
|
+
return interp_val
|
32
|
+
else
|
33
|
+
raise Hiera::InterpolationInvalidValue, "Cannot call alias in the string context"
|
34
|
+
end
|
35
|
+
else
|
36
|
+
interp_val
|
37
|
+
end
|
15
38
|
end
|
16
39
|
else
|
17
40
|
data
|
18
41
|
end
|
19
42
|
end
|
20
43
|
|
21
|
-
def do_interpolation(data,
|
44
|
+
def do_interpolation(data, scope, extra_data, context)
|
22
45
|
if data.is_a?(String) && (match = data.match(INTERPOLATION))
|
23
46
|
interpolation_variable = match[1]
|
24
|
-
recurse_guard.check(interpolation_variable) do
|
47
|
+
context[:recurse_guard].check(interpolation_variable) do
|
25
48
|
interpolate_method, key = get_interpolation_method_and_key(data)
|
26
|
-
interpolated_data = send(interpolate_method, data, key, scope, extra_data)
|
27
|
-
|
49
|
+
interpolated_data = send(interpolate_method, data, key, scope, extra_data, context)
|
50
|
+
|
51
|
+
# Halt recursion if we encounter a literal.
|
52
|
+
return interpolated_data if interpolate_method == :literal_interpolate
|
53
|
+
|
54
|
+
do_interpolation(interpolated_data, scope, extra_data, context)
|
28
55
|
end
|
29
56
|
else
|
30
57
|
data
|
@@ -37,6 +64,8 @@ class Hiera::Interpolate
|
|
37
64
|
case match[1]
|
38
65
|
when 'hiera' then [:hiera_interpolate, match[2]]
|
39
66
|
when 'scope' then [:scope_interpolate, match[2]]
|
67
|
+
when 'literal' then [:literal_interpolate, match[2]]
|
68
|
+
when 'alias' then [:alias_interpolate, match[2]]
|
40
69
|
end
|
41
70
|
elsif (match = data.match(INTERPOLATION))
|
42
71
|
[:scope_interpolate, match[1]]
|
@@ -44,19 +73,26 @@ class Hiera::Interpolate
|
|
44
73
|
end
|
45
74
|
private :get_interpolation_method_and_key
|
46
75
|
|
47
|
-
def scope_interpolate(data, key, scope, extra_data)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
value
|
76
|
+
def scope_interpolate(data, key, scope, extra_data, context)
|
77
|
+
segments = key.split('.')
|
78
|
+
catch(:no_such_key) { return Hiera::Backend.qualified_lookup(segments, scope) }
|
79
|
+
catch(:no_such_key) { Hiera::Backend.qualified_lookup(segments, extra_data) }
|
54
80
|
end
|
55
81
|
private :scope_interpolate
|
56
82
|
|
57
|
-
def hiera_interpolate(data, key, scope, extra_data)
|
58
|
-
Hiera::Backend.lookup(key, nil, scope,
|
83
|
+
def hiera_interpolate(data, key, scope, extra_data, context)
|
84
|
+
Hiera::Backend.lookup(key, nil, scope, context[:order_override], :priority, context)
|
59
85
|
end
|
60
86
|
private :hiera_interpolate
|
87
|
+
|
88
|
+
def literal_interpolate(data, key, scope, extra_data, context)
|
89
|
+
key
|
90
|
+
end
|
91
|
+
private :literal_interpolate
|
92
|
+
|
93
|
+
def alias_interpolate(data, key, scope, extra_data, context)
|
94
|
+
Hiera::Backend.lookup(key, nil, scope, context[:order_override], :priority, context)
|
95
|
+
end
|
96
|
+
private :alias_interpolate
|
61
97
|
end
|
62
98
|
end
|
data/lib/hiera/util.rb
CHANGED
@@ -9,7 +9,7 @@ class Hiera
|
|
9
9
|
|
10
10
|
def microsoft_windows?
|
11
11
|
return false unless file_alt_separator
|
12
|
-
|
12
|
+
|
13
13
|
begin
|
14
14
|
require 'win32/dir'
|
15
15
|
true
|
@@ -21,17 +21,17 @@ class Hiera
|
|
21
21
|
|
22
22
|
def config_dir
|
23
23
|
if microsoft_windows?
|
24
|
-
File.join(common_appdata, 'PuppetLabs', '
|
24
|
+
File.join(common_appdata, 'PuppetLabs', 'code')
|
25
25
|
else
|
26
|
-
'/etc'
|
26
|
+
'/etc/puppetlabs/code'
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
def var_dir
|
31
31
|
if microsoft_windows?
|
32
|
-
File.join(common_appdata, 'PuppetLabs', '
|
32
|
+
File.join(common_appdata, 'PuppetLabs', 'code', 'hieradata')
|
33
33
|
else
|
34
|
-
'/
|
34
|
+
'/etc/puppetlabs/code/hieradata'
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
data/lib/hiera/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -9,6 +9,13 @@ require 'tmpdir'
|
|
9
9
|
RSpec.configure do |config|
|
10
10
|
config.mock_with :mocha
|
11
11
|
|
12
|
+
if Hiera::Util.microsoft_windows? && RUBY_VERSION =~ /^1\./
|
13
|
+
require 'win32console'
|
14
|
+
config.output_stream = $stdout
|
15
|
+
config.error_stream = $stderr
|
16
|
+
config.formatters.each { |f| f.instance_variable_set(:@output, $stdout) }
|
17
|
+
end
|
18
|
+
|
12
19
|
config.after :suite do
|
13
20
|
# Log the spec order to a file, but only if the LOG_SPEC_ORDER environment variable is
|
14
21
|
# set. This should be enabled on Jenkins runs, as it can be used with Nick L.'s bisect
|
@@ -21,6 +28,11 @@ RSpec.configure do |config|
|
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
31
|
+
# So everyone else doesn't have to include this base constant.
|
32
|
+
module HieraSpec
|
33
|
+
FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), 'unit', 'fixtures') unless defined?(FIXTURE_DIR)
|
34
|
+
end
|
35
|
+
|
24
36
|
# In ruby 1.8.5 Dir does not have mktmpdir defined, so this monkey patches
|
25
37
|
# Dir to include the 1.8.7 definition of that method if it isn't already defined.
|
26
38
|
# Method definition borrowed from ruby-1.8.7-p357/lib/ruby/1.8/tmpdir.rb
|
@@ -25,7 +25,7 @@ class Hiera
|
|
25
25
|
Backend.expects(:datafile).with(:json, {}, "one", "json").returns(nil)
|
26
26
|
Backend.expects(:datafile).with(:json, {}, "two", "json").returns(nil)
|
27
27
|
|
28
|
-
@backend.lookup("key", {}, nil, :priority)
|
28
|
+
expect { @backend.lookup("key", {}, nil, :priority, nil) }.to throw_symbol(:no_such_key)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should retain the data types found in data files" do
|
@@ -35,9 +35,9 @@ class Hiera
|
|
35
35
|
|
36
36
|
@cache.expects(:read_file).with("/nonexisting/one.json", Hash).returns({"stringval" => "string", "boolval" => true, "numericval" => 1}).times(3)
|
37
37
|
|
38
|
-
@backend.lookup("stringval", {}, nil, :priority).should == "string"
|
39
|
-
@backend.lookup("boolval", {}, nil, :priority).should == true
|
40
|
-
@backend.lookup("numericval", {}, nil, :priority).should == 1
|
38
|
+
@backend.lookup("stringval", {}, nil, :priority, nil).should == "string"
|
39
|
+
@backend.lookup("boolval", {}, nil, :priority, nil).should == true
|
40
|
+
@backend.lookup("numericval", {}, nil, :priority, nil).should == 1
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should pick data earliest source that has it for priority searches" do
|
@@ -49,12 +49,12 @@ class Hiera
|
|
49
49
|
File.stubs(:exist?).with("/nonexisting/one.json").returns(true)
|
50
50
|
@cache.expects(:read_file).with("/nonexisting/one.json", Hash).returns({"key" => "test_%{rspec}"})
|
51
51
|
|
52
|
-
@backend.lookup("key", scope, nil, :priority).should == "test_test"
|
52
|
+
@backend.lookup("key", scope, nil, :priority, nil).should == "test_test"
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should build an array of all data sources for array searches" do
|
56
56
|
Hiera::Backend.stubs(:empty_answer).returns([])
|
57
|
-
Backend.stubs(:parse_answer).with('answer', {}).returns("answer")
|
57
|
+
Backend.stubs(:parse_answer).with('answer', {}, {}, anything).returns("answer")
|
58
58
|
Backend.expects(:datafile).with(:json, {}, "one", "json").returns("/nonexisting/one.json")
|
59
59
|
Backend.expects(:datafile).with(:json, {}, "two", "json").returns("/nonexisting/two.json")
|
60
60
|
|
@@ -66,18 +66,18 @@ class Hiera
|
|
66
66
|
@cache.expects(:read_file).with("/nonexisting/one.json", Hash).returns({"key" => "answer"})
|
67
67
|
@cache.expects(:read_file).with("/nonexisting/two.json", Hash).returns({"key" => "answer"})
|
68
68
|
|
69
|
-
@backend.lookup("key", {}, nil, :array).should == ["answer", "answer"]
|
69
|
+
@backend.lookup("key", {}, nil, :array, nil).should == ["answer", "answer"]
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should parse the answer for scope variables" do
|
73
|
-
Backend.stubs(:parse_answer).with('test_%{rspec}', {'rspec' => 'test'}).returns("test_test")
|
73
|
+
Backend.stubs(:parse_answer).with('test_%{rspec}', {'rspec' => 'test'}, {}, anything).returns("test_test")
|
74
74
|
Backend.expects(:datasources).yields("one")
|
75
75
|
Backend.expects(:datafile).with(:json, {"rspec" => "test"}, "one", "json").returns("/nonexisting/one.json")
|
76
76
|
|
77
77
|
File.expects(:exist?).with("/nonexisting/one.json").returns(true)
|
78
78
|
@cache.expects(:read_file).with("/nonexisting/one.json", Hash).returns({"key" => "test_%{rspec}"})
|
79
79
|
|
80
|
-
@backend.lookup("key", {"rspec" => "test"}, nil, :priority).should == "test_test"
|
80
|
+
@backend.lookup("key", {"rspec" => "test"}, nil, :priority, nil).should == "test_test"
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
@@ -41,7 +41,7 @@ class Hiera
|
|
41
41
|
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).yields(["one", "/nonexisting/one.yaml"])
|
42
42
|
@cache.value = "---\nkey: answer"
|
43
43
|
|
44
|
-
@backend.lookup("key", {}, nil, :priority).should == "answer"
|
44
|
+
@backend.lookup("key", {}, nil, :priority, nil).should == "answer"
|
45
45
|
end
|
46
46
|
|
47
47
|
describe "handling unexpected YAML values" do
|
@@ -49,19 +49,24 @@ class Hiera
|
|
49
49
|
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).yields(["one", "/nonexisting/one.yaml"])
|
50
50
|
end
|
51
51
|
|
52
|
-
it "
|
52
|
+
it "throws :no_such_key when key is missing in YAML" do
|
53
53
|
@cache.value = "---\n"
|
54
|
-
@backend.lookup("key", {}, nil, :priority).
|
54
|
+
expect { @backend.lookup("key", {}, nil, :priority, nil) }.to throw_symbol(:no_such_key)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "returns nil when the YAML value is nil" do
|
58
|
+
@cache.value = "key: ~\n"
|
59
|
+
@backend.lookup("key", {}, nil, :priority, nil).should be_nil
|
55
60
|
end
|
56
61
|
|
57
|
-
it "
|
62
|
+
it "throws :no_such_key when the YAML file is false" do
|
58
63
|
@cache.value = ""
|
59
|
-
@backend.lookup("key", {}, nil, :priority).
|
64
|
+
expect { @backend.lookup("key", {}, nil, :priority, nil) }.to throw_symbol(:no_such_key)
|
60
65
|
end
|
61
66
|
|
62
67
|
it "raises a TypeError when the YAML value is not a hash" do
|
63
68
|
@cache.value = "---\n[one, two, three]"
|
64
|
-
expect { @backend.lookup("key", {}, nil, :priority) }.to raise_error(TypeError)
|
69
|
+
expect { @backend.lookup("key", {}, nil, :priority, nil) }.to raise_error(TypeError)
|
65
70
|
end
|
66
71
|
end
|
67
72
|
|
@@ -70,7 +75,7 @@ class Hiera
|
|
70
75
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>"answer"})
|
71
76
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>"answer"})
|
72
77
|
|
73
|
-
@backend.lookup("key", {}, nil, :array).should == ["answer", "answer"]
|
78
|
+
@backend.lookup("key", {}, nil, :array, nil).should == ["answer", "answer"]
|
74
79
|
end
|
75
80
|
|
76
81
|
it "should ignore empty hash of data sources for hash searches" do
|
@@ -79,7 +84,7 @@ class Hiera
|
|
79
84
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({})
|
80
85
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
81
86
|
|
82
|
-
@backend.lookup("key", {}, nil, :hash).should == {"a" => "answer"}
|
87
|
+
@backend.lookup("key", {}, nil, :hash, nil).should == {"a" => "answer"}
|
83
88
|
end
|
84
89
|
|
85
90
|
it "should build a merged hash of data sources for hash searches" do
|
@@ -88,7 +93,7 @@ class Hiera
|
|
88
93
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
89
94
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>{"b"=>"answer", "a"=>"wrong"}})
|
90
95
|
|
91
|
-
@backend.lookup("key", {}, nil, :hash).should == {"a" => "answer", "b" => "answer"}
|
96
|
+
@backend.lookup("key", {}, nil, :hash, nil).should == {"a" => "answer", "b" => "answer"}
|
92
97
|
end
|
93
98
|
|
94
99
|
it "should fail when trying to << a Hash" do
|
@@ -97,7 +102,7 @@ class Hiera
|
|
97
102
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>["a", "answer"]})
|
98
103
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
99
104
|
|
100
|
-
expect {@backend.lookup("key", {}, nil, :array)}.to raise_error(Exception, "Hiera type mismatch: expected Array and got Hash")
|
105
|
+
expect {@backend.lookup("key", {}, nil, :array, nil)}.to raise_error(Exception, "Hiera type mismatch for key 'key': expected Array and got Hash")
|
101
106
|
end
|
102
107
|
|
103
108
|
it "should fail when trying to merge an Array" do
|
@@ -106,7 +111,7 @@ class Hiera
|
|
106
111
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
107
112
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>["a", "wrong"]})
|
108
113
|
|
109
|
-
expect { @backend.lookup("key", {}, nil, :hash) }.to raise_error(Exception, "Hiera type mismatch: expected Hash and got Array")
|
114
|
+
expect { @backend.lookup("key", {}, nil, :hash, nil) }.to raise_error(Exception, "Hiera type mismatch for key 'key': expected Hash and got Array")
|
110
115
|
end
|
111
116
|
|
112
117
|
it "should parse the answer for scope variables" do
|
@@ -114,7 +119,7 @@ class Hiera
|
|
114
119
|
|
115
120
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>"test_%{rspec}"})
|
116
121
|
|
117
|
-
@backend.lookup("key", {"rspec" => "test"}, nil, :priority).should == "test_test"
|
122
|
+
@backend.lookup("key", {"rspec" => "test"}, nil, :priority, nil).should == "test_test"
|
118
123
|
end
|
119
124
|
|
120
125
|
it "should retain datatypes found in yaml files" do
|
@@ -123,9 +128,9 @@ class Hiera
|
|
123
128
|
|
124
129
|
@cache.value = "---\nstringval: 'string'\nboolval: true\nnumericval: 1"
|
125
130
|
|
126
|
-
@backend.lookup("stringval", {}, nil, :priority).should == "string"
|
127
|
-
@backend.lookup("boolval", {}, nil, :priority).should == true
|
128
|
-
@backend.lookup("numericval", {}, nil, :priority).should == 1
|
131
|
+
@backend.lookup("stringval", {}, nil, :priority, nil).should == "string"
|
132
|
+
@backend.lookup("boolval", {}, nil, :priority, nil).should == true
|
133
|
+
@backend.lookup("numericval", {}, nil, :priority, nil).should == 1
|
129
134
|
end
|
130
135
|
end
|
131
136
|
end
|
data/spec/unit/backend_spec.rb
CHANGED
@@ -2,6 +2,14 @@ require 'spec_helper'
|
|
2
2
|
require 'hiera/util'
|
3
3
|
|
4
4
|
class Hiera
|
5
|
+
module Backend
|
6
|
+
class Backend1x_backend
|
7
|
+
def lookup(key, scope, order_override, resolution_type)
|
8
|
+
["a", "b"]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
5
13
|
describe Backend do
|
6
14
|
describe "#datadir" do
|
7
15
|
it "interpolates any values in the configured value" do
|
@@ -84,7 +92,7 @@ class Hiera
|
|
84
92
|
end
|
85
93
|
|
86
94
|
it "parses the names of the hierarchy levels using the given scope" do
|
87
|
-
Backend.expects(:parse_string).with("common", {:rspec => :tests})
|
95
|
+
Backend.expects(:parse_string).with("common", {:rspec => :tests}, {}, {:order_override => nil})
|
88
96
|
Backend.datasources({:rspec => :tests}) { }
|
89
97
|
end
|
90
98
|
|
@@ -181,17 +189,6 @@ class Hiera
|
|
181
189
|
"test_%{scope('rspec')}_test" => "test__test"
|
182
190
|
}
|
183
191
|
|
184
|
-
@interprets_undefined_in_scope_tests.each do |input, expected|
|
185
|
-
it "interprets :undefined in scope as a non-value" do
|
186
|
-
Backend.parse_string(input, {"rspec" => :undefined}).should == expected
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
it "uses the value from extra_data when scope is :undefined" do
|
191
|
-
input = "test_%{rspec}_test"
|
192
|
-
Backend.parse_string(input, {"rspec" => :undefined}, { "rspec" => "extra" }).should == "test_extra_test"
|
193
|
-
end
|
194
|
-
|
195
192
|
@exact_lookup_tests = {
|
196
193
|
"test_%{::rspec::data}_test" => "test_value_test",
|
197
194
|
"test_%{scope('::rspec::data')}_test" => "test_value_test"
|
@@ -264,10 +261,21 @@ class Hiera
|
|
264
261
|
scope = {}
|
265
262
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
266
263
|
Config.load_backends
|
267
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("key1", scope, nil, :priority).returns("answer")
|
264
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("key1", scope, nil, :priority, instance_of(Hash)).returns("answer")
|
268
265
|
|
269
266
|
Backend.parse_string(input, scope).should == "answer"
|
270
267
|
end
|
268
|
+
|
269
|
+
it "interpolation passes the order_override back into the backend" do
|
270
|
+
Backend.expects(:lookup).with("lookup::key", nil, {}, "order_override_datasource", :priority, instance_of(Hash))
|
271
|
+
Backend.parse_string("%{hiera('lookup::key')}", {}, {}, {:order_override => "order_override_datasource"})
|
272
|
+
end
|
273
|
+
|
274
|
+
it "replaces literal interpolations with their argument" do
|
275
|
+
scope = {}
|
276
|
+
input = "%{literal('%')}{rspec::data}"
|
277
|
+
Backend.parse_string(input, scope).should == "%{rspec::data}"
|
278
|
+
end
|
271
279
|
end
|
272
280
|
|
273
281
|
describe "#parse_answer" do
|
@@ -306,16 +314,47 @@ class Hiera
|
|
306
314
|
scope = {}
|
307
315
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
308
316
|
Config.load_backends
|
309
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("test")
|
317
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("test")
|
310
318
|
Backend.parse_answer(input, scope).should == "test_test_test"
|
311
319
|
end
|
312
320
|
|
321
|
+
it "interpolates alias lookups with non-string types" do
|
322
|
+
input = "%{alias('rspec')}"
|
323
|
+
scope = {}
|
324
|
+
Config.load({:yaml => {:datadir => "/tmp"}})
|
325
|
+
Config.load_backends
|
326
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns(['test', 'test'])
|
327
|
+
Backend.parse_answer(input, scope).should == ['test', 'test']
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'fails if alias interpolation is attempted in a string context with a prefix' do
|
331
|
+
input = "stuff_before%{alias('rspec')}"
|
332
|
+
scope = {}
|
333
|
+
Config.load({:yaml => {:datadir => "/tmp"}})
|
334
|
+
Config.load_backends
|
335
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns(['test', 'test'])
|
336
|
+
expect do
|
337
|
+
Backend.parse_answer(input, scope).should == ['test', 'test']
|
338
|
+
end.to raise_error(Hiera::InterpolationInvalidValue, 'Cannot call alias in the string context')
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'fails if alias interpolation is attempted in a string context with a postfix' do
|
342
|
+
input = "%{alias('rspec')}_stiff after"
|
343
|
+
scope = {}
|
344
|
+
Config.load({:yaml => {:datadir => "/tmp"}})
|
345
|
+
Config.load_backends
|
346
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns(['test', 'test'])
|
347
|
+
expect do
|
348
|
+
Backend.parse_answer(input, scope).should == ['test', 'test']
|
349
|
+
end.to raise_error(Hiera::InterpolationInvalidValue, 'Cannot call alias in the string context')
|
350
|
+
end
|
351
|
+
|
313
352
|
it "interpolates hiera lookups in each string in an array" do
|
314
353
|
input = ["test_%{hiera('rspec')}_test", "test_%{hiera('rspec')}_test", ["test_%{hiera('rspec')}_test"]]
|
315
354
|
scope = {}
|
316
355
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
317
356
|
Config.load_backends
|
318
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("test")
|
357
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("test")
|
319
358
|
Backend.parse_answer(input, scope).should == ["test_test_test", "test_test_test", ["test_test_test"]]
|
320
359
|
end
|
321
360
|
|
@@ -324,7 +363,7 @@ class Hiera
|
|
324
363
|
scope = {}
|
325
364
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
326
365
|
Config.load_backends
|
327
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("test")
|
366
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("test")
|
328
367
|
Backend.parse_answer(input, scope).should == {"foo"=>"test_test_test", "bar"=>"test_test_test"}
|
329
368
|
end
|
330
369
|
|
@@ -333,7 +372,7 @@ class Hiera
|
|
333
372
|
scope = {}
|
334
373
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
335
374
|
Config.load_backends
|
336
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("foo")
|
375
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("foo")
|
337
376
|
Backend.parse_answer(input, scope).should == {"foo"=>"test"}
|
338
377
|
end
|
339
378
|
|
@@ -342,7 +381,7 @@ class Hiera
|
|
342
381
|
scope = {}
|
343
382
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
344
383
|
Config.load_backends
|
345
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("foo")
|
384
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("foo")
|
346
385
|
Backend.parse_answer(input, scope).should == {"topkey"=>{"foo" => "test"}}
|
347
386
|
end
|
348
387
|
|
@@ -351,7 +390,7 @@ class Hiera
|
|
351
390
|
scope = {}
|
352
391
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
353
392
|
Config.load_backends
|
354
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("test")
|
393
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("test")
|
355
394
|
Backend.parse_answer(input, scope).should == {"foo"=>"test_test_test", "bar"=>["test_test_test", "test_test_test"]}
|
356
395
|
end
|
357
396
|
|
@@ -360,7 +399,7 @@ class Hiera
|
|
360
399
|
scope = {"rspec2" => "scope_rspec"}
|
361
400
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
362
401
|
Config.load_backends
|
363
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("hiera_rspec")
|
402
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("hiera_rspec")
|
364
403
|
Backend.parse_answer(input, scope).should == {"foo"=>"test_hiera_rspec_test", "bar"=>"test_scope_rspec_test"}
|
365
404
|
end
|
366
405
|
|
@@ -369,7 +408,7 @@ class Hiera
|
|
369
408
|
scope = {"rspec" => "scope_rspec"}
|
370
409
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
371
410
|
Config.load_backends
|
372
|
-
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority).returns("hiera_rspec")
|
411
|
+
Backend::Yaml_backend.any_instance.stubs(:lookup).with("rspec", scope, nil, :priority, instance_of(Hash)).returns("hiera_rspec")
|
373
412
|
Backend.parse_answer(input, scope).should == "test_hiera_rspec_test_scope_rspec"
|
374
413
|
end
|
375
414
|
|
@@ -431,7 +470,7 @@ class Hiera
|
|
431
470
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
432
471
|
Config.load_backends
|
433
472
|
|
434
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, nil).returns("answer")
|
473
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, nil, instance_of(Hash)).returns("answer")
|
435
474
|
|
436
475
|
Backend.lookup("key", "default", {}, nil, nil).should == "answer"
|
437
476
|
end
|
@@ -440,9 +479,9 @@ class Hiera
|
|
440
479
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
441
480
|
Config.load_backends
|
442
481
|
|
443
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("stringval", {}, nil, nil).returns("string")
|
444
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("boolval", {}, nil, nil).returns(false)
|
445
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("numericval", {}, nil, nil).returns(1)
|
482
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("stringval", {}, nil, nil, instance_of(Hash)).returns("string")
|
483
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("boolval", {}, nil, nil, instance_of(Hash)).returns(false)
|
484
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("numericval", {}, nil, nil, instance_of(Hash)).returns(1)
|
446
485
|
|
447
486
|
Backend.lookup("stringval", "default", {}, nil, nil).should == "string"
|
448
487
|
Backend.lookup("boolval", "default", {}, nil, nil).should == false
|
@@ -524,7 +563,7 @@ class Hiera
|
|
524
563
|
Config.load_backends
|
525
564
|
|
526
565
|
Backend.expects(:resolve_answer).with("test_test", :priority).returns("parsed")
|
527
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {"rspec" => "test"}, nil, :priority).returns("test_test")
|
566
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {"rspec" => "test"}, nil, :priority, instance_of(Hash)).returns("test_test")
|
528
567
|
|
529
568
|
Backend.lookup("key", "test_%{rspec}", {"rspec" => "test"}, nil, :priority).should == "parsed"
|
530
569
|
end
|
@@ -533,31 +572,129 @@ class Hiera
|
|
533
572
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
534
573
|
Config.load_backends
|
535
574
|
|
536
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {"rspec" => "test"}, nil, nil)
|
575
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {"rspec" => "test"}, nil, nil, instance_of(Hash)).throws(:no_such_key)
|
537
576
|
|
538
577
|
Backend.lookup("key", "test_%{rspec}", {"rspec" => "test"}, nil, nil).should == "test_test"
|
539
578
|
end
|
540
579
|
|
580
|
+
it "returns nil instead of the default when key is found with a nil value" do
|
581
|
+
Config.load({:yaml => {:datadir => "/tmp"}})
|
582
|
+
Config.load_backends
|
583
|
+
|
584
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {"rspec" => "test"}, nil, nil, instance_of(Hash)).returns(nil)
|
585
|
+
|
586
|
+
Backend.lookup("key", "test_%{rspec}", {"rspec" => "test"}, nil, nil).should == nil
|
587
|
+
end
|
588
|
+
|
541
589
|
it "keeps string default data as a string" do
|
542
590
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
543
591
|
Config.load_backends
|
544
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, nil)
|
592
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, nil, instance_of(Hash)).throws(:no_such_key)
|
545
593
|
Backend.lookup("key", "test", {}, nil, nil).should == "test"
|
546
594
|
end
|
547
595
|
|
548
596
|
it "keeps array default data as an array" do
|
549
597
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
550
598
|
Config.load_backends
|
551
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, :array)
|
599
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, :array, instance_of(Hash)).throws(:no_such_key)
|
552
600
|
Backend.lookup("key", ["test"], {}, nil, :array).should == ["test"]
|
553
601
|
end
|
554
602
|
|
555
603
|
it "keeps hash default data as a hash" do
|
556
604
|
Config.load({:yaml => {:datadir => "/tmp"}})
|
557
605
|
Config.load_backends
|
558
|
-
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, :hash)
|
606
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with("key", {}, nil, :hash, instance_of(Hash)).throws(:no_such_key)
|
559
607
|
Backend.lookup("key", {"test" => "value"}, {}, nil, :hash).should == {"test" => "value"}
|
560
608
|
end
|
609
|
+
|
610
|
+
it 'can use qualified key to lookup value in hash' do
|
611
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
612
|
+
Config.load_backends
|
613
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, nil, instance_of(Hash)).returns({ 'test' => 'value'})
|
614
|
+
Backend.lookup('key.test', 'dflt', {}, nil, nil).should == 'value'
|
615
|
+
end
|
616
|
+
|
617
|
+
it 'can use qualified key to lookup value in array' do
|
618
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
619
|
+
Config.load_backends
|
620
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, nil, instance_of(Hash)).returns([ 'first', 'second'])
|
621
|
+
Backend.lookup('key.1', 'dflt', {}, nil, nil).should == 'second'
|
622
|
+
end
|
623
|
+
|
624
|
+
it 'will fail when qualified key is partially found but not expected hash' do
|
625
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
626
|
+
Config.load_backends
|
627
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, nil, instance_of(Hash)).returns(['value 1', 'value 2'])
|
628
|
+
expect do
|
629
|
+
Backend.lookup('key.test', 'dflt', {}, nil, nil)
|
630
|
+
end.to raise_error(Exception, /^Hiera type mismatch:/)
|
631
|
+
end
|
632
|
+
|
633
|
+
it 'will fail when qualified key used with resolution_type :hash' do
|
634
|
+
expect do
|
635
|
+
Backend.lookup('key.test', 'dflt', {}, nil, :hash)
|
636
|
+
end.to raise_error(ArgumentError, /^Resolution type :hash is illegal/)
|
637
|
+
end
|
638
|
+
|
639
|
+
it 'will fail when qualified key used with resolution_type :array' do
|
640
|
+
expect do
|
641
|
+
Backend.lookup('key.test', 'dflt', {}, nil, :array)
|
642
|
+
end.to raise_error(ArgumentError, /^Resolution type :array is illegal/)
|
643
|
+
end
|
644
|
+
|
645
|
+
it 'will succeed when qualified key used with resolution_type :priority' do
|
646
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
647
|
+
Config.load_backends
|
648
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, :priority, instance_of(Hash)).returns({ 'test' => 'value'})
|
649
|
+
Backend.lookup('key.test', 'dflt', {}, nil, :priority).should == 'value'
|
650
|
+
end
|
651
|
+
|
652
|
+
it 'will fail when qualified key is partially found but not expected array' do
|
653
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
654
|
+
Config.load_backends
|
655
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, nil, instance_of(Hash)).returns({ 'test' => 'value'})
|
656
|
+
expect do
|
657
|
+
Backend.lookup('key.2', 'dflt', {}, nil, nil)
|
658
|
+
end.to raise_error(Exception, /^Hiera type mismatch:/)
|
659
|
+
end
|
660
|
+
|
661
|
+
it 'will not fail when qualified key is partially not found' do
|
662
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
663
|
+
Config.load_backends
|
664
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, nil, instance_of(Hash)).returns(nil)
|
665
|
+
Backend.lookup('key.test', 'dflt', {}, nil, nil).should == 'dflt'
|
666
|
+
end
|
667
|
+
|
668
|
+
it 'will not fail when qualified key is array index out of bounds' do
|
669
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
670
|
+
Config.load_backends
|
671
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', {}, nil, nil, instance_of(Hash)).returns(['value 1', 'value 2'])
|
672
|
+
Backend.lookup('key.33', 'dflt', {}, nil, nil).should == 'dflt'
|
673
|
+
end
|
674
|
+
|
675
|
+
it 'can use qualified key in interpolation to lookup value in hash' do
|
676
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
677
|
+
Config.load_backends
|
678
|
+
Hiera::Backend.stubs(:datasourcefiles).yields('foo', 'bar')
|
679
|
+
Hiera::Filecache.any_instance.expects(:read_file).at_most(2).returns({'key' => '%{hiera(\'some.subkey\')}', 'some' => { 'subkey' => 'value' }})
|
680
|
+
Backend.lookup('key', 'dflt', {}, nil, nil).should == 'value'
|
681
|
+
end
|
682
|
+
|
683
|
+
it 'can use qualified key in interpolated default and scope' do
|
684
|
+
Config.load({:yaml => {:datadir => '/tmp'}})
|
685
|
+
Config.load_backends
|
686
|
+
scope = { 'some' => { 'test' => 'value'}}
|
687
|
+
Backend::Yaml_backend.any_instance.expects(:lookup).with('key', scope, nil, nil, instance_of(Hash))
|
688
|
+
Backend.lookup('key.notfound', '%{some.test}', scope, nil, nil).should == 'value'
|
689
|
+
end
|
690
|
+
|
691
|
+
it "handles older backend with 4 argument lookup" do
|
692
|
+
Config.load({})
|
693
|
+
Config.instance_variable_set("@config", {:backends => ["Backend1x"]})
|
694
|
+
|
695
|
+
Hiera.expects(:debug).at_least_once.with(regexp_matches /Using Hiera 1.x backend/)
|
696
|
+
Backend.lookup("key", {}, {"rspec" => "test"}, nil, :priority).should == ["a", "b"]
|
697
|
+
end
|
561
698
|
end
|
562
699
|
|
563
700
|
describe '#merge_answer' do
|
@@ -575,13 +712,30 @@ class Hiera
|
|
575
712
|
|
576
713
|
it "uses deep_merge! when configured with :merge_behavior => :deeper" do
|
577
714
|
Config.load({:merge_behavior => :deeper})
|
578
|
-
Hash.any_instance.expects('deep_merge!').with({"b" => "bnswer"}).returns({"a" => "answer", "b" => "bnswer"})
|
715
|
+
Hash.any_instance.expects('deep_merge!').with({"b" => "bnswer"}, {}).returns({"a" => "answer", "b" => "bnswer"})
|
579
716
|
Backend.merge_answer({"a" => "answer"},{"b" => "bnswer"}).should == {"a" => "answer", "b" => "bnswer"}
|
580
717
|
end
|
581
718
|
|
582
719
|
it "uses deep_merge when configured with :merge_behavior => :deep" do
|
583
720
|
Config.load({:merge_behavior => :deep})
|
584
|
-
Hash.any_instance.expects('deep_merge').with({"b" => "bnswer"}).returns({"a" => "answer", "b" => "bnswer"})
|
721
|
+
Hash.any_instance.expects('deep_merge').with({"b" => "bnswer"}, {}).returns({"a" => "answer", "b" => "bnswer"})
|
722
|
+
Backend.merge_answer({"a" => "answer"},{"b" => "bnswer"}).should == {"a" => "answer", "b" => "bnswer"}
|
723
|
+
end
|
724
|
+
|
725
|
+
it "disregards configuration when 'merge' parameter is given as a Hash" do
|
726
|
+
Config.load({:merge_behavior => :deep})
|
727
|
+
Hash.any_instance.expects('deep_merge!').with({"b" => "bnswer"}, {}).returns({"a" => "answer", "b" => "bnswer"})
|
728
|
+
Backend.merge_answer({"a" => "answer"},{"b" => "bnswer"}, {:behavior => 'deeper' }).should == {"a" => "answer", "b" => "bnswer"}
|
729
|
+
end
|
730
|
+
|
731
|
+
it "propagates deep merge options when given Hash 'merge' parameter" do
|
732
|
+
Hash.any_instance.expects('deep_merge!').with({"b" => "bnswer"}, { :knockout_prefix => '-' }).returns({"a" => "answer", "b" => "bnswer"})
|
733
|
+
Backend.merge_answer({"a" => "answer"},{"b" => "bnswer"}, {:behavior => 'deeper', :knockout_prefix => '-'}).should == {"a" => "answer", "b" => "bnswer"}
|
734
|
+
end
|
735
|
+
|
736
|
+
it "passes Config[:deep_merge_options] into calls to deep_merge" do
|
737
|
+
Config.load({:merge_behavior => :deep, :deep_merge_options => { :knockout_prefix => '-' } })
|
738
|
+
Hash.any_instance.expects('deep_merge').with({"b" => "bnswer"}, {:knockout_prefix => '-'}).returns({"a" => "answer", "b" => "bnswer"})
|
585
739
|
Backend.merge_answer({"a" => "answer"},{"b" => "bnswer"}).should == {"a" => "answer", "b" => "bnswer"}
|
586
740
|
end
|
587
741
|
end
|