Skip to content

Commit f26acb6

Browse files
committed
Add cluster test suite
1 parent 761f222 commit f26acb6

File tree

9 files changed

+139
-21
lines changed

9 files changed

+139
-21
lines changed

.github/workflows/test.yml

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,31 @@ jobs:
2828
server-password: MAVEN_PASSWORD
2929
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
3030
gpg-passphrase: MAVEN_GPG_PASSPHRASE
31-
- name: Start broker
32-
run: ci/start-broker.sh
33-
- name: Start toxiproxy
34-
run: ci/start-toxiproxy.sh
35-
- name: Display Java version
36-
run: ./mvnw --version
37-
- name: Test
38-
run: |
39-
./mvnw verify -Drabbitmqctl.bin=DOCKER:rabbitmq --no-transfer-progress \
40-
-Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
41-
-Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
42-
-Dclient.key=./tls-gen/basic/result/client_$(hostname)_key.pem
31+
# - name: Start broker
32+
# run: ci/start-broker.sh
33+
# - name: Start toxiproxy
34+
# run: ci/start-toxiproxy.sh
35+
# - name: Display Java version
36+
# run: ./mvnw --version
37+
# - name: Test
38+
# run: |
39+
# ./mvnw verify -Drabbitmqctl.bin=DOCKER:rabbitmq --no-transfer-progress \
40+
# -Dca.certificate=./tls-gen/basic/result/ca_certificate.pem \
41+
# -Dclient.certificate=./tls-gen/basic/result/client_$(hostname)_certificate.pem \
42+
# -Dclient.key=./tls-gen/basic/result/client_$(hostname)_key.pem
43+
# - name: Stop toxiproxy
44+
# run: docker stop toxiproxy && docker rm toxiproxy
45+
# - name: Stop broker
46+
# run: docker stop rabbitmq && docker rm rabbitmq
47+
- name: Start cluster
48+
run: ci/start-cluster.sh
49+
- name: Test against cluster
50+
run: ./mvnw test -Dtest=ClusterTest -Drabbitmqctl.bin=DOCKER:rabbitmq0
51+
- name: Stop cluster
52+
run: docker compose --file ci/cluster/docker-compose.yml down
4353
- name: Publish snapshot
4454
run: ./mvnw clean deploy -Psnapshots -DskipITs -DskipTests
4555
env:
4656
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
4757
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
48-
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
49-
- name: Stop toxiproxy
50-
run: docker stop toxiproxy && docker rm toxiproxy
51-
- name: Stop broker
52-
run: docker stop rabbitmq && docker rm rabbitmq
58+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[rabbitmq_management].
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
2+
cluster_formation.classic_config.nodes.1 = rabbit@node0
3+
cluster_formation.classic_config.nodes.2 = rabbit@node1
4+
cluster_formation.classic_config.nodes.3 = rabbit@node2
5+
loopback_users = none

ci/cluster/docker-compose.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
services:
2+
node0:
3+
environment:
4+
- RABBITMQ_ERLANG_COOKIE='secret_cookie'
5+
networks:
6+
- rabbitmq-cluster
7+
hostname: node0
8+
container_name: rabbitmq0
9+
image: ${RABBITMQ_IMAGE:-pivotalrabbitmq/rabbitmq:v4.0.x}
10+
pull_policy: always
11+
ports:
12+
- "5672:5672"
13+
- "15672:15672"
14+
tty: true
15+
volumes:
16+
- ./configuration/:/etc/rabbitmq/
17+
node1:
18+
environment:
19+
- RABBITMQ_ERLANG_COOKIE='secret_cookie'
20+
networks:
21+
- rabbitmq-cluster
22+
hostname: node1
23+
container_name: rabbitmq1
24+
image: ${RABBITMQ_IMAGE:-pivotalrabbitmq/rabbitmq:v4.0.x}
25+
pull_policy: always
26+
ports:
27+
- "5673:5672"
28+
- "15673:15672"
29+
tty: true
30+
volumes:
31+
- ./configuration/:/etc/rabbitmq/
32+
node2:
33+
environment:
34+
- RABBITMQ_ERLANG_COOKIE='secret_cookie'
35+
networks:
36+
- rabbitmq-cluster
37+
hostname: node2
38+
container_name: rabbitmq2
39+
image: ${RABBITMQ_IMAGE:-pivotalrabbitmq/rabbitmq:v4.0.x}
40+
pull_policy: always
41+
ports:
42+
- "5674:5672"
43+
- "15674:15672"
44+
tty: true
45+
volumes:
46+
- ./configuration/:/etc/rabbitmq/
47+
networks:
48+
rabbitmq-cluster:

ci/start-broker.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ RABBITMQ_IMAGE=${RABBITMQ_IMAGE:-pivotalrabbitmq/rabbitmq:v4.0.x}
55
wait_for_message() {
66
while ! docker logs "$1" | grep -q "$2";
77
do
8-
sleep 5
9-
echo "Waiting 5 seconds for $1 to start..."
8+
sleep 2
9+
echo "Waiting 2 seconds for $1 to start..."
1010
done
1111
}
1212

