commit
c2f8741e2e
|
|
@ -957,6 +957,11 @@
|
||||||
<artifactId>cassandra</artifactId>
|
<artifactId>cassandra</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testcontainers</groupId>
|
||||||
|
<artifactId>couchbase</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.testcontainers</groupId>
|
<groupId>org.testcontainers</groupId>
|
||||||
<artifactId>elasticsearch</artifactId>
|
<artifactId>elasticsearch</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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}.
|
* Support class to configure Couchbase based on {@link CouchbaseProperties}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 2.1.0
|
* @since 2.1.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
@ -76,6 +77,9 @@ public class CouchbaseConfiguration {
|
||||||
@Primary
|
@Primary
|
||||||
@DependsOn("couchbaseClient")
|
@DependsOn("couchbaseClient")
|
||||||
public ClusterInfo couchbaseClusterInfo() {
|
public ClusterInfo couchbaseClusterInfo() {
|
||||||
|
if (isRoleBasedAccessControlEnabled()) {
|
||||||
|
return couchbaseCluster().clusterManager().info();
|
||||||
|
}
|
||||||
return couchbaseCluster()
|
return couchbaseCluster()
|
||||||
.clusterManager(this.properties.getBucket().getName(), this.properties.getBucket().getPassword())
|
.clusterManager(this.properties.getBucket().getName(), this.properties.getBucket().getPassword())
|
||||||
.info();
|
.info();
|
||||||
|
|
@ -103,7 +107,14 @@ public class CouchbaseConfiguration {
|
||||||
protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) {
|
protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) {
|
||||||
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
|
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
|
||||||
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
|
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
|
||||||
|
CouchbaseProperties.Bootstrap bootstrap = properties.getEnv().getBootstrap();
|
||||||
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder();
|
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) {
|
if (timeouts.getConnect() != null) {
|
||||||
builder = builder.connectTimeout(timeouts.getConnect().toMillis());
|
builder = builder.connectTimeout(timeouts.getConnect().toMillis());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 Eddú Meléndez
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Yulin Qin
|
* @author Yulin Qin
|
||||||
|
* @author Brian Clozel
|
||||||
* @since 1.4.0
|
* @since 1.4.0
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = "spring.couchbase")
|
@ConfigurationProperties(prefix = "spring.couchbase")
|
||||||
|
|
@ -116,12 +117,18 @@ public class CouchbaseProperties {
|
||||||
|
|
||||||
public static class Env {
|
public static class Env {
|
||||||
|
|
||||||
|
private final Bootstrap bootstrap = new Bootstrap();
|
||||||
|
|
||||||
private final Endpoints endpoints = new Endpoints();
|
private final Endpoints endpoints = new Endpoints();
|
||||||
|
|
||||||
private final Ssl ssl = new Ssl();
|
private final Ssl ssl = new Ssl();
|
||||||
|
|
||||||
private final Timeouts timeouts = new Timeouts();
|
private final Timeouts timeouts = new Timeouts();
|
||||||
|
|
||||||
|
public Bootstrap getBootstrap() {
|
||||||
|
return this.bootstrap;
|
||||||
|
}
|
||||||
|
|
||||||
public Endpoints getEndpoints() {
|
public Endpoints getEndpoints() {
|
||||||
return this.endpoints;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,17 +16,24 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.couchbase;
|
package org.springframework.boot.autoconfigure.couchbase;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
import com.couchbase.client.java.Bucket;
|
import com.couchbase.client.java.Bucket;
|
||||||
import com.couchbase.client.java.Cluster;
|
import com.couchbase.client.java.Cluster;
|
||||||
import com.couchbase.client.java.CouchbaseBucket;
|
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.ClusterInfo;
|
||||||
|
import com.couchbase.client.java.cluster.DefaultBucketSettings;
|
||||||
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
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.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.test.util.TestPropertyValues;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
|
@ -37,29 +44,53 @@ import static org.mockito.Mockito.mock;
|
||||||
* Integration tests for {@link CouchbaseAutoConfiguration}.
|
* Integration tests for {@link CouchbaseAutoConfiguration}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Brian Clozel
|
||||||
*/
|
*/
|
||||||
@ExtendWith(LocalCouchbaseServer.class)
|
@Testcontainers(disabledWithoutDocker = true)
|
||||||
class CouchbaseAutoConfigurationIntegrationTests {
|
class CouchbaseAutoConfigurationIntegrationTests {
|
||||||
|
|
||||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
@Container
|
||||||
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class, CouchbaseAutoConfiguration.class));
|
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
|
@Test
|
||||||
void defaultConfiguration() {
|
void defaultConfiguration() {
|
||||||
this.contextRunner.withPropertyValues("spring.couchbase.bootstrapHosts=localhost")
|
this.context.refresh();
|
||||||
.run((context) -> assertThat(context).hasSingleBean(Cluster.class).hasSingleBean(ClusterInfo.class)
|
assertThat(this.context.getBeansOfType(Cluster.class)).hasSize(1);
|
||||||
.hasSingleBean(CouchbaseEnvironment.class).hasSingleBean(Bucket.class));
|
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
|
@Test
|
||||||
void customConfiguration() {
|
void customConfiguration() {
|
||||||
this.contextRunner.withUserConfiguration(CustomConfiguration.class)
|
this.context.register(CustomConfiguration.class);
|
||||||
.withPropertyValues("spring.couchbase.bootstrapHosts=localhost").run((context) -> {
|
this.context.refresh();
|
||||||
assertThat(context.getBeansOfType(Cluster.class)).hasSize(2);
|
assertThat(this.context.getBeansOfType(Cluster.class)).hasSize(2);
|
||||||
assertThat(context.getBeansOfType(ClusterInfo.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(ClusterInfo.class)).hasSize(1);
|
||||||
assertThat(context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
|
||||||
assertThat(context.getBeansOfType(Bucket.class)).hasSize(2);
|
assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(2);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue