configuration_service 0.0.1 → 1.0.0

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 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: