configuration_service 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c1d020e9ee176a21a78ca58785734d98ebda535
4
- data.tar.gz: 5401e260c0d0a9da6ca31029b847b49fdaa8e6c7
3
+ metadata.gz: 013e070f4e04c050a8fdd8232cac7fb22cb652b1
4
+ data.tar.gz: 3d329fe8548014c9e43e1553a1e506d5438c6a7f
5
5
  SHA512:
6
- metadata.gz: 842390201eb9dc49e9fc37c7a9f9913a6f08ea28fc710000ae220245d53f7503f27a9b2df3446cc74b54acc68492b889159b7485d2282fdf0a42ca22e738262f
7
- data.tar.gz: cc8bdbf31cbaed9751562d69295a521ac0c089c65c3da176fb2b74a521d7e08221c58ad61954c4d00a33f10a7682b855259ed80fb1a2f63613404d6c1db5312b
6
+ metadata.gz: 226d8f3472c3a62716ced933186f5f926388575f29ab8ce91527d8b6ef19d5f9080409519dd8ecf37e405854705c17f7942ad6f994d8d4c76690866cc3438be9
7
+ data.tar.gz: df846414184710ca2d20903e017f1712897e4df8c97dc569f3296eb8bf1ce5a5224586ed531dc8e00985822f42e4405020b89232e54e9b59ba2171ba8f3f2754
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "configuration_service"
7
- spec.version = "0.0.1"
7
+ spec.version = "1.0.0"
8
8
  spec.authors = ["Sheldon Hearn"]
9
9
  spec.email = ["sheldonh@starjuice.net"]
10
10
 
@@ -12,32 +12,44 @@ module ConfigurationService
12
12
  class Base
13
13
 
14
14
  ##
15
- # Creates a new API instance for the +provider+
15
+ # Creates a new API instance for the service +provider+
16
16
  #
17
- def initialize(provider)
17
+ # The +identifier+ is a string that uniquely identifies some configuration data and associated metadata.
18
+ # It might be the name of a service or service component. It might include an environment label (e.g.
19
+ # production, staging, etc.) For example:
20
+ #
21
+ # * billing.acme.com
22
+ # * billing-web1.acme.com
23
+ # * billing/production/web1
24
+ #
25
+ # The +token+ is a string that authorizes the client to access the configuration data and associated metadata.
26
+ # Interpretation of the +token+ is provider-dependent; it is opaque to the API and client.
27
+ #
28
+ # The +provider+ is a configured service provider instance.
29
+ #
30
+ def initialize(identifier, token, provider)
31
+ @identifier = identifier
32
+ @token = token
18
33
  @provider = provider
19
34
  end
20
35
 
21
36
  ##
22
- # Requests configuration data and metadata
37
+ # Requests the configuration data and metadata for the +identifier+
23
38
  #
24
- # Delegates the request to the provider. An optional +metadata_filter+
25
- # may be supplied to restrict access to, for example, a specific revision
26
- # of the configuration.
39
+ # Delegates the request to the provider.
27
40
  #
28
41
  # Returns a Configuration object or raises an Error on failure.
29
42
  # Returns +nil+ if no matching configuration was found.
30
43
  #
31
- def request_configuration(metadata_filter = {})
32
- @provider.request_configuration(metadata_filter)
44
+ def request_configuration
45
+ @provider.request_configuration(@identifier, @token)
33
46
  end
34
47
 
35
48
  ##
36
49
  # Publishes configuration +data+ and optional +metadata+
37
50
  #
38
- # Delegates the publication to the provider. The +data+ and the +metadata+ (if specified)
39
- # must be dictionaries (responding to #to_hash or #to_h). The provider receives a
40
- # copy of the +metadata+ decorated with the following keys:
51
+ # The +data+ and the +metadata+ (if specified) must be dictionaries (responding to #to_hash or #to_h).
52
+ # The provider receives a a Configuration object, whose +metadata+ is decorated with the following keys:
41
53
  #
42
54
  # * "timestamp" - the current UTC time in ISO8601 format
43
55
  # * "revision" - a UUID for this publication
@@ -50,19 +62,9 @@ module ConfigurationService
50
62
  dictionary?(data) or raise ConfigurationService::Error, "data must be a dictionary"
