From 02e34ff74e541b5338fa1b4bae22b02c094f8421 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 30 Jan 2023 15:36:03 +0100 Subject: [PATCH 1/8] feat: integration test showcasing how to use primary to secondary mapper with dependent resources --- .../PrimaryToSecondaryDependentIT.java | 76 +++++++++++++++++++ .../ConfigMapDependent.java | 12 +++ .../ConfigMapReconcilePrecondition.java | 26 +++++++ ...aryToSecondaryDependentCustomResource.java | 15 ++++ ...PrimaryToSecondaryDependentReconciler.java | 74 ++++++++++++++++++ .../PrimaryToSecondaryDependentSpec.java | 15 ++++ .../SecretDependent.java | 32 ++++++++ 7 files changed, 250 insertions(+) create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapDependent.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapReconcilePrecondition.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentSpec.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/SecretDependent.java diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java new file mode 100644 index 0000000000..0aeec9acba --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java @@ -0,0 +1,76 @@ +package io.javaoperatorsdk.operator; + +import java.time.Duration; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.Secret; +import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension; +import io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentCustomResource; +import io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler; +import io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentSpec; + +import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.ConfigMapReconcilePrecondition.DO_NOT_RECONCILE; +import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.DATA_KEY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +class PrimaryToSecondaryDependentIT { + + public static final String TEST_CONFIG_MAP_NAME = "testconfigmap"; + public static final String TEST_CR_NAME = "test1"; + public static final String TEST_DATA = "testData"; + public + + @RegisterExtension LocallyRunOperatorExtension operator = + LocallyRunOperatorExtension.builder() + .withReconciler(new PrimaryToSecondaryDependentReconciler()) + .build(); + + @Test + void testPrimaryToSecondaryInDependentResources() { + var reconciler = operator.getReconcilerOfType(PrimaryToSecondaryDependentReconciler.class); + var cm = operator.create(configMap(DO_NOT_RECONCILE)); + var cr = operator.create(testCustomResource()); + + await().pollDelay(Duration.ofMillis(250)).untilAsserted(() -> { + assertThat(reconciler.getNumberOfExecutions()).isPositive(); + assertThat(operator.get(Secret.class, TEST_CR_NAME)).isNull(); + }); + + cm.setData(Map.of(DATA_KEY, TEST_DATA)); + operator.replace(cm); + var executions = reconciler.getNumberOfExecutions(); + + await().pollDelay(Duration.ofMillis(250)).untilAsserted(() -> { + assertThat(reconciler.getNumberOfExecutions()).isGreaterThan(executions); + var secret = operator.get(Secret.class, TEST_CR_NAME); + assertThat(secret).isNotNull(); + assertThat(secret.getData().get(DATA_KEY)).isEqualTo(TEST_DATA); + }); + } + + PrimaryToSecondaryDependentCustomResource testCustomResource() { + var res = new PrimaryToSecondaryDependentCustomResource(); + res.setMetadata(new ObjectMetaBuilder() + .withName(TEST_CR_NAME) + .build()); + res.setSpec(new PrimaryToSecondaryDependentSpec()); + res.getSpec().setConfigMapName(TEST_CONFIG_MAP_NAME); + return res; + } + + ConfigMap configMap(String data) { + var cm = new ConfigMap(); + cm.setMetadata(new ObjectMetaBuilder() + .withName(TEST_CONFIG_MAP_NAME) + .build()); + cm.setData(Map.of(DATA_KEY, data)); + return cm; + } + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapDependent.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapDependent.java new file mode 100644 index 0000000000..d08bc2131f --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapDependent.java @@ -0,0 +1,12 @@ +package io.javaoperatorsdk.operator.sample.primarytosecondaydependent; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; + +public class ConfigMapDependent extends + KubernetesDependentResource { + + public ConfigMapDependent() { + super(ConfigMap.class); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapReconcilePrecondition.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapReconcilePrecondition.java new file mode 100644 index 0000000000..b8aa65585d --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/ConfigMapReconcilePrecondition.java @@ -0,0 +1,26 @@ +package io.javaoperatorsdk.operator.sample.primarytosecondaydependent; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; + +import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.DATA_KEY; + +public class ConfigMapReconcilePrecondition + implements Condition { + + public static final String DO_NOT_RECONCILE = "doNotReconcile"; + + @Override + public boolean isMet( + DependentResource dependentResource, + PrimaryToSecondaryDependentCustomResource primary, + Context context) { + return dependentResource.getSecondaryResource(primary, context).map(cm -> { + var data = cm.getData().get(DATA_KEY); + return data != null && !data.equals(DO_NOT_RECONCILE); + }) + .orElse(false); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentCustomResource.java new file mode 100644 index 0000000000..4ec7065f2e --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentCustomResource.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.operator.sample.primarytosecondaydependent; + +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("ptsd") +public class PrimaryToSecondaryDependentCustomResource + extends CustomResource + implements Namespaced { +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java new file mode 100644 index 0000000000..8646951b95 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -0,0 +1,74 @@ +package io.javaoperatorsdk.operator.sample.primarytosecondaydependent; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; +import io.javaoperatorsdk.operator.processing.event.ResourceID; +import io.javaoperatorsdk.operator.processing.event.source.EventSource; +import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; +import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; +import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; + +import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.CONFIG_MAP; +import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.CONFIG_MAP_EVENT_SOURCE; + +@ControllerConfiguration(dependents = {@Dependent(type = ConfigMapDependent.class, + name = CONFIG_MAP, + reconcilePrecondition = ConfigMapReconcilePrecondition.class, + useEventSourceWithName = CONFIG_MAP_EVENT_SOURCE), + @Dependent(type = SecretDependent.class, dependsOn = CONFIG_MAP)}) +public class PrimaryToSecondaryDependentReconciler + implements Reconciler, TestExecutionInfoProvider, + EventSourceInitializer { + + public static final String DATA_KEY = "data"; + public static final String CONFIG_MAP = "ConfigMap"; + public static final String CONFIG_MAP_INDEX = "ConfigMapIndex"; + public static final String CONFIG_MAP_EVENT_SOURCE = "ConfigMapEventSource"; + + private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + + @Override + public UpdateControl reconcile( + PrimaryToSecondaryDependentCustomResource resource, + Context context) { + numberOfExecutions.addAndGet(1); + return UpdateControl.noUpdate(); + } + + public int getNumberOfExecutions() { + return numberOfExecutions.get(); + } + + @Override + public Map prepareEventSources( + EventSourceContext context) { + context.getPrimaryCache().addIndexer(CONFIG_MAP_INDEX, (primary -> List + .of(indexKey(primary.getSpec().getConfigMapName(), primary.getMetadata().getNamespace())))); + + var cmES = new InformerEventSource<>(InformerConfiguration + .from(ConfigMap.class, context) + .withPrimaryToSecondaryMapper( + (PrimaryToSecondaryMapper) p -> Set + .of(new ResourceID(p.getSpec().getConfigMapName(), p.getMetadata().getNamespace()))) + .withSecondaryToPrimaryMapper(cm -> context.getPrimaryCache() + .byIndex(CONFIG_MAP_INDEX, indexKey(cm.getMetadata().getName(), + cm.getMetadata().getNamespace())) + .stream().map(ResourceID::fromResource).collect(Collectors.toSet())) + .build(), + context); + + return Map.of(CONFIG_MAP_EVENT_SOURCE, cmES); + } + + private String indexKey(String clusterName, String namespace) { + return clusterName + "#" + namespace; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentSpec.java new file mode 100644 index 0000000000..966a5c242b --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentSpec.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.operator.sample.primarytosecondaydependent; + +public class PrimaryToSecondaryDependentSpec { + + private String configMapName; + + public String getConfigMapName() { + return configMapName; + } + + public PrimaryToSecondaryDependentSpec setConfigMapName(String configMapName) { + this.configMapName = configMapName; + return this; + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/SecretDependent.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/SecretDependent.java new file mode 100644 index 0000000000..c78f3c470f --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/SecretDependent.java @@ -0,0 +1,32 @@ +package io.javaoperatorsdk.operator.sample.primarytosecondaydependent; + +import java.util.Map; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.Secret; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; + +import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.DATA_KEY; + +public class SecretDependent + extends CRUDKubernetesDependentResource { + + public SecretDependent() { + super(Secret.class); + } + + @Override + protected Secret desired(PrimaryToSecondaryDependentCustomResource primary, + Context context) { + Secret secret = new Secret(); + secret.setMetadata(new ObjectMetaBuilder() + .withName(primary.getMetadata().getName()) + .withNamespace(primary.getMetadata().getNamespace()) + .build()); + secret.setData(Map.of(DATA_KEY, context.getSecondaryResource(ConfigMap.class) + .orElseThrow().getData().get(DATA_KEY))); + return secret; + } +} From c2ae4dd32d92422d04d40d35f82c9f2e9e098dc5 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 30 Jan 2023 15:46:35 +0100 Subject: [PATCH 2/8] docs --- .../operator/PrimaryToSecondaryDependentIT.java | 2 +- .../PrimaryToSecondaryDependentReconciler.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java index 0aeec9acba..b396bd231b 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java @@ -35,7 +35,7 @@ class PrimaryToSecondaryDependentIT { void testPrimaryToSecondaryInDependentResources() { var reconciler = operator.getReconcilerOfType(PrimaryToSecondaryDependentReconciler.class); var cm = operator.create(configMap(DO_NOT_RECONCILE)); - var cr = operator.create(testCustomResource()); + operator.create(testCustomResource()); await().pollDelay(Duration.ofMillis(250)).untilAsserted(() -> { assertThat(reconciler.getNumberOfExecutions()).isPositive(); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index 8646951b95..480fdf7f65 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -19,6 +19,11 @@ import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.CONFIG_MAP; import static io.javaoperatorsdk.operator.sample.primarytosecondaydependent.PrimaryToSecondaryDependentReconciler.CONFIG_MAP_EVENT_SOURCE; +/** + * Sample showcases how it is possible to do a primary to secondary mapper for a dependent resource. + * Note that this is usually just used with read only resources. So it has limited usage, one reason + * to use it is to have nice condition on that resource within a workflow. + */ @ControllerConfiguration(dependents = {@Dependent(type = ConfigMapDependent.class, name = CONFIG_MAP, reconcilePrecondition = ConfigMapReconcilePrecondition.class, From c63bc56312916a4024a1e9d8e25879a55323c5da Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 6 Feb 2023 12:49:42 +0100 Subject: [PATCH 3/8] changes for CR --- .../operator/PrimaryToSecondaryDependentIT.java | 2 +- .../PrimaryToSecondaryDependentReconciler.java | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java index b396bd231b..eaa7e4410f 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/PrimaryToSecondaryDependentIT.java @@ -43,8 +43,8 @@ void testPrimaryToSecondaryInDependentResources() { }); cm.setData(Map.of(DATA_KEY, TEST_DATA)); - operator.replace(cm); var executions = reconciler.getNumberOfExecutions(); + operator.replace(cm); await().pollDelay(Duration.ofMillis(250)).untilAsserted(() -> { assertThat(reconciler.getNumberOfExecutions()).isGreaterThan(executions); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index 480fdf7f65..9ba3ce84a0 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -52,6 +52,12 @@ public int getNumberOfExecutions() { return numberOfExecutions.get(); } + /** + * Here just simply creating an Event Source, and setting it for the Dependent Resource. Since it + * is not possible to do this setup within the bounds of the KubernetesDependentResource API. + * However, this is quite a corner case; might be covered more out of the box in the future if + * there will be demand for it. + **/ @Override public Map prepareEventSources( EventSourceContext context) { @@ -73,7 +79,7 @@ public Map prepareEventSources( return Map.of(CONFIG_MAP_EVENT_SOURCE, cmES); } - private String indexKey(String clusterName, String namespace) { - return clusterName + "#" + namespace; + private String indexKey(String configMapName, String namespace) { + return configMapName + "#" + namespace; } } From 81f7e30ced5bbfe097ca9482e5c7b760ed883320 Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 6 Feb 2023 13:10:18 +0100 Subject: [PATCH 4/8] improved javadoc --- .../PrimaryToSecondaryDependentReconciler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index 9ba3ce84a0..559cfa9c07 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -53,10 +53,10 @@ public int getNumberOfExecutions() { } /** - * Here just simply creating an Event Source, and setting it for the Dependent Resource. Since it - * is not possible to do this setup within the bounds of the KubernetesDependentResource API. - * However, this is quite a corner case; might be covered more out of the box in the future if - * there will be demand for it. + * Creating an Event Source and setting it for the Dependent Resource. Since it is not possible to + * do this setup within the bounds of the KubernetesDependentResource API. However, this is quite + * a corner case; might be covered more out of the box in the future if there will be demand for + * it. **/ @Override public Map prepareEventSources( From 6b644b76ed6c749c5288ac184dbcc65055dcd548 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 8 Feb 2023 10:00:23 +0100 Subject: [PATCH 5/8] docs --- docs/documentation/v4-3-migration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/documentation/v4-3-migration.md b/docs/documentation/v4-3-migration.md index 77979fe3ba..f5022fa856 100644 --- a/docs/documentation/v4-3-migration.md +++ b/docs/documentation/v4-3-migration.md @@ -9,8 +9,8 @@ permalink: /docs/v4-3-migration ## Condition API Change -In Workflows the target of the condition was the managed resource itself, not a dependent resource. This changed, from -not the API contains the dependent resource. +In Workflows the target of the condition was the managed resource itself, not the target dependent resource. +This changed, now the API contains the dependent resource. New API: From abe91a96b8a0319bf5ef56e128b8b55d7605360b Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 8 Feb 2023 10:05:16 +0100 Subject: [PATCH 6/8] docs --- .../PrimaryToSecondaryDependentReconciler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index 559cfa9c07..2819c78902 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -54,7 +54,7 @@ public int getNumberOfExecutions() { /** * Creating an Event Source and setting it for the Dependent Resource. Since it is not possible to - * do this setup within the bounds of the KubernetesDependentResource API. However, this is quite + * do this setup elegantly within the bounds of the KubernetesDependentResource API. However, this is quite * a corner case; might be covered more out of the box in the future if there will be demand for * it. **/ From 6d1ef4f9245b45d44d63906b0e944474580eed61 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 8 Feb 2023 10:07:53 +0100 Subject: [PATCH 7/8] format --- .../PrimaryToSecondaryDependentReconciler.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index 2819c78902..5dbb801e5b 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -54,9 +54,9 @@ public int getNumberOfExecutions() { /** * Creating an Event Source and setting it for the Dependent Resource. Since it is not possible to - * do this setup elegantly within the bounds of the KubernetesDependentResource API. However, this is quite - * a corner case; might be covered more out of the box in the future if there will be demand for - * it. + * do this setup elegantly within the bounds of the KubernetesDependentResource API. However, this + * is quite a corner case; might be covered more out of the box in the future if there will be + * demand for it. **/ @Override public Map prepareEventSources( From b20fcdc2de50876f7df9440c71aee05f5f8763db Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 8 Feb 2023 10:37:21 +0100 Subject: [PATCH 8/8] docs --- .../PrimaryToSecondaryDependentReconciler.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java index 5dbb801e5b..c51111b206 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/primarytosecondaydependent/PrimaryToSecondaryDependentReconciler.java @@ -61,14 +61,21 @@ public int getNumberOfExecutions() { @Override public Map prepareEventSources( EventSourceContext context) { + // there is no owner reference in the config map, but we still want to trigger reconciliation if + // the config map changes. So first we add an index which custom resource references the config + // map. context.getPrimaryCache().addIndexer(CONFIG_MAP_INDEX, (primary -> List .of(indexKey(primary.getSpec().getConfigMapName(), primary.getMetadata().getNamespace())))); var cmES = new InformerEventSource<>(InformerConfiguration .from(ConfigMap.class, context) + // if there is a many-to-many relationship (thus no direct owner reference) + // PrimaryToSecondaryMapper needs to be added .withPrimaryToSecondaryMapper( (PrimaryToSecondaryMapper) p -> Set .of(new ResourceID(p.getSpec().getConfigMapName(), p.getMetadata().getNamespace()))) + // the index is used to trigger reconciliation of related custom resources if config map + // changes .withSecondaryToPrimaryMapper(cm -> context.getPrimaryCache() .byIndex(CONFIG_MAP_INDEX, indexKey(cm.getMetadata().getName(), cm.getMetadata().getNamespace()))