Skip to content

Commit 4107952

Browse files
authored
feat: sample with multiple informers for same type dependent resources (#1698)
1 parent ba0fedb commit 4107952

8 files changed

+284
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.javaoperatorsdk.operator;
2+
3+
import java.time.Duration;
4+
import java.util.stream.Collectors;
5+
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.RegisterExtension;
8+
9+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
10+
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
11+
import io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerCustomResource;
12+
import io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerReconciler;
13+
import io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerSpec;
14+
15+
import static io.javaoperatorsdk.operator.IntegrationTestConstants.GARBAGE_COLLECTION_TIMEOUT_SECONDS;
16+
import static io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerReconciler.DATA_KEY;
17+
import static org.assertj.core.api.Assertions.assertThat;
18+
import static org.awaitility.Awaitility.await;
19+
20+
class MultipleDependentSameTypeMultiInformerIT {
21+
22+
public static final String TEST_RESOURCE_NAME = "test1";
23+
public static final String DEFAULT_SPEC_VALUE = "val";
24+
public static final String UPDATED_SPEC_VALUE = "updated-val";
25+
public static final int SECONDS = 30;
26+
27+
@RegisterExtension
28+
LocallyRunOperatorExtension operator =
29+
LocallyRunOperatorExtension.builder()
30+
.withReconciler(new MultipleManagedDependentResourceMultiInformerReconciler())
31+
.build();
32+
33+
@Test
34+
void handlesCrudOperations() {
35+
operator.create(testResource());
36+
assertConfigMapsPresent(DEFAULT_SPEC_VALUE);
37+
38+
var updatedResource = testResource();
39+
updatedResource.getSpec().setValue(UPDATED_SPEC_VALUE);
40+
operator.replace(updatedResource);
41+
assertConfigMapsPresent(UPDATED_SPEC_VALUE);
42+
43+
operator.delete(testResource());
44+
assertConfigMapsDeleted();
45+
}
46+
47+
48+
private void assertConfigMapsPresent(String expectedData) {
49+
await().untilAsserted(() -> {
50+
var maps = operator.getKubernetesClient().configMaps()
51+
.inNamespace(operator.getNamespace()).list().getItems().stream()
52+
.filter(cm -> cm.getMetadata().getName().startsWith(TEST_RESOURCE_NAME))
53+
.collect(Collectors.toList());
54+
assertThat(maps).hasSize(2);
55+
assertThat(maps).allMatch(cm -> cm.getData().get(DATA_KEY).equals(expectedData));
56+
});
57+
}
58+
59+
private void assertConfigMapsDeleted() {
60+
await().atMost(Duration.ofSeconds(GARBAGE_COLLECTION_TIMEOUT_SECONDS)).untilAsserted(() -> {
61+
var maps = operator.getKubernetesClient().configMaps()
62+
.inNamespace(operator.getNamespace()).list().getItems().stream()
63+
.filter(cm -> cm.getMetadata().getName().startsWith(TEST_RESOURCE_NAME))
64+
.collect(Collectors.toList());
65+
assertThat(maps).hasSize(0);
66+
});
67+
}
68+
69+
private MultipleManagedDependentResourceMultiInformerCustomResource testResource() {
70+
var res = new MultipleManagedDependentResourceMultiInformerCustomResource();
71+
res.setMetadata(new ObjectMetaBuilder()
72+
.withName(TEST_RESOURCE_NAME)
73+
.build());
74+
75+
res.setSpec(new MultipleManagedDependentResourceMultiInformerSpec());
76+
res.getSpec().setValue(DEFAULT_SPEC_VALUE);
77+
return res;
78+
}
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
import java.util.Optional;
4+
5+
import io.fabric8.kubernetes.api.model.ConfigMap;
6+
import io.javaoperatorsdk.operator.api.reconciler.Context;
7+
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
8+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
9+
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
10+
11+
import static io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceConfigMap1.NAME_SUFFIX;
12+
13+
public class ConfigMap1MultiInformerDiscriminator
14+
implements
15+
ResourceDiscriminator<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource> {
16+
@Override
17+
public Optional<ConfigMap> distinguish(Class<ConfigMap> resource,
18+
MultipleManagedDependentResourceMultiInformerCustomResource primary,
19+
Context<MultipleManagedDependentResourceMultiInformerCustomResource> context) {
20+
InformerEventSource<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource> ies =
21+
(InformerEventSource<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource>) context
22+
.eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class,
23+
MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_1_DR);
24+
25+
return ies.get(new ResourceID(primary.getMetadata().getName() + NAME_SUFFIX,
26+
primary.getMetadata().getNamespace()));
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
import java.util.Optional;
4+
5+
import io.fabric8.kubernetes.api.model.ConfigMap;
6+
import io.javaoperatorsdk.operator.api.reconciler.Context;
7+
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
8+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
9+
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
10+
11+
import static io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceConfigMap2.NAME_SUFFIX;
12+
13+
public class ConfigMap2MultiInformerDiscriminator
14+
implements
15+
ResourceDiscriminator<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource> {
16+
@Override
17+
public Optional<ConfigMap> distinguish(Class<ConfigMap> resource,
18+
MultipleManagedDependentResourceMultiInformerCustomResource primary,
19+
Context<MultipleManagedDependentResourceMultiInformerCustomResource> context) {
20+
InformerEventSource<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource> ies =
21+
(InformerEventSource<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource>) context
22+
.eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class,
23+
MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_2_DR);
24+
25+
return ies.get(new ResourceID(primary.getMetadata().getName() + NAME_SUFFIX,
26+
primary.getMetadata().getNamespace()));
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import io.fabric8.kubernetes.api.model.ConfigMap;
7+
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
8+
import io.javaoperatorsdk.operator.api.reconciler.Context;
9+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
10+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
11+
import io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceReconciler;
12+
13+
@KubernetesDependent(resourceDiscriminator = ConfigMap1MultiInformerDiscriminator.class)
14+
public class MultipleManagedDependentResourceMultiInformerConfigMap1
15+
extends
16+
CRUDKubernetesDependentResource<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource> {
17+
18+
public static final String NAME_SUFFIX = "-1";
19+
20+
public MultipleManagedDependentResourceMultiInformerConfigMap1() {
21+
super(ConfigMap.class);
22+
}
23+
24+
@Override
25+
protected ConfigMap desired(MultipleManagedDependentResourceMultiInformerCustomResource primary,
26+
Context<MultipleManagedDependentResourceMultiInformerCustomResource> context) {
27+
Map<String, String> data = new HashMap<>();
28+
data.put(MultipleManagedDependentResourceReconciler.DATA_KEY, primary.getSpec().getValue());
29+
30+
return new ConfigMapBuilder()
31+
.withNewMetadata()
32+
.withName(primary.getMetadata().getName() + NAME_SUFFIX)
33+
.withNamespace(primary.getMetadata().getNamespace())
34+
.endMetadata()
35+
.withData(data)
36+
.build();
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import io.fabric8.kubernetes.api.model.ConfigMap;
7+
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
8+
import io.javaoperatorsdk.operator.api.reconciler.Context;
9+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
10+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
11+
12+
import static io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceReconciler.DATA_KEY;
13+
14+
@KubernetesDependent(resourceDiscriminator = ConfigMap2MultiInformerDiscriminator.class)
15+
public class MultipleManagedDependentResourceMultiInformerConfigMap2
16+
extends
17+
CRUDKubernetesDependentResource<ConfigMap, MultipleManagedDependentResourceMultiInformerCustomResource> {
18+
19+
public static final String NAME_SUFFIX = "-2";
20+
21+
public MultipleManagedDependentResourceMultiInformerConfigMap2() {
22+
super(ConfigMap.class);
23+
}
24+
25+
@Override
26+
protected ConfigMap desired(MultipleManagedDependentResourceMultiInformerCustomResource primary,
27+
Context<MultipleManagedDependentResourceMultiInformerCustomResource> context) {
28+
Map<String, String> data = new HashMap<>();
29+
data.put(DATA_KEY, primary.getSpec().getValue());
30+
31+
return new ConfigMapBuilder()
32+
.withNewMetadata()
33+
.withName(primary.getMetadata().getName() + NAME_SUFFIX)
34+
.withNamespace(primary.getMetadata().getNamespace())
35+
.endMetadata()
36+
.withData(data)
37+
.build();
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
import io.fabric8.kubernetes.api.model.Namespaced;
4+
import io.fabric8.kubernetes.client.CustomResource;
5+
import io.fabric8.kubernetes.model.annotation.Group;
6+
import io.fabric8.kubernetes.model.annotation.ShortNames;
7+
import io.fabric8.kubernetes.model.annotation.Version;
8+
9+
@Group("sample.javaoperatorsdk")
10+
@Version("v1")
11+
@ShortNames("mmi")
12+
public class MultipleManagedDependentResourceMultiInformerCustomResource
13+
extends CustomResource<MultipleManagedDependentResourceMultiInformerSpec, Void>
14+
implements Namespaced {
15+
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
import java.util.concurrent.atomic.AtomicInteger;
4+
5+
import io.javaoperatorsdk.operator.api.reconciler.*;
6+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
7+
import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider;
8+
9+
@ControllerConfiguration(dependents = {
10+
@Dependent(name = MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_1_DR,
11+
type = MultipleManagedDependentResourceMultiInformerConfigMap1.class),
12+
@Dependent(name = MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_2_DR,
13+
type = MultipleManagedDependentResourceMultiInformerConfigMap2.class)
14+
})
15+
public class MultipleManagedDependentResourceMultiInformerReconciler
16+
implements Reconciler<MultipleManagedDependentResourceMultiInformerCustomResource>,
17+
TestExecutionInfoProvider {
18+
19+
public static final String CONFIG_MAP_EVENT_SOURCE = "ConfigMapEventSource";
20+
public static final String DATA_KEY = "key";
21+
public static final String CONFIG_MAP_1_DR = "ConfigMap1";
22+
public static final String CONFIG_MAP_2_DR = "ConfigMap2";
23+
24+
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
25+
26+
public MultipleManagedDependentResourceMultiInformerReconciler() {}
27+
28+
@Override
29+
public UpdateControl<MultipleManagedDependentResourceMultiInformerCustomResource> reconcile(
30+
MultipleManagedDependentResourceMultiInformerCustomResource resource,
31+
Context<MultipleManagedDependentResourceMultiInformerCustomResource> context) {
32+
numberOfExecutions.getAndIncrement();
33+
34+
return UpdateControl.noUpdate();
35+
}
36+
37+
38+
public int getNumberOfExecutions() {
39+
return numberOfExecutions.get();
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer;
2+
3+
public class MultipleManagedDependentResourceMultiInformerSpec {
4+
5+
private String value;
6+
7+
public String getValue() {
8+
return value;
9+
}
10+
11+
public MultipleManagedDependentResourceMultiInformerSpec setValue(String value) {
12+
this.value = value;
13+
return this;
14+
}
15+
}

0 commit comments

Comments
 (0)