Skip to content

Commit ff598a9

Browse files
committed
feat(testcontainers): fix after review
1 parent 5f592ea commit ff598a9

File tree

18 files changed

+393
-71
lines changed

18 files changed

+393
-71
lines changed

tarantool-client/src/test/java/io/tarantool/client/integration/TarantoolCrudClientTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
import org.junit.jupiter.params.provider.MethodSource;
4545
import org.msgpack.value.ValueFactory;
4646
import org.slf4j.LoggerFactory;
47-
import org.testcontainers.containers.CartridgeClusterContainer;
48-
import org.testcontainers.containers.ClusterContainer;
49-
import org.testcontainers.containers.VshardClusterContainer;
47+
import org.testcontainers.containers.cluster.ClusterContainer;
48+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
49+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
5050
import org.testcontainers.containers.output.Slf4jLogConsumer;
5151
import org.testcontainers.junit.jupiter.Testcontainers;
5252

tarantool-client/src/test/java/io/tarantool/client/integration/TarantoolCrudClientWithRetryTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import org.junit.jupiter.api.Timeout;
2626
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
2727
import org.slf4j.LoggerFactory;
28-
import org.testcontainers.containers.CartridgeClusterContainer;
28+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
2929
import org.testcontainers.containers.output.Slf4jLogConsumer;
3030
import org.testcontainers.junit.jupiter.Testcontainers;
3131

tarantool-spring-data/tarantool-spring-data-27/src/test/java/io/tarantool/spring/data27/integration/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.junit.jupiter.api.BeforeAll;
1414
import org.junit.jupiter.api.Timeout;
1515
import org.slf4j.LoggerFactory;
16-
import org.testcontainers.containers.CartridgeClusterContainer;
17-
import org.testcontainers.containers.ClusterContainer;
18-
import org.testcontainers.containers.VshardClusterContainer;
16+
import org.testcontainers.containers.cluster.ClusterContainer;
17+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
18+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
1919
import org.testcontainers.containers.output.Slf4jLogConsumer;
2020

2121
import static io.tarantool.spring.data.utils.Constants.DEFAULT_PROPERTY_FILE_NAME;

tarantool-spring-data/tarantool-spring-data-31/src/test/java/io/tarantool/spring/data31/integration/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.junit.jupiter.api.BeforeAll;
1414
import org.junit.jupiter.api.Timeout;
1515
import org.slf4j.LoggerFactory;
16-
import org.testcontainers.containers.CartridgeClusterContainer;
17-
import org.testcontainers.containers.ClusterContainer;
18-
import org.testcontainers.containers.VshardClusterContainer;
16+
import org.testcontainers.containers.cluster.ClusterContainer;
17+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
18+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
1919
import org.testcontainers.containers.output.Slf4jLogConsumer;
2020

2121
import static io.tarantool.spring.data.utils.Constants.DEFAULT_PROPERTY_FILE_NAME;

tarantool-spring-data/tarantool-spring-data-32/src/test/java/io/tarantool/spring/data32/integration/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.junit.jupiter.api.BeforeAll;
1414
import org.junit.jupiter.api.Timeout;
1515
import org.slf4j.LoggerFactory;
16-
import org.testcontainers.containers.CartridgeClusterContainer;
17-
import org.testcontainers.containers.ClusterContainer;
18-
import org.testcontainers.containers.VshardClusterContainer;
16+
import org.testcontainers.containers.cluster.ClusterContainer;
17+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
18+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
1919
import org.testcontainers.containers.output.Slf4jLogConsumer;
2020

2121
import static io.tarantool.spring.data.utils.Constants.DEFAULT_PROPERTY_FILE_NAME;

tarantool-spring-data/tarantool-spring-data-33/src/test/java/io/tarantool/spring/data33/integration/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.junit.jupiter.api.BeforeAll;
1414
import org.junit.jupiter.api.Timeout;
1515
import org.slf4j.LoggerFactory;
16-
import org.testcontainers.containers.CartridgeClusterContainer;
17-
import org.testcontainers.containers.ClusterContainer;
18-
import org.testcontainers.containers.VshardClusterContainer;
16+
import org.testcontainers.containers.cluster.ClusterContainer;
17+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
18+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
1919
import org.testcontainers.containers.output.Slf4jLogConsumer;
2020

2121
import static io.tarantool.spring.data.utils.Constants.DEFAULT_PROPERTY_FILE_NAME;

tarantool-spring-data/tarantool-spring-data-34/src/test/java/io/tarantool/spring/data34/integration/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.junit.jupiter.api.BeforeAll;
1414
import org.junit.jupiter.api.Timeout;
1515
import org.slf4j.LoggerFactory;
16-
import org.testcontainers.containers.CartridgeClusterContainer;
17-
import org.testcontainers.containers.ClusterContainer;
18-
import org.testcontainers.containers.VshardClusterContainer;
16+
import org.testcontainers.containers.cluster.ClusterContainer;
17+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
18+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
1919
import org.testcontainers.containers.output.Slf4jLogConsumer;
2020

