Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

### Testcontainers

- Add TQE 3.x (message-queue-ee 3.x) integration on top of the
existing TQE 2.x support; consolidate the TQE 2.x / 3.x test
surface into a single parameterized suite.
- Add constructor/builder parameters to supply the initial Lua script as a string or as a file path, and optional additional script paths copied into the container data directory (`Tarantool2Container`, `CartridgeClusterContainer`, `VshardClusterContainer`); simplify bundled `server.lua` accordingly.
- Upgrade TQE to v3.5.0.

Expand Down
51 changes: 32 additions & 19 deletions testcontainers/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<properties>
<license.header.file>${project.parent.basedir}/LICENSE_HEADER.txt</license.header.file>
<maven.compiler.release>17</maven.compiler.release>
<protobuf-plugin.version>0.6.1</protobuf-plugin.version>
<protobuf-plugin.version>5.1.4</protobuf-plugin.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -104,13 +104,6 @@
</dependencies>

<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.0</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.jsonschema2pojo</groupId>
Expand Down Expand Up @@ -146,25 +139,45 @@
</dependencies>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<groupId>io.github.ascopes</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>${protobuf-plugin.version}</version>
<configuration>
<protoTestSourceRoot>${project.basedir}/src/test/proto</protoTestSourceRoot>
<protocArtifact>
com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
</pluginArtifact>
<protoc kind="binary-maven">
<version>${protobuf.version}</version>
</protoc>
<plugins>
<plugin kind="binary-maven">
<groupId>io.grpc</groupId>
<artifactId>protoc-gen-grpc-java</artifactId>
<version>${grpc.version}</version>
</plugin>
</plugins>
</configuration>
<executions>
<execution>
<id>generate-test-tqe3</id>
<goals>
<goal>test-compile</goal>
<goal>test-compile-custom</goal>
<goal>generate-test</goal>
</goals>
<configuration>
<sourceDirectories>
<sourceDirectory>${project.basedir}/src/test/proto/tqe3</sourceDirectory>
</sourceDirectories>
<outputDirectory>${project.build.directory}/generated-test-sources/protobuf/tqe3</outputDirectory>
</configuration>
</execution>
<execution>
<id>generate-test-tqe2</id>
<goals>
<goal>generate-test</goal>
</goals>
<configuration>
<sourceDirectories>
<sourceDirectory>${project.basedir}/src/test/proto/tqe2</sourceDirectory>
</sourceDirectories>
<outputDirectory>${project.build.directory}/generated-test-sources/protobuf/tqe2</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -50,24 +51,26 @@ public interface GrpcContainer<SELF extends GrpcContainer<SELF>>
enum GrpcRole {
CONSUMER("consumer"),

PRODUCER("producer");
PRODUCER("producer", "publisher");

private final String role;
private final List<String> aliases;

private static final Map<String, GrpcRole> ROLES = new HashMap<>();

static {
for (GrpcRole value : values()) {
ROLES.put(value.getRole(), value);
for (String alias : value.aliases) {
ROLES.put(alias, value);
}
}
}

GrpcRole(String role) {
this.role = role;
GrpcRole(String... aliases) {
this.aliases = List.of(aliases);
}

public String getRole() {
return this.role;
return this.aliases.get(0);
}

public static GrpcRole from(String role) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private static void validateConfigPath(Path configPath) {
if (configPath == null
|| !Files.exists(configPath)
|| !Files.isRegularFile(configPath)
|| configPath.endsWith(".yml")) {
|| !configPath.toString().endsWith(".yml")) {
LOGGER.error(
"Invalid config file. Config path is null or not exists or not regular or not having"
+ " '.yml' extension: {}",
Expand Down Expand Up @@ -223,11 +223,11 @@ private static Set<Integer> resolveGrpcPorts(GrpcConfiguration config, Path conf
* (required).
*/
private static Set<GrpcRole> resolveRoles(GrpcConfiguration config, Path configPath) {
final Optional<Boolean> isPublisher = config.getProducer().flatMap(ProducerConfig::getEnabled);
final Optional<Boolean> isProducer = config.getProducer().flatMap(ProducerConfig::getEnabled);
final Set<GrpcRole> roles = new LinkedHashSet<>();
if (isPublisher.isPresent() && isPublisher.get()) {
if (isProducer.isPresent() && isProducer.get()) {
roles.add(GrpcRole.PRODUCER);
LOGGER.trace("Publisher role is enabled for: {}", configPath);
LOGGER.trace("Producer role is enabled for: {}", configPath);
}

final Optional<Boolean> isConsumer = config.getConsumer().flatMap(ConsumerConfig::getEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
import io.tarantool.autogen.iproto.listen.Listen;

/**
* Base implementation of {@link TQEConfigurator} that configure TQE cluster using configuration
* files. All other implementations should extend this class.
* Configures TQE cluster using configuration files. Supports both TQE 2.x and TQE 3.x via factory
* methods {@link #tqe2Builder} and {@link #tqe3Builder}.
*/
public class FileTQEConfigurator implements TQEConfigurator {

Expand All @@ -64,11 +64,12 @@ public class FileTQEConfigurator implements TQEConfigurator {
/* Constants
/**********************************************************
*/
private static final String TQE2_ROUTER_ROLE = "app.roles.api";
private static final String TQE3_ROUTER_ROLE = "roles.tqe-router";

private static final String CONFIGURATOR_ERROR_MSG =
"An error occurred when configuring the TQE cluster. See logs for details.";

private static final String TQE_ROUTER_ROLE = "roles.tqe-router";

/*
/**********************************************************
/* Parameter extractors
Expand Down Expand Up @@ -97,6 +98,8 @@ public class FileTQEConfigurator implements TQEConfigurator {

private final Network network;

private final String routerRole;

private boolean configured;

private FileTQEConfigurator(
Expand All @@ -105,11 +108,13 @@ private FileTQEConfigurator(
Collection<Path> grpcConfigs,
String clusterName,
Duration startupTimeout,
Duration bootstrapTimeout) {
Duration bootstrapTimeout,
String routerRole) {
this.queueConfig = queueConfig;
this.grpcConfigs = grpcConfigs;
this.clusterName = clusterName;
this.bootstrapTimeout = bootstrapTimeout;
this.routerRole = routerRole;
this.routerNames = new LinkedHashSet<>(1);
this.image = image;
this.startupTimeout = startupTimeout;
Expand Down Expand Up @@ -156,9 +161,9 @@ private Map<String, TarantoolContainer<?>> initQueue(
final Map<String, TarantoolContainer<?>> nodes = new LinkedHashMap<>(instances.size());

this.routerNames.addAll(
ConfigurationUtils.findInstancesWithRole(this.queueParsedConfig, TQE_ROUTER_ROLE));
ConfigurationUtils.findInstancesWithRole(this.queueParsedConfig, this.routerRole));
if (this.routerNames.isEmpty()) {
LOGGER.error("At least one container must have the 'router' and '{}' roles", TQE_ROUTER_ROLE);
LOGGER.error("At least one container must have the 'router' and '{}' roles", this.routerRole);
throw new ContainerLaunchException(CONFIGURATOR_ERROR_MSG);
}

Expand Down Expand Up @@ -436,11 +441,41 @@ public synchronized void close() {
}
}

public static Builder builder(
/**
* Creates a builder pre-configured for TQE 2.x (router role: {@value #TQE2_ROUTER_ROLE}).
*
* @param image Docker image name
* @param queueConfig path to queue configuration file
* @param grpcConfigs paths to gRPC configuration files
* @return builder with TQE 2.x router role pre-set
*/
public static Builder tqe2Builder(
DockerImageName image, Path queueConfig, Collection<Path> grpcConfigs) {
return new Builder(image, queueConfig, grpcConfigs);
return builder(image, queueConfig, grpcConfigs, TQE2_ROUTER_ROLE);
}

/**
* Creates a builder pre-configured for TQE 3.x (router role: {@value #TQE3_ROUTER_ROLE}).
*
* @param image Docker image name
* @param queueConfig path to queue configuration file
* @param grpcConfigs paths to gRPC configuration files
* @return builder with TQE 3.x router role pre-set
*/
public static Builder tqe3Builder(
DockerImageName image, Path queueConfig, Collection<Path> grpcConfigs) {
return builder(image, queueConfig, grpcConfigs, TQE3_ROUTER_ROLE);
}

private static Builder builder(
DockerImageName image, Path queueConfig, Collection<Path> grpcConfigs, String routerRole) {
return new Builder(image, queueConfig, grpcConfigs, routerRole);
}

/**
* Builder for {@link FileTQEConfigurator}. Use factory methods {@link #tqe2Builder} or {@link
* #tqe3Builder} to obtain a pre-configured builder.
*/
public static class Builder {

private static final String DEFAULT_CLUSTER_NAME_PREFIX = "tqe-test";
Expand All @@ -450,8 +485,10 @@ public static class Builder {
private String clusterName;
private Duration startupTimeout;
private Duration bootstrapTimeout;
private final String routerRole;

public Builder(DockerImageName image, Path queueConfig, Collection<Path> grpcConfigs) {
private Builder(
DockerImageName image, Path queueConfig, Collection<Path> grpcConfigs, String routerRole) {
if (queueConfig == null || !Files.isRegularFile(queueConfig)) {
LOGGER.error("Queue config file is invalid (null or not regular): {})", queueConfig);
throw new IllegalArgumentException(CONFIGURATOR_ERROR_MSG);
Expand All @@ -469,9 +506,11 @@ public Builder(DockerImageName image, Path queueConfig, Collection<Path> grpcCon
throw new IllegalArgumentException(CONFIGURATOR_ERROR_MSG);
}
});

this.image = image;
this.queueConfig = queueConfig;
this.grpcConfigs = new LinkedHashSet<>(grpcConfigs);
this.routerRole = routerRole;
}

public Builder withClusterName(String clusterName) {
Expand Down Expand Up @@ -514,7 +553,8 @@ public FileTQEConfigurator build() {
this.grpcConfigs,
clusterName,
startupTimeout,
bootstrapTimeout);
bootstrapTimeout,
this.routerRole);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Optional;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

Expand Down Expand Up @@ -73,6 +74,7 @@ public class GrpcConfiguration {
private final Boolean daemon;

@JsonProperty("producer")
@JsonAlias("publisher")
private final ProducerConfig producer;

@JsonProperty("consumer")
Expand Down

This file was deleted.

Loading