config 2.2.2 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa6adc2bd8ce8b4bfbd732f11005ae7657ef8f5eb8c08b9e08d480408d344433
4
- data.tar.gz: 48d8c6f90457636a2e1732df83cda5dfa2d2d4f5f8286bf7ceb8683f09831e4e
3
+ metadata.gz: df10a2302fd2bd1f1199e97150b44d3f58a28915533dd7579bf58ed6fb77d7dd
4
+ data.tar.gz: 3fe17720f82d92766fd81b6f4dfcdeea1824ca7aa8a71302d4430496cf5921a1
5
5
  SHA512:
6
- metadata.gz: 32228943bbf540ef716f788fd2cde8c51161cf7a92c3d17f36a109aadf895fde2240187f04e7be17a61488602521ee646c74bdf60657c21ad382b757fd22c203
7
- data.tar.gz: e148e52b0f43442c9e8a36e406622d538bcdf9e2faa7eb256376d60bcf2fd8c7c0bf5890a13077a47a0d8415d908ec63567e622f948f93086181f02c653d68b8
6
+ metadata.gz: b9818ca58226256e90282c8dd1e92d1cac9ad77331e31a8073e811a5be36ada096914030da47ac8df2e57a8dcfcaa0d4d20b5a58ffd934602ac9b02356b53f51
7
+ data.tar.gz: 680d6f2b9002d1ede073b391ff747c47fe5bf13f87689dbed1e59b3f8a3abb031449069593e8de01086b62631a43936e3f461008340ed88d23b39a35ab29a2d2
data/CHANGELOG.md CHANGED
@@ -4,6 +4,43 @@
4
4
 
5
5
  ...
6
6
 
