Make update service operations return when complete.

This commit is contained in:
Scott Frederick
2018-12-11 21:28:20 -06:00
committed by Roy Clarkson
parent c504576793
commit 9487a8d793
9 changed files with 311 additions and 82 deletions

View File

@@ -84,7 +84,16 @@ class UpdateInstanceWithServicesAcceptanceTest extends CloudFoundryAcceptanceTes
parameters.put("parameter3", "value3");
updateServiceInstance(SI_NAME, parameters);
// the services are still bound to it
Optional<ServiceInstanceSummary> updatedServiceInstance = getServiceInstance(SI_NAME);
assertThat(updatedServiceInstance).hasValueSatisfying(value ->
assertThat(value.getLastOperation()).contains("completed"));
// then a backing application is re-deployed
Optional<ApplicationSummary> updatedBackingApplication = getApplicationSummaryByName(APP_NAME);
assertThat(updatedBackingApplication).hasValueSatisfying(app ->
assertThat(app.getRunningInstances()).isEqualTo(1));
// and the services are still bound to it
Optional<ServiceInstanceSummary> backingServiceInstanceUpdated = getServiceInstance(BACKING_SI_NAME);
assertThat(backingServiceInstanceUpdated).hasValueSatisfying(instance ->
assertThat(instance.getApplications()).contains(APP_NAME));

View File

@@ -17,11 +17,14 @@
package org.springframework.cloud.appbroker.acceptance.fixtures.cf;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceResponse;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
import org.cloudfoundry.operations.applications.ApplicationDetail;
@@ -40,11 +43,15 @@ import org.cloudfoundry.operations.serviceadmin.DeleteServiceBrokerRequest;
import org.cloudfoundry.operations.serviceadmin.EnableServiceAccessRequest;
import org.cloudfoundry.operations.services.CreateServiceInstanceRequest;
import org.cloudfoundry.operations.services.DeleteServiceInstanceRequest;
import org.cloudfoundry.operations.services.GetServiceInstanceRequest;
import org.cloudfoundry.operations.services.ServiceInstance;
import org.cloudfoundry.operations.services.ServiceInstanceSummary;
import org.cloudfoundry.operations.services.UpdateServiceInstanceRequest;
import org.cloudfoundry.operations.spaces.CreateSpaceRequest;
import org.cloudfoundry.operations.spaces.SpaceSummary;
import org.cloudfoundry.operations.spaces.Spaces;
import org.cloudfoundry.util.LastOperationUtils;
import org.cloudfoundry.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
@@ -60,11 +67,14 @@ public class CloudFoundryService {
private static final Logger LOGGER = LoggerFactory.getLogger(CloudFoundryService.class);
private final CloudFoundryOperations cloudFoundryOperations;
private final CloudFoundryClient cloudFoundryClient;
private final CloudFoundryProperties cloudFoundryProperties;
public CloudFoundryService(CloudFoundryOperations cloudFoundryOperations,
CloudFoundryClient cloudFoundryClient,
CloudFoundryProperties cloudFoundryProperties) {
this.cloudFoundryOperations = cloudFoundryOperations;
this.cloudFoundryClient = cloudFoundryClient;
this.cloudFoundryProperties = cloudFoundryProperties;
}
@@ -174,6 +184,12 @@ public class CloudFoundryService {
.serviceInstanceName(serviceInstanceName)
.parameters(parameters)
.build())
.then(cloudFoundryOperations.services()
.getInstance(GetServiceInstanceRequest.builder()
.name(serviceInstanceName)
.build()))
.map(ServiceInstance::getId)
.flatMap(this::waitForUpdateInstance)
.doOnSuccess(item -> LOGGER.info("Updated service instance " + serviceInstanceName))
.doOnError(error -> LOGGER.error("Error updating service instance " + serviceInstanceName + ": " + error));
}
@@ -298,6 +314,21 @@ public class CloudFoundryService {
.build();
}
private Mono<Void> waitForUpdateInstance(String serviceInstanceId) {
return LastOperationUtils
.waitForCompletion(Duration.ofMinutes(5), () ->
requestGetServiceInstance(cloudFoundryClient, serviceInstanceId)
.map(response -> ResourceUtils.getEntity(response).getLastOperation()));
}
private Mono<GetServiceInstanceResponse> requestGetServiceInstance(CloudFoundryClient cloudFoundryClient,
String serviceInstanceId) {
return cloudFoundryClient.serviceInstances()
.get(org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceRequest.builder()
.serviceInstanceId(serviceInstanceId)
.build());
}
private Map<String, String> appBrokerDeployerEnvironmentVariables() {
Map<String, String> deployerVariables = new HashMap<>();
deployerVariables.put("spring.cloud.appbroker.deployer.cloudfoundry.api-host",

View File

@@ -35,6 +35,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.cloudfoundry.AbstractCloudFoundryException;
import org.cloudfoundry.UnknownCloudFoundryException;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceResponse;
import org.cloudfoundry.client.v2.spaces.CreateSpaceRequest;
import org.cloudfoundry.client.v2.spaces.DeleteSpaceRequest;
import org.cloudfoundry.operations.CloudFoundryOperations;
@@ -52,6 +53,8 @@ import org.cloudfoundry.operations.services.ServiceInstance;
import org.cloudfoundry.operations.services.UnbindServiceInstanceRequest;
import org.cloudfoundry.operations.spaces.GetSpaceRequest;
import org.cloudfoundry.operations.spaces.SpaceDetail;
import org.cloudfoundry.util.LastOperationUtils;
import org.cloudfoundry.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.Exceptions;
@@ -82,6 +85,8 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
private final Logger logger = LoggerFactory.getLogger(CloudFoundryAppDeployer.class);
private static final Duration ASYNC_OPERATION_TIMEOUT = Duration.ofMinutes(5);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final CloudFoundryDeploymentProperties defaultDeploymentProperties;
@@ -552,9 +557,19 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
.name(request.getServiceInstanceName())
.build());
return getOperations(request.getProperties())
.services()
CloudFoundryOperations operations = getOperations(request.getProperties());
return operations.services()
.updateInstance(updateServiceInstanceRequest)
// for consistency with the createServiceInstance() and deleteServiceInstance() methods,
// this code must wait for the update operation to complete (with either a succeeded or failed status)
// before returning, until this waiting logic is implemented in CF Java Client
// https://github.com/cloudfoundry/cf-java-client/issues/929
.then(operations.services()
.getInstance(GetServiceInstanceRequest.builder()
.name(request.getServiceInstanceName())
.build()))
.map(ServiceInstance::getId)
.flatMap(this::waitForUpdateInstance)
.then(updateServiceInstanceResponseMono);
}
@@ -599,4 +614,19 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
return this.operations;
}
}
private Mono<Void> waitForUpdateInstance(String serviceInstanceId) {
return LastOperationUtils
.waitForCompletion(ASYNC_OPERATION_TIMEOUT, () ->
requestGetServiceInstance(client, serviceInstanceId)
.map(response -> ResourceUtils.getEntity(response).getLastOperation()));
}
private Mono<GetServiceInstanceResponse> requestGetServiceInstance(CloudFoundryClient cloudFoundryClient,
String serviceInstanceId) {
return cloudFoundryClient.serviceInstances()
.get(org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceRequest.builder()
.serviceInstanceId(serviceInstanceId)
.build());
}
}

