Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support arbitrary sources in Config.load_files and Config.load_and_set_settings #315

Merged

Conversation

cjlarose
Copy link
Member

Config.load_and_set_settings is the most convenient interface for initializing the Settings object with a bunch of configuration sources. However, one problem is that it only allows paths to YAML files. This means that if the user wants to use an explicit Config::Sources::HashSource or a Config::Sources::EnvSource such as for AWS Secrets Manager, they have to call add_source! and reload! separately.

Config.setup do |config|
  config.const_name = 'Settings'
end

Config.load_and_set_settings(
  Rails.root.join('config', 'settings', 'base.yml'),
  Rails.root.join('config', 'settings', 'default.yml')
)

secrets_source = Config::Sources::EnvSource.new(
  secrets_from_secrets_manager,
  parse_values: false
)
Settings.add_source!(secrets_source)
Settings.reload!

This is especially cumbersome if the user is using a validation contract and the settings aren't yet valid until adding the non-YAML sources. It's possible to work around this problem by setting the validation_contact after adding all sources:

Config.setup do |config|
  config.const_name = 'Settings'
end

Config.load_and_set_settings(
  Rails.root.join('config', 'settings', 'base.yml'),
  Rails.root.join('config', 'settings', 'default.yml')
)

secrets_source = Config::Sources::EnvSource.new(
  secrets_from_secrets_manager,
  parse_values: false
)
Settings.add_source!(secrets_source)

Config.validation_contract = ConfigContract.new
Settings.reload!

That's clunky. It'd be easier if the user could just specify the non-YAML sources up front.

Config.setup do |config|
  config.const_name = 'Settings'
  config.validation_contract = ConfigContract.new
end

secrets_source = Config::Sources::EnvSource.new(
  secrets_from_secrets_manager,
  parse_values: false
)

Config.load_and_set_settings(
  Rails.root.join('config', 'settings', 'base.yml'),
  Rails.root.join('config', 'settings', 'default.yml'),
  secrets_source
)

This change makes this possible. There are some breaking changes in a few edge cases, but I expect that most applications will be able to upgrade without modification.

There's a .to_s call in there that's likely to support these kinds of
objects, but there wasn't a test for it.
In an upcoming change, we'll allow arbirtary sources as parameters to
these methods, instead of just filenames. The method names remain
unchanged for now for backwards compatibility.
This uniq call causes issues when mixing the types of sources. This
change can technically break some applications that were depending on
the de-deduplication of source files.
This change effectively conslidates the logic for coercing source
specifications to Source objects into `Config::Options#add_source!`.
For sources specified as Strings or Pathnames, there is effectively no
change, but for sources specified as something else that responds to
`.to_s`, this change could be breaking. In those cases, application
developers can explicitly call `.to_s` on those objects before handing
them to config.
@cjlarose cjlarose merged commit 3dd6817 into rubyconfig:master Jan 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

1 participant