diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java
index b5e3fffcf0..dbd09a32cc 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AnnotationControllerConfiguration.java
@@ -17,9 +17,8 @@
import io.javaoperatorsdk.operator.OperatorException;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
-import io.javaoperatorsdk.operator.api.reconciler.Constants;
+import io.javaoperatorsdk.operator.api.reconciler.*;
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
-import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
@@ -54,9 +53,8 @@ public AnnotationControllerConfiguration(Reconciler
reconciler) {
this.reconciler = reconciler;
this.annotation = reconciler.getClass().getAnnotation(ControllerConfiguration.class);
if (annotation == null) {
- throw new OperatorException(
- "Missing mandatory @" + ControllerConfiguration.class.getSimpleName() +
- " annotation for reconciler: " + reconciler);
+ throw new OperatorException("Missing mandatory @" + CONTROLLER_CONFIG_ANNOTATION +
+ " annotation for reconciler: " + reconciler);
}
}
@@ -247,9 +245,9 @@ public List getDependentResources() {
final var context = "DependentResource of type '" + dependentType.getName() + "'";
spec = new DependentResourceSpec(dependentType, config, name,
Set.of(dependent.dependsOn()),
- instantiateConditionIfNotDefault(dependent.readyPostcondition(), context),
- instantiateConditionIfNotDefault(dependent.reconcilePrecondition(), context),
- instantiateConditionIfNotDefault(dependent.deletePostcondition(), context));
+ instantiateIfNotDefault(dependent.readyPostcondition(), Condition.class, context),
+ instantiateIfNotDefault(dependent.reconcilePrecondition(), Condition.class, context),
+ instantiateIfNotDefault(dependent.deletePostcondition(), Condition.class, context));
specsMap.put(name, spec);
}
@@ -258,10 +256,10 @@ public List getDependentResources() {
return specs;
}
- protected Condition, ?> instantiateConditionIfNotDefault(Class extends Condition> condition,
+ protected T instantiateIfNotDefault(Class extends T> toInstantiate, Class defaultClass,
String context) {
- if (condition != Condition.class) {
- return instantiateAndConfigureIfNeeded(condition, Condition.class, context);
+ if (!defaultClass.equals(toInstantiate)) {
+ return instantiateAndConfigureIfNeeded(toInstantiate, defaultClass, context);
}
return null;
}
@@ -287,6 +285,7 @@ private Object createKubernetesResourceConfig(Class extends DependentResource>
OnUpdateFilter extends HasMetadata> onUpdateFilter = null;
OnDeleteFilter extends HasMetadata> onDeleteFilter = null;
GenericFilter extends HasMetadata> genericFilter = null;
+ ResourceDiscriminator, ? extends HasMetadata> resourceDiscriminator = null;
if (kubeDependent != null) {
if (!Arrays.equals(KubernetesDependent.DEFAULT_NAMESPACES,
kubeDependent.namespaces())) {
@@ -297,7 +296,6 @@ private Object createKubernetesResourceConfig(Class extends DependentResource>
final var fromAnnotation = kubeDependent.labelSelector();
labelSelector = Constants.NO_VALUE_SET.equals(fromAnnotation) ? null : fromAnnotation;
-
final var context =
KUBE_DEPENDENT_NAME + " annotation on " + dependentType.getName() + " DependentResource";
onAddFilter = createFilter(kubeDependent.onAddFilter(), OnAddFilter.class, context)
@@ -311,10 +309,15 @@ private Object createKubernetesResourceConfig(Class extends DependentResource>
genericFilter =
createFilter(kubeDependent.genericFilter(), GenericFilter.class, context)
.orElse(null);
+
+ resourceDiscriminator =
+ instantiateIfNotDefault(kubeDependent.resourceDiscriminator(),
+ ResourceDiscriminator.class, context);
}
config =
- new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS, onAddFilter,
+ new KubernetesDependentResourceConfig(namespaces, labelSelector, configuredNS,
+ resourceDiscriminator, onAddFilter,
onUpdateFilter, onDeleteFilter, genericFilter);
return config;
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Context.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Context.java
index 845810c8a1..2e4fb98e6f 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Context.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Context.java
@@ -6,20 +6,27 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ManagedDependentResourceContext;
+import io.javaoperatorsdk.operator.processing.event.EventSourceRetriever;
public interface Context {
Optional getRetryInfo();
- default Optional getSecondaryResource(Class expectedType) {
- return getSecondaryResource(expectedType, null);
+ default Optional getSecondaryResource(Class expectedType) {
+ return getSecondaryResource(expectedType, (String) null);
}
- Set getSecondaryResources(Class expectedType);
+ Set getSecondaryResources(Class expectedType);
- Optional getSecondaryResource(Class expectedType, String eventSourceName);
+ @Deprecated(forRemoval = true)
+ Optional getSecondaryResource(Class expectedType, String eventSourceName);
+
+ Optional getSecondaryResource(Class expectedType,
+ ResourceDiscriminator discriminator);
ControllerConfiguration getControllerConfiguration();
ManagedDependentResourceContext managedDependentResourceContext();
+
+ EventSourceRetriever
eventSourceRetriever();
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DefaultContext.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DefaultContext.java
index afb37a8c53..cb7f4ae63b 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DefaultContext.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DefaultContext.java
@@ -9,6 +9,7 @@
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DefaultManagedDependentResourceContext;
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ManagedDependentResourceContext;
import io.javaoperatorsdk.operator.processing.Controller;
+import io.javaoperatorsdk.operator.processing.event.EventSourceRetriever;
public class DefaultContext
implements Context
{
@@ -47,6 +48,12 @@ public Optional getSecondaryResource(Class expectedType, String eventS
.getSecondaryResource(primaryResource);
}
+ @Override
+ public Optional getSecondaryResource(Class expectedType,
+ ResourceDiscriminator discriminator) {
+ return discriminator.distinguish(expectedType, primaryResource, this);
+ }
+
@Override
public ControllerConfiguration getControllerConfiguration() {
return controllerConfiguration;
@@ -57,6 +64,11 @@ public ManagedDependentResourceContext managedDependentResourceContext() {
return defaultManagedDependentResourceContext;
}
+ @Override
+ public EventSourceRetriever
eventSourceRetriever() {
+ return controller.getEventSourceManager();
+ }
+
public DefaultContext
setRetryInfo(RetryInfo retryInfo) {
this.retryInfo = retryInfo;
return this;
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceDiscriminator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceDiscriminator.java
new file mode 100644
index 0000000000..072e7d8078
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceDiscriminator.java
@@ -0,0 +1,11 @@
+package io.javaoperatorsdk.operator.api.reconciler;
+
+import java.util.Optional;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+
+public interface ResourceDiscriminator {
+
+ Optional distinguish(Class resource, P primary, Context context);
+
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceIDMatcherDiscriminator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceIDMatcherDiscriminator.java
new file mode 100644
index 0000000000..f28633252a
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ResourceIDMatcherDiscriminator.java
@@ -0,0 +1,25 @@
+package io.javaoperatorsdk.operator.api.reconciler;
+
+import java.util.Optional;
+import java.util.function.Function;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
+
+public class ResourceIDMatcherDiscriminator
+ implements ResourceDiscriminator {
+
+ private final Function mapper;
+
+ public ResourceIDMatcherDiscriminator(Function
mapper) {
+ this.mapper = mapper;
+ }
+
+ @Override
+ public Optional distinguish(Class resource, P primary, Context context) {
+ var resourceID = mapper.apply(primary);
+ return context.getSecondaryResources(resource).stream()
+ .filter(resourceID::isSameResource)
+ .findFirst();
+ }
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java
index 0923d19473..8d31778488 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResource.java
@@ -1,8 +1,9 @@
package io.javaoperatorsdk.operator.api.reconciler.dependent;
+import java.util.Optional;
+
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.processing.ResourceOwner;
/**
* An interface to implement and provide dependent resource support.
@@ -10,7 +11,7 @@
* @param the dependent resource type
* @param the associated primary resource type
*/
-public interface DependentResource extends ResourceOwner {
+public interface DependentResource {
/**
* Reconciles the dependent resource given the desired primary state
@@ -21,6 +22,17 @@ public interface DependentResource extends ResourceOwn
*/
ReconcileResult reconcile(P primary, Context context);
+ /**
+ * Retrieves the resource type associated with this DependentResource
+ *
+ * @return the resource type associated with this DependentResource
+ */
+ Class resourceType();
+
+ default Optional getSecondaryResource(P primary, Context context) {
+ return Optional.empty();
+ }
+
/**
* Computes a default name for the specified DependentResource class
*
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/ResourceOwner.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/ResourceOwner.java
deleted file mode 100644
index f9c02a8a33..0000000000
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/ResourceOwner.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package io.javaoperatorsdk.operator.processing;
-
-import java.util.Optional;
-
-import io.fabric8.kubernetes.api.model.HasMetadata;
-
-public interface ResourceOwner {
-
- /**
- * Retrieves the resource type associated with this ResourceOwner
- *
- * @return the resource type associated with this ResourceOwner
- */
- Class resourceType();
-
- /**
- * Retrieves the resource associated with the specified primary one, returning the actual state of
- * the resource. Typically, this state might come from a local cache, updated after
- * reconciliation.
- *
- * @param primary the primary resource for which we want to retrieve the secondary resource
- * @return an {@link Optional} containing the secondary resource or {@link Optional#empty()} if it
- * doesn't exist
- */
- Optional getSecondaryResource(P primary);
-}
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 5dbdba9358..1abfb3df4b 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
@@ -1,11 +1,14 @@
package io.javaoperatorsdk.operator.processing.dependent;
+import java.util.Optional;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.Ignore;
+import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
import io.javaoperatorsdk.operator.processing.event.ResourceID;
@@ -21,6 +24,8 @@ public abstract class AbstractDependentResource
protected Creator creator;
protected Updater updater;
+ private ResourceDiscriminator resourceDiscriminator;
+
@SuppressWarnings("unchecked")
public AbstractDependentResource() {
creator = creatable ? (Creator) this : null;
@@ -29,7 +34,7 @@ public AbstractDependentResource() {
@Override
public ReconcileResult reconcile(P primary, Context context) {
- var maybeActual = getSecondaryResource(primary);
+ Optional maybeActual = getSecondaryResource(primary, context);
if (creatable || updatable) {
if (maybeActual.isEmpty()) {
if (creatable) {
@@ -62,6 +67,11 @@ public ReconcileResult reconcile(P primary, Context context) {
return ReconcileResult.noOperation(maybeActual.orElse(null));
}
+ public Optional getSecondaryResource(P primary, Context context) {
+ return resourceDiscriminator == null ? context.getSecondaryResource(resourceType())
+ : resourceDiscriminator.distinguish(resourceType(), primary, context);
+ }
+
private void throwIfNull(R desired, P primary, String descriptor) {
if (desired == null) {
throw new DependentResourceException(
@@ -118,4 +128,13 @@ protected R desired(P primary, Context
context) {
throw new IllegalStateException(
"desired method must be implemented if this DependentResource can be created and/or updated");
}
+
+ public void setResourceDiscriminator(
+ ResourceDiscriminator resourceDiscriminator) {
+ this.resourceDiscriminator = resourceDiscriminator;
+ }
+
+ public ResourceDiscriminator getResourceDiscriminator() {
+ return resourceDiscriminator;
+ }
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java
index 0ceba16826..be0db98393 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractEventSourceHolderDependentResource.java
@@ -19,12 +19,16 @@ public abstract class AbstractEventSourceHolderDependentResource {
private T eventSource;
+ private final Class resourceType;
private boolean isCacheFillerEventSource;
protected OnAddFilter onAddFilter;
protected OnUpdateFilter onUpdateFilter;
protected OnDeleteFilter onDeleteFilter;
protected GenericFilter genericFilter;
+ protected AbstractEventSourceHolderDependentResource(Class resourceType) {
+ this.resourceType = resourceType;
+ }
public EventSource initEventSource(EventSourceContext context) {
// some sub-classes (e.g. KubernetesDependentResource) can have their event source created
@@ -42,6 +46,11 @@ public EventSource initEventSource(EventSourceContext
context) {
return eventSource;
}
+ @Override
+ public Class resourceType() {
+ return resourceType;
+ }
+
protected abstract T createEventSource(EventSourceContext context);
protected void setEventSource(T eventSource) {
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractCachingDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractCachingDependentResource.java
deleted file mode 100644
index 242625bc5d..0000000000
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractCachingDependentResource.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.javaoperatorsdk.operator.processing.dependent.external;
-
-import java.util.Optional;
-
-import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.javaoperatorsdk.operator.api.reconciler.Ignore;
-import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource;
-import io.javaoperatorsdk.operator.processing.event.source.ExternalResourceCachingEventSource;
-
-@Ignore
-public abstract class AbstractCachingDependentResource
- extends
- AbstractEventSourceHolderDependentResource> {
- private final Class resourceType;
-
- protected AbstractCachingDependentResource(Class resourceType) {
- this.resourceType = resourceType;
- }
-
- @Override
- public Class resourceType() {
- return resourceType;
- }
-
- @Override
- public Optional getSecondaryResource(P primaryResource) {
- return eventSource().getSecondaryResource(primaryResource);
- }
-}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractPollingDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractPollingDependentResource.java
index 6bab6f48cf..2ccba025a7 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractPollingDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractPollingDependentResource.java
@@ -2,11 +2,15 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.reconciler.Ignore;
+import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource;
import io.javaoperatorsdk.operator.processing.event.source.CacheKeyMapper;
+import io.javaoperatorsdk.operator.processing.event.source.ExternalResourceCachingEventSource;
@Ignore
public abstract class AbstractPollingDependentResource
- extends AbstractCachingDependentResource implements CacheKeyMapper {
+ extends
+ AbstractEventSourceHolderDependentResource>
+ implements CacheKeyMapper {
public static final int DEFAULT_POLLING_PERIOD = 5000;
private long pollingPeriod;
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResource.java
index 0675db5f1a..748452c30c 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResource.java
@@ -33,7 +33,7 @@ public AbstractSimpleDependentResource(UpdatableCache cache) {
}
@Override
- public Optional getSecondaryResource(HasMetadata primaryResource) {
+ public Optional getSecondaryResource(P primaryResource, Context context) {
return cache.get(ResourceID.fromResource(primaryResource));
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java
index f66ff95373..603f4ae62e 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependent.java
@@ -6,6 +6,8 @@
import java.lang.annotation.Target;
import io.javaoperatorsdk.operator.api.reconciler.Constants;
+import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
+import io.javaoperatorsdk.operator.processing.event.source.filter.*;
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter;
@@ -68,4 +70,6 @@
* itself if no value is set
*/
Class extends GenericFilter> genericFilter() default GenericFilter.class;
+
+ Class extends ResourceDiscriminator> resourceDiscriminator() default ResourceDiscriminator.class;
}
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 930e5fd5b4..328a061e6b 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
@@ -1,16 +1,13 @@
package io.javaoperatorsdk.operator.processing.dependent.kubernetes;
import java.util.HashMap;
-import java.util.Optional;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.fabric8.kubernetes.api.model.KubernetesResourceList;
import io.fabric8.kubernetes.client.KubernetesClient;
-import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.javaoperatorsdk.operator.OperatorException;
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
@@ -41,13 +38,12 @@ public abstract class KubernetesDependentResource matcher;
private final ResourceUpdatePreProcessor processor;
- private final Class resourceType;
private final boolean garbageCollected = this instanceof GarbageCollected;
private KubernetesDependentResourceConfig kubernetesDependentResourceConfig;
@SuppressWarnings("unchecked")
public KubernetesDependentResource(Class resourceType) {
- this.resourceType = resourceType;
+ super(resourceType);
matcher = this instanceof Matcher ? (Matcher) this
: GenericKubernetesResourceMatcher.matcherFor(resourceType, this);
@@ -75,6 +71,7 @@ private void configureWith(String labelSelector, Set namespaces,
.build();
configureWith(new InformerEventSource<>(ic, context));
+
}
@SuppressWarnings("unchecked")
@@ -94,7 +91,7 @@ private SecondaryToPrimaryMapper getSecondaryToPrimaryMapper() {
/**
* Use to share informers between event more resources.
*
- * @param informerEventSource informer to use*
+ * @param informerEventSource informer to use
*/
public void configureWith(InformerEventSource informerEventSource) {
setEventSource(informerEventSource);
@@ -125,12 +122,12 @@ protected R handleUpdate(R actual, R desired, P primary, Context context) {
@SuppressWarnings("unused")
public R create(R target, P primary, Context
context) {
- return prepare(target, primary, "Creating").create(target);
+ return prepare(target, primary, "Creating").create();
}
public R update(R actual, R target, P primary, Context
context) {
var updatedActual = processor.replaceSpecOnActual(actual, target, context);
- return prepare(target, primary, "Updating").replace(updatedActual);
+ return prepare(updatedActual, primary, "Updating").replace();
}
public Result match(R actualResource, P primary, Context context) {
@@ -138,13 +135,11 @@ public Result match(R actualResource, P primary, Context context) {
}
public void delete(P primary, Context
context) {
- var resource = getSecondaryResource(primary);
- resource.ifPresent(r -> client.resource(r).delete());
+ getSecondaryResource(primary, context).ifPresent(r -> client.resource(r).delete());
}
@SuppressWarnings("unchecked")
- protected NonNamespaceOperation, Resource> prepare(R desired,
- P primary, String actionName) {
+ protected Resource prepare(R desired, P primary, String actionName) {
log.debug("{} target resource with type: {}, with id: {}",
actionName,
desired.getClass(),
@@ -155,7 +150,8 @@ protected NonNamespaceOperation, Resource> prepa
addDefaultSecondaryToPrimaryMapperAnnotations(desired, primary);
}
Class targetClass = (Class) desired.getClass();
- return client.resources(targetClass).inNamespace(desired.getMetadata().getNamespace());
+ return client.resources(targetClass).inNamespace(desired.getMetadata().getNamespace())
+ .resource(desired);
}
@Override
@@ -167,6 +163,7 @@ protected InformerEventSource createEventSource(EventSourceContext cont
onUpdateFilter = kubernetesDependentResourceConfig.onUpdateFilter();
onDeleteFilter = kubernetesDependentResourceConfig.onDeleteFilter();
genericFilter = kubernetesDependentResourceConfig.genericFilter();
+ setResourceDiscriminator(kubernetesDependentResourceConfig.getResourceDiscriminator());
configureWith(kubernetesDependentResourceConfig.labelSelector(),
kubernetesDependentResourceConfig.namespaces(),
@@ -203,16 +200,6 @@ protected boolean addOwnerReference() {
return garbageCollected;
}
- @Override
- public Class resourceType() {
- return resourceType;
- }
-
- @Override
- public Optional getSecondaryResource(P primaryResource) {
- return eventSource().getSecondaryResource(primaryResource);
- }
-
@Override
public void setKubernetesClient(KubernetesClient kubernetesClient) {
this.client = kubernetesClient;
@@ -235,5 +222,4 @@ private void prepareEventFiltering(R desired, ResourceID resourceID) {
private void cleanupAfterEventFiltering(ResourceID resourceID) {
eventSource().cleanupOnCreateOrUpdateEventFiltering(resourceID);
}
-
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java
index e4a75b165a..e2a2c0f684 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResourceConfig.java
@@ -3,6 +3,7 @@
import java.util.Set;
import io.javaoperatorsdk.operator.api.reconciler.Constants;
+import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter;
@@ -15,7 +16,7 @@ public class KubernetesDependentResourceConfig {
private Set namespaces = Constants.SAME_AS_CONTROLLER_NAMESPACES_SET;
private String labelSelector = NO_VALUE_SET;
private boolean namespacesWereConfigured = false;
-
+ private ResourceDiscriminator resourceDiscriminator;
private OnAddFilter onAddFilter;
@@ -27,9 +28,9 @@ public class KubernetesDependentResourceConfig {
public KubernetesDependentResourceConfig() {}
- @SuppressWarnings("rawtypes")
public KubernetesDependentResourceConfig(Set namespaces, String labelSelector,
- boolean configuredNS, OnAddFilter onAddFilter,
+ boolean configuredNS, ResourceDiscriminator resourceDiscriminator,
+ OnAddFilter onAddFilter,
OnUpdateFilter onUpdateFilter,
OnDeleteFilter onDeleteFilter, GenericFilter genericFilter) {
this.namespaces = namespaces;
@@ -39,10 +40,11 @@ public KubernetesDependentResourceConfig(Set namespaces, String labelSel
this.onUpdateFilter = onUpdateFilter;
this.onDeleteFilter = onDeleteFilter;
this.genericFilter = genericFilter;
+ this.resourceDiscriminator = resourceDiscriminator;
}
public KubernetesDependentResourceConfig(Set namespaces, String labelSelector) {
- this(namespaces, labelSelector, true, null, null, null, null);
+ this(namespaces, labelSelector, true, null, null, null, null, null);
}
public KubernetesDependentResourceConfig setNamespaces(Set namespaces) {
@@ -73,17 +75,21 @@ public OnAddFilter onAddFilter() {
return onAddFilter;
}
- @SuppressWarnings("rawtypes")
- public OnUpdateFilter onUpdateFilter() {
+
+ public OnUpdateFilter onUpdateFilter() {
return onUpdateFilter;
}
- @SuppressWarnings("rawtypes")
- public OnDeleteFilter onDeleteFilter() {
+ public OnDeleteFilter onDeleteFilter() {
return onDeleteFilter;
}
public GenericFilter genericFilter() {
return genericFilter;
}
+
+ @SuppressWarnings("rawtypes")
+ public ResourceDiscriminator getResourceDiscriminator() {
+ return resourceDiscriminator;
+ }
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DependentResourceNode.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DependentResourceNode.java
index e317145916..32cef6c68e 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DependentResourceNode.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/DependentResourceNode.java
@@ -5,6 +5,7 @@
import java.util.Optional;
import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
@SuppressWarnings("rawtypes")
@@ -85,4 +86,8 @@ public DependentResourceNode setReadyPostcondition(Condition readyPo
public List getParents() {
return parents;
}
+
+ protected R getSecondaryResource(P primary, Context context) {
+ return getDependentResource().getSecondaryResource(primary, context).orElse(null);
+ }
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutor.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutor.java
index 98c6789869..45541b91d6 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutor.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutor.java
@@ -104,12 +104,10 @@ public void run() {
((Deleter
) dependentResourceNode.getDependentResource()).delete(primary, context);
deleteCalled.add(dependentResourceNode);
}
- boolean deletePostConditionMet =
- deletePostCondition.map(c -> c.isMet(primary,
- dependentResourceNode.getDependentResource().getSecondaryResource(primary)
- .orElse(null),
- context)).orElse(true);
-
+ boolean deletePostConditionMet = deletePostCondition
+ .map(c -> c.isMet(primary, dependentResourceNode.getSecondaryResource(primary, context),
+ context))
+ .orElse(true);
if (deletePostConditionMet) {
alreadyVisited.add(dependentResourceNode);
handleDependentCleaned(dependentResourceNode);
@@ -127,6 +125,7 @@ public void run() {
}
}
+
private synchronized void handleDependentCleaned(
DependentResourceNode, P> dependentResourceNode) {
var dependOns = dependentResourceNode.getDependsOn();
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutor.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutor.java
index 14028cb980..33ecd12f77 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutor.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutor.java
@@ -85,8 +85,7 @@ private synchronized void handleReconcile(DependentResourceNode depend
}
boolean reconcileConditionMet = dependentResourceNode.getReconcilePrecondition()
- .map(rc -> rc.isMet(primary,
- dependentResourceNode.getDependentResource().getSecondaryResource(primary).orElse(null),
+ .map(rc -> rc.isMet(primary, dependentResourceNode.getSecondaryResource(primary, context),
context))
.orElse(true);
@@ -167,9 +166,12 @@ public void run() {
ReconcileResult reconcileResult = dependentResource.reconcile(primary, context);
reconcileResults.put(dependentResource, reconcileResult);
reconciled.add(dependentResourceNode);
+
boolean ready = dependentResourceNode.getReadyPostcondition()
.map(rc -> rc.isMet(primary,
- dependentResourceNode.getDependentResource().getSecondaryResource(primary)
+ context
+ .getSecondaryResource(
+ dependentResourceNode.getDependentResource().resourceType())
.orElse(null),
context))
.orElse(true);
@@ -210,8 +212,8 @@ public void run() {
}
boolean deletePostConditionMet =
deletePostCondition.map(c -> c.isMet(primary,
- dependentResourceNode.getDependentResource().getSecondaryResource(primary)
- .orElse(null),
+ context.getSecondaryResource(
+ dependentResourceNode.getDependentResource().resourceType()).orElse(null),
context)).orElse(true);
if (deletePostConditionMet) {
alreadyVisited.add(dependentResourceNode);
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventProcessor.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventProcessor.java
index 58bf5ee00a..e0280796b2 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventProcessor.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventProcessor.java
@@ -135,7 +135,8 @@ private void handleMarkedEventForResource(ResourceState state) {
private void submitReconciliationExecution(ResourceState state) {
try {
boolean controllerUnderExecution = isControllerUnderExecution(state);
- Optional maybeLatest = cache.get(state.getId());
+ final var resourceID = state.getId();
+ Optional maybeLatest = cache.get(resourceID);
maybeLatest.ifPresent(MDCUtils::addResourceInfo);
if (!controllerUnderExecution && maybeLatest.isPresent()) {
var rateLimit = state.getRateLimit();
@@ -145,24 +146,24 @@ private void submitReconciliationExecution(ResourceState state) {
}
var rateLimiterPermission = rateLimiter.isLimited(rateLimit);
if (rateLimiterPermission.isPresent()) {
- handleRateLimitedSubmission(state.getId(), rateLimiterPermission.get());
+ handleRateLimitedSubmission(resourceID, rateLimiterPermission.get());
return;
}
state.setUnderProcessing(true);
final var latest = maybeLatest.get();
ExecutionScope executionScope = new ExecutionScope<>(latest, state.getRetry());
state.unMarkEventReceived();
- metrics.reconcileCustomResource(state.getId(), state.getRetry(), metricsMetadata);
+ metrics.reconcileCustomResource(resourceID, state.getRetry(), metricsMetadata);
log.debug("Executing events for custom resource. Scope: {}", executionScope);
executor.execute(new ReconcilerExecutor(executionScope));
} else {
log.debug(
"Skipping executing controller for resource id: {}. Controller in execution: {}. Latest Resource present: {}",
- state,
+ resourceID,
controllerUnderExecution,
maybeLatest.isPresent());
if (maybeLatest.isEmpty()) {
- log.debug("no custom resource found in cache for ResourceID: {}", state);
+ log.debug("no custom resource found in cache for resource id: {}", resourceID);
}
}
} finally {
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java
index 3f1e5e848d..fc68e6e413 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java
@@ -23,7 +23,8 @@
import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceAction;
import io.javaoperatorsdk.operator.processing.event.source.timer.TimerEventSource;
-public class EventSourceManager implements LifecycleAware {
+public class EventSourceManager
+ implements LifecycleAware, EventSourceRetriever
{
private static final Logger log = LoggerFactory.getLogger(EventSourceManager.class);
@@ -171,17 +172,23 @@ public ControllerResourceEventSource
getControllerResourceEventSource() {
return eventSources.controllerResourceEventSource();
}
- ResourceEventSource getResourceEventSourceFor(
- Class dependentType) {
+ @Override
+ public ResourceEventSource getResourceEventSourceFor(Class dependentType) {
return getResourceEventSourceFor(dependentType, null);
}
- public List> getEventSourcesFor(Class dependentType) {
+ public List> getResourceEventSourcesFor(Class dependentType) {
return eventSources.getEventSources(dependentType);
}
- public ResourceEventSource getResourceEventSourceFor(
- Class dependentType, String qualifier) {
+ @Deprecated
+ public List> getEventSourcesFor(Class dependentType) {
+ return eventSources.getEventSources(dependentType);
+ }
+
+ @Override
+ public ResourceEventSource getResourceEventSourceFor(
+ Class dependentType, String qualifier) {
Objects.requireNonNull(dependentType, "dependentType is Mandatory");
return eventSources.get(dependentType, qualifier);
}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceRetriever.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceRetriever.java
new file mode 100644
index 0000000000..a31d8902b0
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceRetriever.java
@@ -0,0 +1,18 @@
+package io.javaoperatorsdk.operator.processing.event;
+
+import java.util.List;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
+
+public interface EventSourceRetriever {
+
+ ResourceEventSource getResourceEventSourceFor(
+ Class dependentType);
+
+ ResourceEventSource getResourceEventSourceFor(
+ Class dependentType, String qualifier);
+
+ List> getResourceEventSourcesFor(Class dependentType);
+
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSources.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSources.java
index 17de7ff947..e4fabe7ff8 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSources.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSources.java
@@ -8,7 +8,6 @@
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.processing.Controller;
-import io.javaoperatorsdk.operator.processing.ResourceOwner;
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
import io.javaoperatorsdk.operator.processing.event.source.ResourceEventSource;
import io.javaoperatorsdk.operator.processing.event.source.controller.ControllerResourceEventSource;
@@ -86,8 +85,8 @@ public void add(String name, EventSource eventSource) {
@SuppressWarnings("rawtypes")
private Class> getResourceType(EventSource source) {
- return source instanceof ResourceOwner
- ? ((ResourceOwner) source).resourceType()
+ return source instanceof ResourceEventSource
+ ? ((ResourceEventSource) source).resourceType()
: source.getClass();
}
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 7baeab6a4b..b6c2d976e3 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
@@ -54,6 +54,12 @@ public boolean equals(Object o) {
that.namespace);
}
+ public boolean isSameResource(HasMetadata hasMetadata) {
+ final var metadata = hasMetadata.getMetadata();
+ return getName().equals(metadata.getName()) &&
+ getNamespace().map(ns -> ns.equals(metadata.getNamespace())).orElse(true);
+ }
+
@Override
public int hashCode() {
return Objects.hash(name, namespace);
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventSource.java
index bf6b9c0fd3..38b5d7007f 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventSource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/ResourceEventSource.java
@@ -4,14 +4,19 @@
import java.util.Set;
import io.fabric8.kubernetes.api.model.HasMetadata;
-import io.javaoperatorsdk.operator.processing.ResourceOwner;
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter;
import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter;
-public interface ResourceEventSource extends EventSource,
- ResourceOwner {
+public interface ResourceEventSource extends EventSource {
+
+ /**
+ * Retrieves the resource type associated with this ResourceEventSource
+ *
+ * @return the resource type associated with this ResourceEventSource
+ */
+ Class resourceType();
default Optional getSecondaryResource(P primary) {
var resources = getSecondaryResources(primary);
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java
index 6ebd63a7eb..cc9af59094 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/ManagedInformerEventSource.java
@@ -93,10 +93,10 @@ public void handleRecentResourceCreate(ResourceID resourceID, R resource) {
public Optional get(ResourceID resourceID) {
Optional resource = temporaryResourceCache.getResourceFromCache(resourceID);
if (resource.isPresent()) {
- log.debug("Resource found in temporal cache for Resource ID: {}", resourceID);
+ log.debug("Resource found in temporary cache for Resource ID: {}", resourceID);
return resource;
} else {
- log.debug("Resource not found in temporal cache reading it from informer cache," +
+ log.debug("Resource not found in temporary cache reading it from informer cache," +
" for Resource ID: {}", resourceID);
return cache.get(resourceID);
}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java
index 127cd535b1..6e486b5347 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverriderTest.java
@@ -1,6 +1,5 @@
package io.javaoperatorsdk.operator.api.config;
-import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.Test;
@@ -85,10 +84,6 @@ public Class resourceType() {
return Object.class;
}
- @Override
- public Optional getSecondaryResource(ConfigMap primary) {
- return Optional.empty();
- }
}
}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResourceTest.java
index 4edd3dfb4c..b93abd45c0 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResourceTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResourceTest.java
@@ -16,7 +16,6 @@
class AbstractDependentResourceTest {
-
@Test
void throwsExceptionIfDesiredIsNullOnCreate() {
TestDependentResource testDependentResource = new TestDependentResource();
@@ -80,7 +79,8 @@ public Class resourceType() {
}
@Override
- public Optional getSecondaryResource(TestCustomResource primary) {
+ public Optional getSecondaryResource(TestCustomResource primary,
+ Context context) {
return Optional.ofNullable(secondary);
}
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/EmptyTestDependentResource.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/EmptyTestDependentResource.java
index aa75849051..dab1bc0132 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/EmptyTestDependentResource.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/EmptyTestDependentResource.java
@@ -1,7 +1,5 @@
package io.javaoperatorsdk.operator.processing.dependent;
-import java.util.Optional;
-
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
@@ -17,11 +15,6 @@ public ReconcileResult reconcile(TestCustomResource primary,
return null;
}
- @Override
- public Optional getSecondaryResource(TestCustomResource primaryResource) {
- return Optional.empty();
- }
-
@Override
public Class resourceType() {
return Deployment.class;
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResourceTest.java
index e020fd27a3..520f44365f 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResourceTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/external/AbstractSimpleDependentResourceTest.java
@@ -45,14 +45,14 @@ void getsTheResourceFromSupplyIfReconciling() {
simpleDependentResource.reconcile(TestUtils.testCustomResource1(), null);
verify(supplierMock, times(1)).get();
- assertThat(simpleDependentResource.getSecondaryResource(TestUtils.testCustomResource1()))
+ assertThat(simpleDependentResource.getSecondaryResource(TestUtils.testCustomResource1(), null))
.isPresent()
.isEqualTo(Optional.of(SampleExternalResource.testResource1()));
}
@Test
void getResourceReadsTheResourceFromCache() {
- simpleDependentResource.getSecondaryResource(TestUtils.testCustomResource1());
+ simpleDependentResource.getSecondaryResource(TestUtils.testCustomResource1(), null);
verify(supplierMock, times(0)).get();
verify(updatableCacheMock, times(1)).get(any());
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java
index 8dfab3fa20..9c10c06cc0 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/AbstractWorkflowExecutorTest.java
@@ -3,7 +3,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
@@ -49,11 +48,6 @@ public Class resourceType() {
return String.class;
}
- @Override
- public Optional getSecondaryResource(TestCustomResource primary) {
- return Optional.of(VALUE);
- }
-
@Override
public String toString() {
return name;
@@ -113,11 +107,6 @@ public Class resourceType() {
return String.class;
}
- @Override
- public Optional getSecondaryResource(TestCustomResource primary) {
- return Optional.of(VALUE);
- }
-
@Override
public String toString() {
return name;
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutorTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutorTest.java
index 7c1c5d6ff6..56bd876687 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutorTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowCleanupExecutorTest.java
@@ -4,17 +4,20 @@
import org.junit.jupiter.api.Test;
import io.javaoperatorsdk.operator.AggregatedOperatorException;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.workflow.builder.WorkflowBuilder;
import io.javaoperatorsdk.operator.sample.simple.TestCustomResource;
import static io.javaoperatorsdk.operator.processing.dependent.workflow.ExecutionAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
class WorkflowCleanupExecutorTest extends AbstractWorkflowExecutorTest {
protected TestDeleterDependent dd1 = new TestDeleterDependent("DR_DELETER_1");
protected TestDeleterDependent dd2 = new TestDeleterDependent("DR_DELETER_2");
protected TestDeleterDependent dd3 = new TestDeleterDependent("DR_DELETER_3");
+ Context mockContext = mock(Context.class);
@Test
void cleanUpDiamondWorkflow() {
@@ -45,7 +48,7 @@ void dontDeleteIfDependentErrored() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.cleanup(new TestCustomResource(), null);
+ var res = workflow.cleanup(new TestCustomResource(), mockContext);
assertThrows(AggregatedOperatorException.class,
res::throwAggregateExceptionIfErrorsPresent);
@@ -64,7 +67,7 @@ void cleanupConditionTrivialCase() {
.addDependentResource(dd2).dependsOn(dd1).withDeletePostcondition(noMetDeletePostCondition)
.build();
- var res = workflow.cleanup(new TestCustomResource(), null);
+ var res = workflow.cleanup(new TestCustomResource(), mockContext);
assertThat(executionHistory).deleted(dd2).notReconciled(dd1);
Assertions.assertThat(res.getDeleteCalledOnDependents()).containsExactlyInAnyOrder(dd2);
@@ -79,7 +82,7 @@ void cleanupConditionMet() {
.addDependentResource(dd2).dependsOn(dd1).withDeletePostcondition(metDeletePostCondition)
.build();
- var res = workflow.cleanup(new TestCustomResource(), null);
+ var res = workflow.cleanup(new TestCustomResource(), mockContext);
assertThat(executionHistory).deleted(dd2, dd1);
@@ -99,7 +102,7 @@ void cleanupConditionDiamondWorkflow() {
.addDependentResource(dd4).dependsOn(dd2, dd3)
.build();
- var res = workflow.cleanup(new TestCustomResource(), null);
+ var res = workflow.cleanup(new TestCustomResource(), mockContext);
assertThat(executionHistory)
.reconciledInOrder(dd4, dd2)
diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutorTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutorTest.java
index fa9d757b67..873cf66cb6 100644
--- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutorTest.java
+++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/workflow/WorkflowReconcileExecutorTest.java
@@ -4,11 +4,13 @@
import org.junit.jupiter.api.Test;
import io.javaoperatorsdk.operator.AggregatedOperatorException;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.workflow.builder.WorkflowBuilder;
import io.javaoperatorsdk.operator.sample.simple.TestCustomResource;
import static io.javaoperatorsdk.operator.processing.dependent.workflow.ExecutionAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
@SuppressWarnings("rawtypes")
class WorkflowReconcileExecutorTest extends AbstractWorkflowExecutorTest {
@@ -21,6 +23,8 @@ class WorkflowReconcileExecutorTest extends AbstractWorkflowExecutorTest {
private final Condition notMetReadyCondition =
(primary, secondary, context) -> false;
+ Context mockContext = mock(Context.class);
+
@Test
void reconcileTopLevelResources() {
var workflow = new WorkflowBuilder()
@@ -28,7 +32,7 @@ void reconcileTopLevelResources() {
.addDependentResource(dr2)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).reconciled(dr1, dr2);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
@@ -42,7 +46,7 @@ void reconciliationWithSimpleDependsOn() {
.addDependentResource(dr2).dependsOn(dr1)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
assertThat(executionHistory).reconciledInOrder(dr1, dr2);
@@ -61,7 +65,7 @@ void reconciliationWithTwoTheDependsOns() {
.addDependentResource(dr3).dependsOn(dr1)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
assertThat(executionHistory)
@@ -83,7 +87,7 @@ void diamondShareWorkflowReconcile() {
.addDependentResource(dr4).dependsOn(dr3).dependsOn(dr2)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
assertThat(executionHistory)
@@ -103,7 +107,7 @@ void exceptionHandlingSimpleCases() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThrows(AggregatedOperatorException.class,
res::throwAggregateExceptionIfErrorsPresent);
@@ -123,7 +127,7 @@ void dependentsOnErroredResourceNotReconciled() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThrows(AggregatedOperatorException.class,
res::throwAggregateExceptionIfErrorsPresent);
@@ -145,7 +149,7 @@ void oneBranchErrorsOtherCompletes() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThrows(AggregatedOperatorException.class,
res::throwAggregateExceptionIfErrorsPresent);
@@ -164,7 +168,7 @@ void onlyOneDependsOnErroredResourceNotReconciled() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThrows(AggregatedOperatorException.class,
res::throwAggregateExceptionIfErrorsPresent);
@@ -182,7 +186,7 @@ void simpleReconcileCondition() {
.addDependentResource(drDeleter).withReconcilePrecondition(not_met_reconcile_condition)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).notReconciled(dr1).reconciled(dr2).deleted(drDeleter);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
@@ -200,7 +204,7 @@ void triangleOnceConditionNotMet() {
.dependsOn(dr1)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).reconciledInOrder(dr1, dr2).deleted(drDeleter);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
@@ -222,7 +226,7 @@ void reconcileConditionTransitiveDelete() {
.withReconcilePrecondition(met_reconcile_condition)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
assertThat(executionHistory).notReconciled(dr2);
@@ -246,7 +250,7 @@ void reconcileConditionAlsoErrorDependsOn() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThrows(AggregatedOperatorException.class,
res::throwAggregateExceptionIfErrorsPresent);
@@ -267,7 +271,7 @@ void oneDependsOnConditionNotMet() {
.addDependentResource(drDeleter).dependsOn(dr1, dr2)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
@@ -287,7 +291,7 @@ void deletedIfReconcileConditionNotMet() {
.addDependentResource(drDeleter2).dependsOn(dr1, drDeleter)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory)
.reconciledInOrder(dr1, drDeleter2, drDeleter)
@@ -313,7 +317,7 @@ void deleteDoneInReverseOrder() {
.addDependentResource(drDeleter4).dependsOn(drDeleter3)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory)
.reconciledInOrder(dr1, drDeleter4, drDeleter3, drDeleter)
@@ -339,7 +343,7 @@ void diamondDeleteWithPostConditionInMiddle() {
.addDependentResource(drDeleter4).dependsOn(drDeleter3, drDeleter2)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).notReconciled(drDeleter)
.reconciledInOrder(drDeleter4, drDeleter2)
@@ -363,7 +367,7 @@ void diamondDeleteErrorInMiddle() {
.withThrowExceptionFurther(false)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory)
.notReconciled(drDeleter, drError)
@@ -381,7 +385,7 @@ void readyConditionTrivialCase() {
.addDependentResource(dr2).dependsOn(dr1)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).reconciledInOrder(dr1, dr2);
@@ -397,7 +401,7 @@ void readyConditionNotMetTrivialCase() {
.addDependentResource(dr2).dependsOn(dr1)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).reconciled(dr1).notReconciled(dr2);
@@ -417,7 +421,7 @@ void readyConditionNotMetInOneParent() {
.addDependentResource(dr3).dependsOn(dr1, dr2)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
assertThat(executionHistory).reconciled(dr1, dr2).notReconciled(dr3);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
@@ -437,7 +441,7 @@ void diamondShareWithReadyCondition() {
.addDependentResource(dr4).dependsOn(dr2, dr3)
.build();
- var res = workflow.reconcile(new TestCustomResource(), null);
+ var res = workflow.reconcile(new TestCustomResource(), mockContext);
Assertions.assertThat(res.getErroredDependents()).isEmpty();
assertThat(executionHistory).reconciledInOrder(dr1, dr2)
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/IndexDiscriminatorIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/IndexDiscriminatorIT.java
new file mode 100644
index 0000000000..fe5b63de8a
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/IndexDiscriminatorIT.java
@@ -0,0 +1,77 @@
+package io.javaoperatorsdk.operator;
+
+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.LocallyRunOperatorExtension;
+import io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestCustomResource;
+import io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestReconciler;
+import io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestSpec;
+
+import static io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestDRConfigMap.DATA_KEY;
+import static io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestReconciler.FIRST_CONFIG_MAP_SUFFIX_1;
+import static io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestReconciler.FIRST_CONFIG_MAP_SUFFIX_2;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+class IndexDiscriminatorIT {
+
+ public static final String TEST_RESOURCE_1 = "test1";
+ public static final String CHANGED_SPEC_VALUE = "otherValue";
+ @RegisterExtension
+ LocallyRunOperatorExtension operator =
+ LocallyRunOperatorExtension.builder().withReconciler(IndexDiscriminatorTestReconciler.class)
+ .build();
+
+ @Test
+ void resourcesFoundAndReconciled() {
+ var res = operator.create(createTestCustomResource());
+ var reconciler = operator.getReconcilerOfType(IndexDiscriminatorTestReconciler.class);
+
+ await().untilAsserted(() -> {
+ assertThat(reconciler.getNumberOfExecutions()).isEqualTo(1);
+ assertThat(operator.get(ConfigMap.class, TEST_RESOURCE_1 + FIRST_CONFIG_MAP_SUFFIX_1))
+ .isNotNull();
+ assertThat(operator.get(ConfigMap.class, TEST_RESOURCE_1 + FIRST_CONFIG_MAP_SUFFIX_2))
+ .isNotNull();
+ });
+
+ res.getSpec().setValue(CHANGED_SPEC_VALUE);
+ res = operator.replace(res);
+
+ await().untilAsserted(() -> {
+ assertThat(reconciler.getNumberOfExecutions()).isEqualTo(2);
+ var cm1 = operator.get(ConfigMap.class, TEST_RESOURCE_1 + FIRST_CONFIG_MAP_SUFFIX_1);
+ var cm2 = operator.get(ConfigMap.class, TEST_RESOURCE_1 + FIRST_CONFIG_MAP_SUFFIX_2);
+ assertThat(cm1).isNotNull();
+ assertThat(cm2).isNotNull();
+ assertThat(cm1.getData().get(DATA_KEY)).isEqualTo(CHANGED_SPEC_VALUE);
+ assertThat(cm2.getData().get(DATA_KEY)).isEqualTo(CHANGED_SPEC_VALUE);
+ });
+
+ operator.delete(res);
+
+ await().untilAsserted(() -> {
+ var cm1 = operator.get(ConfigMap.class, TEST_RESOURCE_1 + FIRST_CONFIG_MAP_SUFFIX_1);
+ var cm2 = operator.get(ConfigMap.class, TEST_RESOURCE_1 + FIRST_CONFIG_MAP_SUFFIX_2);
+ assertThat(cm1).isNull();
+ assertThat(cm2).isNull();
+ });
+ }
+
+ public IndexDiscriminatorTestCustomResource createTestCustomResource() {
+ IndexDiscriminatorTestCustomResource resource =
+ new IndexDiscriminatorTestCustomResource();
+ resource.setMetadata(
+ new ObjectMetaBuilder()
+ .withName(TEST_RESOURCE_1)
+ .withNamespace(operator.getNamespace())
+ .build());
+ resource.setSpec(new IndexDiscriminatorTestSpec());
+ resource.getSpec().setValue("default");
+ return resource;
+ }
+
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminator.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminator.java
new file mode 100644
index 0000000000..eb6e193479
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminator.java
@@ -0,0 +1,41 @@
+package io.javaoperatorsdk.operator.sample.indexdiscriminator;
+
+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.source.informer.InformerEventSource;
+
+import static io.javaoperatorsdk.operator.sample.indexdiscriminator.IndexDiscriminatorTestReconciler.configMapKeyFromPrimary;
+
+public class IndexDiscriminator
+ implements ResourceDiscriminator {
+
+ private final String indexName;
+ private final String nameSuffix;
+
+ public IndexDiscriminator(String indexName, String nameSuffix) {
+ this.indexName = indexName;
+ this.nameSuffix = nameSuffix;
+ }
+
+ @Override
+ public Optional distinguish(Class resource,
+ IndexDiscriminatorTestCustomResource primary,
+ Context context) {
+
+ InformerEventSource eventSource =
+ (InformerEventSource) context
+ .eventSourceRetriever()
+ .getResourceEventSourceFor(ConfigMap.class);
+ var resources = eventSource.byIndex(indexName, configMapKeyFromPrimary(primary, nameSuffix));
+ if (resources.isEmpty()) {
+ return Optional.empty();
+ } else if (resources.size() > 1) {
+ throw new IllegalStateException("more than one resource");
+ } else {
+ return Optional.of(resources.get(0));
+ }
+ }
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestCustomResource.java
new file mode 100644
index 0000000000..729b1d80eb
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestCustomResource.java
@@ -0,0 +1,16 @@
+package io.javaoperatorsdk.operator.sample.indexdiscriminator;
+
+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("idt")
+public class IndexDiscriminatorTestCustomResource
+ extends CustomResource
+ implements Namespaced {
+
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestDRConfigMap.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestDRConfigMap.java
new file mode 100644
index 0000000000..88dc40f55c
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestDRConfigMap.java
@@ -0,0 +1,38 @@
+package io.javaoperatorsdk.operator.sample.indexdiscriminator;
+
+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.CRUDNoGCKubernetesDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
+
+@KubernetesDependent
+public class IndexDiscriminatorTestDRConfigMap
+ extends CRUDNoGCKubernetesDependentResource {
+
+ public static final String DATA_KEY = "key";
+ private final String suffix;
+
+ public IndexDiscriminatorTestDRConfigMap(String value) {
+ super(ConfigMap.class);
+ this.suffix = value;
+ }
+
+ @Override
+ protected ConfigMap desired(IndexDiscriminatorTestCustomResource primary,
+ Context context) {
+ Map data = new HashMap<>();
+ data.put(DATA_KEY, primary.getSpec().getValue());
+
+ return new ConfigMapBuilder()
+ .withNewMetadata()
+ .withName(primary.getMetadata().getName() + suffix)
+ .withNamespace(primary.getMetadata().getNamespace())
+ .endMetadata()
+ .withData(data)
+ .build();
+ }
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestReconciler.java
new file mode 100644
index 0000000000..0b0af2a1cc
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestReconciler.java
@@ -0,0 +1,120 @@
+package io.javaoperatorsdk.operator.sample.indexdiscriminator;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import io.fabric8.kubernetes.api.model.ConfigMap;
+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.support.TestExecutionInfoProvider;
+
+@ControllerConfiguration
+public class IndexDiscriminatorTestReconciler
+ implements Reconciler,
+ Cleaner,
+ TestExecutionInfoProvider, EventSourceInitializer,
+ KubernetesClientAware {
+
+ public static final String FIRST_CONFIG_MAP_SUFFIX_1 = "-1";
+ public static final String FIRST_CONFIG_MAP_SUFFIX_2 = "-2";
+ public static final String CONFIG_MAP_INDEX_1 = "CONFIG_MAP_INDEX1";
+ public static final String CONFIG_MAP_INDEX_2 = "CONFIG_MAP_INDEX2";
+
+ private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
+
+ private final IndexDiscriminatorTestDRConfigMap firstDependentResourceConfigMap;
+ private final IndexDiscriminatorTestDRConfigMap secondDependentResourceConfigMap;
+ private KubernetesClient client;
+
+ public IndexDiscriminatorTestReconciler() {
+ firstDependentResourceConfigMap =
+ new IndexDiscriminatorTestDRConfigMap(FIRST_CONFIG_MAP_SUFFIX_1);
+ secondDependentResourceConfigMap =
+ new IndexDiscriminatorTestDRConfigMap(FIRST_CONFIG_MAP_SUFFIX_2);
+ }
+
+ @Override
+ public UpdateControl reconcile(
+ IndexDiscriminatorTestCustomResource resource,
+ Context context) {
+ numberOfExecutions.getAndIncrement();
+ firstDependentResourceConfigMap.reconcile(resource, context);
+ secondDependentResourceConfigMap.reconcile(resource, context);
+ return UpdateControl.noUpdate();
+ }
+
+ public int getNumberOfExecutions() {
+ return numberOfExecutions.get();
+ }
+
+ @Override
+ public Map prepareEventSources(
+ EventSourceContext context) {
+
+ InformerEventSource eventSource =
+ new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context)
+ .build(), context);
+
+ eventSource.addIndexer(CONFIG_MAP_INDEX_1, cm -> {
+ if (cm.getMetadata().getName().endsWith(FIRST_CONFIG_MAP_SUFFIX_1)) {
+ return List.of(configMapKey(cm));
+ } else {
+ return Collections.emptyList();
+ }
+ });
+ eventSource.addIndexer(CONFIG_MAP_INDEX_2, cm -> {
+ if (cm.getMetadata().getName().endsWith(FIRST_CONFIG_MAP_SUFFIX_2)) {
+ return List.of(configMapKey(cm));
+ } else {
+ return Collections.emptyList();
+ }
+ });
+
+ firstDependentResourceConfigMap.configureWith(eventSource);
+ secondDependentResourceConfigMap.configureWith(eventSource);
+
+ firstDependentResourceConfigMap
+ .setResourceDiscriminator(
+ new IndexDiscriminator(CONFIG_MAP_INDEX_1, FIRST_CONFIG_MAP_SUFFIX_1));
+ secondDependentResourceConfigMap
+ .setResourceDiscriminator(
+ new IndexDiscriminator(CONFIG_MAP_INDEX_2, FIRST_CONFIG_MAP_SUFFIX_2));
+ return EventSourceInitializer.nameEventSources(eventSource);
+ }
+
+ @Override
+ public KubernetesClient getKubernetesClient() {
+ return client;
+ }
+
+ @Override
+ public void setKubernetesClient(KubernetesClient kubernetesClient) {
+ this.client = kubernetesClient;
+ firstDependentResourceConfigMap.setKubernetesClient(kubernetesClient);
+ secondDependentResourceConfigMap.setKubernetesClient(kubernetesClient);
+ }
+
+ public static String configMapKey(ConfigMap configMap) {
+ return configMap.getMetadata().getName() + "#" + configMap.getMetadata().getNamespace();
+ }
+
+ public static String configMapKeyFromPrimary(IndexDiscriminatorTestCustomResource primary,
+ String nameSuffix) {
+ return primary.getMetadata().getName() + nameSuffix + "#"
+ + primary.getMetadata().getNamespace();
+ }
+
+ @Override
+ public DeleteControl cleanup(IndexDiscriminatorTestCustomResource resource,
+ Context context) {
+ firstDependentResourceConfigMap.delete(resource, context);
+ secondDependentResourceConfigMap.delete(resource, context);
+ return DeleteControl.defaultDelete();
+ }
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestSpec.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestSpec.java
new file mode 100644
index 0000000000..fcedd48abe
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestSpec.java
@@ -0,0 +1,15 @@
+package io.javaoperatorsdk.operator.sample.indexdiscriminator;
+
+public class IndexDiscriminatorTestSpec {
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public IndexDiscriminatorTestSpec setValue(String value) {
+ this.value = value;
+ return this;
+ }
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestStatus.java
new file mode 100644
index 0000000000..d31c86e8de
--- /dev/null
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/indexdiscriminator/IndexDiscriminatorTestStatus.java
@@ -0,0 +1,5 @@
+package io.javaoperatorsdk.operator.sample.indexdiscriminator;
+
+public class IndexDiscriminatorTestStatus {
+
+}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceConfigMap.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceConfigMap.java
index 4cdc2e457d..1adbfb9f95 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceConfigMap.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceConfigMap.java
@@ -31,7 +31,6 @@ protected ConfigMap desired(MultipleDependentResourceCustomResource primary,
.withNewMetadata()
.withName(primary.getConfigMapName(value))
.withNamespace(primary.getMetadata().getNamespace())
- .withLabels(Map.of(MultipleDependentResourceReconciler.LABEL, String.valueOf(value)))
.endMetadata()
.withData(data)
.build();
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java
index 8cdbb81eba..49f5ee64c1 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multipledependentresource/MultipleDependentResourceReconciler.java
@@ -3,16 +3,14 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
+import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.client.KubernetesClient;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
-import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
-import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+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.dependent.kubernetes.KubernetesDependentResourceConfig;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
+import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider;
@ControllerConfiguration
@@ -23,7 +21,6 @@ public class MultipleDependentResourceReconciler
public static final int FIRST_CONFIG_MAP_ID = 1;
public static final int SECOND_CONFIG_MAP_ID = 2;
- public static final String LABEL = "multipledependentresource";
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
private final MultipleDependentResourceConfigMap firstDependentResourceConfigMap;
@@ -32,18 +29,19 @@ public class MultipleDependentResourceReconciler
public MultipleDependentResourceReconciler() {
firstDependentResourceConfigMap = new MultipleDependentResourceConfigMap(FIRST_CONFIG_MAP_ID);
- secondDependentResourceConfigMap = new MultipleDependentResourceConfigMap(SECOND_CONFIG_MAP_ID);
- firstDependentResourceConfigMap.configureWith(
- new KubernetesDependentResourceConfig()
- .setLabelSelector(getLabelSelector(FIRST_CONFIG_MAP_ID)));
- secondDependentResourceConfigMap.configureWith(
- new KubernetesDependentResourceConfig()
- .setLabelSelector(getLabelSelector(SECOND_CONFIG_MAP_ID)));
- }
+ secondDependentResourceConfigMap = new MultipleDependentResourceConfigMap(SECOND_CONFIG_MAP_ID);
- private String getLabelSelector(int resourceId) {
- return LABEL + "=" + resourceId;
+ firstDependentResourceConfigMap
+ .setResourceDiscriminator(
+ new ResourceIDMatcherDiscriminator<>(
+ p -> new ResourceID(p.getConfigMapName(FIRST_CONFIG_MAP_ID),
+ p.getMetadata().getNamespace())));
+ secondDependentResourceConfigMap
+ .setResourceDiscriminator(
+ new ResourceIDMatcherDiscriminator<>(
+ p -> new ResourceID(p.getConfigMapName(SECOND_CONFIG_MAP_ID),
+ p.getMetadata().getNamespace())));
}
@Override
@@ -64,9 +62,13 @@ public int getNumberOfExecutions() {
@Override
public Map prepareEventSources(
EventSourceContext context) {
- return EventSourceInitializer.nameEventSources(
- firstDependentResourceConfigMap.initEventSource(context),
- secondDependentResourceConfigMap.initEventSource(context));
+ InformerEventSource eventSource =
+ new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context)
+ .build(), context);
+ firstDependentResourceConfigMap.configureWith(eventSource);
+ secondDependentResourceConfigMap.configureWith(eventSource);
+
+ return EventSourceInitializer.nameEventSources(eventSource);
}
@Override
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 14530cf17e..bf8d60d9c4 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
@@ -6,11 +6,14 @@
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.api.reconciler.ResourceIDMatcherDiscriminator;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
-@KubernetesDependent(labelSelector = "dependent = cm1")
+@KubernetesDependent(labelSelector = "dependent = cm1",
+ resourceDiscriminator = ConfigMapDependentResource1.CM1ResourceDiscriminator.class)
public class ConfigMapDependentResource1 extends
CRUDKubernetesDependentResource {
@@ -42,4 +45,11 @@ protected ConfigMap desired(OrderedManagedDependentCustomResource primary,
return configMap;
}
+ public static class CM1ResourceDiscriminator
+ extends ResourceIDMatcherDiscriminator {
+ public CM1ResourceDiscriminator() {
+ super(p -> new ResourceID(p.getMetadata().getName() + "1", p.getMetadata().getNamespace()));
+ }
+ }
+
}
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 35ae69586e..2b17d615b9 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
@@ -6,11 +6,14 @@
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.api.reconciler.ResourceIDMatcherDiscriminator;
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
-@KubernetesDependent(labelSelector = "dependent = cm2")
+@KubernetesDependent(labelSelector = "dependent = cm2",
+ resourceDiscriminator = ConfigMapDependentResource2.CM2ResourceDiscriminator.class)
public class ConfigMapDependentResource2 extends
CRUDKubernetesDependentResource {
@@ -42,4 +45,11 @@ protected ConfigMap desired(OrderedManagedDependentCustomResource primary,
return configMap;
}
+ public static class CM2ResourceDiscriminator
+ extends ResourceIDMatcherDiscriminator {
+ public CM2ResourceDiscriminator() {
+ super(p -> new ResourceID(p.getMetadata().getName() + "2", p.getMetadata().getNamespace()));
+ }
+ }
+
}
diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/perresourceeventsource/PerResourcePollingEventSourceTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/perresourceeventsource/PerResourcePollingEventSourceTestReconciler.java
index dec730d536..ecc33afcb3 100644
--- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/perresourceeventsource/PerResourcePollingEventSourceTestReconciler.java
+++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/perresourceeventsource/PerResourcePollingEventSourceTestReconciler.java
@@ -57,7 +57,8 @@ public void setKubernetesClient(KubernetesClient kubernetesClient) {
}
public int getNumberOfExecutions(String name) {
- return numberOfExecutions.get(name);
+ var num = numberOfExecutions.get(name);
+ return num == null ? 0 : num;
}
public int getNumberOfFetchExecution(String name) {
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 af6b2d7e25..2dace670ba 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
@@ -47,7 +47,7 @@ public UpdateControl reconcile(
StandaloneDependentTestCustomResource primary,
Context context) {
deploymentDependent.reconcile(primary, context);
- Optional deployment = deploymentDependent.getSecondaryResource(primary);
+ Optional deployment = context.getSecondaryResource(Deployment.class);
if (deployment.isEmpty()) {
throw new IllegalStateException("Resource should not be empty after reconcile.");
}
diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java
index 6986180b89..6b81a9d6e3 100644
--- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java
+++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageDependentsWorkflowReconciler.java
@@ -69,7 +69,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex
webPage.setStatus(
createStatus(
- configMapDR.getSecondaryResource(webPage).orElseThrow().getMetadata().getName()));
+ context.getSecondaryResource(ConfigMap.class).orElseThrow().getMetadata().getName()));
return UpdateControl.patchStatus(webPage);
}
@@ -93,6 +93,4 @@ private void initDependentResources(KubernetesClient client) {
});
}
-
-
}
diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java
index 0bb692a4d0..b99e130135 100644
--- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java
+++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java
@@ -65,7 +65,7 @@ public UpdateControl reconcile(WebPage webPage, Context contex
webPage.setStatus(
createStatus(
- configMapDR.getSecondaryResource(webPage).orElseThrow().getMetadata().getName()));
+ context.getSecondaryResource(ConfigMap.class).orElseThrow().getMetadata().getName()));
return UpdateControl.patchStatus(webPage);
}