From eccb733b5ff56f5553b749fe82110bf8a4b7f823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Thu, 19 Mar 2026 13:32:28 +0100 Subject: [PATCH 1/2] improve: config providers for yaml and properties logs only warning on missing file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This it is easier to handle dynamic configurations coming from a ConfigMap Signed-off-by: Attila Mészáros --- .../provider/PropertiesConfigProvider.java | 24 ++++++++++++++++++- .../loader/provider/YamlConfigProvider.java | 24 ++++++++++++++++++- .../PropertiesConfigProviderTest.java | 9 +++---- .../provider/YamlConfigProviderTest.java | 9 +++---- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java index 35dd38f406..83c68c9594 100644 --- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java +++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java @@ -15,6 +15,7 @@ */ package io.javaoperatorsdk.operator.config.loader.provider; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -23,6 +24,9 @@ import java.util.Optional; import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.javaoperatorsdk.operator.config.loader.ConfigProvider; /** @@ -34,6 +38,8 @@ */ public class PropertiesConfigProvider implements ConfigProvider { + private static final Logger log = LoggerFactory.getLogger(PropertiesConfigProvider.class); + private final Properties properties; /** Returns a {@link PropertiesConfigProvider} backed by {@link System#getProperties()}. */ @@ -44,7 +50,18 @@ public static PropertiesConfigProvider systemProperties() { /** * Loads properties from the given file path. * - * @throws UncheckedIOException if the file cannot be read + * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file + * not exists. + */ + public PropertiesConfigProvider(String path) { + this(Path.of(path)); + } + + /** + * Loads properties from the given file path. + * + * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file + * not exists. */ public PropertiesConfigProvider(Path path) { this.properties = load(path); @@ -68,6 +85,11 @@ public Optional getValue(String key, Class type) { } private static Properties load(Path path) { + if (!new File(path.toString()).exists()) { + log.warn("{} does not exist", path); + return new Properties(); + } + try (InputStream in = Files.newInputStream(path)) { Properties props = new Properties(); props.load(in); 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 52b07b011d..21bb1de7fc 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 @@ -15,6 +15,7 @@ */ package io.javaoperatorsdk.operator.config.loader.provider; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -23,6 +24,9 @@ import java.util.Map; import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.javaoperatorsdk.operator.config.loader.ConfigProvider; import com.fasterxml.jackson.databind.ObjectMapper; @@ -39,6 +43,8 @@ */ public class YamlConfigProvider implements ConfigProvider { + private static final Logger log = LoggerFactory.getLogger(YamlConfigProvider.class); + private static final ObjectMapper MAPPER = new ObjectMapper(new YAMLFactory()); private final Map data; @@ -46,7 +52,18 @@ public class YamlConfigProvider implements ConfigProvider { /** * Loads YAML from the given file path. * - * @throws UncheckedIOException if the file cannot be read + * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file + * not exists. + */ + public YamlConfigProvider(String path) { + this(Path.of(path)); + } + + /** + * Loads YAML from the given file path. + * + * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file + * not exists. */ public YamlConfigProvider(Path path) { this.data = load(path); @@ -79,6 +96,11 @@ public Optional getValue(String key, Class type) { @SuppressWarnings("unchecked") private static Map load(Path path) { + if (!new File(path.toString()).exists()) { + log.warn("{} does not exist", path); + return Map.of(); + } + try (InputStream in = Files.newInputStream(path)) { Map result = MAPPER.readValue(in, Map.class); return result != null ? result : Map.of(); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProviderTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProviderTest.java index c44534eb3a..dd9fd7b599 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProviderTest.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProviderTest.java @@ -16,7 +16,6 @@ package io.javaoperatorsdk.operator.config.loader.provider; import java.io.IOException; -import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; @@ -27,7 +26,6 @@ import org.junit.jupiter.api.io.TempDir; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; class PropertiesConfigProviderTest { @@ -120,10 +118,9 @@ void loadsFromFile(@TempDir Path dir) throws IOException { } @Test - void throwsUncheckedIOExceptionForMissingFile(@TempDir Path dir) { + void returnsEmptyForNonExistingFile(@TempDir Path dir) { Path missing = dir.resolve("does-not-exist.properties"); - assertThatExceptionOfType(UncheckedIOException.class) - .isThrownBy(() -> new PropertiesConfigProvider(missing)) - .withMessageContaining("does-not-exist.properties"); + var provider = new PropertiesConfigProvider(missing); + assertThat(provider.getValue("any.key", String.class)).isEmpty(); } } 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 4f8c53ac38..2362b85ea4 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 @@ -16,7 +16,6 @@ package io.javaoperatorsdk.operator.config.loader.provider; import java.io.IOException; -import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; @@ -27,7 +26,6 @@ import org.junit.jupiter.api.io.TempDir; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; class YamlConfigProviderTest { @@ -135,10 +133,9 @@ void loadsFromFile(@TempDir Path dir) throws IOException { } @Test - void throwsUncheckedIOExceptionForMissingFile(@TempDir Path dir) { + void returnsEmptyForNonExistingFile(@TempDir Path dir) { Path missing = dir.resolve("does-not-exist.yaml"); - assertThatExceptionOfType(UncheckedIOException.class) - .isThrownBy(() -> new YamlConfigProvider(missing)) - .withMessageContaining("does-not-exist.yaml"); + var provider = new YamlConfigProvider(missing); + assertThat(provider.getValue("any.key", String.class)).isEmpty(); } } From 03636ac8e09a5086ee5dd21514167a2b2f804579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Thu, 19 Mar 2026 14:02:49 +0100 Subject: [PATCH 2/2] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Attila Mészáros --- .../loader/provider/PropertiesConfigProvider.java | 11 +++++------ .../config/loader/provider/YamlConfigProvider.java | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java index 83c68c9594..8670b88f06 100644 --- a/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java +++ b/operator-framework/src/main/java/io/javaoperatorsdk/operator/config/loader/provider/PropertiesConfigProvider.java @@ -15,7 +15,6 @@ */ package io.javaoperatorsdk.operator.config.loader.provider; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -50,8 +49,8 @@ public static PropertiesConfigProvider systemProperties() { /** * Loads properties from the given file path. * - * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file - * not exists. + * @throws UncheckedIOException if the file cannot be read. Does not throw an exception if the + * file does not exist. */ public PropertiesConfigProvider(String path) { this(Path.of(path)); @@ -60,8 +59,8 @@ public PropertiesConfigProvider(String path) { /** * Loads properties from the given file path. * - * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file - * not exists. + * @throws UncheckedIOException if the file cannot be read. Does not throw an exception if the + * file does not exist. */ public PropertiesConfigProvider(Path path) { this.properties = load(path); @@ -85,7 +84,7 @@ public Optional getValue(String key, Class type) { } private static Properties load(Path path) { - if (!new File(path.toString()).exists()) { + if (!Files.exists(path)) { log.warn("{} does not exist", path); return new Properties(); } 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 21bb1de7fc..d631496d59 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 @@ -15,7 +15,6 @@ */ package io.javaoperatorsdk.operator.config.loader.provider; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -52,8 +51,8 @@ public class YamlConfigProvider implements ConfigProvider { /** * Loads YAML from the given file path. * - * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file - * not exists. + * @throws UncheckedIOException if the file cannot be read. Does not throw an exception if the + * file does not exist. */ public YamlConfigProvider(String path) { this(Path.of(path)); @@ -62,8 +61,8 @@ public YamlConfigProvider(String path) { /** * Loads YAML from the given file path. * - * @throws UncheckedIOException if the file cannot be read. Does not throw exception if the file - * not exists. + * @throws UncheckedIOException if the file cannot be read. Does not throw an exception if the + * file does not exist. */ public YamlConfigProvider(Path path) { this.data = load(path); @@ -96,7 +95,7 @@ public Optional getValue(String key, Class type) { @SuppressWarnings("unchecked") private static Map load(Path path) { - if (!new File(path.toString()).exists()) { + if (!Files.exists(path)) { log.warn("{} does not exist", path); return Map.of(); }