Skip to content

Commit edee120

Browse files
committed
Enhance CATS-SB
- The behaviour for a fetch service instance can now be controlled with `fetch_service_instance` - The behaviour for a fetch service binding can now be controlled with `fetch_service_instance` - The behaviour for a fetch service instance last operation can now be controlled with `fetch_service_instance_last_operation` - The behaviour for a fetch service binding last operation can now be controlled with `fetch_service_binding_last_operation` - Improved error responses in case a service instance or service binding does not exist but the resource or its last operation is being fetched - Improved overriding the response json with configuration
1 parent e4d6058 commit edee120

3 files changed

Lines changed: 130 additions & 35 deletions

File tree

assets/service_broker/data.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
"body": {}
122122
}
123123
},
124-
"fetch": {
124+
"fetch_service_instance_last_operation": {
125125
"default": {
126126
"in_progress": {
127127
"sleep_seconds": 0,

assets/service_broker/service_broker.rb

Lines changed: 124 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,39 @@ def to_json(opts={})
5353
end
5454
end
5555

56+
class ServiceBinding
57+
attr_reader :binding_data, :instance_id, :fetch_count, :deleted
58+
59+
def initialize(opts={})
60+
@binding_data = opts.fetch(:binding_data)
61+
@instance_id = opts.fetch(:instance_id)
62+
@fetch_count = opts.fetch(:fetch_count, 0)
63+
@deleted = opts.fetch(:deleted, false)
64+
end
65+
66+
def plan_id
67+
@binding_data['plan_id']
68+
end
69+
70+
def delete!
71+
@deleted = true
72+
@fetch_count = 0
73+
self
74+
end
75+
76+
def increment_fetch_count
77+
@fetch_count += 1
78+
end
79+
80+
def to_json(opts={})
81+
{
82+
binding_data: binding_data,
83+
fetch_count: fetch_count,
84+
deleted: deleted
85+
}.to_json(opts)
86+
end
87+
end
88+
5689
class DataSource
5790
attr_reader :data
5891

@@ -64,6 +97,10 @@ def max_fetch_service_instance_requests
6497
@data['max_fetch_service_instance_requests'] || 1
6598
end
6699

100+
def max_fetch_service_binding_requests
101+
@data['max_fetch_service_binding_requests'] || 1
102+
end
103+
67104
def service_instance_by_id(cc_id)
68105
@data['service_instances'][cc_id]
69106
end
@@ -78,15 +115,23 @@ def create_service_instance(cc_id, json_data)
78115
service_instance
79116
end
80117

118+
def service_binding_by_id(cc_id)
119+
@data['service_bindings'][cc_id]
120+
end
121+
81122
def create_service_binding(instance_id, binding_id, binding_data)
82-
@data['service_instances'][binding_id] = {
83-
'binding_data' => binding_data,
84-
'instance_id' => instance_id,
85-
}
123+
service_binding = ServiceBinding.new(
124+
binding_data: binding_data,
125+
instance_id: instance_id
126+
)
127+
128+
@data['service_bindings'][binding_id] = service_binding
129+
130+
service_binding
86131
end
87132

88133
def delete_service_binding(binding_id)
89-
@data['service_instances'].delete(binding_id)
134+
@data['service_bindings'].delete(binding_id)
90135
end
91136

92137
def merge!(data)
@@ -195,7 +240,7 @@ def respond_from_config(behavior)
195240
end
196241

197242
def cf_respond_with_api_info_location(cf_api_info_location)
198-
if cf_api_info_location.empty?
243+
if cf_api_info_location.nil?
199244
status 503
200245
log_response(status, JSON.pretty_generate({
201246
error: true,
@@ -225,7 +270,7 @@ def cf_respond_with_api_info_location(cf_api_info_location)
225270
respond_with_behavior($datasource.behavior_for_type(:provision, service_instance.plan_id), params['accepts_incomplete'])
226271
end
227272

228-
# fetch service instance
273+
# fetch service instance last operation
229274
get '/v2/service_instances/:id/last_operation/?' do |id|
230275
service_instance = $datasource.service_instance_by_id(id)
231276
if service_instance
@@ -237,7 +282,7 @@ def cf_respond_with_api_info_location(cf_api_info_location)
237282
state = 'in_progress'
238283
end
239284

240-
behavior = $datasource.behavior_for_type('fetch', plan_id)[state]
285+
behavior = $datasource.behavior_for_type('fetch_service_instance_last_operation', plan_id)[state]
241286
sleep behavior['sleep_seconds']
242287
status behavior['status']
243288

@@ -246,22 +291,42 @@ def cf_respond_with_api_info_location(cf_api_info_location)
246291
else
247292
log_response(status, behavior['raw_body'])
248293
end
249-
else
250-
status 200
251-
log_response(status, {
252-
state: 'failed',
253-
description: "Broker could not find service instance by the given id #{id}",
254-
}.to_json)
294+
else # service instance does not exist
295+
status 410
296+
log_response(status, "Broker could not find service instance by the given id #{id}")
255297
end
256298
end
257299

258-
# fetch service binding
300+
# fetch service binding last operation
259301
get '/v2/service_instances/:instance_id/service_bindings/:binding_id/last_operation/?' do |instance_id, binding_id|
260-
status 200
261-
log_response(status, {
262-
state: 'succeeded',
263-
description: '100%',
264-
}.to_json)
302+
service_binding = $datasource.service_binding_by_id(binding_id)
303+
if service_binding
304+
if service_binding.instance_id == instance_id
305+
plan_id = service_binding.plan_id
306+
307+
if service_binding.increment_fetch_count > $datasource.max_fetch_service_binding_requests
308+
state = 'finished'
309+
else
310+
state = 'in_progress'
311+
end
312+
313+
behavior = $datasource.behavior_for_type('fetch_service_binding_last_operation', plan_id)[state]
314+
sleep behavior['sleep_seconds']
315+
status behavior['status']
316+
317+
if behavior['body']
318+
log_response(status, behavior['body'].to_json)
319+
else
320+
log_response(status, behavior['raw_body'])
321+
end
322+
else # service binding is not associated with the given instance_id
323+
status 410
324+
log_response(status, "Broker could not find the service binding `#{binding_id}` for service instance `#{instance_id}`")
325+
end
326+
else # service binding does not exist
327+
status 410
328+
log_response(status, "Broker could not find the service binding `#{binding_id}` for service instance `#{instance_id}`")
329+
end
265330
end
266331

267332
# update service instance
@@ -295,31 +360,61 @@ def cf_respond_with_api_info_location(cf_api_info_location)
295360
json_body = JSON.parse(request.body.read)
296361

297362
service_binding = $datasource.create_service_binding(instance_id, binding_id, json_body)
298-
respond_with_behavior($datasource.behavior_for_type(:bind, service_binding['binding_data']['plan_id']), params[:accepts_incomplete])
363+
respond_with_behavior($datasource.behavior_for_type(:bind, service_binding.plan_id), params[:accepts_incomplete])
299364
end
300365

301366
# delete service binding
302367
delete '/v2/service_instances/:instance_id/service_bindings/:id' do |instance_id, binding_id|
303368
content_type :json
304369

305-
service_binding = $datasource.delete_service_binding(binding_id)
370+
service_binding = $datasource.service_binding_by_id(binding_id)
306371
if service_binding
307-
respond_with_behavior($datasource.behavior_for_type(:unbind, service_binding['binding_data']['plan_id']), params[:accepts_incomplete])
372+
service_binding.delete!
373+
respond_with_behavior($datasource.behavior_for_type(:unbind, service_binding.plan_id), params[:accepts_incomplete])
308374
else
309375
respond_with_behavior($datasource.behavior_for_type(:unbind, nil), params[:accepts_incomplete])
310376
end
311377
end
312378

379+
# fetch service instance
313380
get '/v2/service_instances/:instance_id' do |instance_id|
314-
status 200
315-
log_response(status, JSON.pretty_generate($datasource.data['service_instances'][instance_id].provision_data))
381+
service_instance = $datasource.service_instance_by_id(instance_id)
382+
if service_instance
383+
behaviour = $datasource.behavior_for_type(:fetch_service_instance, service_instance.plan_id)
384+
385+
provision_data = service_instance.provision_data.clone
386+
if behaviour["body"]
387+
behaviour["body"] = provision_data.merge!(behaviour["body"])
388+
end
389+
390+
respond_with_behavior(behaviour)
391+
else # service instance does not exist
392+
status 404
393+
log_response(status, "Broker could not find service instance by the given id #{id}")
394+
end
316395
end
317396

397+
# fetch service binding
318398
get '/v2/service_instances/:instance_id/service_bindings/:id' do |instance_id, binding_id|
319-
binding_data = $datasource.data['service_instances'][binding_id]['binding_data']
320-
response_body = $datasource.behavior_for_type(:fetch_service_binding, binding_data['plan_id'])
321-
response_body['body'].merge!(binding_data)
322-
respond_with_behavior(response_body)
399+
service_binding = $datasource.service_binding_by_id(binding_id)
400+
if service_binding
401+
if service_binding.instance_id == instance_id
402+
behaviour = $datasource.behavior_for_type(:fetch_service_binding, service_binding.plan_id).clone
403+
404+
binding_data = service_binding.binding_data.clone
405+
if behaviour["body"]
406+
behaviour["body"] = binding_data.merge!(behaviour["body"])
407+
end
408+
409+
respond_with_behavior(behaviour)
410+
else # service binding is not associated with the given instance_id
411+
status 404
412+
log_response(status, "Broker could not find the service binding `#{binding_id}` for service instance `#{instance_id}`")
413+
end
414+
else # service binding does not exist
415+
status 404
416+
log_response(status, "Broker could not find the service binding `#{binding_id}` for service instance `#{instance_id}`")
417+
end
323418
end
324419

325420
get '/config/all/?' do

assets/service_broker/spec/service_broker_spec.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ def unbind
359359
config = {
360360
max_fetch_service_instance_requests: 1,
361361
behaviors: {
362-
fetch: {
362+
fetch_service_instance_last_operation: {
363363
default: {
364364
in_progress: {
365365
status: 200,
@@ -391,7 +391,7 @@ def unbind
391391
config = {
392392
max_fetch_service_instance_requests: 1,
393393
behaviors: {
394-
fetch: {
394+
fetch_service_instance_last_operation: {
395395
default: {
396396
in_progress: {
397397
status: 200,
@@ -423,7 +423,7 @@ def unbind
423423
config = {
424424
max_fetch_service_instance_requests: 1,
425425
behaviors: {
426-
fetch: {
426+
fetch_service_instance_last_operation: {
427427
default: {
428428
in_progress: {
429429
status: 200,
@@ -459,7 +459,7 @@ def unbind
459459
config = {
460460
max_fetch_service_instance_requests: 2,
461461
behaviors: {
462-
fetch: {
462+
fetch_service_instance_last_operation: {
463463
default: {
464464
in_progress: {
465465
status: 200,
@@ -495,7 +495,7 @@ def unbind
495495
config = {
496496
max_fetch_service_instance_requests: 1,
497497
behaviors: {
498-
fetch: {
498+
fetch_service_instance_last_operation: {
499499
'fake-plan-guid' => {
500500
in_progress: {
501501
status: 200,

0 commit comments

Comments
 (0)