Run ATs in parallel

- Split AppManagementAcceptanceTest to follow the pattern
of one test per class
This commit is contained in:
Raul Avila
2019-05-10 16:48:55 +01:00
committed by Alberto Ríos
parent ccd7ec16f1
commit 920cd7bb95
19 changed files with 703 additions and 278 deletions

View File

@@ -54,6 +54,8 @@ bootJar {
}
test {
maxParallelForks = Runtime.runtime.availableProcessors() - 1 ?: 1
// Only run the tests if acceptanceTests is specified
onlyIf {
project.hasProperty("acceptanceTests")

View File

@@ -1,35 +1,12 @@
spring:
application:
name: app-broker-acceptance
cloud:
openservicebroker:
catalog:
services:
- id: 201ae814-ff16-11e8-8eb2-f2801f1b9fd1
name: app-service
description: A service that deploys a backing app
bindable: true
plans:
- id: 201aeb3e-ff16-11e8-8eb2-f2801f1b9fd1
name: standard
bindable: true
description: A simple plan
free: true
- id: 3071bcec-ff16-11e8-8eb2-f2801f1b9fd1
name: backing-service
description: A backing service that can be bound to backing apps
bindable: true
plans:
- id: 3071bf94-ff16-11e8-8eb2-f2801f1b9fd1
name: standard
bindable: true
description: A simple plan
free: true
# appbroker:
# App Broker services configuration properties are configured individual test cases
# services:
# App Broker deployer configuration properties are configured test setup
# deployer:
#spring:
# cloud:
# openservicebroker:
# Open Service Broker configuration properties are configured test setup
# appbroker:
# services:
# App Broker services configuration properties are configured individual test cases
# deployer:
# App Broker deployer configuration properties are configured test setup
logging:
level:

View File

@@ -1,211 +0,0 @@
/*
* Copyright 2002-2019 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 javax.net.ssl.SSLException;
import java.net.URI;
import java.util.Date;
import java.util.List;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.cloudfoundry.operations.applications.ApplicationDetail;
import org.cloudfoundry.operations.services.ServiceInstance;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.netty.http.client.HttpClient;
import reactor.test.StepVerifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
class AppManagementAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String APP_1 = "app-1";
private static final String APP_2 = "app-2";
private static final String SI_NAME = "si-managed";
private final WebClient webClient = getSslIgnoringWebClient();
@BeforeEach
void setUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(cloudFoundryService.createServiceInstance(PLAN_NAME, APP_SERVICE_NAME, SI_NAME, null))
.verifyComplete();
StepVerifier.create(cloudFoundryService.getServiceInstance(SI_NAME))
.assertNext(serviceInstance -> assertThat(serviceInstance.getStatus()).isEqualTo("succeeded"))
.verifyComplete();
}
@AfterEach
void cleanUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(getApplications())
.verifyError();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void stopApps() {
StepVerifier.create(manageApps("stop"))
.assertNext(result -> assertThat(result).contains("stopping"))
.verifyComplete();
StepVerifier.create(getApplications())
.assertNext(apps -> assertThat(apps).extracting("runningInstances").containsOnly(0))
.verifyComplete();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void startApps() {
StepVerifier.create(cloudFoundryService.stopApplication(APP_1)
.then(cloudFoundryService.stopApplication(APP_2)))
.verifyComplete();
StepVerifier.create(getApplications())
.assertNext(apps -> assertThat(apps).extracting("runningInstances").containsOnly(0))
.verifyComplete();
StepVerifier.create(manageApps("start"))
.assertNext(result -> assertThat(result).contains("starting"))
.verifyComplete();
StepVerifier.create(getApplications())
.assertNext(apps -> assertThat(apps).extracting("runningInstances").containsOnly(1))
.verifyComplete();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void restartApps() {
List<ApplicationDetail> apps = getApplications().block();
Date originallySince1 = apps.get(0).getInstanceDetails().get(0).getSince();
Date originallySince2 = apps.get(1).getInstanceDetails().get(0).getSince();
StepVerifier.create(manageApps("restart"))
.assertNext(result -> assertThat(result).contains("restarting"))
.verifyComplete();
List<ApplicationDetail> restagedApps = getApplications().block();
Date since1 = restagedApps.get(0).getInstanceDetails().get(0).getSince();
Date since2 = restagedApps.get(1).getInstanceDetails().get(0).getSince();
assertThat(restagedApps).extracting("runningInstances").containsOnly(1);
assertThat(since1).isAfter(originallySince1);
assertThat(since2).isAfter(originallySince2);
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void restageApps() throws Exception {
List<ApplicationDetail> apps = getApplications().block();
Date originallySince1 = apps.get(0).getInstanceDetails().get(0).getSince();
Date originallySince2 = apps.get(1).getInstanceDetails().get(0).getSince();
assertThat(apps).extracting("runningInstances").containsOnly(1);
StepVerifier.create(manageApps("restage"))
.assertNext(result -> assertThat(result).contains("restaging"))
.verifyComplete();
List<ApplicationDetail> restagedApps = getApplications().block();
Date since1 = restagedApps.get(0).getInstanceDetails().get(0).getSince();
Date since2 = restagedApps.get(1).getInstanceDetails().get(0).getSince();
assertThat(restagedApps).extracting("runningInstances").containsOnly(1);
assertThat(since1).isAfter(originallySince1);
assertThat(since2).isAfter(originallySince2);
}
private Mono<List<ApplicationDetail>> getApplications() {
return Flux.merge(cloudFoundryService.getApplication(APP_1),
cloudFoundryService.getApplication(APP_2))
.parallel()
.runOn(Schedulers.parallel())
.sequential()
.collectList();
}
private Mono<String> manageApps(String operation) {
return cloudFoundryService.getServiceInstance(SI_NAME)
.map(ServiceInstance::getId)
.flatMap(serviceInstanceId -> cloudFoundryService.getApplicationRoute(TEST_BROKER_APP_NAME)
.flatMap(appRoute -> webClient.get()
.uri(URI.create(appRoute + "/" + operation + "/" + serviceInstanceId))
.exchange()
.flatMap(clientResponse -> clientResponse.toEntity(String.class))
.map(HttpEntity::getBody)));
}
private WebClient getSslIgnoringWebClient() {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(HttpClient
.create()
.secure(t -> {
try {
t.sslContext(SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build());
}
catch (SSLException e) {
e.printStackTrace();
}
})))
.build();
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright 2002-2019 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.Date;
import java.util.List;
import org.cloudfoundry.operations.applications.ApplicationDetail;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.test.StepVerifier;
import static org.assertj.core.api.Assertions.assertThat;
class AppManagementRestageAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String SUFFIX = "app-management-restage";
private static final String APP_1 = "app-1-" + SUFFIX;
private static final String APP_2 = "app-2" + SUFFIX;
private static final String SI_NAME = "si-managed" + SUFFIX;
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@BeforeEach
void setUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(cloudFoundryService.createServiceInstance(PLAN_NAME, APP_SERVICE_NAME, SI_NAME, null))
.verifyComplete();
StepVerifier.create(cloudFoundryService.getServiceInstance(SI_NAME))
.assertNext(serviceInstance -> assertThat(serviceInstance.getStatus()).isEqualTo("succeeded"))
.verifyComplete();
}
@AfterEach
void cleanUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.verifyError();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void restageApps() throws Exception {
List<ApplicationDetail> apps = getApplications(APP_1, APP_2).block();
Date originallySince1 = apps.get(0).getInstanceDetails().get(0).getSince();
Date originallySince2 = apps.get(1).getInstanceDetails().get(0).getSince();
assertThat(apps).extracting("runningInstances").containsOnly(1);
StepVerifier.create(manageApps(SI_NAME, "restage"))
.assertNext(result -> assertThat(result).contains("restaging"))
.verifyComplete();
List<ApplicationDetail> restagedApps = getApplications(APP_1, APP_2).block();
Date since1 = restagedApps.get(0).getInstanceDetails().get(0).getSince();
Date since2 = restagedApps.get(1).getInstanceDetails().get(0).getSince();
assertThat(restagedApps).extracting("runningInstances").containsOnly(1);
assertThat(since1).isAfter(originallySince1);
assertThat(since2).isAfter(originallySince2);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2002-2019 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.Date;
import java.util.List;
import org.cloudfoundry.operations.applications.ApplicationDetail;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.test.StepVerifier;
import static org.assertj.core.api.Assertions.assertThat;
class AppManagementRestartAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String SUFFIX = "app-management-restart";
private static final String APP_1 = "app-1-" + SUFFIX;
private static final String APP_2 = "app-2" + SUFFIX;
private static final String SI_NAME = "si-managed" + SUFFIX;
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@BeforeEach
void setUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(cloudFoundryService.createServiceInstance(PLAN_NAME, APP_SERVICE_NAME, SI_NAME, null))
.verifyComplete();
StepVerifier.create(cloudFoundryService.getServiceInstance(SI_NAME))
.assertNext(serviceInstance -> assertThat(serviceInstance.getStatus()).isEqualTo("succeeded"))
.verifyComplete();
}
@AfterEach
void cleanUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.verifyError();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void restartApps() {
List<ApplicationDetail> apps = getApplications(APP_1, APP_2).block();
Date originallySince1 = apps.get(0).getInstanceDetails().get(0).getSince();
Date originallySince2 = apps.get(1).getInstanceDetails().get(0).getSince();
StepVerifier.create(manageApps(SI_NAME, "restart"))
.assertNext(result -> assertThat(result).contains("restarting"))
.verifyComplete();
List<ApplicationDetail> restagedApps = getApplications(APP_1, APP_2).block();
Date since1 = restagedApps.get(0).getInstanceDetails().get(0).getSince();
Date since2 = restagedApps.get(1).getInstanceDetails().get(0).getSince();
assertThat(restagedApps).extracting("runningInstances").containsOnly(1);
assertThat(since1).isAfter(originallySince1);
assertThat(since2).isAfter(originallySince2);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2002-2019 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 org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.test.StepVerifier;
import static org.assertj.core.api.Assertions.assertThat;
class AppManagementStartAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String SUFFIX = "app-management-start";
private static final String APP_1 = "app-1-" + SUFFIX;
private static final String APP_2 = "app-2" + SUFFIX;
private static final String SI_NAME = "si-managed" + SUFFIX;
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@BeforeEach
void setUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(cloudFoundryService.createServiceInstance(PLAN_NAME, APP_SERVICE_NAME, SI_NAME, null))
.verifyComplete();
StepVerifier.create(cloudFoundryService.getServiceInstance(SI_NAME))
.assertNext(serviceInstance -> assertThat(serviceInstance.getStatus()).isEqualTo("succeeded"))
.verifyComplete();
}
@AfterEach
void cleanUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.verifyError();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void startApps() {
StepVerifier.create(cloudFoundryService.stopApplication(APP_1)
.then(cloudFoundryService.stopApplication(APP_2)))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.assertNext(apps -> assertThat(apps).extracting("runningInstances").containsOnly(0))
.verifyComplete();
StepVerifier.create(manageApps(SI_NAME, "start"))
.assertNext(result -> assertThat(result).contains("starting"))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.assertNext(apps -> assertThat(apps).extracting("runningInstances").containsOnly(1))
.verifyComplete();
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2002-2019 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 org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.test.StepVerifier;
import static org.assertj.core.api.Assertions.assertThat;
class AppManagementStopAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String SUFFIX = "app-management-stop";
private static final String APP_1 = "app-1-" + SUFFIX;
private static final String APP_2 = "app-2" + SUFFIX;
private static final String SI_NAME = "si-managed" + SUFFIX;
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@BeforeEach
void setUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(cloudFoundryService.createServiceInstance(PLAN_NAME, APP_SERVICE_NAME, SI_NAME, null))
.verifyComplete();
StepVerifier.create(cloudFoundryService.getServiceInstance(SI_NAME))
.assertNext(serviceInstance -> assertThat(serviceInstance.getStatus()).isEqualTo("succeeded"))
.verifyComplete();
}
@AfterEach
void cleanUp() {
StepVerifier.create(cloudFoundryService.deleteServiceInstance(SI_NAME))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.verifyError();
}
@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_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[1].name=" + APP_2,
"spring.cloud.appbroker.services[0].apps[1].path=" + BACKING_APP_PATH
})
void stopApps() {
StepVerifier.create(manageApps(SI_NAME, "stop"))
.assertNext(result -> assertThat(result).contains("stopping"))
.verifyComplete();
StepVerifier.create(getApplications(APP_1, APP_2))
.assertNext(apps -> assertThat(apps).extracting("runningInstances").containsOnly(0))
.verifyComplete();
}
}

View File

@@ -16,6 +16,8 @@
package org.springframework.cloud.appbroker.acceptance;
import javax.net.ssl.SSLException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
@@ -24,6 +26,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import com.jayway.jsonpath.Configuration;
@@ -34,6 +37,10 @@ import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import org.apache.commons.lang3.ArrayUtils;
import org.cloudfoundry.operations.applications.ApplicationDetail;
import org.cloudfoundry.operations.applications.ApplicationEnvironments;
import org.cloudfoundry.operations.applications.ApplicationSummary;
import org.cloudfoundry.operations.organizations.OrganizationSummary;
@@ -45,6 +52,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.netty.http.client.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -52,15 +61,17 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration;
import org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryService;
import org.springframework.cloud.appbroker.acceptance.fixtures.uaa.UaaService;
import org.springframework.http.HttpEntity;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration.ACCEPTANCE_TEST_OAUTH_CLIENT_AUTHORITIES;
import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration.ACCEPTANCE_TEST_OAUTH_CLIENT_ID;
import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration.ACCEPTANCE_TEST_OAUTH_CLIENT_SECRET;
import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration.APP_BROKER_CLIENT_AUTHORITIES;
import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration.APP_BROKER_CLIENT_ID;
import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFoundryClientConfiguration.APP_BROKER_CLIENT_SECRET;
@SpringBootTest(classes = {
@@ -73,13 +84,8 @@ import static org.springframework.cloud.appbroker.acceptance.fixtures.cf.CloudFo
@ExtendWith(SpringExtension.class)
@ExtendWith(BrokerPropertiesParameterResolver.class)
@EnableConfigurationProperties(AcceptanceTestProperties.class)
class CloudFoundryAcceptanceTest {
abstract class CloudFoundryAcceptanceTest {
static final String TEST_BROKER_APP_NAME = "test-broker-app";
private static final String SERVICE_BROKER_NAME = "test-broker";
static final String APP_SERVICE_NAME = "app-service";
static final String BACKING_SERVICE_NAME = "backing-service";
static final String PLAN_NAME = "standard";
static final String BACKING_APP_PATH = "classpath:backing-app.jar";
@@ -92,9 +98,52 @@ class CloudFoundryAcceptanceTest {
@Autowired
private AcceptanceTestProperties acceptanceTestProperties;
private final WebClient webClient = getSslIgnoringWebClient();
protected abstract String testSuffix();
protected abstract String appServiceName();
protected abstract String backingServiceName();
private String testBrokerAppName() {
return "test-broker-app-" + testSuffix();
}
private String serviceBrokerName() {
return "test-broker-" + testSuffix();
}
private String brokerClientId() {
return appServiceName();
}
@BeforeEach
void setUp(BrokerProperties brokerProperties) {
blockingSubscribe(initializeBroker(brokerProperties.getProperties()));
String[] openServiceBrokerProperties = {
"spring.cloud.openservicebroker.catalog.services[0].id=" + UUID.randomUUID().toString(),
"spring.cloud.openservicebroker.catalog.services[0].name=" + appServiceName(),
"spring.cloud.openservicebroker.catalog.services[0].description=A service that deploys a backing app",
"spring.cloud.openservicebroker.catalog.services[0].bindable=true",
"spring.cloud.openservicebroker.catalog.services[0].plans[0].id=" + UUID.randomUUID().toString() ,
"spring.cloud.openservicebroker.catalog.services[0].plans[0].name=standard",
"spring.cloud.openservicebroker.catalog.services[0].plans[0].bindable=true",
"spring.cloud.openservicebroker.catalog.services[0].plans[0].description=A simple plan",
"spring.cloud.openservicebroker.catalog.services[0].plans[0].free=true",
"spring.cloud.openservicebroker.catalog.services[1].id=" + UUID.randomUUID().toString(),
"spring.cloud.openservicebroker.catalog.services[1].name=" + backingServiceName(),
"spring.cloud.openservicebroker.catalog.services[1].description=A backing service that can be bound to backing apps",
"spring.cloud.openservicebroker.catalog.services[1].bindable=true",
"spring.cloud.openservicebroker.catalog.services[1].plans[0].id=" + UUID.randomUUID().toString(),
"spring.cloud.openservicebroker.catalog.services[1].plans[0].name=standard",
"spring.cloud.openservicebroker.catalog.services[1].plans[0].bindable=true",
"spring.cloud.openservicebroker.catalog.services[1].plans[0].description=A simple plan",
"spring.cloud.openservicebroker.catalog.services[1].plans[0].free=true"
};
String[] appBrokerProperties = ArrayUtils.addAll(
openServiceBrokerProperties,
brokerProperties.getProperties());
blockingSubscribe(initializeBroker(appBrokerProperties));
}
@BeforeEach
@@ -142,20 +191,20 @@ class CloudFoundryAcceptanceTest {
ACCEPTANCE_TEST_OAUTH_CLIENT_SECRET,
ACCEPTANCE_TEST_OAUTH_CLIENT_AUTHORITIES))
.then(uaaService.createClient(
APP_BROKER_CLIENT_ID,
brokerClientId(),
APP_BROKER_CLIENT_SECRET,
APP_BROKER_CLIENT_AUTHORITIES))
.then(cloudFoundryService.associateAppBrokerClientWithOrgAndSpace(orgId, spaceId))
.then(cloudFoundryService.pushBrokerApp(TEST_BROKER_APP_NAME, getTestBrokerAppPath(), appBrokerProperties))
.then(cloudFoundryService.createServiceBroker(SERVICE_BROKER_NAME, TEST_BROKER_APP_NAME))
.then(cloudFoundryService.enableServiceBrokerAccess(APP_SERVICE_NAME))
.then(cloudFoundryService.enableServiceBrokerAccess(BACKING_SERVICE_NAME))));
.then(cloudFoundryService.associateAppBrokerClientWithOrgAndSpace(brokerClientId(), orgId, spaceId))
.then(cloudFoundryService.pushBrokerApp(testBrokerAppName(), getTestBrokerAppPath(), brokerClientId(), appBrokerProperties))
.then(cloudFoundryService.createServiceBroker(serviceBrokerName(), testBrokerAppName()))
.then(cloudFoundryService.enableServiceBrokerAccess(appServiceName()))
.then(cloudFoundryService.enableServiceBrokerAccess(backingServiceName()))));
}
private Mono<Void> cleanup(String orgId, String spaceId) {
return cloudFoundryService.deleteServiceBroker(SERVICE_BROKER_NAME)
.then(cloudFoundryService.deleteApp(TEST_BROKER_APP_NAME))
.then(cloudFoundryService.removeAppBrokerClientFromOrgAndSpace(orgId, spaceId))
return cloudFoundryService.deleteServiceBroker(serviceBrokerName())
.then(cloudFoundryService.deleteApp(testBrokerAppName()))
.then(cloudFoundryService.removeAppBrokerClientFromOrgAndSpace(brokerClientId(), orgId, spaceId))
.onErrorResume(e -> Mono.empty());
}
@@ -164,7 +213,7 @@ class CloudFoundryAcceptanceTest {
}
void createServiceInstance(String serviceInstanceName, Map<String, Object> parameters) {
createServiceInstance(APP_SERVICE_NAME, PLAN_NAME, serviceInstanceName, parameters);
createServiceInstance(appServiceName(), PLAN_NAME, serviceInstanceName, parameters);
}
void createServiceInstance(String serviceName,
@@ -237,10 +286,6 @@ class CloudFoundryAcceptanceTest {
return cloudFoundryService.getApplicationEnvironment(appName, space).block();
}
String getTestBrokerAppRoute() {
return cloudFoundryService.getApplicationRoute(TEST_BROKER_APP_NAME).block();
}
DocumentContext getSpringAppJson(String appName) {
ApplicationEnvironments env = getApplicationEnvironment(appName);
String saj = (String) env.getUserProvided().get("SPRING_APPLICATION_JSON");
@@ -280,4 +325,46 @@ class CloudFoundryAcceptanceTest {
}
}
Mono<String> manageApps(String serviceInstanceName, String operation) {
return cloudFoundryService
.getServiceInstance(serviceInstanceName)
.map(ServiceInstance::getId)
.flatMap(serviceInstanceId ->
cloudFoundryService
.getApplicationRoute(testBrokerAppName())
.flatMap(appRoute ->
webClient.get()
.uri(URI.create(appRoute + "/" + operation + "/" + serviceInstanceId))
.exchange()
.flatMap(clientResponse -> clientResponse.toEntity(String.class))
.map(HttpEntity::getBody)));
}
private WebClient getSslIgnoringWebClient() {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(HttpClient
.create()
.secure(t -> {
try {
t.sslContext(SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build());
}
catch (SSLException e) {
e.printStackTrace();
}
})))
.build();
}
protected Mono<List<ApplicationDetail>> getApplications(String app1, String app2) {
return Flux.merge(cloudFoundryService.getApplication(app1),
cloudFoundryService.getApplication(app2))
.parallel()
.runOn(Schedulers.parallel())
.sequential()
.collectList();
}
}

View File

@@ -30,6 +30,25 @@ class CreateInstanceAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String APP_CREATE_2 = "app-create-2";
private static final String SI_NAME = "si-create";
private static final String SUFFIX = "create-instance";
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@Test
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,
@@ -37,7 +56,7 @@ class CreateInstanceAcceptanceTest extends CloudFoundryAcceptanceTest {
"spring.cloud.appbroker.services[0].apps[0].name=" + APP_CREATE_1,
"spring.cloud.appbroker.services[0].apps[0].path=" + BACKING_APP_PATH,
"spring.cloud.appbroker.services[0].apps[0].environment.ENV_VAR_1=value1",
"spring.cloud.appbroker.services[0].apps[0].environment.ENV_VAR_2=value2",
"spring.cloud.appbroker.services[0].apps[0].properties.memory=2G",

View File

@@ -34,6 +34,25 @@ class CreateInstanceWithOAuth2CredentialsAcceptanceTest extends CloudFoundryAcce
private static final String APP_NAME = "app-create-oauth2";
private static final String SI_NAME = "si-create-oauth2";
private static final String SUFFIX = "create-instance-oauth2";
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@Test
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -31,6 +31,25 @@ class CreateInstanceWithParametersAcceptanceTest extends CloudFoundryAcceptanceT
private static final String APP_NAME = "app-create-params";
private static final String SI_NAME = "si-create-params";
private static final String SUFFIX = "create-instance-with-params";
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@Test
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -26,11 +26,30 @@ import static org.assertj.core.api.Assertions.assertThat;
class CreateInstanceWithServiceInstanceGuidSuffixTargetAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String APP_NAME_1 = "app-create-suffix";
private static final String SI_NAME = "si-create-suffix";
private static final String SUFFIX = "create-si-guid";
private static final String APP_NAME_1 = "app-create-" + SUFFIX;
private static final String SI_NAME = "si-create-" + SUFFIX;
private static final String BACKING_SI_NAME = "backing-si";
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@Test
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -33,6 +33,25 @@ class CreateInstanceWithServicesAcceptanceTest extends CloudFoundryAcceptanceTes
private static final String BACKING_SI_1_NAME = "backing-service-instance-created";
private static final String BACKING_SI_2_NAME = "backing-service-instance-existing";
private static final String SUFFIX = "create-instance-with-services";
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@Test
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -33,6 +33,25 @@ class CreateInstanceWithSpacePerServiceInstanceTargetAcceptanceTest extends Clou
private static final String BACKING_SI_NAME = "backing-service-space-per-target";
private static final String SUFFIX = "create-instance-space-per-si";
private static final String APP_SERVICE_NAME = "app-service-"+ SUFFIX;
private static final String BACKING_SERVICE_NAME = "backing-service-"+ SUFFIX;
@Override
protected String testSuffix() {
return SUFFIX;
}
@Override
protected String appServiceName() {
return APP_SERVICE_NAME;
}
@Override
protected String backingServiceName() {
return BACKING_SERVICE_NAME;
}
@Test
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -33,9 +33,28 @@ class UpdateInstanceAcceptanceTest extends CloudFoundryAcceptanceTest {
private static final String APP_NAME = "app-update";
private static final String SI_NAME = "si-update";
private static final String SUFFIX = "update-instance";
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
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -35,9 +35,28 @@ class UpdateInstanceWithServicesAcceptanceTest extends CloudFoundryAcceptanceTes
private static final String BACKING_SI_NAME = "backing-service-instance-update";
private static final String SUFFIX = "update-instance-with-services";
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
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -33,9 +33,28 @@ class UpdateInstanceWithTargetAcceptanceTest extends CloudFoundryAcceptanceTest
private static final String APP_NAME = "app-update-target";
private static final String SI_NAME = "si-update-target";
private static final String SUFFIX = "update-instance-with-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
@AppBrokerTestProperties({
"spring.cloud.appbroker.services[0].service-name=" + APP_SERVICE_NAME,

View File

@@ -53,7 +53,6 @@ public class CloudFoundryClientConfiguration {
"clients.write"
};
public static final String APP_BROKER_CLIENT_ID = "app-broker-client";
public static final String APP_BROKER_CLIENT_SECRET = "app-broker-client-secret";
public static final String[] APP_BROKER_CLIENT_AUTHORITIES = {
"cloud_controller.read", "cloud_controller.write"

View File

@@ -122,11 +122,11 @@ public class CloudFoundryService {
.map(url -> "https://" + url);
}
public Mono<Void> pushBrokerApp(String appName, Path appPath, String... appBrokerProperties) {
public Mono<Void> pushBrokerApp(String appName, Path appPath, String brokerClientId, String... appBrokerProperties) {
return cloudFoundryOperations.applications()
.pushManifest(PushApplicationManifestRequest.builder()
.manifest(ApplicationManifest.builder()
.putAllEnvironmentVariables(appBrokerDeployerEnvironmentVariables())
.putAllEnvironmentVariables(appBrokerDeployerEnvironmentVariables(brokerClientId))
.putAllEnvironmentVariables(propertiesToEnvironment(appBrokerProperties))
.name(appName)
.path(appPath)
@@ -318,16 +318,16 @@ public class CloudFoundryService {
.next();
}
public Mono<Void> associateAppBrokerClientWithOrgAndSpace(String orgId, String spaceId) {
return Mono.justOrEmpty(CloudFoundryClientConfiguration.APP_BROKER_CLIENT_ID)
public Mono<Void> associateAppBrokerClientWithOrgAndSpace(String brokerClientId, String orgId, String spaceId) {
return Mono.justOrEmpty(brokerClientId)
.flatMap(userId -> associateOrgUser(orgId, userId)
.then(associateOrgManager(orgId, userId))
.then(associateSpaceDeveloper(spaceId, userId)))
.then();
}
public Mono<Void> removeAppBrokerClientFromOrgAndSpace(String orgId, String spaceId) {
return Mono.justOrEmpty(CloudFoundryClientConfiguration.APP_BROKER_CLIENT_ID)
public Mono<Void> removeAppBrokerClientFromOrgAndSpace(String brokerClientId, String orgId, String spaceId) {
return Mono.justOrEmpty(brokerClientId)
.flatMap(userId -> removeSpaceDeveloper(spaceId, userId)
.then(removeOrgManager(orgId, userId))
.then(removeOrgUser(orgId, userId)));
@@ -384,7 +384,7 @@ public class CloudFoundryService {
.build();
}
private Map<String, String> appBrokerDeployerEnvironmentVariables() {
private Map<String, String> appBrokerDeployerEnvironmentVariables(String brokerClientId) {
Map<String, String> deployerVariables = new HashMap<>();
deployerVariables.put(DEPLOYER_PROPERTY_PREFIX + "api-host",
cloudFoundryProperties.getApiHost());
@@ -397,8 +397,7 @@ public class CloudFoundryService {
deployerVariables.put(DEPLOYER_PROPERTY_PREFIX + "skip-ssl-validation",
String.valueOf(cloudFoundryProperties.isSkipSslValidation()));
deployerVariables.put(DEPLOYER_PROPERTY_PREFIX + "properties.memory", "1024M");
deployerVariables.put(DEPLOYER_PROPERTY_PREFIX + "client-id",
CloudFoundryClientConfiguration.APP_BROKER_CLIENT_ID);
deployerVariables.put(DEPLOYER_PROPERTY_PREFIX + "client-id", brokerClientId);
deployerVariables.put(DEPLOYER_PROPERTY_PREFIX + "client-secret",
CloudFoundryClientConfiguration.APP_BROKER_CLIENT_SECRET);
return deployerVariables;