Skip to content

Commit

Permalink
Allow running product tests on IPv6 stack
Browse files Browse the repository at this point in the history
  • Loading branch information
wendigo committed Dec 19, 2024
1 parent 465f48a commit 6fdcd0d
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public static class Execution
private final Map<String, String> extraOptions;
private final PrintStream printStream;
private final boolean debug;
private final boolean ipv6;

@Inject
public Execution(EnvironmentFactory environmentFactory, EnvironmentConfig environmentConfig, EnvironmentOptions options, EnvironmentUpOptions environmentUpOptions, PrintStream printStream)
Expand All @@ -127,6 +128,7 @@ public Execution(EnvironmentFactory environmentFactory, EnvironmentConfig enviro
this.extraOptions = ImmutableMap.copyOf(requireNonNull(environmentUpOptions.extraOptions, "environmentUpOptions.extraOptions is null"));
this.printStream = requireNonNull(printStream, "printStream is null");
this.debug = options.debug;
this.ipv6 = options.ipv6;
}

@Override
Expand All @@ -136,7 +138,8 @@ public Integer call()
Environment.Builder builder = environmentFactory.get(environment, printStream, environmentConfig, extraOptions)
.setContainerOutputMode(outputMode)
.setLogsBaseDir(environmentLogPath)
.removeContainer(TESTS);
.removeContainer(TESTS)
.setIpv6(ipv6);

