Skip to content

Commit e82b963

Browse files
committed
wip
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent 4716cab commit e82b963

File tree

2 files changed

+154
-3
lines changed

2 files changed

+154
-3
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,7 @@ public Consumer<ConfigurationServiceOverrider> applyConfigs() {
203203
/**
204204
* Returns a {@link Consumer} that applies every controller-level property found in the {@link
205205
* ConfigProvider} to the given {@link ControllerConfigurationOverrider}. The keys are looked up
206-
* as {@code josdk.controller.<controllerName>.<property>}. Returns {@code null} when no binding
207-
* has a matching value.
206+
* as {@code josdk.controller.<controllerName>.<property>}.
208207
*/
209208
@SuppressWarnings("unchecked")
210209
public <R extends HasMetadata>

operator-framework/src/test/java/io/javaoperatorsdk/operator/config/loader/ConfigLoaderTest.java

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,159 @@ void leaderElectionMissingLeaseNameThrowsWhenOtherPropertiesPresent() {
390390
.withMessageContaining("lease-name");
391391
}
392392

393-
/** Returns true when the two types are the same or one is the boxed/unboxed form of the other. */
393+
// -- retry ------------------------------------------------------------------
394+
395+
/** A minimal reconciler used to obtain a base ControllerConfiguration in retry tests. */
396+
@io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration
397+
private static class DummyReconciler
398+
implements io.javaoperatorsdk.operator.api.reconciler.Reconciler<
399+
io.fabric8.kubernetes.api.model.ConfigMap> {
400+
@Override
401+
public io.javaoperatorsdk.operator.api.reconciler.UpdateControl<
402+
io.fabric8.kubernetes.api.model.ConfigMap>
403+
reconcile(
404+
io.fabric8.kubernetes.api.model.ConfigMap r,
405+
io.javaoperatorsdk.operator.api.reconciler.Context<
406+
io.fabric8.kubernetes.api.model.ConfigMap>
407+
ctx) {
408+
return io.javaoperatorsdk.operator.api.reconciler.UpdateControl.noUpdate();
409+
}
410+
}
411+
412+
private static io.javaoperatorsdk.operator.api.config.ControllerConfiguration<
413+
io.fabric8.kubernetes.api.model.ConfigMap>
414+
baseControllerConfig() {
415+
return new BaseConfigurationService().getConfigurationFor(new DummyReconciler());
416+
}
417+
418+
private static io.javaoperatorsdk.operator.processing.retry.GenericRetry applyAndGetRetry(
419+
java.util.function.Consumer<
420+
io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider<
421+
io.fabric8.kubernetes.api.model.ConfigMap>>
422+
consumer) {
423+
var overrider =
424+
io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider.override(
425+
baseControllerConfig());
426+
consumer.accept(overrider);
427+
return (io.javaoperatorsdk.operator.processing.retry.GenericRetry) overrider.build().getRetry();
428+
}
429+
430+
@Test
431+
void retryIsNotConfiguredWhenNoRetryPropertiesPresent() {
432+
var loader = new ConfigLoader(mapProvider(Map.of()));
433+
var consumer = loader.<io.fabric8.kubernetes.api.model.ConfigMap>applyControllerConfigs("ctrl");
434+
var overrider =
435+
io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider.override(
436+
baseControllerConfig());
437+
consumer.accept(overrider);
438+
// no retry property set → retry stays at the controller's default (null or unchanged)
439+
var result = overrider.build();
440+
// The consumer must not throw and the config is buildable
441+
assertThat(result).isNotNull();
442+
}
443+
444+
@Test
445+
void retryQueriesExpectedKeys() {
446+
var queriedKeys = new ArrayList<String>();
447+
ConfigProvider recordingProvider =
448+
new ConfigProvider() {
449+
@Override
450+
public <T> Optional<T> getValue(String key, Class<T> type) {
451+
queriedKeys.add(key);
452+
return Optional.empty();
453+
}
454+
};
455+
new ConfigLoader(recordingProvider).applyControllerConfigs("ctrl");
456+
assertThat(queriedKeys)
457+
.contains(
458+
"josdk.controller.ctrl.retry.max-attempts",
459+
"josdk.controller.ctrl.retry.initial-interval",
460+
"josdk.controller.ctrl.retry.interval-multiplier",
461+
"josdk.controller.ctrl.retry.max-interval");
462+
}
463+
464+
@Test
465+
void retryMaxAttemptsIsApplied() {
466+
var loader =
467+
new ConfigLoader(mapProvider(Map.of("josdk.controller.ctrl.retry.max-attempts", 10)));
468+
var retry = applyAndGetRetry(loader.applyControllerConfigs("ctrl"));
469+
assertThat(retry.getMaxAttempts()).isEqualTo(10);
470+
// other fields stay at their defaults
471+
assertThat(retry.getInitialInterval())
472+
.isEqualTo(
473+
io.javaoperatorsdk.operator.processing.retry.GenericRetry
474+
.defaultLimitedExponentialRetry()
475+
.getInitialInterval());
476+
}
477+
478+
@Test
479+
void retryInitialIntervalIsApplied() {
480+
var loader =
481+
new ConfigLoader(mapProvider(Map.of("josdk.controller.ctrl.retry.initial-interval", 500L)));
482+
var retry = applyAndGetRetry(loader.applyControllerConfigs("ctrl"));
483+
assertThat(retry.getInitialInterval()).isEqualTo(500L);
484+
}
485+
486+
@Test
487+
void retryIntervalMultiplierIsApplied() {
488+
var loader =
489+
new ConfigLoader(
490+
mapProvider(Map.of("josdk.controller.ctrl.retry.interval-multiplier", 2.0)));
491+
var retry = applyAndGetRetry(loader.applyControllerConfigs("ctrl"));
492+
assertThat(retry.getIntervalMultiplier()).isEqualTo(2.0);
493+
}
494+
495+
@Test
496+
void retryMaxIntervalIsApplied() {
497+
var loader =
498+
new ConfigLoader(mapProvider(Map.of("josdk.controller.ctrl.retry.max-interval", 30000L)));
499+
var retry = applyAndGetRetry(loader.applyControllerConfigs("ctrl"));
500+
assertThat(retry.getMaxInterval()).isEqualTo(30000L);
501+
}
502+
503+
@Test
504+
void retryAllPropertiesApplied() {
505+
var values = new HashMap<String, Object>();
506+
values.put("josdk.controller.ctrl.retry.max-attempts", 7);
507+
values.put("josdk.controller.ctrl.retry.initial-interval", 1000L);
508+
values.put("josdk.controller.ctrl.retry.interval-multiplier", 3.0);
509+
values.put("josdk.controller.ctrl.retry.max-interval", 60000L);
510+
var loader = new ConfigLoader(mapProvider(values));
511+
var retry = applyAndGetRetry(loader.applyControllerConfigs("ctrl"));
512+
assertThat(retry.getMaxAttempts()).isEqualTo(7);
513+
assertThat(retry.getInitialInterval()).isEqualTo(1000L);
514+
assertThat(retry.getIntervalMultiplier()).isEqualTo(3.0);
515+
assertThat(retry.getMaxInterval()).isEqualTo(60000L);
516+
}
517+
518+
@Test
519+
void retryStartsFromDefaultLimitedExponentialRetryDefaults() {
520+
// Only max-attempts is overridden — other fields must still be the defaults.
521+
var defaults =
522+
io.javaoperatorsdk.operator.processing.retry.GenericRetry.defaultLimitedExponentialRetry();
523+
var loader =
524+
new ConfigLoader(mapProvider(Map.of("josdk.controller.ctrl.retry.max-attempts", 3)));
525+
var retry = applyAndGetRetry(loader.applyControllerConfigs("ctrl"));
526+
assertThat(retry.getMaxAttempts()).isEqualTo(3);
527+
assertThat(retry.getInitialInterval()).isEqualTo(defaults.getInitialInterval());
528+
assertThat(retry.getIntervalMultiplier()).isEqualTo(defaults.getIntervalMultiplier());
529+
assertThat(retry.getMaxInterval()).isEqualTo(defaults.getMaxInterval());
530+
}
531+
532+
@Test
533+
void retryIsIsolatedPerControllerName() {
534+
var values = new HashMap<String, Object>();
535+
values.put("josdk.controller.alpha.retry.max-attempts", 4);
536+
values.put("josdk.controller.beta.retry.max-attempts", 9);
537+
var loader = new ConfigLoader(mapProvider(values));
538+
539+
var alphaRetry = applyAndGetRetry(loader.applyControllerConfigs("alpha"));
540+
var betaRetry = applyAndGetRetry(loader.applyControllerConfigs("beta"));
541+
542+
assertThat(alphaRetry.getMaxAttempts()).isEqualTo(4);
543+
assertThat(betaRetry.getMaxAttempts()).isEqualTo(9);
544+
}
545+
394546
private static boolean isTypeCompatible(Class<?> methodParam, Class<?> bindingType) {
395547
if (methodParam == bindingType) return true;
396548
if (methodParam == boolean.class && bindingType == Boolean.class) return true;

0 commit comments

Comments
 (0)