diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleDependentSameTypeMultiInformerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleDependentSameTypeMultiInformerIT.java new file mode 100644 index 0000000000..53d29f4552 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/MultipleDependentSameTypeMultiInformerIT.java @@ -0,0 +1,79 @@ +package io.javaoperatorsdk.operator; + +import java.time.Duration; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; +import io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerCustomResource; +import io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerReconciler; +import io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerSpec; + +import static io.javaoperatorsdk.operator.IntegrationTestConstants.GARBAGE_COLLECTION_TIMEOUT_SECONDS; +import static io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer.MultipleManagedDependentResourceMultiInformerReconciler.DATA_KEY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +class MultipleDependentSameTypeMultiInformerIT { + + public static final String TEST_RESOURCE_NAME = "test1"; + public static final String DEFAULT_SPEC_VALUE = "val"; + public static final String UPDATED_SPEC_VALUE = "updated-val"; + public static final int SECONDS = 30; + + @RegisterExtension + LocallyRunOperatorExtension operator = + LocallyRunOperatorExtension.builder() + .withReconciler(new MultipleManagedDependentResourceMultiInformerReconciler()) + .build(); + + @Test + void handlesCrudOperations() { + operator.create(testResource()); + assertConfigMapsPresent(DEFAULT_SPEC_VALUE); + + var updatedResource = testResource(); + updatedResource.getSpec().setValue(UPDATED_SPEC_VALUE); + operator.replace(updatedResource); + assertConfigMapsPresent(UPDATED_SPEC_VALUE); + + operator.delete(testResource()); + assertConfigMapsDeleted(); + } + + + private void assertConfigMapsPresent(String expectedData) { + await().untilAsserted(() -> { + var maps = operator.getKubernetesClient().configMaps() + .inNamespace(operator.getNamespace()).list().getItems().stream() + .filter(cm -> cm.getMetadata().getName().startsWith(TEST_RESOURCE_NAME)) + .collect(Collectors.toList()); + assertThat(maps).hasSize(2); + assertThat(maps).allMatch(cm -> cm.getData().get(DATA_KEY).equals(expectedData)); + }); + } + + private void assertConfigMapsDeleted() { + await().atMost(Duration.ofSeconds(GARBAGE_COLLECTION_TIMEOUT_SECONDS)).untilAsserted(() -> { + var maps = operator.getKubernetesClient().configMaps() + .inNamespace(operator.getNamespace()).list().getItems().stream() + .filter(cm -> cm.getMetadata().getName().startsWith(TEST_RESOURCE_NAME)) + .collect(Collectors.toList()); + assertThat(maps).hasSize(0); + }); + } + + private MultipleManagedDependentResourceMultiInformerCustomResource testResource() { + var res = new MultipleManagedDependentResourceMultiInformerCustomResource(); + res.setMetadata(new ObjectMetaBuilder() + .withName(TEST_RESOURCE_NAME) + .build()); + + res.setSpec(new MultipleManagedDependentResourceMultiInformerSpec()); + res.getSpec().setValue(DEFAULT_SPEC_VALUE); + return res; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/ConfigMap1MultiInformerDiscriminator.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/ConfigMap1MultiInformerDiscriminator.java new file mode 100644 index 0000000000..32cf830bc1 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/ConfigMap1MultiInformerDiscriminator.java @@ -0,0 +1,28 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +import java.util.Optional; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator; +import io.javaoperatorsdk.operator.processing.event.ResourceID; +import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; + +import static io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceConfigMap1.NAME_SUFFIX; + +public class ConfigMap1MultiInformerDiscriminator + implements + ResourceDiscriminator { + @Override + public Optional distinguish(Class resource, + MultipleManagedDependentResourceMultiInformerCustomResource primary, + Context context) { + InformerEventSource ies = + (InformerEventSource) context + .eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class, + MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_1_DR); + + return ies.get(new ResourceID(primary.getMetadata().getName() + NAME_SUFFIX, + primary.getMetadata().getNamespace())); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/ConfigMap2MultiInformerDiscriminator.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/ConfigMap2MultiInformerDiscriminator.java new file mode 100644 index 0000000000..cc6a0a656e --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/ConfigMap2MultiInformerDiscriminator.java @@ -0,0 +1,28 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +import java.util.Optional; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator; +import io.javaoperatorsdk.operator.processing.event.ResourceID; +import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; + +import static io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceConfigMap2.NAME_SUFFIX; + +public class ConfigMap2MultiInformerDiscriminator + implements + ResourceDiscriminator { + @Override + public Optional distinguish(Class resource, + MultipleManagedDependentResourceMultiInformerCustomResource primary, + Context context) { + InformerEventSource ies = + (InformerEventSource) context + .eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class, + MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_2_DR); + + return ies.get(new ResourceID(primary.getMetadata().getName() + NAME_SUFFIX, + primary.getMetadata().getNamespace())); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerConfigMap1.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerConfigMap1.java new file mode 100644 index 0000000000..2a63b7267e --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerConfigMap1.java @@ -0,0 +1,38 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +import java.util.HashMap; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ConfigMapBuilder; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; +import io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceReconciler; + +@KubernetesDependent(resourceDiscriminator = ConfigMap1MultiInformerDiscriminator.class) +public class MultipleManagedDependentResourceMultiInformerConfigMap1 + extends + CRUDKubernetesDependentResource { + + public static final String NAME_SUFFIX = "-1"; + + public MultipleManagedDependentResourceMultiInformerConfigMap1() { + super(ConfigMap.class); + } + + @Override + protected ConfigMap desired(MultipleManagedDependentResourceMultiInformerCustomResource primary, + Context context) { + Map data = new HashMap<>(); + data.put(MultipleManagedDependentResourceReconciler.DATA_KEY, primary.getSpec().getValue()); + + return new ConfigMapBuilder() + .withNewMetadata() + .withName(primary.getMetadata().getName() + NAME_SUFFIX) + .withNamespace(primary.getMetadata().getNamespace()) + .endMetadata() + .withData(data) + .build(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerConfigMap2.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerConfigMap2.java new file mode 100644 index 0000000000..8db20cac14 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerConfigMap2.java @@ -0,0 +1,39 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +import java.util.HashMap; +import java.util.Map; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ConfigMapBuilder; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; + +import static io.javaoperatorsdk.operator.sample.multiplemanageddependentsametype.MultipleManagedDependentResourceReconciler.DATA_KEY; + +@KubernetesDependent(resourceDiscriminator = ConfigMap2MultiInformerDiscriminator.class) +public class MultipleManagedDependentResourceMultiInformerConfigMap2 + extends + CRUDKubernetesDependentResource { + + public static final String NAME_SUFFIX = "-2"; + + public MultipleManagedDependentResourceMultiInformerConfigMap2() { + super(ConfigMap.class); + } + + @Override + protected ConfigMap desired(MultipleManagedDependentResourceMultiInformerCustomResource primary, + Context context) { + Map data = new HashMap<>(); + data.put(DATA_KEY, primary.getSpec().getValue()); + + return new ConfigMapBuilder() + .withNewMetadata() + .withName(primary.getMetadata().getName() + NAME_SUFFIX) + .withNamespace(primary.getMetadata().getNamespace()) + .endMetadata() + .withData(data) + .build(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerCustomResource.java new file mode 100644 index 0000000000..24ee0ea0dc --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerCustomResource.java @@ -0,0 +1,16 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +@ShortNames("mmi") +public class MultipleManagedDependentResourceMultiInformerCustomResource + extends CustomResource + implements Namespaced { + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerReconciler.java new file mode 100644 index 0000000000..81c2308eb5 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerReconciler.java @@ -0,0 +1,41 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; +import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; + +@ControllerConfiguration(dependents = { + @Dependent(name = MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_1_DR, + type = MultipleManagedDependentResourceMultiInformerConfigMap1.class), + @Dependent(name = MultipleManagedDependentResourceMultiInformerReconciler.CONFIG_MAP_2_DR, + type = MultipleManagedDependentResourceMultiInformerConfigMap2.class) +}) +public class MultipleManagedDependentResourceMultiInformerReconciler + implements Reconciler, + TestExecutionInfoProvider { + + public static final String CONFIG_MAP_EVENT_SOURCE = "ConfigMapEventSource"; + public static final String DATA_KEY = "key"; + public static final String CONFIG_MAP_1_DR = "ConfigMap1"; + public static final String CONFIG_MAP_2_DR = "ConfigMap2"; + + private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + + public MultipleManagedDependentResourceMultiInformerReconciler() {} + + @Override + public UpdateControl reconcile( + MultipleManagedDependentResourceMultiInformerCustomResource resource, + Context context) { + numberOfExecutions.getAndIncrement(); + + return UpdateControl.noUpdate(); + } + + + public int getNumberOfExecutions() { + return numberOfExecutions.get(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerSpec.java new file mode 100644 index 0000000000..a98a3c0f92 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentsametypemultiinformer/MultipleManagedDependentResourceMultiInformerSpec.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.operator.sample.multipledependentsametypemultiinformer; + +public class MultipleManagedDependentResourceMultiInformerSpec { + + private String value; + + public String getValue() { + return value; + } + + public MultipleManagedDependentResourceMultiInformerSpec setValue(String value) { + this.value = value; + return this; + } +}