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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8abc7a1661131160a981373791ccc8ac3a48323283803b32f04a866ae33d3cd2
4
- data.tar.gz: f6c70feae5652f55c564a98df789518efe4e3980ded79c09f51c7429811444b6
3
+ metadata.gz: fa6d5fd8ad5cf3b9df7fcbc3622a6efac55fc1bc3fcc81327ea061eab9a1ae77
4
+ data.tar.gz: 93434d8c607adf270f4acb503cc93bed92850b0fb366fb2d4513f679f39154e3
5
5
  SHA512:
6
- metadata.gz: 20fd00d62bbb2c98fcb4566fe505d67b208190c6bf7b5240520c410d11822252caad6b5574d08a7603f0c5400d75dc80d4b566c1524bd8181ae912fb5d6d3d48
7
- data.tar.gz: a0d0d0ed7fbdb672bb4252558875d01638d78fb4a92c5179f661192fc4125db47800aff3c6b27b1a185f85cde38c356f096fc6ee1ee09b1c05f24c8718dd6abe
6
+ metadata.gz: e86cddbca8a53cf608b72abb8dbe8c1aefdee558636f21cad45b6b3111ced6159f758175e4a377c55fbe2eba0ffab729b7fe427cf84ae43e77e25818a06593d1
7
+ data.tar.gz: 1ad1589204db6e0fa56ca42300f68c32a796a8c181b03c2aebde4104b66568c9100c2cec032b76ade78b811106228611717f92900f96fa451721be4fafebd240
@@ -39,13 +39,15 @@ jobs:
39
39
  - name: Set up Dependencies
40
40
  run: bundle install --path vendor/bundle
41
41
 
42
- - name: Run Tests
43
- uses: paambaati/codeclimate-action@v2.3.0
42
+ - name: Run specs
44
43
  env:
45
44
  COVERAGE: true
46
- CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
47
- with:
48
- coverageCommand: ./bin/rspec
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
@@ -1 +1,6 @@
1
- SimpleCov.start if ENV["COVERAGE"]
1
+ if ENV["COVERAGE"]
2
+ require 'simplecov'
3
+ require 'codecov'
4
+ SimpleCov.start
5
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
6
+ end
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.1.3...HEAD
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.3)
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.3)
14
- deep_merge (~> 1.0, >= 1.0.1)
15
- faraday (~> 0.9)
15
+ diplomat (2.5.1)
16
+ deep_merge (~> 1.2)
17
+ faraday (>= 0.9)
16
18
  docile (1.3.1)
17
- faraday (0.17.3)
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.2.0)
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 (10.5.0)
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 (~> 10.0)
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
  ![Build Status](https://github.com/matic-insurance/consul_application_settings/workflows/ci/badge.svg?branch=master)
4
- [![Test Coverage](https://api.codeclimate.com/v1/badges/b0eaebcf83898535ea4e/test_coverage)](https://codeclimate.com/github/matic-insurance/consul_application_settings/test_coverage)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/b0eaebcf83898535ea4e/maintainability)](https://codeclimate.com/github/matic-insurance/consul_application_settings/maintainability)
4
+ [![Test Coverage](https://codecov.io/gh/matic-insurance/consul_application_settings/branch/master/graph/badge.svg?token=5E8NA8EE8L)](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 defaults file
44
- config.defaults = Rails.root.join('config/settings.yml')
45
- # Specify namespace to consul settings
46
- config.namespace = 'staging/my_cool_app'
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/settings.yml` looks like:
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.app_name # "MyCoolApp"
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.load_from('integrations/database')
118
- db_settings.domain # "194.78.92.19"
119
- db_settings['user'] # "app"
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.namespace = 'staging/my_cool_app'
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.namespace = 'staging/my_cool_app'
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
- | defaults | yes | | String | Path to the file with default settings |
145
- | namespace | no | | String | Base path to read settings from in consul and defaults |
146
- | disable_consul_connection_errors | no | false | Boolean | Do not raise exception when consul is not available (useful for development) |
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.3'
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', '~> 10.0'
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/defaults'
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
- # Main class used to configure defaults file path and load initial settings
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
- class << self
20
- def configure
21
- yield(config)
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
- def load
31
- load_from('')
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
- # Required attributes
5
- attr_accessor :defaults_path
6
- # Optional attributes
7
- attr_accessor :namespace
8
- attr_accessor :disable_consul_connection_errors
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
- self.namespace = ''
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
@@ -6,6 +6,7 @@ module ConsulApplicationSettings
6
6
 
7
7
  class << self
8
8
  def cast_consul_value(value)
9
+ return nil if value.nil?
9
10
  return false if value == 'false'
10
11
  return true if value == 'true'
11
12
 
@@ -1,3 +1,3 @@
1
1
  module ConsulApplicationSettings
2
- VERSION = '0.1.4'.freeze
2
+ VERSION = '3.0.0'.freeze
3
3
  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.1.4
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: 2020-04-16 00:00:00.000000000 Z
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.3
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.3
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: '10.0'
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: '10.0'
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/defaults.rb
140
- - lib/consul_application_settings/options.rb
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