if (withoutCoordinator) {
builder.removeContainers(container -> isTrinoContainer(container.getLogicalName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public static class Execution
private final EnvironmentFactory environmentFactory;
private final boolean debug;
private final boolean debugSuspend;
private final boolean ipv6;
private final JdkProvider jdkProvider;
private final File testJar;
private final File cliJar;
Expand Down Expand Up @@ -185,6 +186,7 @@ public Execution(
this.environmentFactory = requireNonNull(environmentFactory, "environmentFactory is null");
requireNonNull(environmentOptions, "environmentOptions is null");
this.debug = environmentOptions.debug;
this.ipv6 = environmentOptions.ipv6;
this.debugSuspend = testRunOptions.debugSuspend;
this.jdkProvider = requireNonNull(jdkProvider, "jdkProvider is null");
this.testJar = requireNonNull(testRunOptions.testJar, "testRunOptions.testJar is null");
Expand Down Expand Up @@ -322,7 +324,8 @@ private Environment getEnvironment()
Environment.Builder builder = environmentFactory.get(environment, printStream, environmentConfig, extraOptions)
.setContainerOutputMode(outputMode)
.setStartupRetries(startupRetries)
.setLogsBaseDir(logsDirBase);
.setLogsBaseDir(logsDirBase)
.setIpv6(ipv6);

builder.configureContainer(TESTS, this::mountReportsDir);
builder.configureContainer(TESTS, container -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public final class Environment
private final Map<String, DockerContainer> containers;
private final EnvironmentListener listener;
private final boolean attached;
private final boolean ipv6;
private final Map<String, List<String>> configuredFeatures;

private Environment(
Expand All @@ -111,12 +112,14 @@ private Environment(
Map<String, DockerContainer> containers,
EnvironmentListener listener,
boolean attached,
boolean ipv6,
Map<String, List<String>> configuredFeatures,
List<Supplier<String>> startupLogs)
{
this.name = requireNonNull(name, "name is null");
this.startupRetries = startupRetries;
this.containers = requireNonNull(containers, "containers is null");
this.ipv6 = ipv6;
this.listener = compose(requireNonNull(listener, "listener is null"), printStartupLogs(startupLogs));
this.attached = attached;
this.configuredFeatures = requireNonNull(configuredFeatures, "configuredFeatures is null");
Expand All @@ -141,7 +144,7 @@ public Environment start()
return Failsafe
.with(retryPolicy)
.with(executorService)
.get(this::tryStart);
.get(() -> tryStart());
}

private Environment tryStart()
Expand All @@ -159,7 +162,7 @@ private Environment tryStart()
}

// Create new network when environment tries to start
try (Network network = createNetwork(name)) {
try (Network network = createNetwork(name, ipv6)) {
attachNetwork(containers, network);
Startables.deepStart(containers).get();

Expand Down Expand Up @@ -372,12 +375,13 @@ private static void attachNetwork(Collection<DockerContainer> values, Network ne
values.forEach(container -> container.withNetwork(network));
}

private static Network createNetwork(String environmentName)
private static Network createNetwork(String environmentName, boolean ipv6)
{
Network network = Network.builder()
.createNetworkCmdModifier(createNetworkCmd ->
createNetworkCmd
.withName(PRODUCT_TEST_LAUNCHER_NETWORK)
.withEnableIpv6(ipv6)
.withLabels(ImmutableMap.of(
PRODUCT_TEST_LAUNCHER_STARTED_LABEL_NAME, PRODUCT_TEST_LAUNCHER_STARTED_LABEL_VALUE,
PRODUCT_TEST_LAUNCHER_ENVIRONMENT_LABEL_NAME, environmentName)))
Expand All @@ -399,6 +403,7 @@ public static class Builder
private int startupRetries = 1;
private Optional<Path> logsBaseDir = Optional.empty();
private boolean attached;
private boolean ipv6;

public Builder(String name, PrintStream printStream)
{
Expand Down Expand Up @@ -649,6 +654,7 @@ public Environment build(EnvironmentListener listener)
containers,
listener,
attached,
ipv6,
configuredFeatures,
startupLogs.build());
}
Expand Down Expand Up @@ -738,5 +744,11 @@ public Builder setAttached(boolean attached)
this.attached = attached;
return this;
}

public Builder setIpv6(boolean ipv6)
{
this.ipv6 = ipv6;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,12 @@ public boolean provideTracing(EnvironmentOptions options)
{
return options.tracing;
}

@Provides
@Singleton
@Ipv6
public boolean provideIpv6(EnvironmentOptions options)
{
return options.ipv6;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public final class EnvironmentOptions
@Nullable
public Path jdkDownloadPath;

@Option(names = "--ipv6", paramLabel = "<ipv6>", description = "Enable IPv6 networking")
public boolean ipv6;

@Option(names = "--bind", description = "Bind exposed container ports to host ports, possible values: " + BIND_ON_HOST + ", " + DO_NOT_BIND + ", [port base number] " + DEFAULT_VALUE, defaultValue = BIND_ON_HOST, arity = "0..1", fallbackValue = BIND_ON_HOST)
public void setBindOnHost(String value)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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
*
* http://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 io.trino.tests.product.launcher.env;

import com.google.inject.BindingAnnotation;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target({FIELD, PARAMETER, METHOD})
@BindingAnnotation
public @interface Ipv6
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import io.trino.tests.product.launcher.env.Environment;
import io.trino.tests.product.launcher.env.EnvironmentConfig;
import io.trino.tests.product.launcher.env.EnvironmentContainers;
import io.trino.tests.product.launcher.env.Ipv6;
import io.trino.tests.product.launcher.env.ServerPackage;
import io.trino.tests.product.launcher.env.Tracing;
import io.trino.tests.product.launcher.env.jdk.JdkProvider;
Expand Down Expand Up @@ -90,6 +91,7 @@ public final class Standard
private final File serverPackage;
private final boolean debug;
private final boolean tracing;
private final boolean ipv6;

@Inject
public Standard(
Expand All @@ -99,14 +101,16 @@ public Standard(
@ServerPackage File serverPackage,
JdkProvider jdkProvider,
@Debug boolean debug,
@Tracing boolean tracing)
@Tracing boolean tracing,
@Ipv6 boolean ipv6)
{
this.dockerFiles = requireNonNull(dockerFiles, "dockerFiles is null");
this.portBinder = requireNonNull(portBinder, "portBinder is null");
this.imagesVersion = environmentConfig.getImagesVersion();
this.jdkProvider = requireNonNull(jdkProvider, "jdkProvider is null");
this.serverPackage = requireNonNull(serverPackage, "serverPackage is null");
this.debug = debug;
this.ipv6 = ipv6;
this.tracing = tracing;
checkArgument(serverPackage.getName().endsWith(".tar.gz"), "Currently only server .tar.gz package is supported");
}
Expand Down Expand Up @@ -169,7 +173,7 @@ private DockerContainer createTracingCollector()
private DockerContainer createTrinoCoordinator()
{
DockerContainer container =
createTrinoContainer(dockerFiles, serverPackage, jdkProvider, debug, tracing, "ghcr.io/trinodb/testing/almalinux9-oj17:" + imagesVersion, COORDINATOR)
createTrinoContainer(dockerFiles, serverPackage, jdkProvider, debug, tracing, ipv6, "ghcr.io/trinodb/testing/almalinux9-oj17:" + imagesVersion, COORDINATOR)
.withCopyFileToContainer(forHostPath(dockerFiles.getDockerFilesHostPath("common/standard/access-control.properties")), CONTAINER_TRINO_ACCESS_CONTROL_PROPERTIES)
.withCopyFileToContainer(forHostPath(dockerFiles.getDockerFilesHostPath("common/standard/config.properties")), CONTAINER_TRINO_CONFIG_PROPERTIES);

Expand All @@ -188,7 +192,7 @@ private DockerContainer createTestsContainer()
}

@SuppressWarnings("resource")
public static DockerContainer createTrinoContainer(DockerFiles dockerFiles, File serverPackage, JdkProvider jdkProvider, boolean debug, boolean tracing, String dockerImageName, String logicalName)
public static DockerContainer createTrinoContainer(DockerFiles dockerFiles, File serverPackage, JdkProvider jdkProvider, boolean debug, boolean tracing, boolean ipv6, String dockerImageName, String logicalName)
{
DockerContainer container = new DockerContainer(dockerImageName, logicalName)
.withNetworkAliases(logicalName + ".docker.cluster")
Expand All @@ -215,6 +219,10 @@ public static DockerContainer createTrinoContainer(DockerFiles dockerFiles, File
enableTrinoTracing(container);
}

if (ipv6) {
enableTrinoIpv6(container);
}

return jdkProvider.applyTo(container);
}

Expand Down Expand Up @@ -289,6 +297,32 @@ private static void enableTrinoTracing(DockerContainer container)
}
}

private static void enableTrinoIpv6(DockerContainer container)
{
log.info("Setting IPv6 as preferred networking stack for container: '%s'", container.getLogicalName());

try {
FileAttribute<Set<PosixFilePermission>> rwx = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxrwxrwx"));
Path script = Files.createTempFile("enable-ipv6-stack", ".sh", rwx);
script.toFile().deleteOnExit();
Files.writeString(
script,
format(
"#!/bin/bash\n" +
"ipv6=$(hostname -I | awk '{print $2}')\n" +
"IPv6 address of the node: ${ipv6}\n" +
"echo '-Djava.net.preferIPv6Addresses=true' >> '%s'\n" +
"echo \"node.internal-address=${ipv6}\" >> '%s'\n",
CONTAINER_TRINO_JVM_CONFIG,
CONTAINER_TRINO_CONFIG_PROPERTIES),
UTF_8);
container.withCopyFileToContainer(forHostPath(script), "/docker/presto-init.d/enable-ipv6-stack.sh");
}
catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private static void enableTrinoJmxRmi(DockerContainer dockerContainer)
{
String logicalName = dockerContainer.getLogicalName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.trino.tests.product.launcher.env.DockerContainer;
import io.trino.tests.product.launcher.env.Environment;
import io.trino.tests.product.launcher.env.EnvironmentConfig;
import io.trino.tests.product.launcher.env.Ipv6;
import io.trino.tests.product.launcher.env.ServerPackage;
import io.trino.tests.product.launcher.env.Tracing;
import io.trino.tests.product.launcher.env.jdk.JdkProvider;
Expand All @@ -46,6 +47,7 @@ public class StandardMultinode
private final JdkProvider jdkProvider;
private final boolean debug;
private final boolean tracing;
private final boolean ipv6;

@Inject
public StandardMultinode(
Expand All @@ -55,7 +57,8 @@ public StandardMultinode(
@ServerPackage File serverPackage,
JdkProvider jdkProvider,
@Debug boolean debug,
@Tracing boolean tracing)
@Tracing boolean tracing,
@Ipv6 boolean ipv6)
{
this.standard = requireNonNull(standard, "standard is null");
this.dockerFiles = requireNonNull(dockerFiles, "dockerFiles is null");
Expand All @@ -65,6 +68,7 @@ public StandardMultinode(
this.serverPackage = requireNonNull(serverPackage, "serverPackage is null");
this.debug = debug;
this.tracing = tracing;
this.ipv6 = ipv6;
checkArgument(serverPackage.getName().endsWith(".tar.gz"), "Currently only server .tar.gz package is supported");
}

Expand All @@ -85,7 +89,7 @@ public void extendEnvironment(Environment.Builder builder)
@SuppressWarnings("resource")
private DockerContainer createTrinoWorker()
{
return createTrinoContainer(dockerFiles, serverPackage, jdkProvider, debug, tracing, "ghcr.io/trinodb/testing/almalinux9-oj17:" + imagesVersion, WORKER)
return createTrinoContainer(dockerFiles, serverPackage, jdkProvider, debug, tracing, ipv6, "ghcr.io/trinodb/testing/almalinux9-oj17:" + imagesVersion, WORKER)
.withCopyFileToContainer(forHostPath(configDir.getPath("multinode-worker-config.properties")), CONTAINER_TRINO_CONFIG_PROPERTIES);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.trino.tests.product.launcher.env.Environment;
import io.trino.tests.product.launcher.env.EnvironmentConfig;
import io.trino.tests.product.launcher.env.EnvironmentProvider;
import io.trino.tests.product.launcher.env.Ipv6;
import io.trino.tests.product.launcher.env.ServerPackage;
import io.trino.tests.product.launcher.env.Tracing;
import io.trino.tests.product.launcher.env.common.Hadoop;
Expand Down Expand Up @@ -53,6 +54,7 @@ public final class EnvMultinodeTls
private final File serverPackage;
private final boolean debug;
private final boolean tracing;
private final boolean ipv6;
private final JdkProvider jdkProvider;

@Inject
Expand All @@ -65,7 +67,8 @@ public EnvMultinodeTls(
@ServerPackage File serverPackage,
JdkProvider jdkProvider,
@Debug boolean debug,
@Tracing boolean tracing)
@Tracing boolean tracing,
@Ipv6 boolean ipv6)
{
super(ImmutableList.of(standard, hadoop));
this.dockerFiles = requireNonNull(dockerFiles, "dockerFiles is null");
Expand All @@ -75,6 +78,7 @@ public EnvMultinodeTls(
this.serverPackage = requireNonNull(serverPackage, "serverPackage is null");
this.debug = debug;
this.tracing = tracing;
this.ipv6 = ipv6;
}

@Override
Expand All @@ -97,7 +101,7 @@ public void extendEnvironment(Environment.Builder builder)

private DockerContainer createTrinoWorker(String workerName)
{
return createTrinoContainer(dockerFiles, serverPackage, jdkProvider, debug, tracing, "ghcr.io/trinodb/testing/almalinux9-oj17:" + imagesVersion, workerName)
return createTrinoContainer(dockerFiles, serverPackage, jdkProvider, debug, tracing, ipv6, "ghcr.io/trinodb/testing/almalinux9-oj17:" + imagesVersion, workerName)
.withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withDomainName("docker.cluster"))
.withCopyFileToContainer(forHostPath(dockerFiles.getDockerFilesHostPath("conf/environment/multinode-tls/config-worker.properties")), CONTAINER_TRINO_CONFIG_PROPERTIES)
.withCopyFileToContainer(forHostPath(dockerFiles.getDockerFilesHostPath("common/hadoop/hive.properties")), CONTAINER_TRINO_HIVE_PROPERTIES)
Expand Down
Loading

0 comments on commit 6fdcd0d

Please sign in to comment.