@@ -81,10 +81,6 @@ private PostExecutionControl<R> handleDispatch(ExecutionScope<R> executionScope)
81
81
}
82
82
}
83
83
84
- private ControllerConfiguration <R > configuration () {
85
- return controller .getConfiguration ();
86
- }
87
-
88
84
/**
89
85
* Determines whether the given resource should be dispatched to the controller's
90
86
* {@link Reconciler#cleanup(HasMetadata, Context)} method
@@ -100,36 +96,39 @@ private boolean shouldNotDispatchToDelete(R resource) {
100
96
}
101
97
102
98
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 ())) {
105
102
/*
106
103
* We always add the finalizer if missing and the controller is configured to use a finalizer.
107
104
* We execute the controller processing only for processing the event sent as a results of the
108
105
* finalizer add. This will make sure that the resources are not created before there is a
109
106
* finalizer.
110
107
*/
111
- updateCustomResourceWithFinalizer (resource );
108
+ updateCustomResourceWithFinalizer (originalResource );
112
109
return PostExecutionControl .onlyFinalizerAdded ();
113
110
} else {
114
111
try {
115
112
var resourceForExecution =
116
- cloneResourceForErrorStatusHandlerIfNeeded (resource , context );
117
- return reconcileExecution (executionScope , resourceForExecution , context );
113
+ cloneResourceForErrorStatusHandlerIfNeeded (originalResource , context );
114
+ return reconcileExecution (executionScope , resourceForExecution , originalResource , context );
118
115
} catch (RuntimeException e ) {
119
- handleLastAttemptErrorStatusHandler (resource , context , e );
116
+ handleLastAttemptErrorStatusHandler (originalResource , context , e );
120
117
throw e ;
121
118
}
122
119
}
123
120
}
124
121
125
122
/**
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.
130
128
*/
131
129
private R cloneResourceForErrorStatusHandlerIfNeeded (R resource , Context context ) {
132
- if (isLastAttemptOfRetryAndErrorStatusHandlerPresent (context )) {
130
+ if (isLastAttemptOfRetryAndErrorStatusHandlerPresent (context ) ||
131
+ shouldUpdateObservedGenerationAutomatically (resource )) {
133
132
return controller .getConfiguration ().getConfigurationService ().getResourceCloner ()
134
133
.clone (resource );
135
134
} else {
@@ -138,26 +137,29 @@ private R cloneResourceForErrorStatusHandlerIfNeeded(R resource, Context context
138
137
}
139
138
140
139
private PostExecutionControl <R > reconcileExecution (ExecutionScope <R > executionScope ,
141
- R resource , Context context ) {
140
+ R resourceForExecution , R originalResource , Context context ) {
142
141
log .debug (
143
142
"Executing createOrUpdate for resource {} with version: {} with execution scope: {}" ,
144
- getName (resource ),
145
- getVersion (resource ),
143
+ getName (resourceForExecution ),
144
+ getVersion (resourceForExecution ),
146
145
executionScope );
147
146
148
- UpdateControl <R > updateControl = controller .reconcile (resource , context );
147
+ UpdateControl <R > updateControl = controller .reconcile (resourceForExecution , context );
149
148
R updatedCustomResource = null ;
150
- if (updateControl .isUpdateCustomResourceAndStatusSubResource ()) {
149
+ if (updateControl .isUpdateResourceAndStatus ()) {
151
150
updatedCustomResource = updateCustomResource (updateControl .getResource ());
152
151
updateControl
153
152
.getResource ()
154
153
.getMetadata ()
155
154
.setResourceVersion (updatedCustomResource .getMetadata ().getResourceVersion ());
156
155
updatedCustomResource = updateStatusGenerationAware (updateControl .getResource ());
157
- } else if (updateControl .isUpdateStatusSubResource ()) {
156
+ } else if (updateControl .isUpdateStatus ()) {
158
157
updatedCustomResource = updateStatusGenerationAware (updateControl .getResource ());
159
158
} else if (updateControl .isUpdateResource ()) {
160
159
updatedCustomResource = updateCustomResource (updateControl .getResource ());
160
+ } else if (updateControl .isNoUpdate ()
161
+ && shouldUpdateObservedGenerationAutomatically (resourceForExecution )) {
162
+ updatedCustomResource = updateStatusGenerationAware (originalResource );
161
163
}
162
164
return createPostExecutionControl (updatedCustomResource , updateControl );
163
165
}
@@ -184,14 +186,27 @@ private boolean isLastAttemptOfRetryAndErrorStatusHandlerPresent(Context context
184
186
}
185
187
}
186
188
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 ;
190
207
}
191
208
192
209
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
195
210
if (controller .getConfiguration ().isGenerationAware ()
196
211
&& resource instanceof CustomResource <?, ?>) {
197
212
var customResource = (CustomResource ) resource ;
@@ -280,6 +295,10 @@ private R replace(R resource) {
280
295
return customResourceFacade .replaceWithLock (resource );
281
296
}
282
297
298
+ private ControllerConfiguration <R > configuration () {
299
+ return controller .getConfiguration ();
300
+ }
301
+
283
302
// created to support unit testing
284
303
static class CustomResourceFacade <R extends HasMetadata > {
285
304
0 commit comments