Skip to content

Commit 182c31c

Browse files
committed
wip
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent fde60f4 commit 182c31c

2 files changed

Lines changed: 39 additions & 3 deletions

File tree

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.fabric8.kubernetes.api.model.HasMetadata;
2626
import io.fabric8.kubernetes.client.KubernetesClient;
2727
import io.fabric8.kubernetes.client.informers.SharedIndexInformer;
28+
import io.javaoperatorsdk.operator.OperatorException;
2829

2930
@SuppressWarnings({"unchecked", "rawtypes"})
3031
public class AlwaysNewInformerPool extends AbstractInformerPool {
@@ -39,8 +40,21 @@ public <R extends HasMetadata> SharedIndexInformer<R> getInformer(
3940
String name,
4041
InformerClassifier<R> classifier,
4142
KubernetesClient client) {
43+
var key = new ClassifierWithName(controllerName, name, classifier);
44+
if (informers.containsKey(key)) {
45+
throw new OperatorException(
46+
"Informer already registered for controller: "
47+
+ controllerName
48+
+ ", event source: "
49+
+ name
50+
+ ", classifier: "
51+
+ classifier
52+
+ ". This pool creates a dedicated informer per controller/event source and never"
53+
+ " shares them, so requesting one twice for the same combination without releasing"
54+
+ " the previous one first would leak the earlier informer.");
55+
}
4256
var informer = createInformer(classifier, client);
43-
informers.put(new ClassifierWithName(controllerName, name, classifier), informer);
57+
informers.put(key, informer);
4458
return informer;
4559
}
4660

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020

2121
import io.fabric8.kubernetes.client.KubernetesClient;
2222
import io.javaoperatorsdk.operator.MockKubernetesClient;
23+
import io.javaoperatorsdk.operator.OperatorException;
2324
import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
2425
import io.javaoperatorsdk.operator.sample.simple.TestCustomResource;
2526

2627
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2729
import static org.mockito.Mockito.never;
2830
import static org.mockito.Mockito.times;
2931
import static org.mockito.Mockito.verify;
@@ -70,13 +72,33 @@ void createsSeparateInformerForDifferentEventSourceNames() {
7072
}
7173

7274
@Test
73-
void createsNewInformerEvenForAnIdenticalKey() {
75+
void throwsWhenRequestingAnInformerForAnAlreadyRegisteredKey() {
7476
var classifier = classifier("default");
7577

7678
pool.getInformer(CONTROLLER, ES_NAME, classifier, client);
79+
80+
// requesting the same controller+event source+classifier combination again without releasing
81+
// first would otherwise silently overwrite the map entry and leak the earlier informer
82+
assertThatThrownBy(() -> pool.getInformer(CONTROLLER, ES_NAME, classifier, client))
83+
.isInstanceOf(OperatorException.class)
84+
.hasMessageContaining(CONTROLLER)
85+
.hasMessageContaining(ES_NAME)
86+
.hasMessageContaining(classifier.toString());
87+
88+
// the earlier informer is left untouched, still registered exactly once
89+
assertThat(pool.size()).isEqualTo(1);
90+
verify(client, times(1)).resources(TestCustomResource.class);
91+
}
92+
93+
@Test
94+
void allowsReRequestingAnInformerAfterItWasReleased() {
95+
var classifier = classifier("default");
96+
pool.getInformer(CONTROLLER, ES_NAME, classifier, client);
97+
pool.releaseInformer(CONTROLLER, ES_NAME, classifier);
98+
99+
// must not throw: releasing frees up the key for reuse
77100
pool.getInformer(CONTROLLER, ES_NAME, classifier, client);
78101

79-
// the same key overwrites the map entry, but a fresh informer is created on every call
80102
assertThat(pool.size()).isEqualTo(1);
81103
verify(client, times(2)).resources(TestCustomResource.class);
82104
}

0 commit comments

Comments
 (0)