global 2.1.0 → 3.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 +4 -4
- data/.github/workflows/tests.yml +5 -1
- data/.gitignore +8 -1
- data/.rspec +1 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +11 -1
- data/Rakefile +1 -6
- data/global.gemspec +8 -15
- data/lib/global/backend/aws_parameter_store.rb +1 -1
- data/lib/global/backend/filesystem.rb +1 -1
- data/lib/global/backend/gcp_secret_manager.rb +1 -1
- data/lib/global/configuration.rb +28 -3
- data/lib/global/version.rb +1 -1
- data/spec/global/backend/aws_parameter_store_spec.rb +6 -6
- data/spec/global/backend/gcp_secret_manager_spec.rb +16 -18
- data/spec/global/configuration_spec.rb +83 -81
- data/spec/global_merge_backends_spec.rb +25 -0
- data/spec/global_spec.rb +43 -56
- data/spec/spec_helper.rb +2 -4
- metadata +9 -103
- data/spec/merge_backends_spec.rb +0 -23
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b5acdeb3ad880ec202bb6754c307585a47ffc951982c2d19b85707c2bea17f8
|
|
4
|
+
data.tar.gz: 3c88ae1a5cd961d1d938fecf9598e0da1f87f9d5dc226a110c68bc329c633988
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 93a5195d7db98dc4f806e38428c9553aba5c7b54561f4db729b925145fb3fefa854ee4be3bd8a4a92a02425bd1e4e0203baaa4afcbe37fb33ad6e30ca4482267
|
|
7
|
+
data.tar.gz: bc9d92edd7715f96149c2a5d1ae456ce0e208c636a4f2ed562391d06d7b835c81572b8f6d31591b59aa24f1bf7ed4738e0bf81532f02efa218f98eb2af0b49bf
|
data/.github/workflows/tests.yml
CHANGED
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
|
@@ -2,5 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
source 'https://rubygems.org'
|
|
4
4
|
|
|
5
|
-
# Specify your gem's dependencies in global.gemspec
|
|
6
5
|
gemspec
|
|
6
|
+
|
|
7
|
+
gem 'aws-sdk-ssm', '~> 1'
|
|
8
|
+
gem 'google-cloud-secret_manager', '~> 0'
|
|
9
|
+
|
|
10
|
+
gem 'rake', '>= 13'
|
|
11
|
+
gem 'rspec', '>= 3.0'
|
|
12
|
+
gem 'simplecov'
|
|
13
|
+
|
|
14
|
+
gem 'rubocop', '~> 1.68'
|
|
15
|
+
gem 'rubocop-rake'
|
|
16
|
+
gem 'rubocop-rspec'
|
data/Rakefile
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'rubygems'
|
|
4
|
-
require 'bundler'
|
|
5
|
-
|
|
6
|
-
Bundler.require
|
|
7
|
-
|
|
8
|
-
require 'rspec/core/rake_task'
|
|
9
3
|
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
10
5
|
require 'rubocop/rake_task'
|
|
11
6
|
|
|
12
7
|
RSpec::Core::RakeTask.new(:spec)
|
data/global.gemspec
CHANGED
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require 'global/version'
|
|
3
|
+
require_relative 'lib/global/version'
|
|
5
4
|
|
|
6
5
|
Gem::Specification.new do |s|
|
|
7
6
|
s.name = 'global'
|
|
8
7
|
s.version = Global::VERSION
|
|
8
|
+
s.required_ruby_version = '>= 3.0.0'
|
|
9
9
|
s.authors = ['Railsware LLC']
|
|
10
10
|
s.email = 'contact@railsware.com'
|
|
11
|
-
|
|
12
11
|
s.description = 'Simple way to load your configs from yaml/aws/gcp'
|
|
12
|
+
|
|
13
|
+
s.homepage = 'https://github.com/railsware/global'
|
|
14
|
+
s.licenses = ['MIT']
|
|
13
15
|
s.summary = 'Simple way to load your configs from yaml/aws/gcp'
|
|
14
16
|
|
|
17
|
+
s.metadata['rubygems_mfa_required'] = 'true'
|
|
18
|
+
|
|
15
19
|
s.files = `git ls-files`.split("\n")
|
|
16
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
17
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
18
21
|
s.require_paths = ['lib']
|
|
19
22
|
|
|
20
|
-
s.
|
|
21
|
-
s.licenses = ['MIT']
|
|
22
|
-
|
|
23
|
-
s.add_development_dependency 'aws-sdk-ssm', '~> 1'
|
|
24
|
-
s.add_development_dependency 'google-cloud-secret_manager', '~> 0'
|
|
25
|
-
s.add_development_dependency 'rake', '~> 12.3.1'
|
|
26
|
-
s.add_development_dependency 'rspec', '>= 3.0'
|
|
27
|
-
s.add_development_dependency 'rubocop', '~> 0.81.0'
|
|
28
|
-
s.add_development_dependency 'simplecov', '~> 0.16.1'
|
|
29
|
-
|
|
30
|
-
s.add_runtime_dependency 'activesupport', '>= 2.0'
|
|
23
|
+
s.add_dependency 'activesupport', '>= 2.0'
|
|
31
24
|
end
|
|
@@ -95,7 +95,7 @@ module Global
|
|
|
95
95
|
def build_configuration_from_parameters(parameters)
|
|
96
96
|
configuration = {}
|
|
97
97
|
parameters.each do |parameter|
|
|
98
|
-
parameter_parts = parameter.name[@prefix.length
|
|
98
|
+
parameter_parts = parameter.name[@prefix.length..].split(PATH_SEPARATOR).map(&:to_sym)
|
|
99
99
|
param_container = parameter_parts[0..-2].reduce(configuration) do |container, part|
|
|
100
100
|
container[part] ||= {}
|
|
101
101
|
end
|
|
@@ -60,7 +60,7 @@ module Global
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def load_yml_file(file)
|
|
63
|
-
file_contents = ERB.new(
|
|
63
|
+
file_contents = ERB.new(File.read(file)).result
|
|
64
64
|
permitted_classes = [Date, Time, DateTime, Symbol].concat(@yaml_whitelist_classes)
|
|
65
65
|
|
|
66
66
|
if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('4')
|
|
@@ -108,7 +108,7 @@ module Global
|
|
|
108
108
|
key_name = get_gcp_key_name(parameter)
|
|
109
109
|
next unless key_name.start_with?(@prefix)
|
|
110
110
|
|
|
111
|
-
parameter_parts = key_name[@prefix.length
|
|
111
|
+
parameter_parts = key_name[@prefix.length..].split(PATH_SEPARATOR).map(&:to_sym)
|
|
112
112
|
param_container = parameter_parts[0..-2].reduce(configuration) do |container, part|
|
|
113
113
|
container[part] ||= {}
|
|
114
114
|
end
|
data/lib/global/configuration.rb
CHANGED
|
@@ -13,6 +13,21 @@ module Global
|
|
|
13
13
|
:member?, :[], :[]=, :to_hash, :to_json,
|
|
14
14
|
:inspect, :fetch
|
|
15
15
|
|
|
16
|
+
# rubocop:disable Lint/BooleanSymbol
|
|
17
|
+
# @see ActiveModel::Type::Boolean::FALSE_VALUES
|
|
18
|
+
FALSE_VALUES = [
|
|
19
|
+
false, 0,
|
|
20
|
+
'0', :'0',
|
|
21
|
+
'f', :f,
|
|
22
|
+
'F', :F,
|
|
23
|
+
'false', :false,
|
|
24
|
+
'FALSE', :FALSE,
|
|
25
|
+
'off', :off,
|
|
26
|
+
'OFF', :OFF
|
|
27
|
+
].to_set.freeze
|
|
28
|
+
private_constant :FALSE_VALUES
|
|
29
|
+
# rubocop:enable Lint/BooleanSymbol
|
|
30
|
+
|
|
16
31
|
def initialize(hash)
|
|
17
32
|
@hash = hash.respond_to?(:with_indifferent_access) ? hash.with_indifferent_access : hash
|
|
18
33
|
end
|
|
@@ -49,9 +64,10 @@ module Global
|
|
|
49
64
|
end
|
|
50
65
|
|
|
51
66
|
def method_missing(method, *args, &block)
|
|
52
|
-
|
|
53
|
-
if key?(
|
|
54
|
-
get_configuration_value(
|
|
67
|
+
normalized_method = normalize_key_by_method(method)
|
|
68
|
+
if key?(normalized_method)
|
|
69
|
+
value = get_configuration_value(normalized_method)
|
|
70
|
+
boolean_method?(method) ? cast_boolean(value) : value
|
|
55
71
|
else
|
|
56
72
|
super
|
|
57
73
|
end
|
|
@@ -61,6 +77,15 @@ module Global
|
|
|
61
77
|
'?' == method.to_s[-1]
|
|
62
78
|
end
|
|
63
79
|
|
|
80
|
+
# @see ActiveModel::Type::Boolean#cast_value
|
|
81
|
+
def cast_boolean(value)
|
|
82
|
+
if value == '' || value.nil?
|
|
83
|
+
false
|
|
84
|
+
else
|
|
85
|
+
!FALSE_VALUES.include?(value)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
64
89
|
def normalize_key_by_method(method)
|
|
65
90
|
boolean_method?(method) ? method.to_s[0..-2].to_sym : method
|
|
66
91
|
end
|
data/lib/global/version.rb
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'spec_helper'
|
|
4
3
|
require 'aws-sdk-ssm'
|
|
5
4
|
require 'global/backend/aws_parameter_store'
|
|
6
5
|
|
|
7
6
|
RSpec.describe Global::Backend::AwsParameterStore do
|
|
7
|
+
subject(:parameter_store) do
|
|
8
|
+
described_class.new(prefix: '/testapp/', client: client)
|
|
9
|
+
end
|
|
10
|
+
|
|
8
11
|
let(:client) do
|
|
9
12
|
Aws::SSM::Client.new(stub_responses: true)
|
|
10
13
|
end
|
|
11
|
-
subject do
|
|
12
|
-
described_class.new(prefix: '/testapp/', client: client)
|
|
13
|
-
end
|
|
14
14
|
|
|
15
|
-
it 'reads parameters from the parameter store' do
|
|
15
|
+
it 'reads parameters from the parameter store' do # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
|
|
16
16
|
client.stub_responses(
|
|
17
17
|
:get_parameters_by_path,
|
|
18
18
|
[
|
|
@@ -37,7 +37,7 @@ RSpec.describe Global::Backend::AwsParameterStore do
|
|
|
37
37
|
}
|
|
38
38
|
]
|
|
39
39
|
)
|
|
40
|
-
expect(
|
|
40
|
+
expect(parameter_store.load).to eq(
|
|
41
41
|
foo: 'foo-value',
|
|
42
42
|
bar: {
|
|
43
43
|
baz: 'baz-value',
|
|
@@ -1,39 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'spec_helper'
|
|
4
3
|
require 'google/cloud/secret_manager'
|
|
4
|
+
require 'google/cloud/secret_manager/v1'
|
|
5
5
|
require 'global/backend/gcp_secret_manager'
|
|
6
6
|
|
|
7
7
|
RSpec.describe Global::Backend::GcpSecretManager do
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
subject do
|
|
8
|
+
subject(:secret_manager) do
|
|
11
9
|
described_class.new(prefix: 'prod-myapp-', client: client, project_id: 'example')
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
@match_item = double
|
|
16
|
-
allow(@match_item).to receive(:name).and_return('prod-myapp-example-test_key')
|
|
12
|
+
let(:client) { instance_double(Google::Cloud::SecretManager::V1::SecretManagerService::Client) }
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
before do
|
|
15
|
+
# rubocop:disable RSpec/VerifiedDoubles
|
|
16
|
+
match_item = double(name: 'prod-myapp-example-test_key')
|
|
17
|
+
not_match_item = double(name: 'different_key')
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
secret_data = double(data: 'secret value')
|
|
20
|
+
secret_version_response = double(payload: secret_data)
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
allow(
|
|
26
|
-
allow(
|
|
22
|
+
page = instance_double(Gapic::PagedEnumerable)
|
|
23
|
+
allow(page).to receive(:next_page_token).and_return('')
|
|
24
|
+
allow(page).to receive(:each).and_yield(match_item).and_yield(not_match_item)
|
|
27
25
|
|
|
28
|
-
allow(client).to receive(:project_path).and_return('projects/example')
|
|
29
26
|
allow(client).to receive(:secret_version_path)
|
|
30
27
|
.with(project: 'example', secret: 'prod-myapp-example-test_key', secret_version: 'latest')
|
|
31
28
|
.and_return('some_key_path')
|
|
32
|
-
allow(client).to receive(:access_secret_version).with(name: 'some_key_path').and_return(
|
|
33
|
-
allow(client).to
|
|
29
|
+
allow(client).to receive(:access_secret_version).with(name: 'some_key_path').and_return(secret_version_response)
|
|
30
|
+
allow(client).to receive_messages(project_path: 'projects/example', list_secrets: page)
|
|
31
|
+
# rubocop:enable RSpec/VerifiedDoubles
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
it 'reads parameters from the secret manager' do
|
|
37
|
-
expect(
|
|
35
|
+
expect(secret_manager.load).to eq({ example: { test_key: 'secret value' }})
|
|
38
36
|
end
|
|
39
37
|
end
|
|
@@ -1,163 +1,165 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
3
|
RSpec.describe Global::Configuration do
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
subject(:configuration) { described_class.new hash }
|
|
5
|
+
|
|
6
|
+
let(:hash) do
|
|
7
|
+
{
|
|
8
|
+
'key' => 'value',
|
|
9
|
+
'boolean_key' => true,
|
|
10
|
+
'nested' => { 'key' => 'value' }
|
|
11
|
+
}
|
|
12
|
+
end
|
|
8
13
|
|
|
9
14
|
describe '#hash' do
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
it { is_expected.to eq(hash) }
|
|
15
|
+
it { expect(configuration.hash).to eq(hash) }
|
|
13
16
|
end
|
|
14
17
|
|
|
15
18
|
describe '#to_hash' do
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
it { is_expected.to eq(hash) }
|
|
19
|
+
it { expect(configuration.to_hash).to eq(hash) }
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
describe 'key?' do
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
it { is_expected.to be_truthy }
|
|
22
|
+
describe '#key?' do
|
|
23
|
+
it { expect(configuration.key?(:key)).to be(true) }
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
describe 'has_key?' do
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
it { is_expected.to be_truthy }
|
|
26
|
+
describe '#has_key?' do
|
|
27
|
+
it { expect(configuration).to have_key(:key) }
|
|
31
28
|
end
|
|
32
29
|
|
|
33
30
|
describe 'include?' do
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
it { is_expected.to be_truthy }
|
|
31
|
+
it { expect(configuration.include?(:key)).to be(true) }
|
|
37
32
|
end
|
|
38
33
|
|
|
39
34
|
describe 'member?' do
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
it { is_expected.to be_truthy }
|
|
35
|
+
it { expect(configuration.member?(:key)).to be(true) }
|
|
43
36
|
end
|
|
44
37
|
|
|
45
38
|
describe '#[]' do
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
it { is_expected.to eq('value') }
|
|
39
|
+
it { expect(configuration[:key]).to eq('value') }
|
|
49
40
|
end
|
|
50
41
|
|
|
51
42
|
describe '#[]=' do
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
it { is_expected.to eq('new_value') }
|
|
43
|
+
it 'sets new value' do
|
|
44
|
+
configuration[:new_key] = 'new_value'
|
|
45
|
+
expect(configuration[:new_key]).to eq('new_value')
|
|
46
|
+
end
|
|
57
47
|
end
|
|
58
48
|
|
|
59
49
|
describe '#inspect' do
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
it { is_expected.to eq(hash.inspect) }
|
|
50
|
+
it { expect(configuration.inspect).to eq(hash.inspect) }
|
|
63
51
|
end
|
|
64
52
|
|
|
65
53
|
describe '#filter' do
|
|
66
|
-
subject { configuration.filter(filter_options) }
|
|
54
|
+
subject(:filter) { configuration.filter(filter_options) }
|
|
67
55
|
|
|
68
56
|
context 'when include all' do
|
|
69
57
|
let(:filter_options) { { only: :all } }
|
|
70
58
|
|
|
71
|
-
it {
|
|
59
|
+
it { expect(filter).to eq('key' => 'value', 'boolean_key' => true, 'nested' => { 'key' => 'value' }) }
|
|
72
60
|
end
|
|
73
61
|
|
|
74
62
|
context 'when except all' do
|
|
75
63
|
let(:filter_options) { { except: :all } }
|
|
76
64
|
|
|
77
|
-
it {
|
|
65
|
+
it { expect(filter).to eq({}) }
|
|
78
66
|
end
|
|
79
67
|
|
|
80
68
|
context 'when except present' do
|
|
81
69
|
let(:filter_options) { { except: %w[key] } }
|
|
82
70
|
|
|
83
|
-
it {
|
|
71
|
+
it { expect(filter).to eq('boolean_key' => true, 'nested' => { 'key' => 'value' }) }
|
|
84
72
|
end
|
|
85
73
|
|
|
86
74
|
context 'when include present' do
|
|
87
75
|
let(:filter_options) { { only: %w[key] } }
|
|
88
76
|
|
|
89
|
-
it {
|
|
77
|
+
it { expect(filter).to eq('key' => 'value') }
|
|
90
78
|
end
|
|
91
79
|
|
|
92
80
|
context 'when empty options' do
|
|
93
81
|
let(:filter_options) { {} }
|
|
94
82
|
|
|
95
|
-
it {
|
|
83
|
+
it { expect(filter).to eq({}) }
|
|
96
84
|
end
|
|
97
85
|
end
|
|
98
86
|
|
|
99
87
|
describe '#method_missing' do
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
it { is_expected.to eq('value') }
|
|
88
|
+
it 'returns key value' do
|
|
89
|
+
expect(configuration.key).to eq('value')
|
|
104
90
|
end
|
|
105
91
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
it { is_expected.to eq(true) }
|
|
92
|
+
it 'returns boolean key value' do
|
|
93
|
+
expect(configuration.boolean_key?).to be(true)
|
|
110
94
|
end
|
|
111
95
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
it { expect { subject }.to raise_error(NoMethodError) }
|
|
96
|
+
it 'raises on missing key' do
|
|
97
|
+
expect { configuration.some_key }.to raise_error(NoMethodError)
|
|
116
98
|
end
|
|
117
99
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
it { expect { subject }.to raise_error(NoMethodError) }
|
|
100
|
+
it 'raises on missing boolean key' do
|
|
101
|
+
expect { configuration.some_boolean_key? }.to raise_error(NoMethodError)
|
|
122
102
|
end
|
|
123
103
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
it { is_expected.to eq('value') }
|
|
104
|
+
it 'returns nested key value' do
|
|
105
|
+
expect(configuration.nested.key).to eq('value')
|
|
128
106
|
end
|
|
129
107
|
end
|
|
130
108
|
|
|
131
|
-
describe '
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
109
|
+
describe 'predicate methods' do
|
|
110
|
+
let(:hash) do
|
|
111
|
+
{
|
|
112
|
+
false_string: 'false',
|
|
113
|
+
false_symbol: :false, # rubocop:disable Lint/BooleanSymbol
|
|
114
|
+
off_string: 'off',
|
|
115
|
+
zero_string: '0',
|
|
116
|
+
zero_integer: 0,
|
|
117
|
+
true_string: 'true',
|
|
118
|
+
true_symbol: :true, # rubocop:disable Lint/BooleanSymbol
|
|
119
|
+
on_string: 'on',
|
|
120
|
+
one_string: '1',
|
|
121
|
+
one_integer: 1,
|
|
122
|
+
random_string: ' Offset ',
|
|
123
|
+
empty_string: '',
|
|
124
|
+
nil_value: nil
|
|
125
|
+
}
|
|
136
126
|
end
|
|
137
127
|
|
|
138
|
-
|
|
139
|
-
|
|
128
|
+
it { expect(configuration.false_string?).to be(false) }
|
|
129
|
+
it { expect(configuration.false_symbol?).to be(false) }
|
|
130
|
+
it { expect(configuration.off_string?).to be(false) }
|
|
131
|
+
it { expect(configuration.zero_string?).to be(false) }
|
|
132
|
+
it { expect(configuration.zero_integer?).to be(false) }
|
|
133
|
+
it { expect(configuration.empty_string?).to be(false) }
|
|
134
|
+
it { expect(configuration.nil_value?).to be(false) }
|
|
135
|
+
|
|
136
|
+
it { expect(configuration.true_string?).to be(true) }
|
|
137
|
+
it { expect(configuration.true_symbol?).to be(true) }
|
|
138
|
+
it { expect(configuration.on_string?).to be(true) }
|
|
139
|
+
it { expect(configuration.one_string?).to be(true) }
|
|
140
|
+
it { expect(configuration.one_integer?).to be(true) }
|
|
141
|
+
it { expect(configuration.random_string?).to be(true) }
|
|
142
|
+
end
|
|
140
143
|
|
|
141
|
-
|
|
144
|
+
describe '#respond_to_missing?' do
|
|
145
|
+
it 'responds to key' do
|
|
146
|
+
expect(configuration.respond_to?(:key)).to be(true)
|
|
142
147
|
end
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
it { is_expected.to eq(true) }
|
|
149
|
+
it 'does not respond to unknown key' do
|
|
150
|
+
expect(configuration.respond_to?(:some_key)).to be(false)
|
|
148
151
|
end
|
|
149
152
|
|
|
150
|
-
|
|
151
|
-
|
|
153
|
+
it 'responds to nested key' do
|
|
154
|
+
expect(configuration.nested.respond_to?(:key)).to be(true)
|
|
155
|
+
end
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
it 'calls a method' do
|
|
158
|
+
expect(configuration.method(:key).call).to eq('value')
|
|
154
159
|
end
|
|
155
160
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
expect { configuration.method(:some_key) }.to raise_error(NameError)
|
|
159
|
-
end
|
|
161
|
+
it 'raised on a missing method call' do
|
|
162
|
+
expect { configuration.method(:some_key) }.to raise_error(NameError)
|
|
160
163
|
end
|
|
161
164
|
end
|
|
162
|
-
|
|
163
165
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe Global do
|
|
4
|
+
subject(:global) { described_class }
|
|
5
|
+
|
|
6
|
+
describe 'merging backends' do
|
|
7
|
+
# rubocop:disable RSpec/VerifiedDoubles
|
|
8
|
+
let(:backend_alpha) { double('backend_alpha', load: { foo: 'foo', bar: 'bar-alpha' }) }
|
|
9
|
+
let(:backend_beta) { double('backend_beta', load: { 'bar' => 'bar-beta', 'baz' => 'baz' }) }
|
|
10
|
+
# rubocop:enable RSpec/VerifiedDoubles
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
global.backend backend_alpha
|
|
14
|
+
global.backend backend_beta
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'merges data from two backends together' do
|
|
18
|
+
expect(global.configuration.to_hash).to eq(
|
|
19
|
+
'foo' => 'foo',
|
|
20
|
+
'bar' => 'bar-beta',
|
|
21
|
+
'baz' => 'baz'
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/spec/global_spec.rb
CHANGED
|
@@ -1,65 +1,62 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
3
|
RSpec.describe Global do
|
|
6
|
-
|
|
7
4
|
let(:config_path) { File.join(Dir.pwd, 'spec/files') }
|
|
8
|
-
|
|
5
|
+
|
|
6
|
+
before do
|
|
9
7
|
described_class.configure do |config|
|
|
10
8
|
config.backend :filesystem, path: config_path, environment: 'test'
|
|
11
9
|
end
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
describe '.configuration' do
|
|
15
|
-
subject { described_class.configuration }
|
|
13
|
+
subject(:configuration) { described_class.configuration }
|
|
16
14
|
|
|
17
15
|
it { is_expected.to be_instance_of(Global::Configuration) }
|
|
18
16
|
|
|
19
17
|
context 'when load from directory' do
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
end
|
|
18
|
+
it 'loads configuration' do
|
|
19
|
+
expect(configuration.rspec_config.to_hash).to eq(
|
|
20
|
+
'default_value' => 'default value',
|
|
21
|
+
'test_value' => 'test value'
|
|
22
|
+
)
|
|
26
23
|
end
|
|
27
24
|
end
|
|
28
25
|
|
|
29
26
|
context 'when load from file' do
|
|
30
27
|
let(:config_path) { File.join(Dir.pwd, 'spec/files/rspec_config') }
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
it 'loads configuration' do
|
|
30
|
+
expect(configuration.to_hash).to eq(
|
|
31
|
+
'default_value' => 'default value',
|
|
32
|
+
'test_value' => 'test value'
|
|
33
|
+
)
|
|
37
34
|
end
|
|
38
35
|
end
|
|
39
36
|
|
|
40
37
|
context 'when nested directories' do
|
|
41
|
-
it { expect(
|
|
38
|
+
it { expect(configuration.rspec['config'].to_hash).to eq('default_value' => 'default nested value', 'test_value' => 'test nested value') }
|
|
42
39
|
end
|
|
43
40
|
|
|
44
41
|
context 'when boolean' do
|
|
45
|
-
it { expect(
|
|
46
|
-
it { expect(
|
|
42
|
+
it { expect(configuration.bool_config.works).to be(true) }
|
|
43
|
+
it { expect(configuration.bool_config.works?).to be(true) }
|
|
47
44
|
end
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
it { expect(
|
|
51
|
-
it { expect(
|
|
52
|
-
it { expect(
|
|
46
|
+
describe 'environment file' do
|
|
47
|
+
it { expect(configuration.aws.activated).to be(true) }
|
|
48
|
+
it { expect(configuration.aws.api_key).to eq('some api key') }
|
|
49
|
+
it { expect(configuration.aws.api_secret).to eq('some secret') }
|
|
53
50
|
end
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
it { expect(
|
|
57
|
-
it { expect {
|
|
52
|
+
describe 'skip files with dots in name' do
|
|
53
|
+
it { expect(configuration['aws.test']).to be_nil }
|
|
54
|
+
it { expect { configuration.fetch('aws.test') }.to raise_error(KeyError, /key not found/) }
|
|
58
55
|
end
|
|
59
56
|
end
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
subject { described_class.reload! }
|
|
58
|
+
describe '.reload!' do
|
|
59
|
+
subject(:reloaded_configuration) { described_class.reload! }
|
|
63
60
|
|
|
64
61
|
before do
|
|
65
62
|
described_class.configuration
|
|
@@ -67,49 +64,39 @@ RSpec.describe Global do
|
|
|
67
64
|
described_class.backend :filesystem, path: config_path, environment: 'development'
|
|
68
65
|
end
|
|
69
66
|
|
|
70
|
-
it
|
|
67
|
+
it 'returns configuration' do
|
|
68
|
+
expect(reloaded_configuration).to be_instance_of(Global::Configuration)
|
|
69
|
+
end
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
71
|
+
it 'reloads configuration' do
|
|
72
|
+
expect(reloaded_configuration.rspec_config.to_hash).to eq(
|
|
73
|
+
'default_value' => 'default value',
|
|
74
|
+
'test_value' => 'development value'
|
|
75
|
+
)
|
|
78
76
|
end
|
|
79
77
|
end
|
|
80
78
|
|
|
81
79
|
describe '.respond_to_missing?' do
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
it { is_expected.to be_truthy }
|
|
80
|
+
it 'responds to present config' do
|
|
81
|
+
expect(described_class.respond_to?(:rspec_config)).to be(true)
|
|
86
82
|
end
|
|
87
83
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
it { is_expected.to be_falsey }
|
|
84
|
+
it 'does not respond to missing config' do
|
|
85
|
+
expect(described_class.respond_to?(:some_file)).to be(false)
|
|
92
86
|
end
|
|
93
87
|
end
|
|
94
88
|
|
|
95
89
|
describe '.method_missing' do
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
it { is_expected.to be_kind_of(Global::Configuration) }
|
|
90
|
+
it 'returns configuration' do
|
|
91
|
+
expect(described_class.rspec_config).to be_a(Global::Configuration)
|
|
100
92
|
end
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
it { expect { subject }.to raise_error(NoMethodError) }
|
|
94
|
+
it 'raises on missing configuration' do
|
|
95
|
+
expect { described_class.some_file }.to raise_error(NoMethodError)
|
|
106
96
|
end
|
|
107
97
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
it { is_expected.to be_kind_of(Global::Configuration) }
|
|
98
|
+
it 'returns config with nested hash' do
|
|
99
|
+
expect(described_class.nested_config).to be_a(Global::Configuration)
|
|
112
100
|
end
|
|
113
|
-
|
|
114
101
|
end
|
|
115
102
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
4
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
5
|
-
require 'rspec'
|
|
6
|
-
require 'global'
|
|
7
3
|
require 'simplecov'
|
|
8
4
|
|
|
9
5
|
SimpleCov.start do
|
|
@@ -12,6 +8,8 @@ SimpleCov.start do
|
|
|
12
8
|
add_group 'Libraries', '/lib/'
|
|
13
9
|
end
|
|
14
10
|
|
|
11
|
+
require 'global'
|
|
12
|
+
|
|
15
13
|
RSpec.configure do |config|
|
|
16
14
|
config.disable_monkey_patching!
|
|
17
15
|
|
metadata
CHANGED
|
@@ -1,99 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: global
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Railsware LLC
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-12-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: aws-sdk-ssm
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1'
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: google-cloud-secret_manager
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: rake
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: 12.3.1
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: 12.3.1
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: rspec
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - ">="
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '3.0'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - ">="
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '3.0'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: rubocop
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: 0.81.0
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - "~>"
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: 0.81.0
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: simplecov
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - "~>"
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: 0.16.1
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - "~>"
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: 0.16.1
|
|
97
13
|
- !ruby/object:Gem::Dependency
|
|
98
14
|
name: activesupport
|
|
99
15
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -120,6 +36,7 @@ files:
|
|
|
120
36
|
- ".rspec"
|
|
121
37
|
- ".rubocop.yml"
|
|
122
38
|
- ".ruby-version"
|
|
39
|
+
- CHANGELOG.md
|
|
123
40
|
- CODE_OF_CONDUCT.md
|
|
124
41
|
- Gemfile
|
|
125
42
|
- LICENSE.txt
|
|
@@ -143,13 +60,14 @@ files:
|
|
|
143
60
|
- spec/global/backend/aws_parameter_store_spec.rb
|
|
144
61
|
- spec/global/backend/gcp_secret_manager_spec.rb
|
|
145
62
|
- spec/global/configuration_spec.rb
|
|
63
|
+
- spec/global_merge_backends_spec.rb
|
|
146
64
|
- spec/global_spec.rb
|
|
147
|
-
- spec/merge_backends_spec.rb
|
|
148
65
|
- spec/spec_helper.rb
|
|
149
66
|
homepage: https://github.com/railsware/global
|
|
150
67
|
licenses:
|
|
151
68
|
- MIT
|
|
152
|
-
metadata:
|
|
69
|
+
metadata:
|
|
70
|
+
rubygems_mfa_required: 'true'
|
|
153
71
|
post_install_message:
|
|
154
72
|
rdoc_options: []
|
|
155
73
|
require_paths:
|
|
@@ -158,27 +76,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
158
76
|
requirements:
|
|
159
77
|
- - ">="
|
|
160
78
|
- !ruby/object:Gem::Version
|
|
161
|
-
version:
|
|
79
|
+
version: 3.0.0
|
|
162
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
81
|
requirements:
|
|
164
82
|
- - ">="
|
|
165
83
|
- !ruby/object:Gem::Version
|
|
166
84
|
version: '0'
|
|
167
85
|
requirements: []
|
|
168
|
-
rubygems_version: 3.
|
|
86
|
+
rubygems_version: 3.5.22
|
|
169
87
|
signing_key:
|
|
170
88
|
specification_version: 4
|
|
171
89
|
summary: Simple way to load your configs from yaml/aws/gcp
|
|
172
|
-
test_files:
|
|
173
|
-
- spec/files/aws.test.yml
|
|
174
|
-
- spec/files/aws.yml
|
|
175
|
-
- spec/files/bool_config.yml
|
|
176
|
-
- spec/files/nested_config.yml
|
|
177
|
-
- spec/files/rspec/config.yml
|
|
178
|
-
- spec/files/rspec_config.yml
|
|
179
|
-
- spec/global/backend/aws_parameter_store_spec.rb
|
|
180
|
-
- spec/global/backend/gcp_secret_manager_spec.rb
|
|
181
|
-
- spec/global/configuration_spec.rb
|
|
182
|
-
- spec/global_spec.rb
|
|
183
|
-
- spec/merge_backends_spec.rb
|
|
184
|
-
- spec/spec_helper.rb
|
|
90
|
+
test_files: []
|
data/spec/merge_backends_spec.rb
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Global do
|
|
6
|
-
describe 'merging backends' do
|
|
7
|
-
it 'merges data from two backends together' do
|
|
8
|
-
backend_alpha = double('backend_alpha')
|
|
9
|
-
allow(backend_alpha).to receive(:load).and_return(foo: 'foo', bar: 'bar-alpha')
|
|
10
|
-
described_class.backend backend_alpha
|
|
11
|
-
|
|
12
|
-
backend_beta = double('backend_beta')
|
|
13
|
-
allow(backend_beta).to receive(:load).and_return('bar' => 'bar-beta', 'baz' => 'baz')
|
|
14
|
-
described_class.backend backend_beta
|
|
15
|
-
|
|
16
|
-
expect(described_class.configuration.to_hash).to eq(
|
|
17
|
-
'foo' => 'foo',
|
|
18
|
-
'bar' => 'bar-beta',
|
|
19
|
-
'baz' => 'baz'
|
|
20
|
-
)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|