consul_application_settings 0.1.4 → 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/main.yml +7 -5
- data/.simplecov +6 -1
- data/CHANGELOG.md +40 -1
- data/Gemfile.lock +15 -8
- data/README.md +31 -27
- data/bin/benchmark +63 -0
- data/consul_application_settings.gemspec +3 -2
- data/lib/consul_application_settings.rb +11 -17
- data/lib/consul_application_settings/configuration.rb +11 -6
- data/lib/consul_application_settings/providers/abstract.rb +25 -0
- data/lib/consul_application_settings/providers/consul.rb +24 -0
- data/lib/consul_application_settings/providers/consul_preloaded.rb +26 -0
- data/lib/consul_application_settings/providers/local_storage.rb +42 -0
- data/lib/consul_application_settings/reader.rb +25 -0
- data/lib/consul_application_settings/utils.rb +1 -0
- data/lib/consul_application_settings/version.rb +1 -1
- metadata +27 -10
- data/.codeclimate.yml +0 -15
- data/lib/consul_application_settings/defaults.rb +0 -43
- data/lib/consul_application_settings/options.rb +0 -53
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa6d5fd8ad5cf3b9df7fcbc3622a6efac55fc1bc3fcc81327ea061eab9a1ae77
|
|
4
|
+
data.tar.gz: 93434d8c607adf270f4acb503cc93bed92850b0fb366fb2d4513f679f39154e3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e86cddbca8a53cf608b72abb8dbe8c1aefdee558636f21cad45b6b3111ced6159f758175e4a377c55fbe2eba0ffab729b7fe427cf84ae43e77e25818a06593d1
|
|
7
|
+
data.tar.gz: 1ad1589204db6e0fa56ca42300f68c32a796a8c181b03c2aebde4104b66568c9100c2cec032b76ade78b811106228611717f92900f96fa451721be4fafebd240
|
data/.github/workflows/main.yml
CHANGED
|
@@ -39,13 +39,15 @@ jobs:
|
|
|
39
39
|
- name: Set up Dependencies
|
|
40
40
|
run: bundle install --path vendor/bundle
|
|
41
41
|
|
|
42
|
-
- name: Run
|
|
43
|
-
uses: paambaati/codeclimate-action@v2.3.0
|
|
42
|
+
- name: Run specs
|
|
44
43
|
env:
|
|
45
44
|
COVERAGE: true
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
run: bundle exec rspec
|
|
46
|
+
|
|
47
|
+
- name: Upload coverage
|
|
48
|
+
env:
|
|
49
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
50
|
+
run: bash <(curl -s https://codecov.io/bash)
|
|
49
51
|
|
|
50
52
|
release:
|
|
51
53
|
runs-on: ubuntu-latest
|
data/.simplecov
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [3.0.0]
|
|
4
|
+
### Breaking Changes
|
|
5
|
+
- Use Preloaded Consul Settings Provider by default
|
|
6
|
+
### New features
|
|
7
|
+
- Configurable setting providers
|
|
8
|
+
- Preloaded Consul Settings Provider to prioritize performance over consistency
|
|
9
|
+
- Performance tests in spec
|
|
10
|
+
- Benchmarking script
|
|
11
|
+
### Fixes
|
|
12
|
+
- Return nil instead of empty hash when reading missing setting from file
|
|
13
|
+
- Return nil instead of empty string when reading missing value from Consul
|
|
14
|
+
- Add missing load method on Settings Reader to create object with narrow scope
|
|
15
|
+
|
|
16
|
+
## [2.1.1]
|
|
17
|
+
### Changes
|
|
18
|
+
- Update Diplomat to latest version
|
|
19
|
+
|
|
20
|
+
## [2.1.0]
|
|
21
|
+
### Fixes
|
|
22
|
+
- Return nil for unknown keys
|
|
23
|
+
|
|
24
|
+
## [2.0.0]
|
|
25
|
+
### Breaking Changes
|
|
26
|
+
- Change default naming for setting files
|
|
27
|
+
|
|
28
|
+
## [1.0.0]
|
|
29
|
+
### Features
|
|
30
|
+
- Add support for second settings file (local settings for development)
|
|
31
|
+
|
|
32
|
+
## [0.1.4]
|
|
33
|
+
### Fixes
|
|
34
|
+
- Clone values before returning
|
|
35
|
+
|
|
3
36
|
## [0.1.3]
|
|
4
37
|
### Fixes
|
|
5
38
|
- Add `Diplomat::PathNotFound` to the list of caught exceptions
|
|
@@ -22,7 +55,13 @@
|
|
|
22
55
|
- Support deep settings search
|
|
23
56
|
- Support nested configs
|
|
24
57
|
|
|
25
|
-
[Unreleased]: https://github.com/matic-insurance/consul_application_settings/compare/0.
|
|
58
|
+
[Unreleased]: https://github.com/matic-insurance/consul_application_settings/compare/3.0.0...HEAD
|
|
59
|
+
[3.0.0]: https://github.com/matic-insurance/consul_application_settings/compare/2.0.0...3.0.0
|
|
60
|
+
[2.1.1]: https://github.com/matic-insurance/consul_application_settings/compare/2.1.0...2.1.1
|
|
61
|
+
[2.1.0]: https://github.com/matic-insurance/consul_application_settings/compare/2.0.0...2.1.0
|
|
62
|
+
[2.0.0]: https://github.com/matic-insurance/consul_application_settings/compare/1.0.0...2.0.0
|
|
63
|
+
[1.0.0]: https://github.com/matic-insurance/consul_application_settings/compare/0.1.4...1.0.0
|
|
64
|
+
[0.1.4]: https://github.com/matic-insurance/consul_application_settings/compare/0.1.3...0.1.4
|
|
26
65
|
[0.1.3]: https://github.com/matic-insurance/consul_application_settings/compare/0.1.2...0.1.3
|
|
27
66
|
[0.1.2]: https://github.com/matic-insurance/consul_application_settings/compare/0.1.1...0.1.2
|
|
28
67
|
[0.1.1]: https://github.com/matic-insurance/consul_application_settings/compare/0.1.0...0.1.1
|
data/Gemfile.lock
CHANGED
|
@@ -2,29 +2,34 @@ PATH
|
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
4
|
consul_application_settings (0.0.0)
|
|
5
|
-
diplomat (~> 2.1
|
|
5
|
+
diplomat (~> 2.5.1)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
ast (2.4.0)
|
|
11
|
+
codecov (0.4.3)
|
|
12
|
+
simplecov (>= 0.15, < 0.22)
|
|
11
13
|
deep_merge (1.2.1)
|
|
12
14
|
diff-lcs (1.3)
|
|
13
|
-
diplomat (2.1
|
|
14
|
-
deep_merge (~> 1.
|
|
15
|
-
faraday (
|
|
15
|
+
diplomat (2.5.1)
|
|
16
|
+
deep_merge (~> 1.2)
|
|
17
|
+
faraday (>= 0.9)
|
|
16
18
|
docile (1.3.1)
|
|
17
|
-
faraday (
|
|
19
|
+
faraday (1.3.0)
|
|
20
|
+
faraday-net_http (~> 1.0)
|
|
18
21
|
multipart-post (>= 1.2, < 3)
|
|
22
|
+
ruby2_keywords
|
|
23
|
+
faraday-net_http (1.0.1)
|
|
19
24
|
jaro_winkler (1.5.2)
|
|
20
|
-
json (2.
|
|
25
|
+
json (2.3.1)
|
|
21
26
|
multipart-post (2.1.1)
|
|
22
27
|
parallel (1.16.2)
|
|
23
28
|
parser (2.6.2.0)
|
|
24
29
|
ast (~> 2.4.0)
|
|
25
30
|
psych (3.1.0)
|
|
26
31
|
rainbow (3.0.0)
|
|
27
|
-
rake (
|
|
32
|
+
rake (13.0.1)
|
|
28
33
|
rspec (3.8.0)
|
|
29
34
|
rspec-core (~> 3.8.0)
|
|
30
35
|
rspec-expectations (~> 3.8.0)
|
|
@@ -49,6 +54,7 @@ GEM
|
|
|
49
54
|
rubocop-rspec (1.32.0)
|
|
50
55
|
rubocop (>= 0.60.0)
|
|
51
56
|
ruby-progressbar (1.10.0)
|
|
57
|
+
ruby2_keywords (0.0.4)
|
|
52
58
|
simplecov (0.16.1)
|
|
53
59
|
docile (~> 1.1)
|
|
54
60
|
json (>= 1.8, < 3)
|
|
@@ -61,8 +67,9 @@ PLATFORMS
|
|
|
61
67
|
|
|
62
68
|
DEPENDENCIES
|
|
63
69
|
bundler (~> 2.0)
|
|
70
|
+
codecov (~> 0.4)
|
|
64
71
|
consul_application_settings!
|
|
65
|
-
rake (~>
|
|
72
|
+
rake (~> 13.0)
|
|
66
73
|
rspec (~> 3.0)
|
|
67
74
|
rubocop (~> 0.66)
|
|
68
75
|
rubocop-rspec (~> 1.32.0)
|
data/README.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# ConsulApplicationSettings
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-
[](https://codeclimate.com/github/matic-insurance/consul_application_settings/maintainability)
|
|
4
|
+
[](https://codecov.io/gh/matic-insurance/consul_application_settings)
|
|
6
5
|
|
|
7
6
|
Gem that simplifies usage of Consul (via [Diplomat gem](https://github.com/WeAreFarmGeek/diplomat))
|
|
8
7
|
to host application settings. Gem provides defaults via yaml files and other utilities
|
|
@@ -23,7 +22,7 @@ Example use cases:
|
|
|
23
22
|
|
|
24
23
|
Gem reads any particular setting from consul and if it is missing tries to find value in YAML defaults file
|
|
25
24
|
|
|
26
|
-
**NOTE** Consul is requested every time you query the settings. Defaults YAML file loaded in memory and not changing.
|
|
25
|
+
**NOTE** Consul is requested every time you query the settings. Defaults YAML file is loaded in memory and is not changing.
|
|
27
26
|
|
|
28
27
|
## Installation
|
|
29
28
|
|
|
@@ -40,13 +39,22 @@ gem 'consul_application_settings'
|
|
|
40
39
|
At the load of application:
|
|
41
40
|
```ruby
|
|
42
41
|
ConsulApplicationSettings.configure do |config|
|
|
43
|
-
# Specify path to
|
|
44
|
-
config.
|
|
45
|
-
# Specify
|
|
46
|
-
config.
|
|
42
|
+
# Specify path to the base settings YML. Default: 'config/application_settings.yml'
|
|
43
|
+
config.base_file_path = Rails.root.join('config/my_settings.yml')
|
|
44
|
+
# Specify path to the local settings YML, which overrides the base file. Default: 'config/application_settings.local.yml'
|
|
45
|
+
config.local_file_path = Rails.root.join('config/my_settings.local.yml')
|
|
46
|
+
# Specify whether exceprion should be thrown on Consul connection errors. Default: false
|
|
47
|
+
config.disable_consul_connection_errors = true
|
|
48
|
+
# Specify setting providers. Default: [ConsulApplicationSettings::Providers::ConsulPreloaded, ConsulApplicationSettings::Providers::LocalStorage]
|
|
49
|
+
config.settings_providers = [
|
|
50
|
+
ConsulApplicationSettings::Providers::Consul,
|
|
51
|
+
ConsulApplicationSettings::Providers::LocalStorage
|
|
52
|
+
]
|
|
47
53
|
end
|
|
48
54
|
|
|
49
55
|
APP_SETTINGS = ConsulApplicationSettings.load
|
|
56
|
+
# Specify path to settings both in YML files and Consul
|
|
57
|
+
AUTH_SETTIGNS = ConsulApplicationSettings.load('authentication')
|
|
50
58
|
```
|
|
51
59
|
|
|
52
60
|
**NOTE** For rails you can add this code to custom initializer `console_application_settings.rb` in `app/config/initializers`
|
|
@@ -55,7 +63,7 @@ APP_SETTINGS = ConsulApplicationSettings.load
|
|
|
55
63
|
|
|
56
64
|
### Settings structure
|
|
57
65
|
|
|
58
|
-
Assuming your defaults file in repository `config/
|
|
66
|
+
Assuming your defaults file in repository `config/application_settings.yml` looks like:
|
|
59
67
|
```yaml
|
|
60
68
|
staging:
|
|
61
69
|
my_cool_app:
|
|
@@ -98,15 +106,13 @@ Anywhere in your code base, after initialization, you can use
|
|
|
98
106
|
previously loaded settings to query any key by full path
|
|
99
107
|
|
|
100
108
|
```ruby
|
|
101
|
-
APP_SETTINGS
|
|
109
|
+
APP_SETTINGS['app_name'] # "MyCoolApp"
|
|
102
110
|
APP_SETTINGS.get(:hostname) # "https://mycoolapp.com"
|
|
103
111
|
|
|
104
112
|
APP_SETTINGS.get('integrations/database/user') # "app"
|
|
105
113
|
APP_SETTINGS['integrations/slack/enabled'] # true
|
|
106
114
|
```
|
|
107
115
|
|
|
108
|
-
**NOTE** Gem is pulling settings from consul with namespace but ignores namespace for defaults
|
|
109
|
-
|
|
110
116
|
### Nested settings
|
|
111
117
|
|
|
112
118
|
Assuming some part of your code needs to work with smaller part of settings -
|
|
@@ -114,36 +120,34 @@ gem provides interface to avoid duplicating absolute path
|
|
|
114
120
|
|
|
115
121
|
```ruby
|
|
116
122
|
# You can load subsettings from root object
|
|
117
|
-
db_settings = APP_SETTINGS.
|
|
118
|
-
db_settings.domain # "194.78.92.19"
|
|
119
|
-
db_settings['user']
|
|
120
|
-
|
|
121
|
-
# You can load subsettings from subsettings
|
|
122
|
-
integrations_settings = APP_SETTINGS.load_from('integrations')
|
|
123
|
-
slack_settings = integrations_settings.load_from('slack')
|
|
124
|
-
slack_settings.enabled # true
|
|
125
|
-
slack_settings.get('webhook_url') # "https://hooks.slack.com/services/XXXXXX/XXXXX/XXXXXXX"
|
|
123
|
+
db_settings = APP_SETTINGS.load('integrations/database')
|
|
124
|
+
db_settings.get(:domain) # "194.78.92.19"
|
|
125
|
+
db_settings['user'] # "app"
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
### Gem Configuration
|
|
129
129
|
You can configure gem with block:
|
|
130
130
|
```ruby
|
|
131
131
|
ConsulApplicationSettings.configure do |config|
|
|
132
|
-
config.
|
|
132
|
+
config.local_file_path = 'config/config.yml'
|
|
133
133
|
end
|
|
134
134
|
```
|
|
135
135
|
or one option at a time
|
|
136
136
|
```ruby
|
|
137
|
-
ConsulApplicationSettings.config.
|
|
137
|
+
ConsulApplicationSettings.config.local_file_path = 'config/config.yml'
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
All Gem configurations
|
|
141
141
|
|
|
142
|
-
| Configuration | Required | Default | Type | Description
|
|
143
|
-
|
|
144
|
-
|
|
|
145
|
-
|
|
|
146
|
-
| disable_consul_connection_errors | no |
|
|
142
|
+
| Configuration | Required | Default | Type | Description |
|
|
143
|
+
|----------------------------------|----------|-----------------------------------------|---------|------------------------------------------------------------------------------|
|
|
144
|
+
| base_file_path | no | 'config/application_settings.yml' | String | Path to the file with base settings |
|
|
145
|
+
| local_file_path | no | 'config/application_settings.local.yml' | String | Path to the file with local settings overriding the base settings |
|
|
146
|
+
| disable_consul_connection_errors | no | true | Boolean | Do not raise exception when consul is not available (useful for development) |
|
|
147
|
+
| settings_providers | no | Array(Provider) | Array | Specify custom setting provider lists |
|
|
148
|
+
|
|
149
|
+
### Performance vs Consistency
|
|
150
|
+
To be defined in future iterations on Consul Providers
|
|
147
151
|
|
|
148
152
|
## Development
|
|
149
153
|
|
data/bin/benchmark
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'consul_application_settings'
|
|
5
|
+
require 'benchmark'
|
|
6
|
+
|
|
7
|
+
ITERATIONS = 1000
|
|
8
|
+
|
|
9
|
+
def kill_consul
|
|
10
|
+
`pgrep consul | xargs kill`
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start_consul
|
|
14
|
+
spawn('consul agent -dev -node machine > /dev/null 2>&1')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def application_settings(providers)
|
|
18
|
+
file = 'spec/fixtures/base_application_settings.yml'
|
|
19
|
+
ConsulApplicationSettings.configure do |config|
|
|
20
|
+
config.settings_providers = providers
|
|
21
|
+
end
|
|
22
|
+
ConsulApplicationSettings.load(file)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def benchmark_gem
|
|
26
|
+
Benchmark.bm(20) do |x|
|
|
27
|
+
x.report('Real Time Consul') do
|
|
28
|
+
ca = application_settings([
|
|
29
|
+
ConsulApplicationSettings::Providers::Consul,
|
|
30
|
+
ConsulApplicationSettings::Providers::LocalStorage
|
|
31
|
+
])
|
|
32
|
+
ITERATIONS.times { ca.get('application/name') }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
x.report('Preloaded Consul') do
|
|
36
|
+
ca = application_settings([
|
|
37
|
+
ConsulApplicationSettings::Providers::ConsulPreloaded,
|
|
38
|
+
ConsulApplicationSettings::Providers::LocalStorage
|
|
39
|
+
])
|
|
40
|
+
ITERATIONS.times { ca.get('application/name') }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
x.report('File Only') do
|
|
44
|
+
ca = application_settings([
|
|
45
|
+
ConsulApplicationSettings::Providers::ConsulPreloaded
|
|
46
|
+
])
|
|
47
|
+
ITERATIONS.times { ca.get('application/name') }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
puts '-' * 80
|
|
53
|
+
puts 'Benchmark without consul agent'
|
|
54
|
+
kill_consul
|
|
55
|
+
benchmark_gem
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
puts '-' * 80
|
|
59
|
+
puts 'Benchmark with consul agent running'
|
|
60
|
+
start_consul
|
|
61
|
+
benchmark_gem
|
|
62
|
+
|
|
63
|
+
kill_consul
|
|
@@ -29,12 +29,13 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
30
30
|
spec.require_paths = ['lib']
|
|
31
31
|
|
|
32
|
-
spec.add_dependency 'diplomat', '~> 2.1
|
|
32
|
+
spec.add_dependency 'diplomat', '~> 2.5.1'
|
|
33
33
|
|
|
34
34
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
35
|
-
spec.add_development_dependency 'rake', '~>
|
|
35
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
36
36
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
37
37
|
spec.add_development_dependency 'rubocop', '~> 0.66'
|
|
38
38
|
spec.add_development_dependency 'rubocop-rspec', '~> 1.32.0'
|
|
39
39
|
spec.add_development_dependency 'simplecov', '~> 0.16'
|
|
40
|
+
spec.add_development_dependency 'codecov', '~> 0.4'
|
|
40
41
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
require 'consul_application_settings/version'
|
|
2
|
+
require 'consul_application_settings/providers/abstract'
|
|
3
|
+
require 'consul_application_settings/providers/consul'
|
|
4
|
+
require 'consul_application_settings/providers/consul_preloaded'
|
|
5
|
+
require 'consul_application_settings/providers/local_storage'
|
|
2
6
|
require 'consul_application_settings/configuration'
|
|
3
|
-
require 'consul_application_settings/
|
|
4
|
-
require 'consul_application_settings/options'
|
|
7
|
+
require 'consul_application_settings/reader'
|
|
5
8
|
require 'consul_application_settings/utils'
|
|
6
|
-
require 'diplomat'
|
|
7
9
|
|
|
8
|
-
#
|
|
10
|
+
# The gem provides possibility to load settings from Consul and automatically fall back to data stored in file system
|
|
9
11
|
module ConsulApplicationSettings
|
|
10
12
|
class Error < StandardError; end
|
|
11
13
|
|
|
@@ -16,19 +18,11 @@ module ConsulApplicationSettings
|
|
|
16
18
|
|
|
17
19
|
self.config ||= ConsulApplicationSettings::Configuration.new
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
self.defaults = ConsulApplicationSettings::Defaults.read(config.defaults_path)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def load_from(path)
|
|
26
|
-
settings_path = ConsulApplicationSettings::Utils.generate_path(config.namespace, path)
|
|
27
|
-
ConsulApplicationSettings::Options.new(settings_path, defaults)
|
|
28
|
-
end
|
|
21
|
+
def self.configure
|
|
22
|
+
yield(config)
|
|
23
|
+
end
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
25
|
+
def self.load(path = '')
|
|
26
|
+
Reader.new(path, config)
|
|
33
27
|
end
|
|
34
28
|
end
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
module ConsulApplicationSettings
|
|
2
2
|
# All gem configuration settings
|
|
3
3
|
class Configuration
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
DEFAULT_BASE_FILE_PATH = 'config/app_settings.yml'.freeze
|
|
5
|
+
DEFAULT_LOCAL_FILE_PATH = 'config/app_settings.local.yml'.freeze
|
|
6
|
+
DEFAULT_PROVIDERS = [
|
|
7
|
+
ConsulApplicationSettings::Providers::ConsulPreloaded,
|
|
8
|
+
ConsulApplicationSettings::Providers::LocalStorage
|
|
9
|
+
]
|
|
10
|
+
attr_accessor :base_file_path, :local_file_path, :disable_consul_connection_errors, :settings_providers
|
|
9
11
|
|
|
10
12
|
def initialize
|
|
11
|
-
|
|
13
|
+
@base_file_path = DEFAULT_BASE_FILE_PATH
|
|
14
|
+
@local_file_path = DEFAULT_LOCAL_FILE_PATH
|
|
15
|
+
@disable_consul_connection_errors = true
|
|
16
|
+
@settings_providers = DEFAULT_PROVIDERS
|
|
12
17
|
end
|
|
13
18
|
end
|
|
14
19
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module ConsulApplicationSettings
|
|
2
|
+
module Providers
|
|
3
|
+
# Abstract class with basic functionality
|
|
4
|
+
class Abstract
|
|
5
|
+
def initialize(base_path, config)
|
|
6
|
+
@base_path, @config = base_path, config
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def get(path)
|
|
10
|
+
raise NotImplementedError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
def absolute_key_path(path)
|
|
16
|
+
ConsulApplicationSettings::Utils.generate_path(@base_path, path)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_value_from_hash(path, data)
|
|
20
|
+
parts = ConsulApplicationSettings::Utils.decompose_path(path)
|
|
21
|
+
data.dig(*parts).clone
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'diplomat'
|
|
2
|
+
|
|
3
|
+
module ConsulApplicationSettings
|
|
4
|
+
module Providers
|
|
5
|
+
# Provides access to settings stored in Consul
|
|
6
|
+
class Consul < Abstract
|
|
7
|
+
def get(path)
|
|
8
|
+
full_path = absolute_key_path(path)
|
|
9
|
+
value = get_from_consul(full_path)
|
|
10
|
+
ConsulApplicationSettings::Utils.cast_consul_value(value)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def get_from_consul(path)
|
|
16
|
+
Diplomat::Kv.get(path, {})
|
|
17
|
+
rescue Diplomat::KeyNotFound
|
|
18
|
+
return nil
|
|
19
|
+
rescue SystemCallError, Faraday::ConnectionFailed, Diplomat::PathNotFound => e
|
|
20
|
+
raise e unless @config.disable_consul_connection_errors
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module ConsulApplicationSettings
|
|
2
|
+
module Providers
|
|
3
|
+
# Provides access to settings stored in Consul. Loads them once
|
|
4
|
+
class ConsulPreloaded < Abstract
|
|
5
|
+
def initialize(base_path, config)
|
|
6
|
+
super
|
|
7
|
+
@data = get_all_from_consul
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(path)
|
|
11
|
+
value = get_value_from_hash(absolute_key_path(path), @data)
|
|
12
|
+
ConsulApplicationSettings::Utils.cast_consul_value(value)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
protected
|
|
16
|
+
|
|
17
|
+
def get_all_from_consul
|
|
18
|
+
Diplomat::Kv.get_all(@base_path, { convert_to_hash: true })
|
|
19
|
+
rescue Diplomat::KeyNotFound
|
|
20
|
+
{}
|
|
21
|
+
rescue SystemCallError, Faraday::ConnectionFailed, Diplomat::PathNotFound => e
|
|
22
|
+
raise e unless @config.disable_consul_connection_errors
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module ConsulApplicationSettings
|
|
4
|
+
module Providers
|
|
5
|
+
# Provides access to settings stored in file system with support of base and local files
|
|
6
|
+
class LocalStorage < Abstract
|
|
7
|
+
def initialize(base_path, config)
|
|
8
|
+
super
|
|
9
|
+
@data = load
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get(path)
|
|
13
|
+
get_value_from_hash(absolute_key_path(path), @data)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def load
|
|
19
|
+
base_yml = read_yml(base_file_path)
|
|
20
|
+
local_yml = read_yml(local_file_path)
|
|
21
|
+
DeepMerge.deep_merge!(local_yml, base_yml, preserve_unmergeables: false, overwrite_arrays: true,
|
|
22
|
+
merge_nil_values: true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def base_file_path
|
|
26
|
+
@config.base_file_path
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def local_file_path
|
|
30
|
+
@config.local_file_path
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def read_yml(path)
|
|
34
|
+
return {} unless File.exist?(path)
|
|
35
|
+
|
|
36
|
+
YAML.safe_load(IO.read(path))
|
|
37
|
+
rescue Psych::SyntaxError, Errno::ENOENT => e
|
|
38
|
+
raise ConsulApplicationSettings::Error, "Cannot read settings file at #{path}: #{e.message}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module ConsulApplicationSettings
|
|
2
|
+
# Provides access to settings stored in Consul or in file system
|
|
3
|
+
class Reader
|
|
4
|
+
def initialize(base_path, config)
|
|
5
|
+
@base_path = base_path
|
|
6
|
+
@config = config
|
|
7
|
+
@providers = config.settings_providers.map { |provider| provider.new(base_path, config) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get(path)
|
|
11
|
+
@providers.each do |provider|
|
|
12
|
+
value = provider.get(path)
|
|
13
|
+
return value unless value.nil?
|
|
14
|
+
end
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
alias [] get
|
|
19
|
+
|
|
20
|
+
def load(sub_path)
|
|
21
|
+
new_path = ConsulApplicationSettings::Utils.generate_path(@base_path, sub_path)
|
|
22
|
+
self.class.new(new_path, @config)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: consul_application_settings
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Volodymyr Mykhailyk
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-07-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diplomat
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 2.1
|
|
19
|
+
version: 2.5.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 2.1
|
|
26
|
+
version: 2.5.1
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '13.0'
|
|
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
|
-
version: '
|
|
54
|
+
version: '13.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0.16'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: codecov
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.4'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0.4'
|
|
111
125
|
description: |-
|
|
112
126
|
Gem that simplifies usage of Consul (via Diplomat gem) to host application settings.
|
|
113
127
|
Gem provides defaults and utilities
|
|
@@ -117,7 +131,6 @@ executables: []
|
|
|
117
131
|
extensions: []
|
|
118
132
|
extra_rdoc_files: []
|
|
119
133
|
files:
|
|
120
|
-
- ".codeclimate.yml"
|
|
121
134
|
- ".github/workflows/main.yml"
|
|
122
135
|
- ".gitignore"
|
|
123
136
|
- ".rspec"
|
|
@@ -130,14 +143,18 @@ files:
|
|
|
130
143
|
- LICENSE.txt
|
|
131
144
|
- README.md
|
|
132
145
|
- Rakefile
|
|
146
|
+
- bin/benchmark
|
|
133
147
|
- bin/console
|
|
134
148
|
- bin/rspec
|
|
135
149
|
- bin/setup
|
|
136
150
|
- consul_application_settings.gemspec
|
|
137
151
|
- lib/consul_application_settings.rb
|
|
138
152
|
- lib/consul_application_settings/configuration.rb
|
|
139
|
-
- lib/consul_application_settings/
|
|
140
|
-
- lib/consul_application_settings/
|
|
153
|
+
- lib/consul_application_settings/providers/abstract.rb
|
|
154
|
+
- lib/consul_application_settings/providers/consul.rb
|
|
155
|
+
- lib/consul_application_settings/providers/consul_preloaded.rb
|
|
156
|
+
- lib/consul_application_settings/providers/local_storage.rb
|
|
157
|
+
- lib/consul_application_settings/reader.rb
|
|
141
158
|
- lib/consul_application_settings/utils.rb
|
|
142
159
|
- lib/consul_application_settings/version.rb
|
|
143
160
|
homepage: https://github.com/matic-insurance/consul_application_settings
|
|
@@ -162,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
162
179
|
- !ruby/object:Gem::Version
|
|
163
180
|
version: '0'
|
|
164
181
|
requirements: []
|
|
165
|
-
rubygems_version: 3.0.3
|
|
182
|
+
rubygems_version: 3.0.3.1
|
|
166
183
|
signing_key:
|
|
167
184
|
specification_version: 4
|
|
168
185
|
summary: Application settings via Consul with yaml defaults
|
data/.codeclimate.yml
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
plugins:
|
|
3
|
-
# disabled before git-legal supports bundler 2 https://github.com/kmewhort/git.legal-codeclimate/issues/6
|
|
4
|
-
# git-legal:
|
|
5
|
-
# enabled: true
|
|
6
|
-
rubocop:
|
|
7
|
-
enabled: true
|
|
8
|
-
channel: rubocop-0-73
|
|
9
|
-
config:
|
|
10
|
-
file: ".rubocop.yml"
|
|
11
|
-
bundler-audit:
|
|
12
|
-
enabled: true
|
|
13
|
-
exclude_patterns:
|
|
14
|
-
- "spec/"
|
|
15
|
-
- "*.gemspec"
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
require 'yaml'
|
|
2
|
-
|
|
3
|
-
module ConsulApplicationSettings
|
|
4
|
-
# Reading default file from YAML file and providing interface to query them
|
|
5
|
-
class Defaults
|
|
6
|
-
attr_reader :contents
|
|
7
|
-
|
|
8
|
-
def initialize(hash)
|
|
9
|
-
@contents = hash
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def get(name)
|
|
13
|
-
read_path(name, contents).clone
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def load_from(path)
|
|
17
|
-
keys = ConsulApplicationSettings::Utils.decompose_path(path)
|
|
18
|
-
new_defaults = keys.reduce(contents) { |hash, key| read_path(key, hash, {}) }
|
|
19
|
-
self.class.new(new_defaults)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def self.read(path)
|
|
23
|
-
new YAML.safe_load(IO.read(path))
|
|
24
|
-
rescue Psych::SyntaxError, Errno::ENOENT => e
|
|
25
|
-
raise ConsulApplicationSettings::Error, "Cannot read defaults file at #{path}: #{e.message}"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def read_path(path, hash, default = nil)
|
|
31
|
-
parts = ConsulApplicationSettings::Utils.decompose_path(path)
|
|
32
|
-
result = parts.reduce(hash, &method(:read_value))
|
|
33
|
-
result || default
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def read_value(hash, key)
|
|
37
|
-
raise ConsulApplicationSettings::Error, 'reading arrays not implemented' if hash.is_a? Array
|
|
38
|
-
return {} if hash.nil?
|
|
39
|
-
|
|
40
|
-
hash.fetch(key.to_s)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
require 'json'
|
|
2
|
-
|
|
3
|
-
module ConsulApplicationSettings
|
|
4
|
-
# Reads settings from consul or ask defaults for value
|
|
5
|
-
class Options
|
|
6
|
-
attr_reader :path, :defaults
|
|
7
|
-
|
|
8
|
-
def initialize(path, defaults)
|
|
9
|
-
@path = path
|
|
10
|
-
@defaults = defaults.load_from(path)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def load_from(new_path)
|
|
14
|
-
full_path = ConsulApplicationSettings::Utils.generate_path(path, new_path)
|
|
15
|
-
self.class.new(full_path, defaults)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def get(name)
|
|
19
|
-
consul_value = key_value(name)
|
|
20
|
-
if consul_value.nil? || consul_value.empty?
|
|
21
|
-
defaults.get(name)
|
|
22
|
-
else
|
|
23
|
-
ConsulApplicationSettings::Utils.cast_consul_value(consul_value)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def [](name)
|
|
28
|
-
get(name)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# rubocop:disable Style/MethodMissingSuper
|
|
32
|
-
def method_missing(name, *_args)
|
|
33
|
-
get(name)
|
|
34
|
-
end
|
|
35
|
-
# rubocop:enable Style/MethodMissingSuper
|
|
36
|
-
|
|
37
|
-
def respond_to_missing?(_name)
|
|
38
|
-
true
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def key_value(name)
|
|
44
|
-
Diplomat::Kv.get(key_path(name), {}, :return)
|
|
45
|
-
rescue SystemCallError, Faraday::ConnectionFailed, Diplomat::PathNotFound => e
|
|
46
|
-
raise e unless ConsulApplicationSettings.config.disable_consul_connection_errors
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def key_path(name)
|
|
50
|
-
ConsulApplicationSettings::Utils.generate_path(path, name)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|