Skip to content

Commit

Permalink
Merge 39a2b26 into 73f57eb
Browse files Browse the repository at this point in the history
  • Loading branch information
AnotherRegularDude committed Jan 12, 2022
2 parents 73f57eb + 39a2b26 commit f0ea94c
Show file tree
Hide file tree
Showing 24 changed files with 427 additions and 62 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# Changelog
All notable changes to this project will be documented in this file.

## Unreleased
### Added
- Added file data resolver functionality:
- Added resolver for `file`
- Added resolver for `vault`
- Added DSL methods for defining custom resolvers
- Added support for kv storage for vault
- Fix using of non-kv storage

```ruby
Qonfig.define_resolver(:https) do |file_path|
Net::HTTP.get(URI("https:://#{file_path}"))
end

class Config < Qonfig::DataSet
load_from_yaml "https://yamlhost.com/cool.yaml"
end
```

## [0.27.0] - 2022-01-12
### Changed
- Drop Ruby 2.5 support.
Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2049,6 +2049,8 @@ end
- **Daily work**
- [Save to JSON file](#save-to-json-file) (`save_to_json`)
- [Save to YAML file](#save-to-yaml-file) (`save_to_yaml`)
- **Define file data resolvers**
- [Working with file data resolvers](#working-with-file-data-resolvers)

---

Expand Down Expand Up @@ -3155,6 +3157,35 @@ dynamic: 10

---

### Working with file data resolvers

You can define custom file data resolver

```ruby
Qonfig.define_resolver(:http) do |file_path|
final_url = URI("http://#{file_path}")
Net::HTTP.get(final_url)
rescue SocketError => error
raise Qonfig::FileNotFoundError, error.message
end

class AppConfig < Qonfig::DataSet
load_from_yaml "http://content-holder.com/settings.yml"
end
```

Also, you can set this file data resolver to default resolver.

```ruby
Qonfig.set_default_resolver :http

class AppConfig < Qonfig::DataSet
load_from_yaml "content-holder.com/settings.yml" # same as previous example
end
```

---

### Plugins

- [toml](#plugins-toml) (provides `load_from_toml`, `save_to_toml`, `expose_toml`);
Expand Down Expand Up @@ -3290,6 +3321,9 @@ config = Config.new
- depends on `vault` gem ([link](https://github.com/hashicorp/vault-ruby)) (tested on `>= 0.1`);
- provides `.load_from_vault` (works in `.load_from_yaml` manner ([doc](#load-from-yaml-file)));
- provides `.expose_vault` (works in `.expose_yaml` manner ([doc](#expose-yaml)));
- provides custom file data resolver `vault://path/to/file/key.yml`;
- you can use version option to use specific version of config in kv storage (dsl and resolver);
- kv storage is used by default, but you can use logical storage by setting `use_kv` to `false`;
```ruby
# 1) require external dependency
Expand Down Expand Up @@ -3323,6 +3357,9 @@ Qonfig.plugin(:vault)
- External validation class with an importing api for better custom validations;
- Setting value changement trace (in `anyway_config` manner);
- Instantiation and reloading callbacks;
- Add supported formats for resolvers: for example, if you use vault resolver, you can't use json format;
- Refactor params passed to methods: use value objects instead;
- Refactor loaders: use base class for them;
## Build
Expand Down
14 changes: 14 additions & 0 deletions lib/qonfig.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module Qonfig
require_relative 'qonfig/imports'
require_relative 'qonfig/plugins'
require_relative 'qonfig/compacted'
require_relative 'qonfig/file_data_resolving'

# @api public
# @since 0.4.0
Expand All @@ -31,6 +32,10 @@ module Qonfig
# @since 0.20.0
extend Validation::PredefinitionMixin

# @api public
# @since 0.26.0
extend FileDataResolving::Mixin

# @since 0.20.0
define_validator(:integer) { |value| value.is_a?(Integer) }
# @since 0.20.0
Expand Down Expand Up @@ -60,6 +65,15 @@ module Qonfig
# @since 0.20.0
define_validator(:not_nil) { |value| value == nil }

# @since 0.26.0
define_resolver(:file) do |file_path|
::File.read(file_path)
rescue Errno::ENOENT => error
raise Qonfig::FileNotFoundError, error.message
end
# @since 0.26.0
set_default_resolver :file

# @since 0.12.0
register_plugin('toml', Qonfig::Plugins::TOML)
# @since 0.19.0
Expand Down
10 changes: 9 additions & 1 deletion lib/qonfig/commands/definition/load_from_json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@ class Qonfig::Commands::Definition::LoadFromJSON < Qonfig::Commands::Base
# @sicne 0.5.0
attr_reader :strict

# @return [Hash]
#
# @api private
# @since 0.26.0
attr_reader :file_resolve_options

# @param file_path [String, Pathname]
# @option strict [Boolean]
# @option file_resolve_options [Hash]
#
# @api private
# @since 0.5.0
def initialize(file_path, strict: true)
def initialize(file_path, strict: true, file_resolve_options: {})
@file_path = file_path
@strict = strict
@file_resolve_options = file_resolve_options
end

# @param data_set [Qonfig::DataSet]
Expand Down
13 changes: 11 additions & 2 deletions lib/qonfig/commands/definition/load_from_yaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@ class Qonfig::Commands::Definition::LoadFromYAML < Qonfig::Commands::Base
# @since 0.2.0
attr_reader :strict

# @return [Hash]
#
# @api private
# @since 0.26.0
attr_reader :file_resolve_options

# @param file_path [String, Pathname]
# @option strict [Boolean]
# @option file_resolve_options [Hash]
#
# @api private
# @since 0.2.0
def initialize(file_path, strict: true)
def initialize(file_path, strict: true, file_resolve_options: {})
@file_path = file_path
@strict = strict
@file_resolve_options = file_resolve_options
end

# @param data_set [Qonfig::DataSet]
Expand All @@ -37,7 +45,8 @@ def initialize(file_path, strict: true)
# @api private
# @since 0.2.0
def call(data_set, settings)
yaml_data = Qonfig::Loaders::YAML.load_file(file_path, fail_on_unexist: strict)
yaml_data = Qonfig::Loaders::YAML
.load_file(file_path, fail_on_unexist: strict, **file_resolve_options)

raise(
Qonfig::IncompatibleYAMLStructureError,
Expand Down
16 changes: 13 additions & 3 deletions lib/qonfig/commands/instantiation/values_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,30 @@ class Qonfig::Commands::Instantiation::ValuesFile < Qonfig::Commands::Base
# @since 0.17.0
attr_reader :expose

# @return [Hash]
#
# @api private
# @since 0.26.0
attr_reader :file_resolve_options

# @param file_path [String, Symbol, Pathname]
# @param caller_location [String]
# @option format [String, Symbol]
# @option strict [Boolean]
# @option expose [NilClass, String, Symbol]
# @option file_resolve_options [Hash]
# @return [void]
#
# @api private
# @since 0.17.0
# @version 0.22.0
# @version 0.26.0
def initialize(
file_path,
caller_location,
format: DEFAULT_FORMAT,
strict: DEFAULT_STRICT_BEHAVIOR,
expose: NO_EXPOSE
expose: NO_EXPOSE,
file_resolve_options: {}
)
prevent_incompatible_attributes!(file_path, format, strict, expose)

Expand All @@ -85,6 +93,7 @@ def initialize(
@format = format
@strict = strict
@expose = expose
@file_resolve_options = file_resolve_options
end

# @param data_set [Qonfig::DataSet]
Expand Down Expand Up @@ -117,7 +126,8 @@ def load_settings_values
# @api private
# @since 0.17.0
def load_from_file
Qonfig::Loaders.resolve(format).load_file(file_path, fail_on_unexist: strict).tap do |values|
load_options = { fail_on_unexist: strict, **file_resolve_options }
Qonfig::Loaders.resolve(format).load_file(file_path, **load_options).tap do |values|
raise(
Qonfig::IncompatibleDataStructureError,
'Setting values must be a hash-like structure'
Expand Down
26 changes: 21 additions & 5 deletions lib/qonfig/data_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def reload!(settings_map = {}, &configurations)
# @option format [String, Symbol]
# @option strict [Boolean]
# @option expose [NilClass, String, Symbol] Environment key
# @option **file_resolve_options [Hash]
# @param configurations [Block]
# @return [void]
#
Expand All @@ -109,17 +110,26 @@ def reload!(settings_map = {}, &configurations)
# @api public
# @since 0.17.0
# @version 0.22.0
def load_from_file(file_path, format: :dynamic, strict: true, expose: nil, &configurations)
def load_from_file(
file_path,
format: :dynamic,
strict: true,
expose: nil,
**file_resolve_options,
&configurations
)
thread_safe_access do
load_setting_values_from_file(
file_path, format: format, strict: strict, expose: expose, &configurations
file_path, format: format, strict: strict,
expose: expose, file_resolve_options: file_resolve_options, &configurations
)
end
end

# @param file_path [String, Symbol, Pathname]
# @option strict [Boolean]
# @option expose [NilClass, String, Symbol] Environment key
# @option **file_resolve_options [Hash]
# @param configurations [Block]
# @return [void]
#
Expand All @@ -128,8 +138,11 @@ def load_from_file(file_path, format: :dynamic, strict: true, expose: nil, &conf
# @api public
# @since 0.17.0
# @version 0.22.0
def load_from_yaml(file_path, strict: true, expose: nil, &configurations)
load_from_file(file_path, format: :yml, strict: strict, expose: expose, &configurations)
def load_from_yaml(file_path, strict: true, expose: nil, **file_resolve_options, &configurations)
load_from_file(
file_path, format: :yml, strict: strict,
expose: expose, **file_resolve_options, &configurations
)
end

# @param file_path [String, Symbol, Pathname]
Expand Down Expand Up @@ -521,6 +534,7 @@ def load!(settings_map = {}, &configurations)
# @option strict [Boolean]
# @option expose [NilClass, String, Symbol]
# @option callcer_location [NilClass, String]
# @option **file_resolve_options [Hash]
# @param configurations [Block]
# @return [void]
#
Expand All @@ -535,10 +549,12 @@ def load_setting_values_from_file(
strict: true,
expose: nil,
caller_location: nil,
file_resolve_options: {},
&configurations
)
Qonfig::Commands::Instantiation::ValuesFile.new(
file_path, caller_location, format: format, strict: strict, expose: expose
file_path, caller_location, format: format,
strict: strict, expose: expose, file_resolve_options: file_resolve_options
).call(self, settings)
apply_settings(&configurations)
end
Expand Down
12 changes: 8 additions & 4 deletions lib/qonfig/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,16 @@ def compose(data_set_klass)

# @param file_path [String, Pathname]
# @option strict [Boolean]
# @option **file_resolve_options [Hash]
# @return [void]
#
# @see Qonfig::Commands::Definition::LoadFromYAML
#
# @api public
# @since 0.2.0
def load_from_yaml(file_path, strict: true)
def load_from_yaml(file_path, strict: true, **file_resolve_options)
definition_commands << Qonfig::Commands::Definition::LoadFromYAML.new(
file_path, strict: strict
file_path, strict: strict, file_resolve_options: file_resolve_options
)
end

Expand Down Expand Up @@ -202,14 +203,17 @@ def load_from_env(convert_values: false, prefix: nil, trim_prefix: false)

# @param file_path [String, Pathname]
# @option strict [Boolean]
# @option **file_resolve_options [Hash]
# @return [void]
#
# @see Qonfig::Commands::Definition::LoadFromJSON
#
# @api public
# @since 0.5.0
def load_from_json(file_path, strict: true)
definition_commands << Qonfig::Commands::Definition::LoadFromJSON.new(file_path, strict: strict)
def load_from_json(file_path, strict: true, **file_resolve_options)
definition_commands << Qonfig::Commands::Definition::LoadFromJSON.new(
file_path, strict: strict, file_resolve_options: file_resolve_options
)
end

# @param file_path [String, Pathname]
Expand Down
8 changes: 8 additions & 0 deletions lib/qonfig/file_data_resolving.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

# @api private
# @since 0.26.0
module Qonfig::FileDataResolving
require_relative 'file_data_resolving/resolver'
require_relative 'file_data_resolving/mixin'
end
24 changes: 24 additions & 0 deletions lib/qonfig/file_data_resolving/mixin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

# @api public
# @since 0.26.0
module Qonfig::FileDataResolving::Mixin
# @param scheme_name [Symbol,String]
# @param block [Block]
# @return [void]
#
# @api public
# @since 0.26.0
def define_resolver(scheme_name, &block)
Qonfig::FileDataResolving::Resolver.add_resolver!(scheme_name, block)
end

# @param scheme_name [Symbol,String]
# @return [void]
#
# @api public
# @since 0.26.0
def set_default_resolver(scheme_name)
Qonfig::FileDataResolving::Resolver.set_default_resolver!(scheme_name)
end
end
Loading

0 comments on commit f0ea94c

Please sign in to comment.