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

Commit 241e452

Browse files
Derik EvangelistaFelisiaM
andauthored
v3(bindings): orphan mitigation on create failures (cloudfoundry#1914)
[#174256592](https://www.pivotaltracker.com/story/show/174256592) Co-authored-by: Felisia Martini <fmartini@pivotal.io>
1 parent d8b71b6 commit 241e452

2 files changed

Lines changed: 123 additions & 104 deletions

File tree

spec/request/service_credential_bindings_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,14 @@ def check_filtered_bindings(*bindings)
13981398
end
13991399
end
14001400
end
1401+
1402+
context 'orphan mitigation' do
1403+
it_behaves_like 'create binding orphan mitigation' do
1404+
let(:bind_url) { broker_bind_url }
1405+
let(:plan_id) { plan.unique_id }
1406+
let(:offering_id) { offering.unique_id }
1407+
end
1408+
end
14011409
end
14021410
end
14031411
end
Lines changed: 115 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
RSpec.shared_examples 'create binding orphan mitigation' do
22
let(:job) { VCAP::CloudController::PollableJobModel.last }
3+
let(:bind_response_body) { '{}' }
4+
let(:broker_bind_status_code) { 200 }
35

46
before do
57
stub_request(:delete, bind_url).
@@ -8,133 +10,136 @@
810
plan_id: plan_id,
911
service_id: offering_id,
1012
}).to_return(status: 200, body: {}.to_json)
13+
14+
stub_request(:put, bind_url).
15+
with(query: { accepts_incomplete: true },
16+
body: client_body).to_return(status: broker_bind_status_code, body: bind_response_body)
1117
end
1218

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
19+
context 'should not be performed' do
20+
before do
21+
stub_request(:get, "#{bind_url}/last_operation").
22+
with({ query: { plan_id: plan_id, service_id: offering_id } }).
23+
to_return(status: 200, body: '{"state": "in progress"}')
24+
end
25+
26+
context 'broker returns valid 200, 201, 202' do
27+
[200, 201, 202].each do |code|
28+
context "response is #{code}" do
29+
let(:broker_bind_status_code) { code }
2430

25-
it 'updates the binding and job' do
26-
execute_all_jobs(expected_successes: 1, expected_failures: 0)
31+
it 'succeeds the job and does not perform orphan mitigation' do
32+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
33+
assert_no_orphan_mitigation_performed(plan_id, offering_id)
34+
end
35+
end
36+
end
37+
end
2738

28-
expect(binding.last_operation.type).to eq('create')
29-
expect(binding.last_operation.state).to eq('succeeded')
39+
context 'response is 200 with malformed response' do
40+
let(:broker_bind_status_code) { 200 }
41+
let(:bind_response_body) { nil }
3042

31-
expect(job.state).to eq(VCAP::CloudController::PollableJobModel::COMPLETE_STATE)
43+
it 'fails the job and does not perform orphan mitigation' do
44+
execute_all_jobs(expected_successes: 0, expected_failures: 1)
3245

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
46+
assert_failed_job(binding, job)
47+
assert_no_orphan_mitigation_performed(plan_id, offering_id)
4448
end
4549
end
4650

47-
context 'response is 201 with malformed response' do
51+
context 'response for last operation is 200 state failed' do
52+
let(:broker_bind_status_code) { 202 }
4853
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+
stub_request(:get, "#{bind_url}/last_operation").
55+
with({ query: { plan_id: plan_id, service_id: offering_id } }).
56+
to_return(status: 200, body: '{"state": "failed"}')
5457
end
5558

56-
it 'updates the binding and performs orphan mitigation' do
57-
execute_all_jobs(expected_successes: 1, expected_failures: 1)
59+
it 'fails the job and does not perform orphan mitigation' do
60+
execute_all_jobs(expected_successes: 0, expected_failures: 1)
5861

