Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit 84758b0

Browse files
author
Harsha Nandiwada
committed
2 parents 5ca3e89 + 5334533 commit 84758b0

11 files changed

Lines changed: 178 additions & 58 deletions

app/actions/service_route_binding_create.rb

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'services/service_brokers/service_client_provider'
2+
13
module VCAP::CloudController
24
module V3
35
class ServiceRouteBindingCreate
@@ -6,12 +8,7 @@ def initialize(service_event_repository)
68
end
79

810
def precursor(service_instance, route)
9-
not_supported! unless service_instance.route_service?
10-
not_bindable! unless service_instance.bindable?
11-
route_is_internal! if route.try(:internal?)
12-
space_mismatch! unless route.space == service_instance.space
13-
already_exists! if route.service_instance == service_instance
14-
already_bound! if route.service_instance
11+
validate!(service_instance, route)
1512

1613
RouteBinding.new.save_with_new_operation(
1714
{
@@ -98,6 +95,16 @@ class BindingNotRetrievable < StandardError; end
9895

9996
private
10097

98+
def validate!(service_instance, route)
99+
not_supported! unless service_instance.route_service?
100+
not_bindable! unless service_instance.bindable?
101+
route_is_internal! if route.try(:internal?)
102+
space_mismatch! unless route.space == service_instance.space
103+
already_exists! if route.service_instance == service_instance
104+
already_bound! if route.service_instance
105+
operation_in_progress! if service_instance.operation_in_progress?
106+
end
107+
101108
attr_reader :service_event_repository
102109

103110
def fetch_last_operation(client, binding)
@@ -154,6 +161,10 @@ def bindings_retrievable?(binding)
154161
binding.service_instance.service.bindings_retrievable
155162
end
156163

164+
def operation_in_progress!
165+
raise UnprocessableCreate.new('There is an operation in progress for the service instance')
166+
end
167+
157168
def route_is_internal!
158169
raise UnprocessableCreate.new('Route services cannot be bound to internal routes')
159170
end

app/models/services/route_binding.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'cloud_controller/process_route_handler'
2+
13
module VCAP::CloudController
24
class RouteBinding < Sequel::Model
35
plugin :after_initialize
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module VCAP::CloudController::Presenters::Mixins
2+
module LastOperationHelper
3+
def last_operation(resource)
4+
last_operation = resource.try(:last_operation)
5+
6+
if last_operation
7+
last_operation.to_hash
8+
else
9+
# Bindings created using V2 may not have a last operation, so we make
10+
# a best attempt so that the output JSON can be parsed consistently
11+
{
12+
type: 'create',
13+
state: 'succeeded',
14+
description: '',
15+
created_at: resource.try(:created_at),
16+
updated_at: resource.try(:updated_at),
17+
}
18+
end
19+
end
20+
end
21+
end

app/presenters/v3/service_credential_binding_presenter.rb

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,40 @@
11
require_relative 'base_presenter'
2+
require 'presenters/mixins/last_operation_helper'
23

34
module VCAP
45
module CloudController
56
module Presenters
67
module V3
78
class ServiceCredentialBindingPresenter < BasePresenter
9+
include VCAP::CloudController::Presenters::Mixins::LastOperationHelper
10+
811
def to_hash
912
base_hash.merge(extra).merge(decorations)
1013
end
1114

1215
private
1316

17+
def binding
18+
@resource
19+
end
20+
1421
def base_hash
1522
{
16-
guid: @resource.guid,
17-
created_at: @resource.created_at,
18-
updated_at: @resource.updated_at,
19-
name: @resource.name,
20-
type: type
23+
guid: binding.guid,
24+
created_at: binding.created_at,
25+
updated_at: binding.updated_at,
26+
name: binding.name,
27+
type: type,
28+
last_operation: last_operation(binding),
2129
}
2230
end
2331

2432
def decorations
25-
@decorators.reduce({}) { |memo, d| d.decorate(memo, [@resource]) }
33+
@decorators.reduce({}) { |memo, d| d.decorate(memo, [binding]) }
2634
end
2735

2836
def type
29-
case @resource
37+
case binding
3038
when VCAP::CloudController::ServiceKey
3139
'key'
3240
when VCAP::CloudController::ServiceBinding
@@ -38,65 +46,49 @@ def extra
3846
case type
3947
when 'app'
4048
{
41-
last_operation: last_operation,
4249
relationships: base_relationships.merge(app_relationship),
4350
links: base_links.merge(app_link)
4451
}
4552
when 'key'
4653
{
47-
last_operation: nil,
4854
relationships: base_relationships,
4955
links: base_links
5056
}
5157
end
5258
end
5359

54-
def last_operation
55-
return nil if @resource.last_operation.blank?
56-
57-
last_operation = @resource.last_operation
58-
59-
{
60-
type: last_operation.type,
61-
state: last_operation.state,
62-
description: last_operation.description,
63-
created_at: last_operation.created_at,
64-
updated_at: last_operation.updated_at
65-
}
66-
end
67-
6860
def base_links
69-
parameters = { parameters: "#{path_to_self}/parameters" } unless @resource.service_instance.user_provided_instance?
61+
parameters = { parameters: "#{path_to_self}/parameters" } unless binding.service_instance.user_provided_instance?
7062

7163
{
7264
self: path_to_self,
7365
details: "#{path_to_self}/details",
74-
service_instance: "/v3/service_instances/#{@resource.service_instance_guid}"
66+
service_instance: "/v3/service_instances/#{binding.service_instance_guid}"
7567
}.merge(parameters || {}).transform_values do |path|
7668
hrefify(path)
7769
end
7870
end
7971

8072
def path_to_self
81-
"/v3/service_credential_bindings/#{@resource.guid}"
73+
"/v3/service_credential_bindings/#{binding.guid}"
8274
end
8375

8476
def base_relationships
8577
{
86-
service_instance: { data: { guid: @resource.service_instance_guid } }
78+
service_instance: { data: { guid: binding.service_instance_guid } }
8779
}
8880
end
8981

9082
def app_relationship
91-
return {} if @resource.app_guid.blank?
83+
return {} if binding.app_guid.blank?
9284

93-
{ app: { data: { guid: @resource.app_guid } } }
85+
{ app: { data: { guid: binding.app_guid } } }
9486
end
9587

9688
def app_link
97-
return {} if @resource.app_guid.blank?
89+
return {} if binding.app_guid.blank?
9890

99-
{ app: hrefify("/v3/apps/#{@resource.app_guid}") }
91+
{ app: hrefify("/v3/apps/#{binding.app_guid}") }
10092
end
10193

10294
def hrefify(path)

app/presenters/v3/service_route_binding_presenter.rb

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
require_relative 'base_presenter'
2+
require 'presenters/mixins/last_operation_helper'
23

34
module VCAP
45
module CloudController
56
module Presenters
67
module V3
78
class ServiceRouteBindingPresenter < BasePresenter
9+
include VCAP::CloudController::Presenters::Mixins::LastOperationHelper
10+
811
def to_hash
912
base.merge(decorations)
1013
end
@@ -17,7 +20,7 @@ def base
1720
route_service_url: binding.route_service_url,
1821
created_at: binding.created_at,
1922
updated_at: binding.updated_at,
20-
last_operation: last_operation,
23+
last_operation: last_operation(binding),
2124
relationships: relationships,
2225
links: links
2326
}
@@ -31,20 +34,6 @@ def binding
3134
@resource
3235
end
3336

34-
def last_operation
35-
return nil if binding.last_operation.blank?
36-
37-
last_operation = binding.last_operation
38-
39-
{
40-
type: last_operation.type,
41-
state: last_operation.state,
42-
description: last_operation.description,
43-
created_at: last_operation.created_at,
44-
updated_at: last_operation.updated_at
45-
}
46-
end
47-
4837
def links
4938
{
5039
self: {

app/repositories/app_usage_event_repository.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'database/old_record_cleanup'
2+
require 'cloud_controller/url_secret_obfuscator'
23

34
module VCAP::CloudController
45
module Repositories

spec/request/service_credential_bindings_spec.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,7 +1296,7 @@ def expected_json(binding)
12961296
created_at: iso8601,
12971297
updated_at: iso8601,
12981298
name: binding.name,
1299-
last_operation: nil,
1299+
last_operation: last_operation(binding),
13001300
relationships: {
13011301
service_instance: {
13021302
data: {
@@ -1350,14 +1350,22 @@ def extra(binding)
13501350
end
13511351

13521352
def last_operation(binding)
1353-
if binding.last_operation.present?
1353+
if binding.try(:last_operation)
13541354
{
13551355
type: binding.last_operation.type,
13561356
state: binding.last_operation.state,
13571357
description: binding.last_operation.description,
13581358
created_at: iso8601,
13591359
updated_at: iso8601
13601360
}
1361+
else
1362+
{
1363+
type: 'create',
1364+
state: 'succeeded',
1365+
description: '',
1366+
created_at: iso8601,
1367+
updated_at: iso8601
1368+
}
13611369
end
13621370
end
13631371

spec/request/service_route_bindings_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,21 @@
504504
expect(VCAP::CloudController::RouteBinding.all).to be_empty
505505
end
506506
end
507+
508+
context 'there is an operation in progress for the service instance' do
509+
it 'responds with 422' do
510+
service_instance.save_with_new_operation({}, { type: 'guacamole', state: 'in progress' })
511+
512+
post '/v3/service_route_bindings', request.to_json, space_dev_headers
513+
514+
expect(last_response).to have_status_code(422)
515+
expect(parsed_response['errors']).to include(include({
516+
'detail' => include('There is an operation in progress for the service instance'),
517+
'title' => 'CF-UnprocessableEntity',
518+
'code' => 10008,
519+
}))
520+
end
521+
end
507522
end
508523

509524
context 'user-provided service instance' do

spec/unit/actions/service_route_binding_create_spec.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require 'spec_helper'
1+
require 'db_spec_helper'
22
require 'actions/service_route_binding_create'
33

44
module VCAP::CloudController
@@ -120,6 +120,19 @@ module V3
120120
)
121121
end
122122
end
123+
124+
context 'when there is an operation in progress for the service instance' do
125+
it 'raises an error' do
126+
service_instance.save_with_new_operation({}, { type: 'tacos', state: 'in progress' })
127+
128+
expect {
129+
action.precursor(service_instance, route)
130+
}.to raise_error(
131+
ServiceRouteBindingCreate::UnprocessableCreate,
132+
'There is an operation in progress for the service instance'
133+
)
134+
end
135+
end
123136
end
124137

125138
context 'user-provided service instance' do

0 commit comments

Comments
 (0)