Skip to content

Commit f4cc9f7

Browse files
author
Mauro de Palma
committed
feat!: upgrade Fabric8 to 8.0.0 and support Jackson 3
Migrate resource matchers and YAML configuration to Jackson 3, update HTTP client selection and CI to Vert.x 5, and add regression tests and migration guidance.
1 parent b0ef77f commit f4cc9f7

20 files changed

Lines changed: 312 additions & 47 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
httpclient-tests:
2424
strategy:
2525
matrix:
26-
httpclient: [ 'vertx', 'jdk', 'jetty' ]
26+
httpclient: [ 'vertx-5', 'jdk', 'jetty' ]
2727
uses: ./.github/workflows/integration-tests.yml
2828
with:
2929
java-version: 25

‎.github/workflows/integration-tests.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
http-client:
1313
type: string
1414
required: false
15-
default: 'vertx'
15+
default: 'vertx-5'
1616
experimental:
1717
type: boolean
1818
required: false

‎docs/content/en/docs/documentation/features.md‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,35 @@ public class DeploymentReconciler
2727

2828
**Note:** This feature is provided by the [Fabric8 Kubernetes Client](https://github.com/fabric8io/kubernetes-client), not JOSDK itself.
2929

30-
To automatically generate CRD manifests from your annotated Custom Resource classes, add this dependency to your project:
30+
To automatically generate CRD manifests from your annotated Custom Resource classes, configure the
31+
Fabric8 CRD generator Maven plugin. Use the same Fabric8 version as the SDK:
3132

3233
```xml
33-
34-
<dependency>
34+
<plugin>
3535
<groupId>io.fabric8</groupId>
36-
<artifactId>crd-generator-apt</artifactId>
37-
<scope>provided</scope>
38-
</dependency>
36+
<artifactId>crd-generator-maven-plugin</artifactId>
37+
<version>${fabric8-client.version}</version>
38+
<executions>
39+
<execution>
40+
<goals>
41+
<goal>generate</goal>
42+
</goals>
43+
</execution>
44+
</executions>
45+
</plugin>
3946
```
4047

41-
The CRD will be generated in `target/classes/META-INF/fabric8` (or `target/test-classes/META-INF/fabric8` for test scope) with the CRD name suffixed by the generated spec version.
48+
Add the plugin under `build/plugins` and set `fabric8-client.version` to `8.0.0`.
49+
The old `crd-generator-apt` annotation processor was removed in Fabric8 8.
50+
51+
The CRD will be generated in `target/classes/META-INF/fabric8` with the CRD name suffixed by the
52+
generated spec version. For test resources, configure `classesToScan` to
53+
`${project.build.testOutputDirectory}` and `classpath` to `WITH_ALL_DEPENDENCIES_AND_TESTS`, and
54+
bind the plugin execution to `process-test-classes`.
4255

43-
For example, a CR using the `java-operator-sdk.io` group with a `mycrs` plural form will result in these files:
56+
For example, a CR using the `java-operator-sdk.io` group with a `mycrs` plural form will result in:
4457
- `mycrs.java-operator-sdk.io-v1.yml`
45-
- `mycrs.java-operator-sdk.io-v1beta1.yml`
58+
59+
Only `apiextensions.k8s.io/v1` CRDs are generated.
4660

4761
**Note for Quarkus users:** If you're using the `quarkus-operator-sdk` extension, you don't need to add any extra dependency for CRD generation - the extension handles this automatically.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: Migrating to Fabric8 8 and Jackson 3
3+
description: Updating operators for Fabric8 Kubernetes Client 8 and Jackson 3
4+
---
5+
6+
## Fabric8 Kubernetes Client 8
7+
8+
The SDK now uses Fabric8 Kubernetes Client `8.0.0`, which requires Java 17 or newer, matching the
9+
SDK's existing Java baseline. Align any explicit Fabric8 dependencies and the
10+
`crd-generator-maven-plugin` with this version.
11+
12+
See the [Fabric8 8 migration guide](https://github.com/fabric8io/kubernetes-client/blob/v8.0.0/doc/MIGRATION-v8.md)
13+
for the complete list of client and CRD generator changes.
14+
15+
## Jackson 3
16+
17+
The Kubernetes client, resource matchers, and YAML configuration provider now use Jackson 3.
18+
Code that uses the client's Jackson types must migrate from `com.fasterxml.jackson.core`,
19+
`com.fasterxml.jackson.databind`, and `com.fasterxml.jackson.dataformat` to the corresponding
20+
`tools.jackson` packages. Maven dependencies use `tools.jackson.core:jackson-core`,
21+
`tools.jackson.core:jackson-databind`, and `tools.jackson.dataformat:jackson-dataformat-yaml`.
22+
Jackson annotations such as `@JsonProperty` remain in `com.fasterxml.jackson.annotation`,
23+
provided by `com.fasterxml.jackson.core:jackson-annotations`.
24+
25+
Custom serializers, deserializers, and databind annotations must use Jackson 3 types:
26+
`ValueSerializer`, `ValueDeserializer`, and `tools.jackson.databind.annotation`. Jackson 2
27+
databind annotations are not used by the client, even when Jackson 2 is also on the classpath.
28+
Java time support is built in, so remove `JavaTimeModule` registrations.
29+
30+
Jackson 3 mappers are immutable. Use builders instead of `registerModule` or `configure`.
31+
When supplying a custom mapper to the Kubernetes client, preserve the Fabric8 compatibility
32+
defaults:
33+
34+
```java
35+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
36+
import io.fabric8.kubernetes.client.utils.KubernetesSerialization;
37+
import io.fabric8.kubernetes.model.jackson.Jackson2JdkTypesModule;
38+
import tools.jackson.databind.json.JsonMapper;
39+
40+
var mapper = JsonMapper.builderWithJackson2Defaults()
41+
.addModule(new Jackson2JdkTypesModule())
42+
.build();
43+
var client = new KubernetesClientBuilder()
44+
.withKubernetesSerialization(new KubernetesSerialization(mapper, true))
45+
.build();
46+
```
47+
48+
The default client already applies these compatibility settings. Supplying a mapper configures
49+
a copy; the original mapper is not modified. See the Fabric8 migration guide for wire-format
50+
differences that cannot be restored, and review regenerated CRDs before applying them.
51+
52+
## HTTP client selection
53+
54+
The `operator-framework` module continues to use the JDK HTTP client by default. Fabric8's
55+
default HTTP client is now `kubernetes-httpclient-vertx-5`, which the core module excludes so
56+
that it does not bring a second HTTP implementation into operators.
57+
58+
If you select Vert.x through `fabric8-httpclient-impl.name`, use `vertx-5` instead of `vertx`.
59+
Explicit Vert.x dependencies should use `io.fabric8:kubernetes-httpclient-vertx-5` and compatible
60+
Vert.x 5 dependencies. Applications depending only on `operator-framework-core` must provide
61+
their chosen Fabric8 HTTP client implementation.
62+
63+
## CRD generation
64+
65+
Fabric8 removed the `crd-generator-apt` annotation processor. Use the
66+
[`crd-generator-maven-plugin`](../../documentation/features/#automatic-crd-generation) instead.
67+
Only `apiextensions.k8s.io/v1` CRDs are generated.

‎micrometer-support/pom.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
</dependency>
6565
<dependency>
6666
<groupId>io.fabric8</groupId>
67-
<artifactId>kubernetes-httpclient-vertx</artifactId>
67+
<artifactId>kubernetes-httpclient-vertx-5</artifactId>
6868
<scope>test</scope>
6969
</dependency>
7070
</dependencies>

‎operator-framework-core/pom.xml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,15 @@
4646
<exclusions>
4747
<exclusion>
4848
<groupId>io.fabric8</groupId>
49-
<artifactId>kubernetes-httpclient-okhttp</artifactId>
49+
<artifactId>kubernetes-httpclient-vertx-5</artifactId>
5050
</exclusion>
5151
</exclusions>
5252
</dependency>
53+
<dependency>
54+
<groupId>io.fabric8</groupId>
55+
<artifactId>kubernetes-httpclient-${fabric8-httpclient-impl.name}</artifactId>
56+
<scope>test</scope>
57+
</dependency>
5358
<dependency>
5459
<groupId>org.slf4j</groupId>
5560
<artifactId>slf4j-api</artifactId>

‎operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import io.javaoperatorsdk.operator.processing.event.source.informer.pool.DefaultInformerPool;
5050
import io.javaoperatorsdk.operator.processing.event.source.informer.pool.InformerPool;
5151

52+
import tools.jackson.databind.ObjectMapper;
53+
5254
/** An interface from which to retrieve configuration information. */
5355
public interface ConfigurationService {
5456

@@ -145,11 +147,11 @@ public <R extends HasMetadata> R clone(R object) {
145147
* you do not need to worry about setting the namespace information in most cases).
146148
*
147149
* <p>Previous versions of this class provided direct access to the serialization mechanism (via
148-
* {@link com.fasterxml.jackson.databind.ObjectMapper}) or the client's configuration. This was
149-
* somewhat confusing, in particular with respect to changes made in the Fabric8 client
150-
* serialization architecture made in 6.7. The proper way to configure these aspects is now to
151-
* configure the Kubernetes client accordingly and the SDK will extract the information it needs
152-
* from this instance. The recommended way to do so is to create your operator with {@link
150+
* {@link ObjectMapper}) or the client's configuration. This was somewhat confusing, in particular
151+
* with respect to changes made in the Fabric8 client serialization architecture made in 6.7. The
152+
* proper way to configure these aspects is now to configure the Kubernetes client accordingly and
153+
* the SDK will extract the information it needs from this instance. The recommended way to do so
154+
* is to create your operator with {@link
153155
* io.javaoperatorsdk.operator.Operator#Operator(Consumer)}, passing your custom instance with
154156
* {@link ConfigurationServiceOverrider#withKubernetesClient(KubernetesClient)}.
155157
*

‎operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import io.javaoperatorsdk.operator.api.reconciler.Context;
2626
import io.javaoperatorsdk.operator.processing.dependent.Matcher;
2727

28-
import com.fasterxml.jackson.databind.JsonNode;
28+
import tools.jackson.databind.JsonNode;
2929

3030
public class GenericKubernetesResourceMatcher<R extends HasMetadata, P extends HasMetadata> {
3131

‎operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtils.java‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
import io.javaoperatorsdk.operator.api.reconciler.Context;
2121
import io.javaoperatorsdk.operator.api.reconciler.matcher.Matcher;
2222

23-
import com.fasterxml.jackson.databind.JsonNode;
24-
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
25-
import com.fasterxml.jackson.databind.node.NullNode;
26-
import com.fasterxml.jackson.databind.node.ObjectNode;
23+
import tools.jackson.databind.JsonNode;
24+
import tools.jackson.databind.node.JsonNodeFactory;
25+
import tools.jackson.databind.node.NullNode;
26+
import tools.jackson.databind.node.ObjectNode;
2727

2828
/** Shared helpers for the client-side patch based {@link Matcher} implementations. */
2929
final class MatcherUtils {
@@ -66,9 +66,7 @@ private static JsonNode applyMergePatch(JsonNode target, JsonNode patch) {
6666
}
6767
var targetObject =
6868
target.isObject() ? (ObjectNode) target : JsonNodeFactory.instance.objectNode();
69-
var fields = patch.fields();
70-
while (fields.hasNext()) {
71-
var entry = fields.next();
69+
for (var entry : patch.properties()) {
7270
if (entry.getValue().isNull()) {
7371
targetObject.remove(entry.getKey());
7472
} else {

‎operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceNamespaceChangeTest.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ private SharedIndexInformer informer() {
161161
.resources(Deployment.class)
162162
.inNamespace("ns1")
163163
.withLabelSelector((String) null)
164-
.withShardSelector(null)
164+
.withShardSelector((String) null)
165165
.runnableInformer(0);
166166
}
167167

0 commit comments

Comments
 (0)