51
63
  dictionary?(metadata) or raise ConfigurationService::Error, "metadata must be a dictionary"
52
64
 
53
- @provider.publish_configuration(data, decorate(metadata))
54
- end
55
-
56
- ##
57
- # True if the +metadata+ matches the +metadata_filter+
58
- #
59
- # The +metadata+ matches the +metadata_filter+ if every key in the +metadata_filter+
60
- # is present in the +metadata+, and the values of both keys are equal (==).
61
- #
62
- # This is a utility method intended for use by providers.
63
- #
64
- def self.metadata_matches_filter?(metadata, metadata_filter)
65
- metadata_filter.all? { |k, v| v == metadata[k] }
65
+ metadata = decorate(metadata)
66
+ configuration = Configuration.new(@identifier, data, metadata)
67
+ @provider.publish_configuration(configuration, @token)
66
68
  end
67
69
 
68
70
  private
@@ -3,6 +3,7 @@ module ConfigurationService
3
3
  ##
4
4
  # Encapsulates configuration +data+ and its +metadata+
5
5
  #
6
+ # * +identifier is the string identifier of the data and metadata.
6
7
  # * +data+ is a dictionary of (possibly sensitive) configuration data,
7
8
  # which providers are expected to secure.
8
9
  # * +metadata+ is a dictionary of data about the configuration data,
@@ -13,12 +14,14 @@ module ConfigurationService
13
14
  #
14
15
  class Configuration
15
16
 
16
- attr_reader :data, :metadata, :revision # :nodoc:
17
+ # TODO consider removing :revision as an attr
18
+ attr_reader :identifier, :data, :metadata, :revision # :nodoc:
17
19
 
18
20
  ##
19
21
  # Returns a new Configuration
20
22
  #
21
- def initialize(data, metadata)
23
+ def initialize(identifier, data, metadata)
24
+ @identifier = identifier
22
25
  @data = data
23
26
  @metadata = metadata
24
27
  @revision = metadata["revision"]
@@ -12,14 +12,14 @@ module ConfigurationService
12
12
  ##
13
13
  # Raises Error
14
14
  #
15
- def publish_configuration(data, metadata)
15
+ def publish_configuration(configuration, token)
16
16
  raise ConfigurationService::Error, "error requested by test"
17
17
  end
18
18
 
19
19
  ##
20
20
  # Raises Error
21
21
  #
22
- def request_configuration(metadata_filter = {})
22
+ def request_configuration(identifier, token)
23
23
  raise ConfigurationService::Error, "error requested by test"
24
24
  end
25
25
 
@@ -3,7 +3,6 @@ require "securerandom"
3
3
 
4
4
  require "configuration_service"
5
5
 
6
- require_relative "broken"
7
6
  require_relative "stub_store"
8
7
 
9
8
  module ConfigurationService
@@ -29,12 +28,7 @@ module ConfigurationService
29
28
  ##
30
29
  # Returns a new Stub
31
30
  #
32
- # The object is initialized with a configuration +identifier+ and an
33
- # authorization +token+ and holds a reference to the singleton StubStore.
34
- #
35
- def initialize(identifier, token)
36
- @identifier = identifier
37
- @token = token
31
+ def initialize
38
32
  @configurations = StubStore.instance
39
33
  end
40
34
 
@@ -43,50 +37,41 @@ module ConfigurationService
43
37
  #
44
38
  # See Base#request_configuration.
45
39
  #
46
- # The configured +identifier+ is used to fetch the data from the StubStore.
47
- #
48
- # An optional +metadata_filter+ may be supplied to restrict access to, for
49
- # example, a specific revision of the configuration.
40
+ # Fetches configuration from the singleton StubStore.
50
41
  #
51
42
  # Returns a Configuration object or raises AuthorizationError if the
52
- # configured +token+ is not for the +:consumer+ role.
53
- # Returns +nil+ if no matching configuration was found.
43
+ # +token+ is not for the +:consumer+ role.
54
44
  #
