diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/GarbageCollected.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/GarbageCollected.java
new file mode 100644
index 0000000000..1316c44873
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/GarbageCollected.java
@@ -0,0 +1,15 @@
+package io.javaoperatorsdk.operator.api.reconciler.dependent;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+
+/**
+ * Should be implemented by {@link DependentResource} implementations that are explicitly deleted
+ * during reconciliation but which should also benefit from Kubernetes' automated garbage collection
+ * during the cleanup phase.
+ *
+ * See this issue
+ * for more details.
+ */
+public interface GarbageCollected
extends Deleter
{
+
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
index 63b3c85a9c..9ec33f175d 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java
@@ -37,6 +37,7 @@
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ManagedDependentResourceException;
@@ -74,15 +75,16 @@ public Controller(Reconciler
reconciler,
final var hasDeleterHolder = new boolean[] {false};
final var specs = configuration.getDependentResources();
- final var size = specs.size();
- if (size == 0) {
+ final var specsSize = specs.size();
+ if (specsSize == 0) {
dependents = new LinkedHashMap<>();
} else {
- final Map dependentsHolder = new LinkedHashMap<>(size);
+ final Map dependentsHolder = new LinkedHashMap<>(specsSize);
specs.forEach(drs -> {
final var dependent = createAndConfigureFrom(drs, kubernetesClient);
// check if dependent implements Deleter to record that fact
- if (!hasDeleterHolder[0] && dependent instanceof Deleter) {
+ if (!hasDeleterHolder[0] && dependent instanceof Deleter
+ && !(dependent instanceof GarbageCollected)) {
hasDeleterHolder[0] = true;
}
dependentsHolder.put(drs.getName(), dependent);
@@ -143,7 +145,7 @@ public DeleteControl execute() {
initContextIfNeeded(resource, context);
if (hasDeleterDependents) {
dependents.values().stream()
- .filter(d -> d instanceof Deleter)
+ .filter(d -> d instanceof Deleter && !(d instanceof GarbageCollected))
.map(Deleter.class::cast)
.forEach(deleter -> deleter.delete(resource, context));
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java
index 8611950e04..f3b9ab8eee 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java
@@ -5,7 +5,6 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
@@ -16,7 +15,7 @@ public abstract class AbstractDependentResource
protected final boolean creatable = this instanceof Creator;
protected final boolean updatable = this instanceof Updater;
- protected final boolean deletable = this instanceof Deleter;
+
protected Creator creator;
protected Updater updater;
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java
index 05195e39b9..057aabc9e9 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java
@@ -1,19 +1,22 @@
package io.javaoperatorsdk.operator.processing.dependent.kubernetes;
import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected;
import io.javaoperatorsdk.operator.processing.dependent.Creator;
import io.javaoperatorsdk.operator.processing.dependent.Updater;
/**
- * Adaptor Class for standalone mode for resources that manages Create, Read, Update and Delete
+ * Adaptor class for standalone mode for resources that manage Create, Read and Update operations
+ * and that should be automatically garbage-collected by Kubernetes when the associated primary
+ * resource is destroyed.
*
- * @param Managed resource
- * @param Primary Resource
+ * @param the type of the managed dependent resource
+ * @param the type of the associated primary resource
*/
public abstract class CRUDKubernetesDependentResource
extends
- KubernetesDependentResource implements Creator, Updater, Deleter {
+ KubernetesDependentResource
+ implements Creator, Updater, GarbageCollected {
public CRUDKubernetesDependentResource(Class resourceType) {
super(resourceType);
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUKubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUKubernetesDependentResource.java
deleted file mode 100644
index 7670367936..0000000000
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUKubernetesDependentResource.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.javaoperatorsdk.operator.processing.dependent.kubernetes;
-
-import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.javaoperatorsdk.operator.processing.dependent.Creator;
-import io.javaoperatorsdk.operator.processing.dependent.Updater;
-
-/**
- * Adaptor Class for standalone mode for resources that manages Create, Read and Update
- *
- * @param Managed resource
- * @param Primary Resource
- */
-public abstract class CRUKubernetesDependentResource
- extends
- KubernetesDependentResource implements Creator, Updater {
-
-
- public CRUKubernetesDependentResource(Class resourceType) {
- super(resourceType);
- }
-}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java
index b5dd2a720a..14f8e862ee 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java
@@ -14,6 +14,7 @@
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware;
import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource;
@@ -35,6 +36,7 @@ public abstract class KubernetesDependentResource matcher;
private final ResourceUpdatePreProcessor processor;
private final Class resourceType;
+ private final boolean garbageCollected = this instanceof GarbageCollected;
@SuppressWarnings("unchecked")
public KubernetesDependentResource(Class resourceType) {
@@ -78,11 +80,9 @@ public void configureWith(InformerEventSource informerEventSource) {
protected R handleCreate(R desired, P primary, Context context) {
ResourceID resourceID = ResourceID.fromResource(desired);
- R created = null;
try {
prepareEventFiltering(desired, resourceID);
- created = super.handleCreate(desired, primary, context);
- return created;
+ return super.handleCreate(desired, primary, context);
} catch (RuntimeException e) {
cleanupAfterEventFiltering(resourceID);
throw e;
@@ -91,11 +91,9 @@ protected R handleCreate(R desired, P primary, Context
context) {
protected R handleUpdate(R actual, R desired, P primary, Context
context) {
ResourceID resourceID = ResourceID.fromResource(desired);
- R updated = null;
try {
prepareEventFiltering(desired, resourceID);
- updated = super.handleUpdate(actual, desired, primary, context);
- return updated;
+ return super.handleUpdate(actual, desired, primary, context);
} catch (RuntimeException e) {
cleanupAfterEventFiltering(resourceID);
throw e;
@@ -117,10 +115,8 @@ public Result match(R actualResource, P primary, Context context) {
}
public void delete(P primary, Context
context) {
- if (!addOwnerReference()) {
- var resource = getSecondaryResource(primary);
- resource.ifPresent(r -> client.resource(r).delete());
- }
+ var resource = getSecondaryResource(primary);
+ resource.ifPresent(r -> client.resource(r).delete());
}
@SuppressWarnings("unchecked")
@@ -146,7 +142,7 @@ protected InformerEventSource createEventSource(EventSourceContext cont
}
protected boolean addOwnerReference() {
- return creatable && !deletable;
+ return garbageCollected;
}
@Override
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/KubernetesDependentGarbageCollectionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/KubernetesDependentGarbageCollectionIT.java
new file mode 100644
index 0000000000..50fa4ceea6
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/KubernetesDependentGarbageCollectionIT.java
@@ -0,0 +1,83 @@
+package io.javaoperatorsdk.operator;
+
+import java.time.Duration;
+
+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.javaoperatorsdk.operator.junit.OperatorExtension;
+import io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection.DependentGarbageCollectionTestCustomResource;
+import io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection.DependentGarbageCollectionTestCustomResourceSpec;
+import io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection.DependentGarbageCollectionTestReconciler;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+class KubernetesDependentGarbageCollectionIT {
+
+ public static final String TEST_RESOURCE_NAME = "test1";
+ @RegisterExtension
+ OperatorExtension operator =
+ OperatorExtension.builder()
+ .withReconciler(new DependentGarbageCollectionTestReconciler())
+ .build();
+
+
+ @Test
+ void resourceSecondaryResourceIsGarbageCollected() {
+ var resource = customResource();
+ var createdResources =
+ operator.create(DependentGarbageCollectionTestCustomResource.class, resource);
+
+ await().untilAsserted(() -> {
+ ConfigMap configMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
+ assertThat(configMap).isNotNull();
+ });
+
+ ConfigMap configMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
+ assertThat(configMap.getMetadata().getOwnerReferences()).hasSize(1);
+ assertThat(configMap.getMetadata().getOwnerReferences().get(0).getName())
+ .isEqualTo(TEST_RESOURCE_NAME);
+
+ operator.delete(DependentGarbageCollectionTestCustomResource.class, createdResources);
+
+ await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> {
+ ConfigMap cm = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
+ assertThat(cm).isNull();
+ });
+ }
+
+ @Test
+ void deletesSecondaryResource() {
+ var resource = customResource();
+ var createdResources =
+ operator.create(DependentGarbageCollectionTestCustomResource.class, resource);
+
+ await().untilAsserted(() -> {
+ ConfigMap configMap = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
+ assertThat(configMap).isNotNull();
+ });
+
+ createdResources.getSpec().setCreateConfigMap(false);
+ operator.replace(DependentGarbageCollectionTestCustomResource.class, createdResources);
+
+ await().untilAsserted(() -> {
+ ConfigMap cm = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
+ assertThat(cm).isNull();
+ });
+ }
+
+ DependentGarbageCollectionTestCustomResource customResource() {
+ DependentGarbageCollectionTestCustomResource resource =
+ new DependentGarbageCollectionTestCustomResource();
+ resource.setMetadata(new ObjectMetaBuilder()
+ .withName(TEST_RESOURCE_NAME)
+ .build());
+ resource.setSpec(new DependentGarbageCollectionTestCustomResourceSpec());
+ resource.getSpec().setCreateConfigMap(true);
+ return resource;
+ }
+
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java
index ff1d7f2cc8..9941779784 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java
@@ -6,10 +6,16 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
+import io.javaoperatorsdk.operator.processing.dependent.Creator;
+import io.javaoperatorsdk.operator.processing.dependent.Updater;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
public class ConfigMapDependentResource extends
- CRUDKubernetesDependentResource {
+ KubernetesDependentResource
+ implements Creator,
+ Updater,
+ Deleter {
private static final AtomicInteger numberOfCleanupExecutions = new AtomicInteger(0);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentoperationeventfiltering/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentoperationeventfiltering/ConfigMapDependentResource.java
index 17dbe20ddf..34fbd21c50 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentoperationeventfiltering/ConfigMapDependentResource.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/dependentoperationeventfiltering/ConfigMapDependentResource.java
@@ -5,10 +5,10 @@
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
public class ConfigMapDependentResource extends
- CRUKubernetesDependentResource {
+ CRUDKubernetesDependentResource {
public static final String KEY = "key1";
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResource.java
new file mode 100644
index 0000000000..5f1e5a0435
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResource.java
@@ -0,0 +1,16 @@
+package io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection;
+
+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("dgc")
+public class DependentGarbageCollectionTestCustomResource
+ extends
+ CustomResource
+ implements Namespaced {
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResourceSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResourceSpec.java
new file mode 100644
index 0000000000..9c29ebbacc
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResourceSpec.java
@@ -0,0 +1,16 @@
+package io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection;
+
+public class DependentGarbageCollectionTestCustomResourceSpec {
+
+ private boolean createConfigMap;
+
+ public boolean isCreateConfigMap() {
+ return createConfigMap;
+ }
+
+ public DependentGarbageCollectionTestCustomResourceSpec setCreateConfigMap(
+ boolean createConfigMap) {
+ this.createConfigMap = createConfigMap;
+ return this;
+ }
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResourceStatus.java
new file mode 100644
index 0000000000..79f67c017e
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestCustomResourceStatus.java
@@ -0,0 +1,5 @@
+package io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection;
+
+public class DependentGarbageCollectionTestCustomResourceStatus {
+
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestReconciler.java
new file mode 100644
index 0000000000..e9b947a83b
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/kubernetesdependentgarbagecollection/DependentGarbageCollectionTestReconciler.java
@@ -0,0 +1,102 @@
+package io.javaoperatorsdk.operator.sample.kubernetesdependentgarbagecollection;
+
+import java.util.Map;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.KubernetesClientException;
+import io.javaoperatorsdk.operator.api.reconciler.*;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.GarbageCollected;
+import io.javaoperatorsdk.operator.junit.KubernetesClientAware;
+import io.javaoperatorsdk.operator.processing.dependent.Creator;
+import io.javaoperatorsdk.operator.processing.dependent.Updater;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.event.source.EventSource;
+
+@ControllerConfiguration
+public class DependentGarbageCollectionTestReconciler
+ implements Reconciler,
+ EventSourceInitializer,
+ KubernetesClientAware, ErrorStatusHandler {
+
+ private KubernetesClient kubernetesClient;
+ private volatile boolean errorOccurred = false;
+
+ ConfigMapDependentResource configMapDependent;
+
+ public DependentGarbageCollectionTestReconciler() {
+ configMapDependent = new ConfigMapDependentResource();
+ }
+
+ @Override
+ public Map prepareEventSources(
+ EventSourceContext context) {
+ return EventSourceInitializer
+ .nameEventSources(configMapDependent.initEventSource(context));
+ }
+
+ @Override
+ public UpdateControl reconcile(
+ DependentGarbageCollectionTestCustomResource primary,
+ Context context) {
+
+ if (primary.getSpec().isCreateConfigMap()) {
+ configMapDependent.reconcile(primary, context);
+ } else {
+ configMapDependent.delete(primary, context);
+ }
+
+ return UpdateControl.noUpdate();
+ }
+
+ @Override
+ public void setKubernetesClient(KubernetesClient kubernetesClient) {
+ this.kubernetesClient = kubernetesClient;
+ configMapDependent.setKubernetesClient(kubernetesClient);
+ }
+
+ @Override
+ public KubernetesClient getKubernetesClient() {
+ return this.kubernetesClient;
+ }
+
+ @Override
+ public ErrorStatusUpdateControl updateErrorStatus(
+ DependentGarbageCollectionTestCustomResource resource,
+ Context context, Exception e) {
+ // this can happen when a namespace is terminated in test
+ if (e instanceof KubernetesClientException) {
+ return ErrorStatusUpdateControl.noStatusUpdate();
+ }
+ errorOccurred = true;
+ return ErrorStatusUpdateControl.noStatusUpdate();
+ }
+
+ public boolean isErrorOccurred() {
+ return errorOccurred;
+ }
+
+ private static class ConfigMapDependentResource extends
+ KubernetesDependentResource
+ implements Creator,
+ Updater,
+ GarbageCollected {
+
+ public ConfigMapDependentResource() {
+ super(ConfigMap.class);
+ }
+
+ @Override
+ protected ConfigMap desired(DependentGarbageCollectionTestCustomResource primary,
+ Context context) {
+ ConfigMap configMap = new ConfigMap();
+ configMap.setMetadata(new ObjectMetaBuilder()
+ .withName(primary.getMetadata().getName())
+ .withNamespace(primary.getMetadata().getNamespace())
+ .build());
+ configMap.setData(Map.of("key", "data"));
+ return configMap;
+ }
+ }
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java
index 19fd28b631..14530cf17e 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource1.java
@@ -7,12 +7,12 @@
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
@KubernetesDependent(labelSelector = "dependent = cm1")
public class ConfigMapDependentResource1 extends
- CRUKubernetesDependentResource {
+ CRUDKubernetesDependentResource {
public ConfigMapDependentResource1() {
super(ConfigMap.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java
index 2bffdfa8c1..35ae69586e 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/orderedmanageddependent/ConfigMapDependentResource2.java
@@ -7,12 +7,12 @@
import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
@KubernetesDependent(labelSelector = "dependent = cm2")
public class ConfigMapDependentResource2 extends
- CRUKubernetesDependentResource {
+ CRUDKubernetesDependentResource {
public ConfigMapDependentResource2() {
super(ConfigMap.class);
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/standalonedependent/StandaloneDependentTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/standalonedependent/StandaloneDependentTestReconciler.java
index 2ecaa5cc27..4853a22e9a 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/standalonedependent/StandaloneDependentTestReconciler.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/standalonedependent/StandaloneDependentTestReconciler.java
@@ -16,9 +16,7 @@
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
import io.javaoperatorsdk.operator.junit.KubernetesClientAware;
-import io.javaoperatorsdk.operator.processing.dependent.Creator;
-import io.javaoperatorsdk.operator.processing.dependent.Updater;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
@ControllerConfiguration
@@ -88,9 +86,7 @@ public boolean isErrorOccurred() {
}
private static class DeploymentDependentResource extends
- KubernetesDependentResource
- implements Creator,
- Updater {
+ CRUDKubernetesDependentResource {
public DeploymentDependentResource() {
super(Deployment.class);
diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java
index b1c516df8e..043b50a6cc 100644
--- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java
+++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SecretDependentResource.java
@@ -1,6 +1,7 @@
package io.javaoperatorsdk.operator.sample.dependent;
import java.util.Base64;
+import java.util.Set;
import org.apache.commons.lang3.RandomStringUtils;
@@ -10,12 +11,15 @@
import io.javaoperatorsdk.operator.processing.dependent.Creator;
import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
+import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
import io.javaoperatorsdk.operator.sample.MySQLSchema;
public class SecretDependentResource extends KubernetesDependentResource
- implements Creator {
+ implements Creator, SecondaryToPrimaryMapper {
- public static final String SECRET_FORMAT = "%s-secret";
+ public static final String SECRET_SUFFIX = "-secret";
+ public static final String SECRET_FORMAT = "%s" + SECRET_SUFFIX;
public static final String USERNAME_FORMAT = "%s-user";
public static final String MYSQL_SECRET_USERNAME = "mysql.secret.user.name";
public static final String MYSQL_SECRET_PASSWORD = "mysql.secret.user.password";
@@ -55,4 +59,11 @@ public Result match(Secret actual, MySQLSchema primary, Context toPrimaryResourceIDs(Secret dependentResource) {
+ String name = dependentResource.getMetadata().getName();
+ return Set.of(new ResourceID(name.substring(0, name.length() - SECRET_SUFFIX.length()),
+ dependentResource.getMetadata().getNamespace()));
+ }
}
diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java
index 94726d40ae..25e46fad16 100644
--- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java
+++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java
@@ -5,12 +5,12 @@
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
@KubernetesDependent(labelSelector = "app.kubernetes.io/managed-by=tomcat-operator")
public class DeploymentDependentResource
- extends CRUKubernetesDependentResource {
+ extends CRUDKubernetesDependentResource {
public DeploymentDependentResource() {
super(Deployment.class);
diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java
index 8efaadc0a8..3b526d02bc 100644
--- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java
+++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java
@@ -5,12 +5,11 @@
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.Creator;
-import io.javaoperatorsdk.operator.processing.dependent.Updater;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
-public class ServiceDependentResource extends KubernetesDependentResource
- implements Creator, Updater {
+@KubernetesDependent(labelSelector = "app.kubernetes.io/managed-by=tomcat-operator")
+public class ServiceDependentResource extends CRUDKubernetesDependentResource {
public ServiceDependentResource() {
super(Service.class);
@@ -23,6 +22,7 @@ protected Service desired(Tomcat tomcat, Context context) {
.editMetadata()
.withName(tomcatMetadata.getName())
.withNamespace(tomcatMetadata.getNamespace())
+ .addToLabels("app.kubernetes.io/managed-by", "tomcat-operator")
.endMetadata()
.editSpec()
.addToSelector("app", tomcatMetadata.getName())
diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java
index bba817436c..2fc9c35fe4 100644
--- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java
+++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ConfigMapDependentResource.java
@@ -10,7 +10,7 @@
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import static io.javaoperatorsdk.operator.sample.Utils.configMapName;
@@ -19,7 +19,7 @@
// this annotation only activates when using managed dependents and is not otherwise needed
@KubernetesDependent(labelSelector = SELECTOR)
-class ConfigMapDependentResource extends CRUKubernetesDependentResource {
+class ConfigMapDependentResource extends CRUDKubernetesDependentResource {
private static final Logger log = LoggerFactory.getLogger(ConfigMapDependentResource.class);
diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java
index 80a41e24d8..213be43428 100644
--- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java
+++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/DeploymentDependentResource.java
@@ -6,7 +6,7 @@
import io.fabric8.kubernetes.api.model.ConfigMapVolumeSourceBuilder;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import static io.javaoperatorsdk.operator.ReconcilerUtils.loadYaml;
@@ -15,8 +15,8 @@
import static io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler.SELECTOR;
// this annotation only activates when using managed dependents and is not otherwise needed
-@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
-class DeploymentDependentResource extends CRUKubernetesDependentResource {
+@KubernetesDependent(labelSelector = SELECTOR)
+class DeploymentDependentResource extends CRUDKubernetesDependentResource {
public DeploymentDependentResource() {
super(Deployment.class);
diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/IngressDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/IngressDependentResource.java
index 074f36cffb..703d3aceb1 100644
--- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/IngressDependentResource.java
+++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/IngressDependentResource.java
@@ -2,14 +2,14 @@
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
-import static io.javaoperatorsdk.operator.sample.Utils.*;
+import static io.javaoperatorsdk.operator.sample.Utils.makeDesiredIngress;
// this annotation only activates when using managed dependents and is not otherwise needed
@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
-public class IngressDependentResource extends CRUKubernetesDependentResource {
+public class IngressDependentResource extends CRUDKubernetesDependentResource {
public IngressDependentResource() {
super(Ingress.class);
diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java
index 84d670cfc5..1b89aa5333 100644
--- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java
+++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ServiceDependentResource.java
@@ -5,7 +5,6 @@
import io.fabric8.kubernetes.api.model.Service;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import static io.javaoperatorsdk.operator.ReconcilerUtils.loadYaml;
@@ -14,8 +13,9 @@
import static io.javaoperatorsdk.operator.sample.WebPageManagedDependentsReconciler.SELECTOR;
// this annotation only activates when using managed dependents and is not otherwise needed
-@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
-class ServiceDependentResource extends CRUKubernetesDependentResource {
+@KubernetesDependent(labelSelector = SELECTOR)
+class ServiceDependentResource extends
+ io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource {
public ServiceDependentResource() {
super(Service.class);