Skip to content

Commit a62a914

Browse files
authored
Merge pull request operator-framework#62 from ContainerSolutions/resource_replace_namespace_handling
fix for issues, when we are having different default namespace then custom resource namespace
2 parents 8f15883 + 0ee14b6 commit a62a914

File tree

3 files changed

+37
-26
lines changed

3 files changed

+37
-26
lines changed

operator-framework/src/main/java/com/github/containersolutions/operator/Operator.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,8 @@ private <R extends CustomResource> void registerController(ResourceController<R>
6262
Class<? extends CustomResourceList<R>> list = getCustomResourceListClass(controller);
6363
Class<? extends CustomResourceDoneable<R>> doneable = getCustomResourceDonebaleClass(controller);
6464
MixedOperation client = k8sClient.customResources(crd, resClass, list, doneable);
65-
66-
EventDispatcher eventDispatcher = new EventDispatcher(controller, (CustomResourceOperationsImpl) client,
67-
getDefaultFinalizer(controller));
65+
EventDispatcher eventDispatcher = new EventDispatcher(controller,
66+
getDefaultFinalizer(controller), new EventDispatcher.CustomResourceReplaceFacade(client));
6867
EventScheduler eventScheduler = new EventScheduler(eventDispatcher, retry);
6968
registerWatches(controller, client, resClass, watchAllNamespaces, targetNamespaces, eventScheduler);
7069
}

operator-framework/src/main/java/com/github/containersolutions/operator/processing/EventDispatcher.java

+25-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import com.github.containersolutions.operator.api.ResourceController;
44
import io.fabric8.kubernetes.client.CustomResource;
55
import io.fabric8.kubernetes.client.Watcher;
6-
import io.fabric8.kubernetes.client.dsl.internal.CustomResourceOperationsImpl;
6+
import io.fabric8.kubernetes.client.dsl.MixedOperation;
7+
import io.fabric8.kubernetes.client.dsl.Resource;
78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
910

