hiera 2.0.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +202 -0
- data/LICENSE +18 -0
- data/README.md +276 -0
- data/bin/hiera +248 -0
- data/lib/hiera.rb +115 -0
- data/lib/hiera/backend.rb +325 -0
- data/lib/hiera/backend/json_backend.rb +58 -0
- data/lib/hiera/backend/yaml_backend.rb +63 -0
- data/lib/hiera/config.rb +90 -0
- data/lib/hiera/console_logger.rb +13 -0
- data/lib/hiera/error.rb +4 -0
- data/lib/hiera/fallback_logger.rb +41 -0
- data/lib/hiera/filecache.rb +86 -0
- data/lib/hiera/interpolate.rb +98 -0
- data/lib/hiera/noop_logger.rb +8 -0
- data/lib/hiera/puppet_logger.rb +17 -0
- data/lib/hiera/recursive_guard.rb +20 -0
- data/lib/hiera/util.rb +47 -0
- data/lib/hiera/version.rb +89 -0
- data/spec/spec_helper.rb +78 -0
- data/spec/unit/backend/json_backend_spec.rb +85 -0
- data/spec/unit/backend/yaml_backend_spec.rb +138 -0
- data/spec/unit/backend_spec.rb +743 -0
- data/spec/unit/config_spec.rb +118 -0
- data/spec/unit/console_logger_spec.rb +19 -0
- data/spec/unit/fallback_logger_spec.rb +80 -0
- data/spec/unit/filecache_spec.rb +142 -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/hiera_spec.rb +81 -0
- data/spec/unit/interpolate_spec.rb +36 -0
- data/spec/unit/puppet_logger_spec.rb +31 -0
- data/spec/unit/util_spec.rb +49 -0
- data/spec/unit/version_spec.rb +44 -0
- metadata +142 -0
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Hiera
|
4
|
+
describe Config do
|
5
|
+
describe "#load" do
|
6
|
+
let(:default_config) do
|
7
|
+
{
|
8
|
+
:backends => ["yaml"],
|
9
|
+
:hierarchy => "common",
|
10
|
+
:logger => "console",
|
11
|
+
:merge_behavior=>:native
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should treat string sources as a filename" do
|
16
|
+
expect { Config.load("/nonexisting") }.to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise an error for missing config files" do
|
20
|
+
File.expects(:exist?).with("/nonexisting").returns(false)
|
21
|
+
YAML.expects(:load_file).with("/nonexisting").never
|
22
|
+
|
23
|
+
expect { Config.load("/nonexisting") }.to raise_error "Config file /nonexisting not found"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should attempt to YAML load config files" do
|
27
|
+
File.expects(:exist?).with("/nonexisting").returns(true)
|
28
|
+
YAML.expects(:load_file).with("/nonexisting").returns(YAML.load("---\n"))
|
29
|
+
|
30
|
+
Config.load("/nonexisting")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should use defaults on empty YAML config file" do
|
34
|
+
File.expects(:exist?).with("/nonexisting").returns(true)
|
35
|
+
YAML.expects(:load_file).with("/nonexisting").returns(YAML.load(""))
|
36
|
+
|
37
|
+
Config.load("/nonexisting").should == default_config
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use hash data as source if supplied" do
|
41
|
+
config = Config.load({"rspec" => "test"})
|
42
|
+
config["rspec"].should == "test"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should merge defaults with the loaded or supplied config" do
|
46
|
+
config = Config.load({})
|
47
|
+
config.should == {:backends => ["yaml"], :hierarchy => "common", :logger => "console", :merge_behavior=>:native}
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should force :backends to be a flattened array" do
|
51
|
+
Config.load({:backends => [["foo", ["bar"]]]}).should == {:backends => ["foo", "bar"], :hierarchy => "common", :logger => "console", :merge_behavior=>:native}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should load the supplied logger" do
|
55
|
+
Hiera.expects(:logger=).with("foo")
|
56
|
+
Config.load({:logger => "foo"})
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should default to the console logger" do
|
60
|
+
Hiera.expects(:logger=).with("console")
|
61
|
+
Config.load({})
|
62
|
+
end
|
63
|
+
|
64
|
+
context "loading '/dev/null' as spec tests do", :unless => Hiera::Util.microsoft_windows? do
|
65
|
+
before :each do
|
66
|
+
# Simulate the behavior of YAML.load_file('/dev/null') in MRI 1.9.3p194
|
67
|
+
Config.stubs(:yaml_load_file).
|
68
|
+
raises(TypeError, "no implicit conversion from nil to integer")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "is not exceptional behavior" do
|
72
|
+
Config.load('/dev/null')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "if deep_merge can't be loaded" do
|
77
|
+
let(:error_message) { "Must have 'deep_merge' gem installed for the configured merge_behavior." }
|
78
|
+
before(:each) do
|
79
|
+
Config.expects(:require).with("deep_merge").raises(LoadError, "unable to load")
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should error if merge_behavior is 'deep'" do
|
83
|
+
expect { Config.load(:merge_behavior => :deep) }.to raise_error(Hiera::Error, error_message)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should error if merge_behavior is 'deeper'" do
|
87
|
+
expect { Config.load(:merge_behavior => :deeper) }.to raise_error(Hiera::Error, error_message)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#load_backends" do
|
93
|
+
it "should load each backend" do
|
94
|
+
Config.load(:backends => ["One", "Two"])
|
95
|
+
Config.expects(:require).with("hiera/backend/one_backend")
|
96
|
+
Config.expects(:require).with("hiera/backend/two_backend")
|
97
|
+
Config.load_backends
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should warn if it cant load a backend" do
|
101
|
+
Config.load(:backends => ["one"])
|
102
|
+
Config.expects(:require).with("hiera/backend/one_backend").raises("fail")
|
103
|
+
|
104
|
+
expect {
|
105
|
+
Config.load_backends
|
106
|
+
}.to raise_error("fail")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#include?" do
|
111
|
+
it "should correctly report inclusion" do
|
112
|
+
Config.load({})
|
113
|
+
Config.include?(:foo).should == false
|
114
|
+
Config.include?(:logger).should == true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Hiera
|
4
|
+
describe Console_logger do
|
5
|
+
describe "#warn" do
|
6
|
+
it "should warn to STDERR" do
|
7
|
+
STDERR.expects(:puts).with("WARN: 0: foo")
|
8
|
+
Time.expects(:now).returns(0)
|
9
|
+
Console_logger.warn("foo")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should debug to STDERR" do
|
13
|
+
STDERR.expects(:puts).with("DEBUG: 0: foo")
|
14
|
+
Time.expects(:now).returns(0)
|
15
|
+
Console_logger.debug("foo")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'hiera/fallback_logger'
|
2
|
+
|
3
|
+
describe Hiera::FallbackLogger do
|
4
|
+
before :each do
|
5
|
+
InMemoryLogger.reset
|
6
|
+
SuitableLogger.reset
|
7
|
+
end
|
8
|
+
|
9
|
+
it "delegates #warn to the logger implemenation" do
|
10
|
+
logger = Hiera::FallbackLogger.new(InMemoryLogger)
|
11
|
+
|
12
|
+
logger.warn("the message")
|
13
|
+
|
14
|
+
InMemoryLogger.warnings.should == ["the message"]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "delegates #debug to the logger implemenation" do
|
18
|
+
logger = Hiera::FallbackLogger.new(InMemoryLogger)
|
19
|
+
|
20
|
+
logger.debug("the message")
|
21
|
+
|
22
|
+
InMemoryLogger.debugs.should == ["the message"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "chooses the first logger that is suitable" do
|
26
|
+
logger = Hiera::FallbackLogger.new(UnsuitableLogger, SuitableLogger)
|
27
|
+
|
28
|
+
logger.warn("for the suitable logger")
|
29
|
+
|
30
|
+
SuitableLogger.warnings.should include("for the suitable logger")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "raises an error if no implementation is suitable" do
|
34
|
+
expect do
|
35
|
+
Hiera::FallbackLogger.new(UnsuitableLogger)
|
36
|
+
end.to raise_error "No suitable logging implementation found."
|
37
|
+
end
|
38
|
+
|
39
|
+
it "issues a warning for each implementation that is not suitable" do
|
40
|
+
Hiera::FallbackLogger.new(UnsuitableLogger, UnsuitableLogger, SuitableLogger)
|
41
|
+
|
42
|
+
SuitableLogger.warnings.should == [
|
43
|
+
"Not using UnsuitableLogger. It does not report itself to be suitable.",
|
44
|
+
"Not using UnsuitableLogger. It does not report itself to be suitable."]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Preserves log messages in memory
|
48
|
+
# and also serves as a "legacy" logger that has no
|
49
|
+
# suitable? method
|
50
|
+
class InMemoryLogger
|
51
|
+
class << self
|
52
|
+
attr_accessor :warnings, :debugs
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.reset
|
56
|
+
self.warnings = []
|
57
|
+
self.debugs = []
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.warn(message)
|
61
|
+
self.warnings << message
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.debug(message)
|
65
|
+
self.debugs << message
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class UnsuitableLogger
|
70
|
+
def self.suitable?
|
71
|
+
false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class SuitableLogger < InMemoryLogger
|
76
|
+
def self.suitable?
|
77
|
+
true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class Hiera
|
5
|
+
describe Filecache do
|
6
|
+
before do
|
7
|
+
@cache = Filecache.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def write_file(file, contents)
|
11
|
+
File.open(file, 'w') do |f|
|
12
|
+
f.write(contents)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#read" do
|
17
|
+
it "reads data from a file" do
|
18
|
+
Dir.mktmpdir do |dir|
|
19
|
+
file = File.join(dir, "testing")
|
20
|
+
write_file(file, "my data")
|
21
|
+
|
22
|
+
@cache.read(file).should == "my data"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "rereads data when the file changes" do
|
27
|
+
Dir.mktmpdir do |dir|
|
28
|
+
file = File.join(dir, "testing")
|
29
|
+
write_file(file, "my data")
|
30
|
+
@cache.read(file).should == "my data"
|
31
|
+
|
32
|
+
write_file(file, "changed data")
|
33
|
+
@cache.read(file).should == "changed data"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "uses the provided default when the type does not match the expected type" do
|
38
|
+
Hiera.expects(:debug).with(regexp_matches(/String.*not.*Hash, setting defaults/))
|
39
|
+
Dir.mktmpdir do |dir|
|
40
|
+
file = File.join(dir, "testing")
|
41
|
+
write_file(file, "my data")
|
42
|
+
data = @cache.read(file, Hash, { :testing => "hash" }) do |data|
|
43
|
+
"a string"
|
44
|
+
end
|
45
|
+
|
46
|
+
data.should == { :testing => "hash" }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "traps any errors from the block and uses the default value" do
|
51
|
+
Hiera.expects(:debug).with(regexp_matches(/Reading data.*failed:.*testing error/))
|
52
|
+
Dir.mktmpdir do |dir|
|
53
|
+
file = File.join(dir, "testing")
|
54
|
+
write_file(file, "my data")
|
55
|
+
data = @cache.read(file, Hash, { :testing => "hash" }) do |data|
|
56
|
+
raise ArgumentError, "testing error"
|
57
|
+
end
|
58
|
+
|
59
|
+
data.should == { :testing => "hash" }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises an error when there is no default given and there is a problem" do
|
64
|
+
Dir.mktmpdir do |dir|
|
65
|
+
file = File.join(dir, "testing")
|
66
|
+
write_file(file, "my data")
|
67
|
+
|
68
|
+
expect do
|
69
|
+
@cache.read(file, Hash) do |data|
|
70
|
+
raise ArgumentError, "testing error"
|
71
|
+
end
|
72
|
+
end.to raise_error(ArgumentError, "testing error")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#read_file" do
|
78
|
+
it "reads data from a file" do
|
79
|
+
Dir.mktmpdir do |dir|
|
80
|
+
file = File.join(dir, "testing")
|
81
|
+
write_file(file, "my data")
|
82
|
+
|
83
|
+
@cache.read_file(file).should == "my data"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "rereads data when the file changes" do
|
88
|
+
Dir.mktmpdir do |dir|
|
89
|
+
file = File.join(dir, "testing")
|
90
|
+
write_file(file, "my data")
|
91
|
+
@cache.read_file(file).should == "my data"
|
92
|
+
|
93
|
+
write_file(file, "changed data")
|
94
|
+
@cache.read_file(file).should == "changed data"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "errors when the type does not match the expected type" do
|
99
|
+
Dir.mktmpdir do |dir|
|
100
|
+
file = File.join(dir, "testing")
|
101
|
+
write_file(file, "my data")
|
102
|
+
|
103
|
+
expect do
|
104
|
+
@cache.read_file(file, Hash) do |data|
|
105
|
+
"a string"
|
106
|
+
end
|
107
|
+
end.to raise_error(TypeError)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it "converts the read data using the block" do
|
112
|
+
Dir.mktmpdir do |dir|
|
113
|
+
file = File.join(dir, "testing")
|
114
|
+
write_file(file, "my data")
|
115
|
+
|
116
|
+
@cache.read_file(file, Hash) do |data|
|
117
|
+
{ :data => data }
|
118
|
+
end.should == { :data => "my data" }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it "errors when the file does not exist" do
|
123
|
+
expect do
|
124
|
+
@cache.read_file("/notexist")
|
125
|
+
end.to raise_error(Errno::ENOENT)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "propogates any errors from the block" do
|
129
|
+
Dir.mktmpdir do |dir|
|
130
|
+
file = File.join(dir, "testing")
|
131
|
+
write_file(file, "my data")
|
132
|
+
|
133
|
+
expect do
|
134
|
+
@cache.read_file(file) do |data|
|
135
|
+
raise ArgumentError, "testing error"
|
136
|
+
end
|
137
|
+
end.to raise_error(ArgumentError, "testing error")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
bar: 'alternate'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hiera/util'
|
3
|
+
|
4
|
+
# This is only around for the logger setup tests
|
5
|
+
module Hiera::Foo_logger
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Hiera" do
|
9
|
+
describe "#logger=" do
|
10
|
+
it "loads the given logger" do
|
11
|
+
Hiera.expects(:require).with("hiera/foo_logger")
|
12
|
+
|
13
|
+
Hiera.logger = "foo"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "falls back to the Console logger when the logger could not be loaded" do
|
17
|
+
Hiera.expects(:warn)
|
18
|
+
|
19
|
+
Hiera.logger = "no_such_logger"
|
20
|
+
|
21
|
+
Hiera.logger.should be Hiera::Console_logger
|
22
|
+
end
|
23
|
+
|
24
|
+
it "falls back to the Console logger when the logger class could not be found" do
|
25
|
+
Hiera.expects(:warn)
|
26
|
+
Hiera.expects(:require).with("hiera/no_constant_logger")
|
27
|
+
|
28
|
+
Hiera.logger = "no_constant"
|
29
|
+
|
30
|
+
Hiera.logger.should be Hiera::Console_logger
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#warn" do
|
35
|
+
it "delegates to the configured logger" do
|
36
|
+
Hiera.logger = 'console'
|
37
|
+
Hiera::Console_logger.expects(:warn).with("rspec")
|
38
|
+
|
39
|
+
Hiera.warn("rspec")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#debug" do
|
44
|
+
it "delegates to the configured logger" do
|
45
|
+
Hiera.logger = 'console'
|
46
|
+
Hiera::Console_logger.expects(:debug).with("rspec")
|
47
|
+
|
48
|
+
Hiera.debug("rspec")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#initialize" do
|
53
|
+
it "uses a default config file when none is provided" do
|
54
|
+
config_file = File.join(Hiera::Util.config_dir, 'hiera.yaml')
|
55
|
+
Hiera::Config.expects(:load).with(config_file)
|
56
|
+
Hiera::Config.stubs(:load_backends)
|
57
|
+
Hiera.new
|
58
|
+
end
|
59
|
+
|
60
|
+
it "passes the supplied config to the config class" do
|
61
|
+
Hiera::Config.expects(:load).with({"test" => "rspec"})
|
62
|
+
Hiera::Config.stubs(:load_backends)
|
63
|
+
Hiera.new(:config => {"test" => "rspec"})
|
64
|
+
end
|
65
|
+
|
66
|
+
it "loads all backends on start" do
|
67
|
+
Hiera::Config.stubs(:load)
|
68
|
+
Hiera::Config.expects(:load_backends)
|
69
|
+
Hiera.new
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#lookup" do
|
74
|
+
it "delegates to the Backend#lookup method" do
|
75
|
+
Hiera::Config.stubs(:load)
|
76
|
+
Hiera::Config.stubs(:load_backends)
|
77
|
+
Hiera::Backend.expects(:lookup).with(:key, :default, :scope, :order_override, :resolution_type)
|
78
|
+
Hiera.new.lookup(:key, :default, :scope, :order_override, :resolution_type)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|