Move Spring AMQP 0.9 support to spring-boot-rabbitmq

Now that Spring AMQP supports AMQP 1.0 as well, we need to straighten
out our existing support. AMQP 0.9 is RabbitMQ specific, so we can no
longer refer it to "amqp". This commit migrates the existing support
to spring-boot-rabbitmq and renames the starters as well.

For continuity, users should migrate from "spring-boot-starter-amqp"
to "spring-boot-starter-rabbitmq". While the root package has been
changed for consistency, most names are the same, including
configuration properties still in the "spring.rabbitmq" namespace.

Keys to configure the version of the RabbitMQ clients have migrated to
'rabbitmq.client' and 'rabbitmq.stream.client' respectively.

Closes gh-49677
This commit is contained in:
Stéphane Nicoll
2026-07-15 15:10:09 +02:00
parent 467fde153f
commit f48cc3ac10
110 changed files with 286 additions and 284 deletions
@@ -0,0 +1,69 @@
/*
* 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.rabbitmq.docker.compose;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RabbitMqDockerComposeConnectionDetailsFactory} and
* {@link RabbitMqStreamDockerComposeConnectionDetailsFactory} when used in combination.
*
* @author Andy Wilkinson
*/
class RabbitMqAndRabbitMqStreamDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbitmq-and-rabbitmq-stream-separate-services-compose.yaml",
image = TestImage.RABBITMQ)
void runCreatesConnectionDetailsFromSeparateServices(RabbitConnectionDetails connectionDetails,
RabbitStreamConnectionDetails streamConnectionDetails) {
assertConnectionDetails(connectionDetails);
assertConnectionDetails(streamConnectionDetails);
}
@DockerComposeTest(composeFile = "rabbitmq-and-rabbitmq-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.rabbitmq.docker.compose;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
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 RabbitMqDockerComposeConnectionDetailsFactory}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Scott Frederick
*/
class RabbitMqDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbitmq-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetails(RabbitConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails);
assertThat(connectionDetails.getSslBundle()).isNull();
}
@DockerComposeTest(composeFile = "rabbitmq-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.rabbitmq.docker.compose;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
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 RabbitMqStreamDockerComposeConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
class RabbitMqStreamDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbitmq-stream-compose.yaml", image = TestImage.RABBITMQ)
void runCreatesConnectionDetails(RabbitStreamConnectionDetails connectionDetails) {
assertConnectionDetails(connectionDetails);
}
@DockerComposeTest(composeFile = "rabbitmq-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,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.rabbitmq.docker.compose;
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails.Address;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.testsupport.container.TestImage;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link RabbitMqDockerComposeConnectionDetailsFactory} and
* {@link RabbitMqStreamDockerComposeConnectionDetailsFactory} when using a single service
* for standard and stream-based messaging.
*
* @author Andy Wilkinson
*/
class SingleServiceRabbitAndRabbitMqStreamDockerComposeConnectionDetailsFactoryIntegrationTests {
@DockerComposeTest(composeFile = "rabbitmq-and-rabbitmq-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.rabbitmq.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.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
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 RabbitMqContainerConnectionDetailsFactoryIntegrationTests}.
*/
@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.rabbitmq.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.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
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 RabbitMqContainerConnectionDetailsFactory}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class RabbitMqContainerConnectionDetailsFactoryIntegrationTests {
@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.rabbitmq.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.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
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 RabbitMqStreamContainerConnectionDetailsFactory} 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 RabbitMqStreamContainerConnectionDetailsFactoryIntegrationTests {
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.rabbitmq.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.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
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 RabbitMqStreamContainerConnectionDetailsFactory} 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 RabbitMqStreamWithSslContainerConnectionDetailsFactoryIntegrationTests {
private static final int RABBITMQ_STREAMS_TLS_PORT = 5551;
@Container
@ServiceConnection(type = RabbitStreamConnectionDetails.class)
@PemTrustStore(certificate = "classpath:org/springframework/boot/rabbitmq/ca.crt")
@PemKeyStore(certificate = "classpath:org/springframework/boot/rabbitmq/client.crt",
privateKey = "classpath:org/springframework/boot/rabbitmq/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/rabbitmq/testcontainers/rabbitmq-stream-ssl.conf"),
"/etc/rabbitmq/rabbitmq.conf");
container.withCopyFileToContainer(
MountableFile.forClasspathResource("org/springframework/boot/rabbitmq/ca.crt"), "/etc/rabbitmq/ca.crt");
container.withCopyFileToContainer(
MountableFile.forClasspathResource("org/springframework/boot/rabbitmq/server.key"),
"/etc/rabbitmq/server.key");
container.withCopyFileToContainer(
MountableFile.forClasspathResource("org/springframework/boot/rabbitmq/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.rabbitmq.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.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
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 RabbitMqStreamContainerConnectionDetailsFactory} 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 SeparateContainersRabbitMqAndRabbitMqStreamContainerConnectionDetailsFactoryIntegrationTests {
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.rabbitmq.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.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.EnvironmentBuilderCustomizer;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitAutoConfiguration;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitConnectionDetails;
import org.springframework.boot.rabbitmq.autoconfigure.RabbitStreamConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqContainerConnectionDetailsFactory.RabbitMqContainerConnectionDetails;
import org.springframework.boot.rabbitmq.testcontainers.RabbitMqStreamContainerConnectionDetailsFactory.RabbitMqStreamContainerConnectionDetails;
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 RabbitMqStreamContainerConnectionDetailsFactory} 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 SingleContainerRabbitAndRabbitMqStreamContainerConnectionDetailsFactoryIntegrationTests {
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,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,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 @@
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