Skip to content

Commit 4b8037b

Browse files
csvirimetacosm
andcommitted
feat: move ReconcileUtils methods to ResourceOperations accessible from Context (#3142)
Signed-off-by: Attila Mészáros <a_meszaros@apple.com> Signed-off-by: Chris Laprun <metacosm@gmail.com> Co-authored-by: Chris Laprun <metacosm@gmail.com>
1 parent 16378f5 commit 4b8037b

File tree

15 files changed

+339
-265
lines changed

15 files changed

+339
-265
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ default <R> Stream<R> getSecondaryResourcesAsStream(Class<R> expectedType) {
5858

5959
KubernetesClient getClient();
6060

61+
ResourceOperations<P> resourceOperations();
62+
6163
/** ExecutorService initialized by framework for workflows. Used for workflow standalone mode. */
6264
ExecutorService getWorkflowExecutorService();
6365

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class DefaultContext<P extends HasMetadata> implements Context<P> {
4646
private final boolean primaryResourceDeleted;
4747
private final boolean primaryResourceFinalStateUnknown;
4848
private final Map<DependentResource<?, P>, Object> desiredStates = new ConcurrentHashMap<>();
49+
private final ResourceOperations<P> resourceOperations;
4950

5051
public DefaultContext(
5152
RetryInfo retryInfo,
@@ -61,6 +62,7 @@ public DefaultContext(
6162
this.primaryResourceFinalStateUnknown = primaryResourceFinalStateUnknown;
6263
this.defaultManagedDependentResourceContext =
6364
new DefaultManagedWorkflowAndDependentResourceContext<>(controller, primaryResource, this);
65+
this.resourceOperations = new ResourceOperations<>(this);
6466
}
6567

6668
@Override
@@ -124,6 +126,11 @@ public KubernetesClient getClient() {
124126
return controller.getClient();
125127
}
126128

129+
@Override
130+
public ResourceOperations<P> resourceOperations() {
131+
return resourceOperations;
132+
}
133+
127134
@Override
128135
public ExecutorService getWorkflowExecutorService() {
129136
// note that this should be always received from executor service manager, so we are able to do

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
* If the update fails, it reads the primary resource from the cluster, applies the modifications
4747
* again and retries the update.
4848
*
49-
* @deprecated Use {@link ReconcileUtils} that contains the more efficient up-to-date versions of
50-
* the target utils.
49+
* @deprecated Use {@link Context#resourceOperations()} that contains the more efficient up-to-date
50+
* versions of methods.
5151
*/
5252
@Deprecated(forRemoval = true)
5353
public class PrimaryUpdateAndCacheUtils {

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ReconcileUtils.java renamed to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceOperations.java

Lines changed: 225 additions & 165 deletions
Large diffs are not rendered by default.

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

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import io.javaoperatorsdk.operator.api.reconciler.Context;
3232
import io.javaoperatorsdk.operator.api.reconciler.DefaultContext;
3333
import io.javaoperatorsdk.operator.api.reconciler.DeleteControl;
34-
import io.javaoperatorsdk.operator.api.reconciler.ReconcileUtils;
3534
import io.javaoperatorsdk.operator.api.reconciler.RetryInfo;
3635
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
3736
import io.javaoperatorsdk.operator.processing.Controller;
@@ -73,13 +72,14 @@ public ReconciliationDispatcher(Controller<P> controller) {
7372
public PostExecutionControl<P> handleExecution(ExecutionScope<P> executionScope) {
7473
validateExecutionScope(executionScope);
7574
try {
76-
return handleDispatch(executionScope);
75+
return handleDispatch(executionScope, null);
7776
} catch (Exception e) {
7877
return PostExecutionControl.exceptionDuringExecution(e);
7978
}
8079
}
8180

82-
private PostExecutionControl<P> handleDispatch(ExecutionScope<P> executionScope)
81+
// visible for testing
82+
PostExecutionControl<P> handleDispatch(ExecutionScope<P> executionScope, Context<P> context)
8383
throws Exception {
8484
P originalResource = executionScope.getResource();
8585
var resourceForExecution = cloneResource(originalResource);
@@ -98,13 +98,16 @@ && shouldNotDispatchToCleanupWhenMarkedForDeletion(originalResource)) {
9898
originalResource.getMetadata().getFinalizers());
9999
return PostExecutionControl.defaultDispatch();
100100
}
101-
Context<P> context =
102-
new DefaultContext<>(
103-
executionScope.getRetryInfo(),
104-
controller,
105-
resourceForExecution,
106-
executionScope.isDeleteEvent(),
107-
executionScope.isDeleteFinalStateUnknown());
101+
// context can be provided only for testing purposes
102+
context =
103+
context == null
104+
? new DefaultContext<>(
105+
executionScope.getRetryInfo(),
106+
controller,
107+
resourceForExecution,
108+
executionScope.isDeleteEvent(),
109+
executionScope.isDeleteFinalStateUnknown())
110+
: context;
108111

109112
// checking the cleaner for all-event-mode
110113
if (!triggerOnAllEvents() && markedForDeletion) {
@@ -137,9 +140,9 @@ private PostExecutionControl<P> handleReconcile(
137140
*/
138141
P updatedResource;
139142
if (useSSA) {
140-
updatedResource = ReconcileUtils.addFinalizerWithSSA(context);
143+
updatedResource = context.resourceOperations().addFinalizerWithSSA();
141144
} else {
142-
updatedResource = ReconcileUtils.addFinalizer(context);
145+
updatedResource = context.resourceOperations().addFinalizer();
143146
}
144147
return PostExecutionControl.onlyFinalizerAdded(updatedResource)
145148
.withReSchedule(BaseControl.INSTANT_RESCHEDULE);
@@ -321,7 +324,7 @@ private PostExecutionControl<P> handleCleanup(
321324
// cleanup is finished, nothing left to be done
322325
final var finalizerName = configuration().getFinalizerName();
323326
if (deleteControl.isRemoveFinalizer() && resourceForExecution.hasFinalizer(finalizerName)) {
324-
P customResource = ReconcileUtils.removeFinalizer(context);
327+
P customResource = context.resourceOperations().removeFinalizer();
325328
return PostExecutionControl.customResourceFinalizerRemoved(customResource);
326329
}
327330
}
@@ -387,9 +390,9 @@ public R patchResource(Context<R> context, R resource, R originalResource) {
387390
resource.getMetadata().getResourceVersion());
388391
}
389392
if (useSSA) {
390-
return ReconcileUtils.serverSideApplyPrimary(context, resource);
393+
return context.resourceOperations().serverSideApplyPrimary(resource);
391394
} else {
392-
return ReconcileUtils.jsonPatchPrimary(context, originalResource, r -> resource);
395+
return context.resourceOperations().jsonPatchPrimary(originalResource, r -> resource);
393396
}
394397
}
395398

@@ -399,7 +402,7 @@ public R patchStatus(Context<R> context, R resource, R originalResource) {
399402
var managedFields = resource.getMetadata().getManagedFields();
400403
try {
401404
resource.getMetadata().setManagedFields(null);
402-
return ReconcileUtils.serverSideApplyPrimaryStatus(context, resource);
405+
return context.resourceOperations().serverSideApplyPrimaryStatus(resource);
403406
} finally {
404407
resource.getMetadata().setManagedFields(managedFields);
405408
}
@@ -416,13 +419,14 @@ private R editStatus(Context<R> context, R resource, R originalResource) {
416419
try {
417420
clonedOriginal.getMetadata().setResourceVersion(null);
418421
resource.getMetadata().setResourceVersion(null);
419-
return ReconcileUtils.jsonPatchPrimaryStatus(
420-
context,
421-
clonedOriginal,
422-
r -> {
423-
ReconcilerUtilsInternal.setStatus(r, ReconcilerUtilsInternal.getStatus(resource));
424-
return r;
425-
});
422+
return context
423+
.resourceOperations()
424+
.jsonPatchPrimaryStatus(
425+
clonedOriginal,
426+
r -> {
427+
ReconcilerUtilsInternal.setStatus(r, ReconcilerUtilsInternal.getStatus(resource));
428+
return r;
429+
});
426430
} finally {
427431
// restore initial resource version
428432
clonedOriginal.getMetadata().setResourceVersion(resourceVersion);

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/reconciler/ReconcileUtilsTest.java renamed to operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/reconciler/ResourceOperationsTest.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@
3636

3737
import static org.assertj.core.api.Assertions.assertThat;
3838
import static org.junit.jupiter.api.Assertions.*;
39-
import static org.mockito.ArgumentMatchers.any;
4039
import static org.mockito.Mockito.*;
4140

42-
class ReconcileUtilsTest {
41+
class ResourceOperationsTest {
4342

4443
private static final String FINALIZER_NAME = "test.javaoperatorsdk.io/finalizer";
4544

@@ -49,6 +48,7 @@ class ReconcileUtilsTest {
4948
private Resource resourceOp;
5049
private ControllerEventSource<TestCustomResource> controllerEventSource;
5150
private ControllerConfiguration<TestCustomResource> controllerConfiguration;
51+
private ResourceOperations<TestCustomResource> resourceOperations;
5252

5353
@BeforeEach
5454
@SuppressWarnings("unchecked")
@@ -71,6 +71,8 @@ void setupMocks() {
7171
when(client.resources(TestCustomResource.class)).thenReturn(mixedOperation);
7272
when(mixedOperation.inNamespace(any())).thenReturn(mixedOperation);
7373
when(mixedOperation.withName(any())).thenReturn(resourceOp);
74+
75+
resourceOperations = new ResourceOperations<>(context);
7476
}
7577

7678
@Test
@@ -91,7 +93,7 @@ void addsFinalizer() {
9193
return res;
9294
});
9395

94-
var result = ReconcileUtils.addFinalizer(context, FINALIZER_NAME);
96+
var result = resourceOperations.addFinalizer(FINALIZER_NAME);
9597

9698
assertThat(result).isNotNull();
9799
assertThat(result.hasFinalizer(FINALIZER_NAME)).isTrue();
@@ -118,7 +120,7 @@ void addsFinalizerWithSSA() {
118120
return res;
119121
});
120122

121-
var result = ReconcileUtils.addFinalizerWithSSA(context, FINALIZER_NAME);
123+
var result = resourceOperations.addFinalizerWithSSA(FINALIZER_NAME);
122124

123125
assertThat(result).isNotNull();
124126
assertThat(result.hasFinalizer(FINALIZER_NAME)).isTrue();
@@ -146,7 +148,7 @@ void removesFinalizer() {
146148
return res;
147149
});
148150

149-
var result = ReconcileUtils.removeFinalizer(context, FINALIZER_NAME);
151+
var result = resourceOperations.removeFinalizer(FINALIZER_NAME);
150152

151153
assertThat(result).isNotNull();
152154
assertThat(result.hasFinalizer(FINALIZER_NAME)).isFalse();
@@ -177,7 +179,7 @@ void retriesAddingFinalizerWithoutSSA() {
177179
// Return fresh resource on retry
178180
when(resourceOp.get()).thenReturn(resource);
179181

180-
var result = ReconcileUtils.addFinalizer(context, FINALIZER_NAME);
182+
var result = resourceOperations.addFinalizer(FINALIZER_NAME);
181183

182184
assertThat(result).isNotNull();
183185
assertThat(result.hasFinalizer(FINALIZER_NAME)).isTrue();
@@ -202,7 +204,7 @@ void nullResourceIsGracefullyHandledOnFinalizerRemovalRetry() {
202204
// Return null on retry (resource was deleted)
203205
when(resourceOp.get()).thenReturn(null);
204206

205-
ReconcileUtils.removeFinalizer(context, FINALIZER_NAME);
207+
resourceOperations.removeFinalizer(FINALIZER_NAME);
206208

207209
verify(controllerEventSource, times(1))
208210
.eventFilteringUpdateAndCacheResource(any(), any(UnaryOperator.class));
@@ -235,7 +237,7 @@ void retriesFinalizerRemovalWithFreshResource() {
235237
freshResource.addFinalizer(FINALIZER_NAME);
236238
when(resourceOp.get()).thenReturn(freshResource);
237239

238-
var result = ReconcileUtils.removeFinalizer(context, FINALIZER_NAME);
240+
var result = resourceOperations.removeFinalizer(FINALIZER_NAME);
239241

240242
assertThat(result).isNotNull();
241243
assertThat(result.getMetadata().getResourceVersion()).isEqualTo("3");
@@ -262,7 +264,7 @@ void resourcePatchWithSingleEventSource() {
262264
when(managedEventSource.eventFilteringUpdateAndCacheResource(any(), any(UnaryOperator.class)))
263265
.thenReturn(updatedResource);
264266

265-
var result = ReconcileUtils.resourcePatch(context, resource, UnaryOperator.identity());
267+
var result = resourceOperations.resourcePatch(resource, UnaryOperator.identity());
266268

267269
assertThat(result).isNotNull();
268270
assertThat(result.getMetadata().getResourceVersion()).isEqualTo("2");
@@ -282,7 +284,7 @@ void resourcePatchThrowsWhenNoEventSourceFound() {
282284
var exception =
283285
assertThrows(
284286
IllegalStateException.class,
285-
() -> ReconcileUtils.resourcePatch(context, resource, UnaryOperator.identity()));
287+
() -> resourceOperations.resourcePatch(resource, UnaryOperator.identity()));
286288

287289
assertThat(exception.getMessage()).contains("No event source found for type");
288290
}
@@ -301,7 +303,7 @@ void resourcePatchThrowsWhenMultipleEventSourcesFound() {
301303
var exception =
302304
assertThrows(
303305
IllegalStateException.class,
304-
() -> ReconcileUtils.resourcePatch(context, resource, UnaryOperator.identity()));
306+
() -> resourceOperations.resourcePatch(resource, UnaryOperator.identity()));
305307

306308
assertThat(exception.getMessage()).contains("Multiple event sources found for");
307309
assertThat(exception.getMessage()).contains("please provide the target event source");
@@ -320,7 +322,7 @@ void resourcePatchThrowsWhenEventSourceIsNotManagedInformer() {
320322
var exception =
321323
assertThrows(
322324
IllegalStateException.class,
323-
() -> ReconcileUtils.resourcePatch(context, resource, UnaryOperator.identity()));
325+
() -> resourceOperations.resourcePatch(resource, UnaryOperator.identity()));
324326

325327
assertThat(exception.getMessage()).contains("Target event source must be a subclass off");
326328
assertThat(exception.getMessage()).contains("ManagedInformerEventSource");

0 commit comments

Comments
 (0)