Skip to content

Commit 93ec70d

Browse files
committed
error handler suppoer for conditional update
1 parent 397cc5c commit 93ec70d

File tree

5 files changed

+71
-28
lines changed

5 files changed

+71
-28
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ErrorStatusUpdateControl.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,34 @@ public class ErrorStatusUpdateControl<P extends HasMetadata> {
99
private final P resource;
1010
private final boolean patch;
1111
private boolean noRetry = false;
12-
12+
private final boolean onlyOnChange;
1313

1414
public static <T extends HasMetadata> ErrorStatusUpdateControl<T> patchStatus(T resource) {
15-
return new ErrorStatusUpdateControl<>(resource, true);
15+
return new ErrorStatusUpdateControl<>(resource, true, false);
1616
}
1717

1818
public static <T extends HasMetadata> ErrorStatusUpdateControl<T> updateStatus(T resource) {
19-
return new ErrorStatusUpdateControl<>(resource, false);
19+
return new ErrorStatusUpdateControl<>(resource, false, false);
20+
}
21+
22+
public static <T extends HasMetadata> ErrorStatusUpdateControl<T> patchStatusIfChanged(
23+
T resource) {
24+
return new ErrorStatusUpdateControl<>(resource, true, true);
25+
}
26+
27+
public static <T extends HasMetadata> ErrorStatusUpdateControl<T> updateStatusIfChanged(
28+
T resource) {
29+
return new ErrorStatusUpdateControl<>(resource, false, true);
2030
}
2131

2232
public static <T extends HasMetadata> ErrorStatusUpdateControl<T> noStatusUpdate() {
23-
return new ErrorStatusUpdateControl<>(null, true);
33+
return new ErrorStatusUpdateControl<>(null, true, false);
2434
}
2535

26-
private ErrorStatusUpdateControl(P resource, boolean patch) {
36+
private ErrorStatusUpdateControl(P resource, boolean patch, boolean onlyOnChange) {
2737
this.resource = resource;
2838
this.patch = patch;
39+
this.onlyOnChange = onlyOnChange;
2940
}
3041

3142
/**
@@ -49,4 +60,8 @@ public boolean isNoRetry() {
4960
public boolean isPatch() {
5061
return patch;
5162
}
63+
64+
public boolean isOnlyOnChange() {
65+
return onlyOnChange;
66+
}
5267
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@
1515
import io.javaoperatorsdk.operator.api.ObservedGenerationAware;
1616
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
1717
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
18-
import io.javaoperatorsdk.operator.api.reconciler.BaseControl;
19-
import io.javaoperatorsdk.operator.api.reconciler.Context;
20-
import io.javaoperatorsdk.operator.api.reconciler.DefaultContext;
21-
import io.javaoperatorsdk.operator.api.reconciler.DeleteControl;
22-
import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusHandler;
23-
import io.javaoperatorsdk.operator.api.reconciler.RetryInfo;
24-
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
18+
import io.javaoperatorsdk.operator.api.reconciler.*;
2519
import io.javaoperatorsdk.operator.processing.Controller;
2620

2721
import static io.javaoperatorsdk.operator.processing.KubernetesResourceUtils.getName;
@@ -185,21 +179,14 @@ public boolean isLastAttempt() {
185179
var errorStatusUpdateControl = ((ErrorStatusHandler<R>) controller.getReconciler())
186180
.updateErrorStatus(resource, context, e);
187181

188-
R updatedResource = null;
189-
if (errorStatusUpdateControl.getResource().isPresent()) {
190-
updatedResource = errorStatusUpdateControl.isPatch() ? customResourceFacade
191-
.patchStatus(errorStatusUpdateControl.getResource().orElseThrow(), originalResource)
192-
: customResourceFacade
193-
.updateStatus(errorStatusUpdateControl.getResource().orElseThrow());
194-
}
182+
Optional<R> updatedResource = errorStatusUpdateControl.getResource()
183+
.flatMap(r -> updateForErrorHandling(originalResource, r,
184+
errorStatusUpdateControl));
195185
if (errorStatusUpdateControl.isNoRetry()) {
196-
if (updatedResource != null) {
197-
return errorStatusUpdateControl.isPatch()
198-
? PostExecutionControl.customResourceStatusPatched(updatedResource)
199-
: PostExecutionControl.customResourceUpdated(updatedResource);
200-
} else {
201-
return PostExecutionControl.defaultDispatch();
202-
}
186+
return updatedResource.map(r -> errorStatusUpdateControl.isPatch()
187+
? PostExecutionControl.customResourceStatusPatched(r)
188+
: PostExecutionControl.customResourceUpdated(r))
189+
.orElseGet(PostExecutionControl::defaultDispatch);
203190
}
204191
} catch (RuntimeException ex) {
205192
log.error("Error during error status handling.", ex);
@@ -208,6 +195,18 @@ public boolean isLastAttempt() {
208195
throw e;
209196
}
210197

198+
private Optional<R> updateForErrorHandling(R originalResource, R updatedResource,
199+
ErrorStatusUpdateControl<R> errorStatusUpdateControl) {
200+
if (errorStatusUpdateControl.isOnlyOnChange()
201+
&& statusEqual(originalResource, updatedResource)) {
202+
return Optional.empty();
203+
}
204+
return Optional.of(errorStatusUpdateControl.isPatch() ? customResourceFacade
205+
.patchStatus(errorStatusUpdateControl.getResource().orElseThrow(), originalResource)
206+
: customResourceFacade
207+
.updateStatus(errorStatusUpdateControl.getResource().orElseThrow()));
208+
}
209+
211210
private boolean isErrorStatusHandlerPresent() {
212211
return controller.getReconciler() instanceof ErrorStatusHandler;
213212
}

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ void callErrorStatusHandlerEvenOnFirstError() {
541541
@Test
542542
void errorHandlerCanInstructNoRetryWithUpdate() {
543543
testCustomResource.addFinalizer(DEFAULT_FINALIZER);
544+
when(customResourceFacade.updateStatus(any())).thenReturn(testCustomResource);
544545
reconciler.reconcile = (r, c) -> {
545546
throw new IllegalStateException("Error Status Test");
546547
};
@@ -599,6 +600,34 @@ void errorStatusHandlerCanPatchResource() {
599600
any(), any());
600601
}
601602

603+
@Test
604+
void errorStatusHandlerConditionallyUpdatesStatus() {
605+
extracted((r, ri, e) -> ErrorStatusUpdateControl.updateStatusIfChanged(testCustomResource));
606+
}
607+
608+
@Test
609+
void errorStatusHandlerConditionallyPatchesStatus() {
610+
extracted((r, ri, e) -> ErrorStatusUpdateControl.patchStatusIfChanged(testCustomResource));
611+
}
612+
613+
private void extracted(ErrorStatusHandler<TestCustomResource> errorHandler) {
614+
testCustomResource.addFinalizer(DEFAULT_FINALIZER);
615+
reconciler.reconcile = (r, c) -> {
616+
throw new IllegalStateException("Error Status Test");
617+
};
618+
619+
reconciler.errorHandler = errorHandler;
620+
621+
reconciliationDispatcher.handleExecution(
622+
new ExecutionScope(
623+
testCustomResource, null));
624+
625+
verify(customResourceFacade, never()).updateStatus(eq(testCustomResource));
626+
verify(customResourceFacade, never()).patchStatus(eq(testCustomResource), any());
627+
verify(((ErrorStatusHandler) reconciler), times(1)).updateErrorStatus(eq(testCustomResource),
628+
any(), any());
629+
}
630+
602631
@Test
603632
void schedulesReconciliationIfMaxDelayIsSet() {
604633
testCustomResource.addFinalizer(DEFAULT_FINALIZER);

sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public ErrorStatusUpdateControl<MySQLSchema> updateErrorStatus(MySQLSchema schem
5757
status.setSecretName(null);
5858
status.setStatus("ERROR: " + e.getMessage());
5959
schema.setStatus(status);
60-
return ErrorStatusUpdateControl.patchStatus(schema);
60+
return ErrorStatusUpdateControl.patchStatusIfChanged(schema);
6161
}
6262

6363

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/Utils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static String serviceName(WebPage webPage) {
3131

3232
static ErrorStatusUpdateControl<WebPage> handleError(WebPage resource, Exception e) {
3333
resource.getStatus().setErrorMessage("Error: " + e.getMessage());
34-
return ErrorStatusUpdateControl.updateStatus(resource);
34+
return ErrorStatusUpdateControl.updateStatusIfChanged(resource);
3535
}
3636

3737
static void simulateErrorIfRequested(WebPage webPage) throws ErrorSimulationException {

0 commit comments

Comments
 (0)