dacs 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/VERSION +1 -1
- data/example/example.rb +15 -2
- data/lib/dacs/app_config.rb +59 -7
- data/lib/dacs/environment_source.rb +3 -3
- data/lib/dacs/errors.rb +5 -0
- data/lib/dacs/schema.rb +2 -2
- data/spec/dacs/app_config_spec.rb +54 -0
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 0.3.0 2010-01-14
|
2
|
+
* Minor enhancements
|
3
|
+
* When an explicit schema is defined (using DSL):
|
4
|
+
* Will warn and exit when required keys are not configured
|
5
|
+
* Will raise an error when an undefined key is referenced
|
6
|
+
* New #report method added to dump a full configuration report
|
7
|
+
|
1
8
|
== 0.2.0 2010-01-13
|
2
9
|
* Major enhancements
|
3
10
|
* Added new mini-DSL for defining known configuration keys
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/example/example.rb
CHANGED
@@ -17,9 +17,10 @@ puts "foo: #{Dacs::AppConfig['foo']}"
|
|
17
17
|
puts "bar: #{Dacs::AppConfig['bar']}"
|
18
18
|
puts "baz: #{Dacs::AppConfig['baz']}"
|
19
19
|
puts Dacs::AppConfig.dump # => nil
|
20
|
+
puts Dacs::AppConfig.report # => nil
|
20
21
|
|
21
|
-
# >> I, [2010-02-
|
22
|
-
# >> W, [2010-02-
|
22
|
+
# >> I, [2010-02-14T09:45:52.703585 #17437] INFO -- : Found config file /devver-repos/dacs/example/example.yml.
|
23
|
+
# >> W, [2010-02-14T09:45:52.704092 #17437] WARN -- : Unknown configuration key 'fuz' in file example.yml
|
23
24
|
# >> Running in development mode
|
24
25
|
# >> foo: file_foo
|
25
26
|
# >> bar: env_bar
|
@@ -31,3 +32,15 @@ puts Dacs::AppConfig.dump # => nil
|
|
31
32
|
# >> | foo | file_foo | file example.yml |
|
32
33
|
# >> | bar | env_bar | environment |
|
33
34
|
# >> +--------------------------------------+
|
35
|
+
# >> App name: example
|
36
|
+
# >> Environment: development
|
37
|
+
# >> Configuration file: /devver-repos/dacs/example/example.yml
|
38
|
+
# >> Configuration setup: -:5
|
39
|
+
# >> Env var prefix: EXAMPLE_
|
40
|
+
# >> +--------------------------------------+
|
41
|
+
# >> | Key | Value | Source |
|
42
|
+
# >> +--------------------------------------+
|
43
|
+
# >> | baz | default_baz | defaults |
|
44
|
+
# >> | foo | file_foo | file example.yml |
|
45
|
+
# >> | bar | env_bar | environment |
|
46
|
+
# >> +--------------------------------------+
|
data/lib/dacs/app_config.rb
CHANGED
@@ -41,7 +41,7 @@ module Dacs
|
|
41
41
|
|
42
42
|
# Delegate a subset of Hash methods to the singleton instance
|
43
43
|
def_delegators :instance, :[], :fetch, :key?, :merge, :merge!, :app_name,
|
44
|
-
:source, :dump
|
44
|
+
:source, :dump, :report
|
45
45
|
|
46
46
|
def_delegators :schema, :required?, :optional?, :keys, :default_value
|
47
47
|
end
|
@@ -64,6 +64,7 @@ module Dacs
|
|
64
64
|
@@options[:logger] ||= ::Logger.new($stderr)
|
65
65
|
@@options[:environment] ||= :development
|
66
66
|
@@options[:defaults] ||= {}
|
67
|
+
@@definition_location = caller[0]
|
67
68
|
if block_given?
|
68
69
|
schema = Schema.new
|
69
70
|
yield(schema)
|
@@ -85,6 +86,10 @@ module Dacs
|
|
85
86
|
def self.environment
|
86
87
|
@@options[:environment]
|
87
88
|
end
|
89
|
+
|
90
|
+
def self.definition_location
|
91
|
+
@@definition_location
|
92
|
+
end
|
88
93
|
|
89
94
|
attr_reader :app_name
|
90
95
|
attr_reader :logger
|
@@ -98,27 +103,37 @@ module Dacs
|
|
98
103
|
@logger = @@options[:logger]
|
99
104
|
@environment = @@options[:environment]
|
100
105
|
@defaults = self.class.schema.defaults
|
106
|
+
@system = @@options.fetch(:system){Kernel}
|
101
107
|
find_or_create_config_file!
|
102
108
|
|
103
109
|
defaults_source = DefaultSource.new(@defaults)
|
104
110
|
file_source = FileSource.new(config_path, @environment)
|
105
|
-
env_source = EnvironmentSource.new(
|
111
|
+
env_source = EnvironmentSource.new(env_var_prefix)
|
106
112
|
|
107
113
|
load_values!(self.class.schema, env_source, file_source, defaults_source)
|
114
|
+
verify_no_missing_required_values!
|
115
|
+
end
|
116
|
+
|
117
|
+
def definition_location
|
118
|
+
self.class.definition_location
|
119
|
+
end
|
120
|
+
|
121
|
+
def env_var_prefix
|
122
|
+
app_name.to_s.upcase + "_"
|
108
123
|
end
|
109
124
|
|
110
125
|
def source(key)
|
111
|
-
|
112
|
-
raise ConfigurationError, "No such key '#{key}'"
|
113
|
-
end
|
126
|
+
assert_key_defined!(key)
|
114
127
|
configured_value.source.to_s
|
115
128
|
end
|
116
129
|
|
117
130
|
def [](key)
|
131
|
+
assert_key_defined!(key)
|
118
132
|
super(key).value
|
119
133
|
end
|
120
134
|
|
121
135
|
def fetch(key, &block)
|
136
|
+
assert_key_defined!(key)
|
122
137
|
case result = super(key, &block)
|
123
138
|
when ConfiguredValue then result.value
|
124
139
|
else result
|
@@ -133,8 +148,45 @@ module Dacs
|
|
133
148
|
table.as(:text)
|
134
149
|
end
|
135
150
|
|
151
|
+
def report
|
152
|
+
text = ""
|
153
|
+
text << "%-22s%s\n" % ["App name:", app_name]
|
154
|
+
text << "%-22s%s\n" % ["Environment:", environment]
|
155
|
+
text << "%-22s%s\n" % ["Configuration file:", config_path]
|
156
|
+
text << "%-22s%s\n" % ["Configuration setup:", definition_location]
|
157
|
+
text << "%-22s%s\n" % ["Env var prefix:", env_var_prefix]
|
158
|
+
text << dump
|
159
|
+
text
|
160
|
+
end
|
161
|
+
|
162
|
+
def verify_no_missing_required_values!
|
163
|
+
missing_keys = schema.keys - keys
|
164
|
+
missing_required_keys = missing_keys.select{|k| schema.required?(k)}
|
165
|
+
unless missing_required_keys.empty?
|
166
|
+
logger.fatal "Application not configured; exiting"
|
167
|
+
@system.warn "These required configuration keys were missing:"
|
168
|
+
missing_required_keys.each do |key|
|
169
|
+
@system.warn " #{key}"
|
170
|
+
end
|
171
|
+
@system.warn ""
|
172
|
+
@system.warn "Please set the required keys in #{config_path} or "\
|
173
|
+
"environment and try again."
|
174
|
+
@system.exit(1)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
136
178
|
private
|
137
179
|
|
180
|
+
def assert_key_defined!(key)
|
181
|
+
unless schema.defined?(key.to_s)
|
182
|
+
raise UndefinedKeyError, key, caller(3)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def schema
|
187
|
+
self.class.schema
|
188
|
+
end
|
189
|
+
|
138
190
|
def find_or_create_config_file!
|
139
191
|
if Pathname(config_path).exist?
|
140
192
|
logger.info "Found config file #{config_path}."
|
@@ -174,8 +226,8 @@ END
|
|
174
226
|
def load_values!(schema, *sources)
|
175
227
|
sources.reverse_each do |source|
|
176
228
|
source.each do |configured_value|
|
177
|
-
if schema.defined?(configured_value.key)
|
178
|
-
self[configured_value.key] = configured_value
|
229
|
+
if schema.defined?(configured_value.key.to_s)
|
230
|
+
self[configured_value.key.to_s] = configured_value
|
179
231
|
else
|
180
232
|
key = configured_value.key
|
181
233
|
logger.warn "Unknown configuration key '#{key}' in #{source}"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Dacs
|
2
2
|
class EnvironmentSource
|
3
|
-
def initialize(
|
4
|
-
@
|
3
|
+
def initialize(prefix, environment=ENV)
|
4
|
+
@prefix = prefix
|
5
5
|
@environment = environment
|
6
6
|
end
|
7
7
|
|
@@ -11,7 +11,7 @@ module Dacs
|
|
11
11
|
|
12
12
|
def each
|
13
13
|
@environment.each_pair do |key, value|
|
14
|
-
if match = /^#{@
|
14
|
+
if match = /^#{@prefix.downcase}(.*)$/.match(key.downcase)
|
15
15
|
yield ConfiguredValue.new(self, match[1], value)
|
16
16
|
end
|
17
17
|
end
|
data/lib/dacs/errors.rb
CHANGED
data/lib/dacs/schema.rb
CHANGED
@@ -31,7 +31,7 @@ module Dacs
|
|
31
31
|
|
32
32
|
def defaults
|
33
33
|
key_defs.inject({}) { |h, key_def|
|
34
|
-
h[key_def[:name]] = key_def[:default]
|
34
|
+
h[key_def[:name]] = key_def[:default] if key_def.key?(:default)
|
35
35
|
h
|
36
36
|
}
|
37
37
|
end
|
@@ -39,7 +39,7 @@ module Dacs
|
|
39
39
|
private
|
40
40
|
|
41
41
|
def assert_key_defined!(key)
|
42
|
-
!!key_def(key) or raise
|
42
|
+
!!key_def(key) or raise UndefinedKeyError, key
|
43
43
|
end
|
44
44
|
|
45
45
|
def key_defs
|
@@ -59,6 +59,31 @@ module Dacs
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
context "given strict definitions and a missing required key" do
|
63
|
+
before :each do
|
64
|
+
@system = stub("system").as_null_object
|
65
|
+
end
|
66
|
+
|
67
|
+
def do_init
|
68
|
+
AppConfig.init!(@app_name, :logger => @logger, :system => @system) do |config|
|
69
|
+
config.key "foo"
|
70
|
+
config.key "bar"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should exit the program with an error status" do
|
75
|
+
@system.should_receive(:exit).with(1)
|
76
|
+
do_init
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should warn the user about the missing config keys" do
|
80
|
+
@system.should_receive(:warn).with(/foo/)
|
81
|
+
@system.should_receive(:warn).with(/bar/)
|
82
|
+
@system.should_receive(:warn).any_number_of_times
|
83
|
+
do_init
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
62
87
|
context "without explicit key definitions" do
|
63
88
|
before :each do
|
64
89
|
AppConfig.init!(@app_name,
|
@@ -91,12 +116,18 @@ module Dacs
|
|
91
116
|
|
92
117
|
context "with explicit key definitions" do
|
93
118
|
before :each do
|
119
|
+
ENV['FOO_APP_BAR'] = 'env_bar'
|
120
|
+
@def_line = __LINE__ + 1
|
94
121
|
AppConfig.init!(@app_name, :logger => @logger) do |config|
|
95
122
|
config.key :foo, :default => 42
|
96
123
|
config.key 'bar'
|
97
124
|
end
|
98
125
|
end
|
99
126
|
|
127
|
+
after :each do
|
128
|
+
ENV.delete('FOO_APP_BAR')
|
129
|
+
end
|
130
|
+
|
100
131
|
it "should be able to list known keys" do
|
101
132
|
AppConfig.keys.should == ['foo', 'bar']
|
102
133
|
end
|
@@ -115,6 +146,25 @@ module Dacs
|
|
115
146
|
AppConfig.optional?(:foo).should be_true
|
116
147
|
end
|
117
148
|
|
149
|
+
it "should raise an exception when an undefined key is referenced" do
|
150
|
+
lambda do
|
151
|
+
AppConfig['faz']
|
152
|
+
end.should raise_error(ConfigurationError)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should reference the offending line when an undefined key is referenced" do
|
156
|
+
@error_line = __LINE__ + 2
|
157
|
+
error = begin
|
158
|
+
AppConfig['faz']
|
159
|
+
rescue ConfigurationError => error
|
160
|
+
error
|
161
|
+
end
|
162
|
+
error.backtrace[0].should match(/#{__FILE__}:#{@error_line}/)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should remember where the keys were defined" do
|
166
|
+
AppConfig.definition_location.should match(/#{__FILE__}:#{@def_line}/)
|
167
|
+
end
|
118
168
|
end
|
119
169
|
|
120
170
|
context "with a mix of default, file, and environment settings" do
|
@@ -136,6 +186,10 @@ module Dacs
|
|
136
186
|
end
|
137
187
|
end
|
138
188
|
|
189
|
+
after :each do
|
190
|
+
ENV.delete('FOO_APP_BUZ')
|
191
|
+
end
|
192
|
+
|
139
193
|
it "should have the correct values for each" do
|
140
194
|
AppConfig['foo'].should be == 42
|
141
195
|
AppConfig['bar'].should be == 'file_bar'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dacs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Devver, Inc.
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-14 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|