Skip to content

Commit 6f5cf2e

Browse files
committed
fix: default stop handler exists only if informer started (#1575)
1 parent 33ac184 commit 6f5cf2e

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,9 @@ default Duration cacheSyncTimeout() {
184184
*/
185185
default Optional<InformerStoppedHandler> getInformerStoppedHandler() {
186186
return Optional.of((informer, ex) -> {
187-
if (ex != null) {
187+
// hasSynced is checked to verify that informer already started. If not started, in case
188+
// of a fatal error the operator will stop, no need for explicit exit.
189+
if (ex != null && informer.hasSynced()) {
188190
Logger log = LoggerFactory.getLogger(ConfigurationService.class);
189191
log.error("Fatal error in informer: {}. Stopping the operator", informer, ex);
190192
System.exit(1);

operator-framework/src/test/java/io/javaoperatorsdk/operator/InformerRelatedBehaviorITS.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class InformerRelatedBehaviorITS {
4141
KubernetesClient adminClient = new KubernetesClientBuilder().build();
4242
InformerRelatedBehaviorTestReconciler reconciler;
4343
String actualNamespace;
44-
volatile boolean stopHandlerCalled = false;
44+
volatile boolean replacementStopHandlerCalled = false;
4545

4646
@BeforeEach
4747
void beforeEach(TestInfo testInfo) {
@@ -136,7 +136,19 @@ void callsStopHandlerOnStartupFail() {
136136

137137
assertThrows(OperatorException.class, () -> startOperator(true));
138138

139-
await().untilAsserted(() -> assertThat(stopHandlerCalled).isTrue());
139+
await().untilAsserted(() -> assertThat(replacementStopHandlerCalled).isTrue());
140+
}
141+
142+
@Test
143+
void notExitingWithDefaultStopHandlerIfErrorHappensOnStartup() {
144+
setNoCustomResourceAccess();
145+
adminClient.resource(testCustomResource()).createOrReplace();
146+
147+
assertThrows(OperatorException.class, () -> startOperator(true, false));
148+
149+
// note that we just basically check here that the default handler does not call system exit.
150+
// Thus, the test does not terminate before to assert.
151+
await().untilAsserted(() -> assertThat(replacementStopHandlerCalled).isFalse());
140152
}
141153

142154
private static void waitForWatchReconnect() {
@@ -183,16 +195,20 @@ KubernetesClient clientUsingServiceAccount() {
183195
}
184196

185197
Operator startOperator(boolean stopOnInformerErrorDuringStartup) {
198+
return startOperator(stopOnInformerErrorDuringStartup, true);
199+
}
200+
201+
Operator startOperator(boolean stopOnInformerErrorDuringStartup, boolean addStopHandler) {
186202
ConfigurationServiceProvider.reset();
187203
reconciler = new InformerRelatedBehaviorTestReconciler();
188204

189205
Operator operator = new Operator(clientUsingServiceAccount(),
190206
co -> {
191207
co.withStopOnInformerErrorDuringStartup(stopOnInformerErrorDuringStartup);
192208
co.withCacheSyncTimeout(Duration.ofMillis(3000));
193-
co.withInformerStoppedHandler((informer, ex) -> {
194-
stopHandlerCalled = true;
195-
});
209+
if (addStopHandler) {
210+
co.withInformerStoppedHandler((informer, ex) -> replacementStopHandlerCalled = true);
211+
}
196212
});
197213
operator.register(reconciler);
198214
operator.installShutdownHook();

0 commit comments

Comments
 (0)