11package io .javaoperatorsdk .operator .processing .event ;
22
3+ import java .net .HttpURLConnection ;
34import java .time .Duration ;
45import java .util .HashMap ;
56import java .util .Map ;
1011import org .slf4j .LoggerFactory ;
1112
1213import io .fabric8 .kubernetes .api .model .HasMetadata ;
14+ import io .fabric8 .kubernetes .client .KubernetesClientException ;
1315import io .javaoperatorsdk .operator .OperatorException ;
1416import io .javaoperatorsdk .operator .api .config .ConfigurationService ;
1517import io .javaoperatorsdk .operator .api .config .ControllerConfiguration ;
@@ -224,6 +226,7 @@ synchronized void eventProcessingFinished(
224226 postExecutionControl );
225227 unsetUnderExecution (resourceID );
226228
229+ logErrorIfNoRetryConfigured (executionScope , postExecutionControl );
227230 // If a delete event present at this phase, it was received during reconciliation.
228231 // So we either removed the finalizer during reconciliation or we don't use finalizers.
229232 // Either way we don't want to retry.
@@ -261,6 +264,17 @@ synchronized void eventProcessingFinished(
261264 }
262265 }
263266
267+ /**
268+ * In case retry is configured more complex error logging takes place, see handleRetryOnException
269+ */
270+ private void logErrorIfNoRetryConfigured (ExecutionScope <P > executionScope ,
271+ PostExecutionControl <P > postExecutionControl ) {
272+ if (!isRetryConfigured () && postExecutionControl .exceptionDuringExecution ()) {
273+ log .error ("Error during event processing {}" , executionScope ,
274+ postExecutionControl .getRuntimeException ().orElseThrow ());
275+ }
276+ }
277+
264278 private void reScheduleExecutionIfInstructed (
265279 PostExecutionControl <P > postExecutionControl , P customResource ) {
266280
@@ -302,6 +316,7 @@ private void handleRetryOnException(
302316 boolean eventPresent = state .eventPresent ();
303317 state .markEventReceived ();
304318
319+ retryAwareErrorLogging (state .getRetry (), eventPresent , exception , executionScope );
305320 if (eventPresent ) {
306321 log .debug ("New events exists for for resource id: {}" , resourceID );
307322 submitReconciliationExecution (state );
@@ -319,11 +334,29 @@ private void handleRetryOnException(
319334 retryEventSource ().scheduleOnce (resourceID , delay );
320335 },
321336 () -> {
322- log .error ("Exhausted retries for {} " , executionScope );
337+ log .error ("Exhausted retries for scope {}. " , executionScope );
323338 scheduleExecutionForMaxReconciliationInterval (executionScope .getResource ());
324339 });
325340 }
326341
342+ private void retryAwareErrorLogging (RetryExecution retry , boolean eventPresent ,
343+ Exception exception ,
344+ ExecutionScope <P > executionScope ) {
345+ if (!eventPresent && !retry .isLastAttempt () && exception instanceof KubernetesClientException ) {
346+ KubernetesClientException ex = (KubernetesClientException ) exception ;
347+ if (ex .getCode () == HttpURLConnection .HTTP_CONFLICT ) {
348+ log .debug ("Full client conflict error during event processing {}" , executionScope ,
349+ exception );
350+ log .warn (
351+ "Resource Kubernetes Resource Creator/Update Conflict during reconciliation. Message: {} Resource name: {}" ,
352+ ex .getMessage (), ex .getFullResourceName ());
353+ return ;
354+ }
355+ }
356+ log .error ("Error during event processing {}" , executionScope ,
357+ exception );
358+ }
359+
327360 private void cleanupOnSuccessfulExecution (ExecutionScope <P > executionScope ) {
328361 log .debug (
329362 "Cleanup for successful execution for resource: {}" , getName (executionScope .getResource ()));
0 commit comments