foundry 0.2.2 → 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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/README.md +66 -12
- data/foundry.gemspec +1 -0
- data/lib/foundry.rb +4 -2
- data/lib/foundry/configurator.rb +67 -38
- data/lib/foundry/refinements/hash.rb +25 -0
- data/lib/foundry/sources/file.rb +11 -0
- data/lib/foundry/sources/uri.rb +21 -0
- data/lib/foundry/version.rb +1 -1
- data/spec/configurator_spec.rb +63 -24
- data/spec/refinements/hash_spec.rb +170 -0
- data/spec/sources/file_spec.rb +14 -0
- data/spec/sources/uri_spec.rb +63 -0
- data/spec/spec_helper.rb +1 -4
- metadata +38 -21
- data/lib/foundry/loaders/file.rb +0 -9
- data/lib/foundry/loaders/uri.rb +0 -19
- data/spec/loaders/file_spec.rb +0 -15
- data/spec/loaders/uri_spec.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b28681a81e233360028348be15505ab62d698a9c
|
4
|
+
data.tar.gz: 060e3a8c45400254f9fb8e926b75683f82a4fed9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52e33f3b602ff5a8dd9fdc6728a8898e42d3572bc4c147f4755cab966d4ceece89ce46639619302677882028620084aaf60c93cebf92e8490515fdfb8fb13a7d
|
7
|
+
data.tar.gz: 3bf3b2b64289087f2abd06816434e51590fd59add1fb82b0aee96522d1a5571d58a0496fc993d420e97b78191219324bd183a78b55e62a0de7bf4a50f508e8fe
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -36,40 +36,94 @@ Or install it yourself as:
|
|
36
36
|
Loading from a local-file:
|
37
37
|
|
38
38
|
```ruby
|
39
|
-
config = Foundry::Configurator.configure(
|
39
|
+
config = Foundry::Configurator.configure(
|
40
|
+
:root_path => 'local-root-path',
|
41
|
+
:relative_path => 'relative-path-to-file',
|
42
|
+
:source_type => Foundry::Sources::File
|
43
|
+
)
|
40
44
|
```
|
41
45
|
|
42
46
|
Loading from a HTTP/HTTPS endpoint:
|
43
47
|
|
44
48
|
```ruby
|
45
|
-
config = Foundry::Configurator.configure(
|
49
|
+
config = Foundry::Configurator.configure(
|
50
|
+
:root_path => 'http-or-https-root-url',
|
51
|
+
:relative_path => 'relative-path-to-file',
|
52
|
+
:source_type => Foundry::Sources::URI
|
53
|
+
)
|
46
54
|
```
|
47
55
|
|
48
56
|
Loading from a HTTP/HTTPS endpoint using "Basic Authentication":
|
49
57
|
|
50
58
|
```ruby
|
51
59
|
config = Foundry::Configurator.configure(
|
52
|
-
:
|
60
|
+
:root_path => 'http-or-https-root-url',
|
61
|
+
:relative_path => 'relative-path-to-file',
|
62
|
+
:source_type => Foundry::Sources::URI,
|
53
63
|
:username => 'basic-auth-username',
|
54
64
|
:password => 'basic-auth-password'
|
55
65
|
)
|
56
66
|
```
|
57
67
|
|
58
|
-
|
68
|
+
Fetching top-level and nested values:
|
59
69
|
|
60
70
|
```ruby
|
61
|
-
# The examples below assume that
|
62
|
-
#
|
71
|
+
# The examples below assume that a file containing the following has already
|
72
|
+
# been loaded and processed by a call to `Foundry::Configurator.configure` (into
|
73
|
+
# a variable named `config`).
|
63
74
|
#
|
64
75
|
# ---
|
65
|
-
#
|
66
|
-
#
|
76
|
+
# value1: value
|
77
|
+
# value2:
|
78
|
+
# nested_value1: value
|
79
|
+
|
80
|
+
# Fetching a top-level value using dot-notation
|
81
|
+
value1 = config.value1
|
82
|
+
|
83
|
+
# Fetching a nested value using dot-notation
|
84
|
+
nested_value1 = config.value2.nested_value1
|
85
|
+
|
86
|
+
# Fetching a top-level value by key
|
87
|
+
value1 = config['value1']
|
88
|
+
|
89
|
+
# Fetching a nested value by key
|
90
|
+
nested_value1 = config['value2']['nested_value1']
|
91
|
+
```
|
92
|
+
|
93
|
+
Inheritance support:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# The examples below assume that there are two files available, relative to the
|
97
|
+
# `root_path`, named "file1.yml" and "file2.yml" (and that "file2.yml" inherits
|
98
|
+
# from "file1.yml").
|
99
|
+
#
|
100
|
+
# The file contents are as follows:
|
101
|
+
#
|
102
|
+
# === file1.yml ===
|
103
|
+
#
|
104
|
+
# ---
|
105
|
+
# value1: value
|
106
|
+
#
|
107
|
+
# === file2.yml ===
|
108
|
+
#
|
109
|
+
# ---
|
110
|
+
# value2: value
|
111
|
+
# inherit: file1.yml
|
112
|
+
#
|
113
|
+
# It is also assumed that the files have already been loaded and processed by a
|
114
|
+
# call to `Foundry::Configurator.configure` (into a variable named `config`).
|
115
|
+
#
|
116
|
+
# The result now contains values for both `value1` and `value2` and can be used
|
117
|
+
# as follows (it is worth noting that the `inherit` key is removed during the
|
118
|
+
# configuration process):
|
67
119
|
|
68
|
-
#
|
69
|
-
|
120
|
+
# Fetching `value1` and `value2` using dot-notation
|
121
|
+
value1 = config.value1
|
122
|
+
value2 = config.value2
|
70
123
|
|
71
|
-
#
|
72
|
-
|
124
|
+
# Fetching `value1` and `value2` by key
|
125
|
+
value1 = config['value1']
|
126
|
+
value2 = config['value2']
|
73
127
|
```
|
74
128
|
|
75
129
|
## Contributing
|
data/foundry.gemspec
CHANGED
data/lib/foundry.rb
CHANGED
@@ -5,7 +5,9 @@ require 'ostruct'
|
|
5
5
|
require 'uri'
|
6
6
|
require 'yaml'
|
7
7
|
|
8
|
+
require 'foundry/refinements/hash'
|
9
|
+
|
8
10
|
require 'foundry/configurator'
|
9
|
-
require 'foundry/
|
10
|
-
require 'foundry/
|
11
|
+
require 'foundry/sources/file'
|
12
|
+
require 'foundry/sources/uri'
|
11
13
|
require 'foundry/version'
|
data/lib/foundry/configurator.rb
CHANGED
@@ -1,52 +1,81 @@
|
|
1
1
|
module Foundry
|
2
2
|
class Configurator
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
)
|
3
|
+
def self.configure(opts)
|
4
|
+
Configurator.new.configure(opts)
|
5
|
+
end
|
6
|
+
|
7
|
+
def configure(opts)
|
8
|
+
with_opts(opts) do
|
9
|
+
transmorgs = transmorgify(opts.fetch(:relative_path))
|
10
|
+
merged = mergify(transmorgs)
|
11
|
+
structify(merged)
|
12
12
|
end
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
+
private
|
15
16
|
|
16
|
-
|
17
|
-
ERB.new(str).result
|
18
|
-
end
|
17
|
+
attr_reader :opts
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
elsif uri = opts.delete(:uri)
|
24
|
-
Foundry::Loaders::Uri.load(uri, opts)
|
25
|
-
else
|
26
|
-
raise NotImplementedError
|
27
|
-
end
|
28
|
-
end
|
19
|
+
def erbify(str)
|
20
|
+
ERB.new(str).result
|
21
|
+
end
|
29
22
|
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
def loadify(relative_path)
|
24
|
+
source.load(
|
25
|
+
root_path,
|
26
|
+
relative_path,
|
27
|
+
opts
|
28
|
+
)
|
29
|
+
end
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
31
|
+
def mergify(transmorgs)
|
32
|
+
transmorgs.reduce({}) { |memo, transmorg| memo.deep_merge(transmorg) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def parsify(str)
|
36
|
+
YAML.load(str) || {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def root_path
|
40
|
+
opts.fetch(:root_path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def source
|
44
|
+
source_type.new
|
45
|
+
end
|
46
|
+
|
47
|
+
def source_type
|
48
|
+
opts.fetch(:source_type)
|
49
|
+
end
|
50
|
+
|
51
|
+
def structify(object)
|
52
|
+
case object
|
53
|
+
when Array
|
54
|
+
object.map do |value|
|
55
|
+
structify(value)
|
56
|
+
end
|
57
|
+
when Hash
|
58
|
+
OpenStruct.new.tap do |open_struct|
|
59
|
+
object.each do |key, value|
|
60
|
+
open_struct.send("#{key}=", structify(value))
|
45
61
|
end
|
46
|
-
else
|
47
|
-
object
|
48
62
|
end
|
63
|
+
else
|
64
|
+
object
|
49
65
|
end
|
50
66
|
end
|
67
|
+
|
68
|
+
def transmorgify(relative_path)
|
69
|
+
parsed = parsify(erbify(loadify(relative_path)))
|
70
|
+
inherit = parsed.delete('inherit')
|
71
|
+
Array(inherit && transmorgify(inherit)) << parsed
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_opts(opts)
|
75
|
+
@opts = opts
|
76
|
+
yield
|
77
|
+
ensure
|
78
|
+
@opts = nil
|
79
|
+
end
|
51
80
|
end
|
52
81
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Hash
|
2
|
+
def deep_merge(other)
|
3
|
+
dup.deep_merge!(other)
|
4
|
+
end
|
5
|
+
|
6
|
+
def deep_merge!(other)
|
7
|
+
other.each_pair do |other_key, other_value|
|
8
|
+
this_value = self[other_key]
|
9
|
+
if this_value.is_a?(Hash) && other_value.is_a?(Hash)
|
10
|
+
self[other_key] = this_value.deep_merge(other_value)
|
11
|
+
else
|
12
|
+
self[other_key] = other_value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def without(*keys)
|
19
|
+
dup.without!(*keys)
|
20
|
+
end
|
21
|
+
|
22
|
+
def without!(*keys)
|
23
|
+
self.reject! { |key, _| keys.include?(key) }; self
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Foundry
|
2
|
+
module Sources
|
3
|
+
class File
|
4
|
+
def load(root_path, relative_path, opts)
|
5
|
+
file_path = ::File.join(root_path, relative_path)
|
6
|
+
raise "Unknown configuration file: #{file_path}" unless ::File.exists?(file_path)
|
7
|
+
::File.read(file_path)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Foundry
|
2
|
+
module Sources
|
3
|
+
class URI
|
4
|
+
def load(root_path, relative_path, opts)
|
5
|
+
uri = ::URI.join(root_path, relative_path)
|
6
|
+
client = Net::HTTP.new(uri.host, uri.port)
|
7
|
+
if uri.scheme == 'https'
|
8
|
+
client.use_ssl = true
|
9
|
+
client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
10
|
+
end
|
11
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
12
|
+
if (username = opts[:username]) && (password = opts[:password])
|
13
|
+
request.basic_auth(username, password)
|
14
|
+
end
|
15
|
+
response = client.request(request)
|
16
|
+
raise "Unknown configuration file: #{uri}" unless response.is_a?(Net::HTTPSuccess)
|
17
|
+
response.body
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/foundry/version.rb
CHANGED
data/spec/configurator_spec.rb
CHANGED
@@ -1,36 +1,45 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'foundry/configurator'
|
3
2
|
|
4
3
|
describe Foundry::Configurator do
|
5
|
-
|
4
|
+
REQUIRED_OPTS = [
|
5
|
+
:root_path,
|
6
|
+
:relative_path,
|
7
|
+
:source_type,
|
8
|
+
]
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
+
subject { Foundry::Configurator.new }
|
11
|
+
let(:opts) { REQUIRED_OPTS.reduce({}) { |memo, opt| memo[opt] = nil; memo } }
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
REQUIRED_OPTS.each do |key|
|
14
|
+
it %{must be passed a "#{key}"} do
|
15
|
+
expect { subject.configure(opts.without(key)) }.to raise_error
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
|
-
it 'will
|
17
|
-
|
18
|
-
|
19
|
+
it 'will load from a source' do
|
20
|
+
with_source do |source|
|
21
|
+
expect(source).to receive(:load) { '' }
|
22
|
+
expect { subject.configure(opts) }.not_to raise_error
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
it 'will fail-fast if the YAML is invalid' do
|
22
|
-
|
23
|
-
|
27
|
+
with_source do |source|
|
28
|
+
expect(source).to receive(:load)
|
29
|
+
expect { subject.configure(opts) }.to raise_error
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
it 'will fail-fast if the ERB raises an error' do
|
27
|
-
|
28
|
-
|
34
|
+
with_source do |source|
|
35
|
+
expect(source).to receive(:load) { 'foo: <%= 1/0 %>' }
|
36
|
+
expect { subject.configure(opts) }.to raise_error
|
37
|
+
end
|
29
38
|
end
|
30
39
|
|
31
|
-
it 'can parse
|
32
|
-
|
33
|
-
|
40
|
+
it 'can parse YAML/ERB' do
|
41
|
+
with_source do |source|
|
42
|
+
expect(source).to receive(:load) { <<-YAML
|
34
43
|
erb: <%= 1 * 2 * 3 %>
|
35
44
|
float: 123.0
|
36
45
|
integer: 42
|
@@ -39,11 +48,10 @@ describe Foundry::Configurator do
|
|
39
48
|
- dos
|
40
49
|
- tres
|
41
50
|
string: hello world
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
'root' => OpenStruct.new(
|
51
|
+
YAML
|
52
|
+
}
|
53
|
+
expect(subject.configure(opts)).to eq(
|
54
|
+
OpenStruct.new(
|
47
55
|
'erb' => 6,
|
48
56
|
'float' => 123.0,
|
49
57
|
'integer' => 42,
|
@@ -51,6 +59,37 @@ describe Foundry::Configurator do
|
|
51
59
|
'string' => 'hello world'
|
52
60
|
)
|
53
61
|
)
|
54
|
-
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'supports inheritance' do
|
66
|
+
with_source(:exactly => :twice) do |source|
|
67
|
+
expect(source).to receive(:load).and_return(
|
68
|
+
"foo: foo\ninherit: bar",
|
69
|
+
"bar: bar"
|
70
|
+
)
|
71
|
+
expect(subject.configure(opts)).to eq(
|
72
|
+
OpenStruct.new(
|
73
|
+
'foo' => 'foo',
|
74
|
+
'bar' => 'bar'
|
75
|
+
)
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def default_opts
|
83
|
+
{
|
84
|
+
:exactly => :once,
|
85
|
+
:type => Foundry::Sources::File,
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def with_source(opts={})
|
90
|
+
merged_opts = default_opts.merge(opts)
|
91
|
+
source = merged_opts[:type].new
|
92
|
+
expect(subject).to receive(:source).exactly(merged_opts[:exactly]) { source }
|
93
|
+
yield source
|
55
94
|
end
|
56
95
|
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
subject do
|
5
|
+
{
|
6
|
+
:A => nil,
|
7
|
+
:B => nil,
|
8
|
+
:C => nil,
|
9
|
+
:D => nil,
|
10
|
+
}
|
11
|
+
end
|
12
|
+
let(:keys) do
|
13
|
+
[
|
14
|
+
:A,
|
15
|
+
:B,
|
16
|
+
:C,
|
17
|
+
:D,
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:other) do
|
22
|
+
{
|
23
|
+
:E => nil,
|
24
|
+
:F => nil,
|
25
|
+
:G => nil,
|
26
|
+
:H => nil,
|
27
|
+
}
|
28
|
+
end
|
29
|
+
let(:other_keys) do
|
30
|
+
[
|
31
|
+
:E,
|
32
|
+
:F,
|
33
|
+
:G,
|
34
|
+
:H,
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
let(:nested) do
|
39
|
+
{
|
40
|
+
:I => nil,
|
41
|
+
:J => nil,
|
42
|
+
:K => {
|
43
|
+
:L => nil,
|
44
|
+
},
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'destructive' do
|
49
|
+
describe 'deep_merge!' do
|
50
|
+
it 'can merge two hashes' do
|
51
|
+
expect(subject.deep_merge!(other)).to eq({
|
52
|
+
:A => nil,
|
53
|
+
:B => nil,
|
54
|
+
:C => nil,
|
55
|
+
:D => nil,
|
56
|
+
:E => nil,
|
57
|
+
:F => nil,
|
58
|
+
:G => nil,
|
59
|
+
:H => nil,
|
60
|
+
})
|
61
|
+
expect(subject.size).to eq(keys.size + other_keys.size)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'can merge nested hashes' do
|
65
|
+
expect(subject.deep_merge!(nested)).to eq({
|
66
|
+
:A => nil,
|
67
|
+
:B => nil,
|
68
|
+
:C => nil,
|
69
|
+
:D => nil,
|
70
|
+
:I => nil,
|
71
|
+
:J => nil,
|
72
|
+
:K => {
|
73
|
+
:L => nil,
|
74
|
+
},
|
75
|
+
})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'without!' do
|
80
|
+
it 'can filter one key' do
|
81
|
+
expect(subject.without!(:A)).to eq({
|
82
|
+
:B => nil,
|
83
|
+
:C => nil,
|
84
|
+
:D => nil,
|
85
|
+
})
|
86
|
+
expect(subject.size).to eq(keys.size - 1)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'can filter multiple keys' do
|
90
|
+
expect(subject.without!(:A, :B)).to eq({
|
91
|
+
:C => nil,
|
92
|
+
:D => nil,
|
93
|
+
})
|
94
|
+
expect(subject.size).to eq(keys.size - 2)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'skips keys that do not exist' do
|
98
|
+
expect(subject.without!(:E)).to eq({
|
99
|
+
:A => nil,
|
100
|
+
:B => nil,
|
101
|
+
:C => nil,
|
102
|
+
:D => nil,
|
103
|
+
})
|
104
|
+
expect(subject.size).to eq(keys.size)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'non-destructive' do
|
110
|
+
describe 'deep_merge' do
|
111
|
+
it 'can merge two hashes' do
|
112
|
+
expect(subject.deep_merge(other)).to eq({
|
113
|
+
:A => nil,
|
114
|
+
:B => nil,
|
115
|
+
:C => nil,
|
116
|
+
:D => nil,
|
117
|
+
:E => nil,
|
118
|
+
:F => nil,
|
119
|
+
:G => nil,
|
120
|
+
:H => nil,
|
121
|
+
})
|
122
|
+
expect(subject.size).to eq(keys.size)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'can merge nested hashes' do
|
126
|
+
expect(subject.deep_merge(nested)).to eq({
|
127
|
+
:A => nil,
|
128
|
+
:B => nil,
|
129
|
+
:C => nil,
|
130
|
+
:D => nil,
|
131
|
+
:I => nil,
|
132
|
+
:J => nil,
|
133
|
+
:K => {
|
134
|
+
:L => nil,
|
135
|
+
},
|
136
|
+
})
|
137
|
+
expect(subject.size).to eq(keys.size)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'without' do
|
142
|
+
it 'can filter one key' do
|
143
|
+
expect(subject.without(:A)).to eq({
|
144
|
+
:B => nil,
|
145
|
+
:C => nil,
|
146
|
+
:D => nil,
|
147
|
+
})
|
148
|
+
expect(subject.size).to eq(keys.size)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'can filter multiple keys' do
|
152
|
+
expect(subject.without(:A, :B)).to eq({
|
153
|
+
:C => nil,
|
154
|
+
:D => nil,
|
155
|
+
})
|
156
|
+
expect(subject.size).to eq(keys.size)
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'skips keys that do not exist' do
|
160
|
+
expect(subject.without(:E)).to eq({
|
161
|
+
:A => nil,
|
162
|
+
:B => nil,
|
163
|
+
:C => nil,
|
164
|
+
:D => nil,
|
165
|
+
})
|
166
|
+
expect(subject.size).to eq(keys.size)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Foundry::Sources::File do
|
4
|
+
subject { Foundry::Sources::File.new }
|
5
|
+
|
6
|
+
it 'can load a file' do
|
7
|
+
expect(File).to receive(:read)
|
8
|
+
subject.load('', '', {})
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'will raise an error if the file does not exist' do
|
12
|
+
expect { subject.load('', '', {}) }.to raise_error
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Foundry::Sources::URI do
|
4
|
+
subject { Foundry::Sources::URI.new }
|
5
|
+
let(:domain) { 'foo.bar.com' }
|
6
|
+
let(:relative_path) { 'config.yml' }
|
7
|
+
|
8
|
+
let(:http_uri) { "#{http_root_path}/#{relative_path}" }
|
9
|
+
let(:http_root_path) { "http://#{domain}" }
|
10
|
+
let(:http_response_body) { 'http_response_body' }
|
11
|
+
let(:http_opts) { {} }
|
12
|
+
|
13
|
+
let(:https_uri) { "#{https_root_path}/#{relative_path}" }
|
14
|
+
let(:https_root_path) { "https://#{domain}" }
|
15
|
+
let(:https_response_body) { 'https_response_body' }
|
16
|
+
let(:https_opts) { {} }
|
17
|
+
|
18
|
+
let(:basic_auth_uri) { "http://#{basic_auth_username}:#{basic_auth_password}@#{domain}/#{relative_path}" }
|
19
|
+
let(:basic_auth_root_path) { http_root_path }
|
20
|
+
let(:basic_auth_response_body) { 'basic_auth_response_body' }
|
21
|
+
let(:basic_auth_username) { 'basic_auth_username' }
|
22
|
+
let(:basic_auth_password) { 'basic_auth_password' }
|
23
|
+
let(:basic_auth_opts) { { :username => basic_auth_username, :password => basic_auth_password } }
|
24
|
+
|
25
|
+
before do
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can load from a HTTP endpoint' do
|
29
|
+
stub_request(:get, http_uri).to_return(:body => http_response_body)
|
30
|
+
|
31
|
+
expect(
|
32
|
+
subject.load(
|
33
|
+
http_root_path,
|
34
|
+
relative_path,
|
35
|
+
http_opts
|
36
|
+
)
|
37
|
+
).to eq(http_response_body)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can load from a HTTPS endpoint' do
|
41
|
+
stub_request(:get, https_uri).to_return(:body => https_response_body)
|
42
|
+
|
43
|
+
expect(
|
44
|
+
subject.load(
|
45
|
+
https_root_path,
|
46
|
+
relative_path,
|
47
|
+
https_opts
|
48
|
+
)
|
49
|
+
).to eq(https_response_body)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'can load from a endpoint using basic-auth' do
|
53
|
+
stub_request(:get, basic_auth_uri).to_return(:body => basic_auth_response_body)
|
54
|
+
|
55
|
+
expect(
|
56
|
+
subject.load(
|
57
|
+
basic_auth_root_path,
|
58
|
+
relative_path,
|
59
|
+
basic_auth_opts
|
60
|
+
)
|
61
|
+
).to eq(basic_auth_response_body)
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foundry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan W. Zaleski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.6'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pry
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0.10'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.10'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '10.3'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.3'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '3.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: webmock
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.20'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.20'
|
69
83
|
description: |2
|
70
84
|
Let's face it, there are a number of problems when application/environment
|
71
85
|
configuration logic is too tightly coupled with the configuration-data itself.
|
@@ -76,8 +90,8 @@ executables: []
|
|
76
90
|
extensions: []
|
77
91
|
extra_rdoc_files: []
|
78
92
|
files:
|
79
|
-
-
|
80
|
-
-
|
93
|
+
- .gitignore
|
94
|
+
- .travis.yml
|
81
95
|
- Gemfile
|
82
96
|
- LICENSE.txt
|
83
97
|
- README.md
|
@@ -86,12 +100,14 @@ files:
|
|
86
100
|
- foundry.gemspec
|
87
101
|
- lib/foundry.rb
|
88
102
|
- lib/foundry/configurator.rb
|
89
|
-
- lib/foundry/
|
90
|
-
- lib/foundry/
|
103
|
+
- lib/foundry/refinements/hash.rb
|
104
|
+
- lib/foundry/sources/file.rb
|
105
|
+
- lib/foundry/sources/uri.rb
|
91
106
|
- lib/foundry/version.rb
|
92
107
|
- spec/configurator_spec.rb
|
93
|
-
- spec/
|
94
|
-
- spec/
|
108
|
+
- spec/refinements/hash_spec.rb
|
109
|
+
- spec/sources/file_spec.rb
|
110
|
+
- spec/sources/uri_spec.rb
|
95
111
|
- spec/spec_helper.rb
|
96
112
|
homepage: https://github.com/jzaleski/foundry
|
97
113
|
licenses:
|
@@ -103,22 +119,23 @@ require_paths:
|
|
103
119
|
- lib
|
104
120
|
required_ruby_version: !ruby/object:Gem::Requirement
|
105
121
|
requirements:
|
106
|
-
- -
|
122
|
+
- - '>='
|
107
123
|
- !ruby/object:Gem::Version
|
108
124
|
version: '0'
|
109
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
126
|
requirements:
|
111
|
-
- -
|
127
|
+
- - '>='
|
112
128
|
- !ruby/object:Gem::Version
|
113
129
|
version: '0'
|
114
130
|
requirements: []
|
115
131
|
rubyforge_project:
|
116
|
-
rubygems_version: 2.
|
132
|
+
rubygems_version: 2.2.2
|
117
133
|
signing_key:
|
118
134
|
specification_version: 4
|
119
135
|
summary: An application configuration gem that aims to keep it simple
|
120
136
|
test_files:
|
121
137
|
- spec/configurator_spec.rb
|
122
|
-
- spec/
|
123
|
-
- spec/
|
138
|
+
- spec/refinements/hash_spec.rb
|
139
|
+
- spec/sources/file_spec.rb
|
140
|
+
- spec/sources/uri_spec.rb
|
124
141
|
- spec/spec_helper.rb
|
data/lib/foundry/loaders/file.rb
DELETED
data/lib/foundry/loaders/uri.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module Foundry
|
2
|
-
module Loaders
|
3
|
-
class Uri
|
4
|
-
def self.load(uri, opts)
|
5
|
-
parsed_uri = URI.parse(uri)
|
6
|
-
http = Net::HTTP.new(parsed_uri.host, parsed_uri.port)
|
7
|
-
if parsed_uri.scheme == 'https'
|
8
|
-
http.use_ssl = true
|
9
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
10
|
-
end
|
11
|
-
request = Net::HTTP::Get.new(parsed_uri.request_uri)
|
12
|
-
if username = opts.delete(:username) && password = opts.delete(:password)
|
13
|
-
request.basic_auth(username, password)
|
14
|
-
end
|
15
|
-
http.request(request).body
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/spec/loaders/file_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'foundry/loaders/file'
|
3
|
-
|
4
|
-
describe Foundry::Loaders::File do
|
5
|
-
subject { Foundry::Loaders::File }
|
6
|
-
|
7
|
-
it 'can load a file' do
|
8
|
-
expect(File).to receive(:read)
|
9
|
-
subject.load('', {})
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'will raise an error if the file does not exist' do
|
13
|
-
expect { subject.load('', {}) }.to raise_error
|
14
|
-
end
|
15
|
-
end
|
data/spec/loaders/uri_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'foundry/loaders/uri'
|
3
|
-
|
4
|
-
describe Foundry::Loaders::Uri do
|
5
|
-
subject { Foundry::Loaders::Uri }
|
6
|
-
let(:request) { double }
|
7
|
-
let(:response_body) { 'response_body' }
|
8
|
-
let(:response) { double(:body => response_body) }
|
9
|
-
let(:http) { double(:request => response) }
|
10
|
-
let(:http_url) { 'http://foo.bar.com' }
|
11
|
-
let(:https_url) { http_url.gsub(/\Ahttp:/, 'https:') }
|
12
|
-
|
13
|
-
before do
|
14
|
-
expect(Net::HTTP).to receive(:new) { http }
|
15
|
-
expect(Net::HTTP::Get).to receive(:new) { request }
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'can load from a HTTP endpoint' do
|
19
|
-
expect(subject.load(http_url, {})).to eq(response_body)
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'can load from a HTTPS endpoint' do
|
23
|
-
expect(http).to receive_messages([:use_ssl=, :verify_mode=])
|
24
|
-
expect(subject.load(https_url, {})).to eq(response_body)
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'can load from a endpoint using basic-auth' do
|
28
|
-
expect(request).to receive(:basic_auth)
|
29
|
-
expect(subject.load(
|
30
|
-
http_url, {
|
31
|
-
:username => 'basic_auth_username',
|
32
|
-
:password => 'basic_auth_password',
|
33
|
-
}
|
34
|
-
)).to eq(response_body)
|
35
|
-
end
|
36
|
-
end
|