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

Commit 8ef7732

Browse files
v3(tests): lifecycle tests for service route bindings
[#175575600](https://www.pivotaltracker.com/story/show/175575600)
1 parent 52a934c commit 8ef7732

1 file changed

Lines changed: 284 additions & 0 deletions

File tree

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
require 'spec_helper'
2+
require 'cloud_controller'
3+
4+
# This lifecycle test aims to use different v3 service endpoints together
5+
RSpec.describe 'V3 service route bindings synoptic' do
6+
before do
7+
stub_request(:get, 'http://example.org/amazing-service-broker/v2/catalog').
8+
with(basic_auth: %w(admin password)).
9+
to_return(status: 200, body: catalog, headers: {})
10+
11+
stub_request(:put, %r{\Ahttp://example.org/amazing-service-broker/v2/service_instances/.+\z}).
12+
with(basic_auth: %w(admin password)).
13+
to_return(status: 201, body: {}.to_json, headers: {})
14+
15+
stub_request(:get, 'https://master.default.svc.cluster-domain.example/apis/networking.cloudfoundry.org/v1alpha1').
16+
with(basic_auth: %w(admin password)).
17+
to_return(status: 200, body: '', headers: {})
18+
19+
stub_request(:get, %r{\Ahttp://example.org/amazing-service-broker/v2/service_instances/.+/service_bindings/.+\z}).
20+
with(basic_auth: %w(admin password)).
21+
to_return(status: 200, body: { parameters: { key1: 'value1', key2: 'value2' } }.to_json, headers: {})
22+
23+
stub_request(:delete, %r{\Ahttp://example.org/amazing-service-broker/v2/service_instances/.+/service_bindings/.+\z}).
24+
with(basic_auth: %w(admin password)).
25+
to_return(status: 410, body: '', headers: {})
26+
VCAP::CloudController::Config.config.set(:kubernetes, nil)
27+
end
28+
29+
it 'works end to end' do
30+
org_guid = create_org
31+
space_guid = create_space(org_guid)
32+
33+
post '/v3/service_brokers', create_service_broker_request_body.to_json, admin_headers
34+
expect(last_response).to have_status_code(202)
35+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
36+
37+
plan_guid = get_route_service_plan using: admin_headers
38+
make_plan_visible plan_guid
39+
40+
service_instance_guid = wait_for_service_instance_to_be_created(space_guid, plan_guid)
41+
42+
domain_guid = create_domain
43+
route_guid = create_route(domain_guid, space_guid)
44+
45+
create_request = create_route_binding_request(route_guid, service_instance_guid)
46+
post '/v3/service_route_bindings', create_request.to_json, admin_headers
47+
expect(last_response).to have_status_code(202)
48+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
49+
50+
get '/v3/service_route_bindings', nil, admin_headers
51+
route_binding_guid = parsed_response['resources'][0]['guid']
52+
get "/v3/service_route_bindings/#{route_binding_guid}/parameters", nil, admin_headers
53+
expect(parsed_response).to contain_exactly(*create_request[:parameters].with_indifferent_access)
54+
55+
update_request = {
56+
metadata: {
57+
labels: { key: 'value' },
58+
annotations: { note: 'detailed information' }
59+
}
60+
}
61+
patch "/v3/service_route_bindings/#{route_binding_guid}", update_request.to_json, admin_headers
62+
expect(last_response).to have_status_code(200)
63+
expect(parsed_response['metadata']['annotations']).to contain_exactly(*update_request[:metadata][:annotations].merge(create_request[:metadata][:annotations]).stringify_keys)
64+
expect(parsed_response['metadata']['labels']).to contain_exactly(*update_request[:metadata][:labels].merge(create_request[:metadata][:labels]).stringify_keys)
65+
66+
delete "/v3/service_route_bindings/#{route_binding_guid}", nil, admin_headers
67+
expect(last_response).to have_status_code(202)
68+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
69+
get "/v3/service_route_bindings/#{route_binding_guid}", nil, admin_headers
70+
expect(last_response).to have_status_code(404)
71+
end
72+
73+
def create_org
74+
org_request_body = { name: 'my-organization' }
75+
76+
post '/v3/organizations', org_request_body.to_json, admin_headers
77+
expect(last_response).to have_status_code(201)
78+
parsed_response['guid']
79+
end
80+
81+
def create_space(org_guid)
82+
space_request_body = {
83+
name: 'my-space',
84+
relationships: {
85+
organization: {
86+
data: {
87+
guid: org_guid
88+
}
89+
}
90+
}
91+
}
92+
93+
post '/v3/spaces', space_request_body.to_json, admin_headers
94+
expect(last_response).to have_status_code(201)
95+
parsed_response['guid']
96+
end
97+
98+
def get_route_service_plan(using:)
99+
get_service_plan_with(name: 'route_plan', using: using)
100+
end
101+
102+
def get_service_plan_with(name:, using:)
103+
headers = using
104+
get "/v3/service_plans?names=#{name}", nil, headers
105+
expect(last_response).to have_status_code(200)
106+
107+
parsed_response['resources'][0]['guid']
108+
end
109+
110+
def make_plan_visible(plan_guid)
111+
post "v3/service_plans/#{plan_guid}/visibility", { type: 'public' }.to_json, admin_headers
112+
expect(last_response).to have_status_code(200)
113+
114+
get "v3/service_plans/#{plan_guid}/visibility", nil, admin_headers
115+
expect(last_response).to have_status_code(200)
116+
expect(parsed_response['type']).to eq('public')
117+
end
118+
119+
def create_service_instance(space_guid, plan_guid)
120+
create_service_instance_request_body = {
121+
name: 'my-service-instance',
122+
relationships: {
123+
service_plan: {
124+
data: {
125+
guid: plan_guid
126+
}
127+
},
128+
space: {
129+
data: {
130+
guid: space_guid
131+
}
132+
}
133+
},
134+
type: 'managed'
135+
}
136+
137+
post '/v3/service_instances', create_service_instance_request_body.to_json, admin_headers
138+
expect(last_response).to have_status_code(202)
139+
last_response.headers['Location']
140+
end
141+
142+
def wait_for_service_instance_to_be_created(space_guid, plan_guid)
143+
job_location = create_service_instance(space_guid, plan_guid)
144+
145+
get job_location, nil, admin_headers
146+
expect(last_response).to have_status_code(200)
147+
expect(parsed_response['state']).to eql('PROCESSING')
148+
149+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
150+
151+
get job_location, nil, admin_headers
152+
expect(last_response).to have_status_code(200)
153+
expect(parsed_response['state']).to eql('COMPLETE')
154+
155+
get parsed_response['links']['service_instances']['href'], nil, admin_headers
156+
parsed_response['guid']
157+
end
158+
159+
let(:create_service_broker_request_body) do
160+
{
161+
name: 'amazing-service-broker',
162+
url: 'http://example.org/amazing-service-broker',
163+
authentication: {
164+
type: 'basic',
165+
credentials: {
166+
username: 'admin',
167+
password: 'password',
168+
}
169+
},
170+
metadata: {
171+
labels: { to_update: 'value', to_delete: 'value', 'to.delete/with_prefix' => 'value' },
172+
annotations: { to_update: 'value', to_delete: 'value', 'to.delete/with_prefix' => 'value' }
173+
}
174+
}
175+
end
176+
177+
let(:create_service_broker_request_body) do
178+
{
179+
name: 'amazing-service-broker',
180+
url: 'http://example.org/amazing-service-broker',
181+
authentication: {
182+
type: 'basic',
183+
credentials: {
184+
username: 'admin',
185+
password: 'password',
186+
}
187+
},
188+
metadata: {
189+
labels: { to_update: 'value', to_delete: 'value', 'to.delete/with_prefix' => 'value' },
190+
annotations: { to_update: 'value', to_delete: 'value', 'to.delete/with_prefix' => 'value' }
191+
}
192+
}
193+
end
194+
195+
let(:catalog) do
196+
{
197+
'services' => [
198+
{
199+
'id' => 'catalog1',
200+
'name' => 'service_name-1',
201+
'description' => 'some description 1',
202+
'bindable' => true,
203+
'plans' => [
204+
{
205+
'id' => 'fake_plan_id-1',
206+
'name' => 'plan_name-1',
207+
'description' => 'fake_plan_description 1',
208+
'schemas' => nil
209+
}
210+
]
211+
},
212+
{
213+
'id' => 'catalog2',
214+
'name' => 'route_volume_service_name-2',
215+
'requires' => ['volume_mount', 'route_forwarding'],
216+
'description' => 'some description 2',
217+
'bindable' => true,
218+
'bindings_retrievable' => true,
219+
'plans' => [
220+
{
221+
'id' => 'route_plan',
222+
'name' => 'route_plan',
223+
'description' => 'plan with route forwarding enabled',
224+
'schemas' => nil
225+
}
226+
]
227+
},
228+
]
229+
}.to_json
230+
end
231+
232+
def create_route_binding_request(route_guid, service_instance_guid)
233+
{
234+
metadata: {
235+
annotations: {
236+
foo: 'bar'
237+
},
238+
labels: {
239+
baz: 'qux'
240+
}
241+
},
242+
relationships: {
243+
route: {
244+
data: {
245+
guid: route_guid
246+
}
247+
},
248+
service_instance: {
249+
data: {
250+
guid: service_instance_guid
251+
}
252+
}
253+
},
254+
parameters: {
255+
key1: 'value1',
256+
key2: 'value2'
257+
}
258+
}
259+
end
260+
261+
def create_domain
262+
post '/v3/domains', { 'name': 'example.com', 'internal': false }.to_json, admin_headers
263+
expect(last_response).to have_status_code(201)
264+
parsed_response['guid']
265+
end
266+
267+
def create_route(domain_guid, space_guid)
268+
route_request = {
269+
host: 'a-hostname',
270+
path: '/some_path',
271+
relationships: {
272+
domain: {
273+
data: { guid: domain_guid }
274+
},
275+
space: {
276+
data: { guid: space_guid }
277+
}
278+
}
279+
}
280+
post '/v3/routes', route_request.to_json, admin_headers
281+
expect(last_response).to have_status_code(201)
282+
parsed_response['guid']
283+
end
284+
end

0 commit comments

Comments
 (0)