2121
import static io.tarantool.spring.data.utils.Constants.DEFAULT_PROPERTY_FILE_NAME;

tarantool-spring-data/tarantool-spring-data-35/src/test/java/io/tarantool/spring/data35/integration/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
import org.junit.jupiter.api.BeforeAll;
1414
import org.junit.jupiter.api.Timeout;
1515
import org.slf4j.LoggerFactory;
16-
import org.testcontainers.containers.CartridgeClusterContainer;
17-
import org.testcontainers.containers.ClusterContainer;
18-
import org.testcontainers.containers.VshardClusterContainer;
16+
import org.testcontainers.containers.cluster.ClusterContainer;
17+
import org.testcontainers.containers.cluster.cartridge.CartridgeClusterContainer;
18+
import org.testcontainers.containers.cluster.vshard.VshardClusterContainer;
1919
import org.testcontainers.containers.output.Slf4jLogConsumer;
2020

2121
import static io.tarantool.spring.data.utils.Constants.DEFAULT_PROPERTY_FILE_NAME;

testcontainers/src/main/java/org/testcontainers/containers/TarantoolConfigParser.java

Lines changed: 115 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,148 @@
55

66
package org.testcontainers.containers;
77

8+
import java.io.ByteArrayOutputStream;
9+
import java.io.IOException;
810
import java.io.InputStream;
11+
import java.net.URI;
12+
import java.nio.charset.StandardCharsets;
913
import java.util.Collection;
1014
import java.util.List;
1115
import java.util.Map;
12-
import java.util.stream.Collectors;
16+
import java.util.Objects;
17+
import java.util.Optional;
1318

14-
import org.yaml.snakeyaml.LoaderOptions;
19+
import org.testcontainers.containers.tarantool.config.ConfigurationUtils;
1520
import org.yaml.snakeyaml.Yaml;
16-
import org.yaml.snakeyaml.constructor.Constructor;
1721

