hiera 1.3.0 → 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 +7 -0
- data/LICENSE +1 -1
- data/README.md +47 -10
- data/bin/hiera +48 -27
- data/lib/hiera/backend/json_backend.rb +9 -7
- data/lib/hiera/backend/yaml_backend.rb +17 -14
- data/lib/hiera/backend.rb +163 -44
- data/lib/hiera/config.rb +1 -3
- data/lib/hiera/interpolate.rb +64 -14
- data/lib/hiera/util.rb +5 -5
- data/lib/hiera/version.rb +1 -1
- data/lib/hiera.rb +55 -3
- data/spec/spec_helper.rb +23 -0
- data/spec/unit/backend/json_backend_spec.rb +9 -9
- data/spec/unit/backend/yaml_backend_spec.rb +62 -73
- data/spec/unit/backend_spec.rb +192 -32
- data/spec/unit/config_spec.rb +17 -2
- 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 +51 -41
data/lib/hiera/interpolate.rb
CHANGED
@@ -1,28 +1,71 @@
|
|
1
1
|
require 'hiera/backend'
|
2
|
+
require 'hiera/recursive_guard'
|
3
|
+
|
4
|
+
|
5
|
+
class Hiera::InterpolationInvalidValue < StandardError; end
|
2
6
|
|
3
7
|
class Hiera::Interpolate
|
4
8
|
class << self
|
5
9
|
INTERPOLATION = /%\{([^\}]*)\}/
|
6
|
-
METHOD_INTERPOLATION = /%\{(scope|hiera)\(['"]([^"']*)["']\)\}/
|
10
|
+
METHOD_INTERPOLATION = /%\{(scope|hiera|literal|alias)\(['"]([^"']*)["']\)\}/
|
11
|
+
|
12
|
+
def interpolate(data, scope, extra_data, context)
|
13
|
+
if data.is_a?(String)
|
14
|
+
# Wrapping do_interpolation in a gsub block ensures we process
|
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
|
19
|
+
data.gsub(INTERPOLATION) do |match|
|
20
|
+
interp_val = do_interpolation(match, scope, extra_data, new_context)
|
7
21
|
|
8
|
-
|
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
|
38
|
+
end
|
39
|
+
else
|
40
|
+
data
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def do_interpolation(data, scope, extra_data, context)
|
9
45
|
if data.is_a?(String) && (match = data.match(INTERPOLATION))
|
10
46
|
interpolation_variable = match[1]
|
11
|
-
recurse_guard.check(interpolation_variable) do
|
47
|
+
context[:recurse_guard].check(interpolation_variable) do
|
12
48
|
interpolate_method, key = get_interpolation_method_and_key(data)
|
13
|
-
interpolated_data = send(interpolate_method, data, key, scope, extra_data)
|
14
|
-
|
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)
|
15
55
|
end
|
16
56
|
else
|
17
57
|
data
|
18
58
|
end
|
19
59
|
end
|
60
|
+
private :do_interpolation
|
20
61
|
|
21
62
|
def get_interpolation_method_and_key(data)
|
22
63
|
if (match = data.match(METHOD_INTERPOLATION))
|
23
64
|
case match[1]
|
24
65
|
when 'hiera' then [:hiera_interpolate, match[2]]
|
25
66
|
when 'scope' then [:scope_interpolate, match[2]]
|
67
|
+
when 'literal' then [:literal_interpolate, match[2]]
|
68
|
+
when 'alias' then [:alias_interpolate, match[2]]
|
26
69
|
end
|
27
70
|
elsif (match = data.match(INTERPOLATION))
|
28
71
|
[:scope_interpolate, match[1]]
|
@@ -30,19 +73,26 @@ class Hiera::Interpolate
|
|
30
73
|
end
|
31
74
|
private :get_interpolation_method_and_key
|
32
75
|
|
33
|
-
def scope_interpolate(data, key, scope, extra_data)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
data.sub(INTERPOLATION, value.to_s)
|
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) }
|
39
80
|
end
|
40
81
|
private :scope_interpolate
|
41
82
|
|
42
|
-
def hiera_interpolate(data, key, scope, extra_data)
|
43
|
-
|
44
|
-
data.sub(METHOD_INTERPOLATION, value)
|
83
|
+
def hiera_interpolate(data, key, scope, extra_data, context)
|
84
|
+
Hiera::Backend.lookup(key, nil, scope, context[:order_override], :priority, context)
|
45
85
|
end
|
46
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
|
47
97
|
end
|
48
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/lib/hiera.rb
CHANGED
@@ -49,15 +49,67 @@ class Hiera
|
|
49
49
|
|
50
50
|
# Calls the backends to do the actual lookup.
|
51
51
|
#
|
52
|
-
# The
|
52
|
+
# The _scope_ can be anything that responds to `[]`, if you have input
|
53
53
|
# data like a Puppet Scope that does not you can wrap that data in a
|
54
|
-
# class that has a [] method that fetches the data from your source.
|
54
|
+
# class that has a `[]` method that fetches the data from your source.
|
55
55
|
# See hiera-puppet for an example of this.
|
56
56
|
#
|
57
57
|
# The order-override will insert as first in the hierarchy a data source
|
58
58
|
# of your choice.
|
59
|
+
#
|
60
|
+
# Possible values for the _resolution_type_ parameter:
|
61
|
+
#
|
62
|
+
# - _:priority_ - This is the default. First found value is returned and no merge is performed
|
63
|
+
# - _:array_ - An array merge lookup assembles a value from every matching level of the hierarchy. It retrieves all
|
64
|
+
# of the (string or array) values for a given key, then flattens them into a single array of unique values.
|
65
|
+
# If _priority_ lookup can be thought of as a “default with overrides” pattern, _array_ merge lookup can be though
|
66
|
+
# of as “default with additions.”
|
67
|
+
# - _:hash_ - A hash merge lookup assembles a value from every matching level of the hierarchy. It retrieves all of
|
68
|
+
# the (hash) values for a given key, then merges the hashes into a single hash. Hash merge lookups will fail with
|
69
|
+
# an error if any of the values found in the data sources are strings or arrays. It only works when every value
|
70
|
+
# found is a hash. The actual merge behavior is determined by looking up the keys `:merge_behavior` and
|
71
|
+
# `:deep_merge_options` in the Hiera config. `:merge_behavior` can be set to `:deep`, :deeper` or `:native`
|
72
|
+
# (explained in detail below).
|
73
|
+
# - _{ deep merge options }_ - Configured values for `:merge_behavior` and `:deep_merge_options`will be completely
|
74
|
+
# ignored. Instead the _resolution_type_ will be a `:hash` merge where the `:merge_behavior` will be the value
|
75
|
+
# keyed by `:behavior` in the given hash and the `:deep_merge_options` will be the remaining top level entries of
|
76
|
+
# that same hash.
|
77
|
+
#
|
78
|
+
# Valid behaviors for the _:hash_ resolution type:
|
79
|
+
#
|
80
|
+
# - _native_ - Performs a simple hash-merge by overwriting keys of lower lookup priority.
|
81
|
+
# - _deeper_ - In a deeper hash merge, Hiera recursively merges keys and values in each source hash. For each key,
|
82
|
+
# if the value is:
|
83
|
+
# - only present in one source hash, it goes into the final hash.
|
84
|
+
# - a string/number/boolean and exists in two or more source hashes, the highest priority value goes into
|
85
|
+
# the final hash.
|
86
|
+
# - an array and exists in two or more source hashes, the values from each source are merged into a single
|
87
|
+
# array and de-duplicated (but not automatically flattened, as in an array merge lookup).
|
88
|
+
# - a hash and exists in two or more source hashes, the values from each source are recursively merged, as
|
89
|
+
# though they were source hashes.
|
90
|
+
# - mismatched between two or more source hashes, we haven’t validated the behavior. It should act as
|
91
|
+
# described in the deep_merge gem documentation.
|
92
|
+
# - _deep_ - In a deep hash merge, Hiera behaves the same as for _deeper_, except that when a string/number/boolean
|
93
|
+
# exists in two or more source hashes, the lowest priority value goes into the final hash. This is considered
|
94
|
+
# largely useless and should be avoided. Use _deeper_ instead.
|
95
|
+
#
|
96
|
+
# The _merge_ can be given as a hash with the mandatory key `:strategy` to denote the actual strategy. This
|
97
|
+
# is useful for the `:deeper` and `:deep` strategy since they can use additional options to control the behavior.
|
98
|
+
# The options can be passed as top level keys in the `merge` parameter when it is a given as a hash. Recognized
|
99
|
+
# options are:
|
100
|
+
#
|
101
|
+
# - 'knockout_prefix' Set to string value to signify prefix which deletes elements from existing element. Defaults is _undef_
|
102
|
+
# - 'sort_merged_arrays' Set to _true_ to sort all arrays that are merged together. Default is _false_
|
103
|
+
# - 'unpack_arrays' Set to string value used as a deliminator to join all array values and then split them again. Default is _undef_
|
104
|
+
# - 'merge_hash_arrays' Set to _true_ to merge hashes within arrays. Default is _false_
|
105
|
+
#
|
106
|
+
# @param key [String] The key to lookup
|
107
|
+
# @param default [Object,nil] The value to return when there is no match for _key_
|
108
|
+
# @param scope [#[],nil] The scope to use for the lookup
|
109
|
+
# @param order_override [#[]] An override that will considered the first source of lookup
|
110
|
+
# @param resolution_type [String,Hash<Symbol,String>] Symbolic resolution type or deep merge configuration
|
111
|
+
# @return [Object] The found value or the given _default_ value
|
59
112
|
def lookup(key, default, scope, order_override=nil, resolution_type=:priority)
|
60
113
|
Backend.lookup(key, default, scope, order_override, resolution_type)
|
61
114
|
end
|
62
115
|
end
|
63
|
-
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,29 @@ require 'tmpdir'
|
|
8
8
|
|
9
9
|
RSpec.configure do |config|
|
10
10
|
config.mock_with :mocha
|
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
|
+
|
19
|
+
config.after :suite do
|
20
|
+
# Log the spec order to a file, but only if the LOG_SPEC_ORDER environment variable is
|
21
|
+
# set. This should be enabled on Jenkins runs, as it can be used with Nick L.'s bisect
|
22
|
+
# script to help identify and debug order-dependent spec failures.
|
23
|
+
if ENV['LOG_SPEC_ORDER']
|
24
|
+
File.open("./spec_order.txt", "w") do |logfile|
|
25
|
+
config.instance_variable_get(:@files_to_run).each { |f| logfile.puts f }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
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)
|
11
34
|
end
|
12
35
|
|
13
36
|
# In ruby 1.8.5 Dir does not have mktmpdir defined, so this monkey patches
|
@@ -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
|
@@ -3,12 +3,29 @@ require 'hiera/backend/yaml_backend'
|
|
3
3
|
|
4
4
|
class Hiera
|
5
5
|
module Backend
|
6
|
+
class FakeCache
|
7
|
+
attr_accessor :value
|
8
|
+
def read(path, expected_type, default, &block)
|
9
|
+
read_file(path, expected_type, &block)
|
10
|
+
rescue => e
|
11
|
+
default
|
12
|
+
end
|
13
|
+
|
14
|
+
def read_file(path, expected_type, &block)
|
15
|
+
output = block.call(@value)
|
16
|
+
if !output.is_a? expected_type
|
17
|
+
raise TypeError
|
18
|
+
end
|
19
|
+
output
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
6
23
|
describe Yaml_backend do
|
7
24
|
before do
|
8
25
|
Config.load({})
|
9
26
|
Hiera.stubs(:debug)
|
10
27
|
Hiera.stubs(:warn)
|
11
|
-
@cache =
|
28
|
+
@cache = FakeCache.new
|
12
29
|
@backend = Yaml_backend.new(@cache)
|
13
30
|
end
|
14
31
|
|
@@ -20,128 +37,100 @@ class Hiera
|
|
20
37
|
end
|
21
38
|
|
22
39
|
describe "#lookup" do
|
23
|
-
it "should look for data in all sources" do
|
24
|
-
Backend.expects(:datasources).multiple_yields(["one"], ["two"])
|
25
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns(nil)
|
26
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns(nil)
|
27
|
-
|
28
|
-
@backend.lookup("key", {}, nil, :priority)
|
29
|
-
end
|
30
|
-
|
31
40
|
it "should pick data earliest source that has it for priority searches" do
|
32
|
-
Backend.expects(:
|
33
|
-
|
34
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns(nil).never
|
35
|
-
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>"answer"})
|
36
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
37
|
-
|
38
|
-
@backend.lookup("key", {}, nil, :priority).should == "answer"
|
39
|
-
end
|
41
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).yields(["one", "/nonexisting/one.yaml"])
|
42
|
+
@cache.value = "---\nkey: answer"
|
40
43
|
|
41
|
-
|
42
|
-
Backend.expects(:datasources).multiple_yields(["one"])
|
43
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns(nil)
|
44
|
-
YAML.expects(:load_file).never
|
45
|
-
|
46
|
-
@backend.lookup("key", {}, nil, :priority)
|
44
|
+
@backend.lookup("key", {}, nil, :priority, nil).should == "answer"
|
47
45
|
end
|
48
46
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
47
|
+
describe "handling unexpected YAML values" do
|
48
|
+
before do
|
49
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).yields(["one", "/nonexisting/one.yaml"])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "throws :no_such_key when key is missing in YAML" do
|
53
|
+
@cache.value = "---\n"
|
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
|
60
|
+
end
|
61
|
+
|
62
|
+
it "throws :no_such_key when the YAML file is false" do
|
63
|
+
@cache.value = ""
|
64
|
+
expect { @backend.lookup("key", {}, nil, :priority, nil) }.to throw_symbol(:no_such_key)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "raises a TypeError when the YAML value is not a hash" do
|
68
|
+
@cache.value = "---\n[one, two, three]"
|
69
|
+
expect { @backend.lookup("key", {}, nil, :priority, nil) }.to raise_error(TypeError)
|
70
|
+
end
|
56
71
|
end
|
57
72
|
|
58
73
|
it "should build an array of all data sources for array searches" do
|
59
|
-
Backend.expects(:
|
60
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns("/nonexisting/one.yaml")
|
61
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns("/nonexisting/two.yaml")
|
62
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
63
|
-
File.stubs(:exist?).with("/nonexisting/two.yaml").returns(true)
|
64
|
-
|
74
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"], ["two", "/nonexisting/two.yaml"])
|
65
75
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>"answer"})
|
66
76
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>"answer"})
|
67
77
|
|
68
|
-
@backend.lookup("key", {}, nil, :array).should == ["answer", "answer"]
|
78
|
+
@backend.lookup("key", {}, nil, :array, nil).should == ["answer", "answer"]
|
69
79
|
end
|
70
80
|
|
71
81
|
it "should ignore empty hash of data sources for hash searches" do
|
72
|
-
Backend.expects(:
|
73
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns("/nonexisting/one.yaml")
|
74
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns("/nonexisting/two.yaml")
|
75
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
76
|
-
File.stubs(:exist?).with("/nonexisting/two.yaml").returns(true)
|
82
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"], ["two", "/nonexisting/two.yaml"])
|
77
83
|
|
78
84
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({})
|
79
85
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
80
86
|
|
81
|
-
@backend.lookup("key", {}, nil, :hash).should == {"a" => "answer"}
|
87
|
+
@backend.lookup("key", {}, nil, :hash, nil).should == {"a" => "answer"}
|
82
88
|
end
|
83
89
|
|
84
90
|
it "should build a merged hash of data sources for hash searches" do
|
85
|
-
Backend.expects(:
|
86
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns("/nonexisting/one.yaml")
|
87
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns("/nonexisting/two.yaml")
|
88
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
89
|
-
File.stubs(:exist?).with("/nonexisting/two.yaml").returns(true)
|
91
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"], ["two", "/nonexisting/two.yaml"])
|
90
92
|
|
91
93
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
92
94
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>{"b"=>"answer", "a"=>"wrong"}})
|
93
95
|
|
94
|
-
@backend.lookup("key", {}, nil, :hash).should == {"a" => "answer", "b" => "answer"}
|
96
|
+
@backend.lookup("key", {}, nil, :hash, nil).should == {"a" => "answer", "b" => "answer"}
|
95
97
|
end
|
96
98
|
|
97
99
|
it "should fail when trying to << a Hash" do
|
98
|
-
Backend.expects(:
|
99
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns("/nonexisting/one.yaml")
|
100
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns("/nonexisting/two.yaml")
|
101
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
102
|
-
File.stubs(:exist?).with("/nonexisting/two.yaml").returns(true)
|
100
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"], ["two", "/nonexisting/two.yaml"])
|
103
101
|
|
104
102
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>["a", "answer"]})
|
105
103
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
106
104
|
|
107
|
-
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")
|
108
106
|
end
|
109
107
|
|
110
108
|
it "should fail when trying to merge an Array" do
|
111
|
-
Backend.expects(:
|
112
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns("/nonexisting/one.yaml")
|
113
|
-
Backend.expects(:datafile).with(:yaml, {}, "two", "yaml").returns("/nonexisting/two.yaml")
|
114
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
115
|
-
File.stubs(:exist?).with("/nonexisting/two.yaml").returns(true)
|
109
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"], ["two", "/nonexisting/two.yaml"])
|
116
110
|
|
117
111
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>{"a"=>"answer"}})
|
118
112
|
@cache.expects(:read_file).with("/nonexisting/two.yaml", Hash).returns({"key"=>["a", "wrong"]})
|
119
113
|
|
120
|
-
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")
|
121
115
|
end
|
122
116
|
|
123
117
|
it "should parse the answer for scope variables" do
|
124
|
-
Backend.expects(:
|
125
|
-
Backend.expects(:datafile).with(:yaml, {"rspec" => "test"}, "one", "yaml").returns("/nonexisting/one.yaml")
|
126
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
118
|
+
Backend.expects(:datasourcefiles).with(:yaml, {"rspec" => "test"}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"])
|
127
119
|
|
128
120
|
@cache.expects(:read_file).with("/nonexisting/one.yaml", Hash).returns({"key"=>"test_%{rspec}"})
|
129
121
|
|
130
|
-
@backend.lookup("key", {"rspec" => "test"}, nil, :priority).should == "test_test"
|
122
|
+
@backend.lookup("key", {"rspec" => "test"}, nil, :priority, nil).should == "test_test"
|
131
123
|
end
|
132
124
|
|
133
125
|
it "should retain datatypes found in yaml files" do
|
134
|
-
Backend.expects(:
|
135
|
-
Backend.expects(:datafile).with(:yaml, {}, "one", "yaml").returns("/nonexisting/one.yaml").times(3)
|
136
|
-
File.stubs(:exist?).with("/nonexisting/one.yaml").returns(true)
|
126
|
+
Backend.expects(:datasourcefiles).with(:yaml, {}, "yaml", nil).multiple_yields(["one", "/nonexisting/one.yaml"]).times(3)
|
137
127
|
|
138
|
-
yaml = "---\nstringval: 'string'\nboolval: true\nnumericval: 1"
|
139
128
|
|
140
|
-
@cache.
|
129
|
+
@cache.value = "---\nstringval: 'string'\nboolval: true\nnumericval: 1"
|
141
130
|
|
142
|
-
@backend.lookup("stringval", {}, nil, :priority).should == "string"
|
143
|
-
@backend.lookup("boolval", {}, nil, :priority).should == true
|
144
|
-
@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
|
145
134
|
end
|
146
135
|
end
|
147
136
|
end
|