@@ -18,15 +19,14 @@ public class EventDispatcher {
1819
private final static Logger log = LoggerFactory.getLogger(EventDispatcher.class);
1920

2021
private final ResourceController controller;
21-
private final CustomResourceOperationsImpl resourceOperation;
2222
private final String resourceDefaultFinalizer;
23+
private final CustomResourceReplaceFacade customResourceReplaceFacade;
2324

2425
public EventDispatcher(ResourceController controller,
25-
CustomResourceOperationsImpl resourceOperation,
26-
String defaultFinalizer
27-
) {
26+
String defaultFinalizer,
27+
CustomResourceReplaceFacade customResourceReplaceFacade) {
2828
this.controller = controller;
29-
this.resourceOperation = resourceOperation;
29+
this.customResourceReplaceFacade = customResourceReplaceFacade;
3030
this.resourceDefaultFinalizer = defaultFinalizer;
3131
}
3232

@@ -77,12 +77,12 @@ private boolean hasDefaultFinalizer(CustomResource resource) {
7777
private void removeDefaultFinalizer(CustomResource resource) {
7878
resource.getMetadata().getFinalizers().remove(resourceDefaultFinalizer);
7979
log.debug("Removed finalizer. Trying to replace resource {}, version: {}", resource.getMetadata().getName(), resource.getMetadata().getResourceVersion());
80-
resourceOperation.lockResourceVersion(resource.getMetadata().getResourceVersion()).replace(resource);
80+
customResourceReplaceFacade.replaceWithLock(resource);
8181
}
8282

8383
private void replace(CustomResource resource) {
8484
log.debug("Trying to replace resource {}, version: {}", resource.getMetadata().getName(), resource.getMetadata().getResourceVersion());
85-
resourceOperation.lockResourceVersion(resource.getMetadata().getResourceVersion()).replace(resource);
85+
customResourceReplaceFacade.replaceWithLock(resource);
8686
}
8787

8888
private void addFinalizerIfNotPresent(CustomResource resource) {
@@ -98,4 +98,21 @@ private void addFinalizerIfNotPresent(CustomResource resource) {
9898
private boolean markedForDeletion(CustomResource resource) {
9999
return resource.getMetadata().getDeletionTimestamp() != null && !resource.getMetadata().getDeletionTimestamp().isEmpty();
100100
}
101+
102+
// created to support unit testing
103+
public static class CustomResourceReplaceFacade {
104+
105+
private final MixedOperation<?, ?, ?, Resource<CustomResource, ?>> resourceOperation;
106+
107+
public CustomResourceReplaceFacade(MixedOperation<?, ?, ?, Resource<CustomResource, ?>> resourceOperation) {
108+
this.resourceOperation = resourceOperation;
109+
}
110+
111+
public CustomResource replaceWithLock(CustomResource resource) {
112+
return resourceOperation.inNamespace(resource.getMetadata().getNamespace())
113+
.withName(resource.getMetadata().getName())
114+
.lockResourceVersion(resource.getMetadata().getResourceVersion())
115+
.replace(resource);
116+
}
117+
}
101118
}

operator-framework/src/test/java/com/github/containersolutions/operator/EventDispatcherTest.java

+10-15
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
import com.github.containersolutions.operator.sample.TestCustomResource;
88
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
99
import io.fabric8.kubernetes.client.CustomResource;
10-
import io.fabric8.kubernetes.client.CustomResourceDoneable;
11-
import io.fabric8.kubernetes.client.CustomResourceList;
1210
import io.fabric8.kubernetes.client.Watcher;
13-
import io.fabric8.kubernetes.client.dsl.Replaceable;
14-
import io.fabric8.kubernetes.client.dsl.internal.CustomResourceOperationsImpl;
1511
import org.junit.jupiter.api.BeforeEach;
1612
import org.junit.jupiter.api.Test;
1713
import org.mockito.ArgumentMatchers;
@@ -27,19 +23,19 @@ class EventDispatcherTest {
2723
private CustomResource testCustomResource;
2824
private EventDispatcher eventDispatcher;
2925
private ResourceController<CustomResource> resourceController = mock(ResourceController.class);
30-
private CustomResourceOperationsImpl<CustomResource, CustomResourceList<CustomResource>,
31-
CustomResourceDoneable<CustomResource>> resourceOperation = mock(CustomResourceOperationsImpl.class);
26+
private EventDispatcher.CustomResourceReplaceFacade customResourceReplaceFacade = mock(EventDispatcher.CustomResourceReplaceFacade.class);
27+
3228

3329
@BeforeEach
3430
void setup() {
35-
eventDispatcher = new EventDispatcher(resourceController, resourceOperation,
36-
Controller.DEFAULT_FINALIZER);
31+
eventDispatcher = new EventDispatcher(resourceController,
32+
Controller.DEFAULT_FINALIZER, customResourceReplaceFacade);
3733

3834
testCustomResource = getResource();
3935

4036
when(resourceController.createOrUpdateResource(eq(testCustomResource))).thenReturn(Optional.of(testCustomResource));
4137
when(resourceController.deleteResource(eq(testCustomResource))).thenReturn(true);
42-
when(resourceOperation.lockResourceVersion(any())).thenReturn(mock(Replaceable.class));
38+
when(customResourceReplaceFacade.replaceWithLock(any())).thenReturn(null);
4339
}
4440

4541
@Test
@@ -92,7 +88,7 @@ void removesDefaultFinalizerOnDelete() {
9288
eventDispatcher.handleEvent(Watcher.Action.MODIFIED, testCustomResource);
9389

9490
assertEquals(0, testCustomResource.getMetadata().getFinalizers().size());
95-
verify(resourceOperation, times(1)).lockResourceVersion(any());
91+
verify(customResourceReplaceFacade, times(1)).replaceWithLock(any());
9692
}
9793

9894
@Test
@@ -104,7 +100,7 @@ void doesNotRemovesTheFinalizerIfTheDeleteMethodRemovesFalse() {
104100
eventDispatcher.handleEvent(Watcher.Action.MODIFIED, testCustomResource);
105101

106102
assertEquals(1, testCustomResource.getMetadata().getFinalizers().size());
107-
verify(resourceOperation, never()).lockResourceVersion(any());
103+
verify(customResourceReplaceFacade, never()).replaceWithLock(any());
108104
}
109105

110106
@Test
@@ -113,8 +109,7 @@ void doesNotUpdateTheResourceIfEmptyOptionalReturned() {
113109
when(resourceController.createOrUpdateResource(eq(testCustomResource))).thenReturn(Optional.empty());
114110

115111
eventDispatcher.handleEvent(Watcher.Action.MODIFIED, testCustomResource);
116-
117-
verify(resourceOperation, never()).lockResourceVersion(any());
112+
verify(customResourceReplaceFacade, never()).replaceWithLock(any());
118113
}
119114

120115
@Test
@@ -124,7 +119,7 @@ void addsFinalizerIfNotMarkedForDeletionAndEmptyCustomResourceReturned() {
124119
eventDispatcher.handleEvent(Watcher.Action.MODIFIED, testCustomResource);
125120

126121
assertEquals(1, testCustomResource.getMetadata().getFinalizers().size());
127-
verify(resourceOperation, times(1)).lockResourceVersion(any());
122+
verify(customResourceReplaceFacade, times(1)).replaceWithLock(any());
128123
}
129124

130125
@Test
@@ -135,7 +130,7 @@ void doesNotAddFinalizerIfOptionalIsReturnedButMarkedForDeletion() {
135130
eventDispatcher.handleEvent(Watcher.Action.MODIFIED, testCustomResource);
136131

137132
assertEquals(0, testCustomResource.getMetadata().getFinalizers().size());
138-
verify(resourceOperation, never()).lockResourceVersion(any());
133+
verify(customResourceReplaceFacade, never()).replaceWithLock(any());
139134
}
140135

141136
private void markForDeletion(CustomResource customResource) {

0 commit comments

Comments
 (0)