18-
class TarantoolConfigParser {
22+
import io.tarantool.autogen.Tarantool3Configuration;
23+
import io.tarantool.autogen.groups.groupsProperty.GroupsProperty;
24+
import io.tarantool.autogen.groups.groupsProperty.replicasets.replicasetsProperty.ReplicasetsProperty;
25+
import io.tarantool.autogen.groups.groupsProperty.replicasets.replicasetsProperty.instances.instancesProperty.InstancesProperty;
26+
import io.tarantool.autogen.groups.groupsProperty.replicasets.replicasetsProperty.instances.instancesProperty.iproto.Iproto;
27+
import io.tarantool.autogen.groups.groupsProperty.replicasets.replicasetsProperty.instances.instancesProperty.iproto.listen.Listen;
1928

20-
private final Config config;
29+
public class TarantoolConfigParser {
30+
31+
private static final String ROUTERS_GROUP_NAME = "routers";
32+
33+
private final Tarantool3Configuration config;
34+
private final Config fallbackConfig;
2135

2236
public TarantoolConfigParser(String instanceFileName) {
23-
Yaml yaml = new Yaml(new Constructor(Config.class, new LoaderOptions()));
24-
InputStream inputStream =
25-
this.getClass().getClassLoader().getResourceAsStream(instanceFileName);
26-
config = yaml.load(inputStream);
37+
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(instanceFileName);
38+
if (inputStream == null) {
39+
throw new IllegalArgumentException(
40+
String.format("No resource path found for the specified resource %s", instanceFileName));
41+
}
42+
Tarantool3Configuration parsedConfig = null;
43+
Config parsedFallbackConfig = null;
44+
try (InputStream is = inputStream) {
45+
String rawConfig = readAsString(is);
46+
try {
47+
parsedConfig = ConfigurationUtils.create(rawConfig);
48+
} catch (LinkageError e) {
49+
parsedFallbackConfig = new Yaml().loadAs(rawConfig, Config.class);
50+
}
51+
} catch (IOException e) {
52+
throw new RuntimeException(e);
53+
}
54+
this.config = parsedConfig;
55+
this.fallbackConfig = parsedFallbackConfig;
2756
}
2857

2958
public Integer[] getExposablePorts() {
59+
if (config != null) {
60+
return getExposablePortsFromTypedConfig();
61+
}
62+
return getExposablePortsFromFallbackConfig();
63+
}
64+
65+
private Integer[] getExposablePortsFromTypedConfig() {
66+
if (config.getGroups().isEmpty()) {
67+
return new Integer[] {};
68+
}
69+
GroupsProperty routersGroup =
70+
config.getGroups().get().getAdditionalProperties().get(ROUTERS_GROUP_NAME);
71+
if (routersGroup == null || !routersGroup.getReplicasets().isPresent()) {
72+
return new Integer[] {};
73+
}
3074
List<Integer> ports =
31-
config.getGroups().get("routers").getReplicasets().values().stream()
32-
.map(replicaset -> replicaset.getInstances().values())
75+
routersGroup.getReplicasets().get().getAdditionalProperties().values().stream()
76+
.map(ReplicasetsProperty::getInstances)
77+
.filter(Optional::isPresent)
78+
.map(Optional::get)
79+
.map(instances -> instances.getAdditionalProperties().values())
3380
.flatMap(Collection::stream)
34-
.map(instance -> instance.getIproto().values())
81+
.map(InstancesProperty::getIproto)
82+
.filter(Optional::isPresent)
83+
.map(Optional::get)
84+
.map(Iproto::getListen)
85+
.filter(Optional::isPresent)
86+
.map(Optional::get)
87+
.flatMap(List::stream)
88+
.map(Listen::getUri)
89+
.filter(Optional::isPresent)
90+
.map(Optional::get)
91+
.map(TarantoolConfigParser::parsePort)
92+
.toList();
93+
94+
return ports.toArray(new Integer[] {});
95+
}
96+
97+
private Integer[] getExposablePortsFromFallbackConfig() {
98+
if (fallbackConfig == null
99+
|| fallbackConfig.getGroups() == null
100+
|| !fallbackConfig.getGroups().containsKey(ROUTERS_GROUP_NAME)) {
101+
return new Integer[] {};
102+
}
103+
Group routersGroup = fallbackConfig.getGroups().get(ROUTERS_GROUP_NAME);
104+
if (routersGroup == null || routersGroup.getReplicasets() == null) {
105+
return new Integer[] {};
106+
}
107+
List<Integer> ports =
108+
routersGroup.getReplicasets().values().stream()
109+
.map(Replicaset::getInstances)
110+
.filter(Objects::nonNull)
111+
.map(Map::values)
112+
.flatMap(Collection::stream)
113+
.map(Instance::getIproto)
114+
.filter(Objects::nonNull)
115+
.map(Map::values)
35116
.flatMap(Collection::stream)
36117
.flatMap(Collection::stream)
37118
.map(Map::values)
38119
.flatMap(Collection::stream)
39120
.map(TarantoolConfigParser::parsePort)
40-
.collect(Collectors.toList());
41-
121+
.toList();
42122
return ports.toArray(new Integer[] {});
43123
}
44124

45125
private static Integer parsePort(String uri) {
46-
if (uri == null || uri.isEmpty()) {
126+
if (uri == null || uri.isBlank()) {
47127
throw new IllegalArgumentException("Listen URI must not be null or empty");
48128
}
49-
50129
String normalized = uri.trim();
51-
int lastColon = normalized.lastIndexOf(':');
52-
if (lastColon >= 0) {
53-
normalized = normalized.substring(lastColon + 1);
130+
String uriWithScheme = normalized.contains("://") ? normalized : "tcp://" + normalized;
131+
try {
132+
URI parsed = URI.create(uriWithScheme);
133+
int port = parsed.getPort();
134+
if (port < 0) {
135+
throw new IllegalArgumentException("Listen URI must contain a valid port: " + uri);
136+
}
137+
return port;
138+
} catch (IllegalArgumentException e) {
139+
throw new IllegalArgumentException("Failed to parse listen URI: " + uri, e);
140+
}
141+
}
142+
143+
private static String readAsString(InputStream inputStream) throws IOException {
144+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
145+
byte[] buffer = new byte[8192];
146+
int bytesRead;
147+
while ((bytesRead = inputStream.read(buffer)) != -1) {
148+
outputStream.write(buffer, 0, bytesRead);
54149
}
55-
return Integer.parseInt(normalized);
150+
return outputStream.toString(StandardCharsets.UTF_8);
56151
}
57152
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2025 VK DIGITAL TECHNOLOGIES LIMITED LIABILITY COMPANY
3+
* All Rights Reserved.
4+
*/
5+
6+
package org.testcontainers.containers.cluster;
7+
8+
import java.util.Map;
9+
10+
/**
11+
* Common configurator contract for single-router test clusters.
12+
*
13+
* @param <C> cluster container type
14+
*/
15+
public interface ClusterConfigurator<C extends ClusterContainer<?>> extends AutoCloseable {
16+
17+
/** Returns cluster name. */
18+
String clusterName();
19+
20+
/** Returns all cluster nodes participating in configuration. */
21+
Map<String, C> nodes();
22+
23+
/** Applies cluster-specific configuration after container startup. */
24+
void configure();
25+
26+
/** Returns true if configuration was already applied for current lifecycle. */
27+
boolean configured();
28+
29+
@Override
30+
default void close() {}
31+
}

0 commit comments

Comments
 (0)