Skip to content

Commit 905ac9d

Browse files
committed
refinements based upon review feedback
moving handling of known resource versions, and making the config names more descriptive Signed-off-by: Steve Hawkins <[email protected]>
1 parent 05d7951 commit 905ac9d

File tree

8 files changed

+53
-48
lines changed

8 files changed

+53
-48
lines changed

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -365,20 +365,20 @@ default Set<Class<? extends HasMetadata>> defaultNonSSAResource() {
365365
}
366366

367367
/**
368-
* If an annotation should be used so that the operator sdk can detect events from its own updates
368+
* If a javaoperatorsdk.io/previous annotation should be used so that the operator sdk can detect events from its own updates
369369
* of dependent resources and then filter them.
370370
* <p>
371371
* Disable this if you want to react to your own dependent resource updates
372372
*
373373
* @since 4.5.0
374374
*/
375-
default boolean previousAnnotationForDependentResources() {
375+
default boolean previousAnnotationForDependentResourcesEventFiltering() {
376376
return true;
377377
}
378378

379379
/**
380-
* If the event logic should parse the resourceVersion to determine the ordering of events. This
381-
* is typically not needed.
380+
* If the event logic should parse the resourceVersion to determine the ordering of dependent
381+
* resource events. This is typically not needed.
382382
* <p>
383383
* Disabled by default as Kubernetes does not support, and discourages, this interpretation of
384384
* resourceVersions. Enable only if your api server event processing seems to lag the operator
@@ -387,7 +387,7 @@ default boolean previousAnnotationForDependentResources() {
387387
*
388388
* @since 4.5.0
389389
*/
390-
default boolean parseResourceVersions() {
390+
default boolean parseResourceVersionsForEventFilteringAndCaching() {
391391
return false;
392392
}
393393

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -286,17 +286,17 @@ public Set<Class<? extends HasMetadata>> defaultNonSSAResource() {
286286
}
287287

288288
@Override
289-
public boolean previousAnnotationForDependentResources() {
289+
public boolean previousAnnotationForDependentResourcesEventFiltering() {
290290
return previousAnnotationForDependentResources != null
291291
? previousAnnotationForDependentResources
292-
: super.previousAnnotationForDependentResources();
292+
: super.previousAnnotationForDependentResourcesEventFiltering();
293293
}
294294

295295
@Override
296-
public boolean parseResourceVersions() {
296+
public boolean parseResourceVersionsForEventFilteringAndCaching() {
297297
return parseResourceVersions != null
298298
? parseResourceVersions
299-
: super.parseResourceVersions();
299+
: super.parseResourceVersionsForEventFilteringAndCaching();
300300
}
301301
};
302302
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ protected boolean useSSA(Context<P> context) {
211211

212212
private boolean usePreviousAnnotation(Context<P> context) {
213213
return context.getControllerConfiguration().getConfigurationService()
214-
.previousAnnotationForDependentResources();
214+
.previousAnnotationForDependentResourcesEventFiltering();
215215
}
216216

217217
@Override

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java

+2-20
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ public class InformerEventSource<R extends HasMetadata, P extends HasMetadata>
6969
extends ManagedInformerEventSource<R, P, InformerConfiguration<R>>
7070
implements ResourceEventHandler<R> {
7171

72-
private static final int MAX_RESOURCE_VERSIONS = 256;
73-
7472
public static String PREVIOUS_ANNOTATION_KEY = "javaoperatorsdk.io/previous";
7573

7674
private static final Logger log = LoggerFactory.getLogger(InformerEventSource.class);
@@ -80,12 +78,11 @@ public class InformerEventSource<R extends HasMetadata, P extends HasMetadata>
8078
private final PrimaryToSecondaryMapper<P> primaryToSecondaryMapper;
8179
private Map<String, Function<R, List<String>>> indexerBuffer = new HashMap<>();
8280
private final String id = UUID.randomUUID().toString();
83-
private final Set<String> knownResourceVersions;
8481

8582
public InformerEventSource(
8683
InformerConfiguration<R> configuration, EventSourceContext<P> context) {
8784
this(configuration, context.getClient(),
88-
context.getControllerConfiguration().getConfigurationService().parseResourceVersions());
85+
context.getControllerConfiguration().getConfigurationService().parseResourceVersionsForEventFilteringAndCaching());
8986
}
9087

9188
public InformerEventSource(InformerConfiguration<R> configuration, KubernetesClient client) {
@@ -95,17 +92,6 @@ public InformerEventSource(InformerConfiguration<R> configuration, KubernetesCli
9592
public InformerEventSource(InformerConfiguration<R> configuration, KubernetesClient client,
9693
boolean parseResourceVersions) {
9794
super(client.resources(configuration.getResourceClass()), configuration, parseResourceVersions);
98-
if (parseResourceVersions) {
99-
knownResourceVersions = Collections.newSetFromMap(new LinkedHashMap<>() {
100-
@Override
101-
protected boolean removeEldestEntry(java.util.Map.Entry<String, Boolean> eldest) {
102-
return size() >= MAX_RESOURCE_VERSIONS;
103-
}
104-
});
105-
} else {
106-
knownResourceVersions = null;
107-
}
108-
10995
// If there is a primary to secondary mapper there is no need for primary to secondary index.
11096
primaryToSecondaryMapper = configuration.getPrimaryToSecondaryMapper();
11197
if (primaryToSecondaryMapper == null) {
@@ -188,8 +174,7 @@ private synchronized void onAddOrUpdate(Operation operation, R newObject, R oldO
188174
}
189175

190176
private boolean canSkipEvent(R newObject, R oldObject, ResourceID resourceID) {
191-
if (knownResourceVersions != null
192-
&& knownResourceVersions.contains(newObject.getMetadata().getResourceVersion())) {
177+
if (temporaryResourceCache.isKnownResourceVersion(newObject)) {
193178
return true;
194179
}
195180
var res = temporaryResourceCache.getResourceFromCache(resourceID);
@@ -285,9 +270,6 @@ public synchronized void handleRecentResourceCreate(ResourceID resourceID, R res
285270

286271
private void handleRecentCreateOrUpdate(Operation operation, R newResource, R oldResource) {
287272
primaryToSecondaryIndex.onAddOrUpdate(newResource);
288-
if (knownResourceVersions != null) {
289-
knownResourceVersions.add(newResource.getMetadata().getResourceVersion());
290-
}
291273
temporaryResourceCache.putResource(newResource, Optional.ofNullable(oldResource)
292274
.map(r -> r.getMetadata().getResourceVersion()).orElse(null));
293275
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/TemporaryResourceCache.java

+22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.javaoperatorsdk.operator.processing.event.source.informer;
22

3+
import java.util.Collections;
4+
import java.util.LinkedHashMap;
35
import java.util.Map;
46
import java.util.Optional;
7+
import java.util.Set;
58
import java.util.concurrent.ConcurrentHashMap;
69

710
import org.slf4j.Logger;
@@ -34,15 +37,27 @@
3437
public class TemporaryResourceCache<T extends HasMetadata> {
3538

3639
private static final Logger log = LoggerFactory.getLogger(TemporaryResourceCache.class);
40+
private static final int MAX_RESOURCE_VERSIONS = 256;
3741

3842
private final Map<ResourceID, T> cache = new ConcurrentHashMap<>();
3943
private final ManagedInformerEventSource<T, ?, ?> managedInformerEventSource;
4044
private final boolean parseResourceVersions;
45+
private final Set<String> knownResourceVersions;
4146

4247
public TemporaryResourceCache(ManagedInformerEventSource<T, ?, ?> managedInformerEventSource,
4348
boolean parseResourceVersions) {
4449
this.managedInformerEventSource = managedInformerEventSource;
4550
this.parseResourceVersions = parseResourceVersions;
51+
if (parseResourceVersions) {
52+
knownResourceVersions = Collections.newSetFromMap(new LinkedHashMap<String, Boolean>() {
53+
@Override
54+
protected boolean removeEldestEntry(java.util.Map.Entry<String, Boolean> eldest) {
55+
return size() >= MAX_RESOURCE_VERSIONS;
56+
}
57+
});
58+
} else {
59+
knownResourceVersions = null;
60+
}
4661
}
4762

4863
public synchronized void onEvent(T resource, boolean unknownState) {
@@ -62,6 +77,9 @@ public synchronized void putAddedResource(T newResource) {
6277
* @param previousResourceVersion null indicates an add
6378
*/
6479
public synchronized void putResource(T newResource, String previousResourceVersion) {
80+
if (knownResourceVersions != null) {
81+
knownResourceVersions.add(newResource.getMetadata().getResourceVersion());
82+
}
6583
var resourceId = ResourceID.fromResource(newResource);
6684
var cachedResource = getResourceFromCache(resourceId)
6785
.orElse(managedInformerEventSource.get(resourceId).orElse(null));
@@ -79,6 +97,10 @@ public synchronized void putResource(T newResource, String previousResourceVersi
7997
}
8098
}
8199

100+
public boolean isKnownResourceVersion(T resource) {
101+
return knownResourceVersions != null && knownResourceVersions.contains(resource.getMetadata().getResourceVersion());
102+
}
103+
82104
/**
83105
* @return true if {@link InformerConfiguration#parseResourceVersions()} is enabled and the
84106
* resourceVersion of newResource is numerically greater than cachedResource, otherwise

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,15 @@ void removesResourceFromCache() {
9191
void resourceVersionParsing() {
9292
this.temporaryResourceCache = new TemporaryResourceCache<>(informerEventSource, true);
9393

94+
assertThat(temporaryResourceCache.isKnownResourceVersion(testResource())).isFalse();
95+
9496
ConfigMap testResource = propagateTestResourceToCache();
9597

9698
// an event with a newer version will not remove
97-
temporaryResourceCache.onEvent(new ConfigMapBuilder(testResource()).editMetadata()
99+
temporaryResourceCache.onEvent(new ConfigMapBuilder(testResource).editMetadata()
98100
.withResourceVersion("1").endMetadata().build(), false);
99101

102+
assertThat(temporaryResourceCache.isKnownResourceVersion(testResource)).isTrue();
100103
assertThat(temporaryResourceCache.getResourceFromCache(ResourceID.fromResource(testResource)))
101104
.isPresent();
102105

operator-framework/src/test/java/io/javaoperatorsdk/operator/CreateUpdateInformerEventSourceEventFilterIT.java

+11-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package io.javaoperatorsdk.operator;
22

3-
import java.time.Duration;
4-
5-
import org.junit.jupiter.api.Test;
6-
import org.junit.jupiter.api.extension.RegisterExtension;
7-
83
import io.fabric8.kubernetes.api.model.ConfigMap;
94
import io.fabric8.kubernetes.api.model.ObjectMeta;
105
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
116
import io.javaoperatorsdk.operator.sample.createupdateeventfilter.CreateUpdateEventFilterTestCustomResource;
127
import io.javaoperatorsdk.operator.sample.createupdateeventfilter.CreateUpdateEventFilterTestCustomResourceSpec;
138
import io.javaoperatorsdk.operator.sample.createupdateeventfilter.CreateUpdateEventFilterTestReconciler;
9+
import org.junit.jupiter.api.Test;
10+
import org.junit.jupiter.api.extension.RegisterExtension;
11+
12+
import java.time.Duration;
1413

1514
import static io.javaoperatorsdk.operator.sample.createupdateeventfilter.CreateUpdateEventFilterTestReconciler.CONFIG_MAP_TEST_DATA_KEY;
1615
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,19 +30,19 @@ void updateEventNotReceivedAfterCreateOrUpdate() {
3130
var createdResource =
3231
operator.create(resource);
3332

34-
assertData(operator, createdResource, 1);
33+
assertData(operator, createdResource, 1, 1);
3534

3635
CreateUpdateEventFilterTestCustomResource actualCreatedResource =
3736
operator.get(CreateUpdateEventFilterTestCustomResource.class,
3837
resource.getMetadata().getName());
3938
actualCreatedResource.getSpec().setValue("2");
4039
operator.replace(actualCreatedResource);
4140

42-
assertData(operator, actualCreatedResource, 2);
41+
assertData(operator, actualCreatedResource, 2, 2);
4342
}
4443

4544
static void assertData(LocallyRunOperatorExtension operator,
46-
CreateUpdateEventFilterTestCustomResource resource, int executions) {
45+
CreateUpdateEventFilterTestCustomResource resource, int minExecutions, int maxExecutions) {
4746
await()
4847
.atMost(Duration.ofSeconds(1))
4948
.until(() -> {
@@ -56,10 +55,10 @@ static void assertData(LocallyRunOperatorExtension operator,
5655
.equals(resource.getSpec().getValue());
5756
});
5857

59-
assertThat(
60-
((CreateUpdateEventFilterTestReconciler) operator.getFirstReconciler())
61-
.getNumberOfExecutions())
62-
.isEqualTo(executions);
58+
int numberOfExecutions = ((CreateUpdateEventFilterTestReconciler) operator.getFirstReconciler())
59+
.getNumberOfExecutions();
60+
assertThat(numberOfExecutions).isGreaterThanOrEqualTo(minExecutions);
61+
assertThat(numberOfExecutions).isLessThanOrEqualTo(maxExecutions);
6362
}
6463

6564
static CreateUpdateEventFilterTestCustomResource prepareTestResource() {

operator-framework/src/test/java/io/javaoperatorsdk/operator/PreviousAnnotationDisabledIT.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package io.javaoperatorsdk.operator;
22

3-
import org.junit.jupiter.api.Test;
4-
import org.junit.jupiter.api.extension.RegisterExtension;
5-
63
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
74
import io.javaoperatorsdk.operator.sample.createupdateeventfilter.CreateUpdateEventFilterTestCustomResource;
85
import io.javaoperatorsdk.operator.sample.createupdateeventfilter.CreateUpdateEventFilterTestReconciler;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.RegisterExtension;
98

109
class PreviousAnnotationDisabledIT {
1110

@@ -24,15 +23,15 @@ void updateEventReceivedAfterCreateOrUpdate() {
2423
var createdResource =
2524
operator.create(resource);
2625

27-
CreateUpdateInformerEventSourceEventFilterIT.assertData(operator, createdResource, 2);
26+
CreateUpdateInformerEventSourceEventFilterIT.assertData(operator, createdResource, 1, 2);
2827

2928
CreateUpdateEventFilterTestCustomResource actualCreatedResource =
3029
operator.get(CreateUpdateEventFilterTestCustomResource.class,
3130
resource.getMetadata().getName());
3231
actualCreatedResource.getSpec().setValue("2");
3332
operator.replace(actualCreatedResource);
3433

35-
CreateUpdateInformerEventSourceEventFilterIT.assertData(operator, actualCreatedResource, 4);
34+
CreateUpdateInformerEventSourceEventFilterIT.assertData(operator, actualCreatedResource, 2, 4);
3635
}
3736

3837
}

0 commit comments

Comments
 (0)