configuration_service 2.0.4 → 2.0.5
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 +8 -8
- data/.yardopts +3 -0
- data/README.rdoc +26 -27
- data/lib/configuration_service/base.rb +34 -30
- data/lib/configuration_service/configuration.rb +13 -9
- data/lib/configuration_service/errors.rb +1 -4
- data/lib/configuration_service/factory/environment_context/env_dict.rb +1 -1
- data/lib/configuration_service/factory/environment_context.rb +31 -32
- data/lib/configuration_service/factory.rb +1 -5
- data/lib/configuration_service/provider/broken.rb +3 -3
- data/lib/configuration_service/provider/stub.rb +16 -19
- data/lib/configuration_service/provider/stub_store.rb +33 -13
- data/lib/configuration_service/provider.rb +3 -4
- data/lib/configuration_service/provider_registry.rb +21 -17
- data/lib/configuration_service/test/orchestration_provider.rb +114 -104
- data/lib/configuration_service/test/orchestration_provider_registry.rb +21 -15
- data/lib/configuration_service/test/orchestrator.rb +63 -44
- data/lib/configuration_service/test/orchestrator_environment_factory.rb +22 -9
- data/lib/configuration_service/test/response.rb +55 -27
- data/lib/configuration_service/test/stub_orchestration_provider.rb +45 -37
- data/lib/configuration_service/test.rb +7 -6
- data/lib/configuration_service/version.rb +1 -1
- data/lib/configuration_service.rb +3 -3
- metadata +3 -2
- data/README.md +0 -34
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjZmYTRlOWVjZTY2N2NlMjhlNjIwMTBmNmY2ZGU5YWVjZGYyMTY5OA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YjQ2YzUwMWM1YTFlMWY5ZTM1MzBiOTgyM2I4ZDJlNWI3Y2U5OWVhYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZmU3YTI3OTcwMTBkMWQyYmMzNDZiNDQzMzU2MWMzODIzMGU3ZWY4ZWM1YWI3
|
10
|
+
ZGI2ZDYwOWNjOGUxMmQzOGEwYmQxMDUzZWEwMjkxNTIzNWVhNThmYjRmZWY2
|
11
|
+
YTQ3NmZiNmY4MzAzZDI2YTUwYTljY2RhYmU4YjQ1ZTcxMWFiYmU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTY0ZjJkZWYzNWI2ZDdlYjMzZDlkZWMzZmQ0MTg5Y2QyZDdjM2NjYWU4YjQ3
|
14
|
+
OWNiMzNhNzFkYzQ3OGJkMDc0NjQxNTAwMDExYzAzYjdiZWY0OWYzZDRiNDEx
|
15
|
+
OTNjMGZmZmY4YWY5NWQ5MGJjMGE1ZGUyNmVlNzRjYmY2NDk5MTY=
|
data/.yardopts
ADDED
data/README.rdoc
CHANGED
@@ -1,34 +1,32 @@
|
|
1
1
|
= Configuration service
|
2
2
|
|
3
3
|
The configuration service provides
|
4
|
-
{
|
5
|
-
{
|
6
|
-
{
|
4
|
+
{file:features/authorization.feature authorized}
|
5
|
+
{file:features/publishing.feature publication} and
|
6
|
+
{file:features/consuming.feature consumption}
|
7
7
|
of identified configuration data with metadata.
|
8
|
+
The service supports {file:features/bootstrapping.feature bootstrapping}.
|
8
9
|
|
9
|
-
A pluggable Ruby API is provided in ConfigurationService::Base.
|
10
|
+
A pluggable Ruby API is provided in {ConfigurationService::Base}.
|
10
11
|
|
11
|
-
The declarative specification of the service is implemented with
|
12
|
-
|
13
|
-
|
14
|
-
See ConfigurationService::Test.
|
12
|
+
The declarative specification of the service is implemented with cucumber, using a pluggable imperative orchestration providers.
|
13
|
+
This allows for implementations that are not providers to the Ruby API.
|
14
|
+
See {ConfigurationService::Test}.
|
15
15
|
|
16
|
-
A stub service provider is provided in
|
17
|
-
|
16
|
+
A stub service provider is provided in {ConfigurationService::Provider::Stub}.
|
17
|
+
This is used to validate the test framework architecture, and may be used as a stub configuration service in tests.
|
18
|
+
{https://rubygems.org/search?query=configuration_service-provider Other providers} are available as gems.
|
18
19
|
|
19
|
-
Service providers are registered against the
|
20
|
-
ConfigurationService::ProviderRegistry.
|
20
|
+
Service providers are registered against the {ConfigurationService::ProviderRegistry}.
|
21
21
|
|
22
|
-
Factories for creating and configuring service instances are provided in
|
23
|
-
ConfigurationService::Factory.
|
22
|
+
Factories for creating and configuring service instances are provided in {ConfigurationService::Factory}.
|
24
23
|
|
25
24
|
== Usage
|
26
25
|
|
27
|
-
The recommended approach to creating a configuration service client is to use
|
28
|
-
a Factory.
|
26
|
+
The recommended approach to creating a configuration service client is to use a {ConfigurationService::Factory Factory}.
|
29
27
|
|
30
|
-
For example, we can use the EnvironmentContext factory
|
31
|
-
a configuration service client backed by the vault provider as follows.
|
28
|
+
For example, we can use the {ConfigurationService::Factory::EnvironmentContext EnvironmentContext} factory
|
29
|
+
to create and configure a configuration service client backed by the vault provider as follows.
|
32
30
|
|
33
31
|
Our +main.rb+ (or +config.ru+ or whatever) is simple:
|
34
32
|
|
@@ -39,15 +37,15 @@ Our +main.rb+ (or +config.ru+ or whatever) is simple:
|
|
39
37
|
configuraton = service.request_configuration
|
40
38
|
AcmeApplication.new(configuration.data).run
|
41
39
|
|
42
|
-
This relies on a bundler Gemfile to load the gem
|
43
|
-
service provider we configure in the environment:
|
40
|
+
This relies on a {http://bundler.io/ bundler} {http://bundler.io/gemfile.html Gemfile} to load the gem
|
41
|
+
that contains whatever service provider we configure in the environment:
|
44
42
|
|
45
43
|
source 'https://rubygems.org'
|
46
44
|
|
47
45
|
gem 'configuration_service-provider-vault'
|
48
46
|
gem 'acme_application'
|
49
47
|
|
50
|
-
Now we use the process environment to configure the EnvironmentContext factory:
|
48
|
+
Now we use the process environment to configure the {ConfigurationService::Factory::EnvironmentContext EnvironmentContext} factory:
|
51
49
|
|
52
50
|
CFGSRV_IDENTIFIER="acme" \
|
53
51
|
CFGSRV_TOKEN="0b2a80f4-54ce-45f4-8267-f6558fee64af" \
|
@@ -55,13 +53,14 @@ Now we use the process environment to configure the EnvironmentContext factory:
|
|
55
53
|
CFGSRV_PROVIDER_ADDRESS="http://127.0.0.1:8200" \
|
56
54
|
bundle exec main.rb
|
57
55
|
|
58
|
-
Note that +main.rb+ is completely decoupled from the selection of provider and
|
59
|
-
|
60
|
-
manipulating only the Gemfile and the environment.
|
56
|
+
Note that +main.rb+ is completely decoupled from the selection of provider and provider configuration.
|
57
|
+
We could swap and/or reconfigure the provider by manipulating only the +Gemfile+ and the environment.
|
61
58
|
|
62
|
-
If you prefer to hard-code everything,
|
63
|
-
the configuration service isn't expressed by an existing factory yet,
|
64
|
-
construct the service yourself:
|
59
|
+
If you prefer to hard-code everything,
|
60
|
+
or if your strategy for bootstrapping the configuration service isn't expressed by an existing factory yet,
|
61
|
+
you can construct the service yourself:
|
62
|
+
|
63
|
+
# Bad example (hardcoding token into source):
|
65
64
|
|
66
65
|
require 'configuration_service/provider/vault'
|
67
66
|
require 'acme_application'
|
@@ -3,32 +3,28 @@ module ConfigurationService
|
|
3
3
|
##
|
4
4
|
# The configuration service API
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# {authorized}[link:features/authorization_feature.html]
|
8
|
-
# {publication}[link:features/publishing_feature.html] and
|
9
|
-
# {consumption}[link:features/consuming_feature.html]
|
10
|
-
# of identified configuration data with metadata.
|
6
|
+
# See {file:README.rdoc} for a summary of the service, including links to user stories.
|
11
7
|
#
|
12
|
-
# It is recommended that consumers use a Factory to create
|
13
|
-
# and configure the service.
|
8
|
+
# It is recommended that consumers use a {ConfigurationService::Factory} to create and configure the service.
|
14
9
|
#
|
15
10
|
class Base
|
16
11
|
|
17
12
|
##
|
18
|
-
# Creates a new API instance
|
13
|
+
# Creates a new configuration service API instance
|
19
14
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
15
|
+
# @param [String] identifier
|
16
|
+
# the unique identity of some configuration data and its associated metadata.
|
17
|
+
# It might be the name of a service or service component. It might include an environment label
|
18
|
+
# (e.g. production, staging, etc.) For example:
|
23
19
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
20
|
+
# * billing.acme.com
|
21
|
+
# * billing-web1.acme.com
|
22
|
+
# * billing/production/web1
|
23
|
+
# @param [String] token
|
24
|
+
# opaque string representing authority to access the configuration data and associated metadata.
|
25
|
+
# Interpretation of the token is provider-dependent; it is opaque to the API and client.
|
26
|
+
# @param [Object] provider
|
27
|
+
# a configured service provider instance, to which requests will be delegated.
|
32
28
|
#
|
33
29
|
def initialize(identifier, token, provider)
|
34
30
|
@identifier = identifier
|
@@ -37,13 +33,13 @@ module ConfigurationService
|
|
37
33
|
end
|
38
34
|
|
39
35
|
##
|
40
|
-
# Requests the configuration data and metadata
|
36
|
+
# Requests the configuration data and metadata
|
41
37
|
#
|
42
|
-
# Delegates the request to the provider
|
38
|
+
# Delegates the request to the configured +provider+.
|
43
39
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
40
|
+
# @return [ConfigurationService::Configuration] object containing the configuration data, metadata and identifier
|
41
|
+
# @raise [ConfigurationService::ConfigurationNotFoundError] if no configuration was found for the configured +identifier+
|
42
|
+
# @raise [ConfigurationService::Error] if the request failed
|
47
43
|
#
|
48
44
|
def request_configuration
|
49
45
|
@provider.request_configuration(@identifier, @token) or
|
@@ -51,17 +47,25 @@ module ConfigurationService
|
|
51
47
|
end
|
52
48
|
|
53
49
|
##
|
54
|
-
# Publishes configuration
|
50
|
+
# Publishes configuration data and metadata
|
55
51
|
#
|
56
|
-
# The +
|
57
|
-
# The provider receives a a Configuration object, whose +metadata+ is decorated with the following keys:
|
52
|
+
# The +metadata+ is decorated with the following keys:
|
58
53
|
#
|
59
54
|
# * "timestamp" - the current UTC time in ISO8601 format
|
60
55
|
# * "revision" - a UUID for this publication
|
61
56
|
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
57
|
+
# Delegates the request to the configured +provider+. The provider may further decorate the +metadata+.
|
58
|
+
#
|
59
|
+
# It is recommended that both the +data+ and +metadata+ dictionaries use strings as keys,
|
60
|
+
# and that values be limited to those that can be serialized to JSON.
|
61
|
+
#
|
62
|
+
# @param [Hash] data
|
63
|
+
# dictionary of probably sensitive configuration data intended for an application, which providers are expected to secure
|
64
|
+
# @param [Hash] metadata
|
65
|
+
# dictionary of data about the configuration data, which providers are not expected to secure
|
66
|
+
#
|
67
|
+
# @return [ConfigurationService::Configuration] object containing the configuration data, decorated metadata and identifier
|
68
|
+
# @raise [ConfigurationService::Error] if publication failed
|
65
69
|
#
|
66
70
|
def publish_configuration(data, metadata = {})
|
67
71
|
dictionary?(data) or raise ConfigurationService::Error, "data must be a dictionary"
|
@@ -1,24 +1,28 @@
|
|
1
1
|
module ConfigurationService
|
2
2
|
|
3
3
|
##
|
4
|
-
# Encapsulates configuration
|
4
|
+
# Encapsulates identified configuration data and its metadata
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
6
|
+
# @attr_reader [String] identifier
|
7
|
+
# the unique identity of some configuration data and its associated metadata
|
8
|
+
# @attr_reader [Hash] data
|
9
|
+
# dictionary of probably sensitive configuration data intended for an application, which providers are expected to secure
|
10
|
+
# @attr_reader [Hash] metadata
|
11
|
+
# dictionary of data about the configuration data, which providers are not expected to secure
|
11
12
|
#
|
12
|
-
#
|
13
|
-
# values be limited to those that can be serialized to JSON.
|
13
|
+
# @see ConfigurationService::Base#publish_configuration
|
14
14
|
#
|
15
15
|
class Configuration
|
16
16
|
|
17
|
-
attr_reader :identifier, :data, :metadata
|
17
|
+
attr_reader :identifier, :data, :metadata
|
18
18
|
|
19
19
|
##
|
20
20
|
# Returns a new Configuration
|
21
21
|
#
|
22
|
+
# @param [String] identifier unique identity
|
23
|
+
# @param [Hash] data sensitive configuration data
|
24
|
+
# @param [Hash] metadata non-sensitive configuration metadata
|
25
|
+
#
|
22
26
|
def initialize(identifier, data, metadata)
|
23
27
|
@identifier = identifier
|
24
28
|
@data = data
|
@@ -3,14 +3,11 @@ module ConfigurationService
|
|
3
3
|
##
|
4
4
|
# The base of the configuration service exception tree
|
5
5
|
#
|
6
|
-
# * Error
|
7
|
-
# * AuthorizationError
|
8
|
-
#
|
9
6
|
class Error < StandardError
|
10
7
|
end
|
11
8
|
|
12
9
|
##
|
13
|
-
# A configuration service authorization
|
10
|
+
# A configuration service authorization error
|
14
11
|
#
|
15
12
|
class AuthorizationError < Error
|
16
13
|
end
|
@@ -3,7 +3,9 @@ module ConfigurationService
|
|
3
3
|
module Factory
|
4
4
|
|
5
5
|
##
|
6
|
-
#
|
6
|
+
# A factory for creating a configuration service bootstrapped from environmental configuration
|
7
|
+
#
|
8
|
+
# @example Requesting configuration from the {https://github.com/hetznerZA/configuration_service-provider-vault Vault service provider}
|
7
9
|
#
|
8
10
|
# # With the following in the environment:
|
9
11
|
# #
|
@@ -25,17 +27,15 @@ module ConfigurationService
|
|
25
27
|
# require 'bundler'
|
26
28
|
# Bundler.require(:default) # Registers the vault provider
|
27
29
|
#
|
28
|
-
#
|
29
|
-
# configuraton =
|
30
|
+
# configuration_service = ConfigurationService::Factory::EnvironmentContext.create
|
31
|
+
# configuraton = configuration_service.request_configuration
|
30
32
|
# AcmeApplication.new(configuration.data).run
|
31
33
|
#
|
34
|
+
# @attr_reader [String] prefix
|
35
|
+
# prefix for matching environment variable names. Names match if they begin with the prefix and an underscore.
|
36
|
+
#
|
32
37
|
class EnvironmentContext
|
33
38
|
|
34
|
-
##
|
35
|
-
# The prefix for matching environment variable names
|
36
|
-
#
|
37
|
-
# Names match if they begin with the prefix and an underscore.
|
38
|
-
#
|
39
39
|
attr_reader :prefix
|
40
40
|
|
41
41
|
##
|
@@ -46,11 +46,13 @@ module ConfigurationService
|
|
46
46
|
##
|
47
47
|
# Returns a new factory
|
48
48
|
#
|
49
|
-
#
|
50
|
-
#
|
49
|
+
# @param [Hash] env
|
50
|
+
# the string-keyed environment
|
51
|
+
# @param [String] prefix
|
52
|
+
# the prefix for matching environment variable names
|
51
53
|
#
|
52
|
-
# Most consumers will not need to call this method;
|
53
|
-
# .create which instantiates a factory with default +env+ and +prefix+
|
54
|
+
# Most consumers will not need to call this method;
|
55
|
+
# they can use {.create} which instantiates a factory with default +env+ and +prefix+
|
54
56
|
# and uses that internally.
|
55
57
|
#
|
56
58
|
def initialize(env = ENV, prefix = DEFAULT_PREFIX)
|
@@ -58,33 +60,30 @@ module ConfigurationService
|
|
58
60
|
end
|
59
61
|
|
60
62
|
##
|
61
|
-
#
|
63
|
+
# Create a configuration service bootstrapped with environmental configuration
|
62
64
|
#
|
63
|
-
# The environment is scanned for #prefix matches, within which
|
64
|
-
# the following variables are used:
|
65
|
+
# The environment is scanned for {#prefix} matches, within which the following variables are used:
|
65
66
|
#
|
66
67
|
# [IDENTIFIER] the unique identity of the configuration data
|
67
|
-
# (see Base#initialize)
|
68
|
+
# (see {ConfigurationService::Base#initialize})
|
68
69
|
# [TOKEN] authorization token for the identified configuration data
|
69
|
-
# (see Base#initialize)
|
70
|
+
# (see {ConfigurationService::Base#initialize})
|
70
71
|
# [PROVIDER] the unique identity of the service provider
|
71
|
-
# (see ProviderRegistry)
|
72
|
+
# (see {ConfigurationService::ProviderRegistry})
|
72
73
|
# [PROVIDER_*] configuration options for the service provider
|
73
|
-
# (see provider documentation)
|
74
|
+
# (see service provider documentation)
|
74
75
|
#
|
75
|
-
# The service provider class is fetched from the ProviderRegistry using
|
76
|
-
#
|
77
|
-
#
|
78
|
-
# name of the variable without +PROVIDER_+, downcased and intern'd.
|
76
|
+
# The service provider class is fetched from the {ConfigurationService::ProviderRegistry} using +PROVIDER+.
|
77
|
+
# A service provider instance is then constructed with a dictionary of the +PROVIDER_*+ variables,
|
78
|
+
# in which the keys are the name of the variable without +PROVIDER_+, downcased and intern'd.
|
79
79
|
#
|
80
|
-
# Then a service Base is constructed with the +IDENTIFIER+, +TOKEN+
|
81
|
-
# and service provider instance.
|
80
|
+
# Then a service {ConfigurationService::Base} is constructed with the +IDENTIFIER+, +TOKEN+ and service provider instance.
|
82
81
|
#
|
83
|
-
# And finally, the environment is scrubbed of the variables used, to
|
84
|
-
#
|
85
|
-
# that prints the environment).
|
82
|
+
# And finally, the environment is scrubbed of the variables used, to protect them from accidental exposure
|
83
|
+
# (e.g. in an exception handler that prints the environment).
|
86
84
|
#
|
87
|
-
#
|
85
|
+
# @return [ConfigurationService::Base] the configuration service instance created
|
86
|
+
# @raise [ProviderNotFoundError] if no service provider has been registered with the name given by +PROVIDER+
|
88
87
|
#
|
89
88
|
def create
|
90
89
|
ConfigurationService.new(@env[:identifier], @env[:token], provider).tap do
|
@@ -93,11 +92,11 @@ module ConfigurationService
|
|
93
92
|
end
|
94
93
|
|
95
94
|
##
|
96
|
-
# Return a
|
95
|
+
# Return a configuration service bootstrapped with environmental configuration
|
97
96
|
#
|
98
|
-
#
|
97
|
+
# Instantiates a new factory with the process +ENV+ and the {DEFAULT_PREFIX} and uses it to create a configuration service.
|
99
98
|
#
|
100
|
-
#
|
99
|
+
# @see #create
|
101
100
|
#
|
102
101
|
def self.create
|
103
102
|
new.create
|
@@ -3,11 +3,7 @@ Dir.glob(File.expand_path("../factory/**/*.rb", __FILE__), &method(:require))
|
|
3
3
|
module ConfigurationService
|
4
4
|
|
5
5
|
##
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# Current implementations provided by this package:
|
9
|
-
#
|
10
|
-
# * EnvironmentContext
|
6
|
+
# Configuration service factories
|
11
7
|
#
|
12
8
|
module Factory
|
13
9
|
|
@@ -3,21 +3,21 @@ module ConfigurationService
|
|
3
3
|
module Provider
|
4
4
|
|
5
5
|
##
|
6
|
-
# A stub broken ConfigurationService::Base service provider
|
6
|
+
# A stub broken {ConfigurationService::Base} service provider
|
7
7
|
#
|
8
8
|
# Used to validate the test framework architecture.
|
9
9
|
#
|
10
10
|
class Broken
|
11
11
|
|
12
12
|
##
|
13
|
-
#
|
13
|
+
# @raise [ConfigurationService::Error] always
|
14
14
|
#
|
15
15
|
def publish_configuration(configuration, token)
|
16
16
|
raise ConfigurationService::Error, "error requested by test"
|
17
17
|
end
|
18
18
|
|
19
19
|
##
|
20
|
-
#
|
20
|
+
# @raise [ConfigurationService::Error] always
|
21
21
|
#
|
22
22
|
def request_configuration(identifier, token)
|
23
23
|
raise ConfigurationService::Error, "error requested by test"
|
@@ -10,17 +10,14 @@ module ConfigurationService
|
|
10
10
|
module Provider
|
11
11
|
|
12
12
|
##
|
13
|
-
# A stub
|
13
|
+
# A stub configuration service provider
|
14
14
|
#
|
15
15
|
# Used to validate the test framework architecture.
|
16
16
|
#
|
17
|
-
#
|
17
|
+
# It is registered into the {ConfigurationService::ProviderRegistry} with identifier "stub".
|
18
18
|
#
|
19
19
|
class Stub
|
20
20
|
|
21
|
-
##
|
22
|
-
# Maps roles to authorization tokens
|
23
|
-
#
|
24
21
|
BUILTIN_TOKENS = {
|
25
22
|
:consumer => '64867ebd-6364-0bd3-3fda-81-requestor',
|
26
23
|
:publisher => 'f53606cb-7f3c-4432-afe8-44-publisher',
|
@@ -28,10 +25,10 @@ module ConfigurationService
|
|
28
25
|
} unless defined?(BUILTIN_TOKENS)
|
29
26
|
|
30
27
|
##
|
31
|
-
# Returns a new Stub
|
32
28
|
#
|
33
|
-
#
|
34
|
-
#
|
29
|
+
# @param [Hash] options
|
30
|
+
# @option options [String]
|
31
|
+
# :name arbitrary name, used solely for testing factory methods
|
35
32
|
#
|
36
33
|
def initialize(options = {})
|
37
34
|
@name = options[:name] or raise ArgumentError, "missing required argument: name"
|
@@ -39,16 +36,15 @@ module ConfigurationService
|
|
39
36
|
end
|
40
37
|
|
41
38
|
##
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# See Base#request_configuration.
|
39
|
+
# Request configuration
|
45
40
|
#
|
46
|
-
# Fetches configuration from the singleton StubStore.
|
41
|
+
# Fetches configuration from the singleton {ConfigurationService::StubStore}.
|
47
42
|
#
|
48
|
-
#
|
49
|
-
#
|
43
|
+
# @return [ConfigurationService::Configuration] if authorized and found
|
44
|
+
# @return [nil] if not found
|
45
|
+
# @raise [ConfigurationService::AuthorizationError] if not authorized for the +:consumer+ role
|
50
46
|
#
|
51
|
-
#
|
47
|
+
# @see ConfigurationService::Base#request_configuration
|
52
48
|
#
|
53
49
|
def request_configuration(identifier, token)
|
54
50
|
authorize_request(:consumer, token)
|
@@ -59,13 +55,14 @@ module ConfigurationService
|
|
59
55
|
end
|
60
56
|
|
61
57
|
##
|
62
|
-
#
|
58
|
+
# Publish configuration
|
63
59
|
#
|
64
|
-
#
|
60
|
+
# @param [ConfigurationService::Configuration] configuration configuration to publish
|
65
61
|
#
|
66
|
-
#
|
62
|
+
# @return [ConfigurationService::Configuration] published configuration
|
63
|
+
# @raise [ConfigurationService::Error] on failure.
|
67
64
|
#
|
68
|
-
#
|
65
|
+
# @see ConfigurationService::Base#publish_configuration
|
69
66
|
#
|
70
67
|
def publish_configuration(configuration, token)
|
71
68
|
authorize_request(:publisher, token)
|
@@ -9,45 +9,65 @@ unless defined?(ConfigurationService::Provider::StubStore)
|
|
9
9
|
##
|
10
10
|
# A singleton store for the Stub service provider
|
11
11
|
#
|
12
|
+
# @example Storing data and metadata
|
13
|
+
#
|
14
|
+
# data = {"username" => "sheldonh", "password" => "secret123"}
|
15
|
+
# metadata = {"version" => "1.0.0"}
|
16
|
+
# StubStore.instance.store("acme", data, metadata)
|
17
|
+
#
|
18
|
+
# @example Fetching data and metadata
|
19
|
+
#
|
20
|
+
# data, metadata = StubStore.instance.fetch("acme")
|
21
|
+
# # data -> {"username" => "sheldonh", "password" => "secret123"}
|
22
|
+
# # metadata -> {"version" => "1.0.0"}
|
23
|
+
#
|
24
|
+
# @!method self.instance
|
25
|
+
# The singleton registry instance
|
26
|
+
#
|
27
|
+
# @return [ConfigurationService::ProviderRegistry] singleton instance
|
28
|
+
#
|
12
29
|
class StubStore
|
13
30
|
|
14
31
|
include Singleton
|
15
32
|
|
16
|
-
def initialize # :nodoc:
|
17
|
-
@configurations = {}
|
18
|
-
end
|
19
|
-
|
20
33
|
##
|
21
|
-
#
|
34
|
+
# Fetch configuration data and metadata
|
22
35
|
#
|
23
|
-
#
|
36
|
+
# @param [String] identifier the configuration identifier
|
24
37
|
#
|
25
|
-
#
|
38
|
+
# @return [Array<Hash>] data and metadata as a tuple
|
26
39
|
#
|
27
40
|
def fetch(identifier)
|
28
41
|
@configurations.fetch(identifier)
|
29
42
|
end
|
30
43
|
|
31
44
|
##
|
32
|
-
#
|
45
|
+
# Store configuration data and metadata
|
46
|
+
#
|
47
|
+
# @param [String] identifier the configuration identifier
|
48
|
+
# @param [Hash] data the configuration data
|
49
|
+
# @param [Hash] metadata the configuration metadata
|
33
50
|
#
|
34
51
|
def store(identifier, data, metadata)
|
35
52
|
@configurations.store(identifier, [data, metadata])
|
36
53
|
end
|
37
54
|
|
38
55
|
##
|
39
|
-
#
|
56
|
+
# Delete configuration data and metadata
|
57
|
+
#
|
58
|
+
# It is not an error to delete non-existent configuration
|
40
59
|
#
|
41
|
-
#
|
60
|
+
# @param [String] identifier the configuration identifier
|
42
61
|
#
|
43
62
|
def delete(identifier)
|
44
63
|
@configurations.delete(identifier)
|
45
64
|
nil
|
46
65
|
end
|
47
66
|
|
48
|
-
|
49
|
-
|
50
|
-
|
67
|
+
# @private
|
68
|
+
def initialize
|
69
|
+
@configurations = {}
|
70
|
+
end
|
51
71
|
|
52
72
|
end
|
53
73
|
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module ConfigurationService
|
2
2
|
|
3
3
|
##
|
4
|
-
# A configuration service provider is an imperative implementation
|
5
|
-
#
|
6
|
-
# ConfigurationService::Base.
|
4
|
+
# A configuration service provider is an imperative implementation of the configuration service API,
|
5
|
+
# to be plugged into a {ConfigurationService::Base}.
|
7
6
|
#
|
8
|
-
# A Stub implementation is provided to validate the test framework architecture.
|
7
|
+
# A {ConfigurationService::Provider::Stub} implementation is provided to validate the test framework architecture.
|
9
8
|
#
|
10
9
|
module Provider
|
11
10
|
end
|