Skip to content

Commit 05cea60

Browse files
committed
wip
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent 685829c commit 05cea60

File tree

3 files changed

+63
-6
lines changed

3 files changed

+63
-6
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/loader/ConfigLoader.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717

1818
import java.time.Duration;
1919
import java.util.List;
20+
import java.util.Optional;
2021
import java.util.function.Consumer;
2122

2223
import io.fabric8.kubernetes.api.model.HasMetadata;
2324
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceOverrider;
2425
import io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider;
26+
import io.javaoperatorsdk.operator.processing.retry.GenericRetry;
2527

2628
public class ConfigLoader {
2729

@@ -87,6 +89,14 @@ public class ConfigLoader {
8789
Boolean.class,
8890
ConfigurationServiceOverrider::withCloneSecondaryResourcesWhenGettingFromCache));
8991

92+
// ---------------------------------------------------------------------------
93+
// Controller-level retry property suffixes
94+
// ---------------------------------------------------------------------------
95+
static final String RETRY_MAX_ATTEMPTS_SUFFIX = "retry.max-attempts";
96+
static final String RETRY_INITIAL_INTERVAL_SUFFIX = "retry.initial-interval";
97+
static final String RETRY_INTERVAL_MULTIPLIER_SUFFIX = "retry.interval-multiplier";
98+
static final String RETRY_MAX_INTERVAL_SUFFIX = "retry.max-interval";
99+
90100
// ---------------------------------------------------------------------------
91101
// Controller-level (ControllerConfigurationOverrider) bindings
92102
// The key used at runtime is built as:
@@ -163,7 +173,47 @@ Consumer<ControllerConfigurationOverrider<R>> applyControllerConfigs(String cont
163173
// ControllerConfigurationOverrider<R>.
164174
List<ConfigBinding<ControllerConfigurationOverrider<R>, ?>> bindings =
165175
(List<ConfigBinding<ControllerConfigurationOverrider<R>, ?>>) (List<?>) CONTROLLER_BINDINGS;
166-
return buildConsumer(bindings, prefix);
176+
Consumer<ControllerConfigurationOverrider<R>> consumer = buildConsumer(bindings, prefix);
177+
178+
Consumer<ControllerConfigurationOverrider<R>> retryStep = buildRetryConsumer(prefix);
179+
if (retryStep != null) {
180+
consumer = consumer == null ? retryStep : consumer.andThen(retryStep);
181+
}
182+
183+
return consumer;
184+
}
185+
186+
/**
187+
* If at least one retry property is present for the given prefix, returns a {@link Consumer} that
188+
* builds a {@link GenericRetry} starting from {@link GenericRetry#defaultLimitedExponentialRetry}
189+
* and overrides only the properties that are explicitly set.
190+
*/
191+
private <R extends HasMetadata> Consumer<ControllerConfigurationOverrider<R>> buildRetryConsumer(
192+
String prefix) {
193+
Optional<Integer> maxAttempts =
194+
configProvider.getValue(prefix + RETRY_MAX_ATTEMPTS_SUFFIX, Integer.class);
195+
Optional<Long> initialInterval =
196+
configProvider.getValue(prefix + RETRY_INITIAL_INTERVAL_SUFFIX, Long.class);
197+
Optional<Double> intervalMultiplier =
198+
configProvider.getValue(prefix + RETRY_INTERVAL_MULTIPLIER_SUFFIX, Double.class);
199+
Optional<Long> maxInterval =
200+
configProvider.getValue(prefix + RETRY_MAX_INTERVAL_SUFFIX, Long.class);
201+
202+
if (maxAttempts.isEmpty()
203+
&& initialInterval.isEmpty()
204+
&& intervalMultiplier.isEmpty()
205+
&& maxInterval.isEmpty()) {
206+
return null;
207+
}
208+
209+
return overrider -> {
210+
GenericRetry retry = GenericRetry.defaultLimitedExponentialRetry();
211+
maxAttempts.ifPresent(retry::setMaxAttempts);
212+
initialInterval.ifPresent(retry::setInitialInterval);
213+
intervalMultiplier.ifPresent(retry::setIntervalMultiplier);
214+
maxInterval.ifPresent(retry::setMaxInterval);
215+
overrider.withRetry(retry);
216+
};
167217
}
168218

