This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new c26d612f912 [improve][build] Upgrade kubernetes client-java to 26.0.0
(#25856)
c26d612f912 is described below
commit c26d612f9128292db610d72fd6157ed848a5f2d1
Author: Lari Hotari <[email protected]>
AuthorDate: Fri May 22 23:40:17 2026 +0300
[improve][build] Upgrade kubernetes client-java to 26.0.0 (#25856)
---
distribution/server/src/assemble/LICENSE.bin.txt | 6 ++---
gradle/libs.versions.toml | 2 +-
pulsar-broker-auth-oidc/build.gradle.kts | 4 ++-
pulsar-functions/runtime/build.gradle.kts | 1 +
pulsar-functions/secrets/build.gradle.kts | 4 ++-
tests/integration/build.gradle.kts | 31 +++++++++++++++-------
.../k8s/AbstractPulsarStandaloneK8STest.java | 31 +++++++++++++++++++---
7 files changed, 61 insertions(+), 18 deletions(-)
diff --git a/distribution/server/src/assemble/LICENSE.bin.txt
b/distribution/server/src/assemble/LICENSE.bin.txt
index 5241a63ccf2..9342e35d2f4 100644
--- a/distribution/server/src/assemble/LICENSE.bin.txt
+++ b/distribution/server/src/assemble/LICENSE.bin.txt
@@ -484,9 +484,9 @@ The Apache Software License, Version 2.0
* Apache Yetus
- org.apache.yetus-audience-annotations-0.12.0.jar
* Kubernetes Client
- - io.kubernetes-client-java-23.0.0.jar
- - io.kubernetes-client-java-api-23.0.0.jar
- - io.kubernetes-client-java-proto-23.0.0.jar
+ - io.kubernetes-client-java-26.0.0.jar
+ - io.kubernetes-client-java-api-26.0.0.jar
+ - io.kubernetes-client-java-proto-26.0.0.jar
* Dropwizard
- io.dropwizard.metrics-metrics-core-4.1.12.1.jar
- io.dropwizard.metrics-metrics-graphite-4.1.12.1.jar
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index c8a099c4aad..46430c79444 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -161,7 +161,7 @@ skyscreamer = "1.5.0"
zstd-jni = "1.5.7-3"
lz4java = "1.10.3"
spring = "6.2.12"
-kubernetesclient = "23.0.0"
+kubernetesclient = "26.0.0"
aws-sdk = "1.12.788"
hadoop3 = "3.5.0"
jclouds = "2.6.0"
diff --git a/pulsar-broker-auth-oidc/build.gradle.kts
b/pulsar-broker-auth-oidc/build.gradle.kts
index 35769387a46..8001b53fed5 100644
--- a/pulsar-broker-auth-oidc/build.gradle.kts
+++ b/pulsar-broker-auth-oidc/build.gradle.kts
@@ -31,7 +31,9 @@ dependencies {
implementation(libs.asynchttpclient)
implementation(libs.jackson.databind)
implementation(libs.jackson.annotations)
- implementation(libs.kubernetes.client.java)
+ implementation(libs.kubernetes.client.java) {
+ exclude(group = "software.amazon.awssdk")
+ }
implementation(libs.okhttp3)
implementation(libs.commons.lang3)
implementation(libs.opentelemetry.api)
diff --git a/pulsar-functions/runtime/build.gradle.kts
b/pulsar-functions/runtime/build.gradle.kts
index e6edcdf3d38..34cb0d6c8e4 100644
--- a/pulsar-functions/runtime/build.gradle.kts
+++ b/pulsar-functions/runtime/build.gradle.kts
@@ -50,6 +50,7 @@ dependencies {
exclude(group = "org.bouncycastle", module = "bcutil-jdk18on")
exclude(group = "org.bouncycastle", module = "bcprov-jdk18on")
exclude(group = "javax.annotation", module = "javax.annotation-api")
+ exclude(group = "software.amazon.awssdk")
}
implementation(libs.simpleclient.hotspot)
implementation(libs.prometheus.jmx.collector)
diff --git a/pulsar-functions/secrets/build.gradle.kts
b/pulsar-functions/secrets/build.gradle.kts
index 2cc40772e09..91779589e50 100644
--- a/pulsar-functions/secrets/build.gradle.kts
+++ b/pulsar-functions/secrets/build.gradle.kts
@@ -23,7 +23,9 @@ plugins {
dependencies {
implementation(project(":pulsar-functions:pulsar-functions-proto"))
- implementation(libs.kubernetes.client.java)
+ implementation(libs.kubernetes.client.java) {
+ exclude(group = "software.amazon.awssdk")
+ }
implementation(libs.gson)
implementation(libs.commons.lang3)
}
diff --git a/tests/integration/build.gradle.kts
b/tests/integration/build.gradle.kts
index 35bcab80b4b..3749d278564 100644
--- a/tests/integration/build.gradle.kts
+++ b/tests/integration/build.gradle.kts
@@ -51,15 +51,18 @@ dependencies {
testImplementation(libs.restassured)
testImplementation(libs.testcontainers.k3s)
testImplementation(libs.jetty.websocket.jetty.client)
+ testImplementation(libs.joda.time)
testImplementation(libs.kubernetes.client.java) {
exclude(group = "io.prometheus", module = "simpleclient_httpserver")
exclude(group = "org.bouncycastle")
exclude(group = "javax.annotation", module = "javax.annotation-api")
+ exclude(group = "software.amazon.awssdk")
}
testImplementation(libs.kubernetes.client.java.api.fluent) {
exclude(group = "io.prometheus", module = "simpleclient_httpserver")
exclude(group = "org.bouncycastle")
exclude(group = "javax.annotation", module = "javax.annotation-api")
+ exclude(group = "software.amazon.awssdk")
}
}
@@ -79,26 +82,36 @@ tasks.test {
}
// Register a task for each integration test suite
-val integrationTestSuiteFile =
providers.gradleProperty("integrationTestSuiteFile").getOrElse("pulsar.xml")
+val integrationTestSuiteFileProperty =
providers.gradleProperty("integrationTestSuiteFile")
+val integrationTestSuiteFile =
integrationTestSuiteFileProperty.getOrElse("pulsar.xml")
+val integrationTestSuiteFileExplicit =
integrationTestSuiteFileProperty.isPresent
val integrationTestGroups = providers.gradleProperty("testGroups").orNull
val integrationTestExcludedGroups =
providers.gradleProperty("excludedTestGroups").orNull
+val ideaActive = providers.systemProperty("idea.active").map { it.toBoolean()
}.getOrElse(false)
+// When `--tests` is passed on the CLI, let TestNG discover tests directly
from the classpath
+// instead of restricting discovery to the suite XML — unless
-PintegrationTestSuiteFile was
+// set explicitly, in which case the user-selected suite still wins.
+val hasCliTestsFilter = gradle.startParameter.taskRequests
+ .flatMap { it.args }
+ .any { it == "--tests" }
val integrationTest by tasks.registering(Test::class) {
testClassesDirs = sourceSets.test.get().output.classesDirs
classpath = sourceSets.test.get().runtimeClasspath
- useTestNG {
- suites("src/test/resources/${integrationTestSuiteFile}")
- if (!integrationTestGroups.isNullOrEmpty()) {
- includeGroups(integrationTestGroups)
- }
- if (!integrationTestExcludedGroups.isNullOrEmpty()) {
- excludeGroups(integrationTestExcludedGroups)
+ if (!ideaActive && (!hasCliTestsFilter ||
integrationTestSuiteFileExplicit)) {
+ useTestNG {
+ suites("src/test/resources/${integrationTestSuiteFile}")
+ if (!integrationTestGroups.isNullOrEmpty()) {
+ includeGroups(integrationTestGroups)
+ }
+ if (!integrationTestExcludedGroups.isNullOrEmpty()) {
+ excludeGroups(integrationTestExcludedGroups)
+ }
}
}
val failFastValue =
providers.gradleProperty("testFailFast").getOrElse("true").toBoolean()
failFast = failFastValue
- val ideaActive = providers.systemProperty("idea.active").map {
it.toBoolean() }.getOrElse(false)
val defaultTestRetryCount = if (ideaActive) "0" else "1"
systemProperty("testRetryCount",
providers.gradleProperty("testRetryCount").getOrElse(defaultTestRetryCount))
systemProperty("testFailFast", failFastValue.toString())
diff --git
a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/k8s/AbstractPulsarStandaloneK8STest.java
b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/k8s/AbstractPulsarStandaloneK8STest.java
index 3aa3f06c8f4..149a7f1a26e 100644
---
a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/k8s/AbstractPulsarStandaloneK8STest.java
+++
b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/k8s/AbstractPulsarStandaloneK8STest.java
@@ -53,10 +53,12 @@ import java.nio.file.Files;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.UUID;
import lombok.CustomLog;
import lombok.Getter;
import org.apache.pulsar.functions.runtime.kubernetes.KubernetesRuntimeFactory;
import
org.apache.pulsar.functions.secretsproviderconfigurator.KubernetesSecretsProviderConfigurator;
+import org.apache.pulsar.tests.integration.containers.PulsarContainer;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarInputStream;
import org.testcontainers.containers.wait.strategy.Wait;
@@ -73,6 +75,17 @@ import org.testng.annotations.BeforeClass;
* with the deployed Pulsar instance and Kubernetes cluster.
* The main reason to use this base class is to test features in Pulsar which
are integrated into Kubernetes
* APIs.
+ *
+ * For debugging purposes, it is useful to have the ability to leave
containers running.
+ * This mode can be activated by setting environment variables
+ * PULSAR_CONTAINERS_LEAVE_RUNNING=true and TESTCONTAINERS_REUSE_ENABLE=true
+ * For example:
+ * PULSAR_CONTAINERS_LEAVE_RUNNING=true TESTCONTAINERS_REUSE_ENABLE=true
./gradlew \
+ * :tests:integration:integrationTest --rerun --tests PulsarFunctionsK8STest
--no-daemon
+ * Check the logs for KUBECONFIG file location to connect to the k3d cluster
for debugging. For example:
+ * KUBECONFIG=/tmp/kubeconfig10863493890794345578.yaml k9s
+ * After debugging, one can use this command to kill all containers that were
left running:
+ * docker kill $(docker ps -q --filter "label=pulsarcontainer=true")
*/
@CustomLog
public abstract class AbstractPulsarStandaloneK8STest {
@@ -80,7 +93,7 @@ public abstract class AbstractPulsarStandaloneK8STest {
"apachepulsar/java-test-image:latest");
private static final int PULSAR_NODE_PORT = 30101;
private static final int PULSAR_HTTP_NODE_PORT = 30102;
- private static final String K3S_IMAGE_NAME = "rancher/k3s:v1.33.5-k3s1";
+ private static final String K3S_IMAGE_NAME = "rancher/k3s:v1.34.8-k3s1";
private static final String PULSAR_STANDALONE_POD =
"pulsar-standalone-pod";
K3sContainer k3sContainer;
KubeConfig kubeConfig;
@@ -100,6 +113,14 @@ public abstract class AbstractPulsarStandaloneK8STest {
k3sContainer = new K3sContainer(DockerImageName.parse(K3S_IMAGE_NAME));
k3sContainer.addExposedPort(PULSAR_NODE_PORT);
k3sContainer.addExposedPort(PULSAR_HTTP_NODE_PORT);
+ if (PulsarContainer.PULSAR_CONTAINERS_LEAVE_RUNNING) {
+ // use Testcontainers reuse containers feature to leave the
container running
+ k3sContainer.withReuse(true);
+ // add label that can be used to find containers that are left
running.
+ k3sContainer.withLabel("pulsarcontainer", "true");
+ // add a random label to prevent reuse of containers
+ k3sContainer.withLabel("pulsarcontainer.random",
UUID.randomUUID().toString());
+ }
k3sContainer.start();
dockerHostName = k3sContainer.getHost();
pulsarBrokerUrl = "pulsar://" + dockerHostName + ":" +
k3sContainer.getMappedPort(PULSAR_NODE_PORT);
@@ -110,8 +131,8 @@ public abstract class AbstractPulsarStandaloneK8STest {
apiClient = Config.fromConfig(kubeConfig);
kubeConfigFile = File.createTempFile("kubeconfig", ".yaml");
Files.writeString(kubeConfigFile.toPath(), kubeConfigYaml);
- log.info().attr("uRL", pulsarBrokerUrl).attr("uRL",
pulsarWebServiceUrl).log("Pulsar broker URL: http URL");
- log.info().attr("kUBECONFIG",
kubeConfigFile.getAbsolutePath()).log("For debugging k8s, use KUBECONFIG");
+ log.info().attr("URL", pulsarBrokerUrl).attr("URL",
pulsarWebServiceUrl).log("Pulsar broker URL: http URL");
+ log.info().attr("KUBECONFIG",
kubeConfigFile.getAbsolutePath()).log("For debugging k8s, use KUBECONFIG");
importPulsarImage();
deployPulsarStandalonePod();
log.info("Waiting for Pulsar cluster to be ready");
@@ -129,6 +150,10 @@ public abstract class AbstractPulsarStandaloneK8STest {
public final void cleanupCluster() throws InterruptedException {
if (k3sContainer != null) {
copyLogsToTargetDirectory();
+ if (PulsarContainer.PULSAR_CONTAINERS_LEAVE_RUNNING) {
+ log.warn("Ignoring stop due to
PULSAR_CONTAINERS_LEAVE_RUNNING=true.");
+ return;
+ }
k3sContainer.stop();
kubeConfigFile.delete();
}