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 -->