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

Commit aa19fd5

Browse files
v3(test): route bindings orphan mitigation scenarios
[#174398275](https://www.pivotaltracker.com/story/show/174398275)
1 parent 63f2c3e commit aa19fd5

2 files changed

Lines changed: 186 additions & 2 deletions

File tree

spec/request/service_route_bindings_spec.rb

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@
286286
end
287287

288288
context 'when the bind completes synchronously' do
289-
it 'updates the the binding' do
289+
it 'updates the binding' do
290290
execute_all_jobs(expected_successes: 1, expected_failures: 0)
291291

292292
binding.reload
@@ -300,6 +300,30 @@
300300

301301
expect(job.state).to eq(VCAP::CloudController::PollableJobModel::COMPLETE_STATE)
302302
end
303+
304+
context 'orphan mitigation' do
305+
it_behaves_like 'create binding orphan mitigation' do
306+
let(:bind_url) { broker_bind_url }
307+
let(:plan_id) { plan.unique_id }
308+
let(:offering_id) { offering.unique_id }
309+
let(:client_body) do
310+
{
311+
context: {
312+
platform: 'cloudfoundry',
313+
organization_guid: org.guid,
314+
organization_name: org.name,
315+
space_guid: space.guid,
316+
space_name: space.name,
317+
},
318+
service_id: service_instance.service_plan.service.unique_id,
319+
plan_id: service_instance.service_plan.unique_id,
320+
bind_resource: {
321+
route: route.uri,
322+
},
323+
}
324+
end
325+
end
326+
end
303327
end
304328

305329
context 'when the binding completes asynchronously' do
@@ -365,7 +389,7 @@
365389
to_return(status: fetch_binding_status_code, body: fetch_binding_body.to_json, headers: {})
366390
end
367391

368-
it 'fetches the service instance' do
392+
it 'fetches the binding' do
369393
execute_all_jobs(expected_successes: 1, expected_failures: 0)
370394

371395
expect(
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
RSpec.shared_examples 'create binding orphan mitigation' do
2+
let(:job) { VCAP::CloudController::PollableJobModel.last }
3+
4+
before do
5+
stub_request(:delete, bind_url).
6+
with(query: {
7+
accepts_incomplete: true,
8+
plan_id: plan_id,
9+
service_id: offering_id,
10+
}).to_return(status: 200, body: {}.to_json)
11+
end
12+
13+
context 'broker returns a success code' do
14+
codes = [200, 201]
15+
codes.each do |code|
16+
context "response is #{code}" do
17+
before do
18+
stub_request(:put, bind_url).
19+
with(query: {
20+
accepts_incomplete: true,
21+
},
22+
body: client_body).to_return(status: code, body: {}.to_json)
23+
end
24+
25+
it 'updates the binding and job' do
26+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
27+
28+
expect(binding.last_operation.type).to eq('create')
29+
expect(binding.last_operation.state).to eq('succeeded')
30+
31+
expect(job.state).to eq(VCAP::CloudController::PollableJobModel::COMPLETE_STATE)
32+
33+
expect(
34+
a_request(:delete, bind_url).
35+
with(
36+
query: {
37+
accepts_incomplete: true,
38+
plan_id: plan_id,
39+
service_id: offering_id,
40+
},
41+
)
42+
).not_to have_been_made
43+
end
44+
end
45+
end
46+
47+
context 'response is 201 with malformed response' do
48+
before do
49+
stub_request(:put, bind_url).
50+
with(query: {
51+
accepts_incomplete: true,
52+
},
53+
body: client_body).to_return(status: 201, body: nil)
54+
end
55+
56+
it 'updates the binding and performs orphan mitigation' do
57+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
58+
59+
assert_failed_job(binding, job)
60+
assert_orphan_mitigation_performed(plan_id, offering_id)
61+
end
62+
end
63+
end
64+
65+
context 'broker does not process the request' do
66+
[400, 401, 408, 409, *411..431].each do |code|
67+
context "response is #{code}" do
68+
before do
69+
stub_request(:put, bind_url).
70+
with(query: {
71+
accepts_incomplete: true,
72+
},
73+
body: client_body).to_return(status: code, body: { error: 'ConcurrencyError', description: 'some description' }.to_json)
74+
end
75+
76+
it 'updates the binding and job' do
77+
execute_all_jobs(expected_successes: 0, expected_failures: 1)
78+
79+
assert_failed_job(binding, job)
80+
81+
expect(
82+
a_request(:delete, bind_url).
83+
with(
84+
query: {
85+
accepts_incomplete: true,
86+
plan_id: plan_id,
87+
service_id: offering_id,
88+
},
89+
)
90+
).not_to have_been_made
91+
end
92+
end
93+
end
94+
end
95+
96+
context 'broker fails to bind with an error not specified in osbapi' do
97+
[*500..511, *203..208].sample(4).each do |code|
98+
context "response is #{code}" do
99+
before do
100+
stub_request(:put, bind_url).
101+
with(query: {
102+
accepts_incomplete: true,
103+
},
104+
body: client_body).to_return(status: code, body: {}.to_json)
105+
end
106+
107+
it 'does orphan mitigation and fails the job' do
108+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
109+
110+
assert_failed_job(binding, job)
111+
assert_orphan_mitigation_performed(plan_id, offering_id)
112+
end
113+
end
114+
end
115+
end
116+
117+
context 'timeout' do
118+
before do
119+
stub_request(:put, bind_url).
120+
with(query: {
121+
accepts_incomplete: true,
122+
},
123+
body: client_body).to_timeout
124+
125+
stub_request(:delete, bind_url).
126+
with(query: {
127+
accepts_incomplete: true,
128+
plan_id: plan_id,
129+
service_id: offering_id,
130+
}).to_return(status: 200, body: {}.to_json)
131+
end
132+
133+
it 'does orphan mitigation and fails the job' do
134+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
135+
136+
assert_failed_job(binding, job)
137+
assert_orphan_mitigation_performed(plan_id, offering_id)
138+
end
139+
end
140+
end
141+
142+
def assert_failed_job(binding, job)
143+
binding.reload
144+
expect(binding.last_operation.type).to eq('create')
145+
expect(binding.last_operation.state).to eq('failed')
146+
expect(job.state).to eq(VCAP::CloudController::PollableJobModel::FAILED_STATE)
147+
end
148+
149+
def assert_orphan_mitigation_performed(plan_id, offering_id)
150+
expect(
151+
a_request(:delete, bind_url).
152+
with(
153+
query: {
154+
accepts_incomplete: true,
155+
plan_id: plan_id,
156+
service_id: offering_id,
157+
},
158+
)
159+
).to have_been_made.once
160+
end

0 commit comments

Comments
 (0)