@@ -81,10 +81,6 @@ private PostExecutionControl<R> handleDispatch(ExecutionScope<R> executionScope)
8181 }
8282 }
8383
84- private ControllerConfiguration <R > configuration () {
85- return controller .getConfiguration ();
86- }
87-
8884 /**
8985 * Determines whether the given resource should be dispatched to the controller's
9086 * {@link Reconciler#cleanup(HasMetadata, Context)} method
@@ -100,36 +96,39 @@ private boolean shouldNotDispatchToDelete(R resource) {
10096 }
10197
10298 private PostExecutionControl <R > handleReconcile (
103- ExecutionScope <R > executionScope , R resource , Context context ) {
104- if (configuration ().useFinalizer () && !resource .hasFinalizer (configuration ().getFinalizer ())) {
99+ ExecutionScope <R > executionScope , R originalResource , Context context ) {
100+ if (configuration ().useFinalizer ()
101+ && !originalResource .hasFinalizer (configuration ().getFinalizer ())) {
105102 /*
106103 * We always add the finalizer if missing and the controller is configured to use a finalizer.
107104 * We execute the controller processing only for processing the event sent as a results of the
108105 * finalizer add. This will make sure that the resources are not created before there is a
109106 * finalizer.
110107 */
111- updateCustomResourceWithFinalizer (resource );
108+ updateCustomResourceWithFinalizer (originalResource );
112109 return PostExecutionControl .onlyFinalizerAdded ();
113110 } else {
114111 try {
115112 var resourceForExecution =
116- cloneResourceForErrorStatusHandlerIfNeeded (resource , context );
117- return reconcileExecution (executionScope , resourceForExecution , context );
113+ cloneResourceForErrorStatusHandlerIfNeeded (originalResource , context );
114+ return reconcileExecution (executionScope , resourceForExecution , originalResource , context );
118115 } catch (RuntimeException e ) {
119- handleLastAttemptErrorStatusHandler (resource , context , e );
116+ handleLastAttemptErrorStatusHandler (originalResource , context , e );
120117 throw e ;
121118 }
122119 }
123120 }
124121
125122 /**
126- * Resource make sense only to clone for the ErrorStatusHandler. Otherwise, this operation can be
127- * skipped since it can be memory and time-consuming. However, it needs to be cloned since it's
128- * common that the custom resource is changed during an execution, and it's much cleaner to have
129- * to original resource in place for status update.
123+ * Resource make sense only to clone for the ErrorStatusHandler or if the observed generation in
124+ * status is handled automatically. Otherwise, this operation can be skipped since it can be
125+ * memory and time-consuming. However, it needs to be cloned since it's common that the custom
126+ * resource is changed during an execution, and it's much cleaner to have to original resource in
127+ * place for status update.
130128 */
131129 private R cloneResourceForErrorStatusHandlerIfNeeded (R resource , Context context ) {
132- if (isLastAttemptOfRetryAndErrorStatusHandlerPresent (context )) {
130+ if (isLastAttemptOfRetryAndErrorStatusHandlerPresent (context ) ||
131+ shouldUpdateObservedGenerationAutomatically (resource )) {
133132 return controller .getConfiguration ().getConfigurationService ().getResourceCloner ()
134133 .clone (resource );
135134 } else {
@@ -138,26 +137,29 @@ private R cloneResourceForErrorStatusHandlerIfNeeded(R resource, Context context
138137 }
139138
140139 private PostExecutionControl <R > reconcileExecution (ExecutionScope <R > executionScope ,
141- R resource , Context context ) {
140+ R resourceForExecution , R originalResource , Context context ) {
142141 log .debug (
143142 "Executing createOrUpdate for resource {} with version: {} with execution scope: {}" ,
144- getName (resource ),
145- getVersion (resource ),
143+ getName (resourceForExecution ),
144+ getVersion (resourceForExecution ),
146145 executionScope );
147146
148- UpdateControl <R > updateControl = controller .reconcile (resource , context );
147+ UpdateControl <R > updateControl = controller .reconcile (resourceForExecution , context );
149148 R updatedCustomResource = null ;
150- if (updateControl .isUpdateCustomResourceAndStatusSubResource ()) {
149+ if (updateControl .isUpdateResourceAndStatus ()) {
151150 updatedCustomResource = updateCustomResource (updateControl .getResource ());
152151 updateControl
153152 .getResource ()
154153 .getMetadata ()
155154 .setResourceVersion (updatedCustomResource .getMetadata ().getResourceVersion ());
156155 updatedCustomResource = updateStatusGenerationAware (updateControl .getResource ());
157- } else if (updateControl .isUpdateStatusSubResource ()) {
156+ } else if (updateControl .isUpdateStatus ()) {
158157 updatedCustomResource = updateStatusGenerationAware (updateControl .getResource ());
159158 } else if (updateControl .isUpdateResource ()) {
160159 updatedCustomResource = updateCustomResource (updateControl .getResource ());
160+ } else if (updateControl .isNoUpdate ()
161+ && shouldUpdateObservedGenerationAutomatically (resourceForExecution )) {
162+ updatedCustomResource = updateStatusGenerationAware (originalResource );
161163 }
162164 return createPostExecutionControl (updatedCustomResource , updateControl );
163165 }
@@ -184,14 +186,27 @@ private boolean isLastAttemptOfRetryAndErrorStatusHandlerPresent(Context context
184186 }
185187 }
186188
187- private R updateStatusGenerationAware (R customResource ) {
188- updateStatusObservedGenerationIfRequired (customResource );
189- return customResourceFacade .updateStatus (customResource );
189+ private R updateStatusGenerationAware (R resource ) {
190+ updateStatusObservedGenerationIfRequired (resource );
191+ return customResourceFacade .updateStatus (resource );
192+ }
193+
194+ private boolean shouldUpdateObservedGenerationAutomatically (R resource ) {
195+ if (controller .getConfiguration ().isGenerationAware ()
196+ && resource instanceof CustomResource <?, ?>) {
197+ var customResource = (CustomResource ) resource ;
198+ var status = customResource .getStatus ();
199+ // Note that if status is null we won't update the observed generation.
200+ if (status instanceof ObservedGenerationAware ) {
201+ var observedGen = ((ObservedGenerationAware ) status ).getObservedGeneration ();
202+ var currentGen = resource .getMetadata ().getGeneration ();
203+ return !currentGen .equals (observedGen );
204+ }
205+ }
206+ return false ;
190207 }
191208
192209 private void updateStatusObservedGenerationIfRequired (R resource ) {
193- // todo: change this to check for HasStatus (or similar) when
194- // https://github.com/fabric8io/kubernetes-client/issues/3586 is fixed
195210 if (controller .getConfiguration ().isGenerationAware ()
196211 && resource instanceof CustomResource <?, ?>) {
197212 var customResource = (CustomResource ) resource ;
@@ -280,6 +295,10 @@ private R replace(R resource) {
280295 return customResourceFacade .replaceWithLock (resource );
281296 }
282297
298+ private ControllerConfiguration <R > configuration () {
299+ return controller .getConfiguration ();
300+ }
301+
283302 // created to support unit testing
284303 static class CustomResourceFacade <R extends HasMetadata > {
285304
0 commit comments