169219
/**

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/loader/DefaultConfigProvider.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ private Object convert(String raw, Class<?> type) {
6565
return Integer.parseInt(raw);
6666
} else if (type == Long.class) {
6767
return Long.parseLong(raw);
68+
} else if (type == Double.class) {
69+
return Double.parseDouble(raw);
6870
} else if (type == Duration.class) {
6971
return Duration.parse(raw);
7072
}

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/loader/DefaultConfigProviderTest.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package io.javaoperatorsdk.operator.api.config.loader;
1717

1818
import java.time.Duration;
19+
import java.util.concurrent.atomic.AtomicInteger;
1920

2021
import org.junit.jupiter.api.Test;
2122

@@ -35,14 +36,16 @@ void returnsEmptyWhenNeitherEnvNorPropertyIsSet() {
3536

3637
@Test
3738
void readsStringFromEnvVariable() {
38-
var envProvider = new DefaultConfigProvider(k -> k.equals("JOSDK_TEST_STRING") ? "from-env" : null);
39+
var envProvider =
40+
new DefaultConfigProvider(k -> k.equals("JOSDK_TEST_STRING") ? "from-env" : null);
3941
assertThat(envProvider.getValue("josdk.test.string", String.class)).hasValue("from-env");
4042
}
4143

4244
@Test
4345
void envVariableKeyUsesUppercaseWithUnderscores() {
4446
// dots and hyphens both become underscores, key is uppercased
45-
var envProvider = new DefaultConfigProvider(k -> k.equals("JOSDK_CACHE_SYNC_TIMEOUT") ? "PT10S" : null);
47+
var envProvider =
48+
new DefaultConfigProvider(k -> k.equals("JOSDK_CACHE_SYNC_TIMEOUT") ? "PT10S" : null);
4649
assertThat(envProvider.getValue("josdk.cache-sync.timeout", Duration.class))
4750
.hasValue(Duration.ofSeconds(10));
4851
}
@@ -51,7 +54,8 @@ void envVariableKeyUsesUppercaseWithUnderscores() {
5154
void envVariableTakesPrecedenceOverSystemProperty() {
5255
System.setProperty("josdk.test.precedence", "from-sysprop");
5356
try {
54-
var envProvider = new DefaultConfigProvider(k -> k.equals("JOSDK_TEST_PRECEDENCE") ? "from-env" : null);
57+
var envProvider =
58+
new DefaultConfigProvider(k -> k.equals("JOSDK_TEST_PRECEDENCE") ? "from-env" : null);
5559
assertThat(envProvider.getValue("josdk.test.precedence", String.class)).hasValue("from-env");
5660
} finally {
5761
System.clearProperty("josdk.test.precedence");
@@ -63,7 +67,8 @@ void fallsBackToSystemPropertyWhenEnvVariableAbsent() {
6367
System.setProperty("josdk.test.fallback", "from-sysprop");
6468
try {
6569
var envProvider = new DefaultConfigProvider(k -> null);
66-
assertThat(envProvider.getValue("josdk.test.fallback", String.class)).hasValue("from-sysprop");
70+
assertThat(envProvider.getValue("josdk.test.fallback", String.class))
71+
.hasValue("from-sysprop");
6772
} finally {
6873
System.clearProperty("josdk.test.fallback");
6974
}
@@ -125,7 +130,7 @@ void throwsForUnsupportedType() {
125130
System.setProperty("josdk.test.unsupported", "value");
126131
try {
127132
assertThatIllegalArgumentException()
128-
.isThrownBy(() -> provider.getValue("josdk.test.unsupported", Double.class))
133+
.isThrownBy(() -> provider.getValue("josdk.test.unsupported", AtomicInteger.class))
129134
.withMessageContaining("Unsupported config type");
130135
} finally {
131136
System.clearProperty("josdk.test.unsupported");

0 commit comments

Comments
 (0)