R clone(R object) {
* you do not need to worry about setting the namespace information in most cases).
*
* Previous versions of this class provided direct access to the serialization mechanism (via
- * {@link com.fasterxml.jackson.databind.ObjectMapper}) or the client's configuration. This was
- * somewhat confusing, in particular with respect to changes made in the Fabric8 client
- * serialization architecture made in 6.7. The proper way to configure these aspects is now to
- * configure the Kubernetes client accordingly and the SDK will extract the information it needs
- * from this instance. The recommended way to do so is to create your operator with {@link
+ * {@link ObjectMapper}) or the client's configuration. This was somewhat confusing, in particular
+ * with respect to changes made in the Fabric8 client serialization architecture made in 6.7. The
+ * proper way to configure these aspects is now to configure the Kubernetes client accordingly and
+ * the SDK will extract the information it needs from this instance. The recommended way to do so
+ * is to create your operator with {@link
* io.javaoperatorsdk.operator.Operator#Operator(Consumer)}, passing your custom instance with
* {@link ConfigurationServiceOverrider#withKubernetesClient(KubernetesClient)}.
*
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java
index 23fb29151f..84be53d722 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java
@@ -25,7 +25,7 @@
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.Matcher;
-import com.fasterxml.jackson.databind.JsonNode;
+import tools.jackson.databind.JsonNode;
public class GenericKubernetesResourceMatcher {
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtils.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtils.java
index 413a1c4acc..9bd6994fb2 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtils.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtils.java
@@ -20,10 +20,10 @@
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.matcher.Matcher;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.JsonNodeFactory;
-import com.fasterxml.jackson.databind.node.NullNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import tools.jackson.databind.JsonNode;
+import tools.jackson.databind.node.JsonNodeFactory;
+import tools.jackson.databind.node.NullNode;
+import tools.jackson.databind.node.ObjectNode;
/** Shared helpers for the client-side patch based {@link Matcher} implementations. */
final class MatcherUtils {
@@ -66,9 +66,7 @@ private static JsonNode applyMergePatch(JsonNode target, JsonNode patch) {
}
var targetObject =
target.isObject() ? (ObjectNode) target : JsonNodeFactory.instance.objectNode();
- var fields = patch.fields();
- while (fields.hasNext()) {
- var entry = fields.next();
+ for (var entry : patch.properties()) {
if (entry.getValue().isNull()) {
targetObject.remove(entry.getKey());
} else {
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/Jackson3SerializationTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/Jackson3SerializationTest.java
new file mode 100644
index 0000000000..ab9abeaa9f
--- /dev/null
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/Jackson3SerializationTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright Java Operator SDK Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.javaoperatorsdk.operator.api.config;
+
+import java.time.Duration;
+import java.util.Locale;
+import java.util.Objects;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import io.fabric8.kubernetes.client.CustomResource;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.KubernetesClientBuilder;
+import io.fabric8.kubernetes.client.utils.KubernetesSerialization;
+import io.fabric8.kubernetes.model.annotation.Group;
+import io.fabric8.kubernetes.model.annotation.Version;
+import io.fabric8.kubernetes.model.jackson.Jackson2JdkTypesModule;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.processing.matcher.JsonMergePatchMatcher;
+import io.javaoperatorsdk.operator.processing.matcher.JsonPatchMatcher;
+
+import tools.jackson.core.JsonGenerator;
+import tools.jackson.core.JsonParser;
+import tools.jackson.databind.DeserializationContext;
+import tools.jackson.databind.JsonNode;
+import tools.jackson.databind.SerializationContext;
+import tools.jackson.databind.ValueDeserializer;
+import tools.jackson.databind.ValueSerializer;
+import tools.jackson.databind.annotation.JsonDeserialize;
+import tools.jackson.databind.annotation.JsonSerialize;
+import tools.jackson.databind.cfg.ContextAttributes;
+import tools.jackson.databind.json.JsonMapper;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class Jackson3SerializationTest {
+
+ private static final String PREFIX_ATTRIBUTE = "valuePrefix";
+ private static final String PREFIX = "custom:";
+
+ private KubernetesClient client;
+ private ConfigurationService configuration;
+
+ @BeforeEach
+ void setup() {
+ var mapper =
+ JsonMapper.builderWithJackson2Defaults()
+ .addModule(new Jackson2JdkTypesModule())
+ .defaultAttributes(
+ ContextAttributes.getEmpty().withSharedAttribute(PREFIX_ATTRIBUTE, PREFIX))
+ .build();
+ client =
+ new KubernetesClientBuilder()
+ .withKubernetesSerialization(new KubernetesSerialization(mapper, true))
+ .build();
+ configuration =
+ new ConfigurationServiceOverrider(new BaseConfigurationService())
+ .withKubernetesClient(client)
+ .build();
+ }
+
+ @AfterEach
+ void cleanup() {
+ client.close();
+ }
+
+ @Test
+ void configuredClientClonesCustomResourceUsingJackson3Annotations() {
+ var original = resource("value");
+ var node =
+ configuration
+ .getKubernetesClient()
+ .getKubernetesSerialization()
+ .convertValue(original, JsonNode.class);
+
+ assertThat(configuration.getKubernetesClient()).isSameAs(client);
+ assertThat(node.at("/spec/value").asString()).isEqualTo("custom:value");
+ assertThat(node.at("/spec/timeout").asString()).isEqualTo("PT30S");
+
+ var cloned = configuration.getResourceCloner().clone(original);
+ assertThat(cloned).isNotSameAs(original);
+ assertThat(cloned.getSpec()).isNotSameAs(original.getSpec()).isEqualTo(original.getSpec());
+ assertThat(cloned.getMetadata()).isNotSameAs(original.getMetadata());
+ assertThat(cloned.getMetadata().getName()).isEqualTo(original.getMetadata().getName());
+ }
+
+ @Test
+ void matchersUseConfiguredSerializationRatherThanPojoEquality() {
+ Context context = mock();
+ when(context.getClient()).thenReturn(configuration.getKubernetesClient());
+ var desired = resource("VALUE");
+ var actual = configuration.getResourceCloner().clone(desired);
+
+ assertThat(desired.getSpec()).isNotEqualTo(actual.getSpec());
+ assertThat(JsonPatchMatcher.getInstance().matches(desired, actual, context)).isTrue();
+ assertThat(JsonMergePatchMatcher.getInstance().matches(desired, actual, context)).isTrue();
+
+ var changed = resource("different");
+ assertThat(JsonPatchMatcher.getInstance().matches(changed, actual, context)).isFalse();
+ assertThat(JsonMergePatchMatcher.getInstance().matches(changed, actual, context)).isFalse();
+ }
+
+ private static SerializationCustomResource resource(String value) {
+ var resource = new SerializationCustomResource();
+ resource.getMetadata().setName("serialization-test");
+ resource.setSpec(new SerializationSpec(new EncodedValue(value), Duration.ofSeconds(30)));
+ return resource;
+ }
+
+ @Group("serialization.javaoperatorsdk.io")
+ @Version("v1")
+ public static class SerializationCustomResource extends CustomResource {}
+
+ public record SerializationSpec(EncodedValue value, Duration timeout) {}
+
+ @JsonSerialize(using = EncodedValueSerializer.class)
+ @JsonDeserialize(using = EncodedValueDeserializer.class)
+ public record EncodedValue(String value) {}
+
+ public static class EncodedValueSerializer extends ValueSerializer {
+ @Override
+ public void serialize(
+ EncodedValue value, JsonGenerator generator, SerializationContext context) {
+ var prefix = (String) Objects.requireNonNull(context.getAttribute(PREFIX_ATTRIBUTE));
+ generator.writeString(prefix + value.value().toLowerCase(Locale.ROOT));
+ }
+ }
+
+ public static class EncodedValueDeserializer extends ValueDeserializer {
+ @Override
+ public EncodedValue deserialize(JsonParser parser, DeserializationContext context) {
+ var prefix = (String) Objects.requireNonNull(context.getAttribute(PREFIX_ATTRIBUTE));
+ return new EncodedValue(parser.getString().substring(prefix.length()));
+ }
+ }
+}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceNamespaceChangeTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceNamespaceChangeTest.java
index 7a2ee4ee16..e28becd6f2 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceNamespaceChangeTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceNamespaceChangeTest.java
@@ -161,7 +161,7 @@ private SharedIndexInformer informer() {
.resources(Deployment.class)
.inNamespace("ns1")
.withLabelSelector((String) null)
- .withShardSelector(null)
+ .withShardSelector((String) null)
.runnableInformer(0);
}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourcePoolIdentityTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourcePoolIdentityTest.java
index a2d0759fbc..5ee911de1f 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourcePoolIdentityTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourcePoolIdentityTest.java
@@ -70,7 +70,7 @@ void setup() {
.resources(Deployment.class)
.inNamespace(NAMESPACE)
.withLabelSelector((String) null)
- .withShardSelector(null)
+ .withShardSelector((String) null)
.runnableInformer(0);
when(informer.getStore()).thenReturn(mock(Cache.class));
}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceStartFailureTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceStartFailureTest.java
index a4d78ace74..17ff0f38b6 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceStartFailureTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSourceStartFailureTest.java
@@ -88,7 +88,7 @@ private void stubInformerStore() {
.resources(Deployment.class)
.inNamespace("ns1")
.withLabelSelector((String) null)
- .withShardSelector(null)
+ .withShardSelector((String) null)
.runnableInformer(0);
when(informer.getStore()).thenReturn(mock(Cache.class));
}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtilsTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtilsTest.java
new file mode 100644
index 0000000000..7998557f70
--- /dev/null
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/matcher/MatcherUtilsTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright Java Operator SDK Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.javaoperatorsdk.operator.processing.matcher;
+
+import org.junit.jupiter.api.Test;
+
+import tools.jackson.databind.json.JsonMapper;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class MatcherUtilsTest {
+
+ private static final JsonMapper MAPPER = JsonMapper.builder().build();
+
+ @Test
+ void mergePatchMatchesNestedValuesWithoutChangingActual() {
+ var actual =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":1,"extra":"value"}}
+ """);
+ var desired =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":1}}
+ """);
+ var original = actual.deepCopy();
+
+ assertThat(MatcherUtils.mergePatchMatches(actual, desired)).isTrue();
+ assertThat(actual).isEqualTo(original);
+ }
+
+ @Test
+ void mergePatchDoesNotMatchWhenNullRemovesExistingField() {
+ var actual =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":1}}
+ """);
+ var desired =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":null}}
+ """);
+ var original = actual.deepCopy();
+
+ assertThat(MatcherUtils.mergePatchMatches(actual, desired)).isFalse();
+ assertThat(actual).isEqualTo(original);
+ }
+
+ @Test
+ void mergePatchMatchesWhenNullTargetsAbsentField() {
+ var actual =
+ MAPPER.readTree(
+ """
+ {"spec":{}}
+ """);
+ var desired =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":null}}
+ """);
+
+ assertThat(MatcherUtils.mergePatchMatches(actual, desired)).isTrue();
+ }
+
+ @Test
+ void mergePatchReplacesScalarWithObject() {
+ var actual =
+ MAPPER.readTree(
+ """
+ {"spec":"value"}
+ """);
+ var desired =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":1}}
+ """);
+
+ assertThat(MatcherUtils.mergePatchMatches(actual, desired)).isFalse();
+ }
+
+ @Test
+ void mergePatchReplacesArraysRatherThanMergingThem() {
+ var actual =
+ MAPPER.readTree(
+ """
+ {"values":[1,2]}
+ """);
+ var desired =
+ MAPPER.readTree(
+ """
+ {"values":[1]}
+ """);
+
+ assertThat(MatcherUtils.mergePatchMatches(actual, actual)).isTrue();
+ assertThat(MatcherUtils.mergePatchMatches(actual, desired)).isFalse();
+ }
+
+ @Test
+ void jsonPatchUsesJackson3Nodes() {
+ var actual =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":1}}
+ """);
+ var desired =
+ MAPPER.readTree(
+ """
+ {"spec":{"replicas":2}}
+ """);
+
+ assertThat(MatcherUtils.jsonPatchMatches(actual, actual.deepCopy())).isTrue();
+ assertThat(MatcherUtils.jsonPatchMatches(actual, desired)).isFalse();
+ }
+}
diff --git a/operator-framework-junit/pom.xml b/operator-framework-junit/pom.xml
index a46d4f6512..91e87055dd 100644
--- a/operator-framework-junit/pom.xml
+++ b/operator-framework-junit/pom.xml
@@ -21,7 +21,7 @@
io.javaoperatorsdk
java-operator-sdk
- 5.6.4-SNAPSHOT
+ 6.0.0-SNAPSHOT
operator-framework-junit
diff --git a/operator-framework/pom.xml b/operator-framework/pom.xml
index c0e8952668..9e91485637 100644
--- a/operator-framework/pom.xml
+++ b/operator-framework/pom.xml
@@ -21,7 +21,7 @@
io.javaoperatorsdk
java-operator-sdk
- 5.6.4-SNAPSHOT
+ 6.0.0-SNAPSHOT
operator-framework
diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProvider.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProvider.java
index fc80e46a43..396d72e587 100644
--- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProvider.java
+++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProvider.java
@@ -16,7 +16,6 @@
package io.javaoperatorsdk.operator.config.loader.provider;
import java.io.IOException;
-import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -28,8 +27,8 @@
import io.javaoperatorsdk.operator.config.loader.ConfigProvider;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import tools.jackson.core.JacksonException;
+import tools.jackson.dataformat.yaml.YAMLMapper;
/**
* A {@link ConfigProvider} that resolves configuration values from a YAML file.
@@ -44,7 +43,7 @@ public class YamlConfigProvider implements ConfigProvider {
private static final Logger log = LoggerFactory.getLogger(YamlConfigProvider.class);
- private static final ObjectMapper MAPPER = new ObjectMapper(new YAMLFactory());
+ private static final YAMLMapper MAPPER = YAMLMapper.builder().build();
private final Map data;
@@ -100,8 +99,8 @@ private static Map load(Path path) {
return Map.of();
}
- try (InputStream in = Files.newInputStream(path);
- com.fasterxml.jackson.core.JsonParser parser = MAPPER.getFactory().createParser(in)) {
+ try (var in = Files.newInputStream(path);
+ var parser = MAPPER.createParser(in)) {
if (parser.nextToken() == null) {
log.debug(
"YAML file contains no mappings (possibly empty or comments only). "
@@ -111,6 +110,8 @@ private static Map load(Path path) {
}
Map result = MAPPER.readValue(parser, Map.class);
return result != null ? result : Map.of();
+ } catch (JacksonException e) {
+ throw new UncheckedIOException("Failed to load config YAML from " + path, new IOException(e));
} catch (IOException e) {
throw new UncheckedIOException("Failed to load config YAML from " + path, e);
}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java
index b2606ad740..c6dee7195d 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/baseapi/multiversioncrd/MultiVersionCRDIT.java
@@ -32,7 +32,7 @@
import io.javaoperatorsdk.operator.api.config.InformerStoppedHandler;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
-import com.fasterxml.jackson.core.JsonProcessingException;
+import tools.jackson.core.JacksonException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
@@ -104,7 +104,7 @@ public void onStop(SharedIndexInformer informer, Throwable ex) {
.get(0)
.get("apiVersion")
.asText());
- } catch (JsonProcessingException e) {
+ } catch (JacksonException e) {
throw new RuntimeException(e);
}
});
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProviderTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProviderTest.java
index 328ac6d83f..3ca569a70a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProviderTest.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/YamlConfigProviderTest.java
@@ -26,6 +26,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
+import tools.jackson.core.JacksonException;
+
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
@@ -173,7 +175,55 @@ void throwsForMalformedYaml(@TempDir Path dir) throws IOException {
- item2
""");
assertThatExceptionOfType(UncheckedIOException.class)
- .isThrownBy(() -> new YamlConfigProvider(file));
+ .isThrownBy(() -> new YamlConfigProvider(file))
+ .withMessageContaining(file.toString())
+ .withCauseInstanceOf(IOException.class)
+ .havingCause()
+ .withCauseInstanceOf(JacksonException.class);
+ }
+
+ @Test
+ void throwsForInvalidYamlSyntax(@TempDir Path dir) throws IOException {
+ var file = dir.resolve("invalid.yaml");
+ Files.writeString(file, "key: [unterminated");
+
+ assertThatExceptionOfType(UncheckedIOException.class)
+ .isThrownBy(() -> new YamlConfigProvider(file))
+ .withMessageContaining(file.toString())
+ .withCauseInstanceOf(IOException.class)
+ .havingCause()
+ .withCauseInstanceOf(JacksonException.class);
+ }
+
+ @Test
+ void nullDocumentReturnsEmpty(@TempDir Path dir) throws IOException {
+ var file = dir.resolve("null.yaml");
+ Files.writeString(file, "null");
+
+ var provider = new YamlConfigProvider(file);
+ assertThat(provider.getValue("any.key", String.class)).isEmpty();
+ }
+
+ @Test
+ void loadsTypedValuesFromFile(@TempDir Path dir) throws IOException {
+ var file = dir.resolve("typed.yaml");
+ Files.writeString(
+ file,
+ """
+ josdk:
+ enabled: true
+ limit: 2147483648
+ ratio: 3.14
+ timeout: PT30S
+ unset: null
+ """);
+
+ var provider = new YamlConfigProvider(file);
+ assertThat(provider.getValue("josdk.enabled", Boolean.class)).hasValue(true);
+ assertThat(provider.getValue("josdk.limit", Long.class)).hasValue(2147483648L);
+ assertThat(provider.getValue("josdk.ratio", Double.class)).hasValue(3.14);
+ assertThat(provider.getValue("josdk.timeout", Duration.class)).hasValue(Duration.ofSeconds(30));
+ assertThat(provider.getValue("josdk.unset", String.class)).isEmpty();
}
@Test
diff --git a/pom.xml b/pom.xml
index e9277efe34..5cab963f5d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
io.javaoperatorsdk
java-operator-sdk
- 5.6.4-SNAPSHOT
+ 6.0.0-SNAPSHOT
pom
Operator SDK for Java
Java SDK for implementing Kubernetes operators
@@ -71,7 +71,7 @@
https://sonarcloud.io
jdk
6.1.3
- 7.9.0
+ 8.0.0
2.0.20
2.26.1
5.24.0
@@ -233,7 +233,7 @@