Adding service creation
This commit is contained in:
committed by
Alberto Ríos
parent
f6b68c800e
commit
64f1072a4b
@@ -0,0 +1,60 @@
|
||||
package org.springframework.cloud.appbroker.acceptance;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.cloudfoundry.operations.applications.ApplicationSummary;
|
||||
import org.cloudfoundry.operations.services.ServiceInstanceSummary;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CreateInstanceWithServicesAcceptanceTest extends CloudFoundryAcceptanceTest {
|
||||
|
||||
private static final String BROKER_APP_SERVICES = "broker-app-new-services";
|
||||
private static final String SI_1_NAME = "service-instance-1";
|
||||
private static final String SERVICE_1_NAME = "db-service";
|
||||
|
||||
@Test
|
||||
@AppBrokerTestProperties({
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
"spring.cloud.appbroker.services[0].plan-name=standard",
|
||||
"spring.cloud.appbroker.services[0].apps[0].name=" + BROKER_APP_SERVICES,
|
||||
"spring.cloud.appbroker.services[0].apps[0].path=classpath:demo.jar",
|
||||
"spring.cloud.appbroker.services[0].apps[0].services[0].service-instance-name=" + SI_1_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].service-instance-name=" + SI_1_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].name=" + SERVICE_1_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].plan=standard"
|
||||
})
|
||||
void shouldPushAppWithServicesBind() {
|
||||
// given that a service is available in the marketplace
|
||||
setupServiceBrokerForService("db-service");
|
||||
|
||||
// when a service instance is created
|
||||
createServiceInstance();
|
||||
|
||||
// then a backing application is deployed
|
||||
Optional<ApplicationSummary> backingApplication = getApplicationSummaryByName(BROKER_APP_SERVICES);
|
||||
assertThat(backingApplication).isNotEmpty();
|
||||
|
||||
// and the service bind to it
|
||||
Optional<ServiceInstanceSummary> serviceInstance = getServiceInstance(SI_1_NAME);
|
||||
assertThat(serviceInstance).isNotEmpty();
|
||||
assertThat(serviceInstance.get().getApplications()).contains(BROKER_APP_SERVICES);
|
||||
|
||||
// when the service instance is deleted
|
||||
deleteServiceInstance();
|
||||
|
||||
// service has no applications bound to it
|
||||
Optional<ServiceInstanceSummary> serviceInstanceAfterDeletion = getServiceInstance(SI_1_NAME);
|
||||
assertThat(serviceInstanceAfterDeletion).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
super.tearDown();
|
||||
|
||||
deleteServiceBrokerForService("db-service");
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.appbroker.deployer.AppDeployer;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployerClient;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialGenerator;
|
||||
@@ -131,21 +132,39 @@ public class AppBrokerAutoConfiguration {
|
||||
return new TargetService(targets);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BackingServicesProvisionService backingServicesProvisionService(DeployerClient deployerClient) {
|
||||
return new BackingServicesProvisionService(deployerClient);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CreateServiceInstanceWorkflow appDeploymentCreateServiceInstanceWorkflow(BrokeredServices brokeredServices,
|
||||
BackingAppDeploymentService backingAppDeploymentService,
|
||||
ParametersTransformationService parametersTransformationService,
|
||||
CredentialProviderService credentialProviderService,
|
||||
TargetService targetService) {
|
||||
return new AppDeploymentCreateServiceInstanceWorkflow(brokeredServices, backingAppDeploymentService, parametersTransformationService, credentialProviderService, targetService);
|
||||
TargetService targetService,
|
||||
BackingServicesProvisionService backingServicesProvisionService) {
|
||||
return new AppDeploymentCreateServiceInstanceWorkflow(
|
||||
brokeredServices,
|
||||
backingAppDeploymentService,
|
||||
parametersTransformationService,
|
||||
credentialProviderService,
|
||||
targetService,
|
||||
backingServicesProvisionService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DeleteServiceInstanceWorkflow appDeploymentDeleteServiceInstanceWorkflow(BrokeredServices brokeredServices,
|
||||
BackingAppDeploymentService backingAppDeploymentService,
|
||||
CredentialProviderService credentialProviderService,
|
||||
TargetService targetService) {
|
||||
return new AppDeploymentDeleteServiceInstanceWorkflow(brokeredServices, backingAppDeploymentService, credentialProviderService, targetService);
|
||||
TargetService targetService,
|
||||
BackingServicesProvisionService backingServicesProvisionService) {
|
||||
return new AppDeploymentDeleteServiceInstanceWorkflow(
|
||||
brokeredServices,
|
||||
backingAppDeploymentService,
|
||||
credentialProviderService,
|
||||
targetService,
|
||||
backingServicesProvisionService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingApplications;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployerClient;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderService;
|
||||
@@ -101,6 +102,7 @@ class AppBrokerAutoConfigurationTest {
|
||||
assertThat(context).hasSingleBean(ParametersTransformationService.class);
|
||||
assertThat(context).hasSingleBean(CredentialProviderService.class);
|
||||
assertThat(context).hasSingleBean(TargetService.class);
|
||||
assertThat(context).hasSingleBean(BackingServicesProvisionService.class);
|
||||
assertThat(context).hasSingleBean(WorkflowServiceInstanceService.class);
|
||||
assertThat(context).hasSingleBean(WorkflowServiceInstanceBindingService.class);
|
||||
assertThat(context).hasSingleBean(AppDeploymentCreateServiceInstanceWorkflow.class);
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2016-2018 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
|
||||
*
|
||||
* http://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.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BackingService {
|
||||
|
||||
private String serviceInstanceName;
|
||||
private String name;
|
||||
private String plan;
|
||||
private Map<String, String> parameters;
|
||||
|
||||
private BackingService() {
|
||||
}
|
||||
|
||||
BackingService(String serviceInstanceName, String name, String plan, Map<String, String> parameters) {
|
||||
this.serviceInstanceName = serviceInstanceName;
|
||||
this.name = name;
|
||||
this.plan = plan;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
BackingService(BackingService backingServiceToCopy) {
|
||||
this.serviceInstanceName = backingServiceToCopy.serviceInstanceName;
|
||||
this.name = backingServiceToCopy.name;
|
||||
this.plan = backingServiceToCopy.plan;
|
||||
this.parameters = backingServiceToCopy.parameters == null
|
||||
? new HashMap<>()
|
||||
: new HashMap<>(backingServiceToCopy.parameters);
|
||||
}
|
||||
|
||||
public String getServiceInstanceName() {
|
||||
return serviceInstanceName;
|
||||
}
|
||||
|
||||
public void setServiceInstanceName(String serviceInstanceName) {
|
||||
this.serviceInstanceName = serviceInstanceName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPlan() {
|
||||
return plan;
|
||||
}
|
||||
|
||||
public void setPlan(String plan) {
|
||||
this.plan = plan;
|
||||
}
|
||||
|
||||
public Map<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
BackingService that = (BackingService) o;
|
||||
return Objects.equals(serviceInstanceName, that.serviceInstanceName) &&
|
||||
Objects.equals(name, that.name) &&
|
||||
Objects.equals(plan, that.plan) &&
|
||||
Objects.equals(parameters, that.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(serviceInstanceName, name, plan, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BackingService{" +
|
||||
"serviceInstanceName='" + serviceInstanceName + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", plan='" + plan + '\'' +
|
||||
", parameters=" + parameters +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static BackingServiceBuilder builder() {
|
||||
return new BackingServiceBuilder();
|
||||
}
|
||||
|
||||
public static final class BackingServiceBuilder {
|
||||
|
||||
private String serviceInstanceName;
|
||||
private String name;
|
||||
private String plan;
|
||||
private Map<String, String> parameters = new HashMap<>();
|
||||
|
||||
BackingServiceBuilder() {
|
||||
}
|
||||
|
||||
public BackingService build() {
|
||||
return new BackingService(serviceInstanceName, name, plan, parameters);
|
||||
}
|
||||
|
||||
public BackingServiceBuilder serviceInstanceName(String serviceInstanceName) {
|
||||
this.serviceInstanceName = serviceInstanceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BackingServiceBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BackingServiceBuilder plan(String plan) {
|
||||
this.plan = plan;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BackingServiceBuilder parameters(Map<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2016-2018 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
|
||||
*
|
||||
* http://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;
|
||||
|
||||
public class BackingServices extends ArrayList<BackingService> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private BackingServices() {
|
||||
}
|
||||
|
||||
BackingServices(List<BackingService> backingServices) {
|
||||
super.addAll(backingServices);
|
||||
}
|
||||
|
||||
public BackingServices(BackingServices backingServicesToCopy) {
|
||||
backingServicesToCopy.forEach(backingServiceToCopy ->
|
||||
this.add(new BackingService(backingServiceToCopy)));
|
||||
}
|
||||
|
||||
public static BackingServicesBuilder builder() {
|
||||
return new BackingServicesBuilder();
|
||||
}
|
||||
|
||||
public static class BackingServicesBuilder {
|
||||
|
||||
private final List<BackingService> backingServices = new ArrayList<>();
|
||||
|
||||
public BackingServicesBuilder backingService(BackingService backingService) {
|
||||
this.backingServices.add(backingService);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BackingServices build() {
|
||||
return new BackingServices(backingServices);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2016-2018 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
|
||||
*
|
||||
* http://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 BackingServicesProvisionService {
|
||||
|
||||
private final Logger log = Loggers.getLogger(BackingServicesProvisionService.class);
|
||||
|
||||
private final DeployerClient deployerClient;
|
||||
|
||||
public BackingServicesProvisionService(DeployerClient deployerClient) {
|
||||
this.deployerClient = deployerClient;
|
||||
}
|
||||
|
||||
public Flux<String> createServiceInstance(List<BackingService> backingServices) {
|
||||
return Flux.fromIterable(backingServices)
|
||||
.parallel()
|
||||
.runOn(Schedulers.parallel())
|
||||
.flatMap(deployerClient::createServiceInstance)
|
||||
.doOnRequest(l -> log.info("Creating backing services {}", backingServices))
|
||||
.doOnEach(d -> log.info("Finished creating backing service {}", d))
|
||||
.doOnComplete(() -> log.info("Finished creating backing service {}", backingServices))
|
||||
.doOnError(e -> log.info("Error creating backing services {} with error {}", backingServices, e))
|
||||
.sequential();
|
||||
}
|
||||
|
||||
public Flux<String> deleteServiceInstance(List<BackingService> backingServices) {
|
||||
return Flux.fromIterable(backingServices)
|
||||
.parallel()
|
||||
.runOn(Schedulers.parallel())
|
||||
.flatMap(deployerClient::deleteServiceInstance)
|
||||
.doOnRequest(l -> log.info("Deleting backing services {}", backingServices))
|
||||
.doOnEach(d -> log.info("Finished deleting backing service {}", d))
|
||||
.doOnComplete(() -> log.info("Finished deleting backing service {}", backingServices))
|
||||
.doOnError(e -> log.info("Error deleting backing services {} with error {}", backingServices, e))
|
||||
.sequential();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,17 +19,20 @@ package org.springframework.cloud.appbroker.deployer;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BrokeredService {
|
||||
|
||||
private String serviceName;
|
||||
private String planName;
|
||||
private BackingApplications apps;
|
||||
private BackingServices services;
|
||||
|
||||
private BrokeredService() {
|
||||
}
|
||||
|
||||
BrokeredService(String serviceName, String planName, BackingApplications apps) {
|
||||
BrokeredService(String serviceName, String planName, BackingApplications apps, BackingServices services) {
|
||||
this.serviceName = serviceName;
|
||||
this.planName = planName;
|
||||
this.apps = apps;
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public String getServiceName() {
|
||||
@@ -56,6 +59,14 @@ public class BrokeredService {
|
||||
this.apps = apps;
|
||||
}
|
||||
|
||||
public BackingServices getServices() {
|
||||
return services;
|
||||
}
|
||||
|
||||
public void setServices(BackingServices services) {
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public static BrokeredServiceBuilder builder() {
|
||||
return new BrokeredServiceBuilder();
|
||||
}
|
||||
@@ -71,12 +82,13 @@ public class BrokeredService {
|
||||
BrokeredService that = (BrokeredService) o;
|
||||
return Objects.equals(serviceName, that.serviceName) &&
|
||||
Objects.equals(planName, that.planName) &&
|
||||
Objects.equals(apps, that.apps);
|
||||
Objects.equals(apps, that.apps) &&
|
||||
Objects.equals(services, that.services);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(serviceName, planName, apps);
|
||||
return Objects.hash(serviceName, planName, apps, services);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,13 +97,16 @@ public class BrokeredService {
|
||||
"serviceName='" + serviceName + '\'' +
|
||||
", planName='" + planName + '\'' +
|
||||
", apps=" + apps +
|
||||
", services=" + services +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static class BrokeredServiceBuilder {
|
||||
|
||||
private String id;
|
||||
private String planId;
|
||||
private BackingApplications backingApplications;
|
||||
private BackingServices backingServices;
|
||||
|
||||
public BrokeredServiceBuilder serviceName(String id) {
|
||||
this.id = id;
|
||||
@@ -108,8 +123,13 @@ public class BrokeredService {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BrokeredServiceBuilder services(BackingServices backingServices) {
|
||||
this.backingServices = backingServices;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BrokeredService build() {
|
||||
return new BrokeredService(id, planId, backingApplications);
|
||||
return new BrokeredService(id, planId, backingApplications, backingServices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,4 +54,23 @@ public class DeployerClient {
|
||||
.map(UndeployApplicationResponse::getName);
|
||||
}
|
||||
|
||||
Mono<String> createServiceInstance(BackingService backingService) {
|
||||
return appDeployer.createServiceInstance(CreateServiceInstanceRequest.builder()
|
||||
.serviceInstanceName(backingService.getServiceInstanceName())
|
||||
.name(backingService.getName())
|
||||
.plan(backingService.getPlan())
|
||||
.parameters(backingService.getParameters())
|
||||
.build())
|
||||
.doOnRequest(l -> log.info("Creating backing service {}", backingService.getName()))
|
||||
.doOnSuccess(d -> log.info("Finished creating backing service {}", backingService.getName()))
|
||||
.doOnError(e -> log.info("Error creating backing service {} with error {}", backingService.getName(), e))
|
||||
.map(CreateServiceInstanceResponse::getName);
|
||||
}
|
||||
|
||||
Mono<String> deleteServiceInstance(BackingService backingService) {
|
||||
return appDeployer.deleteServiceInstance(DeleteServiceInstanceRequest.builder()
|
||||
.name(backingService.getServiceInstanceName())
|
||||
.build())
|
||||
.map(DeleteServiceInstanceResponse::getName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import reactor.util.Logger;
|
||||
import reactor.util.Loggers;
|
||||
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderService;
|
||||
import org.springframework.cloud.appbroker.extensions.parameters.ParametersTransformationService;
|
||||
@@ -42,33 +43,38 @@ public class AppDeploymentCreateServiceInstanceWorkflow
|
||||
private final ParametersTransformationService parametersTransformationService;
|
||||
private final CredentialProviderService credentialProviderService;
|
||||
private final TargetService targetService;
|
||||
private final BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
public AppDeploymentCreateServiceInstanceWorkflow(BrokeredServices brokeredServices,
|
||||
BackingAppDeploymentService deploymentService,
|
||||
ParametersTransformationService parametersTransformationService,
|
||||
CredentialProviderService credentialProviderService,
|
||||
TargetService targetService) {
|
||||
TargetService targetService,
|
||||
BackingServicesProvisionService backingServicesProvisionService) {
|
||||
super(brokeredServices);
|
||||
this.deploymentService = deploymentService;
|
||||
this.parametersTransformationService = parametersTransformationService;
|
||||
this.credentialProviderService = credentialProviderService;
|
||||
this.targetService = targetService;
|
||||
this.backingServicesProvisionService = backingServicesProvisionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Void> create(CreateServiceInstanceRequest request) {
|
||||
return getBackingApplicationsForService(request.getServiceDefinition(), request.getPlanId())
|
||||
.flatMap(backingApps -> targetService.add(backingApps, request.getServiceInstanceId()))
|
||||
.flatMap(backingApps ->
|
||||
parametersTransformationService.transformParameters(backingApps, request.getParameters()))
|
||||
.flatMap(backingApplications ->
|
||||
credentialProviderService.addCredentials(backingApplications, request.getServiceInstanceId()))
|
||||
.flatMapMany(deploymentService::deploy)
|
||||
.doOnRequest(l -> log.info("Deploying applications {}", brokeredServices))
|
||||
.doOnEach(s -> log.info("Finished deploying {}", s))
|
||||
.doOnComplete(() -> log.info("Finished deploying applications {}", brokeredServices))
|
||||
.doOnError(e -> log.info("Error deploying applications {} with error {}", brokeredServices, e))
|
||||
.flatMap(apps -> Flux.empty());
|
||||
return
|
||||
getBackingServicesForService(request.getServiceDefinition(), request.getPlanId())
|
||||
.flatMapMany(backingServicesProvisionService::createServiceInstance)
|
||||
.thenMany(
|
||||
getBackingApplicationsForService(request.getServiceDefinition(), request.getPlanId())
|
||||
.flatMap(backingApps -> targetService.add(backingApps, request.getServiceInstanceId()))
|
||||
.flatMap(backingApps -> parametersTransformationService.transformParameters(backingApps, request.getParameters()))
|
||||
.flatMap(backingApplications -> credentialProviderService.addCredentials(backingApplications, request.getServiceInstanceId()))
|
||||
.flatMapMany(deploymentService::deploy)
|
||||
.doOnRequest(l -> log.info("Deploying applications {}", brokeredServices))
|
||||
.doOnEach(s -> log.info("Finished deploying {}", s))
|
||||
.doOnComplete(() -> log.info("Finished deploying applications {}", brokeredServices))
|
||||
.doOnError(e -> log.info("Error deploying applications {} with error {}", brokeredServices, e))
|
||||
.flatMap(apps -> Flux.empty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ import reactor.util.Logger;
|
||||
import reactor.util.Loggers;
|
||||
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingServicesProvisionService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderService;
|
||||
import org.springframework.cloud.appbroker.extensions.targets.TargetService;
|
||||
@@ -40,29 +41,35 @@ public class AppDeploymentDeleteServiceInstanceWorkflow
|
||||
private final BackingAppDeploymentService deploymentService;
|
||||
private final CredentialProviderService credentialProviderService;
|
||||
private final TargetService targetService;
|
||||
private final BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
public AppDeploymentDeleteServiceInstanceWorkflow(BrokeredServices brokeredServices,
|
||||
BackingAppDeploymentService deploymentService,
|
||||
CredentialProviderService credentialProviderService,
|
||||
TargetService targetService) {
|
||||
TargetService targetService,
|
||||
BackingServicesProvisionService backingServicesProvisionService) {
|
||||
super(brokeredServices);
|
||||
this.deploymentService = deploymentService;
|
||||
this.credentialProviderService = credentialProviderService;
|
||||
this.targetService = targetService;
|
||||
this.backingServicesProvisionService = backingServicesProvisionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<Void> delete(DeleteServiceInstanceRequest request) {
|
||||
return getBackingApplicationsForService(request.getServiceDefinition(), request.getPlanId())
|
||||
.flatMap(backingApplications ->
|
||||
credentialProviderService.deleteCredentials(backingApplications, request.getServiceInstanceId()))
|
||||
.flatMap(backingApps -> targetService.add(backingApps, request.getServiceInstanceId()))
|
||||
.flatMapMany(deploymentService::undeploy)
|
||||
.doOnRequest(l -> log.info("Undeploying applications {}", brokeredServices))
|
||||
.doOnEach(s -> log.info("Finished undeploying {}", s))
|
||||
.doOnComplete(() -> log.info("Finished undeploying applications {}", brokeredServices))
|
||||
.doOnError(e -> log.info("Error undeploying applications {} with error {}", brokeredServices, e))
|
||||
.flatMap(apps -> Flux.empty());
|
||||
return
|
||||
getBackingServicesForService(request.getServiceDefinition(), request.getPlanId())
|
||||
.flatMapMany(backingServicesProvisionService::deleteServiceInstance)
|
||||
.thenMany(
|
||||
getBackingApplicationsForService(request.getServiceDefinition(), request.getPlanId())
|
||||
.flatMap(backingApplications -> credentialProviderService.deleteCredentials(backingApplications, request.getServiceInstanceId()))
|
||||
.flatMap(backingApps -> targetService.add(backingApps, request.getServiceInstanceId()))
|
||||
.flatMapMany(deploymentService::undeploy)
|
||||
.doOnRequest(l -> log.info("Undeploying applications {}", brokeredServices))
|
||||
.doOnEach(s -> log.info("Finished undeploying {}", s))
|
||||
.doOnComplete(() -> log.info("Finished undeploying applications {}", brokeredServices))
|
||||
.doOnError(e -> log.info("Error undeploying applications {} with error {}", brokeredServices, e))
|
||||
.flatMap(apps -> Flux.empty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,14 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.appbroker.workflow.instance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.appbroker.deployer.BackingApplication;
|
||||
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.BrokeredService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.servicebroker.model.catalog.ServiceDefinition;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class AppDeploymentInstanceWorkflow {
|
||||
|
||||
@@ -44,25 +47,38 @@ class AppDeploymentInstanceWorkflow {
|
||||
Mono.justOrEmpty(findBackingApplications(serviceDefinition, planId)));
|
||||
}
|
||||
|
||||
Mono<List<BackingService>> getBackingServicesForService(ServiceDefinition serviceDefinition, String planId) {
|
||||
return Mono.defer(() ->
|
||||
Mono.justOrEmpty(findBackingServices(serviceDefinition, planId)));
|
||||
}
|
||||
|
||||
private BackingApplications findBackingApplications(ServiceDefinition serviceDefinition,
|
||||
String planId) {
|
||||
BrokeredService brokeredService = findBrokeredService(serviceDefinition, planId);
|
||||
return brokeredService == null ? null : new BackingApplications(brokeredService.getApps());
|
||||
}
|
||||
|
||||
private BackingServices findBackingServices(ServiceDefinition serviceDefinition,
|
||||
String planId) {
|
||||
BrokeredService brokeredService = findBrokeredService(serviceDefinition, planId);
|
||||
return brokeredService == null || brokeredService.getServices() == null
|
||||
? null
|
||||
: new BackingServices(brokeredService.getServices());
|
||||
}
|
||||
|
||||
private BrokeredService findBrokeredService(ServiceDefinition serviceDefinition,
|
||||
String planId) {
|
||||
String serviceName = serviceDefinition.getName();
|
||||
|
||||
String planName = serviceDefinition.getPlans().stream()
|
||||
.filter(plan -> plan.getId().equals(planId))
|
||||
.findFirst().get().getName();
|
||||
.filter(plan -> plan.getId().equals(planId))
|
||||
.findFirst().get().getName();
|
||||
|
||||
return brokeredServices.stream()
|
||||
.filter(brokeredService ->
|
||||
brokeredService.getServiceName().equals(serviceName)
|
||||
&& brokeredService.getPlanName().equals(planName))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
.filter(brokeredService ->
|
||||
brokeredService.getServiceName().equals(serviceName)
|
||||
&& brokeredService.getPlanName().equals(planName))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.springframework.cloud.appbroker.deployer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
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 org.mockito.Mockito.doReturn;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class BackingServicesProvisionServiceTest {
|
||||
|
||||
@Mock
|
||||
private DeployerClient deployerClient;
|
||||
|
||||
private BackingServicesProvisionService backingServicesProvisionService;
|
||||
private BackingServices backingServices;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
backingServicesProvisionService = new BackingServicesProvisionService(deployerClient);
|
||||
backingServices = BackingServices.builder()
|
||||
.backingService(BackingService.builder()
|
||||
.serviceInstanceName("si1")
|
||||
.name("service1")
|
||||
.plan("standard")
|
||||
.parameters(Collections.singletonMap("key1", "value1"))
|
||||
.build())
|
||||
.backingService(BackingService.builder()
|
||||
.serviceInstanceName("si2")
|
||||
.name("service2")
|
||||
.plan("free")
|
||||
.parameters(Collections.singletonMap("key2", "value2"))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("UnassignedFluxMonoInstance")
|
||||
void shouldCreateServiceInstance() {
|
||||
doReturn(Mono.just("si1"))
|
||||
.when(deployerClient).createServiceInstance(backingServices.get(0));
|
||||
doReturn(Mono.just("si2"))
|
||||
.when(deployerClient).createServiceInstance(backingServices.get(1));
|
||||
|
||||
List<String> expectedValues = new ArrayList<>();
|
||||
expectedValues.add("si1");
|
||||
expectedValues.add("si2");
|
||||
|
||||
StepVerifier.create(backingServicesProvisionService.createServiceInstance(backingServices))
|
||||
// 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();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("UnassignedFluxMonoInstance")
|
||||
void shouldDeleteServiceInstance() {
|
||||
doReturn(Mono.just("deleted1"))
|
||||
.when(deployerClient).deleteServiceInstance(backingServices.get(0));
|
||||
doReturn(Mono.just("deleted2"))
|
||||
.when(deployerClient).deleteServiceInstance(backingServices.get(1));
|
||||
|
||||
List<String> expectedValues = new ArrayList<>();
|
||||
expectedValues.add("deleted1");
|
||||
expectedValues.add("deleted2");
|
||||
|
||||
StepVerifier.create(backingServicesProvisionService.deleteServiceInstance(backingServices))
|
||||
// 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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,6 +31,9 @@ import reactor.test.StepVerifier;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingApplication;
|
||||
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.BrokeredService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderService;
|
||||
@@ -62,7 +65,11 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
@Mock
|
||||
private TargetService targetService;
|
||||
|
||||
@Mock
|
||||
private BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
private BackingApplications backingApps;
|
||||
private BackingServices backingServices;
|
||||
|
||||
private CreateServiceInstanceWorkflow createServiceInstanceWorkflow;
|
||||
|
||||
@@ -82,6 +89,16 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
.build())
|
||||
.build();
|
||||
|
||||
backingServices = BackingServices
|
||||
.builder()
|
||||
.backingService(BackingService
|
||||
.builder()
|
||||
.name("my-service")
|
||||
.plan("a-plan")
|
||||
.serviceInstanceName("my-service-instance")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
BrokeredServices brokeredServices = BrokeredServices
|
||||
.builder()
|
||||
.service(BrokeredService
|
||||
@@ -89,6 +106,7 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
.serviceName("service1")
|
||||
.planName("plan1")
|
||||
.apps(backingApps)
|
||||
.services(backingServices)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
@@ -97,7 +115,8 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
backingAppDeploymentService,
|
||||
parametersTransformationService,
|
||||
credentialProviderService,
|
||||
targetService);
|
||||
targetService,
|
||||
backingServicesProvisionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -105,14 +124,7 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
void createServiceInstanceSucceeds() {
|
||||
CreateServiceInstanceRequest request = buildRequest("service1", "plan1");
|
||||
|
||||
given(this.backingAppDeploymentService.deploy(eq(backingApps)))
|
||||
.willReturn(Flux.just("app1", "app2"));
|
||||
given(this.parametersTransformationService.transformParameters(eq(backingApps), eq(request.getParameters())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.credentialProviderService.addCredentials(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.targetService.add(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
setupMocks(request);
|
||||
|
||||
StepVerifier
|
||||
.create(createServiceInstanceWorkflow.create(request))
|
||||
@@ -121,6 +133,7 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
.verifyComplete();
|
||||
|
||||
verify(backingAppDeploymentService).deploy(backingApps);
|
||||
verify(backingServicesProvisionService).createServiceInstance(backingServices);
|
||||
|
||||
verifyNoMoreInteractionsWithServices();
|
||||
}
|
||||
@@ -130,14 +143,7 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
CreateServiceInstanceRequest request = buildRequest("service1", "plan1",
|
||||
singletonMap("ENV_VAR_1", "value from parameters"));
|
||||
|
||||
given(this.backingAppDeploymentService.deploy(eq(backingApps)))
|
||||
.willReturn(Flux.just("app1", "app2"));
|
||||
given(this.parametersTransformationService.transformParameters(eq(backingApps), eq(request.getParameters())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.credentialProviderService.addCredentials(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.targetService.add(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
setupMocks(request);
|
||||
|
||||
StepVerifier
|
||||
.create(createServiceInstanceWorkflow.create(request))
|
||||
@@ -155,14 +161,7 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
CreateServiceInstanceRequest request = buildRequest("service1", "plan1",
|
||||
singletonMap("ENV_VAR_1", "value from parameters"));
|
||||
|
||||
given(this.backingAppDeploymentService.deploy(eq(backingApps)))
|
||||
.willReturn(Flux.just("app1", "app2"));
|
||||
given(this.parametersTransformationService.transformParameters(eq(backingApps), eq(request.getParameters())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.credentialProviderService.addCredentials(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.targetService.add(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
setupMocks(request);
|
||||
|
||||
StepVerifier
|
||||
.create(createServiceInstanceWorkflow.create(request))
|
||||
@@ -187,11 +186,25 @@ class AppDeploymentCreateServiceInstanceWorkflowTest {
|
||||
verifyNoMoreInteractionsWithServices();
|
||||
}
|
||||
|
||||
private void setupMocks(CreateServiceInstanceRequest request) {
|
||||
given(this.backingAppDeploymentService.deploy(eq(backingApps)))
|
||||
.willReturn(Flux.just("app1", "app2"));
|
||||
given(this.parametersTransformationService.transformParameters(eq(backingApps), eq(request.getParameters())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.credentialProviderService.addCredentials(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.targetService.add(eq(backingApps), eq(request.getServiceInstanceId())))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.backingServicesProvisionService.createServiceInstance(eq(backingServices)))
|
||||
.willReturn(Flux.just("my-service-instance"));
|
||||
}
|
||||
|
||||
private void verifyNoMoreInteractionsWithServices() {
|
||||
verifyNoMoreInteractions(this.backingAppDeploymentService);
|
||||
verifyNoMoreInteractions(this.parametersTransformationService);
|
||||
verifyNoMoreInteractions(this.credentialProviderService);
|
||||
verifyNoMoreInteractions(this.targetService);
|
||||
verifyNoMoreInteractions(this.backingServicesProvisionService);
|
||||
}
|
||||
|
||||
private CreateServiceInstanceRequest buildRequest(String serviceName, String planName) {
|
||||
|
||||
@@ -28,6 +28,9 @@ import reactor.test.StepVerifier;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingAppDeploymentService;
|
||||
import org.springframework.cloud.appbroker.deployer.BackingApplication;
|
||||
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.BrokeredService;
|
||||
import org.springframework.cloud.appbroker.deployer.BrokeredServices;
|
||||
import org.springframework.cloud.appbroker.extensions.credentials.CredentialProviderService;
|
||||
@@ -53,30 +56,49 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
@Mock
|
||||
private CredentialProviderService credentialProviderService;
|
||||
|
||||
private DeleteServiceInstanceWorkflow deleteServiceInstanceWorkflow;
|
||||
@Mock
|
||||
private BackingServicesProvisionService backingServicesProvisionService;
|
||||
|
||||
private BackingApplications backingApps;
|
||||
private BackingServices backingServices;
|
||||
|
||||
private DeleteServiceInstanceWorkflow deleteServiceInstanceWorkflow;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
backingApps = BackingApplications
|
||||
.builder()
|
||||
.backingApplication(BackingApplication.builder()
|
||||
.name("app1")
|
||||
.path("http://myfiles/app1.jar")
|
||||
.build())
|
||||
.backingApplication(BackingApplication.builder()
|
||||
.name("app2")
|
||||
.path("http://myfiles/app2.jar")
|
||||
.build())
|
||||
.backingApplication(BackingApplication
|
||||
.builder()
|
||||
.name("app1")
|
||||
.path("http://myfiles/app1.jar")
|
||||
.build())
|
||||
.backingApplication(BackingApplication
|
||||
.builder()
|
||||
.name("app2")
|
||||
.path("http://myfiles/app2.jar")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
backingServices = BackingServices
|
||||
.builder()
|
||||
.backingService(BackingService
|
||||
.builder()
|
||||
.name("my-service")
|
||||
.plan("a-plan")
|
||||
.serviceInstanceName("my-service-instance")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
BrokeredServices brokeredServices = BrokeredServices
|
||||
.builder()
|
||||
.service(BrokeredService.builder()
|
||||
.serviceName("service1")
|
||||
.planName("plan1")
|
||||
.apps(backingApps)
|
||||
.build())
|
||||
.service(BrokeredService
|
||||
.builder()
|
||||
.serviceName("service1")
|
||||
.planName("plan1")
|
||||
.apps(backingApps)
|
||||
.services(backingServices)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
deleteServiceInstanceWorkflow =
|
||||
@@ -84,7 +106,8 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
brokeredServices,
|
||||
backingAppDeploymentService,
|
||||
credentialProviderService,
|
||||
targetService);
|
||||
targetService,
|
||||
backingServicesProvisionService);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,6 +120,8 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.targetService.add(eq(backingApps), eq("service-instance-id")))
|
||||
.willReturn(Mono.just(backingApps));
|
||||
given(this.backingServicesProvisionService.deleteServiceInstance(eq(backingServices)))
|
||||
.willReturn(Flux.just("my-service-instance"));
|
||||
|
||||
StepVerifier
|
||||
.create(deleteServiceInstanceWorkflow.delete(request))
|
||||
@@ -104,9 +129,7 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
.expectNext()
|
||||
.verifyComplete();
|
||||
|
||||
verifyNoMoreInteractions(this.backingAppDeploymentService);
|
||||
verifyNoMoreInteractions(this.credentialProviderService);
|
||||
verifyNoMoreInteractions(this.targetService);
|
||||
verifyNoMoreInteractionsWithServices();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -115,6 +138,11 @@ class AppDeploymentDeleteServiceInstanceWorkflowTest {
|
||||
.create(deleteServiceInstanceWorkflow.delete(buildRequest("unsupported-service", "plan1")))
|
||||
.verifyComplete();
|
||||
|
||||
verifyNoMoreInteractionsWithServices();
|
||||
}
|
||||
|
||||
private void verifyNoMoreInteractionsWithServices() {
|
||||
verifyNoMoreInteractions(this.backingServicesProvisionService);
|
||||
verifyNoMoreInteractions(this.backingAppDeploymentService);
|
||||
verifyNoMoreInteractions(this.credentialProviderService);
|
||||
verifyNoMoreInteractions(this.targetService);
|
||||
|
||||
@@ -21,10 +21,12 @@ import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -45,14 +47,22 @@ import org.cloudfoundry.operations.applications.PushApplicationManifestRequest;
|
||||
import org.cloudfoundry.operations.applications.Route;
|
||||
import org.cloudfoundry.operations.organizations.OrganizationDetail;
|
||||
import org.cloudfoundry.operations.organizations.OrganizationInfoRequest;
|
||||
import org.cloudfoundry.operations.services.GetServiceInstanceRequest;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import reactor.core.Exceptions;
|
||||
import reactor.core.publisher.Flux;
|
||||
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.DeleteServiceInstanceRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteServiceInstanceResponse;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployApplicationRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployApplicationResponse;
|
||||
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
|
||||
@@ -494,4 +504,54 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<CreateServiceInstanceResponse> createServiceInstance(CreateServiceInstanceRequest request) {
|
||||
return this.operations
|
||||
.services()
|
||||
.createInstance(
|
||||
org.cloudfoundry.operations.services.CreateServiceInstanceRequest
|
||||
.builder()
|
||||
.serviceInstanceName(request.getServiceInstanceName())
|
||||
.serviceName(request.getName())
|
||||
.planName(request.getPlan())
|
||||
.parameters(request.getParameters())
|
||||
.build())
|
||||
.then(Mono.just(CreateServiceInstanceResponse.builder().name(request.getServiceInstanceName()).build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<DeleteServiceInstanceResponse> deleteServiceInstance(DeleteServiceInstanceRequest request) {
|
||||
final String serviceInstanceName = request.getName();
|
||||
return this.operations
|
||||
.services()
|
||||
.getInstance(GetServiceInstanceRequest.builder().name(serviceInstanceName).build())
|
||||
.map(ServiceInstance::getApplications)
|
||||
.flatMap(unbindApplications(serviceInstanceName))
|
||||
.then(
|
||||
this.operations
|
||||
.services()
|
||||
.deleteInstance(
|
||||
org.cloudfoundry.operations.services.DeleteServiceInstanceRequest
|
||||
.builder()
|
||||
.name(serviceInstanceName)
|
||||
.build())
|
||||
.then(Mono.just(DeleteServiceInstanceResponse.builder().name(serviceInstanceName).build())));
|
||||
}
|
||||
|
||||
private Function<List<String>, Mono<?>> unbindApplications(String serviceInstanceName) {
|
||||
return applications ->
|
||||
Flux.fromIterable(applications)
|
||||
.flatMap(
|
||||
application ->
|
||||
this.operations
|
||||
.services()
|
||||
.unbind(
|
||||
UnbindServiceInstanceRequest
|
||||
.builder()
|
||||
.applicationName(application)
|
||||
.serviceInstanceName(serviceInstanceName)
|
||||
.build())
|
||||
).collectList();
|
||||
}
|
||||
}
|
||||
@@ -25,18 +25,26 @@ import org.cloudfoundry.operations.applications.ApplicationHealthCheck;
|
||||
import org.cloudfoundry.operations.applications.ApplicationManifest;
|
||||
import org.cloudfoundry.operations.applications.Applications;
|
||||
import org.cloudfoundry.operations.applications.PushApplicationManifestRequest;
|
||||
import org.cloudfoundry.operations.services.GetServiceInstanceRequest;
|
||||
import org.cloudfoundry.operations.services.ServiceInstance;
|
||||
import org.cloudfoundry.operations.services.ServiceInstanceType;
|
||||
import org.cloudfoundry.operations.services.Services;
|
||||
import org.cloudfoundry.operations.services.UnbindServiceInstanceRequest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.cloud.appbroker.deployer.AppDeployer;
|
||||
import org.springframework.cloud.appbroker.deployer.DeleteServiceInstanceRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.DeployApplicationRequest;
|
||||
import org.springframework.cloud.appbroker.deployer.DeploymentProperties;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
@@ -48,6 +56,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
@SuppressWarnings("UnassignedFluxMonoInstance")
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class CloudFoundryAppDeployerTest {
|
||||
|
||||
private static final String APP_NAME = "test-app";
|
||||
@@ -58,6 +67,9 @@ class CloudFoundryAppDeployerTest {
|
||||
@Mock
|
||||
private Applications applications;
|
||||
|
||||
@Mock
|
||||
private Services services;
|
||||
|
||||
@Mock
|
||||
private CloudFoundryOperations cloudFoundryOperations;
|
||||
|
||||
@@ -81,6 +93,9 @@ class CloudFoundryAppDeployerTest {
|
||||
when(resourceLoader.getResource(APP_PATH))
|
||||
.thenReturn(new FileSystemResource(APP_PATH));
|
||||
|
||||
when(cloudFoundryOperations.services())
|
||||
.thenReturn(services);
|
||||
|
||||
appDeployer = new CloudFoundryAppDeployer(deploymentProperties,
|
||||
cloudFoundryOperations, cloudFoundryClient, targetProperties, resourceLoader);
|
||||
}
|
||||
@@ -276,6 +291,46 @@ class CloudFoundryAppDeployerTest {
|
||||
verify(applications).pushManifest(argThat(matchesManifest(expectedManifest)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteServiceInstanceShouldUnbindServices() {
|
||||
when(services.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()))
|
||||
.thenReturn(Mono.just(ServiceInstance.builder()
|
||||
.id("siid")
|
||||
.type(ServiceInstanceType.MANAGED)
|
||||
.name("service-instance-name")
|
||||
.applications("app1", "app2")
|
||||
.build()));
|
||||
|
||||
when(services.unbind(UnbindServiceInstanceRequest.builder()
|
||||
.serviceInstanceName("service-instance-name")
|
||||
.applicationName("app1")
|
||||
.build()))
|
||||
.thenReturn(Mono.empty());
|
||||
|
||||
when(services.unbind(UnbindServiceInstanceRequest.builder()
|
||||
.serviceInstanceName("service-instance-name")
|
||||
.applicationName("app2")
|
||||
.build()))
|
||||
.thenReturn(Mono.empty());
|
||||
|
||||
DeleteServiceInstanceRequest request =
|
||||
DeleteServiceInstanceRequest.builder()
|
||||
.name("service-instance-name")
|
||||
.build();
|
||||
|
||||
StepVerifier.create(
|
||||
appDeployer.deleteServiceInstance(request))
|
||||
.assertNext(response -> assertThat(response.getName()).isEqualTo("service-instance-name"))
|
||||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
private ApplicationManifest.Builder baseManifest() {
|
||||
return ApplicationManifest.builder()
|
||||
.environmentVariable("SPRING_APPLICATION_INDEX", "${vcap.application.instance_index}")
|
||||
|
||||
@@ -28,4 +28,12 @@ public interface AppDeployer {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
default Mono<CreateServiceInstanceResponse> createServiceInstance(CreateServiceInstanceRequest request) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
default Mono<DeleteServiceInstanceResponse> deleteServiceInstance(DeleteServiceInstanceRequest request) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* http://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.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CreateServiceInstanceRequest {
|
||||
|
||||
private final String serviceInstanceName;
|
||||
private final String name;
|
||||
private final String plan;
|
||||
private final Map<String, String> parameters;
|
||||
private final String target;
|
||||
|
||||
CreateServiceInstanceRequest(String serviceInstanceName,
|
||||
String name,
|
||||
String plan,
|
||||
Map<String, String> parameters,
|
||||
String target) {
|
||||
this.serviceInstanceName = serviceInstanceName;
|
||||
this.name = name;
|
||||
this.plan = plan;
|
||||
this.parameters = parameters;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static CreateServiceInstanceRequestBuilder builder() {
|
||||
return new CreateServiceInstanceRequestBuilder();
|
||||
}
|
||||
|
||||
public String getServiceInstanceName() {
|
||||
return serviceInstanceName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getPlan() {
|
||||
return plan;
|
||||
}
|
||||
|
||||
public Map<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public static class CreateServiceInstanceRequestBuilder {
|
||||
|
||||
private String serviceInstanceName;
|
||||
private String name;
|
||||
private String plan;
|
||||
private final Map<String, String> parameters = new HashMap<>();
|
||||
private String target;
|
||||
|
||||
CreateServiceInstanceRequestBuilder() {
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequestBuilder serviceInstanceName(String serviceInstanceName) {
|
||||
this.serviceInstanceName = serviceInstanceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequestBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequestBuilder plan(String plan) {
|
||||
this.plan = plan;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequestBuilder parameters(String key, String value) {
|
||||
this.parameters.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequestBuilder parameters(Map<String, String> parameters) {
|
||||
if (parameters == null) {
|
||||
return this;
|
||||
}
|
||||
this.parameters.putAll(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequestBuilder target(String target) {
|
||||
this.target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceRequest build() {
|
||||
return new CreateServiceInstanceRequest(serviceInstanceName, name, plan, parameters, target);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* http://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 CreateServiceInstanceResponse {
|
||||
|
||||
private final String name;
|
||||
|
||||
CreateServiceInstanceResponse(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static CreateServiceInstanceResponseBuilder builder() {
|
||||
return new CreateServiceInstanceResponseBuilder();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static class CreateServiceInstanceResponseBuilder {
|
||||
|
||||
private String name;
|
||||
|
||||
CreateServiceInstanceResponseBuilder() {
|
||||
}
|
||||
|
||||
public CreateServiceInstanceResponseBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CreateServiceInstanceResponse build() {
|
||||
return new CreateServiceInstanceResponse(name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* http://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 DeleteServiceInstanceRequest {
|
||||
|
||||
private final String name;
|
||||
|
||||
DeleteServiceInstanceRequest(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static DeleteServiceInstanceRequestBuilder builder() {
|
||||
return new DeleteServiceInstanceRequestBuilder();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static class DeleteServiceInstanceRequestBuilder {
|
||||
|
||||
private String name;
|
||||
|
||||
DeleteServiceInstanceRequestBuilder() {
|
||||
}
|
||||
|
||||
public DeleteServiceInstanceRequestBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteServiceInstanceRequest build() {
|
||||
return new DeleteServiceInstanceRequest(name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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
|
||||
*
|
||||
* http://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 DeleteServiceInstanceResponse {
|
||||
|
||||
private final String name;
|
||||
|
||||
DeleteServiceInstanceResponse(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static DeleteServiceInstanceResponseBuilder builder() {
|
||||
return new DeleteServiceInstanceResponseBuilder();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static class DeleteServiceInstanceResponseBuilder {
|
||||
|
||||
private String name;
|
||||
|
||||
DeleteServiceInstanceResponseBuilder() {
|
||||
}
|
||||
|
||||
public DeleteServiceInstanceResponseBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeleteServiceInstanceResponse build() {
|
||||
return new DeleteServiceInstanceResponse(name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2016-2018. 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
|
||||
*
|
||||
* http://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.sample;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.appbroker.sample.fixtures.CloudControllerStubFixture;
|
||||
import org.springframework.cloud.appbroker.sample.fixtures.OpenServiceBrokerApiFixture;
|
||||
import org.springframework.cloud.servicebroker.model.instance.OperationState;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
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.sample.CreateInstanceWithServicesComponentTest.APP_NAME;
|
||||
import static org.springframework.cloud.appbroker.sample.CreateInstanceWithServicesComponentTest.SERVICE_1_NAME;
|
||||
import static org.springframework.cloud.appbroker.sample.CreateInstanceWithServicesComponentTest.SERVICE_INSTANCE_1_NAME;
|
||||
|
||||
@TestPropertySource(properties = {
|
||||
"spring.cloud.appbroker.services[0].service-name=example",
|
||||
"spring.cloud.appbroker.services[0].plan-name=standard",
|
||||
"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=" + SERVICE_INSTANCE_1_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].service-instance-name=" + SERVICE_INSTANCE_1_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].name=" + SERVICE_1_NAME,
|
||||
"spring.cloud.appbroker.services[0].services[0].plan=standard"
|
||||
})
|
||||
class CreateInstanceWithServicesComponentTest extends WiremockComponentTest {
|
||||
|
||||
static final String APP_NAME = "app-with-new-services";
|
||||
|
||||
static final String SERVICE_INSTANCE_1_NAME = "my-db-service";
|
||||
static final String SERVICE_1_NAME = "db-service";
|
||||
|
||||
@Autowired
|
||||
private OpenServiceBrokerApiFixture brokerFixture;
|
||||
|
||||
@Autowired
|
||||
private CloudControllerStubFixture cloudControllerFixture;
|
||||
|
||||
@Test
|
||||
void pushAppWithServicesWhenServicesExist() {
|
||||
cloudControllerFixture.stubAppDoesNotExist(APP_NAME);
|
||||
cloudControllerFixture.stubPushApp(APP_NAME);
|
||||
|
||||
// given that service instances does not exist
|
||||
cloudControllerFixture.stubServiceInstanceDoesNotExists(SERVICE_INSTANCE_1_NAME);
|
||||
|
||||
// and the services are available in the marketplace
|
||||
cloudControllerFixture.stubServiceExists(SERVICE_1_NAME);
|
||||
|
||||
// will create and bind the service instance
|
||||
cloudControllerFixture.stubCreateServiceInstance(SERVICE_INSTANCE_1_NAME);
|
||||
cloudControllerFixture.stubCreateServiceBinding(APP_NAME, SERVICE_INSTANCE_1_NAME);
|
||||
cloudControllerFixture.stubServiceInstanceExists(SERVICE_INSTANCE_1_NAME);
|
||||
|
||||
// when a service instance is created
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.put(brokerFixture.createServiceInstanceUrl(), "instance-id")
|
||||
.then()
|
||||
.statusCode(HttpStatus.ACCEPTED.value());
|
||||
|
||||
// when the "last_operation" API is polled
|
||||
given(brokerFixture.serviceInstanceRequest())
|
||||
.when()
|
||||
.get(brokerFixture.getLastInstanceOperationUrl(), "instance-id")
|
||||
.then()
|
||||
.statusCode(HttpStatus.OK.value())
|
||||
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
|
||||
|
||||
String state = brokerFixture.waitForAsyncOperationComplete("instance-id");
|
||||
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
|
||||
}
|
||||
}
|
||||
@@ -291,6 +291,32 @@ public class CloudControllerStubFixture extends WiremockStubFixture {
|
||||
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"))
|
||||
.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"))
|
||||
.willReturn(ok()
|
||||
.withBody(cc("list-space-services"))));
|
||||
|
||||
stubFor(get(urlEqualTo("/v2/service_plans?q=service_guid:SERVICE-ID&page=1"))
|
||||
.willReturn(ok()
|
||||
.withBody(cc("list-service-plans"))));
|
||||
}
|
||||
public void stubCreateServiceInstance(String serviceInstanceName) {
|
||||
stubFor(post(urlEqualTo("/v2/service_instances?accepts_incomplete=true"))
|
||||
.withRequestBody(matchingJsonPath("$.[?(@.name == '" + serviceInstanceName + "')]"))
|
||||
.willReturn(ok()));
|
||||
}
|
||||
|
||||
public void stubCreateServiceBinding(String appName, String serviceInstanceName) {
|
||||
String serviceInstanceGuid = serviceInstanceName + "-GUID";
|
||||
String serviceBindingGuid = appGuid(appName) + "-" + serviceInstanceGuid;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"total_results": 1,
|
||||
"total_pages": 1,
|
||||
"prev_url": null,
|
||||
"next_url": null,
|
||||
"resources": [
|
||||
{
|
||||
"metadata": {
|
||||
"guid": "SERVICE-PLAN-ID",
|
||||
"url": "/v2/service_plans/SERVICE-PLAN-ID",
|
||||
"created_at": "2018-01-26T20:48:20Z",
|
||||
"updated_at": "2018-06-11T18:08:05Z"
|
||||
},
|
||||
"entity": {
|
||||
"name": "standard",
|
||||
"free": true,
|
||||
"description": "basic",
|
||||
"service_guid": "SERVICE-ID",
|
||||
"extra": "{}",
|
||||
"public": true,
|
||||
"bindable": true,
|
||||
"active": true,
|
||||
"service_url": "/v2/services/SERVICE-ID",
|
||||
"service_instances_url": "/v2/service_plans/SERVICE-PLAN-ID/service_instances",
|
||||
"schemas": {
|
||||
"service_instance": {
|
||||
"create": {
|
||||
"parameters": {}
|
||||
},
|
||||
"update": {
|
||||
"parameters": {}
|
||||
}
|
||||
},
|
||||
"service_binding": {
|
||||
"create": {
|
||||
"parameters": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"total_results": 0,
|
||||
"total_pages": 1,
|
||||
"prev_url": null,
|
||||
"next_url": null,
|
||||
"resources": [
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"total_results": 1,
|
||||
"total_pages": 1,
|
||||
"prev_url": null,
|
||||
"next_url": null,
|
||||
"resources": [
|
||||
{
|
||||
"metadata": {
|
||||
"guid": "SERVICE-ID",
|
||||
"url": "/v2/services/SERVICE-ID",
|
||||
"created_at": "2018-01-26T20:48:20Z",
|
||||
"updated_at": "2018-06-11T18:08:05Z"
|
||||
},
|
||||
"entity": {
|
||||
"label": "db-service",
|
||||
"provider": null,
|
||||
"url": null,
|
||||
"description": "My DB Service",
|
||||
"long_description": null,
|
||||
"version": null,
|
||||
"info_url": null,
|
||||
"active": 1,
|
||||
"bindable": 1,
|
||||
"extra": "{}",
|
||||
"tags": [
|
||||
],
|
||||
"requires": [],
|
||||
"documentation_url": null,
|
||||
"plan_updateable": 0,
|
||||
"service_plans_url": "/v2/services/SERVICE-ID/service_plans"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user