Merge branch '2.2.x'

Closes gh-19517
This commit is contained in:
Brian Clozel 2020-01-03 09:46:43 +01:00
commit c2f8741e2e
5 changed files with 104 additions and 92 deletions

View File

@ -957,6 +957,11 @@
<artifactId>cassandra</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>couchbase</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>elasticsearch</artifactId>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -37,6 +37,7 @@ import org.springframework.context.annotation.Primary;
* Support class to configure Couchbase based on {@link CouchbaseProperties}.
*
* @author Stephane Nicoll
* @author Brian Clozel
* @since 2.1.0
*/
@Configuration
@ -76,6 +77,9 @@ public class CouchbaseConfiguration {
@Primary
@DependsOn("couchbaseClient")
public ClusterInfo couchbaseClusterInfo() {
if (isRoleBasedAccessControlEnabled()) {
return couchbaseCluster().clusterManager().info();
}
return couchbaseCluster()
.clusterManager(this.properties.getBucket().getName(), this.properties.getBucket().getPassword())
.info();
@ -103,7 +107,14 @@ public class CouchbaseConfiguration {
protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) {
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
CouchbaseProperties.Bootstrap bootstrap = properties.getEnv().getBootstrap();
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder();
if (bootstrap.getHttpDirectPort() != null) {
builder.bootstrapHttpDirectPort(bootstrap.getHttpDirectPort());
}
if (bootstrap.getHttpSslPort() != null) {
builder.bootstrapHttpSslPort(bootstrap.getHttpSslPort());
}
if (timeouts.getConnect() != null) {
builder = builder.connectTimeout(timeouts.getConnect().toMillis());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Yulin Qin
* @author Brian Clozel
* @since 1.4.0
*/
@ConfigurationProperties(prefix = "spring.couchbase")
@ -116,12 +117,18 @@ public class CouchbaseProperties {
public static class Env {
private final Bootstrap bootstrap = new Bootstrap();
private final Endpoints endpoints = new Endpoints();
private final Ssl ssl = new Ssl();
private final Timeouts timeouts = new Timeouts();
public Bootstrap getBootstrap() {
return this.bootstrap;
}
public Endpoints getEndpoints() {
return this.endpoints;
}
@ -314,4 +321,34 @@ public class CouchbaseProperties {
}
public static class Bootstrap {
/**
* Port for the HTTP bootstrap.
*/
private Integer httpDirectPort;
/**
* Port for the HTTPS bootstrap.
*/
private Integer httpSslPort;
public Integer getHttpDirectPort() {
return this.httpDirectPort;
}
public void setHttpDirectPort(Integer httpDirectPort) {
this.httpDirectPort = httpDirectPort;
}
public Integer getHttpSslPort() {
return this.httpSslPort;
}
public void setHttpSslPort(Integer httpSslPort) {
this.httpSslPort = httpSslPort;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,17 +16,24 @@
package org.springframework.boot.autoconfigure.couchbase;
import java.time.Duration;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseBucket;
import com.couchbase.client.java.bucket.BucketType;
import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.cluster.DefaultBucketSettings;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -37,29 +44,53 @@ import static org.mockito.Mockito.mock;
* Integration tests for {@link CouchbaseAutoConfiguration}.
*
* @author Stephane Nicoll
* @author Brian Clozel
*/
@ExtendWith(LocalCouchbaseServer.class)
@Testcontainers(disabledWithoutDocker = true)
class CouchbaseAutoConfigurationIntegrationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class, CouchbaseAutoConfiguration.class));
@Container
static final CouchbaseContainer couchbase = new CouchbaseContainer().withClusterAdmin("spring", "password")
.withNewBucket(DefaultBucketSettings.builder().enableFlush(true).name("default").password("secret")
.quota(100).replicas(0).type(BucketType.COUCHBASE).build())
.withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(2));
private AnnotationConfigApplicationContext context;
@BeforeEach
void setUp() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(CouchbaseAutoConfiguration.class);
TestPropertyValues.of("spring.couchbase.bootstrap-hosts=localhost",
"spring.couchbase.env.bootstrap.http-direct-port:" + couchbase.getMappedPort(8091),
"spring.couchbase.username:spring", "spring.couchbase.password:password",
"spring.couchbase.bucket.name:default").applyTo(this.context.getEnvironment());
}
@AfterEach
void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
void defaultConfiguration() {
this.contextRunner.withPropertyValues("spring.couchbase.bootstrapHosts=localhost")
.run((context) -> assertThat(context).hasSingleBean(Cluster.class).hasSingleBean(ClusterInfo.class)
.hasSingleBean(CouchbaseEnvironment.class).hasSingleBean(Bucket.class));
this.context.refresh();
assertThat(this.context.getBeansOfType(Cluster.class)).hasSize(1);
assertThat(this.context.getBeansOfType(ClusterInfo.class)).hasSize(1);
assertThat(this.context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(1);
}
@Test
void customConfiguration() {
this.contextRunner.withUserConfiguration(CustomConfiguration.class)
.withPropertyValues("spring.couchbase.bootstrapHosts=localhost").run((context) -> {
assertThat(context.getBeansOfType(Cluster.class)).hasSize(2);
assertThat(context.getBeansOfType(ClusterInfo.class)).hasSize(1);
assertThat(context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
assertThat(context.getBeansOfType(Bucket.class)).hasSize(2);
});
this.context.register(CustomConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeansOfType(Cluster.class)).hasSize(2);
assertThat(this.context.getBeansOfType(ClusterInfo.class)).hasSize(1);
assertThat(this.context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(2);
}
@Configuration(proxyBeanMethods = false)

View File

@ -1,72 +0,0 @@
/*
* Copyright 2012-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.boot.autoconfigure.couchbase;
import java.util.concurrent.TimeUnit;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseCluster;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
import org.springframework.beans.factory.BeanCreationException;
/**
* {@link Extension} for working with an optional Couchbase server. Expects a default
* {@link Bucket} with no password to be available on localhost.
*
* @author Stephane Nicoll
* @author Andy Wilkinson
*/
class LocalCouchbaseServer implements ExecutionCondition, TestExecutionExceptionHandler {
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
try {
CouchbaseEnvironment environment = DefaultCouchbaseEnvironment.create();
Cluster cluster = CouchbaseCluster.create(environment, "localhost");
testConnection(cluster);
cluster.disconnect();
environment.shutdownAsync();
return ConditionEvaluationResult.enabled("Local Couchbase server available");
}
catch (Exception ex) {
return ConditionEvaluationResult.disabled("Local Couchbase server not available");
}
}
private static void testConnection(Cluster cluster) {
Bucket bucket = cluster.openBucket(2, TimeUnit.SECONDS);
bucket.close();
}
@Override
public void handleTestExecutionException(ExtensionContext context, Throwable ex) throws Throwable {
if ((ex instanceof BeanCreationException)
&& "couchbaseClient".equals(((BeanCreationException) ex).getBeanName())) {
return;
}
throw ex;
}
}