55
- def request_configuration(metadata_filter)
56
- authorize_request(:consumer)
57
- data, metadata = @configurations.fetch(@identifier)
58
- if Base.metadata_matches_filter?(metadata, metadata_filter)
59
- Configuration.new(data, metadata)
60
- end
45
+ # Returns +nil+ if no configuration was found for the +identifier+.
46
+ #
47
+ def request_configuration(identifier, token)
48
+ authorize_request(:consumer, token)
49
+ data, metadata = @configurations.fetch(identifier)
50
+ Configuration.new(identifier, data, metadata)
61
51
  rescue KeyError
62
52
  nil
63
53
  end
64
54
 
65
55
  ##
66
- # Publishes configuration +data+ and optional +metadata+
56
+ # Publishes configuration
67
57
  #
68
58
  # See Base#publish_configuration.
69
59
  #
70
- # The +data+ and the +metadata+ (if specified) must be dictionaries
71
- # (responding to #to_hash or #to_h). The provider receives a copy of the
72
- # +metadata+ decorated with the following keys:
73
- #
74
- # * "timestamp" - the current UTC time in ISO8601 format
75
- # * "revision" - a UUID for this publication
60
+ # +configuration+ should be a Configuration object or similar.
76
61
  #
77
62
  # Returns a Configuration object or raises an Error on failure.
78
63
  #
79
- def publish_configuration(data, metadata)
80
- authorize_request(:publisher)
81
- @configurations.store(@identifier, data, metadata)
82
- Configuration.new(data, metadata)
64
+ def publish_configuration(configuration, token)
65
+ authorize_request(:publisher, token)
66
+ @configurations.store(configuration.identifier, configuration.data, configuration.metadata)
67
+ configuration
83
68
  end
84
69
 
85
70
  private
86
71
 
87
- def authorize_request(role)
88
- raise AuthorizationError.new("missing token") unless @token
89
- raise AuthorizationError.new("authorization failed") unless @token == BUILTIN_TOKENS[role]
72
+ def authorize_request(role, token)
73
+ raise AuthorizationError.new("missing token") unless token
74
+ raise AuthorizationError.new("authorization failed") unless token == BUILTIN_TOKENS[role]
90
75
  end
91
76
 
92
77
  end
@@ -1,3 +1,4 @@
1
+ require 'cucumber/errors'
1
2
  require 'configuration_service'
2
3
 
3
4
  module ConfigurationService
@@ -65,13 +66,6 @@ module ConfigurationService
65
66
  @metadata = {"version" => "1.0"}
66
67
  end
67
68
 
68
- ##
69
- # See Orchestrator#given_metadata_filter
70
- #
71
- def given_metadata_filter
72
- @metadata_filter = {"revision" => "d4d40eab-cf66-4af5-9a77-d956a11682de"}
73
- end
74
-
75
69
  ##
76
70
  # See Orchestrator#given_existing_configuration
77
71
  #
@@ -98,22 +92,6 @@ module ConfigurationService
98
92
  end
99
93
  end
100
94
 
101
- ##
102
- # See Orchestrator#given_existing_configuration_matching_metadata_filter
103
- #
104
- def given_existing_configuration_matching_metadata_filter
105
- @metadata_matching_filter = (@metadata || {}).merge(@metadata_filter)
106
- given_existing_configuration
107
- end
108
-
109
- ##
110
- # See Orchestrator#given_existing_configuration_not_matching_metadata_filter
111
- #
112
- def given_existing_configuration_not_matching_metadata_filter
113
- @metadata_matching_filter = {}
114
- given_existing_configuration
115
- end
116
-
117
95
  ##
118
96
  # See Orchestrator#existing_configuration
119
97
  #
@@ -135,11 +113,7 @@ module ConfigurationService
135
113
  #
136
114
  def request_configuration
137
115
  wrap_response do
138
- if @metadata_filter
139
- service.request_configuration(@metadata_filter)
140
- else
141
- service.request_configuration
142
- end
116
+ service.request_configuration
143
117
  end
144
118
  end
145
119
 
@@ -152,8 +126,6 @@ module ConfigurationService
152
126
  wrap_response do
153
127
  if @metadata
154
128
  service.publish_configuration(configuration, @metadata)
155
- elsif @metadata_matching_filter
156
- service.publish_configuration(configuration, @metadata_matching_filter)
157
129
  else
158
130
  service.publish_configuration(configuration)
159
131
  end
