This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new f54a2007cbcb CAMEL-25031: Upgrade fabric8 kubernetes-client to 8.0.0 
(#27863)
f54a2007cbcb is described below

commit f54a2007cbcbc96c5818f7610e571cc257af355c
Author: James Netherton <[email protected]>
AuthorDate: Thu Oct 15 11:05:23 2026 +0100

    CAMEL-25031: Upgrade fabric8 kubernetes-client to 8.0.0 (#27863)
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../kubernetes/cluster/utils/LockTestServer.java   |  9 +++----
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    | 24 +++++++++++++++++
 .../camel-jbang-plugin-kubernetes/pom.xml          | 18 ++++++++++++-
 .../core/commands/kubernetes/KubernetesHelper.java | 30 ++++++++++++----------
 .../core/commands/kubernetes/KubernetesRun.java    | 25 +++++++++++++-----
 .../kubernetes/traits/knative/KnativeTrait.java    |  4 +--
 parent/pom.xml                                     |  2 +-
 7 files changed, 81 insertions(+), 31 deletions(-)

diff --git 
a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cluster/utils/LockTestServer.java
 
b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cluster/utils/LockTestServer.java
index 6a8e6549bd09..d6ece2286a27 100644
--- 
a/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cluster/utils/LockTestServer.java
+++ 
b/components/camel-kubernetes/src/test/java/org/apache/camel/component/kubernetes/cluster/utils/LockTestServer.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.component.kubernetes.cluster.utils;
 
-import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -26,8 +25,6 @@ import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import io.fabric8.kubernetes.api.model.HasMetadata;
 import io.fabric8.kubernetes.api.model.PodBuilder;
 import io.fabric8.kubernetes.api.model.PodListBuilder;
@@ -36,6 +33,7 @@ import io.fabric8.kubernetes.api.model.PodStatusBuilder;
 import io.fabric8.kubernetes.client.NamespacedKubernetesClient;
 import io.fabric8.kubernetes.client.RequestConfig;
 import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
+import io.fabric8.kubernetes.client.utils.Serialization;
 import io.fabric8.mockwebserver.http.Headers;
 import io.fabric8.mockwebserver.http.RecordedRequest;
 import io.fabric8.mockwebserver.utils.ResponseProvider;
@@ -338,9 +336,8 @@ public class LockTestServer<T extends HasMetadata> extends 
KubernetesMockServer
         }
     }
 
-    private T convert(RecordedRequest request, Class<T> targetClass) throws 
IOException {
-        ObjectMapper mapper = new ObjectMapper().registerModule(new 
JavaTimeModule());
-        return mapper.readValue(request.getBody().readByteArray(), 
targetClass);
+    private T convert(RecordedRequest request, Class<T> targetClass) {
+        return Serialization.unmarshal(request.getBody().readUtf8(), 
targetClass);
     }
 
 }
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 50374dc80224..f987550b9f00 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -88,6 +88,30 @@ artifacts, so either the ArangoDB driver or the other 
components fail at runtime
 driver maintainers is to replace `com.arangodb:arangodb-java-driver` with 
`com.arangodb:arangodb-java-driver-shaded`,
 which embeds its own relocated copy of Vert.x. The `vertx` option of 
`camel-arangodb` cannot be used in that case.
 
+=== camel-kubernetes - Kubernetes client 8
+
+`camel-kubernetes` now uses the fabric8 Kubernetes client 8.0, which brings 
these changes for applications:
+
+* The client uses its Vert.x 5 HTTP client 
(`io.fabric8:kubernetes-httpclient-vertx-5`) instead of the Vert.x 4 one
+  (`io.fabric8:kubernetes-httpclient-vertx`). An application that excludes the 
default HTTP client, for example
+  to use OkHttp or the JDK HTTP client, must now exclude 
`kubernetes-httpclient-vertx-5`.
+* The client and its model use Jackson 3 (`tools.jackson`). Jackson 2 does not 
apply the serializers of the
+  model, so Kubernetes model objects serialized with Jackson 2 come out in a 
different shape. For example, a
+  `targetPort` of `8080` is written as `{"value":8080,"intVal":8080}`, and a 
CPU limit of `500m` as
+  `{"amount":"500","format":"m"}`. This affects routes that marshal the result 
of a `camel-kubernetes` producer
+  with the `camel-jackson` data format (`marshal().json()`), and application 
code that uses its own Jackson 2
+  `ObjectMapper`. Replace the `camel-jackson` dependency with 
`camel-jackson3`, which provides the same `jackson`
+  data format on Jackson 3 (see 
xref:components:dataformats:jackson3-dataformat.adoc[JSON Jackson 3]), so the 
route does not
+  change. In Java code, use Jackson 3 or 
`io.fabric8.kubernetes.client.utils.Serialization`.
+* Jackson 3 uses the Jackson 2 
`com.fasterxml.jackson.core:jackson-annotations` artifact, and needs version 
2.21
+  or later. An application that pins Jackson 2 to 2.20 or older, for example 
through an older Spring Boot BOM,
+  fails on the first use of the client with
+  `NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonSerializeAs`. 
Use `jackson-annotations` 2.21 or
+  later; Camel uses 2.22.
+
+See the 
https://github.com/fabric8io/kubernetes-client/blob/main/doc/MIGRATION-v8.md[Kubernetes
 client 8 migration guide]
