This is an automated email from the ASF dual-hosted git repository. zhfeng pushed a commit to branch 3.8.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/3.8.x by this push: new 9f56ec94b8 [3.8.x] Reinstate Kudu tablet server host resolution workaround (#5943) 9f56ec94b8 is described below commit 9f56ec94b89d6feeea39f6af3a82f4b4dbd51922 Author: James Netherton <jamesnether...@users.noreply.github.com> AuthorDate: Tue Apr 2 23:46:08 2024 +0100 [3.8.x] Reinstate Kudu tablet server host resolution workaround (#5943) * Reinstate Kudu tablet server host resolution workaround Relates #1206 * Fix Splunk container image to 9.2.0 tag --- integration-tests/kudu/pom.xml | 7 ++ .../kudu/it/KuduInfrastructureTestHelper.java | 98 ++++++++++++++++++++++ .../component/kudu/it/KuduTestResource.java | 25 ++---- pom.xml | 2 +- 4 files changed, 113 insertions(+), 19 deletions(-) diff --git a/integration-tests/kudu/pom.xml b/integration-tests/kudu/pom.xml index 53f282822f..48ae491a2e 100644 --- a/integration-tests/kudu/pom.xml +++ b/integration-tests/kudu/pom.xml @@ -30,6 +30,13 @@ <name>Camel Quarkus :: Integration Tests :: Kudu</name> <description>Integration tests for Camel Quarkus Kudu extension</description> + <properties> + <!-- This is to allow the "deep reflection" we do in KuduInfrastructureTestHelper --> + <opens>java.base/java.net=ALL-UNNAMED</opens> + <argLine>--add-opens ${opens}</argLine> + <quarkus.native.additional-build-args>-J--add-opens=${opens}</quarkus.native.additional-build-args> + </properties> + <dependencies> <dependency> <groupId>io.quarkus</groupId> diff --git a/integration-tests/kudu/src/main/java/org/apache/camel/quarkus/component/kudu/it/KuduInfrastructureTestHelper.java b/integration-tests/kudu/src/main/java/org/apache/camel/quarkus/component/kudu/it/KuduInfrastructureTestHelper.java new file mode 100644 index 0000000000..fcf34ecb1c --- /dev/null +++ b/integration-tests/kudu/src/main/java/org/apache/camel/quarkus/component/kudu/it/KuduInfrastructureTestHelper.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.kudu.it; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.util.concurrent.ConcurrentHashMap; + +import io.quarkus.runtime.StartupEvent; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; +import org.eclipse.microprofile.config.ConfigProvider; +import org.jboss.logging.Logger; + +/** + * In order to run Kudu integration tests, {@code KuduTest} and {@code KuduIT} should have access to: + * 1) A Kudu master server needed to create a table and also to obtain the host/port of the associated tablet server + * 2) A Kudu tablet server needed to insert and scan records + * + * As such, one solution could be to use a custom setup where Kudu servers run on the same network than integration + * tests. Please note that Kudu servers are not able to run on Windows machine. + * Another solution could be to use the container based setup where Kudu servers are managed by + * {@code KuduTestResource}. + * + * A) How to run integration tests against a custom setup (advised when not running on top of OpenJDK): + * Install Kudu master and tablet servers on the same network than integration tests. + * Configure "camel.kudu.test.master.rpc-authority" in "application.properties", for instance: + * camel.kudu.test.master.rpc-authority=kudu-master-hostname:7051 + * Run integration tests with mvn clean integration-test -P native + * + * B) How to run integration tests against the container based setup: + * The container based setup should run out of the box as {@code KuduTestResource} runs master and tablet server + * containers in a shared network. + * Simply run integration tests with mvn clean integration-test -P native + * Note that the test harness is NOT guaranteed to work when NOT running on top of OpenJDK. + * + * Troubleshooting the container based setup: + * If a message like "Unknown host kudu-tserver" is issued, it may be that + * {@link KuduInfrastructureTestHelper#overrideTabletServerHostnameResolution()} + * is not working. Please try to manually override the tablet server hostname resolution on your Operating System. + * For instance, adding an entry in /etc/hosts file like: "127.0.0.1 kudu-tserver" + * + * If a message like "Not enough live tablet server" is issued, it may be that the shared network setup by + * {@code KuduTestResource} is not working. In this case please refer to links below for a possible workaround: + * <a href="https://github.com/apache/camel-quarkus/issues/1206"> + * <a href="https://github.com/moby/moby/issues/32138"> + */ +@ApplicationScoped +public class KuduInfrastructureTestHelper { + + static final String KUDU_TABLET_NETWORK_ALIAS = "kudu-tserver"; + static final String DOCKER_HOST = "docker.host"; + private static final Logger LOG = Logger.getLogger(KuduInfrastructureTestHelper.class); + + void onStart(@Observes StartupEvent ev) { + LOG.info("Attempting to override the kudu tablet server hostname resolution on application startup"); + KuduInfrastructureTestHelper.overrideTabletServerHostnameResolution(); + } + + public static void overrideTabletServerHostnameResolution() { + try { + // Warm up the InetAddress cache + String dockerHost = ConfigProvider.getConfig().getValue("docker.host", String.class); + String tabletServerHostName = dockerHost.equals("localhost") || dockerHost.equals("127.0.0.1") ? "localhost" + : KUDU_TABLET_NETWORK_ALIAS; + InetAddress.getByName(tabletServerHostName); + final Field cacheField = InetAddress.class.getDeclaredField("cache"); + cacheField.setAccessible(true); + final Object cache = cacheField.get(null); + final Method get = ConcurrentHashMap.class.getMethod("get", Object.class); + final Object cachedAddresses = get.invoke(cache, tabletServerHostName); + if (cachedAddresses == null) { + throw new IllegalStateException("Unable to resolve host %s. Please add a host entry for %s %s" + .formatted(tabletServerHostName, dockerHost, tabletServerHostName)); + } + + final Method put = ConcurrentHashMap.class.getMethod("put", Object.class, Object.class); + put.invoke(cache, KUDU_TABLET_NETWORK_ALIAS, cachedAddresses); + } catch (Exception e) { + throw new IllegalStateException("Failed to apply kudu tablet server hostname override", e); + } + } +} diff --git a/integration-tests/kudu/src/test/java/org/apache/camel/quarkus/component/kudu/it/KuduTestResource.java b/integration-tests/kudu/src/test/java/org/apache/camel/quarkus/component/kudu/it/KuduTestResource.java index 6abba1d8fb..036c8ee886 100644 --- a/integration-tests/kudu/src/test/java/org/apache/camel/quarkus/component/kudu/it/KuduTestResource.java +++ b/integration-tests/kudu/src/test/java/org/apache/camel/quarkus/component/kudu/it/KuduTestResource.java @@ -36,6 +36,8 @@ import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.TestcontainersConfiguration; +import static org.apache.camel.quarkus.component.kudu.it.KuduInfrastructureTestHelper.DOCKER_HOST; +import static org.apache.camel.quarkus.component.kudu.it.KuduInfrastructureTestHelper.KUDU_TABLET_NETWORK_ALIAS; import static org.apache.camel.quarkus.component.kudu.it.KuduRoute.KUDU_AUTHORITY_CONFIG_KEY; public class KuduTestResource implements QuarkusTestResourceLifecycleManager { @@ -46,7 +48,6 @@ public class KuduTestResource implements QuarkusTestResourceLifecycleManager { private static final int KUDU_TABLET_HTTP_PORT = 8050; private static final String KUDU_IMAGE = ConfigProvider.getConfig().getValue("kudu.container.image", String.class); private static final String KUDU_MASTER_NETWORK_ALIAS = "kudu-master"; - private static final String KUDU_TABLET_NETWORK_ALIAS = "kudu-tserver"; private GenericContainer<?> masterContainer; private GenericContainer<?> tabletContainer; @@ -58,14 +59,12 @@ public class KuduTestResource implements QuarkusTestResourceLifecycleManager { Network kuduNetwork = Network.newNetwork(); // Setup the Kudu master server container - String masterAdvertisedAddress = getRpcAdvertisedAddress(KUDU_MASTER_NETWORK_ALIAS, KUDU_MASTER_RPC_PORT); masterContainer = new GenericContainer<>(KUDU_IMAGE) .withCommand("master") + .withEnv("MASTER_ARGS", "--unlock_unsafe_flags=true") .withExposedPorts(KUDU_MASTER_RPC_PORT, KUDU_MASTER_HTTP_PORT) .withNetwork(kuduNetwork) .withNetworkAliases(KUDU_MASTER_NETWORK_ALIAS) - .withEnv("MASTER_ARGS", - "--unlock_unsafe_flags=true --rpc_advertised_addresses=" + masterAdvertisedAddress) .withLogConsumer(new Slf4jLogConsumer(LOG)) .waitingFor(Wait.forListeningPort()); masterContainer.start(); @@ -82,16 +81,14 @@ public class KuduTestResource implements QuarkusTestResourceLifecycleManager { }; // Setup the Kudu tablet server container - String tabletAdvertisedAddress = getRpcAdvertisedAddress(KUDU_TABLET_NETWORK_ALIAS, KUDU_TABLET_RPC_PORT); tabletContainer = new GenericContainer<>(KUDU_IMAGE) .withCommand("tserver") + .withEnv("TSERVER_ARGS", "--unlock_unsafe_flags=true") .withEnv("KUDU_MASTERS", KUDU_MASTER_NETWORK_ALIAS) .withExposedPorts(KUDU_TABLET_RPC_PORT, KUDU_TABLET_HTTP_PORT) .withNetwork(kuduNetwork) .withNetworkAliases(KUDU_TABLET_NETWORK_ALIAS) .withCreateContainerCmdModifier(consumer) - .withEnv("TSERVER_ARGS", - "--unlock_unsafe_flags=true --rpc_advertised_addresses=" + tabletAdvertisedAddress) .withLogConsumer(new Slf4jLogConsumer(LOG)) .waitingFor(Wait.forListeningPort()); tabletContainer.start(); @@ -111,7 +108,9 @@ public class KuduTestResource implements QuarkusTestResourceLifecycleManager { + tabletContainer.getMappedPort(KUDU_TABLET_HTTP_PORT); LOG.info("Kudu tablet server HTTP accessible at " + tServerHttpAuthority); - return CollectionHelper.mapOf(KUDU_AUTHORITY_CONFIG_KEY, masterRpcAuthority); + return CollectionHelper.mapOf( + KUDU_AUTHORITY_CONFIG_KEY, masterRpcAuthority, + DOCKER_HOST, DockerClientFactory.instance().dockerHostIpAddress()); } @Override @@ -127,14 +126,4 @@ public class KuduTestResource implements QuarkusTestResourceLifecycleManager { LOG.error("An issue occurred while stopping the KuduTestResource", ex); } } - - String getRpcAdvertisedAddress(String host, int port) { - String addressFormat = "%s:%d"; - String dockerHost = DockerClientFactory.instance().dockerHostIpAddress(); - if (dockerHost.equals("localhost") || dockerHost.equals("127.0.0.1")) { - return addressFormat.formatted(host, port); - } else { - return addressFormat.formatted(dockerHost, port); - } - } } diff --git a/pom.xml b/pom.xml index b9c739c7f0..89d89f4ec6 100644 --- a/pom.xml +++ b/pom.xml @@ -246,7 +246,7 @@ <rabbitmq.container.image>docker.io/rabbitmq:3.9.29-management-alpine</rabbitmq.container.image> <redis.container.image>docker.io/redis:7.0.12</redis.container.image> <smb.container.image>quay.io/jamesnetherton/camel-smb-test-server:1.0.0</smb.container.image> - <splunk.container.image>docker.io/splunk/splunk:9.0</splunk.container.image> + <splunk.container.image>docker.io/splunk/splunk:9.2.0</splunk.container.image> <sql-server.container.image>mcr.microsoft.com/mssql/server:2017-CU12</sql-server.container.image> <!-- Plugin configuration through properties -->