Skip to content

Commit 0c28244

Browse files
author
attila.meszaros
committed
- generation aware impl different approach
1 parent 120b703 commit 0c28244

File tree

6 files changed

+53
-8
lines changed

6 files changed

+53
-8
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ static String getDefaultFinalizer(ResourceController controller) {
2828
return getAnnotation(controller).finalizerName();
2929
}
3030

31+
static boolean getGenerationEventProcessing(ResourceController controller) {
32+
return getAnnotation(controller).generationAwareEventProcessing();
33+
}
34+
3135
static <R extends CustomResource> Class<R> getCustomResourceClass(ResourceController controller) {
3236
return (Class<R>) getAnnotation(controller).customResourceClass();
3337
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.containersolutions.operator;
22

3+
import com.github.containersolutions.operator.api.Controller;
34
import com.github.containersolutions.operator.api.ResourceController;
45
import com.github.containersolutions.operator.processing.EventDispatcher;
56
import com.github.containersolutions.operator.processing.EventScheduler;
@@ -59,7 +60,7 @@ private <R extends CustomResource> void registerController(ResourceController<R>
5960
String finalizer = getDefaultFinalizer(controller);
6061
MixedOperation client = k8sClient.customResources(crd, resClass, CustomResourceList.class, getCustomResourceDoneableClass(controller));
6162
EventDispatcher eventDispatcher = new EventDispatcher(controller,
62-
finalizer, new EventDispatcher.CustomResourceFacade(client));
63+
finalizer, new EventDispatcher.CustomResourceFacade(client), ControllerUtils.getGenerationEventProcessing(controller));
6364
EventScheduler eventScheduler = new EventScheduler(eventDispatcher, retry, finalizer);
6465
registerWatches(controller, client, resClass, watchAllNamespaces, targetNamespaces, eventScheduler);
6566
}

operator-framework/src/main/java/com/github/containersolutions/operator/api/Controller.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,11 @@
1919

2020
String finalizerName() default DEFAULT_FINALIZER;
2121

22+
/**
23+
* If true, will process new event only if generation increased since the last processing, otherwise will
24+
* process all events.
25+
* See generation meta attribute
26+
* <a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#status-subresource">here</a>
27+
*/
28+
boolean generationAwareEventProcessing() default false;
2229
}

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

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import org.slf4j.LoggerFactory;
1111

1212
import java.util.ArrayList;
13+
import java.util.Map;
14+
import java.util.concurrent.ConcurrentHashMap;
1315

1416
/**
1517
* Dispatches events to the Controller and handles Finalizers for a single type of Custom Resource.
@@ -21,13 +23,16 @@ public class EventDispatcher {
2123
private final ResourceController controller;
2224
private final String resourceDefaultFinalizer;
2325
private final CustomResourceFacade customResourceFacade;
26+
private final boolean generationAware;
27+
private final Map<String, Long> lastGenerationProcessedSuccessfully = new ConcurrentHashMap<>();
2428

2529
public EventDispatcher(ResourceController controller,
2630
String defaultFinalizer,
27-
CustomResourceFacade customResourceFacade) {
31+
CustomResourceFacade customResourceFacade, boolean generationAware) {
2832
this.controller = controller;
2933
this.customResourceFacade = customResourceFacade;
3034
this.resourceDefaultFinalizer = defaultFinalizer;
35+
this.generationAware = generationAware;
3136
}
3237

3338
public void handleEvent(CustomResourceEvent event) {
@@ -47,6 +52,7 @@ public void handleEvent(CustomResourceEvent event) {
4752
if (removeFinalizer && ControllerUtils.hasDefaultFinalizer(resource, resourceDefaultFinalizer)) {
4853
removeDefaultFinalizer(resource);
4954
}
55+
cleanup(resource);
5056
} else {
5157
if (!ControllerUtils.hasDefaultFinalizer(resource, resourceDefaultFinalizer) && !markedForDeletion(resource)) {
5258
/* We always add the default finalizer if missing and not marked for deletion.
@@ -56,16 +62,42 @@ public void handleEvent(CustomResourceEvent event) {
5662
*/
5763
updateCustomResourceWithFinalizer(resource);
5864
} else {
59-
UpdateControl<? extends CustomResource> updateControl = controller.createOrUpdateResource(resource, context);
60-
if (updateControl.isUpdateStatusSubResource()) {
61-
customResourceFacade.updateStatus(updateControl.getCustomResource());
62-
} else if (updateControl.isUpdateCustomResource()) {
63-
updateCustomResource(updateControl.getCustomResource());
65+
if (!generationAware || largerGenerationThenProcessedBefore(resource)) {
66+
UpdateControl<? extends CustomResource> updateControl = controller.createOrUpdateResource(resource, context);
67+
if (updateControl.isUpdateStatusSubResource()) {
68+
customResourceFacade.updateStatus(updateControl.getCustomResource());
69+
} else if (updateControl.isUpdateCustomResource()) {
70+
updateCustomResource(updateControl.getCustomResource());
71+
}
72+
markLastGenerationProcessed(resource);
73+
} else {
74+
log.debug("Skipping processing since generation not increased. Event: {}", event);
6475
}
6576
}
6677
}
6778
}
6879

80+
public boolean largerGenerationThenProcessedBefore(CustomResource resource) {
81+
Long lastGeneration = lastGenerationProcessedSuccessfully.get(resource.getMetadata().getUid());
82+
if (lastGeneration == null) {
83+
return true;
84+
} else {
85+
return resource.getMetadata().getGeneration() > lastGeneration;
86+
}
87+
}
88+
89+
private void cleanup(CustomResource resource) {
90+
if (generationAware) {
91+
lastGenerationProcessedSuccessfully.remove(resource.getMetadata().getUid());
92+
}
93+
}
94+
95+
private void markLastGenerationProcessed(CustomResource resource) {
96+
if (generationAware) {
97+
lastGenerationProcessedSuccessfully.put(resource.getMetadata().getUid(), resource.getMetadata().getGeneration());
98+
}
99+
}
100+
69101
private void updateCustomResourceWithFinalizer(CustomResource resource) {
70102
log.debug("Adding finalizer for resource: {} version: {}", resource.getMetadata().getName(),
71103
resource.getMetadata().getResourceVersion());

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public void returnsValuesFromControllerAnnotationFinalizer() {
1717
assertEquals(DEFAULT_FINALIZER, ControllerUtils.getDefaultFinalizer(new TestCustomResourceController(null)));
1818
assertEquals(TestCustomResource.class, ControllerUtils.getCustomResourceClass(new TestCustomResourceController(null)));
1919
assertEquals(CRD_NAME, ControllerUtils.getCrdName(new TestCustomResourceController(null)));
20+
assertEquals(false, ControllerUtils.getGenerationEventProcessing(new TestCustomResourceController(null)));
2021
assertTrue(CustomResourceDoneable.class.isAssignableFrom(ControllerUtils.getCustomResourceDoneableClass(new TestCustomResourceController(null))));
2122
}
2223
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class EventDispatcherTest {
2727
@BeforeEach
2828
void setup() {
2929
eventDispatcher = new EventDispatcher(resourceController,
30-
DEFAULT_FINALIZER, customResourceFacade);
30+
DEFAULT_FINALIZER, customResourceFacade, false);
3131

3232
testCustomResource = getResource();
3333

0 commit comments

Comments
 (0)