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();
         }

Reply via email to