Set target on bound services so deleteServiceInstance can find the right service
Also temporarily disable delete space on deleteServiceInstance Connects to #413
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.acceptance;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.cloudfoundry.operations.applications.ApplicationSummary;
|
||||
import org.cloudfoundry.operations.services.ServiceInstance;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class UpdateInstanceWithNewServiceAndTargetAcceptanceTest extends CloudFoundryAcceptanceTest {
|
||||
|
||||
private static final String APP_NAME = "app-new-service";
|
||||
|
||||
private static final int FIRST_TEST = 1;
|
||||
|
||||
private static final int SECOND_TEST = 2;
|
||||
|
||||
private static final String SI_NAME = "si-new-service";
|
||||
|
||||
private static final String OLD_BACKING_SI_NAME = "backing-service-instance-old";
|
||||
|
||||
private static final String NEW_BACKING_SI_NAME = "backing-service-instance-new";
|
||||
|
||||
private static final String SUFFIX = "update-with-new-services-and-target";
|
||||
|
||||
private static final String APP_SERVICE_NAME = "app-service-" + SUFFIX;
|
||||
|
||||
private static final String BACKING_SERVICE_NAME = "backing-service-" + SUFFIX;
|
||||
|
||||
|
||||
@Autowired
|
||||
private HealthListener healthListener;
|
||||
|
||||
@Override
|
||||
protected String testSuffix() {
|
||||
return SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String appServiceName() {
|
||||
return APP_SERVICE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String backingServiceName() {
|
||||
return BACKING_SERVICE_NAME;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("first")
|
||||
@Order(FIRST_TEST)
|
||||
@AppBrokerTestProperties({
|
||||
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,
|
||||
"spring.cloud.appbroker.services[0].plan-name=" + PLAN_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
|
||||
"spring.cloud.appbroker.services[0].apps[0].services[0].service-instance-name=" + OLD_BACKING_SI_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].services[0].name=" + BACKING_SERVICE_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].plan=" + PLAN_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].service-instance-name=" + OLD_BACKING_SI_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].target.name=SpacePerServiceInstance"
|
||||
})
|
||||
void weCreateAService() {
|
||||
// when a service instance is created
|
||||
createServiceInstance(SI_NAME);
|
||||
|
||||
// then a backing application is deployed
|
||||
String spaceName = getServiceInstanceGuid(SI_NAME);
|
||||
|
||||
Optional<ApplicationSummary> backingApplication = getApplicationSummary(APP_NAME, spaceName);
|
||||
assertThat(backingApplication).hasValueSatisfying(app -> assertThat(app.getRunningInstances()).isEqualTo(1));
|
||||
|
||||
// and the services are bound to it
|
||||
ServiceInstance backingServiceInstance = getBackingServiceInstance(OLD_BACKING_SI_NAME, spaceName);
|
||||
assertThat(backingServiceInstance.getApplications()).contains(APP_NAME);
|
||||
|
||||
String path = backingApplication.get().getUrls().get(0);
|
||||
healthListener.start(path);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(SECOND_TEST)
|
||||
@Tag("last")
|
||||
@AppBrokerTestProperties({
|
||||
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,
|
||||
"spring.cloud.appbroker.services[0].plan-name=" + PLAN_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
|
||||
"spring.cloud.appbroker.services[0].apps[0].services[0].service-instance-name=" + NEW_BACKING_SI_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].services[0].name=" + BACKING_SERVICE_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].plan=" + PLAN_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].service-instance-name=" + NEW_BACKING_SI_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].target.name=SpacePerServiceInstance"
|
||||
})
|
||||
void weUpdateTheServiceInstanceWithANewBackingService() {
|
||||
// when the service instance is updated with a new service
|
||||
updateServiceInstance(SI_NAME, Collections.emptyMap());
|
||||
String spaceName = getServiceInstanceGuid(SI_NAME);
|
||||
|
||||
// then the backing application was updated with zero downtime
|
||||
healthListener.stop();
|
||||
assertThat(healthListener.getFailures()).isEqualTo(0);
|
||||
assertThat(healthListener.getSuccesses()).isGreaterThan(0);
|
||||
|
||||
// then a backing application is re-deployed
|
||||
Optional<ApplicationSummary> updatedBackingApplication = getApplicationSummary(APP_NAME, spaceName);
|
||||
assertThat(updatedBackingApplication).hasValueSatisfying(app ->
|
||||
assertThat(app.getRunningInstances()).isEqualTo(1));
|
||||
|
||||
// and the new backing service is bound to it
|
||||
ServiceInstance newBackingServiceInstance = getBackingServiceInstance(NEW_BACKING_SI_NAME, spaceName);
|
||||
assertThat(newBackingServiceInstance.getApplications()).contains(APP_NAME);
|
||||
|
||||
// and the old backing service is deleted
|
||||
assertThat(listServiceInstances()).doesNotContain(OLD_BACKING_SI_NAME);
|
||||
|
||||
// then the service instance is deleted
|
||||
deleteServiceInstance(SI_NAME);
|
||||
|
||||
// and the backing service is deleted
|
||||
assertThat(listServiceInstances()).doesNotContain(NEW_BACKING_SI_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
void setUp(TestInfo testInfo, BrokerProperties brokerProperties) {
|
||||
if (testInfo.getTags().contains("first")) {
|
||||
super.setUp(testInfo, brokerProperties);
|
||||
}
|
||||
else {
|
||||
setUpForBrokerUpdate(brokerProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@AfterEach
|
||||
public void tearDown(TestInfo testInfo) {
|
||||
if (testInfo.getTags().contains("last")) {
|
||||
super.tearDown(testInfo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,9 +31,11 @@ import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingApplication;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingSpaceManagementService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.deployer.DefaultBackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.DefaultBackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.DefaultBackingSpaceManagementService;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployerClient;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialGenerator;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderFactory;
|
||||
@@ -324,6 +326,18 @@ public class AppBrokerAutoConfiguration {
|
||||
return new DefaultBackingServicesProvisionService(deployerClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@link BackingSpaceManagementService} bean
|
||||
*
|
||||
* @param deployerClient the DeployerClient bean
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BackingSpaceManagementService backingSpaceProvisionService(DeployerClient deployerClient) {
|
||||
return new DefaultBackingSpaceManagementService(deployerClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a {@link CreateServiceInstanceWorkflow} bean
|
||||
*
|
||||
@@ -401,6 +415,7 @@ public class AppBrokerAutoConfiguration {
|
||||
BrokeredServices brokeredServices, BackingAppDeploymentService backingAppDeploymentService,
|
||||
BackingAppManagementService backingAppManagementService,
|
||||
BackingServicesProvisionService backingServicesProvisionService,
|
||||
BackingSpaceManagementService backingSpaceManagementService,
|
||||
CredentialProviderService credentialProviderService, TargetService targetService) {
|
||||
|
||||
return new AppDeploymentDeleteServiceInstanceWorkflow(
|
||||
@@ -408,6 +423,7 @@ public class AppBrokerAutoConfiguration {
|
||||
backingAppDeploymentService,
|
||||
backingAppManagementService,
|
||||
backingServicesProvisionService,
|
||||
backingSpaceManagementService,
|
||||
credentialProviderService,
|
||||
targetService
|
||||
);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.deployer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
public interface BackingSpaceManagementService {
|
||||
|
||||
Flux<String> deleteTargetSpaces(List<String> targetSpaces);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.deployer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
import reactor.util.Logger;
|
||||
import reactor.util.Loggers;
|
||||
|
||||
public class DefaultBackingSpaceManagementService implements BackingSpaceManagementService {
|
||||
|
||||
private static final Logger LOG = Loggers.getLogger(DefaultBackingSpaceManagementService.class);
|
||||
|
||||
private static final String BACKINGSPACES_LOG_TEMPLATE = "backingSpaces={}";
|
||||
|
||||
private final DeployerClient deployerClient;
|
||||
|
||||
public DefaultBackingSpaceManagementService(DeployerClient deployerClient) {
|
||||
this.deployerClient = deployerClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<String> deleteTargetSpaces(List<String> targetSpaces) {
|
||||
return Flux.fromIterable(targetSpaces)
|
||||
.parallel()
|
||||
.runOn(Schedulers.parallel())
|
||||
.flatMap(deployerClient::deleteSpace)
|
||||
.sequential()
|
||||
.doOnRequest(l -> {
|
||||
LOG.info("Deleting backing spaces");
|
||||
LOG.debug(BACKINGSPACES_LOG_TEMPLATE, targetSpaces);
|
||||
})
|
||||
.doOnComplete(() -> {
|
||||
LOG.info("Finish deleting backing spaces");
|
||||
LOG.debug(BACKINGSPACES_LOG_TEMPLATE, targetSpaces);
|
||||
})
|
||||
.doOnError(e -> LOG.error(String.format("Error deleting backing spaces. error=%s", e.getMessage()), e));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -204,6 +204,29 @@ public class DeployerClient {
|
||||
.map(DeleteServiceInstanceResponse::getName);
|
||||
}
|
||||
|
||||
public Mono<String> deleteSpace(String spaceName) {
|
||||
return appDeployer
|
||||
.deleteBackingSpace(
|
||||
DeleteBackingSpaceRequest
|
||||
.builder()
|
||||
.name(spaceName)
|
||||
.build())
|
||||
.doOnRequest(l -> {
|
||||
LOG.info("Deleting backing space {}", spaceName);
|
||||
})
|
||||
.doOnSuccess(response -> {
|
||||
LOG.info("Success deleting backing space {}", spaceName);
|
||||
})
|
||||
.doOnError(e -> {
|
||||
LOG.error(String.format("Error deleting backing space. backingSpaceName=%s, error=%s",
|
||||
spaceName, e.getMessage()), e);
|
||||
})
|
||||
.onErrorReturn(DeleteBackingSpaceResponse.builder()
|
||||
.name(spaceName)
|
||||
.build())
|
||||
.map(DeleteBackingSpaceResponse::getName);
|
||||
}
|
||||
|
||||
private static UpdateApplicationRequest getUpdateApplicationRequest(BackingApplication backingApplication,
|
||||
String serviceInstanceId) {
|
||||
return UpdateApplicationRequest
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors
|
||||
* Copyright 2002-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -275,6 +275,7 @@ public class BackingAppManagementService {
|
||||
.builder()
|
||||
.name(response.getName())
|
||||
.services(services)
|
||||
.properties(app.getProperties())
|
||||
.environment(response.getEnvironment())
|
||||
.build()))
|
||||
.doOnRequest(l -> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.appbroker.workflow.instance;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -25,8 +26,10 @@ import reactor.util.Logger;
|
||||
import reactor.util.Loggers;
|
||||
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingApplication;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingSpaceManagementService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderService;
|
||||
@@ -52,21 +55,25 @@ public class AppDeploymentDeleteServiceInstanceWorkflow
|
||||
|
||||
private final BackingAppManagementService backingAppManagementService;
|
||||
|
||||
private final BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
private final BackingSpaceManagementService backingSpaceManagementService;
|
||||
|
||||
private final CredentialProviderService credentialProviderService;
|
||||
|
||||
private final TargetService targetService;
|
||||
|
||||
private final BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
public AppDeploymentDeleteServiceInstanceWorkflow(BrokeredServices brokeredServices,
|
||||
BackingAppDeploymentService deploymentService,
|
||||
BackingAppManagementService backingAppManagementService,
|
||||
BackingServicesProvisionService backingServicesProvisionService,
|
||||
BackingSpaceManagementService backingSpaceManagementService,
|
||||
CredentialProviderService credentialProviderService,
|
||||
TargetService targetService) {
|
||||
super(brokeredServices);
|
||||
this.deploymentService = deploymentService;
|
||||
this.backingAppManagementService = backingAppManagementService;
|
||||
this.backingSpaceManagementService = backingSpaceManagementService;
|
||||
this.credentialProviderService = credentialProviderService;
|
||||
this.targetService = targetService;
|
||||
this.backingServicesProvisionService = backingServicesProvisionService;
|
||||
@@ -75,36 +82,47 @@ public class AppDeploymentDeleteServiceInstanceWorkflow
|
||||
@Override
|
||||
public Mono<Void> delete(DeleteServiceInstanceRequest request, DeleteServiceInstanceResponse response) {
|
||||
return deleteBackingServices(request)
|
||||
.thenMany(undeployBackingApplications(request))
|
||||
.flatMapMany(Flux::fromIterable)
|
||||
.map(BackingService::getProperties)
|
||||
.concatWith(undeployBackingApplications(request)
|
||||
.flatMapMany(Flux::fromIterable)
|
||||
.map(BackingApplication::getProperties))
|
||||
.filter(properties ->
|
||||
properties != null && properties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY))
|
||||
.map(properties -> properties.get(DeploymentProperties.TARGET_PROPERTY_KEY))
|
||||
.distinct()
|
||||
.collectList()
|
||||
.flatMapMany(backingSpaceManagementService::deleteTargetSpaces)
|
||||
.then();
|
||||
}
|
||||
|
||||
private Flux<String> deleteBackingServices(DeleteServiceInstanceRequest request) {
|
||||
private Mono<List<BackingService>> deleteBackingServices(DeleteServiceInstanceRequest request) {
|
||||
return collectBackingServices(request)
|
||||
.collectList()
|
||||
.flatMapMany(backingServices -> {
|
||||
.delayUntil(backingServices -> {
|
||||
if (!CollectionUtils.isEmpty(backingServices)) {
|
||||
return backingServicesProvisionService.deleteServiceInstance(backingServices);
|
||||
return backingServicesProvisionService.deleteServiceInstance(backingServices)
|
||||
.doOnRequest(l -> {
|
||||
LOG.info("Deleting backing services. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnComplete(() -> {
|
||||
LOG.info("Finish deleting backing services. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnError(e -> {
|
||||
if (LOG.isErrorEnabled()) {
|
||||
LOG.error(String.format("Error deleting backing services. " +
|
||||
"serviceDefinitionName=%s, planName=%s, error=%s",
|
||||
request.getServiceDefinition().getName(),
|
||||
request.getPlan().getName(), e.getMessage()), e);
|
||||
}
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
});
|
||||
}
|
||||
return Flux.empty();
|
||||
})
|
||||
.doOnRequest(l -> {
|
||||
LOG.info("Deleting backing services. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnComplete(() -> {
|
||||
LOG.info("Finish deleting backing services. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnError(e -> {
|
||||
if (LOG.isErrorEnabled()) {
|
||||
LOG.error(String.format("Error deleting backing services. " +
|
||||
"serviceDefinitionName=%s, planName=%s, error=%s", request.getServiceDefinition().getName(),
|
||||
request.getPlan().getName(), e.getMessage()), e);
|
||||
}
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -144,7 +162,7 @@ public class AppDeploymentDeleteServiceInstanceWorkflow
|
||||
}));
|
||||
}
|
||||
|
||||
private Flux<String> undeployBackingApplications(DeleteServiceInstanceRequest request) {
|
||||
private Mono<List<BackingApplication>> undeployBackingApplications(DeleteServiceInstanceRequest request) {
|
||||
return getBackingApplicationsForService(request.getServiceDefinition(), request.getPlan())
|
||||
.flatMap(backingApps ->
|
||||
credentialProviderService.deleteCredentials(backingApps,
|
||||
@@ -153,25 +171,26 @@ public class AppDeploymentDeleteServiceInstanceWorkflow
|
||||
.flatMap(targetSpec -> targetService.addToBackingApplications(backingApps, targetSpec,
|
||||
request.getServiceInstanceId()))
|
||||
.defaultIfEmpty(backingApps))
|
||||
.flatMapMany(deploymentService::undeploy)
|
||||
.doOnRequest(l -> {
|
||||
LOG.info("Undeploying backing applications. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnComplete(() -> {
|
||||
LOG.info("Finish undeploying backing applications. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnError(e -> {
|
||||
if (LOG.isErrorEnabled()) {
|
||||
LOG.error(String.format("Error undeploying backing applications. serviceDefinitionName=%s, " +
|
||||
"planName=%s, error=%s", request.getServiceDefinition().getName(), request.getPlan().getName(),
|
||||
e.getMessage()), e);
|
||||
}
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
});
|
||||
.delayUntil(backingApps -> deploymentService.undeploy(backingApps)
|
||||
.doOnRequest(l -> {
|
||||
LOG.info("Undeploying backing applications. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnComplete(() -> {
|
||||
LOG.info("Finish undeploying backing applications. serviceDefinitionName={}, planName={}",
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName());
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
})
|
||||
.doOnError(e -> {
|
||||
if (LOG.isErrorEnabled()) {
|
||||
LOG.error(String.format("Error undeploying backing applications. serviceDefinitionName=%s, " +
|
||||
"planName=%s, error=%s", request.getServiceDefinition().getName(),
|
||||
request.getPlan().getName(),
|
||||
e.getMessage()), e);
|
||||
}
|
||||
LOG.debug(REQUEST_LOG_TEMPLATE, request);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.appbroker.workflow.instance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.cloud.appbroker.deployer.BackingApplication;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
|
||||
import org.springframework.cloud.appbroker.extensions.parameters.BackingApplicationsParametersTransformationService;
|
||||
import org.springframework.cloud.appbroker.extensions.parameters.BackingServicesParametersTransformationService;
|
||||
import org.springframework.cloud.appbroker.extensions.targets.TargetService;
|
||||
@@ -178,12 +180,22 @@ public class AppDeploymentUpdateServiceInstanceWorkflow extends AppDeploymentIns
|
||||
return backingAppManagementService.getDeployedBackingApplications(request.getServiceInstanceId(),
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName())
|
||||
.flatMapMany(Flux::fromIterable)
|
||||
.map(BackingApplication::getServices)
|
||||
.flatMap(Flux::fromIterable)
|
||||
.flatMap(backingApplication -> Flux
|
||||
.fromIterable(backingApplication.getServices())
|
||||
.map(servicesSpec -> {
|
||||
Map<String, String> properties = null;
|
||||
if (backingApplication.getProperties() != null) {
|
||||
String target = backingApplication.getProperties().get(DeploymentProperties.TARGET_PROPERTY_KEY);
|
||||
if (target != null) {
|
||||
properties = Collections.singletonMap(DeploymentProperties.TARGET_PROPERTY_KEY, target);
|
||||
}
|
||||
}
|
||||
return BackingService.builder()
|
||||
.serviceInstanceName(servicesSpec.getServiceInstanceName())
|
||||
.properties(properties)
|
||||
.build();
|
||||
}))
|
||||
.distinct()
|
||||
.map(servicesSpec -> BackingService.builder()
|
||||
.serviceInstanceName(servicesSpec.getServiceInstanceName())
|
||||
.build())
|
||||
.collectMap(BackingService::getServiceInstanceName, Function.identity());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.deployer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DefaultBackingSpaceManagementServiceTest {
|
||||
|
||||
@Mock
|
||||
private DeployerClient deployerClient;
|
||||
|
||||
private BackingSpaceManagementService backingSpaceManagementService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
backingSpaceManagementService = new DefaultBackingSpaceManagementService(deployerClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("UnassignedFluxMonoInstance")
|
||||
void deleteSpace() {
|
||||
final String spaceName1 = "space1";
|
||||
final String spaceName2 = "space2";
|
||||
doReturn(Mono.just("returned-space-1"))
|
||||
.when(deployerClient).deleteSpace(spaceName1);
|
||||
doReturn(Mono.just("returned-space-2"))
|
||||
.when(deployerClient).deleteSpace(spaceName2);
|
||||
|
||||
List<String> expectedValues = new ArrayList<>();
|
||||
expectedValues.add("returned-space-1");
|
||||
expectedValues.add("returned-space-2");
|
||||
|
||||
StepVerifier.create(backingSpaceManagementService.deleteTargetSpaces(asList(spaceName1, spaceName2)))
|
||||
// deployments are run in parallel, so the order of completion is not predictable
|
||||
// ensure that both expected signals are sent in any order
|
||||
.expectNextMatches(expectedValues::remove)
|
||||
.expectNextMatches(expectedValues::remove)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -420,4 +420,32 @@ class DeployerClientTest {
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class DeleteSpace {
|
||||
|
||||
private static final String RETURNED_SPACE_NAME = "space";
|
||||
|
||||
@Test
|
||||
void shouldDeleteSpace() {
|
||||
// given
|
||||
setupAppDeployer();
|
||||
|
||||
// when
|
||||
StepVerifier.create(deployerClient.deleteSpace("test-space"))
|
||||
// then
|
||||
.expectNext(RETURNED_SPACE_NAME)
|
||||
.verifyComplete();
|
||||
|
||||
then(appDeployer).should().deleteBackingSpace(argThat(space -> "test-space".equals(space.getName())));
|
||||
}
|
||||
|
||||
|
||||
private void setupAppDeployer() {
|
||||
given(appDeployer.deleteBackingSpace(any()))
|
||||
.willReturn(Mono.just(DeleteBackingSpaceResponse.builder()
|
||||
.name(RETURNED_SPACE_NAME)
|
||||
.build()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors
|
||||
* Copyright 2002-2021 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.appbroker.manager;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -68,6 +70,7 @@ class BackingAppManagementServiceTest {
|
||||
this.backingApps = BackingApplications.builder()
|
||||
.backingApplication(BackingApplication.builder()
|
||||
.name("testApp1")
|
||||
.properties(Collections.singletonMap("target", "customTarget"))
|
||||
.path("https://myfiles/app1.jar")
|
||||
.build())
|
||||
.backingApplication(BackingApplication.builder()
|
||||
@@ -344,6 +347,7 @@ class BackingAppManagementServiceTest {
|
||||
.expectNext(BackingApplications.builder()
|
||||
.backingApplication(BackingApplication.builder()
|
||||
.name("testApp1")
|
||||
.properties(Collections.singletonMap("target", "customTarget"))
|
||||
.services(
|
||||
ServicesSpec.builder().serviceInstanceName("service1").build(),
|
||||
ServicesSpec.builder().serviceInstanceName("service2").build())
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.appbroker.workflow.instance;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.cloud.appbroker.deployer.BackingApplications;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServices;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingSpaceManagementService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
|
||||
@@ -48,6 +50,9 @@ import org.springframework.cloud.servicebroker.model.catalog.ServiceDefinition;
|
||||
import org.springframework.cloud.servicebroker.model.instance.DeleteServiceInstanceRequest;
|
||||
import org.springframework.cloud.servicebroker.model.instance.DeleteServiceInstanceResponse;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -64,15 +69,18 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
@Mock
|
||||
private BackingAppManagementService backingAppManagementService;
|
||||
|
||||
@Mock
|
||||
private BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
@Mock
|
||||
private BackingSpaceManagementService backingSpaceManagementService;
|
||||
|
||||
@Mock
|
||||
private TargetService targetService;
|
||||
|
||||
@Mock
|
||||
private CredentialProviderService credentialProviderService;
|
||||
|
||||
@Mock
|
||||
private BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
private BackingApplications backingApps;
|
||||
|
||||
private BackingServices backingServices;
|
||||
@@ -116,7 +124,7 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
.name("my-service2")
|
||||
.plan("a-plan2")
|
||||
.serviceInstanceName("my-service-instance2")
|
||||
.properties(Collections.singletonMap(DeploymentProperties.TARGET_PROPERTY_KEY, "my-space2"))
|
||||
.properties(getPropertiesWithSpace("my-space2"))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@@ -153,7 +161,9 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
new AppDeploymentDeleteServiceInstanceWorkflow(
|
||||
brokeredServices,
|
||||
backingAppDeploymentService,
|
||||
backingAppManagementService, backingServicesProvisionService,
|
||||
backingAppManagementService,
|
||||
backingServicesProvisionService,
|
||||
backingSpaceManagementService,
|
||||
credentialProviderService,
|
||||
targetService
|
||||
);
|
||||
@@ -186,13 +196,56 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
return sizeMatch && nameMatch;
|
||||
}))).willReturn(Flux.just("my-service-instance"));
|
||||
|
||||
given(this.backingSpaceManagementService.deleteTargetSpaces(any())).willReturn(Flux.empty());
|
||||
|
||||
StepVerifier
|
||||
.create(deleteServiceInstanceWorkflow.delete(request, response))
|
||||
.expectNext()
|
||||
.expectNext()
|
||||
.verifyComplete();
|
||||
|
||||
verify(this.backingServicesProvisionService, Mockito.times(1)).deleteServiceInstance(any());
|
||||
verify(this.backingSpaceManagementService).deleteTargetSpaces(eq(emptyList()));
|
||||
verifyNoMoreInteractionsWithServices();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteBackingSpacesSpecifiedInTargetProperties() {
|
||||
DeleteServiceInstanceRequest request = buildRequest("service1", "plan1");
|
||||
DeleteServiceInstanceResponse response = DeleteServiceInstanceResponse.builder().build();
|
||||
String space1 = "CustomSpace1";
|
||||
String space2 = "CustomSpace2";
|
||||
|
||||
// configured backing services
|
||||
BackingServices servicesWithTarget = BackingServices.builder().backingServices(backingServices).build();
|
||||
servicesWithTarget.get(0).setProperties(getPropertiesWithSpace(space1));
|
||||
given(this.targetService.addToBackingServices(eq(backingServices), eq(targetSpec), eq("service-instance-id")))
|
||||
.willReturn(Mono.just(servicesWithTarget));
|
||||
|
||||
// configured backing apps
|
||||
BackingApplications appsWithTarget = BackingApplications.builder().backingApplications(backingApps).build();
|
||||
appsWithTarget.get(0).setProperties(getPropertiesWithSpace(space2));
|
||||
given(this.targetService.addToBackingApplications(eq(backingApps), eq(targetSpec), eq("service-instance-id")))
|
||||
.willReturn(Mono.just(appsWithTarget));
|
||||
|
||||
// services bound to deployed apps
|
||||
given(this.backingAppManagementService.getDeployedBackingApplications(request.getServiceInstanceId(),
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName()))
|
||||
.willReturn(Mono.just(getExistingBackingAppsWithService("my-service-instance")));
|
||||
given(this.credentialProviderService.deleteCredentials(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
|
||||
// delete in action
|
||||
given(this.backingAppDeploymentService.undeploy(eq(appsWithTarget)))
|
||||
.willReturn(Flux.just("undeployed1", "undeployed2"));
|
||||
given(this.backingServicesProvisionService.deleteServiceInstance(any()))
|
||||
.willReturn(Flux.just("my-service-instance"));
|
||||
given(this.backingSpaceManagementService.deleteTargetSpaces(any())).willReturn(Flux.just("space-name"));
|
||||
|
||||
StepVerifier
|
||||
.create(deleteServiceInstanceWorkflow.delete(request, response))
|
||||
.verifyComplete();
|
||||
|
||||
verify(this.backingServicesProvisionService, Mockito.times(1)).deleteServiceInstance(any());
|
||||
verify(this.backingSpaceManagementService).deleteTargetSpaces(Arrays.asList(space1, space2));
|
||||
verifyNoMoreInteractionsWithServices();
|
||||
}
|
||||
|
||||
@@ -228,6 +281,9 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
return sizeMatch && (nameMatch0 && spaceMatch0 || nameMatch1 && spaceMatch1);
|
||||
}))).willReturn(Flux.just("different-service-instance"));
|
||||
|
||||
given(this.backingSpaceManagementService.deleteTargetSpaces(eq(singletonList("my-space2"))))
|
||||
.willReturn(Flux.just("space-name"));
|
||||
|
||||
StepVerifier.create(deleteServiceInstanceWorkflow.delete(request, response))
|
||||
.expectNext()
|
||||
.expectNext()
|
||||
@@ -246,6 +302,8 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
request.getServiceDefinition().getName(), request.getPlan().getName()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
given(this.backingSpaceManagementService.deleteTargetSpaces(any())).willReturn(Flux.empty());
|
||||
|
||||
StepVerifier
|
||||
.create(deleteServiceInstanceWorkflow.delete(request, response))
|
||||
.verifyComplete();
|
||||
@@ -273,6 +331,8 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
return sizeMatch && nameMatch;
|
||||
}))).willReturn(Flux.just("my-service-instance"));
|
||||
|
||||
given(this.backingSpaceManagementService.deleteTargetSpaces(any())).willReturn(Flux.empty());
|
||||
|
||||
StepVerifier.create(deleteServiceInstanceWorkflow.delete(request, response))
|
||||
.expectNext()
|
||||
.expectNext()
|
||||
@@ -285,10 +345,15 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
private void verifyNoMoreInteractionsWithServices() {
|
||||
verifyNoMoreInteractions(this.backingServicesProvisionService);
|
||||
verifyNoMoreInteractions(this.backingAppDeploymentService);
|
||||
verifyNoMoreInteractions(this.backingSpaceManagementService);
|
||||
verifyNoMoreInteractions(this.credentialProviderService);
|
||||
verifyNoMoreInteractions(this.targetService);
|
||||
}
|
||||
|
||||
private Map<String, String> getPropertiesWithSpace(String customSpace) {
|
||||
return singletonMap(DeploymentProperties.TARGET_PROPERTY_KEY, customSpace);
|
||||
}
|
||||
|
||||
private DeleteServiceInstanceRequest buildRequest(String serviceName, String planName) {
|
||||
return DeleteServiceInstanceRequest
|
||||
.builder()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -207,6 +207,7 @@ class AppDeploymentUpdateServiceInstanceWorkflowTest {
|
||||
.builder()
|
||||
.backingService(BackingService
|
||||
.builder()
|
||||
.properties(singletonMap("target", "customTarget"))
|
||||
.serviceInstanceName("existing-service-instance")
|
||||
.build())
|
||||
.build());
|
||||
@@ -295,11 +296,15 @@ class AppDeploymentUpdateServiceInstanceWorkflowTest {
|
||||
}
|
||||
|
||||
private BackingApplications getExistingBackingAppsWithService(String serviceInstanceName) {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
properties.put("target", "customTarget");
|
||||
properties.put("not-important-property", "not-important-value");
|
||||
return BackingApplications
|
||||
.builder()
|
||||
.backingApplication(BackingApplication
|
||||
.builder()
|
||||
.name("app1")
|
||||
.properties(properties)
|
||||
.services(ServicesSpec
|
||||
.builder()
|
||||
.serviceInstanceName(serviceInstanceName)
|
||||
@@ -308,6 +313,7 @@ class AppDeploymentUpdateServiceInstanceWorkflowTest {
|
||||
.backingApplication(BackingApplication
|
||||
.builder()
|
||||
.name("app2")
|
||||
.properties(properties)
|
||||
.services(ServicesSpec
|
||||
.builder()
|
||||
.serviceInstanceName(serviceInstanceName)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -108,6 +108,8 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.cloud.appbroker.deployer.AppDeployer;
|
||||
import org.springframework.cloud.appbroker.deployer.CreateServiceInstanceRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.CreateServiceInstanceResponse;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteBackingSpaceRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteBackingSpaceResponse;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteServiceInstanceRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteServiceInstanceResponse;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployApplicationRequest;
|
||||
@@ -802,8 +804,7 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
|
||||
Mono<Void> requestDeleteApplication;
|
||||
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY)) {
|
||||
String space = deploymentProperties.get(DeploymentProperties.TARGET_PROPERTY_KEY);
|
||||
requestDeleteApplication = deleteApplicationInSpace(appName, space)
|
||||
.then(deleteSpace(space));
|
||||
requestDeleteApplication = deleteApplicationInSpace(appName, space);
|
||||
}
|
||||
else {
|
||||
requestDeleteApplication = deleteApplication(appName);
|
||||
@@ -840,19 +841,21 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
|
||||
.onErrorResume(e -> Mono.empty());
|
||||
}
|
||||
|
||||
private Mono<Void> deleteSpace(String spaceName) {
|
||||
@Override
|
||||
public Mono<DeleteBackingSpaceResponse> deleteBackingSpace(DeleteBackingSpaceRequest request) {
|
||||
String spaceName = request.getName();
|
||||
return getSpaceId(spaceName)
|
||||
.doOnError(e -> LOG.error(String.format("Unable to get space name. spaceName=%s, " + ERROR_LOG_TEMPLATE,
|
||||
spaceName, e.getMessage()), e))
|
||||
.onErrorResume(e -> Mono.empty())
|
||||
.flatMap(spaceId -> this.client.spaces()
|
||||
.delete(DeleteSpaceRequest.builder()
|
||||
.spaceId(spaceId)
|
||||
.recursive(true)
|
||||
.build())
|
||||
.then())
|
||||
.build()))
|
||||
.doOnError(e -> LOG.error(String.format("Error deleting space. spaceName=%s, " + ERROR_LOG_TEMPLATE,
|
||||
spaceName, e.getMessage()), e))
|
||||
.onErrorResume(e -> Mono.empty());
|
||||
.thenReturn(DeleteBackingSpaceResponse.builder().name(spaceName).build());
|
||||
}
|
||||
|
||||
private Mono<String> getSpaceId(String spaceName) {
|
||||
@@ -1185,11 +1188,9 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
|
||||
|
||||
Mono<Void> requestDeleteServiceInstance;
|
||||
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY)) {
|
||||
String space = deploymentProperties.get(DeploymentProperties.TARGET_PROPERTY_KEY);
|
||||
requestDeleteServiceInstance = operationsUtils.getOperations(deploymentProperties)
|
||||
.flatMap(cfOperations -> unbindServiceInstance(serviceInstanceName, cfOperations)
|
||||
.then(deleteServiceInstance(serviceInstanceName, cfOperations, deploymentProperties)))
|
||||
.then(deleteSpace(space));
|
||||
.then(deleteServiceInstance(serviceInstanceName, cfOperations, deploymentProperties)));
|
||||
}
|
||||
else {
|
||||
requestDeleteServiceInstance = unbindServiceInstance(serviceInstanceName, operations)
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.deployer.cloudfoundry;
|
||||
|
||||
import org.cloudfoundry.client.CloudFoundryClient;
|
||||
import org.cloudfoundry.client.v2.Metadata;
|
||||
import org.cloudfoundry.client.v2.organizations.ListOrganizationSpacesRequest;
|
||||
import org.cloudfoundry.client.v2.organizations.ListOrganizationSpacesResponse;
|
||||
import org.cloudfoundry.client.v2.spaces.DeleteSpaceRequest;
|
||||
import org.cloudfoundry.client.v2.spaces.SpaceEntity;
|
||||
import org.cloudfoundry.client.v2.spaces.SpaceResource;
|
||||
import org.cloudfoundry.operations.CloudFoundryOperations;
|
||||
import org.cloudfoundry.operations.organizations.OrganizationDetail;
|
||||
import org.cloudfoundry.operations.organizations.OrganizationInfoRequest;
|
||||
import org.cloudfoundry.operations.organizations.OrganizationQuota;
|
||||
import org.cloudfoundry.operations.organizations.Organizations;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.cloud.appbroker.deployer.AppDeployer;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteBackingSpaceRequest;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CloudFoundryAppDeployerDeleteSpaceTest {
|
||||
|
||||
private AppDeployer appDeployer;
|
||||
|
||||
@Mock
|
||||
private Organizations operationsOrganizations;
|
||||
|
||||
@Mock
|
||||
private org.cloudfoundry.client.v2.spaces.Spaces clientSpaces;
|
||||
|
||||
@Mock
|
||||
private org.cloudfoundry.client.v2.organizations.Organizations clientOrganizations;
|
||||
|
||||
@Mock
|
||||
private CloudFoundryOperations cloudFoundryOperations;
|
||||
|
||||
@Mock
|
||||
private CloudFoundryClient cloudFoundryClient;
|
||||
|
||||
@Mock
|
||||
private CloudFoundryOperationsUtils operationsUtils;
|
||||
|
||||
@Mock
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
CloudFoundryDeploymentProperties deploymentProperties = new CloudFoundryDeploymentProperties();
|
||||
|
||||
CloudFoundryTargetProperties targetProperties = new CloudFoundryTargetProperties();
|
||||
targetProperties.setDefaultOrg("default-org");
|
||||
targetProperties.setDefaultSpace("default-space");
|
||||
|
||||
given(cloudFoundryOperations.organizations()).willReturn(operationsOrganizations);
|
||||
given(cloudFoundryClient.organizations()).willReturn(clientOrganizations);
|
||||
|
||||
given(operationsOrganizations
|
||||
.get(
|
||||
OrganizationInfoRequest
|
||||
.builder()
|
||||
.name("default-org")
|
||||
.build()))
|
||||
.willReturn(Mono.just(
|
||||
OrganizationDetail
|
||||
.builder()
|
||||
.id("default-org-id")
|
||||
.name("default-org")
|
||||
.quota(OrganizationQuota
|
||||
.builder()
|
||||
.id("quota-id")
|
||||
.instanceMemoryLimit(0)
|
||||
.organizationId("default-org-id")
|
||||
.name("quota")
|
||||
.paidServicePlans(false)
|
||||
.totalMemoryLimit(0)
|
||||
.totalRoutes(0)
|
||||
.totalServiceInstances(0)
|
||||
.build())
|
||||
.build()));
|
||||
|
||||
appDeployer = new CloudFoundryAppDeployer(deploymentProperties, cloudFoundryOperations, cloudFoundryClient,
|
||||
operationsUtils, targetProperties, resourceLoader);
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteSpaceIfExists() {
|
||||
given(clientOrganizations
|
||||
.listSpaces(ListOrganizationSpacesRequest
|
||||
.builder()
|
||||
.name("test-space-name")
|
||||
.organizationId("default-org-id")
|
||||
.page(1)
|
||||
.build()))
|
||||
.willReturn(Mono.just(ListOrganizationSpacesResponse
|
||||
.builder()
|
||||
.resource(SpaceResource
|
||||
.builder()
|
||||
.entity(SpaceEntity
|
||||
.builder()
|
||||
.name("test-space-name")
|
||||
.build())
|
||||
.metadata(Metadata
|
||||
.builder()
|
||||
.id("test-space-id")
|
||||
.build())
|
||||
.build())
|
||||
.build()));
|
||||
|
||||
given(cloudFoundryClient.spaces()).willReturn(clientSpaces);
|
||||
given(clientSpaces
|
||||
.delete(DeleteSpaceRequest
|
||||
.builder()
|
||||
.spaceId("test-space-id")
|
||||
.recursive(true)
|
||||
.build()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
DeleteBackingSpaceRequest request =
|
||||
DeleteBackingSpaceRequest.builder()
|
||||
.name("test-space-name")
|
||||
.build();
|
||||
|
||||
StepVerifier.create(
|
||||
appDeployer.deleteBackingSpace(request))
|
||||
.assertNext(response -> assertThat(response.getName()).isEqualTo("test-space-name"))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doNothingIfSpaceDoesNotExist() {
|
||||
given(clientOrganizations
|
||||
.listSpaces(ListOrganizationSpacesRequest
|
||||
.builder()
|
||||
.name("test-space-name")
|
||||
.organizationId("default-org-id")
|
||||
.page(1)
|
||||
.build()))
|
||||
.willReturn(Mono.just(ListOrganizationSpacesResponse
|
||||
.builder()
|
||||
.resources()
|
||||
.build()));
|
||||
|
||||
DeleteBackingSpaceRequest request =
|
||||
DeleteBackingSpaceRequest.builder()
|
||||
.name("test-space-name")
|
||||
.build();
|
||||
|
||||
StepVerifier.create(
|
||||
appDeployer.deleteBackingSpace(request))
|
||||
.assertNext(response -> assertThat(response.getName()).isEqualTo("test-space-name"))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,24 +23,20 @@ import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudfoundry.client.CloudFoundryClient;
|
||||
import org.cloudfoundry.client.v2.Metadata;
|
||||
import org.cloudfoundry.client.v2.applications.SummaryApplicationRequest;
|
||||
import org.cloudfoundry.client.v2.applications.SummaryApplicationResponse;
|
||||
import org.cloudfoundry.client.v2.applications.UpdateApplicationResponse;
|
||||
import org.cloudfoundry.client.v2.organizations.GetOrganizationRequest;
|
||||
import org.cloudfoundry.client.v2.organizations.GetOrganizationResponse;
|
||||
import org.cloudfoundry.client.v2.organizations.ListOrganizationSpacesRequest;
|
||||
import org.cloudfoundry.client.v2.organizations.ListOrganizationSpacesResponse;
|
||||
import org.cloudfoundry.client.v2.organizations.OrganizationEntity;
|
||||
import org.cloudfoundry.client.v2.serviceinstances.GetServiceInstanceResponse;
|
||||
import org.cloudfoundry.client.v2.serviceinstances.ServiceInstanceEntity;
|
||||
import org.cloudfoundry.client.v2.serviceinstances.ServiceInstances;
|
||||
import org.cloudfoundry.client.v2.spaces.CreateSpaceRequest;
|
||||
import org.cloudfoundry.client.v2.spaces.DeleteSpaceRequest;
|
||||
import org.cloudfoundry.client.v2.spaces.GetSpaceRequest;
|
||||
import org.cloudfoundry.client.v2.spaces.GetSpaceResponse;
|
||||
import org.cloudfoundry.client.v2.spaces.SpaceEntity;
|
||||
import org.cloudfoundry.client.v2.spaces.SpaceResource;
|
||||
import org.cloudfoundry.operations.CloudFoundryOperations;
|
||||
import org.cloudfoundry.operations.applications.ApplicationDetail;
|
||||
import org.cloudfoundry.operations.applications.ApplicationHealthCheck;
|
||||
@@ -618,59 +614,6 @@ class CloudFoundryAppDeployerTest {
|
||||
.build()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
given(operationsOrganizations
|
||||
.get(
|
||||
OrganizationInfoRequest
|
||||
.builder()
|
||||
.name("default-org")
|
||||
.build()))
|
||||
.willReturn(Mono.just(
|
||||
OrganizationDetail
|
||||
.builder()
|
||||
.id("default-org-id")
|
||||
.name("default-org")
|
||||
.quota(OrganizationQuota
|
||||
.builder()
|
||||
.id("quota-id")
|
||||
.instanceMemoryLimit(0)
|
||||
.organizationId("default-org-id")
|
||||
.name("quota")
|
||||
.paidServicePlans(false)
|
||||
.totalMemoryLimit(0)
|
||||
.totalRoutes(0)
|
||||
.totalServiceInstances(0)
|
||||
.build())
|
||||
.build()));
|
||||
|
||||
given(clientOrganizations
|
||||
.listSpaces(ListOrganizationSpacesRequest
|
||||
.builder()
|
||||
.name("service-instance-id")
|
||||
.organizationId("default-org-id")
|
||||
.page(1)
|
||||
.build()))
|
||||
.willReturn(Mono.just(ListOrganizationSpacesResponse
|
||||
.builder()
|
||||
.resource(SpaceResource
|
||||
.builder()
|
||||
.entity(SpaceEntity
|
||||
.builder()
|
||||
.name("service-instance-id")
|
||||
.build())
|
||||
.metadata(Metadata
|
||||
.builder()
|
||||
.id("service-instance-space-id")
|
||||
.build())
|
||||
.build())
|
||||
.build()));
|
||||
|
||||
given(clientSpaces
|
||||
.delete(DeleteSpaceRequest
|
||||
.builder()
|
||||
.spaceId("service-instance-space-id")
|
||||
.build()))
|
||||
.willReturn(Mono.empty());
|
||||
|
||||
DeleteServiceInstanceRequest request =
|
||||
DeleteServiceInstanceRequest.builder()
|
||||
.serviceInstanceName("service-instance-name")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,4 +56,8 @@ public interface AppDeployer {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
default Mono<DeleteBackingSpaceResponse> deleteBackingSpace(DeleteBackingSpaceRequest request) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.deployer;
|
||||
|
||||
public class DeleteBackingSpaceRequest {
|
||||
|
||||
private final String name;
|
||||
|
||||
protected DeleteBackingSpaceRequest(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static DeleteBackingSpaceRequestBuilder builder() {
|
||||
return new DeleteBackingSpaceRequestBuilder();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static final class DeleteBackingSpaceRequestBuilder {
|
||||
|
||||
private String name;
|
||||
|
||||
private DeleteBackingSpaceRequestBuilder() {
|
||||
}
|
||||
|
||||
public DeleteBackingSpaceRequestBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteBackingSpaceRequest build() {
|
||||
return new DeleteBackingSpaceRequest(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.deployer;
|
||||
|
||||
public class DeleteBackingSpaceResponse {
|
||||
|
||||
private final String name;
|
||||
|
||||
protected DeleteBackingSpaceResponse(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static DeleteBackingSpaceResponseBuilder builder() {
|
||||
return new DeleteBackingSpaceResponseBuilder();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static final class DeleteBackingSpaceResponseBuilder {
|
||||
|
||||
private String name;
|
||||
|
||||
private DeleteBackingSpaceResponseBuilder() {
|
||||
}
|
||||
|
||||
public DeleteBackingSpaceResponseBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteBackingSpaceResponse build() {
|
||||
return new DeleteBackingSpaceResponse(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,9 +38,9 @@ import static io.restassured.RestAssured.given;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithSpacePerServiceInstanceTargetComponentTest.APP_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithSpacePerServiceInstanceTargetComponentTest.BACKING_SERVICE_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithSpacePerServiceInstanceTargetComponentTest.BACKING_SI_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithCustomTargetComponentTest.APP_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithCustomTargetComponentTest.BACKING_SERVICE_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.CreateInstanceWithCustomTargetComponentTest.BACKING_SI_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
@@ -76,18 +76,18 @@ class CreateInstanceWithCustomTargetComponentTest extends WiremockComponentTest
|
||||
void pushAppWithServicesInSpace() {
|
||||
String serviceInstanceId = "instance-id";
|
||||
String customSpace = "my-space";
|
||||
|
||||
cloudControllerFixture.stubCreateSpace(customSpace);
|
||||
cloudControllerFixture.stubAssociatePermissions(customSpace);
|
||||
String customSpaceGuid = "my-space-guid";
|
||||
cloudControllerFixture.stubCreateSpace(customSpace, customSpaceGuid);
|
||||
cloudControllerFixture.stubAssociatePermissions(customSpace, customSpaceGuid);
|
||||
cloudControllerFixture.stubPushApp(APP_NAME);
|
||||
|
||||
// given services are available in the marketplace
|
||||
cloudControllerFixture.stubServiceExists(BACKING_SERVICE_NAME, BACKING_PLAN_NAME);
|
||||
cloudControllerFixture.stubServiceExistsInSpace(BACKING_SERVICE_NAME, BACKING_PLAN_NAME, customSpaceGuid);
|
||||
|
||||
// will create and bind the service instance
|
||||
cloudControllerFixture.stubCreateServiceInstance(BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubCreateServiceBinding(APP_NAME, BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubServiceInstanceExists(BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubServiceInstanceExistsInSpace(BACKING_SI_NAME, customSpaceGuid);
|
||||
|
||||
// when a service instance is created
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -65,18 +65,19 @@ class CreateInstanceWithSpacePerServiceInstanceTargetComponentTest extends Wirem
|
||||
@Test
|
||||
void pushAppWithServicesInSpace() {
|
||||
String serviceInstanceId = "instance-id";
|
||||
String backingSpaceGuid = "my-space-guid";
|
||||
|
||||
cloudControllerFixture.stubCreateSpace(serviceInstanceId);
|
||||
cloudControllerFixture.stubAssociatePermissions(serviceInstanceId);
|
||||
cloudControllerFixture.stubCreateSpace(serviceInstanceId, backingSpaceGuid);
|
||||
cloudControllerFixture.stubAssociatePermissions(serviceInstanceId, backingSpaceGuid);
|
||||
cloudControllerFixture.stubPushAppWithHost(APP_NAME, APP_NAME + "-" + serviceInstanceId);
|
||||
|
||||
// given services are available in the marketplace
|
||||
cloudControllerFixture.stubServiceExists(BACKING_SERVICE_NAME, BACKING_PLAN_NAME);
|
||||
cloudControllerFixture.stubServiceExistsInSpace(BACKING_SERVICE_NAME, BACKING_PLAN_NAME, backingSpaceGuid);
|
||||
|
||||
// will create and bind the service instance
|
||||
cloudControllerFixture.stubCreateServiceInstance(BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubCreateServiceBinding(APP_NAME, BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubServiceInstanceExists(BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubServiceInstanceExistsInSpace(BACKING_SI_NAME, backingSpaceGuid);
|
||||
|
||||
// when a service instance is created
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.appbroker.integration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.CloudControllerStubFixture;
|
||||
import org.springframework.cloud.appbroker.integration.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED;
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.cloud.appbroker.integration.UpdateInstanceWithNewServiceAndTargetComponentTest.APP_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.UpdateInstanceWithNewServiceAndTargetComponentTest.NEW_BACKING_PLAN_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.UpdateInstanceWithNewServiceAndTargetComponentTest.NEW_BACKING_SERVICE_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.UpdateInstanceWithNewServiceAndTargetComponentTest.NEW_BACKING_SI_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.UpdateInstanceWithNewServiceAndTargetComponentTest.PLAN_NAME;
|
||||
import static org.springframework.cloud.appbroker.integration.UpdateInstanceWithNewServiceAndTargetComponentTest.SERVICE_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=" + SERVICE_NAME,
|
||||
"spring.cloud.appbroker.services[0].plan-name=" + PLAN_NAME,
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_NAME,
|
||||
"spring.cloud.appbroker.services[0].apps[0].services[0].service-instance-name=" + NEW_BACKING_SI_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].service-instance-name=" + NEW_BACKING_SI_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].name=" + NEW_BACKING_SERVICE_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].plan=" + NEW_BACKING_PLAN_NAME,
|
||||
|
||||
"spring.cloud.appbroker.services[0].target.name=SpacePerServiceInstance"
|
||||
})
|
||||
class UpdateInstanceWithNewServiceAndTargetComponentTest extends WiremockComponentTest {
|
||||
|
||||
protected static final String APP_NAME = "app-update-with-new-service-and-target";
|
||||
|
||||
protected static final String BACKING_SI_NAME = "my-db-service";
|
||||
|
||||
protected static final String BACKING_SERVICE_NAME = "db-service";
|
||||
|
||||
protected static final String BACKING_PLAN_NAME = "backing-standard";
|
||||
|
||||
protected static final String NEW_BACKING_SERVICE_NAME = "new-service";
|
||||
|
||||
protected static final String NEW_BACKING_SI_NAME = "my-new-service";
|
||||
|
||||
protected static final String NEW_BACKING_PLAN_NAME = "new-backing-standard";
|
||||
|
||||
protected static final String SERVICE_NAME = "example";
|
||||
|
||||
protected static final String PLAN_NAME = "standard";
|
||||
|
||||
@Autowired
|
||||
private OpenServiceBrokerApiFixture brokerFixture;
|
||||
|
||||
@Autowired
|
||||
private CloudControllerStubFixture cloudControllerFixture;
|
||||
|
||||
@Test
|
||||
void updateAppWithNewServiceAndTarget() {
|
||||
final String backingSpaceGuid = "instance-id-space-guid";
|
||||
final String serviceInstanceId = "instance-id";
|
||||
|
||||
cloudControllerFixture.stubFindSpace(serviceInstanceId, backingSpaceGuid, STARTED);
|
||||
cloudControllerFixture.stubSpaceExists(serviceInstanceId, backingSpaceGuid, STARTED);
|
||||
cloudControllerFixture.stubAppExistsWithBackingService(APP_NAME, BACKING_SI_NAME,
|
||||
BACKING_SERVICE_NAME, BACKING_PLAN_NAME, backingSpaceGuid);
|
||||
cloudControllerFixture.stubUpdateAppWithTarget(APP_NAME, backingSpaceGuid);
|
||||
|
||||
// will unbind and delete the existing service instance
|
||||
cloudControllerFixture.stubGetBackingServiceInstanceFromSpace(BACKING_SI_NAME, BACKING_SERVICE_NAME,
|
||||
BACKING_PLAN_NAME, backingSpaceGuid);
|
||||
cloudControllerFixture.stubServiceBindingExists(APP_NAME, BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubDeleteServiceBinding(APP_NAME, BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubDeleteServiceInstance(BACKING_SI_NAME);
|
||||
|
||||
// will create and bind the service instance
|
||||
cloudControllerFixture.stubServiceExistsInSpace(NEW_BACKING_SERVICE_NAME, NEW_BACKING_PLAN_NAME, backingSpaceGuid);
|
||||
cloudControllerFixture.stubCreateServiceInstance(NEW_BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubCreateServiceBinding(APP_NAME, NEW_BACKING_SI_NAME);
|
||||
cloudControllerFixture.stubServiceInstanceExistsInSpace(NEW_BACKING_SI_NAME, backingSpaceGuid);
|
||||
|
||||
// when a service instance is updated
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.patch(brokerFixture.createServiceInstanceUrl(), serviceInstanceId)
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value());
|
||||
|
||||
// when the "last_operation" API is polled
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.get(brokerFixture.getLastInstanceOperationUrl(), serviceInstanceId)
|
||||
.then()
|
||||
.statusCode(HttpStatus.OK.value())
|
||||
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
|
||||
|
||||
String state = brokerFixture.waitForAsyncOperationComplete(serviceInstanceId);
|
||||
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,10 +35,15 @@ import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.put;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
|
||||
import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED;
|
||||
|
||||
@TestComponent
|
||||
public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
|
||||
private static final String SCENARIO_NAME = "CreateSpace";
|
||||
|
||||
private static final String SPACE_CREATED_STATE = "SpaceCreated";
|
||||
|
||||
private static final String TEST_SPACE_GUID = "TEST-SPACE-GUID";
|
||||
|
||||
private static final String TEST_ORG_GUID = "TEST-ORG-GUID";
|
||||
@@ -52,7 +57,7 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
public void stubCommonCloudControllerRequests() {
|
||||
stubGetPlatformInfo();
|
||||
stubFindTestOrg();
|
||||
stubFindTestSpace();
|
||||
stubFindSpace("development", TEST_SPACE_GUID, STARTED);
|
||||
stubFindDomains();
|
||||
}
|
||||
|
||||
@@ -82,29 +87,39 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
replace("@org-guid", TEST_ORG_GUID)))));
|
||||
}
|
||||
|
||||
private void stubFindTestSpace() {
|
||||
public void stubFindSpace(String spaceName, String spaceGuid, String scenario) {
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces"))
|
||||
.inScenario(SCENARIO_NAME)
|
||||
.whenScenarioStateIs(scenario)
|
||||
.withQueryParam("q", equalTo("name:" + spaceName))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("list-spaces",
|
||||
replace("@org-guid", TEST_ORG_GUID),
|
||||
replace("@space-guid", TEST_SPACE_GUID)))));
|
||||
replace("@name", spaceName),
|
||||
replace("@space-guid", spaceGuid)))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID))
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid))
|
||||
.inScenario(SCENARIO_NAME)
|
||||
.whenScenarioStateIs(scenario)
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-space",
|
||||
replace("@name", "test"),
|
||||
replace("@org-guid", TEST_ORG_GUID),
|
||||
replace("@space-guid", TEST_SPACE_GUID)))));
|
||||
replace("@space-guid", spaceGuid)))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/apps"))
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid + "/apps"))
|
||||
.inScenario(SCENARIO_NAME)
|
||||
.whenScenarioStateIs(scenario)
|
||||
.withQueryParam("page", equalTo("1"))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("empty-query-results"))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/security_groups"))
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid + "/security_groups"))
|
||||
.inScenario(SCENARIO_NAME)
|
||||
.whenScenarioStateIs(scenario)
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-space-security_groups"))));
|
||||
@@ -144,15 +159,20 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
replace("@org-guid", TEST_ORG_GUID)))));
|
||||
}
|
||||
|
||||
public void stubCreateSpace(final String spaceName) {
|
||||
public void stubCreateSpace(final String spaceName, final String spaceGuid) {
|
||||
stubFor(post(urlPathEqualTo("/v2/spaces"))
|
||||
.inScenario(SCENARIO_NAME)
|
||||
.whenScenarioStateIs(STARTED)
|
||||
.willSetStateTo(SPACE_CREATED_STATE)
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + spaceName + "')]"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.organization_guid == '" + TEST_ORG_GUID + "')]"))
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-space",
|
||||
replace("@name", spaceName),
|
||||
replace("@space-guid", "CREATED-SPACE-GUID"),
|
||||
replace("@space-guid", spaceGuid),
|
||||
replace("@org-guid", TEST_ORG_GUID)))));
|
||||
|
||||
stubFindSpace(spaceName, spaceGuid, SPACE_CREATED_STATE);
|
||||
}
|
||||
|
||||
public void stubAppDoesNotExist(final String appName) {
|
||||
@@ -163,26 +183,24 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
.withBody(cc("empty-query-results"))));
|
||||
}
|
||||
|
||||
public void stubAppExists(final String appName) {
|
||||
public void stubAppExistsInSpace(final String appName, final String spaceGuid) {
|
||||
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName)))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-app-STAGED",
|
||||
replace("@name", appName)))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/apps"))
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid + "/apps"))
|
||||
.withQueryParam("q", equalTo("name:" + appName))
|
||||
.withQueryParam("page", equalTo("1"))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("list-space-apps",
|
||||
replace("@name", appName),
|
||||
replace("@guid", appGuid(appName)),
|
||||
replace("@space-guid", TEST_SPACE_GUID),
|
||||
replace("@space-guid", spaceGuid),
|
||||
replace("@stack-guid", stackGuid(appName))))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/instances"))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-app-instances"))));
|
||||
|
||||
@@ -196,24 +214,30 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
replace("@route-guid", routeGuid(appName))))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/stats"))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-app-stats",
|
||||
replace("@name", appName)))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/stacks/" + stackGuid(appName)))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-stack",
|
||||
replace("@guid", stackGuid(appName))))));
|
||||
}
|
||||
|
||||
public void stubAppExists(final String appName) {
|
||||
stubAppExistsInSpace(appName, TEST_SPACE_GUID);
|
||||
}
|
||||
|
||||
public void stubAppExistsWithBackingService(final String appName, final String serviceInstanceName,
|
||||
final String serviceName, final String planName) {
|
||||
stubAppExists(appName);
|
||||
stubAppExistsWithBackingService(appName, serviceInstanceName, serviceName, planName, TEST_SPACE_GUID);
|
||||
}
|
||||
|
||||
public void stubAppExistsWithBackingService(final String appName, final String serviceInstanceName,
|
||||
final String serviceName, final String planName, final String spaceGuid) {
|
||||
stubAppExistsInSpace(appName, spaceGuid);
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/apps/" + appGuid(appName) + "/summary"))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-app-summary-with-backing-service",
|
||||
replace("@name", appName),
|
||||
@@ -248,6 +272,11 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
stubCreateRoute(appName);
|
||||
}
|
||||
|
||||
public void stubUpdateAppWithTarget(final String appName, final String spaceGuid) {
|
||||
stubUpdateApp(appName);
|
||||
stubCreateRouteInSpace(appName, spaceGuid);
|
||||
}
|
||||
|
||||
public void stubUpdateApp(final String appName) {
|
||||
stubGetV3App(appName);
|
||||
stubUpdateEnvironment(appName);
|
||||
@@ -425,14 +454,14 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
.withBody(cc("get-app-instances"))));
|
||||
}
|
||||
|
||||
private void stubCreateRoute(final String appName) {
|
||||
private void stubCreateRouteInSpace(final String appName, final String spaceGuid) {
|
||||
stubFor(get(urlPathEqualTo("/v2/private_domains"))
|
||||
.withQueryParam("page", equalTo("1"))
|
||||
.withMetadata(optionalStubMapping())
|
||||
.willReturn(ok()
|
||||
.withBody(cc("empty-query-results"))));
|
||||
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/services"))
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid + "/services"))
|
||||
.withQueryParam("page", equalTo("1"))
|
||||
.willReturn(ok()
|
||||
.withBody(cc("list-space-services")
|
||||
@@ -449,6 +478,10 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
.withBody(cc("get-app-summary"))));
|
||||
}
|
||||
|
||||
private void stubCreateRoute(final String appName) {
|
||||
stubCreateRouteInSpace(appName, TEST_SPACE_GUID);
|
||||
}
|
||||
|
||||
public void stubDeleteApp(String appName) {
|
||||
stubFor(delete(urlPathEqualTo("/v2/routes/" + appName + "-ROUTE-GUID"))
|
||||
.willReturn(ok()
|
||||
@@ -463,19 +496,30 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
stubServiceInstanceExists(serviceInstanceName, "doNotCare", "doNotCare");
|
||||
}
|
||||
|
||||
public void stubServiceInstanceExists(String serviceInstanceName, String serviceName, String planName) {
|
||||
stubServiceInstanceExists(serviceInstanceGuid(serviceInstanceName), serviceInstanceName, serviceName, planName);
|
||||
public void stubServiceInstanceExistsInSpace(String serviceInstanceName, String spaceGuid) {
|
||||
stubServiceInstanceExistsInSpace(serviceInstanceName, "doNotCare", "doNotCare", spaceGuid);
|
||||
}
|
||||
|
||||
private void stubServiceInstanceExists(String serviceInstanceId, String serviceInstanceName, String serviceName,
|
||||
String planName) {
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/service_instances"))
|
||||
public void stubServiceInstanceExists(String serviceInstanceName, String serviceName, String planName) {
|
||||
stubServiceInstanceExists(serviceInstanceGuid(serviceInstanceName), serviceInstanceName, serviceName,
|
||||
planName, TEST_SPACE_GUID);
|
||||
}
|
||||
|
||||
public void stubServiceInstanceExistsInSpace(String serviceInstanceName, String serviceName, String planName,
|
||||
String spaceGuid) {
|
||||
stubServiceInstanceExists(serviceInstanceGuid(serviceInstanceName), serviceInstanceName, serviceName,
|
||||
planName, spaceGuid);
|
||||
}
|
||||
|
||||
private void stubServiceInstanceExists(String serviceInstanceId, String serviceInstanceName,
|
||||
String serviceName, String planName, String spaceGuid) {
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid + "/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("@space-guid", spaceGuid),
|
||||
replace("@service-guid", serviceGuid(serviceName)),
|
||||
replace("@plan-guid", planGuid(planName)),
|
||||
replace("@name", serviceInstanceName),
|
||||
@@ -491,13 +535,18 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
}
|
||||
|
||||
public void stubGetBackingServiceInstance(String serviceInstanceName, String serviceName, String planName) {
|
||||
stubGetBackingServiceInstanceFromSpace(serviceInstanceName, serviceName, planName, TEST_SPACE_GUID);
|
||||
}
|
||||
|
||||
public void stubGetBackingServiceInstanceFromSpace(String serviceInstanceName, String serviceName,
|
||||
String planName, String spaceGuid) {
|
||||
String serviceInstanceId = serviceInstanceGuid(serviceInstanceName);
|
||||
stubServiceInstanceExists(serviceInstanceId, serviceInstanceName, serviceName, planName);
|
||||
stubServiceInstanceExists(serviceInstanceId, serviceInstanceName, serviceName, planName, spaceGuid);
|
||||
stubGetServiceAndGetPlan(serviceName, planName);
|
||||
}
|
||||
|
||||
public void stubServiceExists(String serviceName, String planName) {
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + TEST_SPACE_GUID + "/services"))
|
||||
public void stubServiceExistsInSpace(String serviceName, String planName, String spaceGuid) {
|
||||
stubFor(get(urlPathEqualTo("/v2/spaces/" + spaceGuid + "/services"))
|
||||
.withQueryParam("q", equalTo("label:" + serviceName))
|
||||
.withQueryParam("page", equalTo("1"))
|
||||
.willReturn(ok()
|
||||
@@ -516,6 +565,10 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
.replace("@plan-guid", planGuid(planName)))));
|
||||
}
|
||||
|
||||
public void stubServiceExists(String serviceName, String planName) {
|
||||
stubServiceExistsInSpace(serviceName, planName, TEST_SPACE_GUID);
|
||||
}
|
||||
|
||||
public void stubCreateServiceInstance(String serviceInstanceName) {
|
||||
stubFor(post(urlPathEqualTo("/v2/service_instances"))
|
||||
.withQueryParam("accepts_incomplete", equalTo("true"))
|
||||
@@ -596,11 +649,11 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
.withBody(cc("empty-query-results"))));
|
||||
}
|
||||
|
||||
public void stubAssociatePermissions(final String spaceName) {
|
||||
public void stubAssociatePermissions(final String spaceName, final String spaceGuid) {
|
||||
stubFor(get(urlPathEqualTo("/v2/config/feature_flags/set_roles_by_username"))
|
||||
.willReturn(ok()
|
||||
.withBody(cc("get-feature-flag-roles"))));
|
||||
stubSpaceExists(spaceName);
|
||||
stubSpaceExists(spaceName, spaceGuid, SPACE_CREATED_STATE);
|
||||
|
||||
stubFor(put(urlPathEqualTo("/v2/organizations/" + TEST_ORG_GUID + "/users"))
|
||||
.willReturn(ok()));
|
||||
@@ -621,13 +674,15 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
.replace("@service-name", serviceName))));
|
||||
}
|
||||
|
||||
private void stubSpaceExists(final String spaceName) {
|
||||
public void stubSpaceExists(final String spaceName, final String spaceGuid, final String scenario) {
|
||||
stubFor(get(urlPathEqualTo("/v2/organizations/" + TEST_ORG_GUID + "/spaces"))
|
||||
.inScenario(SCENARIO_NAME)
|
||||
.whenScenarioStateIs(scenario)
|
||||
.withQueryParam("q", equalTo("name:" + spaceName))
|
||||
.willReturn(ok()
|
||||
.withBody(cc("list-spaces",
|
||||
replace("@org-guid", TEST_ORG_GUID),
|
||||
replace("@space-guid", TEST_SPACE_GUID),
|
||||
replace("@space-guid", spaceGuid),
|
||||
replace("@name", spaceName)))));
|
||||
}
|
||||
|
||||
@@ -659,7 +714,7 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
return planName + "-PLAN-GUID";
|
||||
}
|
||||
|
||||
private static String serviceInstanceGuid(String serviceInstanceName) {
|
||||
public static String serviceInstanceGuid(String serviceInstanceName) {
|
||||
return serviceInstanceName + "-INSTANCE-GUID";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.github.tomakehurst.wiremock.admin.model.ListStubMappingsResult;
|
||||
import com.github.tomakehurst.wiremock.client.MappingBuilder;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.common.Metadata;
|
||||
@@ -45,6 +46,10 @@ public class WiremockStubFixture {
|
||||
.build();
|
||||
}
|
||||
|
||||
public ListStubMappingsResult getAllStubs() {
|
||||
return wireMock.allStubMappings();
|
||||
}
|
||||
|
||||
protected StubMapping stubFor(MappingBuilder mappingBuilder) {
|
||||
return givenThat(mappingBuilder);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"total_results": 2,
|
||||
"total_results": 3,
|
||||
"total_pages": 1,
|
||||
"prev_url": null,
|
||||
"next_url": null,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"updated_at": "2018-07-19T20:34:16Z"
|
||||
},
|
||||
"entity": {
|
||||
"name": "development",
|
||||
"name": "@name",
|
||||
"organization_guid": "@org-guid",
|
||||
"space_quota_definition_guid": null,
|
||||
"isolation_segment_guid": null,
|
||||
|
||||
Reference in New Issue
Block a user