configuration_service 2.0.4 → 2.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|