();
63 | credentials.put("uri", dbURL);
64 |
65 | return new ServiceInstanceBinding(bindingId, serviceInstanceId, credentials, null, appGuid);
66 | }
67 |
68 | @Override
69 | public ServiceInstanceBinding deleteServiceInstanceBinding(DeleteServiceInstanceBindingRequest deleteServiceInstanceBindingRequest)
70 | throws ServiceBrokerException {
71 | String serviceInstanceId = deleteServiceInstanceBindingRequest.getInstance().getServiceInstanceId();
72 | String bindingId = deleteServiceInstanceBindingRequest.getBindingId();
73 | try {
74 | this.role.unBindRoleFromDatabase(serviceInstanceId);
75 | } catch (SQLException e) {
76 | logger.error("Error while deleting service instance binding '" + bindingId + "'", e);
77 | throw new ServiceBrokerException(e.getMessage());
78 | }
79 | return new ServiceInstanceBinding(bindingId, serviceInstanceId, null, null, null);
80 | }
81 | }
--------------------------------------------------------------------------------
/src/main/java/org/cloudfoundry/community/servicebroker/postgresql/service/PostgreSQLServiceInstanceService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.cloudfoundry.community.servicebroker.postgresql.service;
17 |
18 | import org.cloudfoundry.community.servicebroker.exception.ServiceBrokerException;
19 | import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceDoesNotExistException;
20 | import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceExistsException;
21 | import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceUpdateNotSupportedException;
22 | import org.cloudfoundry.community.servicebroker.model.CreateServiceInstanceRequest;
23 | import org.cloudfoundry.community.servicebroker.model.DeleteServiceInstanceRequest;
24 | import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
25 | import org.cloudfoundry.community.servicebroker.model.UpdateServiceInstanceRequest;
26 | import org.cloudfoundry.community.servicebroker.service.ServiceInstanceService;
27 | import org.slf4j.Logger;
28 | import org.slf4j.LoggerFactory;
29 | import org.springframework.beans.factory.annotation.Autowired;
30 | import org.springframework.stereotype.Service;
31 |
32 | import java.sql.SQLException;
33 |
34 | @Service
35 | public class PostgreSQLServiceInstanceService implements ServiceInstanceService {
36 |
37 | private static final Logger logger = LoggerFactory.getLogger(PostgreSQLServiceInstanceService.class);
38 |
39 | private final Database db;
40 |
41 | private final Role role;
42 |
43 | @Autowired
44 | public PostgreSQLServiceInstanceService(Database db, Role role) {
45 | this.db = db;
46 | this.role = role;
47 | }
48 |
49 | @Override
50 | public ServiceInstance createServiceInstance(CreateServiceInstanceRequest createServiceInstanceRequest)
51 | throws ServiceInstanceExistsException, ServiceBrokerException {
52 | String serviceInstanceId = createServiceInstanceRequest.getServiceInstanceId();
53 | String serviceId = createServiceInstanceRequest.getServiceDefinitionId();
54 | String planId = createServiceInstanceRequest.getPlanId();
55 | String organizationGuid = createServiceInstanceRequest.getOrganizationGuid();
56 | String spaceGuid = createServiceInstanceRequest.getSpaceGuid();
57 | try {
58 | db.createDatabaseForInstance(serviceInstanceId, serviceId, planId, organizationGuid, spaceGuid);
59 | role.createRoleForInstance(serviceInstanceId);
60 | } catch (SQLException e) {
61 | logger.error("Error while creating service instance '" + serviceInstanceId + "'", e);
62 | throw new ServiceBrokerException(e.getMessage());
63 | }
64 | return new ServiceInstance(createServiceInstanceRequest);
65 | }
66 |
67 | @Override
68 | public ServiceInstance deleteServiceInstance(DeleteServiceInstanceRequest deleteServiceInstanceRequest)
69 | throws ServiceBrokerException {
70 | String serviceInstanceId = deleteServiceInstanceRequest.getServiceInstanceId();
71 | ServiceInstance instance = getServiceInstance(serviceInstanceId);
72 |
73 | try {
74 | db.deleteDatabase(serviceInstanceId);
75 | role.deleteRole(serviceInstanceId);
76 | } catch (SQLException e) {
77 | logger.error("Error while deleting service instance '" + serviceInstanceId + "'", e);
78 | throw new ServiceBrokerException(e.getMessage());
79 | }
80 | return instance;
81 | }
82 |
83 | @Override
84 | public ServiceInstance updateServiceInstance(UpdateServiceInstanceRequest updateServiceInstanceRequest)
85 | throws ServiceInstanceUpdateNotSupportedException, ServiceBrokerException, ServiceInstanceDoesNotExistException {
86 | throw new IllegalStateException("Not implemented");
87 | }
88 |
89 | @Override
90 | public ServiceInstance getServiceInstance(String id) {
91 | try {
92 | return db.findServiceInstance(id);
93 | } catch (SQLException e) {
94 | logger.error("Error while finding service instance '" + id + "'", e);
95 | return null;
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/src/main/java/org/cloudfoundry/community/servicebroker/postgresql/service/Role.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.cloudfoundry.community.servicebroker.postgresql.service;
17 |
18 | import org.springframework.stereotype.Component;
19 |
20 | import java.math.BigInteger;
21 | import java.security.SecureRandom;
22 | import java.sql.SQLException;
23 |
24 | @Component
25 | public class Role {
26 |
27 | public void createRoleForInstance(String instanceId) throws SQLException {
28 | Utils.checkValidUUID(instanceId);
29 | PostgreSQLDatabase.executeUpdate("CREATE ROLE \"" + instanceId + "\"");
30 | PostgreSQLDatabase.executeUpdate("ALTER DATABASE \"" + instanceId + "\" OWNER TO \"" + instanceId + "\"");
31 | }
32 |
33 | public void deleteRole(String instanceId) throws SQLException {
34 | Utils.checkValidUUID(instanceId);
35 | PostgreSQLDatabase.executeUpdate("DROP ROLE IF EXISTS \"" + instanceId + "\"");
36 | }
37 |
38 | public String bindRoleToDatabase(String dbInstanceId) throws SQLException {
39 | Utils.checkValidUUID(dbInstanceId);
40 |
41 | SecureRandom random = new SecureRandom();
42 | String passwd = new BigInteger(130, random).toString(32);
43 |
44 | PostgreSQLDatabase.executeUpdate("ALTER ROLE \"" + dbInstanceId + "\" LOGIN password '" + passwd + "'");
45 | return passwd;
46 | }
47 |
48 | public void unBindRoleFromDatabase(String dbInstanceId) throws SQLException{
49 | Utils.checkValidUUID(dbInstanceId);
50 | PostgreSQLDatabase.executeUpdate("ALTER ROLE \"" + dbInstanceId + "\" NOLOGIN");
51 | }
52 | }
--------------------------------------------------------------------------------
/src/main/java/org/cloudfoundry/community/servicebroker/postgresql/service/Utils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.cloudfoundry.community.servicebroker.postgresql.service;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 |
21 | import java.util.UUID;
22 |
23 | public class Utils {
24 |
25 | private static final Logger logger = LoggerFactory.getLogger(Utils.class);
26 |
27 | private Utils() {
28 | }
29 |
30 | public static void checkValidUUID(String uuidString) {
31 | logger.info("Checking if this UUID string is a valid UUID: " + uuidString);
32 | UUID uuid = UUID.fromString(uuidString);
33 |
34 | if(!uuidString.equals(uuid.toString())) {
35 | throw new IllegalStateException("UUID '" + uuidString + "' is not an UUID.");
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | security.user.password: password
--------------------------------------------------------------------------------
/src/test/java/org/cloudfoundry/community/servicebroker/ServiceBrokerV2IntegrationTestBase.java:
--------------------------------------------------------------------------------
1 | package org.cloudfoundry.community.servicebroker;
2 |
3 | import com.jayway.restassured.RestAssured;
4 | import com.jayway.restassured.http.ContentType;
5 | import com.jayway.restassured.response.Header;
6 | import org.apache.http.HttpStatus;
7 | import org.junit.Before;
8 | import org.junit.BeforeClass;
9 | import org.junit.FixMethodOrder;
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 | import org.junit.runners.MethodSorters;
13 | import org.springframework.beans.factory.annotation.Value;
14 | import org.springframework.boot.test.IntegrationTest;
15 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
16 | import org.springframework.test.context.web.WebAppConfiguration;
17 |
18 | import java.util.UUID;
19 |
20 | import static com.jayway.restassured.RestAssured.given;
21 |
22 | /**
23 | * Abstract test base class for the Service Broker V2 API.
24 | *
25 | * Usage:
26 | * Annotate the implementing test class with the following implementation-specific annotation:
27 | *
28 | * @SpringApplicationConfiguration(classes = Application.class)
29 | *
30 | * If you would want to test the actual creation/deletion of resources, you might also want this annotation:
31 | *
32 | * @FixMethodOrder(MethodSorters.NAME_ASCENDING)
33 | *
34 | * This would cause JUnit to run the methods in name-ascending order, causing the cases to run in order.
35 | */
36 | @RunWith(SpringJUnit4ClassRunner.class)
37 | @WebAppConfiguration
38 | @IntegrationTest("server.port:0")
39 | @FixMethodOrder(MethodSorters.NAME_ASCENDING)
40 | public abstract class ServiceBrokerV2IntegrationTestBase {
41 |
42 | @Value("${local.server.port}")
43 | protected int port;
44 |
45 | @Value("${security.user.password}")
46 | protected String password;
47 |
48 | @Value("${service_id}")
49 | protected String serviceId;
50 |
51 | @Value("${plan_id}")
52 | protected String planId;
53 |
54 | protected final String username = "user";
55 |
56 | protected final String organizationGuid = "system";
57 |
58 | protected final String spaceGuid = "thespace";
59 |
60 | protected static String instanceId;
61 |
62 | protected static String appGuid;
63 |
64 | protected final String fetchCatalogPath = "/v2/catalog";
65 |
66 | protected final String provisionOrRemoveInstanceBasePath = "/v2/service_instances/%s";
67 |
68 | protected final String createOrRemoveBindingBasePath = "/v2/service_instances/%s/service_bindings/%s";
69 |
70 | protected final Header apiVersionHeader = new Header("X-Broker-Api-Version", BROKER_API_VERSION);
71 |
72 | public static final String BROKER_API_VERSION = "2.4";
73 |
74 | @Before
75 | public void setUp() throws Exception {
76 | RestAssured.port = port;
77 | }
78 |
79 | @BeforeClass
80 | public static void generateUniqueIds() {
81 | instanceId = UUID.randomUUID().toString();
82 | appGuid = UUID.randomUUID().toString();
83 | }
84 |
85 | /**
86 | * cf marketplace
87 | * cf create-service-broker
88 | *
89 | * Fetch Catalog (GET /v2/catalog)
90 | */
91 |
92 | @Test
93 | public void case1_fetchCatalogFailsWithoutCredentials() throws Exception {
94 | given().auth().none().when().get(fetchCatalogPath).then().statusCode(HttpStatus.SC_UNAUTHORIZED);
95 | }
96 |
97 | @Test
98 | public void case1_fetchCatalogSucceedsWithCredentials() throws Exception {
99 | given().auth().basic(username, password).header(apiVersionHeader).when().get(fetchCatalogPath).then().statusCode(HttpStatus.SC_OK);
100 | }
101 |
102 | /**
103 | * cf create-service
104 | *
105 | * Provision Instance (PUT /v2/service_instances/:id)
106 | */
107 |
108 | @Test
109 | public void case2_provisionInstanceFailsWithoutCredentials() throws Exception {
110 | String provisionInstancePath = String.format(provisionOrRemoveInstanceBasePath, instanceId);
111 | given().auth().none().when().put(provisionInstancePath).then().statusCode(HttpStatus.SC_UNAUTHORIZED);
112 | }
113 |
114 | @Test
115 | public void case2_provisionInstanceSucceedsWithCredentials() throws Exception {
116 | String provisionInstancePath = String.format(provisionOrRemoveInstanceBasePath, instanceId);
117 | String request_body = "{\n" +
118 | " \"service_id\": \"" + serviceId + "\",\n" +
119 | " \"plan_id\": \"" + planId + "\",\n" +
120 | " \"organization_guid\": \"" + organizationGuid + "\",\n" +
121 | " \"space_guid\": \"" + spaceGuid + "\"\n" +
122 | "}";
123 |
124 | given().auth().basic(username, password).header(apiVersionHeader).request().contentType(ContentType.JSON).body(request_body).when().put(provisionInstancePath).then().statusCode(HttpStatus.SC_CREATED);
125 | }
126 |
127 | /**
128 | * cf bind-service
129 | *
130 | * Create Binding (PUT /v2/service_instances/:instance_id/service_bindings/:id)
131 | */
132 |
133 | @Test
134 | public void case3_createBindingFailsWithoutCredentials() throws Exception {
135 | String createBindingPath = String.format(createOrRemoveBindingBasePath, instanceId, serviceId);
136 | given().auth().none().when().put(createBindingPath).then().statusCode(HttpStatus.SC_UNAUTHORIZED);
137 | }
138 |
139 | @Test
140 | public void case3_createBindingSucceedsWithCredentials() throws Exception {
141 | String createBindingPath = String.format(createOrRemoveBindingBasePath, instanceId, serviceId);
142 | String request_body = "{\n" +
143 | " \"plan_id\": \"" + planId + "\",\n" +
144 | " \"service_id\": \"" + serviceId + "\",\n" +
145 | " \"app_guid\": \"" + appGuid + "\"\n" +
146 | "}";
147 |
148 | given().auth().basic(username, password).header(apiVersionHeader).request().contentType(ContentType.JSON).body(request_body).when().put(createBindingPath).then().statusCode(HttpStatus.SC_CREATED);
149 | }
150 |
151 | /**
152 | * cf unbind-service
153 | *
154 | * Remove Binding (DELETE /v2/service_instances/:instance_id/service_bindings/:id)
155 | */
156 |
157 | @Test
158 | public void case4_removeBindingFailsWithoutCredentials() throws Exception {
159 | String removeBindingPath = String.format(createOrRemoveBindingBasePath, instanceId, serviceId) + "?service_id=" + serviceId + "&plan_id=" + planId;
160 | given().auth().none().when().delete(removeBindingPath).then().statusCode(HttpStatus.SC_UNAUTHORIZED);
161 | }
162 |
163 | @Test
164 | public void case4_removeBindingSucceedsWithCredentials() throws Exception {
165 | String removeBindingPath = String.format(createOrRemoveBindingBasePath, instanceId, serviceId) + "?service_id=" + serviceId + "&plan_id=" + planId;
166 | given().auth().basic(username, password).header(apiVersionHeader).when().delete(removeBindingPath).then().statusCode(HttpStatus.SC_OK);
167 | }
168 |
169 | /**
170 | * cf delete-service
171 | *
172 | * Remove Instance (DELETE /v2/service_instances/:id)
173 | */
174 |
175 | @Test
176 | public void case5_removeInstanceFailsWithoutCredentials() throws Exception {
177 | String removeInstancePath = String.format(provisionOrRemoveInstanceBasePath, instanceId) + "?service_id=" + serviceId + "&plan_id=" + planId;
178 | given().auth().none().when().delete(removeInstancePath).then().statusCode(HttpStatus.SC_UNAUTHORIZED);
179 | }
180 |
181 | @Test
182 | public void case5_removeInstanceSucceedsWithCredentials() throws Exception {
183 | String removeInstancePath = String.format(provisionOrRemoveInstanceBasePath, instanceId) + "?service_id=" + serviceId + "&plan_id=" + planId;
184 | given().auth().basic(username, password).header(apiVersionHeader).when().delete(removeInstancePath).then().statusCode(HttpStatus.SC_OK);
185 | }
186 | }
--------------------------------------------------------------------------------
/src/test/java/org/cloudfoundry/community/servicebroker/postgresql/PostgreSQLServiceBrokerV2IntegrationTests.java:
--------------------------------------------------------------------------------
1 | package org.cloudfoundry.community.servicebroker.postgresql;
2 |
3 | import com.google.common.collect.ImmutableMap;
4 | import com.jayway.restassured.http.ContentType;
5 | import com.jayway.restassured.response.ValidatableResponse;
6 | import org.apache.http.HttpStatus;
7 | import org.cloudfoundry.community.servicebroker.ServiceBrokerV2IntegrationTestBase;
8 | import org.cloudfoundry.community.servicebroker.model.Plan;
9 | import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
10 | import org.cloudfoundry.community.servicebroker.postgresql.config.Application;
11 | import org.cloudfoundry.community.servicebroker.postgresql.config.BrokerConfiguration;
12 | import org.cloudfoundry.community.servicebroker.postgresql.service.PostgreSQLDatabase;
13 | import org.junit.Before;
14 | import org.junit.FixMethodOrder;
15 | import org.junit.Test;
16 | import org.junit.runners.MethodSorters;
17 | import org.springframework.beans.factory.annotation.Value;
18 | import org.springframework.boot.test.SpringApplicationConfiguration;
19 |
20 | import java.sql.Connection;
21 | import java.sql.DatabaseMetaData;
22 | import java.sql.DriverManager;
23 | import java.sql.ResultSet;
24 | import java.util.ArrayList;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | import static com.jayway.restassured.RestAssured.given;
29 | import static org.hamcrest.CoreMatchers.*;
30 | import static org.junit.Assert.*;
31 |
32 | @FixMethodOrder(MethodSorters.NAME_ASCENDING)
33 | @SpringApplicationConfiguration(classes = Application.class)
34 | public class PostgreSQLServiceBrokerV2IntegrationTests extends ServiceBrokerV2IntegrationTestBase {
35 |
36 | @Value("${MASTER_JDBC_URL}")
37 | private String jdbcUrl;
38 |
39 | private Connection conn;
40 |
41 | @Override
42 | @Before
43 | public void setUp() throws Exception {
44 | super.setUp();
45 | conn = DriverManager.getConnection(this.jdbcUrl);
46 | }
47 |
48 | /**
49 | * Sanity check, to make sure that the 'service' table required for this Service Broker is created.
50 | */
51 |
52 | @Test
53 | public void case0_checkThatServiceTableIsCreated() throws Exception {
54 | assertTrue(checkTableExists("service"));
55 | }
56 |
57 | /**
58 | * cf marketplace
59 | * cf create-service-broker
60 | *
61 | * Fetch Catalog (GET /v2/catalog)
62 | */
63 |
64 | @Override
65 | @Test
66 | public void case1_fetchCatalogSucceedsWithCredentials() throws Exception {
67 | // same as super code, but we need the response here
68 | ValidatableResponse response = given().auth().basic(username, password).header(apiVersionHeader).when().get(fetchCatalogPath).then().statusCode(HttpStatus.SC_OK);
69 |
70 | BrokerConfiguration brokerConfiguration = new BrokerConfiguration();
71 | ServiceDefinition serviceDefinition = brokerConfiguration.catalog().getServiceDefinitions().get(0);
72 |
73 | response.body("services[0].id", equalTo(serviceDefinition.getId()));
74 | response.body("services[0].name", equalTo(serviceDefinition.getName()));
75 | response.body("services[0].description", equalTo(serviceDefinition.getDescription()));
76 | response.body("services[0].requires", equalTo(serviceDefinition.getRequires()));
77 | response.body("services[0].tags", equalTo(serviceDefinition.getTags()));
78 |
79 | List planIds = new ArrayList();
80 | for(Plan plan: serviceDefinition.getPlans()) {
81 | planIds.add(plan.getId());
82 | }
83 | response.body("services[0].plans.id", equalTo(planIds));
84 | }
85 |
86 | /**
87 | * cf create-service
88 | *
89 | * Provision Instance (PUT /v2/service_instances/:id)
90 | */
91 |
92 | @Override
93 | @Test
94 | public void case2_provisionInstanceSucceedsWithCredentials() throws Exception {
95 | super.case2_provisionInstanceSucceedsWithCredentials();
96 |
97 | assertTrue(checkDatabaseExists(instanceId));
98 | assertTrue(checkRoleExists(instanceId));
99 | assertTrue(checkRoleIsDatabaseOwner(instanceId, instanceId));
100 |
101 | Map serviceResult = PostgreSQLDatabase.executePreparedSelect("SELECT * FROM service WHERE serviceinstanceid = ?", ImmutableMap.of(1, instanceId));
102 | assertThat(serviceResult.get("organizationguid"), is(organizationGuid));
103 | assertThat(serviceResult.get("planid"), is(planId));
104 | assertThat(serviceResult.get("spaceguid"), is(spaceGuid));
105 | assertThat(serviceResult.get("servicedefinitionid"), is(serviceId));
106 | assertThat(serviceResult.get("serviceinstanceid"), is(instanceId));
107 | }
108 |
109 | /**
110 | * cf bind-service
111 | *
112 | * Create Binding (PUT /v2/service_instances/:instance_id/service_bindings/:id)
113 | */
114 |
115 | @Override
116 | @Test
117 | public void case3_createBindingSucceedsWithCredentials() throws Exception {
118 | // same as super code, but we need the response here
119 | String createBindingPath = String.format(createOrRemoveBindingBasePath, instanceId, serviceId);
120 | String request_body = "{\n" +
121 | " \"plan_id\": \"" + planId + "\",\n" +
122 | " \"service_id\": \"" + serviceId + "\",\n" +
123 | " \"app_guid\": \"" + appGuid + "\"\n" +
124 | "}";
125 |
126 | ValidatableResponse response = given().auth().basic(username, password).header(apiVersionHeader).request().contentType(ContentType.JSON).body(request_body).when().put(createBindingPath).then().statusCode(HttpStatus.SC_CREATED);
127 |
128 | response.body("credentials.uri", containsString("postgres://" + instanceId));
129 | response.body("syslog_drain_url", is(nullValue()));
130 | }
131 |
132 | /**
133 | * cf unbind-service
134 | *
135 | * Remove Binding (DELETE /v2/service_instances/:instance_id/service_bindings/:id)
136 | */
137 |
138 | @Override
139 | @Test
140 | public void case4_removeBindingSucceedsWithCredentials() throws Exception {
141 | // same as super code, but we need the response here
142 | String removeBindingPath = String.format(createOrRemoveBindingBasePath, instanceId, serviceId) + "?service_id=" + serviceId + "&plan_id=" + planId;
143 | ValidatableResponse response = given().auth().basic(username, password).header(apiVersionHeader).when().delete(removeBindingPath).then().statusCode(HttpStatus.SC_OK);
144 |
145 | // response body is empty json
146 | response.body(equalTo("{}"));
147 | }
148 |
149 | /**
150 | * cf delete-service
151 | *
152 | * Remove Instance (DELETE /v2/service_instances/:id)
153 | */
154 |
155 | @Override
156 | @Test
157 | public void case5_removeInstanceSucceedsWithCredentials() throws Exception {
158 | super.case5_removeInstanceSucceedsWithCredentials();
159 |
160 | assertFalse(checkDatabaseExists(instanceId));
161 | assertFalse(checkRoleExists(instanceId));
162 | assertFalse(checkRoleIsDatabaseOwner(instanceId, instanceId));
163 |
164 | Map serviceResult = PostgreSQLDatabase.executePreparedSelect("SELECT * FROM service WHERE serviceinstanceid = ?", ImmutableMap.of(1, instanceId));
165 | assertTrue(serviceResult.isEmpty());
166 | }
167 |
168 | private boolean checkTableExists(String tableName) throws Exception {
169 | DatabaseMetaData md = conn.getMetaData();
170 | ResultSet rs = md.getTables(null, null, tableName, null);
171 |
172 | // ResultSet.last() followed by ResultSet.getRow() will give you the row count
173 | rs.last();
174 | int rowCount = rs.getRow();
175 | return rowCount == 1;
176 | }
177 |
178 | private boolean checkDatabaseExists(String databaseName) throws Exception {
179 | Map pgDatabaseResult = PostgreSQLDatabase.executePreparedSelect("SELECT * FROM pg_catalog.pg_database WHERE datname = ?", ImmutableMap.of(1, databaseName));
180 | return pgDatabaseResult.size() > 0;
181 | }
182 |
183 | private boolean checkRoleExists(String roleName) throws Exception {
184 | Map pgRoleResult = PostgreSQLDatabase.executePreparedSelect("SELECT * FROM pg_catalog.pg_roles WHERE rolname = ?", ImmutableMap.of(1, roleName));
185 | return pgRoleResult.size() > 0;
186 | }
187 |
188 | private boolean checkRoleIsDatabaseOwner(String roleName, String databaseName) throws Exception {
189 | Map pgRoleIsDatabaseOwnerResult = PostgreSQLDatabase.executePreparedSelect("SELECT d.datname as name, pg_catalog.pg_get_userbyid(d.datdba) as owner FROM pg_catalog.pg_database d WHERE d.datname = ?", ImmutableMap.of(1, databaseName));
190 | String owner = pgRoleIsDatabaseOwnerResult.get("owner");
191 | return (owner != null) ? owner.equals(roleName) : false;
192 | }
193 | }
--------------------------------------------------------------------------------
/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | security.user.password: password
2 | service_id: pg
3 | plan_id: postgresql-basic-plan
4 | MASTER_JDBC_URL: jdbc:postgresql://localhost:5432/travis_ci_test?user=postgres&password=
--------------------------------------------------------------------------------