ci/start-cluster.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
3+
export RABBITMQ_IMAGE=${RABBITMQ_IMAGE:-pivotalrabbitmq/rabbitmq:v4.0.x}
4+
5+
wait_for_message() {
6+
while ! docker logs "$1" | grep -q "$2";
7+
do
8+
sleep 2
9+
echo "Waiting 2 seconds for $1 to start..."
10+
done
11+
}
12+
13+
docker compose --file ci/cluster/docker-compose.yml down
14+
docker compose --file ci/cluster/docker-compose.yml config
15+
docker compose --file ci/cluster/docker-compose.yml up --detach
16+
17+
wait_for_message rabbitmq0 "completed with"
18+
19+
docker exec rabbitmq0 rabbitmqctl await_online_nodes 3
20+
21+
docker exec rabbitmq0 rabbitmq-diagnostics erlang_version
22+
docker exec rabbitmq0 rabbitmqctl version

src/main/java/com/rabbitmq/client/amqp/impl/AmqpConnection.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,19 @@ private static NativeConnectionWrapper enforceAffinity(
249249
Management.QueueInfo info = management.queueInfo(affinity.queue());
250250
NativeConnectionWrapper pickedConnection = null;
251251
int attemptCount = 0;
252-
while (pickedConnection == null && ++attemptCount <= 5) {
252+
while (pickedConnection == null) {
253+
attemptCount++;
253254
List<String> nodesWithAffinity = ConnectionUtils.findAffinity(affinity, info);
254255
LOGGER.debug("Currently connected to node {}", connectionWrapper.nodename);
255256
if (nodesWithAffinity.contains(connectionWrapper.nodename)) {
256257
LOGGER.debug("Affinity {} found with node {}", affinity, connectionWrapper.nodename);
257258
pickedConnection = connectionWrapper;
259+
} else if (attemptCount == 5) {
260+
LOGGER.debug(
261+
"Could not find affinity {} after {} attempt(s), using last connection",
262+
affinity,
263+
attemptCount);
264+
pickedConnection = connectionWrapper;
258265
} else {
259266
LOGGER.debug(
260267
"Affinity {} not found with node {}", affinity, connectionWrapper.nodename);

src/test/java/com/rabbitmq/client/amqp/impl/ClusterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import java.util.function.Consumer;
2626
import org.junit.jupiter.api.*;
2727

28-
@Disabled
28+
@TestUtils.DisabledIfNotCluster
2929
public class ClusterTest {
3030

3131
Environment environment;

src/test/java/com/rabbitmq/client/amqp/impl/TestUtils.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ static boolean addressV1Permitted() {
370370
.endsWith("true");
371371
}
372372

373+
static boolean isCluster() {
374+
return !Cli.rabbitmqctl("eval 'nodes().'").output().replace("[", "").replace("]", "").isBlank();
375+
}
376+
373377
static class DisabledIfTlsNotEnabledCondition implements ExecutionCondition {
374378

375379
@Override
@@ -479,6 +483,25 @@ private static class DisabledIfAuthMechanismSslNotEnabledCondition
479483
}
480484
}
481485

486+
static class DisabledIfNotClusterCondition implements ExecutionCondition {
487+
488+
private static final String KEY = "isCluster";
489+
490+
@Override
491+
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
492+
boolean isCluster =
493+
context
494+
.getRoot()
495+
.getStore(ExtensionContext.Namespace.GLOBAL)
496+
.getOrComputeIfAbsent(KEY, k -> isCluster(), Boolean.class);
497+
if (isCluster) {
498+
return ConditionEvaluationResult.enabled("Multi-node cluster");
499+
} else {
500+
return ConditionEvaluationResult.disabled("Not a multi-node cluster");
501+
}
502+
}
503+
}
504+
482505
@Target({ElementType.TYPE, ElementType.METHOD})
483506
@Retention(RetentionPolicy.RUNTIME)
484507
@Documented
@@ -509,6 +532,12 @@ private static class DisabledIfAuthMechanismSslNotEnabledCondition
509532
@ExtendWith(DisabledIfAuthMechanismSslNotEnabledCondition.class)
510533
@interface DisabledIfAuthMechanismSslNotEnabled {}
511534

535+
@Target({ElementType.TYPE, ElementType.METHOD})
536+
@Retention(RetentionPolicy.RUNTIME)
537+
@Documented
538+
@ExtendWith(DisabledIfNotClusterCondition.class)
539+
@interface DisabledIfNotCluster {}
540+
512541
static class QueueInfoAssert extends AbstractObjectAssert<QueueInfoAssert, Management.QueueInfo> {
513542

514543
private QueueInfoAssert(Management.QueueInfo queueInfo) {

0 commit comments

Comments
 (0)