From b7383adb27888f747431284728ddc6115936508e Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 14 Feb 2023 14:35:35 +0100 Subject: [PATCH 1/6] feat: secondary to primary mapper supporting cluster scoped resource --- .../operator/processing/event/ResourceID.java | 7 ++++- .../event/source/informer/Mappers.java | 12 +++++++- ...ClusterScopedCustomResourceReconciler.java | 30 ++++++++++++++----- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ResourceID.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ResourceID.java index b6c2d976e3..a6bf6dd4e8 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ResourceID.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ResourceID.java @@ -14,10 +14,15 @@ public static ResourceID fromResource(HasMetadata resource) { } public static Optional fromFirstOwnerReference(HasMetadata resource) { + return fromFirstOwnerReference(resource, false); + } + + public static Optional fromFirstOwnerReference(HasMetadata resource, + boolean clusterScoped) { var ownerReferences = resource.getMetadata().getOwnerReferences(); if (!ownerReferences.isEmpty()) { return Optional.of(new ResourceID(ownerReferences.get(0).getName(), - resource.getMetadata().getNamespace())); + clusterScoped ? null : resource.getMetadata().getNamespace())); } else { return Optional.empty(); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java index 5764e5f888..8ec9b42af0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/Mappers.java @@ -42,7 +42,17 @@ public static SecondaryToPrimaryMapper fromLabel( } public static SecondaryToPrimaryMapper fromOwnerReference() { - return resource -> ResourceID.fromFirstOwnerReference(resource).map(Set::of) + return fromOwnerReference(false); + } + + /** + * @param clusterScope if the owner is a cluster scoped resource + * @return mapper + * @param type of the secondary resource, where the owner reference is + */ + public static SecondaryToPrimaryMapper fromOwnerReference( + boolean clusterScope) { + return resource -> ResourceID.fromFirstOwnerReference(resource, clusterScope).map(Set::of) .orElseGet(Collections::emptySet); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index edbf22a69f..fb7d6f1658 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -6,13 +6,17 @@ import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.client.KubernetesClient; +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.junit.KubernetesClientAware; +import io.javaoperatorsdk.operator.processing.event.source.EventSource; +import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; +import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; @ControllerConfiguration public class ClusterScopedCustomResourceReconciler - implements Reconciler, Cleaner, - KubernetesClientAware { + implements Reconciler, + KubernetesClientAware, EventSourceInitializer { public static final String DATA_KEY = "data-key"; @@ -22,7 +26,13 @@ public class ClusterScopedCustomResourceReconciler public UpdateControl reconcile( ClusterScopedCustomResource resource, Context context) { - client.configMaps().resource(desired(resource)).createOrReplace(); + var optionalConfigMap = context.getSecondaryResource(ConfigMap.class); + + optionalConfigMap.ifPresentOrElse(cm -> { + if (cm.getData().get(DATA_KEY).equals(resource.getSpec().getData())) { + client.configMaps().resource(desired(resource)).replace(); + } + }, () -> client.configMaps().resource(desired(resource)).create()); resource.setStatus(new ClusterScopedCustomResourceStatus()); resource.getStatus().setCreated(true); @@ -30,13 +40,15 @@ public UpdateControl reconcile( } private ConfigMap desired(ClusterScopedCustomResource resource) { - return new ConfigMapBuilder() + var cm = new ConfigMapBuilder() .withMetadata(new ObjectMetaBuilder() .withName(resource.getMetadata().getName()) .withNamespace(resource.getSpec().getTargetNamespace()) .build()) .withData(Map.of(DATA_KEY, resource.getSpec().getData())) .build(); + cm.addOwnerReference(resource); + return cm; } @Override @@ -50,9 +62,11 @@ public void setKubernetesClient(KubernetesClient kubernetesClient) { } @Override - public DeleteControl cleanup(ClusterScopedCustomResource resource, - Context context) { - client.configMaps().resource(desired(resource)).delete(); - return DeleteControl.defaultDelete(); + public Map prepareEventSources( + EventSourceContext context) { + var ies = new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) + .withSecondaryToPrimaryMapper(Mappers.fromOwnerReference(true)) + .build(), context); + return EventSourceInitializer.nameEventSources(ies); } } From 60a141b1289d13c23cd8205b4859d924f652ac65 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 14 Feb 2023 14:41:57 +0100 Subject: [PATCH 2/6] wip --- .../ClusterScopedCustomResourceReconciler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index fb7d6f1658..651dbfb741 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -29,7 +29,7 @@ public UpdateControl reconcile( var optionalConfigMap = context.getSecondaryResource(ConfigMap.class); optionalConfigMap.ifPresentOrElse(cm -> { - if (cm.getData().get(DATA_KEY).equals(resource.getSpec().getData())) { + if (!cm.getData().get(DATA_KEY).equals(resource.getSpec().getData())) { client.configMaps().resource(desired(resource)).replace(); } }, () -> client.configMaps().resource(desired(resource)).create()); From e243b9a36679905a51b966d3b2180c2fc230bae0 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 14 Feb 2023 15:47:07 +0100 Subject: [PATCH 3/6] log info --- .../ClusterScopedCustomResourceReconciler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index 651dbfb741..b72cdb389a 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -2,6 +2,9 @@ import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; @@ -20,6 +23,9 @@ public class ClusterScopedCustomResourceReconciler public static final String DATA_KEY = "data-key"; + private static final Logger log = + LoggerFactory.getLogger(ClusterScopedCustomResourceReconciler.class); + private KubernetesClient client; @Override @@ -29,7 +35,8 @@ public UpdateControl reconcile( var optionalConfigMap = context.getSecondaryResource(ConfigMap.class); optionalConfigMap.ifPresentOrElse(cm -> { - if (!cm.getData().get(DATA_KEY).equals(resource.getSpec().getData())) { + log.debug("Config map data: {} ", cm.getData()); + if (!resource.getSpec().getData().equals(cm.getData().get(DATA_KEY))) { client.configMaps().resource(desired(resource)).replace(); } }, () -> client.configMaps().resource(desired(resource)).create()); From 20155e35ffd0326faddfb91d7fc8f39728562c5b Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 14 Feb 2023 15:49:51 +0100 Subject: [PATCH 4/6] log --- .../ClusterScopedCustomResourceReconciler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index b72cdb389a..e3b042bf56 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -35,7 +35,7 @@ public UpdateControl reconcile( var optionalConfigMap = context.getSecondaryResource(ConfigMap.class); optionalConfigMap.ifPresentOrElse(cm -> { - log.debug("Config map data: {} ", cm.getData()); + log.debug("Existing config map: {} ", cm); if (!resource.getSpec().getData().equals(cm.getData().get(DATA_KEY))) { client.configMaps().resource(desired(resource)).replace(); } From bbf4272248f43ac59071cb9c55e386f167b1f393 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 14 Feb 2023 16:00:31 +0100 Subject: [PATCH 5/6] test fix --- .../ClusterScopedCustomResourceReconciler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index e3b042bf56..4a40a676b7 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -25,6 +25,8 @@ public class ClusterScopedCustomResourceReconciler private static final Logger log = LoggerFactory.getLogger(ClusterScopedCustomResourceReconciler.class); + public static final String TEST_LABEL_VALUE = "clusterscopecrtest"; + public static final String TEST_LABEL_KEY = "test"; private KubernetesClient client; @@ -51,6 +53,7 @@ private ConfigMap desired(ClusterScopedCustomResource resource) { .withMetadata(new ObjectMetaBuilder() .withName(resource.getMetadata().getName()) .withNamespace(resource.getSpec().getTargetNamespace()) + .withLabels(Map.of(TEST_LABEL_KEY, TEST_LABEL_VALUE)) .build()) .withData(Map.of(DATA_KEY, resource.getSpec().getData())) .build(); @@ -73,6 +76,7 @@ public Map prepareEventSources( EventSourceContext context) { var ies = new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context) .withSecondaryToPrimaryMapper(Mappers.fromOwnerReference(true)) + .withLabelSelector(TEST_LABEL_KEY + "=" + TEST_LABEL_VALUE) .build(), context); return EventSourceInitializer.nameEventSources(ies); } From c6f9ceef3303ba0add5a21176314021a47a568f0 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 14 Feb 2023 16:20:41 +0100 Subject: [PATCH 6/6] remove unnecessary logs --- .../ClusterScopedCustomResourceReconciler.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java index 4a40a676b7..9d4a4fbd74 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/clusterscopedresource/ClusterScopedCustomResourceReconciler.java @@ -2,9 +2,6 @@ import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; @@ -23,8 +20,6 @@ public class ClusterScopedCustomResourceReconciler public static final String DATA_KEY = "data-key"; - private static final Logger log = - LoggerFactory.getLogger(ClusterScopedCustomResourceReconciler.class); public static final String TEST_LABEL_VALUE = "clusterscopecrtest"; public static final String TEST_LABEL_KEY = "test"; @@ -37,7 +32,6 @@ public UpdateControl reconcile( var optionalConfigMap = context.getSecondaryResource(ConfigMap.class); optionalConfigMap.ifPresentOrElse(cm -> { - log.debug("Existing config map: {} ", cm); if (!resource.getSpec().getData().equals(cm.getData().get(DATA_KEY))) { client.configMaps().resource(desired(resource)).replace(); }