@@ -216,17 +188,31 @@ module ConfigurationService
216
188
  raise NotImplementedError, "#{self.class} must implement token_for(role)"
217
189
  end
218
190
 
191
+ ##
192
+ # Raise a Cucumber::Pending exception
193
+ #
194
+ # This allows incomplete implementations to mark features as pending
195
+ #
196
+ def pending(message = nil) # :doc:
197
+ if message
198
+ raise Cucumber::Pending, message
199
+ else
200
+ raise Cucumber::Pending
201
+ end
202
+ end
203
+
219
204
  def configuration
220
205
  @configuration ||= {"verbose" => true}
221
206
  end
222
207
 
223
208
  def service
224
- if @fail_next
225
- @fail_next = false
226
- ConfigurationService.new(broken_service_provider)
227
- else
228
- ConfigurationService.new(service_provider)
229
- end
209
+ provider = if @fail_next
210
+ @fail_next = false
211
+ broken_service_provider
212
+ else
213
+ service_provider
214
+ end
215
+ ConfigurationService.new(@identifier, @token, provider)
230
216
  end
231
217
 
232
218
  def authorized_as(role)
@@ -29,7 +29,7 @@ module ConfigurationService
29
29
  ##
30
30
  # Return the +provider+ identified by the string +identifier+
31
31
  #
32
- # The +provider must already have been registered with #register,
32
+ # The +provider+ must already have been registered with #register,
33
33
  # and should be a class with a default (nullary) constructor.
34
34
  #
35
35
  # Returns +nil+ if no provider has been registered with the given
@@ -44,13 +44,6 @@ module ConfigurationService
44
44
  @provider.given_metadata
45
45
  end
46
46
 
47
- ##
48
- # Include a metadata filter in the next consuming operation
49
- #
50
- def given_metadata_filter
51
- @provider.given_metadata_filter
52
- end
53
-
54
47
  ##
55
48
  # Arrange a published configuration fixture
56
49
  def given_existing_configuration
@@ -71,24 +64,6 @@ module ConfigurationService
71
64
  @provider.given_missing_configuration
72
65
  end
73
66
 
74
- ##
75
- # Arrange a published configuration fixture
76
- #
77
- # Use a metadata filter that matches the fixture's metadata in the next consuming operation.
78
- #
79
- def given_existing_configuration_matching_metadata_filter
80
- @provider.given_existing_configuration_matching_metadata_filter
81
- end
82
-
83
- ##
84
- # Arrange a published configuration fixture
85
- #
86
- # Use a metadata filter that does not match the fixture's metadata in the next consuming operation.
87
- #
88
- def given_existing_configuration_not_matching_metadata_filter
89
- @provider.given_existing_configuration_not_matching_metadata_filter
90
- end
91
-
92
67
  ##
93
68
  # Return a published configuration fixture
94
69
  #
@@ -1,3 +1,4 @@
1
+ require "configuration_service/provider/broken"
1
2
  require "configuration_service/provider/stub"
2
3
  require "configuration_service/test"
3
4
 
@@ -17,11 +18,8 @@ module ConfigurationService
17
18
  ##
18
19
  # Returns a new Stub
19
20
  #
20
- # The object is initialized with the currently #authorize'd +token+
21
- # and consistently used configuration +identifier+.
22
- #
23
21
  def service_provider # :doc:
24
- ConfigurationService::Provider::Stub.new(@identifier, @token)
22
+ ConfigurationService::Provider::Stub.new
25
23
  end
26
24
 
27
25
  ##
@@ -10,8 +10,10 @@ module ConfigurationService
10
10
  ##
11
11
  # Creates a new ConfigurationService::Base for the +provider+
12
12
  #
13
- def self.new(provider)
14
- ConfigurationService::Base.new(provider)
13
+ # See ConfigurationService::Base#initialize.
14
+ #
15
+ def self.new(identifier, token, provider)
16
+ ConfigurationService::Base.new(identifier, token, provider)
15
17
  end
16
18
 
17
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configuration_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sheldon Hearn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-08-12 00:00:00.000000000 Z
11
+ date: 2015-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -119,3 +119,4 @@ signing_key:
119
119
  specification_version: 4
120
120
  summary: Configuration service
121
121
  test_files: []
122
+ has_rdoc: