Skip to content

Commit 2f9ad80

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 2f9ad80

3 files changed

Lines changed: 875 additions & 38 deletions

File tree

assets/service_broker/data.json

Lines changed: 35 additions & 2 deletions
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,
@@ -139,6 +139,20 @@
139139
}
140140
}
141141
},
142+
"fetch_service_instance": {
143+
"default": {
144+
"sleep_seconds": 0,
145+
"status": 200,
146+
"body": {}
147+
}
148+
},
149+
"fetch_service_binding": {
150+
"default": {
151+
"sleep_seconds": 0,
152+
"status": 200,
153+
"body": {}
154+
}
155+
},
142156
"update": {
143157
"fake-async-plan-guid": {
144158
"sleep_seconds": 0,
@@ -198,9 +212,28 @@
198212
"status": 200,
199213
"body": {}
200214
}
215+
},
216+
"fetch_service_binding_last_operation": {
217+
"default": {
218+
"in_progress": {
219+
"sleep_seconds": 0,
220+
"status": 200,
221+
"body": {
222+
"state": "in progress"
223+
}
224+
},
225+
"finished": {
226+
"sleep_seconds": 0,
227+
"status": 200,
228+
"body": {
229+
"state": "succeeded"
230+
}
231+
}
232+
}
201233
}
202234
},
203235
"service_instances": {},
204236
"service_bindings": {},
205-
"max_fetch_service_instance_requests": 1
237+
"max_fetch_service_instance_requests": 1,
238+
"max_fetch_service_binding_requests": 1
206239
}

assets/service_broker/service_broker.rb

Lines changed: 131 additions & 30 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
@@ -294,32 +359,68 @@ def cf_respond_with_api_info_location(cf_api_info_location)
294359
content_type :json
295360
json_body = JSON.parse(request.body.read)
296361

297-
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])
362+
service_instance = $datasource.service_instance_by_id(instance_id)
363+
if service_instance
364+
service_binding = $datasource.create_service_binding(instance_id, binding_id, json_body)
365+
respond_with_behavior($datasource.behavior_for_type(:bind, service_binding.plan_id), params[:accepts_incomplete])
366+
else
367+
status 400
368+
log_response(status, "Broker could not find service instance by the given id #{instance_id}")
369+
end
299370
end
300371

301372
# delete service binding
302373
delete '/v2/service_instances/:instance_id/service_bindings/:id' do |instance_id, binding_id|
303374
content_type :json
304375

305-
service_binding = $datasource.delete_service_binding(binding_id)
376+
service_binding = $datasource.service_binding_by_id(binding_id)
306377
if service_binding
307-
respond_with_behavior($datasource.behavior_for_type(:unbind, service_binding['binding_data']['plan_id']), params[:accepts_incomplete])
378+
service_binding.delete!
379+
respond_with_behavior($datasource.behavior_for_type(:unbind, service_binding.plan_id), params[:accepts_incomplete])
308380
else
309381
respond_with_behavior($datasource.behavior_for_type(:unbind, nil), params[:accepts_incomplete])
310382
end
311383
end
312384

385+
# fetch service instance
313386
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))
387+
service_instance = $datasource.service_instance_by_id(instance_id)
388+
if service_instance
389+
behaviour = $datasource.behavior_for_type(:fetch_service_instance, service_instance.plan_id).clone
390+
391+
provision_data = service_instance.provision_data.clone
392+
if behaviour["body"]
393+
behaviour["body"] = provision_data.merge!(behaviour["body"])
394+
end
395+
396+
respond_with_behavior(behaviour)
397+
else # service instance does not exist
398+
status 404
399+
log_response(status, "Broker could not find service instance by the given id #{instance_id}")
400+
end
316401
end
317402

403+
# fetch service binding
318404
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)
405+
service_binding = $datasource.service_binding_by_id(binding_id)
406+
if service_binding
407+
if service_binding.instance_id == instance_id
408+
behaviour = $datasource.behavior_for_type(:fetch_service_binding, service_binding.plan_id).clone
409+
410+
binding_data = service_binding.binding_data.clone
411+
if behaviour["body"]
412+
behaviour["body"] = binding_data.merge!(behaviour["body"])
413+
end
414+
415+
respond_with_behavior(behaviour)
416+
else # service binding is not associated with the given instance_id
417+
status 404
418+
log_response(status, "Broker could not find the service binding `#{binding_id}` for service instance `#{instance_id}`")
419+
end
420+
else # service binding does not exist
421+
status 404
422+
log_response(status, "Broker could not find the service binding `#{binding_id}` for service instance `#{instance_id}`")
423+
end
323424
end
324425

325426
get '/config/all/?' do

0 commit comments

Comments
 (0)