7
+ ## 3.1.1
8
+
9
+ ### Bug fixes
10
+
11
+ * Allow the use of unsafe YAML parsing features when using psych >= 4 ([#306](https://github.com/railsconfig/config/issues/306))
12
+
13
+ ## 3.1.0
14
+
15
+ ### New features
16
+
17
+ * Evaluating ERB in YAML files can now be disabled with `Config.evaluate_erb_in_yaml = false`. The default value for this option is `true` for backwards-compatibility. ([#303](https://github.com/rubyconfig/config/pull/303))
18
+
19
+ ## 3.0.0
20
+
21
+ ### BREAKING CHANGES
22
+
23
+ * After upgrade behaviour of `to_h` would change and match behaviour of `to_hash`. Check [#217](https://github.com/rubyconfig/config/issues/217#issuecomment-741953382) for more details.
24
+ * `Config::Options#load_env!` and `Config::Options#reload_env!` have been removed. If you need to reload settings after modifying the `ENV` hash, use `Config.reload!` or `Config::Options#reload!` instead.
25
+
26
+ ### Bug fixes
27
+
28
+ * Added alias `to_h` for `to_hash` ([#277](https://github.com/railsconfig/config/issues/277))
29
+
30
+ ### Changes
31
+
32
+ * Add `Config::Sources::EnvSource` for loading settings from flat `Hash`es with `String` keys and `String` values, such as from AWS SecretsManager ([#299](https://github.com/railsconfig/config/pull/299))
33
+
34
+ ## 2.2.3
35
+
36
+ ### Bug fixes
37
+
38
+ * Revert added alias to_h for to_hash ([#277](https://github.com/railsconfig/config/issues/277))
39
+
40
+ ### Changes
41
+
42
+ * Raise explicit error on environment variable conflicts ([#293](https://github.com/railsconfig/config/issues/293))
43
+
7
44
  ## 2.2.2
8
45
 
9
46
  ### Bug fixes
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Config
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/config.svg)](http://badge.fury.io/rb/config)
3
+ [![Version](https://img.shields.io/gem/v/config)](https://rubygems.org/gems/config)
4
+ [![Downloads Total](https://img.shields.io/gem/dt/config)](https://rubygems.org/gems/config)
5
+ [![Build](https://img.shields.io/github/workflow/status/rubyconfig/config/tests)](https://rubygems.org/gems/config)
4
6
  [![Tests](https://github.com/rubyconfig/config/workflows/tests/badge.svg)](https://github.com/rubyconfig/config/actions?query=branch%3Amaster)
5
- [![Maintainability](https://api.codeclimate.com/v1/badges/85c206c13dce7de090af/maintainability)](https://codeclimate.com/github/rubyconfig/config/maintainability)
6
- [![Test Coverage](https://api.codeclimate.com/v1/badges/85c206c13dce7de090af/test_coverage)](https://codeclimate.com/github/rubyconfig/config/test_coverage)
7
7
  [![Financial Contributors on Open Collective](https://opencollective.com/rubyconfig/all/badge.svg?label=backers)](https://opencollective.com/rubyconfig)
8
8
 
9
9
  ## Summary
@@ -190,8 +190,9 @@ Settings.add_source!("#{Rails.root}/config/settings/local.yml")
190
190
  Settings.reload!
191
191
  ```
192
192
 
193
- > Note: this is an example usage, it is easier to just use the default local files `settings.local.yml,
194
- settings/#{Rails.env}.local.yml and environments/#{Rails.env}.local.yml` for your developer specific settings.
193
+ > Note: this is an example usage, it is easier to just use the default local
194
+ > files `settings.local.yml`, `settings/#{Rails.env}.local.yml` and
195
+ > `environments/#{Rails.env}.local.yml` for your developer specific settings.
195
196
 
196
197
  You also have the option to add a raw hash as a source. One use case might be storing settings in the database or in environment variables that overwrite what is in the YML files.
197
198
 
@@ -204,7 +205,9 @@ You may pass a hash to `prepend_source!` as well.
204
205
 
205
206
  ## Embedded Ruby (ERB)
206
207
 
207
- Embedded Ruby is allowed in the configuration files. Consider the two following config files.
208
+ Embedded Ruby is allowed in the YAML configuration files. ERB will be evaluated at load time by default, and when the `evaluate_erb_in_yaml` configuration is set to `true`.
209
+
210
+ Consider the two following config files.
208
211
 
209
212
  * ```#{Rails.root}/config/settings.yml```
210
213
 
@@ -265,6 +268,7 @@ After installing `Config` in Rails, you will find automatically generated file t
265
268
  ### General
266
269
 
267
270
  * `const_name` - name of the object holing you settings. Default: `'Settings'`
271
+ * `evaluate_erb_in_yaml` - evaluate ERB in YAML config files. Set to false if the config file contains ERB that should not be evaluated at load time. Default: `true`
268
272
 
269
273
  ### Merge customization
270
274
 
@@ -419,6 +423,21 @@ ENV['Settings.section.server'] = 'google.com'
419
423
 
420
424
  It won't work with arrays, though.
421
425
 
426
+ It is considered an error to use environment variables to simutaneously assign a "flat" value and a multi-level value to a key.
427
+
428
+ ```ruby
429
+ # Raises an error when settings are loaded
430
+ ENV['BACKEND_DATABASE'] = 'development'
431
+ ENV['BACKEND_DATABASE_USER'] = 'postgres'
432
+ ```
433
+
434
+ Instead, specify keys of equal depth in the environment variable names:
435
+
436
+ ```ruby
437
+ ENV['BACKEND_DATABASE_NAME'] = 'development'
438
+ ENV['BACKEND_DATABASE_USER'] = 'postgres'
439
+ ```
440
+
422
441
  ### Working with Heroku
423
442
 
424
443
  Heroku uses ENV object to store sensitive settings. You cannot upload such files to Heroku because it's ephemeral filesystem gets recreated from the git sources on each instance refresh. To use config with Heroku just set the `use_env` var to `true` as mentioned above.
@@ -464,6 +483,50 @@ Settings.section.server # => 'google.com'
464
483
  Settings.section.ssl_enabled # => false
465
484
  ```
466
485
 
486
+ ### Working with AWS Secrets Manager
487
+
488
+ It is possible to parse variables stored in an AWS Secrets Manager Secret as if they were environment variables by using `Config::Sources::EnvSource`.
489
+
490
+ For example, the plaintext secret might look like this:
491
+
492
+ ```json
493
+ {
494
+ "Settings.foo": "hello",
495
+ "Settings.bar": "world",
496
+ }
497
+ ```
498
+
499
+ In order to load those settings, fetch the settings from AWS Secrets Manager, parse the plaintext as JSON, pass the resulting `Hash` into a new `EnvSource`, load the new source, and reload.
500
+
501
+ ```ruby
502
+ # fetch secrets from AWS
503
+ client = Aws::SecretsManager::Client.new
504
+ response = client.get_secret_value(secret_id: "#{ENV['ENVIRONMENT']}/my_application")
505
+ secrets = JSON.parse(response.secret_string)
506
+
507
+ # load secrets into config
508
+ secret_source = Config::Sources::EnvSource.new(secrets)
509
+ Settings.add_source!(secret_source)
510
+ Settings.reload!
511
+ ```
512
+
513
+ In this case, the following settings will be available:
514
+
515
+ ```ruby
516
+ Settings.foo # => "hello"
517
+ Settings.bar # => "world"
518
+ ```
519
+
520
+ By default, `EnvSource` will use configuration for `env_prefix`, `env_separator`, `env_converter`, and `env_parse_values`, but any of these can be overridden in the constructor.
521
+
522
+ ```ruby
523
+ secret_source = Config::Sources::EnvSource.new(secrets,
524
+ prefix: 'MyConfig',
525
+ separator: '__',
526
+ converter: nil,
527
+ parse_values: false)
528
+ ```
529
+
467
530
  ## Contributing
468
531
 
469
532
  You are very warmly welcome to help. Please follow our [contribution guidelines](CONTRIBUTING.md)
@@ -31,42 +31,6 @@ module Config
31
31
  @config_sources.unshift(source)
32
32
  end
33
33
 
34
- def reload_env!
35
- return self if ENV.nil? || ENV.empty?
36
-
37
- hash = Hash.new
38
-
39
- ENV.each do |variable, value|
40
- separator = Config.env_separator
41
- prefix = (Config.env_prefix || Config.const_name).to_s.split(separator)
42
-
43
- keys = variable.to_s.split(separator)
44
-
45
- next if keys.shift(prefix.size) != prefix
46
-
47
- keys.map! { |key|
48
- case Config.env_converter
49
- when :downcase then
50
- key.downcase.to_sym
51
- when nil then
52
- key.to_sym
53
- else
54
- raise "Invalid ENV variables name converter: #{Config.env_converter}"
55
- end
56
- }
57
-
58
- leaf = keys[0...-1].inject(hash) { |h, key|
59
- h[key] ||= {}
60
- }
61
-
62
- leaf[keys.last] = Config.env_parse_values ? __value(value) : value
63
- end
64
-
65
- merge!(hash)
66
- end
67
-
68
- alias :load_env! :reload_env!
69
-
70
34
  # look through all our sources and rebuild the configuration
71
35
  def reload!
72
36
  conf = {}
@@ -91,7 +55,6 @@ module Config
91
55
  # swap out the contents of the OStruct with a hash (need to recursively convert)
92
56
  marshal_load(__convert(conf).marshal_dump)
93
57
 
94
- reload_env! if Config.use_env
95
58
  validate!
96
59
 
97
60
  self
@@ -218,17 +181,5 @@ module Config
218
181
  end
219
182
  s
220
183
  end
221
-
222
- # Try to convert string to a correct type
223
- def __value(v)
224
- case v
225
- when 'false'
226
- false
227
- when 'true'
228
- true
229
- else
230
- Integer(v) rescue Float(v) rescue v
231
- end
232
- end
233
184
  end
234
185
  end
@@ -0,0 +1,73 @@
1
+ module Config
2
+ module Sources
3
+ # Allows settings to be loaded from a "flat" hash with string keys, like ENV.
4
+ class EnvSource
5
+ attr_reader :prefix
6
+ attr_reader :separator
7
+ attr_reader :converter
8
+ attr_reader :parse_values
9
+
10
+ def initialize(env,
11
+ prefix: Config.env_prefix || Config.const_name,
12
+ separator: Config.env_separator,
13
+ converter: Config.env_converter,
14
+ parse_values: Config.env_parse_values)
15
+ @env = env
16
+ @prefix = prefix.to_s.split(separator)
17
+ @separator = separator
18
+ @converter = converter
19
+ @parse_values = parse_values
20
+ end
21
+
22
+ def load
23
+ return {} if @env.nil? || @env.empty?
24
+
25
+ hash = Hash.new
26
+
27
+ @env.each do |variable, value|
28
+ keys = variable.to_s.split(separator)
29
+
30
+ next if keys.shift(prefix.size) != prefix
31
+
32
+ keys.map! { |key|
33
+ case converter
34
+ when :downcase then
35
+ key.downcase
36
+ when nil then
37
+ key
38
+ else
39
+ raise "Invalid ENV variables name converter: #{converter}"
40
+ end
41
+ }
42
+
43
+ leaf = keys[0...-1].inject(hash) { |h, key|
44
+ h[key] ||= {}
45
+ }
46
+
47
+ unless leaf.is_a?(Hash)
48
+ conflicting_key = (prefix + keys[0...-1]).join(separator)
49
+ raise "Environment variable #{variable} conflicts with variable #{conflicting_key}"
50
+ end
51
+
52
+ leaf[keys.last] = parse_values ? __value(value) : value
53
+ end
54
+
55
+ hash
56
+ end
57
+
58
+ private
59
+
60
+ # Try to convert string to a correct type
61
+ def __value(v)
62
+ case v
63
+ when 'false'
64
+ false
65
+ when 'true'
66
+ true
67
+ else
68
+ Integer(v) rescue Float(v) rescue v
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -5,14 +5,20 @@ module Config
5
5
  module Sources
6
6
  class YAMLSource
7
7
  attr_accessor :path
8
+ attr_reader :evaluate_erb
8
9
 
9
- def initialize(path)
10
+ def initialize(path, evaluate_erb: Config.evaluate_erb_in_yaml)
10
11
  @path = path.to_s
12
+ @evaluate_erb = !!evaluate_erb
11
13
  end
12
14
 
13
15
  # returns a config hash from the YML file
14
16
  def load
15
- result = YAML.load(ERB.new(IO.read(@path)).result) if @path and File.exist?(@path)
17
+ if @path and File.exist?(@path)
18
+ file_contents = IO.read(@path)
19
+ file_contents = ERB.new(file_contents).result if evaluate_erb
20
+ result = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(file_contents) : YAML.load(file_contents)
21
+ end
16
22
 
17
23
  result || {}
18
24
 
@@ -1,3 +1,3 @@
1
1
  module Config
2
- VERSION = '2.2.2'.freeze
2
+ VERSION = '3.1.1'.freeze
3
3
  end
data/lib/config.rb CHANGED
@@ -4,6 +4,7 @@ require 'config/configuration'
4
4
  require 'config/version'
5
5
  require 'config/sources/yaml_source'
6
6
  require 'config/sources/hash_source'
7
+ require 'config/sources/env_source'
7
8
  require 'config/validation/schema'
8
9
  require 'deep_merge'
9
10
 
@@ -23,7 +24,8 @@ module Config
23
24
  merge_nil_values: true,
24
25
  overwrite_arrays: true,
25
26
  merge_hash_arrays: false,
26
- validation_contract: nil
27
+ validation_contract: nil,
28
+ evaluate_erb_in_yaml: true
27
29
  )
28
30
 
29
31
  def self.setup
@@ -41,6 +43,8 @@ module Config
41
43
  config.add_source!(file.to_s)
42
44
  end
43
45
 
46
+ config.add_source!(Sources::EnvSource.new(ENV)) if Config.use_env
47
+
44
48
  config.load!
45
49
  config
46
50
  end
@@ -52,4 +52,7 @@ Config.setup do |config|
52
52
  # required(:email).filled(format?: EMAIL_REGEX)
53
53
  # end
54
54
 
55
+ # Evaluate ERB in YAML config files at load time.
56
+ #
57
+ # config.evaluate_erb_in_yaml = true
55
58
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: config
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.2
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Kuczynski
8
8
  - Fred Wu
9
9
  - Jacques Crocker
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-12-08 00:00:00.000000000 Z
13
+ date: 2022-01-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: deep_merge
@@ -116,44 +116,58 @@ dependencies:
116
116
  name: bootsnap
117
117
  requirement: !ruby/object:Gem::Requirement
118
118
  requirements:
119
- - - "~>"
119
+ - - ">="
120
120
  - !ruby/object:Gem::Version
121
- version: '1.4'
121
+ version: 1.4.4
122
122
  type: :development
123
123
  prerelease: false
124
124
  version_requirements: !ruby/object:Gem::Requirement
125
125
  requirements:
126
- - - "~>"
126
+ - - ">="
127
127
  - !ruby/object:Gem::Version
128
- version: '1.4'
128
+ version: 1.4.4
129
129
  - !ruby/object:Gem::Dependency
130
130
  name: rails
131
131
  requirement: !ruby/object:Gem::Requirement
132
132
  requirements:
133
133
  - - '='
134
134
  - !ruby/object:Gem::Version
135
- version: 6.0.3.1
135
+ version: 6.1.4
136
136
  type: :development
137
137
  prerelease: false
138
138
  version_requirements: !ruby/object:Gem::Requirement
139
139
  requirements:
140
140
  - - '='
141
141
  - !ruby/object:Gem::Version
142
- version: 6.0.3.1
142
+ version: 6.1.4
143
143
  - !ruby/object:Gem::Dependency
144
144
  name: rspec-rails
145
145
  requirement: !ruby/object:Gem::Requirement
146
146
  requirements:
147
147
  - - "~>"
148
148
  - !ruby/object:Gem::Version
149
- version: '3.7'
149
+ version: '5.0'
150
150
  type: :development
151
151
  prerelease: false
152
152
  version_requirements: !ruby/object:Gem::Requirement
153
153
  requirements:
154
154
  - - "~>"
155
155
  - !ruby/object:Gem::Version
156
- version: '3.7'
156
+ version: '5.0'
157
+ - !ruby/object:Gem::Dependency
158
+ name: psych
159
+ requirement: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '4'
164
+ type: :development
165
+ prerelease: false
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '4'
157
171
  - !ruby/object:Gem::Dependency
158
172
  name: mdl
159
173
  requirement: !ruby/object:Gem::Requirement
@@ -215,6 +229,7 @@ files:
215
229
  - lib/config/integrations/sinatra.rb
216
230
  - lib/config/options.rb
217
231
  - lib/config/rack/reloader.rb
232
+ - lib/config/sources/env_source.rb
218
233
  - lib/config/sources/hash_source.rb
219
234
  - lib/config/sources/yaml_source.rb
220
235
  - lib/config/tasks/heroku.rake
@@ -250,8 +265,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
265
  - !ruby/object:Gem::Version
251
266
  version: '0'
252
267
  requirements: []
253
- rubygems_version: 3.1.2
254
- signing_key:
268
+ rubygems_version: 3.1.6
269
+ signing_key:
255
270
  specification_version: 4
256
271
  summary: Effortless multi-environment settings in Rails, Sinatra, Pandrino and others
257
272
  test_files: []