View File

@@ -20,6 +20,10 @@ import java.io.File;
import java.util.ArrayList;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceResponse;
import org.cloudfoundry.client.v2.serviceinstances.LastOperation;
import org.cloudfoundry.client.v2.serviceinstances.ServiceInstanceEntity;
import org.cloudfoundry.client.v2.serviceinstances.ServiceInstances;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.applications.ApplicationHealthCheck;
import org.cloudfoundry.operations.applications.ApplicationManifest;
@@ -69,13 +73,16 @@ class CloudFoundryAppDeployerTest {
private AppDeployer appDeployer;
@Mock
private Applications applications;
private Applications operationsApplications;
@Mock
private Services services;
private Services operationsServices;
@Mock
private Spaces spaces;
private Spaces operationsSpaces;
@Mock
private ServiceInstances clientServiceInstances;
@Mock
private CloudFoundryOperations cloudFoundryOperations;
@@ -93,12 +100,13 @@ class CloudFoundryAppDeployerTest {
deploymentProperties = new CloudFoundryDeploymentProperties();
CloudFoundryTargetProperties targetProperties = new CloudFoundryTargetProperties();
when(applications.pushManifest(any())).thenReturn(Mono.empty());
when(cloudFoundryOperations.applications()).thenReturn(applications);
when(operationsApplications.pushManifest(any())).thenReturn(Mono.empty());
when(resourceLoader.getResource(APP_PATH)).thenReturn(new FileSystemResource(APP_PATH));
when(cloudFoundryOperations.services()).thenReturn(services);
when(cloudFoundryOperations.spaces()).thenReturn(spaces);
when(cloudFoundryOperations.spaces()).thenReturn(operationsSpaces);
when(cloudFoundryOperations.applications()).thenReturn(operationsApplications);
when(cloudFoundryOperations.services()).thenReturn(operationsServices);
when(cloudFoundryClient.serviceInstances()).thenReturn(clientServiceInstances);
appDeployer = new CloudFoundryAppDeployer(deploymentProperties,
cloudFoundryOperations, cloudFoundryClient, targetProperties, resourceLoader);
@@ -120,7 +128,7 @@ class CloudFoundryAppDeployerTest {
.path(new File(APP_PATH).toPath())
.build();
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
verify(operationsApplications).pushManifest(argThat(matchesManifest(expectedManifest)));
}
@Test
@@ -157,7 +165,7 @@ class CloudFoundryAppDeployerTest {
.noRoute(true)
.build();
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
verify(operationsApplications).pushManifest(argThat(matchesManifest(expectedManifest)));
}
@Test
@@ -193,7 +201,7 @@ class CloudFoundryAppDeployerTest {
.host("host")
.build();
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
verify(operationsApplications).pushManifest(argThat(matchesManifest(expectedManifest)));
}
@Test
@@ -239,7 +247,7 @@ class CloudFoundryAppDeployerTest {
.noRoute(true)
.build();
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
verify(operationsApplications).pushManifest(argThat(matchesManifest(expectedManifest)));
}
@Test
@@ -265,7 +273,7 @@ class CloudFoundryAppDeployerTest {
.environmentVariable("SPRING_APPLICATION_JSON", "{\"ENV_VAR_2\":\"value2\",\"ENV_VAR_1\":\"value1\"}")
.build();
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
verify(operationsApplications).pushManifest(argThat(matchesManifest(expectedManifest)));
}
@Test
@@ -292,18 +300,18 @@ class CloudFoundryAppDeployerTest {
.environmentVariable("ENV_VAR_2", "value2")
.build();
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
verify(operationsApplications).pushManifest(argThat(matchesManifest(expectedManifest)));
}
@Test
void deleteServiceInstanceShouldUnbindServices() {
when(services.deleteInstance(
when(operationsServices.deleteInstance(
org.cloudfoundry.operations.services.DeleteServiceInstanceRequest.builder()
.name("service-instance-name")
.build()))
.thenReturn(Mono.empty());
when(services.getInstance(GetServiceInstanceRequest.builder().name("service-instance-name").build()))
when(operationsServices.getInstance(GetServiceInstanceRequest.builder().name("service-instance-name").build()))
.thenReturn(Mono.just(ServiceInstance.builder()
.id("siid")
.type(ServiceInstanceType.MANAGED)
@@ -311,13 +319,13 @@ class CloudFoundryAppDeployerTest {
.applications("app1", "app2")
.build()));
when(services.unbind(UnbindServiceInstanceRequest.builder()
when(operationsServices.unbind(UnbindServiceInstanceRequest.builder()
.serviceInstanceName("service-instance-name")
.applicationName("app1")
.build()))
.thenReturn(Mono.empty());
when(services.unbind(UnbindServiceInstanceRequest.builder()
when(operationsServices.unbind(UnbindServiceInstanceRequest.builder()
.serviceInstanceName("service-instance-name")
.applicationName("app2")
.build()))
@@ -338,7 +346,7 @@ class CloudFoundryAppDeployerTest {
@Test
void createServiceInstance() {
when(services.createInstance(
when(operationsServices.createInstance(
org.cloudfoundry.operations.services.CreateServiceInstanceRequest.builder()
.serviceInstanceName("service-instance-name")
.serviceName("db-service")
@@ -363,23 +371,44 @@ class CloudFoundryAppDeployerTest {
@Test
void updateServiceInstance() {
when(services.updateInstance(
when(operationsServices.updateInstance(
org.cloudfoundry.operations.services.UpdateServiceInstanceRequest.builder()
.serviceInstanceName("service-instance-name")
.parameters(emptyMap())
.build()))
.serviceInstanceName("service-instance-name")
.parameters(emptyMap())
.build()))
.thenReturn(Mono.empty());
when(operationsServices.getInstance(GetServiceInstanceRequest.builder()
.name("service-instance-name")
.build()))
.thenReturn(Mono.just(ServiceInstance.builder()
.name("service-instance-name")
.id("service-instance-guid")
.type(ServiceInstanceType.MANAGED)
.build()));
when(clientServiceInstances.get(
org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceRequest.builder()
.serviceInstanceId("service-instance-guid")
.build()))
.thenReturn(Mono.just(GetServiceInstanceResponse.builder()
.entity(ServiceInstanceEntity.builder()
.lastOperation(LastOperation.builder()
.state("succeeded")
.build())
.build())
.build()));
UpdateServiceInstanceRequest request =
UpdateServiceInstanceRequest.builder()
.serviceInstanceName("service-instance-name")
.parameters(emptyMap())
.build();
.serviceInstanceName("service-instance-name")
.parameters(emptyMap())
.build();
StepVerifier.create(
appDeployer.updateServiceInstance(request))
.assertNext(response -> assertThat(response.getName()).isEqualTo("service-instance-name"))
.verifyComplete();
.assertNext(response -> assertThat(response.getName()).isEqualTo("service-instance-name"))
.verifyComplete();
}
private ApplicationManifest.Builder baseManifest() {

View File

@@ -66,6 +66,8 @@ class UpdateInstanceWithServicesParametersComponentTest extends WiremockComponen
cloudControllerFixture.stubUpdateApp(APP_NAME);
cloudControllerFixture.stubServiceInstanceExists(SERVICE_INSTANCE_NAME);
cloudControllerFixture.stubListServiceBindings(APP_NAME, SERVICE_INSTANCE_NAME);
cloudControllerFixture.stubServiceBindingExists(APP_NAME, SERVICE_INSTANCE_NAME);
// will update with filtered parameters and bind the service instance
HashMap<String, Object> expectedCreationParameters = new HashMap<>();

View File

@@ -26,6 +26,7 @@ import org.springframework.boot.test.context.TestComponent;
import static com.github.tomakehurst.wiremock.client.WireMock.created;
import static com.github.tomakehurst.wiremock.client.WireMock.delete;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
import static com.github.tomakehurst.wiremock.client.WireMock.noContent;
@@ -120,20 +121,26 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
}
public void stubAppDoesNotExistInSpace(final String appName, final String space) {
stubFor(get(urlEqualTo("/v2/spaces/" + space + "/apps?q=name:" + appName + "&page=1"))
stubFor(get(urlPathEqualTo("/v2/spaces/" + space + "/apps"))
.withQueryParam("q", equalTo("name:" + appName))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("empty-query-results"))));
stubFor(post(urlPathEqualTo("/v2/spaces"))
.willReturn(ok()));
stubFor(get(urlEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/apps?q=name:" + appName + "&page=1"))
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/apps"))
.withQueryParam("q", equalTo("name:" + appName))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("empty-query-results"))));
}
public void stubAppExists(final String appName) {
stubFor(get(urlEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/apps?q=name:" + appName + "&page=1"))
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/apps"))
.withQueryParam("q", equalTo("name:" + appName))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("list-space-apps",
replace("@guid", appGuid(appName)),
@@ -186,7 +193,7 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
}
private void stubCreateAppMetadata(String appName, ContentPattern<?>... appMetadataPatterns) {
MappingBuilder mappingBuilder = post(urlEqualTo("/v2/apps"))
MappingBuilder mappingBuilder = post(urlPathEqualTo("/v2/apps"))
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + appName + "')]"));
for (ContentPattern<?> appMetadataPattern : appMetadataPatterns) {
mappingBuilder.withRequestBody(appMetadataPattern);
@@ -199,7 +206,7 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
}
private void stubUpdateAppMetadata(String appName, ContentPattern<?>... appMetadataPatterns) {
MappingBuilder mappingBuilder = put(urlEqualTo("/v2/apps/" + appGuid(appName)))
MappingBuilder mappingBuilder = put(urlPathEqualTo("/v2/apps/" + appGuid(appName)))
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + appName + "')]"));
for (ContentPattern<?> appMetadataPattern : appMetadataPatterns) {
mappingBuilder.withRequestBody(appMetadataPattern);
@@ -216,18 +223,21 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
.willReturn(ok()
.withBody(cc("empty-query-results"))));
stubFor(get(urlEqualTo("/v2/routes?q=domain_guid:" + TEST_ORG_GUID + "&q=host:" + host + "&page=1"))
stubFor(get(urlPathEqualTo("/v2/routes"))
.withQueryParam("q", equalTo("domain_guid:" + TEST_ORG_GUID))
.withQueryParam("q", equalTo("host:" + host))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("empty-query-results"))));
stubFor(post(urlEqualTo("/v2/routes"))
stubFor(post(urlPathEqualTo("/v2/routes"))
.withRequestBody(matchingJsonPath("$.[?(@.host == '" + host + "')]"))
.willReturn(created()
.withBody(cc("list-routes",
replace("@name", appName),
replace("@guid", routeGuid(appName))))));
stubFor(put(urlEqualTo("/v2/apps/" + appGuid(appName) + "/routes/" + routeGuid(appName)))
stubFor(put(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/routes/" + routeGuid(appName)))
.willReturn(created()
.withBody(cc("get-app-STOPPED",
replace("@name", appName),
@@ -235,26 +245,27 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
}
private void stubUploadAppBits(String appName) {
stubFor(put(urlEqualTo("/v2/resource_match"))
stubFor(put(urlPathEqualTo("/v2/resource_match"))
.withMetadata(optionalStubMapping())
.willReturn(ok()
.withBody("[]")));
stubFor(put(urlEqualTo("/v2/apps/" + appGuid(appName) + "/bits?async=true"))
stubFor(put(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/bits"))
.withQueryParam("async", equalTo("true"))
.willReturn(created()
.withBody(cc("put-app-bits",
replace("@guid", appName + "-JOB-GUID")))));
}
private void stubInitializeAppState(String appName) {
stubFor(put(urlEqualTo("/v2/apps/" + appGuid(appName)))
stubFor(put(urlPathEqualTo("/v2/apps/" + appGuid(appName)))
.withRequestBody(matchingJsonPath("$.[?(@.state == 'STOPPED')]"))
.willReturn(created()
.withBody(cc("get-app-STOPPED",
replace("@name", appName),
replace("@guid", appGuid(appName))))));
stubFor(put(urlEqualTo("/v2/apps/" + appGuid(appName)))
stubFor(put(urlPathEqualTo("/v2/apps/" + appGuid(appName)))
.withRequestBody(matchingJsonPath("$.[?(@.state == 'STARTED')]"))
.willReturn(created()
.withBody(cc("get-app-STARTED",
@@ -263,11 +274,11 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
}
private void stubCheckAppState(String appName) {
stubFor(get(urlEqualTo("/v2/apps/" + appGuid(appName)))
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName)))
.willReturn(ok()
.withBody(cc("get-app-STAGED"))));
stubFor(get(urlEqualTo("/v2/apps/" + appGuid(appName) + "/instances"))
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/instances"))
.willReturn(ok()
.withBody(cc("get-app-instances"))));
}
@@ -283,72 +294,109 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
}
public void stubServiceInstanceExists(String serviceInstanceName) {
stubFor(get(urlEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/service_instances" +
"?q=name:" + serviceInstanceName +
"&page=1" +
"&return_user_provided_service_instances=true"))
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/service_instances"))
.withQueryParam("q", equalTo("name:" + serviceInstanceName))
.withQueryParam("page", equalTo("1"))
.withQueryParam("return_user_provided_service_instances", equalTo("true"))
.willReturn(ok()
.withBody(cc("list-space-service_instances",
replace("@space-guid", TEST_SPACE_GUID),
replace("@name", serviceInstanceName),
replace("@guid", serviceInstanceName + "-GUID")))));
stubFor(get(urlPathEqualTo("/v2/service_instances/" + serviceInstanceGuid(serviceInstanceName)))
.willReturn(ok()
.withBody(cc("get-service_instances",
replace("@space-guid", TEST_SPACE_GUID),
replace("@name", serviceInstanceName),
replace("@guid", serviceInstanceName + "-GUID")))));
}
public void stubServiceInstanceDoesNotExists(String serviceInstanceName) {
stubFor(get(urlEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/service_instances" +
"?q=name:" + serviceInstanceName +
"&page=1" +
"&return_user_provided_service_instances=true"))
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/service_instances"))
.withQueryParam("q", equalTo("name:" + serviceInstanceName))
.withQueryParam("page", equalTo("1"))
.withQueryParam("return_user_provided_service_instances", equalTo("true"))
.willReturn(ok()
.withBody(cc("list-space-service_instances-empty"))));
}
public void stubServiceExists(String serviceName) {
stubFor(get(urlEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/services" +
"?q=label:" + serviceName +
"&page=1"))
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/services"))
.withQueryParam("q", equalTo("label:" + serviceName))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("list-space-services"))));
stubFor(get(urlEqualTo("/v2/service_plans?q=service_guid:SERVICE-ID&page=1"))
stubFor(get(urlPathEqualTo("/v2/service_plans"))
.withQueryParam("q", equalTo("service_guid:SERVICE-ID"))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("list-service-plans"))));
}
public void stubCreateServiceInstance(String serviceInstanceName) {
stubFor(post(urlEqualTo("/v2/service_instances?accepts_incomplete=true"))
stubFor(post(urlPathEqualTo("/v2/service_instances"))
.withQueryParam("accepts_incomplete", equalTo("true"))
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + serviceInstanceName + "')]"))
.willReturn(ok()));
}
public void stubCreateServiceInstanceWithParameters(String serviceInstanceName, Map<String, Object> params) {
stubFor(post(urlEqualTo("/v2/service_instances?accepts_incomplete=true"))
stubFor(post(urlPathEqualTo("/v2/service_instances"))
.withQueryParam("accepts_incomplete", equalTo("true"))
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + serviceInstanceName + "')]"))
.withRequestBody(matchingJsonPath("$.[?(@.parameters == " + new JSONObject(params) + ")]"))
.willReturn(ok()));
}
public void stubUpdateServiceInstanceWithParameters(String serviceInstanceName, Map<String, Object> params) {
String serviceInstanceGuid = serviceInstanceName + "-GUID";
stubFor(put(urlEqualTo("/v2/service_instances/" + serviceInstanceGuid + "?accepts_incomplete=true"))
stubFor(put(urlPathEqualTo("/v2/service_instances/" + serviceInstanceGuid(serviceInstanceName)))
.withQueryParam("accepts_incomplete", equalTo("true"))
.withRequestBody(matchingJsonPath("$.[?(@.parameters == " + new JSONObject(params) + ")]"))
.willReturn(ok()));
}
public void stubCreateServiceBinding(String appName, String serviceInstanceName) {
String serviceInstanceGuid = serviceInstanceName + "-GUID";
String serviceBindingGuid = appGuid(appName) + "-" + serviceInstanceGuid;
String serviceInstanceGuid = serviceInstanceGuid(serviceInstanceName);
String serviceBindingGuid = serviceBindingGuid(appName, serviceInstanceName);
stubFor(post(urlEqualTo("/v2/service_bindings"))
stubFor(post(urlPathEqualTo("/v2/service_bindings"))
.withRequestBody(matchingJsonPath("$.[?(@.app_guid == '" + appGuid(appName) + "')]"))
.withRequestBody(matchingJsonPath("$.[?(@.service_instance_guid == '" + serviceInstanceGuid + "')]"))
.willReturn(created()
.withBody(cc("get-service_bindings",
replace("@guid", serviceBindingGuid),
replace("@app-guid", appGuid(appName)),
replace("@service-instance-guid", serviceInstanceGuid)))));
}
public void stubListServiceBindings(String appName, String serviceInstanceName) {
String serviceInstanceGuid = serviceInstanceGuid(serviceInstanceName);
String serviceBindingGuid = serviceBindingGuid(appName, serviceInstanceName);
stubFor(get(urlPathEqualTo("/v2/service_bindings"))
.withQueryParam("q", equalTo("service_instance_guid:" + serviceInstanceGuid))
.withQueryParam("page", equalTo("1"))
.willReturn(ok()
.withBody(cc("list-service-bindings",
replace("@guid", serviceBindingGuid),
replace("@app-guid", appGuid(appName)),
replace("@service-instance-guid", serviceInstanceGuid)))));
}
public void stubServiceBindingExists(String appName, String serviceInstanceName) {
String serviceInstanceGuid = serviceInstanceGuid(serviceInstanceName);
String serviceBindingGuid = serviceBindingGuid(appName, serviceInstanceName);
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/service_bindings"))
.willReturn(ok()
.withBody(cc("get-service_bindings",
replace("@guid", serviceBindingGuid),
replace("@app-guid", appGuid(appName)),
replace("@service-instance-guid", serviceInstanceGuid)))));
}
public void stubServiceBindingDoesNotExist(String appName) {
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/service_bindings"))
.willReturn(ok()
@@ -374,4 +422,12 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
private String stackGuid(String appName) {
return appName + "-STACK-GUID";
}
private String serviceInstanceGuid(String serviceInstanceName) {
return serviceInstanceName + "-GUID";
}
private String serviceBindingGuid(String appName, String serviceInstanceName) {
return appGuid(appName) + "-" + serviceInstanceGuid(serviceInstanceName);
}
}

View File

@@ -0,0 +1,21 @@
{
"entity": {
"app_guid": "@app-guid",
"app_url": "/v2/apps/@app-guid",
"binding_options": {},
"credentials": {},
"gateway_data": null,
"gateway_name": "",
"name": null,
"service_instance_guid": "@service-instance-guid",
"service_instance_url": "/v2/service_instances/@service-instance-guid",
"syslog_drain_url": "",
"volume_mounts": null
},
"metadata": {
"created_at": "2018-08-17T22:01:54Z",
"guid": "@guid",
"updated_at": "2018-08-17T22:01:54Z",
"url": "/v2/service_bindings/@guid"
}
}

View File

@@ -0,0 +1,35 @@
{
"metadata": {
"guid": "@guid",
"url": "/v2/service_instances/@guid",
"created_at": "2016-06-08T16:41:29Z",
"updated_at": "2016-06-08T16:41:26Z"
},
"entity": {
"name": "@name",
"credentials": {},
"service_guid": "a14baddf-1ccc-5299-0152-ab9s49de4422",
"service_plan_guid": "779d2df0-9cdd-48e8-9781-ea05301cedb1",
"space_guid": "@space-guid",
"gateway_data": null,
"dashboard_url": null,
"type": "managed_service_instance",
"last_operation": {
"type": "create",
"state": "succeeded",
"description": "service broker-provided description",
"updated_at": "2016-06-08T16:41:29Z",
"created_at": "2016-06-08T16:41:29Z"
},
"tags": [],
"space_url": "/v2/spaces/@space-guid",
"service_url": "/v2/services/a14baddf-1ccc-5299-0152-ab9s49de4422",
"service_plan_url": "/v2/service_plans/779d2df0-9cdd-48e8-9781-ea05301cedb1",
"service_bindings_url": "/v2/service_instances/@guid/service_bindings",
"service_keys_url": "/v2/service_instances/@guid/service_keys",
"routes_url": "/v2/service_instances/@guid/routes",
"shared_from_url": "/v2/service_instances/@guid/shared_from",
"shared_to_url": "/v2/service_instances/@guid/shared_to",
"service_instance_parameters_url": "/v2/service_instances/@guid/parameters"
}
}

View File

@@ -1,21 +1,37 @@
{
"entity": {
"app_guid": "@app-guid",
"app_url": "/v2/apps/@app-guid",
"binding_options": {},
"credentials": {},
"gateway_data": null,
"gateway_name": "",
"name": null,
"service_instance_guid": "@service-instance-guid",
"service_instance_url": "/v2/service_instances/@service-instance-guid",
"syslog_drain_url": "",
"volume_mounts": null
},
"metadata": {
"created_at": "2018-08-17T22:01:54Z",
"guid": "@guid",
"updated_at": "2018-08-17T22:01:54Z",
"url": "/v2/service_bindings/@guid"
}
"total_results": 1,
"total_pages": 1,
"prev_url": null,
"next_url": null,
"resources": [
{
"metadata": {
"guid": "@guid",
"url": "/v2/service_bindings/@guid",
"created_at": "2016-06-08T16:41:43Z",
"updated_at": "2016-06-08T16:41:26Z"
},
"entity": {
"app_guid": "@app-guid",
"service_instance_guid": "@service-instance-guid",
"credentials": {},
"binding_options": {},
"gateway_data": null,
"gateway_name": "",
"syslog_drain_url": null,
"volume_mounts": [],
"name": "prod-db",
"last_operation": {
"type": "create",
"state": "succeeded",
"description": "",
"updated_at": "2018-02-28T16:25:19Z",
"created_at": "2018-02-28T16:25:19Z"
},
"app_url": "/v2/apps/@app-guid",
"service_instance_url": "/v2/service_instances/@service-instance-guid",
"service_binding_parameters_url": "/v2/service_bindings/@guid/parameters"
}
}
]
}