dacs 0.2.0 → 0.3.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.
- 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
|