+for the other changes.
+
 === camel-jbang - camel validate and camel overview report the same endpoints 
no route consumes
 
 `camel validate source` and `camel overview` now use the same rules for a 
`direct:`, `seda:` or `disruptor:` endpoint
diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml
index 6481988cfd85..21b11ca560b9 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/pom.xml
@@ -41,6 +41,18 @@
         <camel.surefire.parallel>false</camel.surefire.parallel>
     </properties>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>tools.jackson</groupId>
+                <artifactId>jackson-bom</artifactId>
+                <version>${jackson3-version}</version>
+                <scope>import</scope>
+                <type>pom</type>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
     <dependencies>
         <dependency>
           <groupId>org.apache.camel</groupId>
@@ -105,9 +117,13 @@
         </dependency>
         <dependency>
             <groupId>io.fabric8</groupId>
-            <artifactId>kubernetes-httpclient-vertx</artifactId>
+            <artifactId>kubernetes-httpclient-vertx-5</artifactId>
             <version>${kubernetes-client-version}</version>
         </dependency>
+        <dependency>
+            <groupId>tools.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
 
         <!-- OpenShift -->
         <dependency>
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
index c5f68c743634..7db50b25e585 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesHelper.java
@@ -28,12 +28,6 @@ import java.util.Map;
 import java.util.Optional;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.databind.json.JsonMapper;
 import io.fabric8.kubernetes.api.model.APIGroup;
 import io.fabric8.kubernetes.api.model.ConfigMap;
 import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
@@ -46,6 +40,12 @@ import org.apache.camel.dsl.jbang.core.common.YamlHelper;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.StringHelper;
 import org.yaml.snakeyaml.Yaml;
