Skip to content

Commit 6976f7d

Browse files
committed
feat: use SSA for resource status patching
Signed-off-by: Attila Mészáros <csviri@gmail.com>
1 parent b720b16 commit 6976f7d

File tree

4 files changed

+50
-16
lines changed

4 files changed

+50
-16
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,4 +391,11 @@ default boolean parseResourceVersionsForEventFilteringAndCaching() {
391391
return false;
392392
}
393393

394+
/**
395+
* {@link io.javaoperatorsdk.operator.api.reconciler.UpdateControl} patchStatus
396+
*/
397+
default boolean useSSAForResourceStatusPatch() {
398+
return true;
399+
}
400+
394401
}

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class ConfigurationServiceOverrider {
4040
private Set<Class<? extends HasMetadata>> defaultNonSSAResource;
4141
private Boolean previousAnnotationForDependentResources;
4242
private Boolean parseResourceVersions;
43+
private Boolean useSSAForResourceStatusPatch;
4344
private DependentResourceFactory dependentResourceFactory;
4445

4546
ConfigurationServiceOverrider(ConfigurationService original) {
@@ -174,12 +175,17 @@ public ConfigurationServiceOverrider withPreviousAnnotationForDependentResources
174175
return this;
175176
}
176177

177-
public ConfigurationServiceOverrider wihtParseResourceVersions(
178+
public ConfigurationServiceOverrider withParseResourceVersions(
178179
boolean value) {
179180
this.parseResourceVersions = value;
180181
return this;
181182
}
182183

184+
public ConfigurationServiceOverrider withUseSSAForResourceStatusPatch(boolean value) {
185+
this.useSSAForResourceStatusPatch = value;
186+
return this;
187+
}
188+
183189
public ConfigurationService build() {
184190
return new BaseConfigurationService(original.getVersion(), cloner, client) {
185191
@Override
@@ -312,6 +318,14 @@ public boolean parseResourceVersionsForEventFilteringAndCaching() {
312318
? parseResourceVersions
313319
: super.parseResourceVersionsForEventFilteringAndCaching();
314320
}
321+
322+
@Override
323+
public boolean useSSAForResourceStatusPatch() {
324+
return useSSAForResourceStatusPatch != null
325+
? useSSAForResourceStatusPatch
326+
: super.useSSAForResourceStatusPatch();
327+
328+
}
315329
};
316330
}
317331

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import io.fabric8.kubernetes.client.KubernetesClientException;
1313
import io.fabric8.kubernetes.client.dsl.MixedOperation;
1414
import io.fabric8.kubernetes.client.dsl.Resource;
15+
import io.fabric8.kubernetes.client.dsl.base.PatchContext;
16+
import io.fabric8.kubernetes.client.dsl.base.PatchType;
1517
import io.javaoperatorsdk.operator.OperatorException;
1618
import io.javaoperatorsdk.operator.api.ObservedGenerationAware;
1719
import io.javaoperatorsdk.operator.api.config.Cloner;
@@ -147,24 +149,24 @@ private PostExecutionControl<P> reconcileExecution(ExecutionScope<P> executionSc
147149
.setResourceVersion(updatedCustomResource.getMetadata().getResourceVersion());
148150
updatedCustomResource =
149151
updateStatusGenerationAware(updateControl.getResource(), originalResource,
150-
updateControl.isPatchStatus());
152+
updateControl.isPatchStatus(), context);
151153
} else if (updateControl.isUpdateStatus()) {
152154
updatedCustomResource =
153155
updateStatusGenerationAware(updateControl.getResource(), originalResource,
154-
updateControl.isPatchStatus());
156+
updateControl.isPatchStatus(), context);
155157
} else if (updateControl.isUpdateResource()) {
156158
updatedCustomResource =
157159
updateCustomResource(updateControl.getResource());
158160
if (shouldUpdateObservedGenerationAutomatically(updatedCustomResource)) {
159161
updatedCustomResource =
160162
updateStatusGenerationAware(updateControl.getResource(), originalResource,
161-
updateControl.isPatchStatus());
163+
updateControl.isPatchStatus(), context);
162164
}
163165
} else if (updateControl.isNoUpdate()
164166
&& shouldUpdateObservedGenerationAutomatically(resourceForExecution)) {
165167
updatedCustomResource =
166168
updateStatusGenerationAware(originalResource, originalResource,
167-
updateControl.isPatchStatus());
169+
updateControl.isPatchStatus(), context);
168170
}
169171
return createPostExecutionControl(updatedCustomResource, updateControl);
170172
}
@@ -195,7 +197,8 @@ public boolean isLastAttempt() {
195197
P updatedResource = null;
196198
if (errorStatusUpdateControl.getResource().isPresent()) {
197199
updatedResource = errorStatusUpdateControl.isPatch() ? customResourceFacade
198-
.patchStatus(errorStatusUpdateControl.getResource().orElseThrow(), originalResource)
200+
.patchStatus(errorStatusUpdateControl.getResource().orElseThrow(), originalResource,
201+
context)
199202
: customResourceFacade
200203
.updateStatus(errorStatusUpdateControl.getResource().orElseThrow());
201204
}
@@ -223,10 +226,11 @@ private boolean isErrorStatusHandlerPresent() {
223226
return controller.getReconciler() instanceof ErrorStatusHandler;
224227
}
225228

226-
private P updateStatusGenerationAware(P resource, P originalResource, boolean patch) {
229+
private P updateStatusGenerationAware(P resource, P originalResource, boolean patch,
230+
Context<P> context) {
227231
updateStatusObservedGenerationIfRequired(resource);
228232
if (patch) {
229-
return customResourceFacade.patchStatus(resource, originalResource);
233+
return customResourceFacade.patchStatus(resource, originalResource, context);
230234
} else {
231235
return customResourceFacade.updateStatus(resource);
232236
}
@@ -411,15 +415,24 @@ public R updateStatus(R resource) {
411415
.updateStatus();
412416
}
413417

414-
public R patchStatus(R resource, R originalResource) {
415-
log.trace("Updating status for resource: {}", resource);
418+
public R patchStatus(R resource, R originalResource, Context<?> context) {
419+
var useSSA = context.getControllerConfiguration().getConfigurationService()
420+
.useSSAForResourceStatusPatch();
421+
log.trace("Patching status for resource: {} with ssa: {}", resource, useSSA);
416422
String resourceVersion = resource.getMetadata().getResourceVersion();
417423
// don't do optimistic locking on patch
418424
originalResource.getMetadata().setResourceVersion(null);
419425
resource.getMetadata().setResourceVersion(null);
420426
try {
421-
return resource(originalResource)
422-
.editStatus(r -> resource);
427+
var res = resource(originalResource);
428+
if (useSSA) {
429+
return res.subresource("status").patch(new PatchContext.Builder()
430+
.withFieldManager(context.getControllerConfiguration().fieldManager())
431+
.withPatchType(PatchType.SERVER_SIDE_APPLY)
432+
.build());
433+
} else {
434+
return res.editStatus(r -> resource);
435+
}
423436
} finally {
424437
// restore initial resource version
425438
originalResource.getMetadata().setResourceVersion(resourceVersion);

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ void updatesOnlyStatusSubResourceIfFinalizerSet() {
158158

159159
reconciliationDispatcher.handleExecution(executionScopeWithCREvent(testCustomResource));
160160

161-
verify(customResourceFacade, times(1)).patchStatus(eq(testCustomResource), any());
161+
verify(customResourceFacade, times(1)).patchStatus(eq(testCustomResource), any(), any());
162162
verify(customResourceFacade, never()).updateResource(any());
163163
}
164164

@@ -184,7 +184,7 @@ void patchesStatus() {
184184

185185
reconciliationDispatcher.handleExecution(executionScopeWithCREvent(testCustomResource));
186186

187-
verify(customResourceFacade, times(1)).patchStatus(eq(testCustomResource), any());
187+
verify(customResourceFacade, times(1)).patchStatus(eq(testCustomResource), any(), any());
188188
verify(customResourceFacade, never()).updateStatus(any());
189189
verify(customResourceFacade, never()).updateResource(any());
190190
}
@@ -456,7 +456,7 @@ void setObservedGenerationForStatusIfNeeded() throws Exception {
456456

457457
when(reconciler.reconcile(any(), any()))
458458
.thenReturn(UpdateControl.patchStatus(observedGenResource));
459-
when(facade.patchStatus(eq(observedGenResource), any())).thenReturn(observedGenResource);
459+
when(facade.patchStatus(eq(observedGenResource), any(), any())).thenReturn(observedGenResource);
460460

461461
PostExecutionControl<ObservedGenCustomResource> control = dispatcher.handleExecution(
462462
executionScopeWithCREvent(observedGenResource));
@@ -609,7 +609,7 @@ void errorStatusHandlerCanPatchResource() {
609609
reconciliationDispatcher.handleExecution(
610610
new ExecutionScope(null).setResource(testCustomResource));
611611

612-
verify(customResourceFacade, times(1)).patchStatus(eq(testCustomResource), any());
612+
verify(customResourceFacade, times(1)).patchStatus(eq(testCustomResource), any(), any());
613613
verify(((ErrorStatusHandler) reconciler), times(1)).updateErrorStatus(eq(testCustomResource),
614614
any(), any());
615615
}

0 commit comments

Comments
 (0)