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
@@ -5,44 +5,48 @@ module ConfigurationService
|
|
5
5
|
unless defined?(ProviderRegistry)
|
6
6
|
|
7
7
|
##
|
8
|
-
# A singleton registry of
|
8
|
+
# A singleton registry of configuration service providers
|
9
9
|
#
|
10
|
-
#
|
10
|
+
# @!method self.instance
|
11
|
+
# The singleton registry instance
|
12
|
+
#
|
13
|
+
# @return [ConfigurationService::ProviderRegistry] singleton instance
|
11
14
|
#
|
12
15
|
class ProviderRegistry
|
13
16
|
|
14
17
|
include Singleton
|
15
18
|
|
16
|
-
def initialize ## :nodoc:
|
17
|
-
@providers = {}
|
18
|
-
end
|
19
|
-
|
20
19
|
##
|
21
|
-
# Register a
|
20
|
+
# Register a configuration service provider
|
22
21
|
#
|
23
|
-
#
|
24
|
-
#
|
22
|
+
# @param [String] identifier
|
23
|
+
# unique identifier for the configuration service provider
|
24
|
+
# @param [Class] provider
|
25
|
+
# the configuration service provider class
|
25
26
|
#
|
26
27
|
def register(identifier, provider)
|
27
28
|
@providers[identifier] = provider
|
28
29
|
end
|
29
30
|
|
30
31
|
##
|
31
|
-
#
|
32
|
+
# Look up a configuration service provider
|
32
33
|
#
|
33
|
-
#
|
34
|
-
#
|
34
|
+
# @param [String] identifier
|
35
|
+
# the unique identifier for the configuration service provider.
|
36
|
+
# The provider must already have been registered with {#register}.
|
35
37
|
#
|
36
|
-
#
|
37
|
-
# +identifier
|
38
|
+
# @return [Class] the configuration service provider class
|
39
|
+
# @return [nil] if no provider has been registered with the given +identifier+
|
38
40
|
#
|
39
41
|
def lookup(identifier)
|
40
42
|
@providers[identifier]
|
41
43
|
end
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
# @private
|
46
|
+
def initialize
|
47
|
+
@providers = {}
|
48
|
+
end
|
49
|
+
|
46
50
|
end
|
47
51
|
|
48
52
|
end
|
@@ -6,45 +6,34 @@ module ConfigurationService
|
|
6
6
|
module Test
|
7
7
|
|
8
8
|
##
|
9
|
-
#
|
9
|
+
# @abstract
|
10
|
+
# It is a base provider for the test {ConfigurationService::Test::Orchestrator}.
|
10
11
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
12
|
+
# Extend this class if you want your test orchestration provider toconstrain your implementation's interface
|
13
|
+
# to work as a configuration service provider.
|
14
|
+
# If you have no intention of plugging your implementation into {ConfigurationService::Base},
|
15
|
+
# build your own test orchestration provider from scratch, using {ConfigurationService::Test::Orchestrator}
|
16
|
+
# and {ConfigurationService::Test::StubOrchestrationProvider} as a guide.
|
16
17
|
#
|
17
|
-
#
|
18
|
+
# Extensions should implement:
|
18
19
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
20
|
+
# * {#service_provider_id}
|
21
|
+
# * {#service_provider_configuration}
|
22
|
+
# * {#service_provider}
|
23
|
+
# * {#broken_service_provider}
|
24
|
+
# * {#token_for}
|
25
|
+
# * {#delete_configuration}
|
25
26
|
#
|
26
27
|
class OrchestrationProvider
|
27
28
|
|
28
|
-
##
|
29
|
-
# * +:requesting_configurations+
|
30
|
-
# * +:publishing_configurations+
|
31
|
-
# * +:nothing+ (if possible, provide credentials that don't allow
|
32
|
-
# operations on the configuration +identifier+)
|
33
29
|
ACTIVITY_ROLE_MAP = {
|
34
30
|
:requesting_configurations => :consumer,
|
35
31
|
:publishing_configurations => :publisher,
|
36
|
-
:nothing => :none
|
32
|
+
:nothing => :none # if possible, provide credentials that don't allow operations on the configuration identifier
|
37
33
|
} unless defined?(ACTIVITY_ROLE_MAP)
|
38
|
-
##
|
39
|
-
# * +:consumer+
|
40
|
-
# * +:publisher+
|
41
|
-
# * +:none+
|
42
|
-
#
|
43
34
|
ROLES = ACTIVITY_ROLE_MAP.values unless defined?(ROLES)
|
44
35
|
|
45
36
|
##
|
46
|
-
# Returns a new Orchestrator provider
|
47
|
-
#
|
48
37
|
# The provider is always initialized with the same configuration +identifier+
|
49
38
|
#
|
50
39
|
def initialize
|
@@ -52,48 +41,98 @@ module ConfigurationService
|
|
52
41
|
end
|
53
42
|
|
54
43
|
##
|
55
|
-
#
|
44
|
+
# The registered identifier of the service provider under test
|
56
45
|
#
|
57
|
-
#
|
58
|
-
#
|
46
|
+
# @return [String] the +identifier+ with which the service provider is registered
|
47
|
+
# into the {ConfigurationService::ProviderRegistry}
|
59
48
|
#
|
60
49
|
def service_provider_id
|
61
50
|
raise NotImplementedError, "#{self.class} must implement service_provider_id"
|
62
51
|
end
|
63
52
|
|
64
53
|
##
|
65
|
-
#
|
54
|
+
# The configuration for the service provider under test
|
66
55
|
#
|
67
|
-
#
|
68
|
-
# be passed to the constructor of the service provider class.
|
56
|
+
# @return [Hash] dictionary of keyword arguments that can be passed to the constructor of the service provider class
|
69
57
|
#
|
70
|
-
def service_provider_configuration
|
58
|
+
def service_provider_configuration
|
71
59
|
raise NotImplementedError, "#{self.class} must implement service_provider_configuration"
|
72
60
|
end
|
73
61
|
|
74
62
|
##
|
75
|
-
#
|
63
|
+
# The service provider under test
|
64
|
+
#
|
65
|
+
# @return [Object] a provider to be plugged into {ConfigurationService::Base}
|
66
|
+
#
|
67
|
+
def service_provider
|
68
|
+
raise NotImplementedError, "#{self.class} must implement service_provider"
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# A broken service provider
|
73
|
+
#
|
74
|
+
# @return [Object] a provider to be plugged into {ConfigurationService::Base}.
|
75
|
+
# The service provider's +publish_configuration+ and +request_configuration+ methods
|
76
|
+
# must raise an {ConfigurationService::Error} other than {ConfigurationService::AuthorizationError}.
|
77
|
+
#
|
78
|
+
def broken_service_provider
|
79
|
+
raise NotImplementedError, "#{self.class} must implement broken_service_provider"
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Delete configuration data
|
84
|
+
#
|
85
|
+
# Deleting non-existent configuration should not produce an error.
|
86
|
+
# The +@identifier+ instance variable may be used to identify the configuration to delete,
|
87
|
+
# but +@token+ should not be used, because it may not be sufficiently authorized.
|
88
|
+
#
|
89
|
+
# @return [nil] always
|
90
|
+
#
|
91
|
+
def delete_configuration
|
92
|
+
raise NotImplementedError, "#{self.class} must implement delete_configuration"
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Provide a token that authorizes a role
|
97
|
+
#
|
98
|
+
# Valid roles are:
|
99
|
+
#
|
100
|
+
# * +:consumer+
|
101
|
+
# * +:publisher+
|
102
|
+
# * +:nothing+
|
103
|
+
#
|
104
|
+
# Note that a token should be returned for +:nothing+, but the token should
|
105
|
+
# not be authorized to consume or publish to the +identifier+.
|
106
|
+
#
|
107
|
+
# @return [String] a token
|
108
|
+
#
|
109
|
+
def token_for(role)
|
110
|
+
raise NotImplementedError, "#{self.class} must implement token_for(role)"
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# @see ConfigurationService::Test::Orchestrator#authorize
|
76
115
|
#
|
77
116
|
def authorize(role)
|
78
117
|
@token = token_for(role)
|
79
118
|
end
|
80
119
|
|
81
120
|
##
|
82
|
-
#
|
121
|
+
# @see ConfigurationService::Test::Orchestrator#deauthorize
|
83
122
|
#
|
84
123
|
def deauthorize
|
85
124
|
@token = nil
|
86
125
|
end
|
87
126
|
|
88
127
|
##
|
89
|
-
#
|
128
|
+
# @see ConfigurationService::Test::Orchestrator#given_metadata
|
90
129
|
#
|
91
130
|
def given_metadata
|
92
131
|
@metadata = {"version" => "1.0"}
|
93
132
|
end
|
94
133
|
|
95
134
|
##
|
96
|
-
#
|
135
|
+
# @see ConfigurationService::Test::Orchestrator#given_existing_configuration
|
97
136
|
#
|
98
137
|
def given_existing_configuration
|
99
138
|
authorized_as(:publisher) do
|
@@ -102,14 +141,14 @@ module ConfigurationService
|
|
102
141
|
end
|
103
142
|
|
104
143
|
##
|
105
|
-
#
|
144
|
+
# @see ConfigurationService::Test::Orchestrator#given_invalid_configuration
|
106
145
|
#
|
107
146
|
def given_invalid_configuration
|
108
147
|
@configuration = "This should be an object!"
|
109
148
|
end
|
110
149
|
|
111
150
|
##
|
112
|
-
#
|
151
|
+
# @see ConfigurationService::Test::Orchestrator#given_missing_configuration
|
113
152
|
#
|
114
153
|
def given_missing_configuration
|
115
154
|
authorized_as(:publisher) do
|
@@ -119,23 +158,30 @@ module ConfigurationService
|
|
119
158
|
end
|
120
159
|
|
121
160
|
##
|
122
|
-
#
|
161
|
+
# @see ConfigurationService::Test::Orchestrator#existing_configuration
|
123
162
|
#
|
124
163
|
def existing_configuration
|
125
164
|
@existing_configuration.data
|
126
165
|
end
|
127
166
|
|
128
167
|
##
|
129
|
-
#
|
168
|
+
# @see ConfigurationService::Test::Orchestrator#existing_revision
|
130
169
|
#
|
131
170
|
def existing_revision
|
132
171
|
@existing_configuration.revision
|
133
172
|
end
|
134
173
|
|
135
174
|
##
|
136
|
-
#
|
175
|
+
# Request configuration
|
176
|
+
#
|
177
|
+
# Request configuration from the configuration service.
|
178
|
+
# This exercises the configuration service provider under test through the configuration service API.
|
179
|
+
#
|
180
|
+
# The response from the service is wrapped in a test {ConfigurationService::Test::response}.
|
181
|
+
#
|
182
|
+
# @return [ConfigurationService::Test::Response]
|
137
183
|
#
|
138
|
-
#
|
184
|
+
# @see ConfigurationService::Base#request_configuration
|
139
185
|
#
|
140
186
|
def request_configuration
|
141
187
|
wrap_response do
|
@@ -144,9 +190,16 @@ module ConfigurationService
|
|
144
190
|
end
|
145
191
|
|
146
192
|
##
|
147
|
-
#
|
193
|
+
# Publish configuration
|
148
194
|
#
|
149
|
-
#
|
195
|
+
# Publish configuration through the configuration service.
|
196
|
+
# This exercises the configuration service provider under test through the configuration service API.
|
197
|
+
#
|
198
|
+
# The response from the service is wrapped in a test {ConfigurationService::Test::response}.
|
199
|
+
#
|
200
|
+
# @return [ConfigurationService::Test::Response]
|
201
|
+
#
|
202
|
+
# @see ConfigurationService::Base#publish_configuration
|
150
203
|
#
|
151
204
|
def publish_configuration
|
152
205
|
wrap_response do
|
@@ -159,73 +212,30 @@ module ConfigurationService
|
|
159
212
|
end
|
160
213
|
|
161
214
|
##
|
162
|
-
# Arrange for the next
|
215
|
+
# Arrange for the next publish or request operation to fail
|
216
|
+
#
|
217
|
+
# This is done by using a {#broken_service_provider} to service the next operation.
|
163
218
|
#
|
164
|
-
#
|
165
|
-
# next operation.
|
219
|
+
# @return [nil]
|
166
220
|
#
|
167
221
|
def fail_next_request
|
168
222
|
@fail_next = true
|
169
223
|
end
|
170
224
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
##
|
183
|
-
# Return a broken ConfigurationService::Base provider
|
184
|
-
#
|
185
|
-
# The provider's #publish_configuration and #request_configuration
|
186
|
-
# methods must raise an Error other than AuthorizationError.
|
187
|
-
#
|
188
|
-
def broken_service_provider # :doc:
|
189
|
-
raise NotImplementedError, "#{self.class} must implement broken_service_provider"
|
190
|
-
end
|
191
|
-
|
192
|
-
##
|
193
|
-
# Delete the configuration identified by the consistent +identifier+
|
194
|
-
#
|
195
|
-
# Deleting non-existent configuration should not produce an error.
|
196
|
-
#
|
197
|
-
def delete_configuration # :doc:
|
198
|
-
raise NotImplementedError, "#{self.class} must implement delete_configuration"
|
199
|
-
end
|
200
|
-
|
201
|
-
##
|
202
|
-
# Return a token that authorizes +role+
|
203
|
-
#
|
204
|
-
# Valid roles are:
|
205
|
-
#
|
206
|
-
# * +:consumer+
|
207
|
-
# * +:publisher+
|
208
|
-
# * +:nothing+
|
209
|
-
#
|
210
|
-
# Note that a token should be returned for +:nothing+, but the token should
|
211
|
-
# not be authorized to consume or publish to the +identifier+.
|
212
|
-
#
|
213
|
-
def token_for(role) # :doc:
|
214
|
-
raise NotImplementedError, "#{self.class} must implement token_for(role)"
|
225
|
+
##
|
226
|
+
# Mark a cucumber step as pending
|
227
|
+
#
|
228
|
+
# @raise [Cucumber::Pending] always
|
229
|
+
#
|
230
|
+
def pending(message = nil)
|
231
|
+
if message
|
232
|
+
raise Cucumber::Pending, message
|
233
|
+
else
|
234
|
+
raise Cucumber::Pending
|
215
235
|
end
|
236
|
+
end
|
216
237
|
|
217
|
-
|
218
|
-
# Raise a Cucumber::Pending exception
|
219
|
-
#
|
220
|
-
# This allows incomplete implementations to mark features as pending
|
221
|
-
#
|
222
|
-
def pending(message = nil) # :doc:
|
223
|
-
if message
|
224
|
-
raise Cucumber::Pending, message
|
225
|
-
else
|
226
|
-
raise Cucumber::Pending
|
227
|
-
end
|
228
|
-
end
|
238
|
+
private
|
229
239
|
|
230
240
|
def configuration
|
231
241
|
@configuration ||= {"verbose" => true}
|
@@ -8,40 +8,46 @@ module ConfigurationService
|
|
8
8
|
unless defined?(OrchestrationProviderRegistry)
|
9
9
|
|
10
10
|
##
|
11
|
-
# Singleton registry of
|
11
|
+
# Singleton registry of test orchestration providers
|
12
|
+
#
|
13
|
+
# @!method self.instance
|
14
|
+
# The singleton registry instance
|
15
|
+
#
|
16
|
+
# @return [ConfigurationService::Test::OrchestrationProviderRegistry] singleton instance
|
12
17
|
#
|
13
18
|
class OrchestrationProviderRegistry
|
14
19
|
include Singleton
|
15
20
|
|
16
|
-
def initialize ## :nodoc:
|
17
|
-
@providers = {}
|
18
|
-
end
|
19
|
-
|
20
21
|
##
|
21
|
-
# Register a
|
22
|
+
# Register a test orchestration provider
|
22
23
|
#
|
23
|
-
#
|
24
|
+
# @param [String] identifier
|
25
|
+
# unique identifier for the test orchestration provider
|
26
|
+
# @param [Class] provider
|
27
|
+
# the test orchestration provider class (which should have a default/nullary constructor)
|
24
28
|
#
|
25
29
|
def register(identifier, provider)
|
26
30
|
@providers[identifier] = provider
|
27
31
|
end
|
28
32
|
|
29
33
|
##
|
30
|
-
#
|
34
|
+
# Look up a test orchestration provider
|
31
35
|
#
|
32
|
-
#
|
33
|
-
#
|
36
|
+
# @param [String] identifier
|
37
|
+
# the unique identifier for the test orchestration provider.
|
38
|
+
# The provider must already have been registered with {#register}.
|
34
39
|
#
|
35
|
-
#
|
36
|
-
# +identifier
|
40
|
+
# @return [Class] the test orchestration provider class
|
41
|
+
# @return [nil] if no provider has been registered with the given +identifier+
|
37
42
|
#
|
38
43
|
def lookup(identifier)
|
39
44
|
@providers[identifier]
|
40
45
|
end
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
47
|
+
# @private
|
48
|
+
def initialize
|
49
|
+
@providers = {}
|
50
|
+
end
|
45
51
|
|
46
52
|
end
|
47
53
|
|