Skip to content

Commit 4f63a87

Browse files
committed
fix: test setups
1 parent fdd60bb commit 4f63a87

File tree

7 files changed

+88
-52
lines changed

7 files changed

+88
-52
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.concurrent.Callable;
66
import java.util.concurrent.ExecutionException;
77
import java.util.concurrent.ExecutorService;
8+
import java.util.concurrent.Executors;
89
import java.util.concurrent.Future;
910
import java.util.concurrent.TimeUnit;
1011
import java.util.concurrent.TimeoutException;
@@ -43,6 +44,12 @@ public static void stop() {
4344
instance = null;
4445
}
4546

47+
public static void useTestInstance() {
48+
if (instance == null) {
49+
instance = new ExecutorServiceManager(Executors.newFixedThreadPool(5), 1);
50+
}
51+
}
52+
4653
public static ExecutorServiceManager instance() {
4754
if (instance == null) {
4855
throw new IllegalStateException(

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ class ReconciliationDispatcher<R extends HasMetadata> {
2828
private final Controller<R> controller;
2929
private final CustomResourceFacade<R> customResourceFacade;
3030

31-
ReconciliationDispatcher(Controller<R> controller,
32-
CustomResourceFacade<R> customResourceFacade) {
31+
ReconciliationDispatcher(Controller<R> controller, CustomResourceFacade<R> customResourceFacade) {
3332
this.controller = controller;
3433
this.customResourceFacade = customResourceFacade;
3534
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.javaoperatorsdk.operator;
2+
3+
import io.fabric8.kubernetes.api.model.HasMetadata;
4+
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
5+
import io.fabric8.kubernetes.client.KubernetesClient;
6+
import io.fabric8.kubernetes.client.dsl.FilterWatchListDeletable;
7+
import io.fabric8.kubernetes.client.dsl.FilterWatchListMultiDeletable;
8+
import io.fabric8.kubernetes.client.dsl.MixedOperation;
9+
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
10+
import io.fabric8.kubernetes.client.dsl.Resource;
11+
import io.fabric8.kubernetes.client.informers.SharedIndexInformer;
12+
13+
import static org.mockito.ArgumentMatchers.anyLong;
14+
import static org.mockito.ArgumentMatchers.anyString;
15+
import static org.mockito.ArgumentMatchers.nullable;
16+
import static org.mockito.Mockito.mock;
17+
import static org.mockito.Mockito.when;
18+
19+
public class MockKubernetesClient {
20+
public static <T extends HasMetadata> KubernetesClient client(Class<T> clazz) {
21+
final var client = mock(KubernetesClient.class);
22+
MixedOperation<T, KubernetesResourceList<T>, Resource<T>> resources =
23+
mock(MixedOperation.class);
24+
NonNamespaceOperation<T, KubernetesResourceList<T>, Resource<T>> nonNamespaceOperation =
25+
mock(NonNamespaceOperation.class);
26+
FilterWatchListMultiDeletable<T, KubernetesResourceList<T>> inAnyNamespace = mock(
27+
FilterWatchListMultiDeletable.class);
28+
FilterWatchListDeletable<T, KubernetesResourceList<T>> filterable =
29+
mock(FilterWatchListDeletable.class);
30+
when(resources.inNamespace(anyString())).thenReturn(nonNamespaceOperation);
31+
when(nonNamespaceOperation.withLabelSelector(nullable(String.class))).thenReturn(filterable);
32+
when(resources.inAnyNamespace()).thenReturn(inAnyNamespace);
33+
when(inAnyNamespace.withLabelSelector(nullable(String.class))).thenReturn(filterable);
34+
SharedIndexInformer<T> informer = mock(SharedIndexInformer.class);
35+
when(filterable.runnableInformer(anyLong())).thenReturn(informer);
36+
when(client.resources(clazz)).thenReturn(resources);
37+
38+
39+
return client;
40+
}
41+
}

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/OperatorTest.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@
88
import io.fabric8.kubernetes.client.KubernetesClient;
99
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1010
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
11+
import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
1112
import io.javaoperatorsdk.operator.api.reconciler.Context;
1213
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
1314
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
1415

1516
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
1617
import static org.mockito.Mockito.mock;
17-
import static org.mockito.Mockito.verify;
1818
import static org.mockito.Mockito.when;
1919

2020
class OperatorTest {
2121

22-
private final KubernetesClient kubernetesClient = mock(KubernetesClient.class);
22+
private final KubernetesClient kubernetesClient =
23+
MockKubernetesClient.client(FooCustomResource.class);
2324
private final ConfigurationService configurationService = mock(ConfigurationService.class);
2425
private final ControllerConfiguration configuration = mock(ControllerConfiguration.class);
2526

@@ -33,16 +34,14 @@ public void shouldRegisterReconcilerToController() {
3334
when(configurationService.getConfigurationFor(fooReconciler)).thenReturn(configuration);
3435
when(configuration.watchAllNamespaces()).thenReturn(true);
3536
when(configuration.getName()).thenReturn("FOO");
36-
when(configuration.getResourceClass()).thenReturn(FooReconciler.class);
37+
when(configuration.getResourceClass()).thenReturn(FooCustomResource.class);
38+
when(configuration.getRetryConfiguration()).thenReturn(RetryConfiguration.DEFAULT);
39+
when(configuration.getConfigurationService()).thenReturn(configurationService);
3740

3841
// when
3942
operator.register(fooReconciler);
4043

4144
// then
42-
verify(configuration).watchAllNamespaces();
43-
verify(configuration).getName();
44-
verify(configuration).getResourceClass();
45-
4645
assertThat(operator.getControllers().size()).isEqualTo(1);
4746
assertThat(operator.getControllers().get(0).getReconciler()).isEqualTo(fooReconciler);
4847
}

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

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
import io.fabric8.kubernetes.api.model.HasMetadata;
1212
import io.fabric8.kubernetes.api.model.ObjectMeta;
1313
import io.fabric8.kubernetes.client.CustomResource;
14+
import io.javaoperatorsdk.operator.MockKubernetesClient;
1415
import io.javaoperatorsdk.operator.TestUtils;
1516
import io.javaoperatorsdk.operator.api.config.Cloner;
1617
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1718
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
19+
import io.javaoperatorsdk.operator.api.config.ExecutorServiceManager;
20+
import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
1821
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
1922
import io.javaoperatorsdk.operator.api.reconciler.*;
2023
import io.javaoperatorsdk.operator.processing.Controller;
@@ -37,37 +40,43 @@ class ReconciliationDispatcherTest {
3740
private ReconciliationDispatcher<TestCustomResource> reconciliationDispatcher;
3841
private final Reconciler<TestCustomResource> reconciler = mock(Reconciler.class,
3942
withSettings().extraInterfaces(ErrorStatusHandler.class));
40-
private final ControllerConfiguration<TestCustomResource> configuration =
41-
mock(ControllerConfiguration.class);
4243
private final ConfigurationService configService = mock(ConfigurationService.class);
4344
private final CustomResourceFacade<TestCustomResource> customResourceFacade =
4445
mock(ReconciliationDispatcher.CustomResourceFacade.class);
4546

4647
@BeforeEach
4748
void setup() {
49+
ExecutorServiceManager.useTestInstance();
4850
testCustomResource = TestUtils.testCustomResource();
4951
reconciliationDispatcher =
50-
init(testCustomResource, reconciler, configuration, customResourceFacade);
52+
init(testCustomResource, reconciler, null, customResourceFacade, true);
5153
}
5254

5355
private <R extends HasMetadata> ReconciliationDispatcher<R> init(R customResource,
5456
Reconciler<R> reconciler, ControllerConfiguration<R> configuration,
55-
CustomResourceFacade<R> customResourceFacade) {
56-
when(configuration.getFinalizer()).thenReturn(DEFAULT_FINALIZER);
57+
CustomResourceFacade<R> customResourceFacade, boolean useFinalizer) {
58+
configuration = configuration == null ? mock(ControllerConfiguration.class) : configuration;
59+
final var finalizer = useFinalizer ? DEFAULT_FINALIZER : Constants.NO_FINALIZER;
60+
when(configuration.getFinalizer()).thenReturn(finalizer);
5761
when(configuration.useFinalizer()).thenCallRealMethod();
5862
when(configuration.getName()).thenReturn("EventDispatcherTestController");
59-
when(configService.getMetrics()).thenReturn(Metrics.NOOP);
63+
when(configuration.getResourceClass()).thenReturn((Class<R>) customResource.getClass());
64+
when(configuration.getRetryConfiguration()).thenReturn(RetryConfiguration.DEFAULT);
6065
when(configuration.getConfigurationService()).thenReturn(configService);
66+
67+
when(configService.getMetrics()).thenReturn(Metrics.NOOP);
6168
when(configService.getResourceCloner()).thenReturn(new Cloner() {
6269
@Override
63-
public <R extends HasMetadata> R clone(R object) {
70+
71+
public <R extends HasMetadata> R clone(R object) {
6472
return object;
6573
}
6674
});
6775
when(reconciler.cleanup(eq(customResource), any()))
6876
.thenReturn(DeleteControl.defaultDelete());
69-
Controller<R> controller =
70-
new Controller<>(reconciler, configuration, null);
77+
Controller<R> controller = new Controller<>(reconciler, configuration,
78+
MockKubernetesClient.client(customResource.getClass()));
79+
controller.start();
7180

7281
return new ReconciliationDispatcher<>(controller, customResourceFacade);
7382
}
@@ -144,10 +153,12 @@ void callsDeleteIfObjectHasFinalizerAndMarkedForDelete() {
144153
*/
145154
@Test
146155
void callDeleteOnControllerIfMarkedForDeletionWhenNoFinalizerIsConfigured() {
147-
configureToNotUseFinalizer();
156+
final ReconciliationDispatcher<TestCustomResource> dispatcher =
157+
init(testCustomResource, reconciler,
158+
null, customResourceFacade, false);
148159
markForDeletion(testCustomResource);
149160

150-
reconciliationDispatcher.handleExecution(executionScopeWithCREvent(testCustomResource));
161+
dispatcher.handleExecution(executionScopeWithCREvent(testCustomResource));
151162

152163
verify(reconciler).cleanup(eq(testCustomResource), any());
153164
}
@@ -161,23 +172,13 @@ void doNotCallDeleteIfMarkedForDeletionWhenFinalizerHasAlreadyBeenRemoved() {
161172
verify(reconciler, never()).cleanup(eq(testCustomResource), any());
162173
}
163174

164-
private void configureToNotUseFinalizer() {
165-
ControllerConfiguration<HasMetadata> configuration =
166-
mock(ControllerConfiguration.class);
167-
when(configuration.getName()).thenReturn("EventDispatcherTestController");
168-
when(configService.getMetrics()).thenReturn(Metrics.NOOP);
169-
when(configuration.getConfigurationService()).thenReturn(configService);
170-
when(configuration.useFinalizer()).thenReturn(false);
171-
reconciliationDispatcher =
172-
new ReconciliationDispatcher(new Controller(reconciler, configuration, null),
173-
customResourceFacade);
174-
}
175-
176175
@Test
177176
void doesNotAddFinalizerIfConfiguredNotTo() {
178-
configureToNotUseFinalizer();
177+
final ReconciliationDispatcher<TestCustomResource> dispatcher =
178+
init(testCustomResource, reconciler,
179+
null, customResourceFacade, false);
179180

180-
reconciliationDispatcher.handleExecution(executionScopeWithCREvent(testCustomResource));
181+
dispatcher.handleExecution(executionScopeWithCREvent(testCustomResource));
181182

182183
assertEquals(0, testCustomResource.getMetadata().getFinalizers().size());
183184
}
@@ -316,7 +317,7 @@ void setObservedGenerationForStatusIfNeeded() {
316317
ControllerConfiguration<ObservedGenCustomResource> config =
317318
mock(ControllerConfiguration.class);
318319
CustomResourceFacade<ObservedGenCustomResource> facade = mock(CustomResourceFacade.class);
319-
var dispatcher = init(observedGenResource, reconciler, config, facade);
320+
var dispatcher = init(observedGenResource, reconciler, config, facade, true);
320321

321322
when(config.isGenerationAware()).thenReturn(true);
322323
when(reconciler.reconcile(any(), any()))
@@ -341,7 +342,7 @@ void updatesObservedGenerationOnNoUpdateUpdateControl() {
341342
when(reconciler.reconcile(any(), any()))
342343
.thenReturn(UpdateControl.noUpdate());
343344
when(facade.updateStatus(observedGenResource)).thenReturn(observedGenResource);
344-
var dispatcher = init(observedGenResource, reconciler, config, facade);
345+
var dispatcher = init(observedGenResource, reconciler, config, facade, true);
345346

346347
PostExecutionControl<ObservedGenCustomResource> control = dispatcher.handleExecution(
347348
executionScopeWithCREvent(observedGenResource));

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
1010
import io.fabric8.kubernetes.client.dsl.MixedOperation;
1111
import io.fabric8.kubernetes.client.dsl.Resource;
12+
import io.javaoperatorsdk.operator.MockKubernetesClient;
1213
import io.javaoperatorsdk.operator.TestUtils;
1314
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1415
import io.javaoperatorsdk.operator.api.config.DefaultControllerConfiguration;
@@ -28,7 +29,7 @@ class ControllerResourceEventSourceTest {
2829

2930
public static final String FINALIZER = "finalizer";
3031
private static final MixedOperation<TestCustomResource, KubernetesResourceList<TestCustomResource>, Resource<TestCustomResource>> client =
31-
mock(MixedOperation.class);
32+
MockKubernetesClient.client(TestCustomResource.class).resources(TestCustomResource.class);
3233
EventHandler eventHandler = mock(EventHandler.class);
3334
EventSourceRegistry registry = mock(EventSourceRegistry.class);
3435

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

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
import org.junit.jupiter.api.Test;
88

99
import io.fabric8.kubernetes.api.model.HasMetadata;
10-
import io.fabric8.kubernetes.api.model.KubernetesResourceList;
1110
import io.fabric8.kubernetes.api.model.ObjectMeta;
12-
import io.fabric8.kubernetes.client.dsl.MixedOperation;
13-
import io.fabric8.kubernetes.client.dsl.Resource;
11+
import io.javaoperatorsdk.operator.MockKubernetesClient;
1412
import io.javaoperatorsdk.operator.TestUtils;
1513
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1614
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
@@ -191,12 +189,7 @@ public ControllerConfig(String finalizer, boolean generationAware,
191189
private static class TestController extends Controller<TestCustomResource> {
192190

193191
public TestController(ControllerConfiguration<TestCustomResource> configuration) {
194-
super(null, configuration, null);
195-
}
196-
197-
@Override
198-
public MixedOperation<TestCustomResource, KubernetesResourceList<TestCustomResource>, Resource<TestCustomResource>> getCRClient() {
199-
return mock(MixedOperation.class);
192+
super(null, configuration, MockKubernetesClient.client(TestCustomResource.class));
200193
}
201194
}
202195

@@ -205,12 +198,7 @@ private static class ObservedGenController
205198

206199
public ObservedGenController(
207200
ControllerConfiguration<ObservedGenCustomResource> configuration) {
208-
super(null, configuration, null);
209-
}
210-
211-
@Override
212-
public MixedOperation<ObservedGenCustomResource, KubernetesResourceList<ObservedGenCustomResource>, Resource<ObservedGenCustomResource>> getCRClient() {
213-
return mock(MixedOperation.class);
201+
super(null, configuration, MockKubernetesClient.client(ObservedGenCustomResource.class));
214202
}
215203
}
216204
}

0 commit comments

Comments
 (0)