diff --git a/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/cassandra/DeprecatedCassandraContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/cassandra/DeprecatedCassandraContainerConnectionDetailsFactoryTests.java new file mode 100644 index 0000000000..6d13f8eddd --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/cassandra/DeprecatedCassandraContainerConnectionDetailsFactoryTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2024 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.testcontainers.service.connection.cassandra; + +import com.datastax.oss.driver.api.core.CqlSession; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.CassandraContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DeprecatedCassandraContainerConnectionDetailsFactory}. + * + * @author Andy Wilkinson + * @deprecated since 3.4.0 for removal in 3.6.0 + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@Deprecated(since = "3.4.0", forRemoval = true) +class DeprecatedCassandraContainerConnectionDetailsFactoryTests { + + @Container + @ServiceConnection + static final CassandraContainer cassandra = TestImage.container(CassandraContainer.class); + + @Autowired(required = false) + private CassandraConnectionDetails connectionDetails; + + @Autowired + private CqlSession cqlSession; + + @Test + void connectionCanBeMadeToCassandraContainer() { + assertThat(this.connectionDetails).isNotNull(); + assertThat(this.cqlSession.getMetadata().getNodes()).hasSize(1); + } + + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration(CassandraAutoConfiguration.class) + static class TestConfiguration { + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/kafka/DeprecatedConfluentKafkaContainerConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/kafka/DeprecatedConfluentKafkaContainerConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 0000000000..3d9b0aedfe --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/kafka/DeprecatedConfluentKafkaContainerConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2012-2024 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.testcontainers.service.connection.kafka; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DeprecatedConfluentKafkaContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 3.4.0 for removal in 3.6.0 + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@TestPropertySource(properties = { "spring.kafka.consumer.group-id=test-group", + "spring.kafka.consumer.auto-offset-reset=earliest" }) +@Deprecated(since = "3.4.0", forRemoval = true) +class DeprecatedConfluentKafkaContainerConnectionDetailsFactoryIntegrationTests { + + @Container + @ServiceConnection + static final KafkaContainer kafka = TestImage.container(KafkaContainer.class); + + @Autowired + private KafkaTemplate kafkaTemplate; + + @Autowired + private TestListener listener; + + @Test + void connectionCanBeMadeToKafkaContainer() { + this.kafkaTemplate.send("test-topic", "test-data"); + Awaitility.waitAtMost(Duration.ofMinutes(4)) + .untilAsserted(() -> assertThat(this.listener.messages).containsExactly("test-data")); + } + + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration(KafkaAutoConfiguration.class) + static class TestConfiguration { + + @Bean + TestListener testListener() { + return new TestListener(); + } + + } + + static class TestListener { + + private final List messages = new ArrayList<>(); + + @KafkaListener(topics = "test-topic") + void processMessage(String message) { + this.messages.add(message); + } + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/cassandra/DeprecatedCassandraContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/cassandra/DeprecatedCassandraContainerConnectionDetailsFactory.java new file mode 100644 index 0000000000..6e43244ce1 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/cassandra/DeprecatedCassandraContainerConnectionDetailsFactory.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012-2023 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.testcontainers.service.connection.cassandra; + +import java.net.InetSocketAddress; +import java.util.List; + +import org.testcontainers.containers.CassandraContainer; + +import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link CassandraConnectionDetails} + * from a {@link ServiceConnection @ServiceConnection}-annotated + * {@link CassandraContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 3.4.0 for removal in 3.6.0 in favor of + * {@link CassandraContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "3.4.0", forRemoval = true) +class DeprecatedCassandraContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory, CassandraConnectionDetails> { + + @Override + protected CassandraConnectionDetails getContainerConnectionDetails( + ContainerConnectionSource> source) { + return new CassandraContainerConnectionDetails(source); + } + + /** + * {@link CassandraConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class CassandraContainerConnectionDetails + extends ContainerConnectionDetails> implements CassandraConnectionDetails { + + private CassandraContainerConnectionDetails(ContainerConnectionSource> source) { + super(source); + } + + @Override + public List getContactPoints() { + InetSocketAddress contactPoint = getContainer().getContactPoint(); + return List.of(new Node(contactPoint.getHostString(), contactPoint.getPort())); + } + + @Override + public String getUsername() { + return getContainer().getUsername(); + } + + @Override + public String getPassword() { + return getContainer().getPassword(); + } + + @Override + public String getLocalDatacenter() { + return getContainer().getLocalDatacenter(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/kafka/DeprecatedConfluentKafkaContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/kafka/DeprecatedConfluentKafkaContainerConnectionDetailsFactory.java new file mode 100644 index 0000000000..eafd40c87e --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/kafka/DeprecatedConfluentKafkaContainerConnectionDetailsFactory.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2024 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.testcontainers.service.connection.kafka; + +import java.util.List; + +import org.testcontainers.containers.KafkaContainer; + +import org.springframework.boot.autoconfigure.kafka.KafkaConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link KafkaConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link KafkaContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 3.4.0 for removal in 3.6.0 in favor of + * {@link ConfluentKafkaContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "3.4.0", forRemoval = true) +class DeprecatedConfluentKafkaContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory { + + @Override + protected KafkaConnectionDetails getContainerConnectionDetails(ContainerConnectionSource source) { + return new ConfluentKafkaContainerConnectionDetails(source); + } + + /** + * {@link KafkaConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class ConfluentKafkaContainerConnectionDetails + extends ContainerConnectionDetails implements KafkaConnectionDetails { + + private ConfluentKafkaContainerConnectionDetails(ContainerConnectionSource source) { + super(source); + } + + @Override + public List getBootstrapServers() { + return List.of(getContainer().getBootstrapServers()); + } + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories index c556ff49eb..14de79b9ea 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories @@ -13,6 +13,7 @@ org.springframework.boot.testcontainers.service.connection.activemq.ActiveMQCont org.springframework.boot.testcontainers.service.connection.activemq.ArtemisContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.amqp.RabbitContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.cassandra.CassandraContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.cassandra.DeprecatedCassandraContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.couchbase.CouchbaseContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.elasticsearch.ElasticsearchContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.flyway.FlywayContainerConnectionDetailsFactory,\ @@ -20,6 +21,7 @@ org.springframework.boot.testcontainers.service.connection.hazelcast.HazelcastCo org.springframework.boot.testcontainers.service.connection.jdbc.JdbcContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.kafka.ApacheKafkaContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.kafka.ConfluentKafkaContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.kafka.DeprecatedConfluentKafkaContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.ldap.OpenLdapContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.liquibase.LiquibaseContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.mongo.MongoContainerConnectionDetailsFactory,\ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java index b4011ffba4..9c5922723b 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java @@ -83,6 +83,16 @@ public enum TestImage { CASSANDRA("cassandra", "3.11.10", () -> CassandraContainer.class, (container) -> ((CassandraContainer) container).withStartupTimeout(Duration.ofMinutes(10))), + /** + * A container image suitable for testing Cassandra using the deprecated + * {@link org.testcontainers.containers.CassandraContainer}. + * @deprecated since 3.4.0 for removal in 3.6.0 in favor of {@link #CASSANDRA} + */ + @Deprecated(since = "3.4.0", forRemoval = true) + CASSANDRA_DEPRECATED("cassandra", "3.11.10", () -> org.testcontainers.containers.CassandraContainer.class, + (container) -> ((org.testcontainers.containers.CassandraContainer) container) + .withStartupTimeout(Duration.ofMinutes(10))), + /** * A container image suitable for testing Couchbase. */ @@ -119,6 +129,15 @@ public enum TestImage { */ CONFLUENT_KAFKA("confluentinc/cp-kafka", "7.4.0", () -> ConfluentKafkaContainer.class), + /** + * A container image suitable for testing Confluent's distribution of Kafka using the + * deprecated {@link org.testcontainers.containers.KafkaContainer}. + * @deprecated since 3.4.0 for removal in 3.6.0 in favor of {@link #CONFLUENT_KAFKA} + */ + @Deprecated(since = "3.4.0", forRemoval = true) + CONFLUENT_KAFKA_DEPRECATED("confluentinc/cp-kafka", "7.4.0", + () -> org.testcontainers.containers.KafkaContainer.class), + /** * A container image suitable for testing OpenLDAP. */ diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-cassandra/src/dockerTest/java/smoketest/data/cassandra/SecureCassandraContainer.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-cassandra/src/dockerTest/java/smoketest/data/cassandra/SecureCassandraContainer.java index 91ca358d6d..7a5ba7a989 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-cassandra/src/dockerTest/java/smoketest/data/cassandra/SecureCassandraContainer.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-data-cassandra/src/dockerTest/java/smoketest/data/cassandra/SecureCassandraContainer.java @@ -17,6 +17,7 @@ package smoketest.data.cassandra; import org.testcontainers.cassandra.CassandraContainer; +import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; @@ -29,6 +30,7 @@ class SecureCassandraContainer extends CassandraContainer { SecureCassandraContainer(DockerImageName dockerImageName) { super(dockerImageName); + setWaitStrategy(Wait.defaultWaitStrategy()); // default strategy uses plain text withCopyFileToContainer(MountableFile.forClasspathResource("/ssl/cassandra.yaml"), "/etc/cassandra/cassandra.yaml"); withCopyFileToContainer(MountableFile.forClasspathResource("/ssl/test-server.p12"),