Migrate Spring RabbitMQ support to spring-boot-rabbitmq

See gh-49620

Co-authored-by: Eddú Meléndez <eddu.melendez@gmail.com>
This commit is contained in:
Stéphane Nicoll
2026-03-19 08:04:14 +01:00
co-authored by Eddú Meléndez
parent fda2599bc2
commit 72b8a6ca05
102 changed files with 15 additions and 15 deletions
@@ -0,0 +1,68 @@
/*
* Copyright 2012-present 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.amqp.docker.compose;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RabbitDockerComposeConnectionDetailsFactory} and
* {@link RabbitStreamDockerComposeConnectionDetailsFactory} when used in combination.
*
* @author Andy Wilkinson
*/
class RabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbit-and-rabbit-stream-separate-services-compose.yaml",
image = TestImage.RABBITMQ)
void runCreatesConnectionDetailsFromSeparateServices(RabbitConnectionDetails connectionDetails,
RabbitStreamConnectionDetails streamConnectionDetails) {
assertConnectionDetails(connectionDetails);
assertConnectionDetails(streamConnectionDetails);
}
@DockerComposeTest(composeFile = "rabbit-and-rabbit-stream-single-service-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetailsFromSingleService(RabbitConnectionDetails connectionDetails,
RabbitStreamConnectionDetails streamConnectionDetails) {
assertConnectionDetails(connectionDetails);
assertConnectionDetails(streamConnectionDetails);
}
private void assertConnectionDetails(RabbitConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getAddresses()).hasSize(1);
Address address = connectionDetails.getFirstAddress();
assertThat(address.host()).isNotNull();
assertThat(address.port()).isGreaterThan(0);
}
private void assertConnectionDetails(RabbitStreamConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getHost()).isNotNull();
assertThat(connectionDetails.getPort()).isGreaterThan(0);
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2012-present 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.amqp.docker.compose;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RabbitDockerComposeConnectionDetailsFactory}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
*/
class RabbitDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbit-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetails(RabbitConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails);
assertThat(connectionDetails.getSslBundle()).isNull();
}
@DockerComposeTest(composeFile = "rabbit-ssl-compose.yaml", image = TestImage.RABBITMQ,
additionalResources = { "../../ca.crt", "../../server.crt", "../../server.key", "../../client.crt",
"../../client.key", "rabbitmq-ssl.conf" })
void runWithSslCreatesConnectionDetails(RabbitConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails);
SslBundle sslBundle = connectionDetails.getSslBundle();
assertThat(sslBundle).isNotNull();
}
private void assertConnectionDetails(RabbitConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getAddresses()).hasSize(1);
Address address = connectionDetails.getFirstAddress();
assertThat(address.host()).isNotNull();
assertThat(address.port()).isGreaterThan(0);
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2012-present 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.amqp.docker.compose;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RabbitStreamDockerComposeConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
class RabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbit-stream-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetails(RabbitStreamConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails);
}
@DockerComposeTest(composeFile = "rabbit-stream-ssl-compose.yaml", image = TestImage.RABBITMQ,
additionalResources = { "../../ca.crt", "../../server.crt", "../../server.key", "../../client.crt",
"../../client.key", "rabbitmq-stream-ssl.conf" })
void runWithSslCreatesConnectionDetails(RabbitStreamConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails);
SslBundle sslBundle = connectionDetails.getSslBundle();
assertThat(sslBundle).isNotNull();
}
private void assertConnectionDetails(RabbitStreamConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getHost()).isNotNull();
assertThat(connectionDetails.getPort()).isGreaterThan(0);
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2012-present 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.amqp.docker.compose;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RabbitDockerComposeConnectionDetailsFactory} and
* {@link RabbitStreamDockerComposeConnectionDetailsFactory} when using a single service
* for standard and stream-based messaging.
*
* @author Andy Wilkinson
*/
class SingleServiceRabbitAndRabbitStreamDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbit-and-rabbit-stream-single-service-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetails(RabbitConnectionDetails connectionDetails,
RabbitStreamConnectionDetails streamConnectionDetails) {
assertConnectionDetails(connectionDetails);
assertConnectionDetails(streamConnectionDetails);
}
private void assertConnectionDetails(RabbitConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getAddresses()).hasSize(1);
Address address = connectionDetails.getFirstAddress();
assertThat(address.host()).isNotNull();
assertThat(address.port()).isGreaterThan(0);
}
private void assertConnectionDetails(RabbitStreamConnectionDetails connectionDetails) {
assertThat(connectionDetails.getUsername()).isEqualTo("myuser");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
assertThat(connectionDetails.getVirtualHost()).isEqualTo("/");
assertThat(connectionDetails.getHost()).isNotNull();
assertThat(connectionDetails.getPort()).isGreaterThan(0);
}
}
@@ -0,0 +1,102 @@
/*
* Copyright 2012-present 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.amqp.testcontainers;
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.RabbitMQContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DeprecatedRabbitContainerConnectionDetailsFactory}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @deprecated since 4.0.0 for removal in 4.2.0 in favor of
* {@link RabbitContainerConnectionDetailsFactoryIntegrationTests}.
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
@Deprecated(since = "4.0.0", forRemoval = true)
class DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToRabbitContainer() {
assertThat(this.connectionDetails).isNotNull();
this.rabbitTemplate.convertAndSend("test", "message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queuesToDeclare = @Queue("test"))
void processMessage(String message) {
this.messages.add(message);
}
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2012-present 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.amqp.testcontainers;
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.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.rabbitmq.RabbitMQContainer;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link RabbitContainerConnectionDetailsFactory}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class RabbitContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToRabbitContainer() {
assertThat(this.connectionDetails).isNotNull();
this.rabbitTemplate.convertAndSend("test", "message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queuesToDeclare = @Queue("test"))
void processMessage(String message) {
this.messages.add(message);
}
}
}
@@ -0,0 +1,133 @@
/*
* Copyright 2012-present 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.amqp.testcontainers;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import com.rabbitmq.stream.Address;
import com.rabbitmq.stream.Environment;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.rabbitmq.RabbitMQContainer;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.rabbit.stream.producer.RabbitStreamTemplate;
import org.springframework.rabbit.stream.support.StreamAdmin;
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 RabbitStreamContainerConnectionDetailsFactory} with a single container
* that's only used for streams.
*
* @author Eddú Meléndez
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@TestPropertySource(
properties = { "spring.rabbitmq.stream.name=stream.queue1", "spring.rabbitmq.listener.type=stream" })
@Testcontainers(disabledWithoutDocker = true)
class RabbitStreamContainerConnectionDetailsFactoryIntegrationTests {
private static final int RABBITMQ_STREAMS_PORT = 5552;
@Container
@ServiceConnection(type = RabbitStreamConnectionDetails.class)
static final RabbitMQContainer rabbit = getRabbitMqStreamContainer();
private static RabbitMQContainer getRabbitMqStreamContainer() {
RabbitMQContainer container = TestImage.container(RabbitMQContainer.class);
container.addExposedPorts(RABBITMQ_STREAMS_PORT);
String enabledPlugins = "[rabbitmq_stream,rabbitmq_prometheus].";
container.withCopyToContainer(Transferable.of(enabledPlugins), "/etc/rabbitmq/enabled_plugins");
return container;
}
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired(required = false)
private RabbitStreamConnectionDetails streamConnectionDetails;
@Autowired
private RabbitStreamTemplate rabbitStreamTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToRabbitContainer() {
assertThat(this.connectionDetails).isNotInstanceOf(RabbitMqContainerConnectionDetails.class);
assertThat(this.streamConnectionDetails).isInstanceOf(RabbitMqStreamContainerConnectionDetails.class);
this.rabbitStreamTemplate.convertAndSend("message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
@Bean
StreamAdmin streamAdmin(Environment env) {
return new StreamAdmin(env, (sc) -> sc.stream("stream.queue1").create());
}
@Bean
EnvironmentBuilderCustomizer environmentBuilderCustomizer() {
return (env) -> env.addressResolver(
(address) -> new Address(rabbit.getHost(), rabbit.getMappedPort(RABBITMQ_STREAMS_PORT)));
}
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queues = "stream.queue1")
void processMessage(String message) {
this.messages.add(message);
}
}
}
@@ -0,0 +1,151 @@
/*
* Copyright 2012-present 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.amqp.testcontainers;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import com.rabbitmq.stream.Address;
import com.rabbitmq.stream.Environment;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.rabbitmq.RabbitMQContainer;
import org.testcontainers.utility.MountableFile;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.PemKeyStore;
import org.springframework.boot.testcontainers.service.connection.PemTrustStore;
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.rabbit.stream.producer.RabbitStreamTemplate;
import org.springframework.rabbit.stream.support.StreamAdmin;
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 RabbitStreamContainerConnectionDetailsFactory} with SSL.
*
* @author Eddú Meléndez
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@TestPropertySource(
properties = { "spring.rabbitmq.stream.name=stream.queue1", "spring.rabbitmq.listener.type=stream" })
@Testcontainers(disabledWithoutDocker = true)
class RabbitStreamWithSslContainerConnectionDetailsFactoryIntegrationTests {
private static final int RABBITMQ_STREAMS_TLS_PORT = 5551;
@Container
@ServiceConnection(type = RabbitStreamConnectionDetails.class)
@PemTrustStore(certificate = "classpath:org/springframework/boot/amqp/ca.crt")
@PemKeyStore(certificate = "classpath:org/springframework/boot/amqp/client.crt",
privateKey = "classpath:org/springframework/boot/amqp/client.key")
static final RabbitMQContainer rabbit = getRabbitMqStreamContainer();
private static RabbitMQContainer getRabbitMqStreamContainer() {
RabbitMQContainer container = TestImage.container(RabbitMQContainer.class);
container.addExposedPorts(RABBITMQ_STREAMS_TLS_PORT);
String enabledPlugins = "[rabbitmq_stream,rabbitmq_prometheus].";
container.withCopyToContainer(Transferable.of(enabledPlugins), "/etc/rabbitmq/enabled_plugins");
container.withCopyFileToContainer(
MountableFile
.forClasspathResource("org/springframework/boot/amqp/testcontainers/rabbitmq-stream-ssl.conf"),
"/etc/rabbitmq/rabbitmq.conf");
container.withCopyFileToContainer(MountableFile.forClasspathResource("org/springframework/boot/amqp/ca.crt"),
"/etc/rabbitmq/ca.crt");
container.withCopyFileToContainer(
MountableFile.forClasspathResource("org/springframework/boot/amqp/server.key"),
"/etc/rabbitmq/server.key");
container.withCopyFileToContainer(
MountableFile.forClasspathResource("org/springframework/boot/amqp/server.crt"),
"/etc/rabbitmq/server.crt");
return container;
}
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired(required = false)
private RabbitStreamConnectionDetails streamConnectionDetails;
@Autowired
private RabbitStreamTemplate rabbitStreamTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToRabbitContainer() {
assertThat(this.connectionDetails).isNotInstanceOf(RabbitMqContainerConnectionDetails.class);
assertThat(this.streamConnectionDetails).isInstanceOf(RabbitMqStreamContainerConnectionDetails.class);
assertThat(this.streamConnectionDetails.getSslBundle()).isNotNull();
this.rabbitStreamTemplate.convertAndSend("message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
@Bean
StreamAdmin streamAdmin(Environment env) {
return new StreamAdmin(env, (sc) -> sc.stream("stream.queue1").create());
}
@Bean
EnvironmentBuilderCustomizer environmentBuilderCustomizer() {
return (env) -> env.addressResolver(
(address) -> new Address(rabbit.getHost(), rabbit.getMappedPort(RABBITMQ_STREAMS_TLS_PORT)));
}
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queues = "stream.queue1")
void processMessage(String message) {
this.messages.add(message);
}
}
}
@@ -0,0 +1,167 @@
/*
* Copyright 2012-present 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.amqp.testcontainers;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import com.rabbitmq.stream.Address;
import com.rabbitmq.stream.Environment;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.rabbitmq.RabbitMQContainer;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.rabbit.stream.producer.RabbitStreamTemplate;
import org.springframework.rabbit.stream.support.StreamAdmin;
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 RabbitStreamContainerConnectionDetailsFactory} with two containers,
* one for streams and one for standard messaging.
*
* @author Eddú Meléndez
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@TestPropertySource(
properties = { "spring.rabbitmq.stream.name=stream.queue1", "spring.rabbitmq.listener.type=stream" })
@Testcontainers(disabledWithoutDocker = true)
class SeparateContainersRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests {
private static final int RABBITMQ_STREAMS_PORT = 5552;
@Container
@ServiceConnection
static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
@Container
@ServiceConnection(type = RabbitStreamConnectionDetails.class)
static final RabbitMQContainer rabbitStream = getRabbitMqStreamContainer();
private static RabbitMQContainer getRabbitMqStreamContainer() {
RabbitMQContainer container = TestImage.container(RabbitMQContainer.class);
container.addExposedPorts(RABBITMQ_STREAMS_PORT);
String enabledPlugins = "[rabbitmq_stream,rabbitmq_prometheus].";
container.withCopyToContainer(Transferable.of(enabledPlugins), "/etc/rabbitmq/enabled_plugins");
return container;
}
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired(required = false)
private RabbitStreamConnectionDetails streamConnectionDetails;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RabbitStreamTemplate rabbitStreamTemplate;
@Autowired
private StreamTestListener streamListener;
@Test
void rabbitConnectionDetailsAreSourcedFromContainer() {
assertThat(this.connectionDetails).isInstanceOf(RabbitMqContainerConnectionDetails.class);
assertThat(this.connectionDetails.getFirstAddress().port()).isEqualTo(rabbit.getAmqpPort());
}
@Test
void rabbitStreamConnectionDetailsAreSourcedFromContainer() {
assertThat(this.streamConnectionDetails).isInstanceOf(RabbitMqStreamContainerConnectionDetails.class);
assertThat(this.streamConnectionDetails.getPort()).isEqualTo(rabbitStream.getMappedPort(RABBITMQ_STREAMS_PORT));
}
@Test
void connectionCanBeMadeToRabbitContainer() {
this.rabbitTemplate.convertAndSend("test", "message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.rabbitTemplate.receive("test"))
.extracting((message) -> new String(message.getBody(), StandardCharsets.UTF_8))
.isEqualTo("message"));
}
@Test
void streamConnectionCanBeMadeToRabbitContainer() {
this.rabbitStreamTemplate.convertAndSend("message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.streamListener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
TestConfiguration(AmqpAdmin amqpAdmin) {
amqpAdmin.declareQueue(new Queue("test"));
}
@Bean
StreamAdmin streamAdmin(Environment env) {
return new StreamAdmin(env, (sc) -> sc.stream("stream.queue1").create());
}
@Bean
EnvironmentBuilderCustomizer environmentBuilderCustomizer() {
return (env) -> env.addressResolver((address) -> new Address(rabbitStream.getHost(),
rabbitStream.getMappedPort(RABBITMQ_STREAMS_PORT)));
}
@Bean
StreamTestListener streamTestListener() {
return new StreamTestListener();
}
}
static class StreamTestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queues = "stream.queue1")
void processMessage(String message) {
this.messages.add(message);
}
}
}
@@ -0,0 +1,161 @@
/*
* Copyright 2012-present 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.amqp.testcontainers;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import com.rabbitmq.stream.Address;
import com.rabbitmq.stream.Environment;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.rabbitmq.RabbitMQContainer;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.amqp.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.amqp.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.amqp.testcontainers.RabbitStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
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.rabbit.stream.producer.RabbitStreamTemplate;
import org.springframework.rabbit.stream.support.StreamAdmin;
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 RabbitStreamContainerConnectionDetailsFactory} with a single container
* used for both streams and standard messaging.
*
* @author Eddú Meléndez
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@TestPropertySource(
properties = { "spring.rabbitmq.stream.name=stream.queue1", "spring.rabbitmq.listener.type=stream" })
@Testcontainers(disabledWithoutDocker = true)
class SingleContainerRabbitAndRabbitStreamContainerConnectionDetailsFactoryIntegrationTests {
private static final int RABBITMQ_STREAMS_PORT = 5552;
@Container
@ServiceConnection(type = { RabbitConnectionDetails.class, RabbitStreamConnectionDetails.class })
static final RabbitMQContainer rabbit = getRabbitMqStreamContainer();
private static RabbitMQContainer getRabbitMqStreamContainer() {
RabbitMQContainer container = TestImage.container(RabbitMQContainer.class);
container.addExposedPorts(RABBITMQ_STREAMS_PORT);
String enabledPlugins = "[rabbitmq_stream,rabbitmq_prometheus].";
container.withCopyToContainer(Transferable.of(enabledPlugins), "/etc/rabbitmq/enabled_plugins");
return container;
}
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired(required = false)
private RabbitStreamConnectionDetails streamConnectionDetails;
@Autowired
private RabbitStreamTemplate rabbitStreamTemplate;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private StreamTestListener streamListener;
@Test
void rabbitConnectionDetailsAreSourcedFromContainer() {
assertThat(this.connectionDetails).isInstanceOf(RabbitMqContainerConnectionDetails.class);
}
@Test
void rabbitStreamConnectionDetailsAreSourcedFromContainer() {
assertThat(this.streamConnectionDetails).isInstanceOf(RabbitMqStreamContainerConnectionDetails.class);
}
@Test
void connectionCanBeMadeToRabbitContainer() {
this.rabbitTemplate.convertAndSend("test", "message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.rabbitTemplate.receive("test"))
.extracting((message) -> new String(message.getBody(), StandardCharsets.UTF_8))
.isEqualTo("message"));
}
@Test
void streamConnectionCanBeMadeToRabbitContainer() {
this.rabbitStreamTemplate.convertAndSend("message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.streamListener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
TestConfiguration(AmqpAdmin amqpAdmin) {
amqpAdmin.declareQueue(new Queue("test"));
}
@Bean
StreamAdmin streamAdmin(Environment env) {
return new StreamAdmin(env, (sc) -> sc.stream("stream.queue1").create());
}
@Bean
EnvironmentBuilderCustomizer environmentBuilderCustomizer() {
return (env) -> env.addressResolver(
(address) -> new Address(rabbit.getHost(), rabbit.getMappedPort(RABBITMQ_STREAMS_PORT)));
}
@Bean
StreamTestListener streamTestListener() {
return new StreamTestListener();
}
}
static class StreamTestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queues = "stream.queue1")
void processMessage(String message) {
this.messages.add(message);
}
}
}
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
</configuration>
@@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFhjCCA26gAwIBAgIUfIkk29IT9OpbgfjL8oRIPSLjUcAwDQYJKoZIhvcNAQEL
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
OzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlmaWNh
dGUgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAusN2
KzQQUUxZSiI3ZZuZohFwq2KXSUNPdJ6rgD3/YKNTDSZXKZPO53kYPP0DXf0sm3CH
cyWSWVabyimZYuPWena1MElSL4ZpJ9WwkZoOQ3bPFK1utz6kMOwrgAUcky8H/rIK
j2JEBhkSHUIGr57NjUEwG1ygaSerM8RzWw1PtMq+C8LOu3v94qzE3NDg1QRpyvV9
OmsLsjISd0ZmAJNi9vmiEH923KnPyiqnQmWKpYicdgQmX1GXylS22jZqAwaOkYGj
X8UdeyvrohkZkM0hn9uaSufQGEW4yKACn3PkjJtzi8drBIyjIi9YcAzBxZB9oVKq
XZMlltgO2fDMmIJi0Ngt0Ci7fCoEMqSocKyDKML6YLr9UWtx4bfsrk+rVO9Q/D/v
8RKgstv7dCf2KWRX3ZJEC0IBHS5gLNq0qqqVcGx3LcSyhdiKJOtSwAnNkHMh+jSQ
xLSlBjcSqTPiGTRK/Rddl+xnU/mBgk7ZBGNrUFaD5McMFjddS7Ih82aHnpQ1gekW
nUGv+Tm/G68h2BvZ5U2q+RfeOCgRW9i/AYW2jgT7IFnfjyUXgBQveauMAchomqFE
VLe95ZgViF6vmH34EKo3w9L5TQiwk/r53YlM7TSOTyDqx66t4zGYDsVMicpKmzi4
2Rp8EpErARRyREUIKSvWs9O9+uT3+7arNLgHe5ECAwEAAaOBgTB/MB0GA1UdDgQW
BBRVMLDVqPECWaH6GruL9E52VcTrPjAfBgNVHSMEGDAWgBRVMLDVqPECWaH6GruL
9E52VcTrPjAPBgNVHRMBAf8EBTADAQH/MCwGA1UdEQQlMCOCC2V4YW1wbGUuY29t
gglsb2NhbGhvc3SCCTEyNy4wLjAuMTANBgkqhkiG9w0BAQsFAAOCAgEAeSpjCL3j
2GIFBNKr/5amLOYa0kZ6r1dJs+K6xvMsUvsBJ/QQsV5nYDMIoV/NYUd8SyYV4lEj
7LHX5ZbmJrvPk30LGEBG/5Vy2MIATrQrQ14S4nXtEdSnBvTQwPOOaHc+2dTp3YpM
f4ffELKWyispTifx1eqdiUJhURKeQBh+3W7zpyaiN4vJaqEDKGgFQtHA/OyZL2hZ
BpxHB0zpb2iDHV8MeyfOT7HQWUk6p13vdYm6EnyJT8fzWvE+TqYNbqFmB+CLRSXy
R3p1yaeTd4LnVknJ0UBKqEyul3ziHZDhKhBpwdglYOQz4eWjSFhikX9XZ8NaI38Q
QqLZVn0DsH2ztkjrQrUVgK2xn4aUuqoLDk4Hu6h5baUn+f2GLuzx+EXc/i3ikYvw
Y3JyufOgw6nGGFG+/QXEj85XtLPhN7Wm42z2e/BGzi0MLl65sfpEDXvFTA72Yzws
OYaeg/HxeYwUHQgs2fKl/LgV4chntSCvTqfNl6OnQafD/ISJNpx3xWR3HwF+ypFG
UaLE+e1soqEJbzL31U/6pypHLsj8Y8r9hJbZXo2ibnhjFV6fypUAP0rbIzaoWcrJ
T0Sbliz+KQTMzCcubiAi4bI/kZ5FJ4kkaHqUpIWzlx1h2WVJ65ASFDjBWb8eVmB6
Dyno/RVFR/rUL5091gjGRXhLsi1oUHKdEzU=
-----END CERTIFICATE-----
@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIURBZvq442tp+/K9TZII5Vy/LzVx0wDQYJKoZIhvcNAQEL
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvGb7tu0odSuOjeY1lHlh
sRR4PayAvlryjfrrp49hjoVTiL3d/Jo6Po5HlqwJcYuclm0EWQR5Vur/zYJpfUE7
b8+E9Qwe50+YzfQ2tVFEdq/VfqemrYRGee+pMelOCI90enOKCxfpo6EHbz+WnUP0
mnD8OAF9QpolSdWAMOGJoPdWX65KQvyMXvQbj9VIHmsx7NCaIOYxjHXB/dI2FmXV
+m4VT6mb8he9dXmgK/ozMq6XIPOAXe0n3dlfMTSEddeNeVwnBpr/n5e0cpwGFhdf
NNu5CI4ecipBhXljJi/4/47M/6hd69HwE05C4zyH4ZDZ2JTfaSKOLV+jYdBUqJP5
dwIDAQABo2IwYDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgeAMB0GA1Ud
DgQWBBRWiWOo9cm2IF/ZlhWLVjifLzYa/DAfBgNVHSMEGDAWgBRVMLDVqPECWaH6
GruL9E52VcTrPjANBgkqhkiG9w0BAQsFAAOCAgEAA5Wphtu2nBhY+QNOBOwXq4zF
N5qt2IYTLfR7xqpKhhXx9VkIjdPWpcsGuCuMmfPVNvQWE6iK0/jMMqToTj4H6K7e
MN74j0GwwcknT1P42tUzEpg8LKR8VMdhWhyqdniCDNWWuaz1iVSoF0S2i4jFSzH5
1q3KMKMZ4niK5aJI0fAGa4fCjyuun1Mfg/qGBGwLnqDkIXjeAopZf4Jb64TtzjAs
j9NT6mYbe3E0tw3fHT9ihYdbZDZgSjeCsuq9OiRMVb0DWWmRoLmmOrlN8IJlHV/3
WyI/ta4Cw5EZ0oaOg0lIyOxXyvElth1xIvh+kdqZSBsU0gNBri6ZIzYbbTh2KTTO
BJHQt9L5naWG27pDrIxBicWXS/MIYonktm3YgCLfuW3kWcVk8bIlNhfcoAYBBgfM
IEYSYEq+bH2IQ+YoWQz3AxjJ8gEuuSUP6R6mYY65FfpjkKgcpGBvw4EIAmqKDtPS
hlLY/F0XVj9KZzrMyH4/vonu+DAb/P7Zmt2fyk/dQO6bAc3ltRmJbJm4VJ2v/T8I
LVu2FtcUYgtLNtkWUPfdb3GSUUgkKlUpWSty31TKSUszJjW1oRykQhEko6o5U3S8
ptQzXdApsb1lGOqewkubE25tIu2RLiNkKcjFOjJ/lu0vP9k76wWwRVnFLFvfo4lW
pgywiOifs5JbcCt0ZQ0=
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8Zvu27Sh1K46N
5jWUeWGxFHg9rIC+WvKN+uunj2GOhVOIvd38mjo+jkeWrAlxi5yWbQRZBHlW6v/N
gml9QTtvz4T1DB7nT5jN9Da1UUR2r9V+p6athEZ576kx6U4Ij3R6c4oLF+mjoQdv
P5adQ/SacPw4AX1CmiVJ1YAw4Ymg91ZfrkpC/Ixe9BuP1UgeazHs0Jog5jGMdcH9
0jYWZdX6bhVPqZvyF711eaAr+jMyrpcg84Bd7Sfd2V8xNIR11415XCcGmv+fl7Ry
nAYWF18027kIjh5yKkGFeWMmL/j/jsz/qF3r0fATTkLjPIfhkNnYlN9pIo4tX6Nh
0FSok/l3AgMBAAECggEABXnBe3MwXAMQENzNypOiXK4VE3XMYkePfdsSK163byOD
w3ZeTgQNfU4g8LJK8/homzO0SQIJAdz2+ZFbpsp4A2W2zJ+1jvN5RuX/8/UcVhmk
tb1IL/LWCvx5/aoYBWkgIA70UfQJa2jDbdM0v5j/Gu9yE7GI14jh6DFC3xGMGV3b
fOwManxf7sDibCI1nGjnFYNGxninRr+tpb+a1KNbVzhett68LrgPmtph6B3HCPAJ
zBigk1Phgb8WHozTXxnLyw9/RdKJ0Ro4PFmtQv0EvCSlytptnF+0nXkqr3f851XS
bUWwYFchIFWPMhPfD5B3niNWCV42/sU/bQlk+BMQAQKBgQD6NvMq8EdYy2Y7fXT5
FgB4s+7EkLgI2d5LUaCXCFgc6iZtCTQKUXj1rIWeRfGrFVCCe8qV+XIMKt/G5eEi
tn5ifHhktA2A8GK1scj026qHP3bVn0hMaUnkCF1UpDRKPiEO5G/apPtav8PbCNaX
GAimLGw+WZNZuv7+T33bEBeUdwKBgQDAwiidayLXkRkz2deefdDKcXQsB7RHFGGy
vfZPBCGqizxml+6ojJkkDsVUKL1IXFfyK9KpQAI6tezn4oktgu4jAQqkYY7QZobs
RpQx1dR+KxEm7ISDBTq/B1Q9cFKUKVvQQy8N2pnIbCdzb6MTOKLmJqFGTjr+5T8q
F32B5vkDAQKBgDCKfH42AwFc5EZiPlEcTZcdARMtKCa/bXqbKVZjjgR+AFpi0K+3
womWoI1l8E5KYkYOEe0qaU+m+aaybgy37qjYkNqoe34qJFwvU1b9ToXScBFdRz9b
pbQRU1naSTKl/u/OrUxzeTfPwAU8H7VMOlFSiOVHp2he+J0JetcGtixdAoGBAIJQ
QMj7rxhxHcqyEVUy1b6nKNTDeJs9Kjd+uU/+CQyVCQaK3GvScY2w9rLIv/51f3dX
LRoDDf7HExxJSFgeVgQQJjOvSK+XQMvngzSVzQxm7TeVWpiBJpAS0l6e2xUTSODp
KpyBFsoqZBlkdaj+9xIFN66iILxGG4fHTbBOiDYBAoGBAOZMKjM5N/hGcCmik/6t
p/zBA2pN9O6zwPndITTsdyVWSlVqCZhXlRX47CerAN+/WVCidlh7Vp5Tuy75Wa77
v16IDLO01txgWNobcLaM4VgFsyLi5JuxK73S18Vb1cKWdHFRF0LH3cUIq20fjpv6
Odl4vjNOncXMZCLPHQ+bKWaf
-----END PRIVATE KEY-----
@@ -0,0 +1,21 @@
services:
rabbitmq:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
ports:
- '5672'
rabbitmq_streams:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
configs:
- source: plugins
target: /etc/rabbitmq/enabled_plugins
ports:
- '5552'
configs:
plugins:
content: "[rabbitmq_stream]."
@@ -0,0 +1,15 @@
services:
rabbitmq:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
configs:
- source: plugins
target: /etc/rabbitmq/enabled_plugins
ports:
- '5552'
- '5672'
configs:
plugins:
content: "[rabbitmq_stream]."
@@ -0,0 +1,8 @@
services:
rabbitmq:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
ports:
- '5672'
@@ -0,0 +1,26 @@
services:
rabbitmq:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
ports:
- '5672'
- '5671'
secrets:
- ssl-ca
- ssl-key
- ssl-cert
volumes:
- ./rabbitmq-ssl.conf:/etc/rabbitmq/rabbitmq.conf:ro
labels:
- 'org.springframework.boot.sslbundle.pem.keystore.certificate=client.crt'
- 'org.springframework.boot.sslbundle.pem.keystore.private-key=client.key'
- 'org.springframework.boot.sslbundle.pem.truststore.certificate=ca.crt'
secrets:
ssl-ca:
file: 'ca.crt'
ssl-key:
file: 'server.key'
ssl-cert:
file: 'server.crt'
@@ -0,0 +1,14 @@
services:
rabbitmq:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
configs:
- source: plugins
target: /etc/rabbitmq/enabled_plugins
ports:
- '5552'
configs:
plugins:
content: "[rabbitmq_stream]."
@@ -0,0 +1,32 @@
services:
rabbitmq:
image: '{imageName}'
environment:
- 'RABBITMQ_DEFAULT_USER=myuser'
- 'RABBITMQ_DEFAULT_PASS=secret'
configs:
- source: plugins
target: /etc/rabbitmq/enabled_plugins
ports:
- '5551'
- '5552'
secrets:
- ssl-ca
- ssl-key
- ssl-cert
volumes:
- ./rabbitmq-stream-ssl.conf:/etc/rabbitmq/rabbitmq.conf:ro
labels:
- 'org.springframework.boot.sslbundle.pem.keystore.certificate=client.crt'
- 'org.springframework.boot.sslbundle.pem.keystore.private-key=client.key'
- 'org.springframework.boot.sslbundle.pem.truststore.certificate=ca.crt'
secrets:
ssl-ca:
file: 'ca.crt'
ssl-key:
file: 'server.key'
ssl-cert:
file: 'server.crt'
configs:
plugins:
content: "[rabbitmq_stream]."
@@ -0,0 +1,8 @@
listeners.ssl.default=5671
ssl_options.cacertfile=/run/secrets/ssl-ca
ssl_options.certfile=/run/secrets/ssl-cert
ssl_options.keyfile=/run/secrets/ssl-key
ssl_options.verify=verify_peer
ssl_options.fail_if_no_peer_cert=true
@@ -0,0 +1,8 @@
stream.listeners.ssl.1 = 5551
ssl_options.cacertfile=/run/secrets/ssl-ca
ssl_options.certfile=/run/secrets/ssl-cert
ssl_options.keyfile=/run/secrets/ssl-key
ssl_options.verify=verify_peer
ssl_options.fail_if_no_peer_cert=true
@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIURBZvq442tp+/K9TZII5Vy/LzVxwwDQYJKoZIhvcNAQEL
BQAwOzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDEeMBwGA1UEAwwVQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MB4XDTI0MDUwMTE2NTMyNVoXDTM0MDQyOTE2NTMyNVow
LzEZMBcGA1UECgwQU3ByaW5nIEJvb3QgVGVzdDESMBAGA1UEAwwJbG9jYWxob3N0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsllxsSQzTTJlNHMfXC2b
CIXCPsfCgCBl7FbPz828jwJk+EYcXh0+WTFGks0WxSwb8NQza5UtyCUDEueZj9fV
j5mWBY97WCu01Sl/3xClHmYisXfyyv27GKec7PaSOurCm2JDkyHRNumiJROa4jte
N0GOHzw7FYsM3779TuNw14/gtW+eBrGnvgrpU7fbUvx42Di6ftGYQUwIi+3uIaqT
//i7ktDMaAQJtkL6haTzZ5JN2qKO5a34/WRz/ApvPw3lpDV8c4qoTk3C0Bg9MP+a
DnZtjtLBSN9CJWwr+n11QaMgHTotEKsOahGdi3J2zYxCvJP0LT+hjN2O9aRzSMIs
MwIDAQABo2IwYDALBgNVHQ8EBAMCBaAwEQYJYIZIAYb4QgEBBAQDAgZAMB0GA1Ud
DgQWBBS9XQHGwJZhG0olAGM1UMNuwZ65DzAfBgNVHSMEGDAWgBRVMLDVqPECWaH6
GruL9E52VcTrPjANBgkqhkiG9w0BAQsFAAOCAgEAhBcqm5UQahn8iFMETXvfLMR6
OOPijsHQ5lVfhig08s46a9O5eaJ9EYSYyiDnxYvZ4gYVH03f/kPwNLamvGR5KIBQ
R0DltkPPX4a11/vjwlSq1cXAt9r59nY+sNcVXWgIWH7zNodL8lyTpYhqvB2wEQkx
t2/JKZ8A0sGjed4S6I5HofYd7bnBxQZgfZShQ2SdDbzbcyg4SCEb8ghwnsH0KNZo
jJF+20RpK2VMViE6lylLTEMd/PyAdST/NPoqVxyva3QjTrKt+tkkFTsmNVMXcmYC
f1xo1/YFp73FFE63VYFI+Yw+Ajau8sYSo4+YvgFCy+Efhf3h3GFDtaiNod56uX9G
9M/cu8XsFzFP2e/0YWY3XL+v7ESOdc3g7yS4FQZ7Z6YvfAed9hCB25cDECvZXqJG
HSYDR38NHyAPROuCwlEwDyVmWRl9bpwZt+hr9kaTQScIDx+rV/EF3o0GKIwtR7AK
jaPAta0f4/Uu+EuWAcccSRUMtfx5/Jse/6iliBvy7JXmA+Y0PrT7K4uHO7iktdI+
x8WbfZKfnLVuqw5fneTjC1n48Ltjis/f8DgO7BuWTmLdZXddjqqxzBSukFTBn4Hg
/oSg3XiMywOAVrRCNJehcdTG0u/BqZsrRjcYAJaf5qG/0tMLNsuF9Y53XQQAeezE
etL+7y0mkeQhVF+Kmy4=
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEugIBADANBgkqhkiG9w0BAQEFAASCBKQwggSgAgEAAoIBAQCyWXGxJDNNMmU0
cx9cLZsIhcI+x8KAIGXsVs/PzbyPAmT4RhxeHT5ZMUaSzRbFLBvw1DNrlS3IJQMS
55mP19WPmZYFj3tYK7TVKX/fEKUeZiKxd/LK/bsYp5zs9pI66sKbYkOTIdE26aIl
E5riO143QY4fPDsViwzfvv1O43DXj+C1b54Gsae+CulTt9tS/HjYOLp+0ZhBTAiL
7e4hqpP/+LuS0MxoBAm2QvqFpPNnkk3aoo7lrfj9ZHP8Cm8/DeWkNXxziqhOTcLQ
GD0w/5oOdm2O0sFI30IlbCv6fXVBoyAdOi0Qqw5qEZ2LcnbNjEK8k/QtP6GM3Y71
pHNIwiwzAgMBAAECgf9REZuCvy2Bi8SoTnjqQuHG5FuA6cPuisuFZr1k88IO+zJQ
uY3WKNs29BV+LcxnoK29W8jQnjqPHXcMfrF5dVWmkrrJdu8JLaGWVHF+uBq8nRb0
2LvREh5XhZTGzIESNdc/7GIxdouag/8FlzCUYQGuT3v9+wUCiim+4CuIuPvv7ncD
8vANe3Ua5G0mHjVshOiMNpegg45zYlzYpMtUFPs+asLilW6A7UlgC+pLZ1cHUUlU
ZB7KOGT9JdrZpilTidl6LLvDDQK30TSWz8A26SuEAE71DR2VEjLVpjTNS76vlx+c
CrYr/WwpMb0xul+e/uHiNgo+51FiTiJ/IfuGeskCgYEA804CXQM6i5m4/Upps2yG
aTae5xBaYUquZREp5Zb054U6lUAHI41iTMTIwTTvWn5ogNojgi+YjljkzRj2RQ5k
NccBkjBBwwUNVWpBoGeZ73KAdejNB4C4ucGc2kkqEDo4MU5x3IE4JK1Yi1jl9mKb
IR6m3pqb2PCQHjO8sqKNHYkCgYEAu6fH/qUd/XGmCZJWY5K6jg3dISXH16MTO5M+
jetprkGMMybWKZQa1GedXurPexE48oRlRhkjdQkW6Wcj1Qh6OKp6N2Zx8sY4dLeQ
yVChnMPFE2LK+UlRCKJUZi+rzX415ML6pZg+yW7O2cHpMKv7PlXISw2YDqtboCAi
Y+doqNsCgYBE1yqmBJbZDuqfiCF2KduyA0lcmWzpIEdNw1h2ZIrwwup7dj1O2t8Y
V4lx2TdsBF4vLwli+XKRvCcovMpZaaQC70bLhSnmMxS9uS3OY+HTNTORqQfx+oLJ
1DU8Mf1b0A08LjTbLhijkASAkOuoFehMq66NR3OXIyGz2fGnHYUN+QKBgCC47SL2
X/hl7PIWVoIef/FtcXXqRKLRiPUGhA3zUwZT38K7rvSpItSPDN4UTAHFywxfEdnb
YFd0Mk6Y8aKgS8+9ynoGnzAaaJXRvKmeKdBQQvlSbNpzcnHy/IylG2xF6dfuOA7Q
MYKmk+Nc8PDPzIveIYMU58MHFn8hm12YaKOpAoGAV1CE8hFkEK9sbRGoKNJkx9nm
CZTv7PybaG/RN4ZrBSwVmnER0FEagA/Tzrlp1pi3sC8ZsC9onSOf6Btq8ZE0zbO1
vsAm3gTBXcrCJxzw0Wjt8pzEbk3yELm4WE6VDEx4da2jWocdspslpIwdjHnPwsbH
r5O3ZAgigZs/ZtKW/U4=
-----END PRIVATE KEY-----
@@ -0,0 +1,8 @@
stream.listeners.ssl.1 = 5551
ssl_options.cacertfile=/etc/rabbitmq/ca.crt
ssl_options.certfile=/etc/rabbitmq/server.crt
ssl_options.keyfile=/etc/rabbitmq/server.key
ssl_options.verify=verify_peer
ssl_options.fail_if_no_peer_cert=true
@@ -0,0 +1 @@
spring.test.context.cache.maxSize=1