5962
assert_failed_job(binding, job)
60-
assert_orphan_mitigation_performed(plan_id, offering_id)
63+
assert_no_orphan_mitigation_performed(plan_id, offering_id)
6164
end
6265
end
63-
end
6466

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
67+
context 'broker returns a 4xx code' do
68+
[400, 401, 408, 409, *411..431].each do |code|
69+
context "response is #{code}" do
70+
let(:broker_bind_status_code) { code }
71+
let(:bind_response_body) { '{ "error": "ConcurrencyError", "description": "some description" }' }
7572

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
73+
it 'fails the job and updates the binding and job' do
74+
execute_all_jobs(expected_successes: 0, expected_failures: 1)
75+
76+
assert_failed_job(binding, job)
77+
assert_no_orphan_mitigation_performed(plan_id, offering_id)
78+
end
9179
end
9280
end
9381
end
9482
end
9583

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)
84+
context 'should be performed' do
85+
context 'broker returns a 2xx code' do
86+
[201, 202].each do |code|
87+
context "response is #{code} with malformed response" do
88+
let(:broker_bind_status_code) { code }
89+
let(:bind_response_body) { nil }
90+
91+
it 'performs orphan mitigation' do
92+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
93+
94+
assert_failed_job(binding, job)
95+
assert_orphan_mitigation_performed(plan_id, offering_id)
96+
end
10597
end
98+
end
10699

107-
it 'does orphan mitigation and fails the job' do
108-
execute_all_jobs(expected_successes: 1, expected_failures: 1)
100+
[203, 204, 205, 206, 206, 208, 226].each do |code|
101+
context "response is #{code}" do
102+
let(:broker_bind_status_code) { code }
103+
let(:bind_response_body) { '{}' }
109104

110-
assert_failed_job(binding, job)
111-
assert_orphan_mitigation_performed(plan_id, offering_id)
105+
it 'performs orphan mitigation' do
106+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
107+
assert_orphan_mitigation_performed(plan_id, offering_id)
108+
end
112109
end
113110
end
114111
end
115-
end
116112

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)
113+
context 'broker returns a 5xx code' do
114+
[*500..511].each do |code|
115+
context "response is #{code}" do
116+
let(:broker_bind_status_code) { code }
117+
118+
it 'does orphan mitigation and fails the job' do
119+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
120+
121+
assert_failed_job(binding, job)
122+
assert_orphan_mitigation_performed(plan_id, offering_id)
123+
end
124+
end
125+
end
131126
end
132127

133-
it 'does orphan mitigation and fails the job' do
134-
execute_all_jobs(expected_successes: 1, expected_failures: 1)
128+
context 'timeout' do
129+
before do
130+
stub_request(:put, bind_url).
131+
with(query: {
132+
accepts_incomplete: true,
133+
},
134+
body: client_body).to_timeout
135+
end
135136

136-
assert_failed_job(binding, job)
137-
assert_orphan_mitigation_performed(plan_id, offering_id)
137+
it 'does orphan mitigation and fails the job' do
138+
execute_all_jobs(expected_successes: 1, expected_failures: 1)
139+
140+
assert_failed_job(binding, job)
141+
assert_orphan_mitigation_performed(plan_id, offering_id)
142+
end
138143
end
139144
end
140145
end
@@ -147,14 +152,20 @@ def assert_failed_job(binding, job)
147152
end
148153

149154
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
155+
expect(delete_request(plan_id, offering_id)).to have_been_made.once
156+
end
157+
158+
def assert_no_orphan_mitigation_performed(plan_id, offering_id)
159+
expect(delete_request(plan_id, offering_id)).to_not have_been_made
160+
end
161+
162+
def delete_request(plan_id, offering_id)
163+
a_request(:delete, bind_url).
164+
with(
165+
query: {
166+
accepts_incomplete: true,
167+
plan_id: plan_id,
168+
service_id: offering_id,
169+
},
170+
)
160171
end

0 commit comments

Comments
 (0)