+import tools.jackson.core.StreamReadFeature;
+import tools.jackson.databind.DeserializationFeature;
+import tools.jackson.databind.MapperFeature;
+import tools.jackson.databind.ObjectMapper;
+import tools.jackson.databind.cfg.EnumFeature;
+import tools.jackson.databind.json.JsonMapper;
 
 /**
  * Helper class provides access to cached Kubernetes client. Also provides 
access to generic Json and Yaml mappers.
@@ -60,17 +60,19 @@ public final class KubernetesHelper {
     private static final ObjectMapper OBJECT_MAPPER;
 
     static {
-        OBJECT_MAPPER = JsonMapper.builder()
+        // Jackson 3 to match the Kubernetes client, so that the model's own 
serializers (IntOrString, Quantity, etc.) are used.
+        // MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES no longer exists 
in Jackson 3, and this mapper does not use
+        // polymorphic typing (no default typing, no @JsonTypeInfo on the 
trait model).
+        OBJECT_MAPPER = JsonMapper.builderWithJackson2Defaults()
                 .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
-                .enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
+                .enable(EnumFeature.READ_ENUMS_USING_TO_STRING)
                 .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
-                .enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
-                .disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
-                .enable(MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES)
+                .enable(EnumFeature.WRITE_ENUMS_USING_TO_STRING)
+                .disable(StreamReadFeature.AUTO_CLOSE_SOURCE)
                 .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
-                .build()
-                .setDefaultPropertyInclusion(
-                        
JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, 
JsonInclude.Include.NON_EMPTY));
+                .changeDefaultPropertyInclusion(
+                        incl -> 
JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, 
JsonInclude.Include.NON_EMPTY))
+                .build();
     }
 
     private KubernetesHelper() {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
index 91ff84200ee2..64785c15f45b 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRun.java
@@ -36,7 +36,7 @@ import java.util.concurrent.TimeUnit;
 import io.fabric8.kubernetes.api.model.Pod;
 import io.fabric8.kubernetes.client.KubernetesClient;
 import io.fabric8.kubernetes.client.KubernetesClientBuilder;
-import io.fabric8.kubernetes.client.vertx.VertxHttpClientFactory;
+import io.fabric8.kubernetes.client.vertx5.Vertx5HttpClientFactory;
 import io.vertx.core.Vertx;
 import io.vertx.core.VertxOptions;
 import io.vertx.core.file.FileSystemOptions;
@@ -637,12 +637,21 @@ public class KubernetesRun extends KubernetesBaseCommand {
             KubernetesDelete deleteCommand = new KubernetesDelete(getMain());
             deleteCommand.name = projectName;
             deleteCommand.namespace = namespace;
-            try (var client = createKubernetesClientForShutdownHook()) {
+            // the client does not close a Vertx instance that is passed to it
+            var vertx = createVertxForShutdownHook();
+            try (var client = createKubernetesClientForShutdownHook(vertx)) {
                 KubernetesHelper.setKubernetesClient(client);
                 deleteCommand.doCall();
                 CommandHelper.cleanExportDir(workingDir, false);
             } catch (Exception e) {
                 throw new RuntimeException(e);
+            } finally {
+                // close() returns before Vert.x is closed, and its daemon 
threads would not keep the JVM running
+                try {
+                    vertx.close().await(5, TimeUnit.SECONDS);
+                } catch (Exception e) {
+                    printer().printErr("Failed to close Vert.x - 
%s".formatted(e.getMessage()));
+                }
             }
         });
         devModeShutdownTask.setName(ThreadHelper.resolveThreadName(null, 
"CamelShutdownInterceptor"));
@@ -651,17 +660,19 @@ public class KubernetesRun extends KubernetesBaseCommand {
 
     // KubernetesClientVertx can no longer be used in ShutdownHook
     // https://issues.apache.org/jira/browse/CAMEL-21621
-    private KubernetesClient createKubernetesClientForShutdownHook() {
+    private Vertx createVertxForShutdownHook() {
         System.setProperty("vertx.disableDnsResolver", "true");
-        var vertx = Vertx.vertx((new VertxOptions())
+        return Vertx.vertx((new VertxOptions())
                 .setFileSystemOptions((new FileSystemOptions())
                         .setFileCachingEnabled(false)
                         .setClassPathResolvingEnabled(false))
                 .setUseDaemonThread(true));
-        var client = new KubernetesClientBuilder()
-                .withHttpClientFactory(new VertxHttpClientFactory(vertx))
+    }
+
+    private KubernetesClient createKubernetesClientForShutdownHook(Vertx 
vertx) {
+        return new KubernetesClientBuilder()
+                .withHttpClientFactory(new Vertx5HttpClientFactory(vertx))
                 .build();
-        return client;
     }
 
     // build the project locally to generate the artifacts in the target 
directory, but don't deploy it.
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/knative/KnativeTrait.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/knative/KnativeTrait.java
index 187423f4c33b..f6504018ffbd 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/knative/KnativeTrait.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/traits/knative/KnativeTrait.java
@@ -29,7 +29,6 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
 import io.fabric8.knative.duck.v1.DestinationBuilder;
 import io.fabric8.knative.duck.v1.KReference;
 import io.fabric8.knative.duck.v1.KReferenceBuilder;
@@ -48,6 +47,7 @@ import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Knative;
 import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Traits;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.URISupport;
+import tools.jackson.core.JacksonException;
 
 public class KnativeTrait extends KnativeBaseTrait {
 
@@ -140,7 +140,7 @@ public class KnativeTrait extends KnativeBaseTrait {
                 }
                 
camelTrait.getProperties().add("camel.component.knative.environmentPath=classpath:knative.json");
                 traitConfig.setCamel(camelTrait);
-            } catch (JsonProcessingException e) {
+            } catch (JacksonException e) {
                 context.printer().printf("Failed to write knative.json 
environment configuration - %s%n", e.getMessage());
             }
         }
diff --git a/parent/pom.xml b/parent/pom.xml
index d7374f9a29f1..50ad9acbef27 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -349,7 +349,7 @@
         <kafka-version>4.3.1</kafka-version>
         <keycloak-client-version>26.0.12</keycloak-client-version>
         <keycloak-version>26.8.0</keycloak-version>
-        <kubernetes-client-version>7.9.0</kubernetes-client-version>
+        <kubernetes-client-version>8.0.0</kubernetes-client-version>
         <kudu-version>1.18.1</kudu-version>
         <langchain4j-version>1.22.0</langchain4j-version>
         <!-- remove this one when all langchain4j artifacts are made final -->

Reply via email to