diff --git a/docs/documentation/features.md b/docs/documentation/features.md index 3f2a8843c3..7b6143ca02 100644 --- a/docs/documentation/features.md +++ b/docs/documentation/features.md @@ -37,9 +37,13 @@ execution. [Kubernetes finalizers](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/) make sure that a reconciliation happens when a custom resource is instructed to be deleted. Typical case when it's useful, when an operator is down (pod not running). Without a finalizer the reconciliation - thus the cleanup - -i.e. [`Reconciler.cleanup(...)`](https://github.com/java-operator-sdk/java-operator-sdk/blob/b91221bb54af19761a617bf18eef381e8ceb3b4c/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java#L31) +i.e. [`Cleaner.cleanup(...)`](https://github.com/java-operator-sdk/java-operator-sdk/blob/b82c1f106968cb3eb18835c5e9cd1e4d5c40362e/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java#L28-L28) would not happen if a custom resource is deleted. +To use finalizers the reconciler have to implement [`Cleaner

`](https://github.com/java-operator-sdk/java-operator-sdk/blob/b82c1f106968cb3eb18835c5e9cd1e4d5c40362e/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java) interface. +In other words, finalizer is added if the `Reconciler` implements `Cleaner` interface. If not, no +finalizer is added and/or removed. + Finalizers are automatically added by the framework as the first step, thus after a custom resource is created, but before the first reconciliation. The finalizer is added via a separate Kubernetes API call. As a result of this update, the finalizer will be present. The subsequent event will be received, which will trigger the first reconciliation. @@ -50,7 +54,6 @@ in some specific corner cases, when there would be a long waiting period for som The name of the finalizers can be specified, in case it is not, a name will be generated. -Automatic finalizer handling can be turned off, so when configured no finalizer will be added or removed. See [`@ControllerConfiguration`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java) annotation for more details. @@ -66,7 +69,7 @@ When automatic finalizer handling is turned off, the `Reconciler.cleanup(...)` m case when a delete event received. So it does not make sense to implement this method and turn off finalizer at the same time. -## The `reconcile` and `cleanup` Methods of [`Reconciler`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java) +## The `reconcile` and [`cleanup`](https://github.com/java-operator-sdk/java-operator-sdk/blob/b82c1f106968cb3eb18835c5e9cd1e4d5c40362e/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java) Methods on a [`Reconciler`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java) The lifecycle of a custom resource can be clearly separated into two phases from the perspective of an operator. When a custom resource is created or update, or on the other hand when the custom resource is deleted - or rather marked for @@ -75,9 +78,8 @@ deletion in case a finalizer is used. This separation-related logic is automatically handled by the framework. The framework will always call `reconcile` method, unless the custom resource is [marked from deletion](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/#how-finalizers-work) -. From the point when the custom resource is marked from deletion, only the `cleanup` method is called. - -If there is **no finalizer** in place (see Finalizer Support section), the `cleanup` method is **not called**. +. From the point when the custom resource is marked from deletion, only the `cleanup` method is called, of course +only if the reconciler implements the `Cleaner` interface. ### Using [`UpdateControl`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/UpdateControl.java) and [`DeleteControl`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/DeleteControl.java) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ReconcilerUtils.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ReconcilerUtils.java index 98a43492f9..a99abe4d8d 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ReconcilerUtils.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ReconcilerUtils.java @@ -42,7 +42,7 @@ public void setApiVersion(String s) { throw new UnsupportedOperationException(); } }; - return Constants.NO_FINALIZER.equals(finalizer) || validator.isFinalizerValid(finalizer); + return validator.isFinalizerValid(finalizer); } public static String getResourceTypeNameWithVersion(Class resourceClass) { 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 72d34e16a8..eb57d2c71a 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 @@ -39,7 +39,7 @@ public String getName() { } @Override - public String getFinalizer() { + public String getFinalizerName() { if (annotation == null || annotation.finalizerName().isBlank()) { return ReconcilerUtils.getDefaultFinalizerName(getResourceClass()); } else { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java index 03485412b6..aff1d04e8b 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java @@ -8,7 +8,6 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; -import io.javaoperatorsdk.operator.api.reconciler.Constants; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilters; @@ -18,7 +17,7 @@ default String getName() { return ReconcilerUtils.getDefaultReconcilerName(getAssociatedReconcilerClassName()); } - default String getFinalizer() { + default String getFinalizerName() { return ReconcilerUtils.getDefaultFinalizerName(getResourceClass()); } @@ -32,10 +31,6 @@ default RetryConfiguration getRetryConfiguration() { return RetryConfiguration.DEFAULT; } - default boolean useFinalizer() { - return !Constants.NO_FINALIZER.equals(getFinalizer()); - } - /** * Allow controllers to filter events before they are passed to the * {@link io.javaoperatorsdk.operator.processing.event.EventHandler}. diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java index 87297b8d49..da0b6d0a52 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfigurationOverrider.java @@ -25,7 +25,7 @@ public class ControllerConfigurationOverrider { private final List> dependentResourceSpecs; private ControllerConfigurationOverrider(ControllerConfiguration original) { - finalizer = original.getFinalizer(); + finalizer = original.getFinalizerName(); generationAware = original.isGenerationAware(); namespaces = new HashSet<>(original.getNamespaces()); retry = original.getRetryConfiguration(); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java index 4545c9885e..890254d830 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/DefaultControllerConfiguration.java @@ -66,7 +66,7 @@ public String getResourceTypeName() { } @Override - public String getFinalizer() { + public String getFinalizerName() { return finalizer; } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java new file mode 100644 index 0000000000..e2e70a246d --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java @@ -0,0 +1,30 @@ +package io.javaoperatorsdk.operator.api.reconciler; + +import io.fabric8.kubernetes.api.model.HasMetadata; + +public interface Cleaner

{ + + /** + * Note that this method turns on automatic finalizer usage. + * + * The implementation should delete the associated component(s). This method is called when an + * object is marked for deletion. After it's executed the custom resource finalizer is + * automatically removed by the framework; unless the return value is + * {@link DeleteControl#noFinalizerRemoval()}, which indicates that the controller has determined + * that the resource should not be deleted yet. This is usually a corner case, when a cleanup is + * tried again eventually. + * + *

+ * It's important for implementations of this method to be idempotent, since it can be called + * several times. + * + * @param resource the resource that is marked for deletion + * @param context the context with which the operation is executed + * @return {@link DeleteControl#defaultDelete()} - so the finalizer is automatically removed after + * the call. {@link DeleteControl#noFinalizerRemoval()} if you don't want to remove the + * finalizer to indicate that the resource should not be deleted after all, in which case + * the controller should restore the resource's state appropriately. + */ + DeleteControl cleanup(P resource, Context

context); + +} diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java index 85b3a00807..e08e168ca4 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Constants.java @@ -4,7 +4,6 @@ public final class Constants { public static final String EMPTY_STRING = ""; public static final String WATCH_CURRENT_NAMESPACE = "JOSDK_WATCH_CURRENT"; - public static final String NO_FINALIZER = "JOSDK_NO_FINALIZER"; public static final long NO_RECONCILIATION_MAX_INTERVAL = -1L; private Constants() {} 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 2c3fb6ff1e..b2c2270f0b 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 @@ -4,7 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.dependent.ManagedDependentResourceContext; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ManagedDependentResourceContext; public interface Context

{ diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java index 0feaa34b2d..fe69738b1a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java @@ -15,9 +15,10 @@ String name() default Constants.EMPTY_STRING; /** - * Optional finalizer name, if it is not provided, one will be automatically generated. If the - * provided value is the value specified by {@link Constants#NO_FINALIZER}, then no finalizer will - * be added to custom resources. + * Optional finalizer name, if it is not provided, one will be automatically generated. Note that + * finalizers are only added when Reconciler implement {@link Cleaner} interface, or at least one + * managed dependent resource implement + * {@link io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter} interface. * * @return the finalizer name */ 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 d80be8b3ae..0a7b36339d 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 @@ -4,7 +4,7 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.dependent.ManagedDependentResourceContext; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ManagedDependentResourceContext; import io.javaoperatorsdk.operator.processing.Controller; public class DefaultContext

implements Context

{ diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java index 446df36ca1..771b169fd1 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Reconciler.java @@ -15,29 +15,4 @@ public interface Reconciler { */ UpdateControl reconcile(R resource, Context context) throws Exception; - /** - * Note that this method is used in combination with finalizers. If automatic finalizer handling - * is turned off for the controller, this method is not called. - * - * The implementation should delete the associated component(s). This method is called when an - * object is marked for deletion. After it's executed the custom resource finalizer is - * automatically removed by the framework; unless the return value is - * {@link DeleteControl#noFinalizerRemoval()}, which indicates that the controller has determined - * that the resource should not be deleted yet. This is usually a corner case, when a cleanup is - * tried again eventually. - * - *

- * It's important for implementations of this method to be idempotent, since it can be called - * several times. - * - * @param resource the resource that is marked for deletion - * @param context the context with which the operation is executed - * @return {@link DeleteControl#defaultDelete()} - so the finalizer is automatically removed after - * the call. {@link DeleteControl#noFinalizerRemoval()} if you don't want to remove the - * finalizer to indicate that the resource should not be deleted after all, in which case - * the controller should restore the resource's state appropriately. - */ - default DeleteControl cleanup(R resource, Context context) { - return DeleteControl.defaultDelete(); - } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java index 0a1bfc1bab..f6bd2682ca 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java @@ -3,6 +3,12 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.Context; +/** + * DependentResource can implement this interface to denote it requires explicit logic to clean up + * resources. + * + * @param

primary resource type + */ @FunctionalInterface public interface Deleter

{ void delete(P primary, Context

context); 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 377e4aea22..1dcfbe57d5 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 @@ -8,7 +8,5 @@ public interface DependentResource { ReconcileResult reconcile(P primary, Context

context); - default void cleanup(P primary, Context

context) {} - Optional getResource(P primaryResource); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ReconcileResult.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ReconcileResult.java index 392b213e81..86a931c480 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ReconcileResult.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ReconcileResult.java @@ -4,8 +4,8 @@ public class ReconcileResult { - private R resource; - private Operation operation; + private final R resource; + private final Operation operation; public static ReconcileResult resourceCreated(T resource) { return new ReconcileResult<>(resource, Operation.CREATED); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceConfigurator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DependentResourceConfigurator.java similarity index 55% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceConfigurator.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DependentResourceConfigurator.java index b51de9f35f..bbb4f75da9 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceConfigurator.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/DependentResourceConfigurator.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.api.reconciler.dependent.managed; public interface DependentResourceConfigurator { void configureWith(C config); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesClientAware.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/KubernetesClientAware.java similarity index 69% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesClientAware.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/KubernetesClientAware.java index b8ef888ec3..0e787753a5 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/KubernetesClientAware.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/KubernetesClientAware.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.api.reconciler.dependent.managed; import io.fabric8.kubernetes.client.KubernetesClient; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ManagedDependentResourceContext.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ManagedDependentResourceContext.java similarity index 96% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ManagedDependentResourceContext.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ManagedDependentResourceContext.java index 9543b7d582..745f1e3151 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ManagedDependentResourceContext.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ManagedDependentResourceContext.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.api.reconciler.dependent.managed; import java.util.Collections; import java.util.List; @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import io.javaoperatorsdk.operator.OperatorException; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; /** * Contextual information related to {@link DependentResource} either to retrieve the actual 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 de71d54171..7ee63d760f 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 @@ -22,6 +22,7 @@ import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.monitoring.Metrics; import io.javaoperatorsdk.operator.api.monitoring.Metrics.ControllerExecution; +import io.javaoperatorsdk.operator.api.reconciler.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ContextInitializer; import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; @@ -30,16 +31,17 @@ import io.javaoperatorsdk.operator.api.reconciler.Ignore; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceConfigurator; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; -import io.javaoperatorsdk.operator.api.reconciler.dependent.KubernetesClientAware; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware; import io.javaoperatorsdk.operator.processing.event.EventSourceManager; import io.javaoperatorsdk.operator.processing.event.source.EventSource; @SuppressWarnings({"unchecked", "rawtypes"}) @Ignore -public class Controller

implements Reconciler

, +public class Controller

implements Reconciler

, Cleaner

, LifecycleAware, EventSourceInitializer

{ private static final Logger log = LoggerFactory.getLogger(Controller.class); @@ -50,6 +52,8 @@ public class Controller

implements Reconciler

, private final EventSourceManager

eventSourceManager; private final List dependents; private final boolean contextInitializer; + private final boolean hasDeleterDependents; + private final boolean isCleaner; public Controller(Reconciler

reconciler, ControllerConfiguration

configuration, @@ -61,9 +65,19 @@ public Controller(Reconciler

reconciler, eventSourceManager = new EventSourceManager<>(this); + final var hasDeleterHolder = new boolean[] {false}; dependents = configuration.getDependentResources().stream() .map(drs -> createAndConfigureFrom(drs, kubernetesClient)) + .peek(d -> { + // check if any dependent implements Deleter to record that fact + if (!hasDeleterHolder[0] && d instanceof Deleter) { + hasDeleterHolder[0] = true; + } + }) .collect(Collectors.toList()); + + hasDeleterDependents = hasDeleterHolder[0]; + isCleaner = reconciler instanceof Cleaner; } @SuppressWarnings("rawtypes") @@ -92,31 +106,40 @@ private void initContextIfNeeded(P resource, Context

context) { @Override public DeleteControl cleanup(P resource, Context

context) { initContextIfNeeded(resource, context); - dependents.forEach(dependent -> dependent.cleanup(resource, context)); - try { - return metrics().timeControllerExecution( - new ControllerExecution<>() { - @Override - public String name() { - return "cleanup"; - } - - @Override - public String controllerName() { - return configuration.getName(); - } - - @Override - public String successTypeName(DeleteControl deleteControl) { - return deleteControl.isRemoveFinalizer() ? "delete" : "finalizerNotRemoved"; - } - - @Override - public DeleteControl execute() { - return reconciler.cleanup(resource, context); - } - }); + return metrics() + .timeControllerExecution( + new ControllerExecution<>() { + @Override + public String name() { + return "cleanup"; + } + + @Override + public String controllerName() { + return configuration.getName(); + } + + @Override + public String successTypeName(DeleteControl deleteControl) { + return deleteControl.isRemoveFinalizer() ? "delete" : "finalizerNotRemoved"; + } + + @Override + public DeleteControl execute() { + if (hasDeleterDependents) { + dependents.stream() + .filter(d -> d instanceof Deleter) + .map(Deleter.class::cast) + .forEach(deleter -> deleter.delete(resource, context)); + } + if (isCleaner) { + return ((Cleaner

) reconciler).cleanup(resource, context); + } else { + return DeleteControl.defaultDelete(); + } + } + }); } catch (Exception e) { throw new OperatorException(e); } @@ -125,8 +148,6 @@ public DeleteControl execute() { @Override public UpdateControl

reconcile(P resource, Context

context) throws Exception { initContextIfNeeded(resource, context); - dependents.forEach(dependent -> dependent.reconcile(resource, context)); - return metrics().timeControllerExecution( new ControllerExecution<>() { @Override @@ -153,6 +174,7 @@ public String successTypeName(UpdateControl

result) { @Override public UpdateControl

execute() throws Exception { + dependents.forEach(dependent -> dependent.reconcile(resource, context)); return reconciler.reconcile(resource, context); } }); @@ -304,6 +326,10 @@ public void stop() { } } + public boolean useFinalizer() { + return isCleaner || hasDeleterDependents; + } + @SuppressWarnings("rawtypes") public List getDependents() { return dependents; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/AbstractDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java similarity index 92% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/AbstractDependentResource.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java index 799355185c..4758ba5eab 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/AbstractDependentResource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java @@ -1,10 +1,11 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; 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.dependent.*; import io.javaoperatorsdk.operator.processing.event.ResourceID; public abstract class AbstractDependentResource @@ -13,16 +14,13 @@ public abstract class AbstractDependentResource private final boolean creatable = this instanceof Creator; private final boolean updatable = this instanceof Updater; - private final boolean deletable = this instanceof Deleter; protected Creator creator; protected Updater updater; - protected Deleter

deleter; @SuppressWarnings("unchecked") public AbstractDependentResource() { creator = creatable ? (Creator) this : null; updater = updatable ? (Updater) this : null; - deleter = deletable ? (Deleter

) this : null; } @Override @@ -147,13 +145,6 @@ protected boolean isRecentOperationCacheFiller() { } } - @Override - public void cleanup(P primary, Context

context) { - if (isDeletable(primary, context)) { - deleter.delete(primary, context); - } - } - protected R desired(P primary, Context

context) { throw new IllegalStateException( "desired method must be implemented if this DependentResource can be created and/or updated"); @@ -169,8 +160,4 @@ protected boolean isUpdatable(P primary, Context

context) { return updatable; } - @SuppressWarnings("unused") - protected boolean isDeletable(P primary, Context

context) { - return deletable; - } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Creator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Creator.java similarity index 79% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Creator.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Creator.java index 48af8fb61b..b4143906bd 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Creator.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Creator.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.Context; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DesiredEqualsMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DesiredEqualsMatcher.java similarity index 91% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DesiredEqualsMatcher.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DesiredEqualsMatcher.java index 2cf8b155ff..459d7951d6 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DesiredEqualsMatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DesiredEqualsMatcher.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.Context; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Matcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Matcher.java similarity index 92% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Matcher.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Matcher.java index 09e78911e6..84290fe464 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Matcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Matcher.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; import java.util.Optional; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Updater.java similarity index 68% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Updater.java index d49ccc632e..828f9ad785 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Updater.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/Updater.java @@ -1,8 +1,8 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent; import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher.Result; +import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result; public interface Updater { R update(R actual, R desired, P primary, Context

context); 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 index 04b49bf0bf..c45e50db9a 100644 --- 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 @@ -3,9 +3,9 @@ import java.util.Optional; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.dependent.AbstractDependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; import io.javaoperatorsdk.operator.api.reconciler.dependent.ResourceTypeAware; +import io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource; import io.javaoperatorsdk.operator.processing.event.ExternalResourceCachingEventSource; import io.javaoperatorsdk.operator.processing.event.source.EventSource; 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 850b290c12..2b91e6d75f 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 @@ -4,10 +4,10 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.AbstractDependentResource; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DesiredEqualsMatcher; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher; import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult; +import io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.DesiredEqualsMatcher; +import io.javaoperatorsdk.operator.processing.dependent.Matcher; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.ConcurrentHashMapCache; import io.javaoperatorsdk.operator.processing.event.source.UpdatableCache; @@ -51,11 +51,13 @@ public ReconcileResult reconcile(P primary, Context

context) { return super.reconcile(primary, context); } - public void cleanup(P primary, Context

context) { - super.cleanup(primary, context); + public final void delete(P primary, Context

context) { + deleteResource(primary, context); cache.remove(ResourceID.fromResource(primary)); } + protected abstract void deleteResource(P primary, Context

context); + @Override protected R handleCreate(R desired, P primary, Context

context) { var res = this.creator.create(desired, primary, context); 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 similarity index 50% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CrudKubernetesDependentResource.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java index b363e81b51..05195e39b9 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,21 +1,21 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; +import io.javaoperatorsdk.operator.processing.dependent.Creator; +import io.javaoperatorsdk.operator.processing.dependent.Updater; /** - * Adaptor Class for standalone mode for resources that manages Create, Update and Delete + * Adaptor Class for standalone mode for resources that manages Create, Read, Update and Delete * * @param Managed resource * @param

Primary Resource */ -public abstract class CrudKubernetesDependentResource - extends KubernetesDependentResource - implements Creator, Updater, Deleter

{ +public abstract class CRUDKubernetesDependentResource + extends + KubernetesDependentResource implements Creator, Updater, Deleter

{ - public CrudKubernetesDependentResource(Class resourceType) { + 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 new file mode 100644 index 0000000000..7670367936 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUKubernetesDependentResource.java @@ -0,0 +1,21 @@ +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/GenericKubernetesResourceMatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java index 0bbe19837e..f2c789e267 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericKubernetesResourceMatcher.java @@ -7,7 +7,7 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher; +import io.javaoperatorsdk.operator.processing.dependent.Matcher; public class GenericKubernetesResourceMatcher implements Matcher { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessor.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessor.java index 0e0624d183..e35913af68 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessor.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessor.java @@ -6,7 +6,6 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.ResourceUpdatePreProcessor; public abstract class GenericResourceUpdatePreProcessor implements ResourceUpdatePreProcessor { 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 9439d74865..233deb020d 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,14 +14,13 @@ 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.AbstractDependentResource; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceConfigurator; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; -import io.javaoperatorsdk.operator.api.reconciler.dependent.KubernetesClientAware; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher.Result; import io.javaoperatorsdk.operator.api.reconciler.dependent.ResourceTypeAware; -import io.javaoperatorsdk.operator.api.reconciler.dependent.ResourceUpdatePreProcessor; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware; +import io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.Matcher; +import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ResourceUpdatePreProcessor.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/ResourceUpdatePreProcessor.java similarity index 78% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ResourceUpdatePreProcessor.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/ResourceUpdatePreProcessor.java index 55ebcca230..3b88884e6a 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/ResourceUpdatePreProcessor.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/ResourceUpdatePreProcessor.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.operator.api.reconciler.dependent; +package io.javaoperatorsdk.operator.processing.dependent.kubernetes; import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.Context; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java index 235a27481d..2a0f0997f0 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java @@ -16,7 +16,6 @@ import io.javaoperatorsdk.operator.api.reconciler.DefaultContext; import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusHandler; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.RetryInfo; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.processing.Controller; @@ -60,9 +59,9 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) log.debug("Handling dispatch for resource {}", getName(resource)); final var markedForDeletion = resource.isMarkedForDeletion(); - if (markedForDeletion && shouldNotDispatchToDelete(resource)) { + if (markedForDeletion && shouldNotDispatchToCleanup(resource)) { log.debug( - "Skipping delete of resource {} because finalizer(s) {} don't allow processing yet", + "Skipping cleanup of resource {} because finalizer(s) {} don't allow processing yet", getName(resource), resource.getMetadata().getFinalizers()); return PostExecutionControl.defaultDispatch(); @@ -76,25 +75,17 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) } } - /** - * Determines whether the given resource should be dispatched to the controller's - * {@link Reconciler#cleanup(HasMetadata, Context)} method - * - * @param resource the resource to be potentially deleted - * @return {@code true} if the resource should be handed to the controller's - * {@link Reconciler#cleanup(HasMetadata, Context)} method, {@code false} otherwise - */ - private boolean shouldNotDispatchToDelete(R resource) { - // we don't dispatch to delete if the controller is configured to use a finalizer but that + private boolean shouldNotDispatchToCleanup(R resource) { + // we don't dispatch to cleanup if the controller is configured to use a finalizer but that // finalizer is not present (which means it's already been removed) - return !configuration().useFinalizer() || (configuration().useFinalizer() - && !resource.hasFinalizer(configuration().getFinalizer())); + return !controller.useFinalizer() || (controller.useFinalizer() + && !resource.hasFinalizer(configuration().getFinalizerName())); } private PostExecutionControl handleReconcile( ExecutionScope executionScope, R originalResource, Context context) throws Exception { - if (configuration().useFinalizer() - && !originalResource.hasFinalizer(configuration().getFinalizer())) { + if (controller.useFinalizer() + && !originalResource.hasFinalizer(configuration().getFinalizerName())) { /* * We always add the finalizer if missing and the controller is configured to use a finalizer. * We execute the controller processing only for processing the event sent as a results of the @@ -265,12 +256,12 @@ private PostExecutionControl handleCleanup(R resource, Context context) { getVersion(resource)); DeleteControl deleteControl = controller.cleanup(resource, context); - final var useFinalizer = configuration().useFinalizer(); + final var useFinalizer = controller.useFinalizer(); if (useFinalizer) { // note that we don't reschedule here even if instructed. Removing finalizer means that // cleanup is finished, nothing left to done if (deleteControl.isRemoveFinalizer() - && resource.hasFinalizer(configuration().getFinalizer())) { + && resource.hasFinalizer(configuration().getFinalizerName())) { R customResource = removeFinalizer(resource); return PostExecutionControl.customResourceUpdated(customResource); } @@ -289,7 +280,7 @@ private PostExecutionControl handleCleanup(R resource, Context context) { private void updateCustomResourceWithFinalizer(R resource) { log.debug( "Adding finalizer for resource: {} version: {}", getUID(resource), getVersion(resource)); - resource.addFinalizer(configuration().getFinalizer()); + resource.addFinalizer(configuration().getFinalizerName()); replace(resource); } @@ -304,7 +295,7 @@ private R removeFinalizer(R resource) { "Removing finalizer on resource: {} with version: {}", getUID(resource), getVersion(resource)); - resource.removeFinalizer(configuration().getFinalizer()); + resource.removeFinalizer(configuration().getFinalizerName()); return customResourceFacade.replaceWithLock(resource); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSource.java index b43666660c..fe9d802630 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSource.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSource.java @@ -59,7 +59,7 @@ public void eventReceived(ResourceAction action, T resource, T oldResource) { log.debug("Event received for resource: {}", getName(resource)); MDCUtils.addResourceInfo(resource); controller.getEventSourceManager().broadcastOnResourceEvent(action, resource, oldResource); - if (filter.acceptChange(controller.getConfiguration(), oldResource, resource)) { + if (filter.acceptChange(controller, oldResource, resource)) { getEventHandler().handleEvent( new ResourceEvent(action, ResourceID.fromResource(resource))); } else { diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilter.java index 497c9016b7..17cb27fd71 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilter.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilter.java @@ -1,29 +1,29 @@ package io.javaoperatorsdk.operator.processing.event.source.controller; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.processing.Controller; /** * A functional interface to determine whether resource events should be processed by the SDK. This * allows users to more finely tuned which events trigger a reconciliation than was previously * possible (where the logic was limited to generation-based checking). * - * @param the type of custom resources handled by this filter + * @param

the type of custom resources handled by this filter */ @FunctionalInterface -public interface ResourceEventFilter { +public interface ResourceEventFilter

{ /** * Determines whether the change between the old version of the resource and the new one needs to * be propagated to the controller or not. * - * @param configuration the target controller's configuration + * @param controller the target controller * @param oldResource the old version of the resource, null if no old resource available * @param newResource the new version of the resource * @return {@code true} if the change needs to be propagated to the controller, {@code false} * otherwise */ - boolean acceptChange(ControllerConfiguration configuration, T oldResource, T newResource); + boolean acceptChange(Controller

controller, P oldResource, P newResource); /** * Combines this filter with the provided one with an AND logic, i.e. the resulting filter will @@ -32,11 +32,11 @@ public interface ResourceEventFilter { * @param other the possibly {@code null} other filter to combine this one with * @return a composite filter implementing the AND logic between this and the provided filter */ - default ResourceEventFilter and(ResourceEventFilter other) { + default ResourceEventFilter

and(ResourceEventFilter

other) { return other == null ? this - : (ControllerConfiguration configuration, T oldResource, T newResource) -> { - boolean result = acceptChange(configuration, oldResource, newResource); - return result && other.acceptChange(configuration, oldResource, newResource); + : (Controller

controller, P oldResource, P newResource) -> { + boolean result = acceptChange(controller, oldResource, newResource); + return result && other.acceptChange(controller, oldResource, newResource); }; } @@ -48,11 +48,11 @@ default ResourceEventFilter and(ResourceEventFilter other) { * @param other the possibly {@code null} other filter to combine this one with * @return a composite filter implementing the OR logic between this and the provided filter */ - default ResourceEventFilter or(ResourceEventFilter other) { + default ResourceEventFilter

or(ResourceEventFilter

other) { return other == null ? this - : (ControllerConfiguration configuration, T oldResource, T newResource) -> { - boolean result = acceptChange(configuration, oldResource, newResource); - return result || other.acceptChange(configuration, oldResource, newResource); + : (Controller

controller, P oldResource, P newResource) -> { + boolean result = acceptChange(controller, oldResource, newResource); + return result || other.acceptChange(controller, oldResource, newResource); }; } } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilters.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilters.java index c314af7f2e..5a22cafac8 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilters.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilters.java @@ -8,9 +8,9 @@ public final class ResourceEventFilters { private static final ResourceEventFilter USE_FINALIZER = - (configuration, oldResource, newResource) -> { - if (configuration.useFinalizer()) { - final var finalizer = configuration.getFinalizer(); + (controller, oldResource, newResource) -> { + if (controller.useFinalizer()) { + final var finalizer = controller.getConfiguration().getFinalizerName(); boolean oldFinalizer = oldResource == null || oldResource.hasFinalizer(finalizer); boolean newFinalizer = newResource.hasFinalizer(finalizer); @@ -21,8 +21,8 @@ public final class ResourceEventFilters { }; private static final ResourceEventFilter GENERATION_AWARE = - (configuration, oldResource, newResource) -> { - final var generationAware = configuration.isGenerationAware(); + (controller, oldResource, newResource) -> { + final var generationAware = controller.getConfiguration().isGenerationAware(); return oldResource == null || !generationAware || oldResource.getMetadata().getGeneration() < newResource.getMetadata().getGeneration(); }; diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ReconcilerUtilsTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ReconcilerUtilsTest.java index e137a2ff11..5081767980 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ReconcilerUtilsTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ReconcilerUtilsTest.java @@ -7,7 +7,6 @@ import io.fabric8.kubernetes.api.model.PodTemplateSpec; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentSpec; -import io.javaoperatorsdk.operator.api.reconciler.Constants; import io.javaoperatorsdk.operator.sample.simple.TestCustomReconciler; import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; @@ -40,11 +39,6 @@ void defaultFinalizerShouldWork() { assertTrue(isFinalizerValid(getDefaultFinalizerName(TestCustomResource.class))); } - @Test - void noFinalizerMarkerShouldWork() { - assertTrue(isFinalizerValid(Constants.NO_FINALIZER)); - } - @Test void equalsSpecObject() { var d1 = createTestDeployment(); diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/ControllerTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/ControllerTest.java index ba31d6634e..2f5b9bf4ba 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/ControllerTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/ControllerTest.java @@ -7,23 +7,24 @@ import io.javaoperatorsdk.operator.MockKubernetesClient; import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.sample.simple.TestCustomResource; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @SuppressWarnings("unchecked") class ControllerTest { + + final ControllerConfiguration configuration = mock(ControllerConfiguration.class); + final Reconciler reconciler = mock(Reconciler.class); + @Test void crdShouldNotBeCheckedForNativeResources() { final var client = MockKubernetesClient.client(Secret.class); - final var reconciler = mock(Reconciler.class); - final var configuration = mock(ControllerConfiguration.class); + when(configuration.getResourceClass()).thenReturn(Secret.class); final var controller = new Controller(reconciler, configuration, client); @@ -34,8 +35,6 @@ void crdShouldNotBeCheckedForNativeResources() { @Test void crdShouldNotBeCheckedForCustomResourcesIfDisabled() { final var client = MockKubernetesClient.client(TestCustomResource.class); - final var reconciler = mock(Reconciler.class); - final var configuration = mock(ControllerConfiguration.class); when(configuration.getResourceClass()).thenReturn(TestCustomResource.class); try { @@ -52,8 +51,6 @@ void crdShouldNotBeCheckedForCustomResourcesIfDisabled() { void crdShouldBeCheckedForCustomResourcesByDefault() { ConfigurationServiceProvider.reset(); final var client = MockKubernetesClient.client(TestCustomResource.class); - final var reconciler = mock(Reconciler.class); - final var configuration = mock(ControllerConfiguration.class); when(configuration.getResourceClass()).thenReturn(TestCustomResource.class); final var controller = new Controller(reconciler, configuration, client); @@ -62,4 +59,15 @@ void crdShouldBeCheckedForCustomResourcesByDefault() { assertThrows(MissingCRDException.class, controller::start); verify(client, times(1)).apiextensions(); } + + @Test + void usesFinalizerIfThereIfReconcilerImplementsCleaner() { + Reconciler reconciler = mock(Reconciler.class, withSettings().extraInterfaces(Cleaner.class)); + when(configuration.getResourceClass()).thenReturn(TestCustomResource.class); + + final var controller = new Controller(reconciler, + configuration, MockKubernetesClient.client(TestCustomResource.class)); + + assertThat(controller.useFinalizer()).isTrue(); + } } 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 b654ac5d1e..0b9517eb81 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 @@ -9,9 +9,9 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.TestUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; +import io.javaoperatorsdk.operator.processing.dependent.Creator; +import io.javaoperatorsdk.operator.processing.dependent.Updater; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SampleExternalResource; import io.javaoperatorsdk.operator.processing.event.source.UpdatableCache; @@ -84,7 +84,7 @@ void updatePutsNewResourceToCache() { @Test void deleteRemovesResourceFromCache() { - simpleDependentResource.cleanup(TestUtils.testCustomResource1(), null); + simpleDependentResource.delete(TestUtils.testCustomResource1(), null); verify(updatableCacheMock, times(1)).remove(any()); } @@ -111,6 +111,10 @@ public Optional fetchResource(HasMetadata primaryResourc return Optional.ofNullable(supplier.get()); } + @Override + protected void deleteResource(TestCustomResource primary, + Context context) {} + @Override public SampleExternalResource create( SampleExternalResource desired, TestCustomResource primary, @@ -127,9 +131,6 @@ public SampleExternalResource update( return SampleExternalResource.testResource1(); } - @Override - public void delete(TestCustomResource primary, Context context) {} - @Override protected SampleExternalResource desired(TestCustomResource primary, Context context) { diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessorTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessorTest.java index 802be9c3d9..e67d579adc 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessorTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/GenericResourceUpdatePreProcessorTest.java @@ -9,7 +9,6 @@ import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.ResourceUpdatePreProcessor; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java index 2e6ee4aa0d..ccf218d3d0 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcherTest.java @@ -93,9 +93,8 @@ private ReconciliationDispatcher init(R customResourc CustomResourceFacade customResourceFacade, boolean useFinalizer) { configuration = configuration == null ? mock(ControllerConfiguration.class) : configuration; - final var finalizer = useFinalizer ? DEFAULT_FINALIZER : Constants.NO_FINALIZER; - when(configuration.getFinalizer()).thenReturn(finalizer); - when(configuration.useFinalizer()).thenCallRealMethod(); + + when(configuration.getFinalizerName()).thenReturn(DEFAULT_FINALIZER); when(configuration.getName()).thenReturn("EventDispatcherTestController"); when(configuration.getResourceClass()).thenReturn((Class) customResource.getClass()); when(configuration.getRetryConfiguration()).thenReturn(RetryConfiguration.DEFAULT); @@ -103,7 +102,12 @@ private ReconciliationDispatcher init(R customResourc .thenReturn(Optional.of(Duration.ofHours(RECONCILIATION_MAX_INTERVAL))); Controller controller = new Controller<>(reconciler, configuration, - MockKubernetesClient.client(customResource.getClass())); + MockKubernetesClient.client(customResource.getClass())) { + @Override + public boolean useFinalizer() { + return useFinalizer; + } + }; controller.start(); return new ReconciliationDispatcher<>(controller, customResourceFacade); @@ -539,7 +543,8 @@ public ExecutionScope executionScopeWithCREvent(T res } private class TestReconciler - implements Reconciler, ErrorStatusHandler { + implements Reconciler, Cleaner, + ErrorStatusHandler { private BiFunction> reconcile; private BiFunction cleanup; private ErrorStatusHandler errorHandler; diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/CustomResourceSelectorTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/CustomResourceSelectorTest.java index fd08a614af..2d943deb80 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/CustomResourceSelectorTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/CustomResourceSelectorTest.java @@ -134,7 +134,7 @@ public TestCustomResource newMyResource(String app, String namespace) { public static class MyConfiguration extends DefaultControllerConfiguration { public MyConfiguration() { - super(MyController.class.getCanonicalName(), "mycontroller", null, Constants.NO_FINALIZER, + super(MyController.class.getCanonicalName(), "mycontroller", null, Constants.EMPTY_STRING, false, null, null, null, null, TestCustomResource.class, null, null); } diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java index d06cf97fe8..1c467e0490 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/event/source/controller/ControllerResourceEventSourceTest.java @@ -34,7 +34,7 @@ public void setup() { } @Test - public void skipsEventHandlingIfGenerationNotIncreased() { + void skipsEventHandlingIfGenerationNotIncreased() { TestCustomResource customResource = TestUtils.testCustomResource(); customResource.getMetadata().setFinalizers(List.of(FINALIZER)); customResource.getMetadata().setGeneration(2L); @@ -50,7 +50,7 @@ public void skipsEventHandlingIfGenerationNotIncreased() { } @Test - public void dontSkipEventHandlingIfMarkedForDeletion() { + void dontSkipEventHandlingIfMarkedForDeletion() { TestCustomResource customResource1 = TestUtils.testCustomResource(); source.eventReceived(ResourceAction.UPDATED, customResource1, customResource1); @@ -63,7 +63,7 @@ public void dontSkipEventHandlingIfMarkedForDeletion() { } @Test - public void normalExecutionIfGenerationChanges() { + void normalExecutionIfGenerationChanges() { TestCustomResource customResource1 = TestUtils.testCustomResource(); source.eventReceived(ResourceAction.UPDATED, customResource1, customResource1); @@ -75,7 +75,7 @@ public void normalExecutionIfGenerationChanges() { } @Test - public void handlesAllEventIfNotGenerationAware() { + void handlesAllEventIfNotGenerationAware() { source = new ControllerResourceEventSource<>(new TestController(false)); setup(); @@ -124,6 +124,11 @@ public TestController(boolean generationAware) { public EventSourceManager getEventSourceManager() { return eventSourceManager; } + + @Override + public boolean useFinalizer() { + return true; + } } private static class TestConfiguration extends diff --git a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestCustomReconciler.java b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestCustomReconciler.java index 9595f3c13f..3413b620b3 100644 --- a/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestCustomReconciler.java +++ b/operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestCustomReconciler.java @@ -15,7 +15,8 @@ import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; @ControllerConfiguration(generationAwareEventProcessing = false) -public class TestCustomReconciler implements Reconciler { +public class TestCustomReconciler + implements Reconciler, Cleaner { private static final Logger log = LoggerFactory.getLogger(TestCustomReconciler.class); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForReconcilerIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForReconcilerIT.java new file mode 100644 index 0000000000..5356204491 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForReconcilerIT.java @@ -0,0 +1,49 @@ +package io.javaoperatorsdk.operator; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.javaoperatorsdk.operator.junit.OperatorExtension; +import io.javaoperatorsdk.operator.sample.cleanerforreconciler.CleanerForReconcilerCustomResource; +import io.javaoperatorsdk.operator.sample.cleanerforreconciler.CleanerForReconcilerTestReconciler; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +class CleanerForReconcilerIT { + + public static final String TEST_RESOURCE_NAME = "cleaner-for-reconciler-test1"; + + @RegisterExtension + OperatorExtension operator = + OperatorExtension.builder().withReconciler(new CleanerForReconcilerTestReconciler()).build(); + + + @Test + void addsFinalizerAndCallsCleanupIfCleanerImplemented() { + var testResource = createTestResource(); + operator.create(CleanerForReconcilerCustomResource.class, testResource); + + await().until(() -> !operator.get(CleanerForReconcilerCustomResource.class, TEST_RESOURCE_NAME) + .getMetadata().getFinalizers().isEmpty()); + + operator.delete(CleanerForReconcilerCustomResource.class, testResource); + + await().until( + () -> operator.get(CleanerForReconcilerCustomResource.class, TEST_RESOURCE_NAME) == null); + + CleanerForReconcilerTestReconciler reconciler = + (CleanerForReconcilerTestReconciler) operator.getFirstReconciler(); + assertThat(reconciler.getNumberOfExecutions()).isEqualTo(1); + assertThat(reconciler.getNumberOfCleanupExecutions()).isEqualTo(1); + } + + private CleanerForReconcilerCustomResource createTestResource() { + CleanerForReconcilerCustomResource cr = new CleanerForReconcilerCustomResource(); + cr.setMetadata(new ObjectMeta()); + cr.getMetadata().setName(TEST_RESOURCE_NAME); + return cr; + } + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ControllerExecutionIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ControllerExecutionIT.java index 0a3ed114a1..3688b55d3c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/ControllerExecutionIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/ControllerExecutionIT.java @@ -1,5 +1,6 @@ package io.javaoperatorsdk.operator; +import java.time.Duration; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -42,6 +43,22 @@ void eventIsSkippedChangedOnMetadataOnlyUpdate() { assertThat(TestUtils.getNumberOfExecutions(operator)).isEqualTo(1); } + @Test + void cleanupExecuted() { + operator.getControllerOfType(TestReconciler.class).setUpdateStatus(true); + + TestCustomResource resource = TestUtils.testCustomResource(); + resource = operator.create(TestCustomResource.class, resource); + + awaitResourcesCreatedOrUpdated(); + awaitStatusUpdated(); + operator.delete(TestCustomResource.class, resource); + + await().atMost(Duration.ofSeconds(1)) + .until(() -> ((TestReconciler) operator.getFirstReconciler()) + .getNumberOfCleanupExecutions() == 1); + } + void awaitResourcesCreatedOrUpdated() { await("config map created") .atMost(5, TimeUnit.SECONDS) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/DeleterForManagedDependentResourcesOnlyIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/DeleterForManagedDependentResourcesOnlyIT.java new file mode 100644 index 0000000000..94c7c7798d --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/DeleterForManagedDependentResourcesOnlyIT.java @@ -0,0 +1,54 @@ +package io.javaoperatorsdk.operator; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.fabric8.kubernetes.api.model.ObjectMeta; +import io.javaoperatorsdk.operator.junit.OperatorExtension; +import io.javaoperatorsdk.operator.sample.cleanermanageddependent.CleanerForManagedDependentCustomResource; +import io.javaoperatorsdk.operator.sample.cleanermanageddependent.CleanerForManagedDependentTestReconciler; +import io.javaoperatorsdk.operator.sample.cleanermanageddependent.ConfigMapDependentResource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +class DeleterForManagedDependentResourcesOnlyIT { + + public static final String TEST_RESOURCE_NAME = "cleaner-for-reconciler-test1"; + + @RegisterExtension + OperatorExtension operator = + OperatorExtension.builder().withReconciler(new CleanerForManagedDependentTestReconciler()) + .build(); + + + @Test + void addsFinalizerAndCallsCleanupIfCleanerImplemented() { + var testResource = createTestResource(); + operator.create(CleanerForManagedDependentCustomResource.class, testResource); + + await().until( + () -> !operator.get(CleanerForManagedDependentCustomResource.class, TEST_RESOURCE_NAME) + .getMetadata().getFinalizers().isEmpty()); + + operator.delete(CleanerForManagedDependentCustomResource.class, testResource); + + await().until( + () -> operator.get(CleanerForManagedDependentCustomResource.class, + TEST_RESOURCE_NAME) == null); + + CleanerForManagedDependentTestReconciler reconciler = + (CleanerForManagedDependentTestReconciler) operator.getFirstReconciler(); + + assertThat(reconciler.getNumberOfExecutions()).isEqualTo(1); + assertThat(ConfigMapDependentResource.getNumberOfCleanupExecutions()).isEqualTo(1); + } + + private CleanerForManagedDependentCustomResource createTestResource() { + CleanerForManagedDependentCustomResource cr = new CleanerForManagedDependentCustomResource(); + cr.setMetadata(new ObjectMeta()); + cr.getMetadata().setName(TEST_RESOURCE_NAME); + return cr; + } + +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/EventSourceIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/EventSourceIT.java index eea996cb3b..5aaeb0bab4 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/EventSourceIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/EventSourceIT.java @@ -41,7 +41,6 @@ public EventSourceTestCustomResource createTestCustomResource(String id) { new ObjectMetaBuilder() .withName("eventsource-" + id) .withNamespace(operator.getNamespace()) - .withFinalizers(EventSourceTestCustomReconciler.FINALIZER_NAME) .build()); resource.setSpec(new EventSourceTestCustomResourceSpec()); resource.getSpec().setValue(id); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/RetryIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/RetryIT.java index 02b7b7af9e..7a951aadc7 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/RetryIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/RetryIT.java @@ -65,7 +65,6 @@ public static RetryTestCustomResource createTestCustomResource(String id) { resource.setMetadata( new ObjectMetaBuilder() .withName("retrysource-" + id) - .withFinalizers(RetryTestCustomReconciler.FINALIZER_NAME) .build()); resource.setKind("retrysample"); resource.setSpec(new RetryTestCustomResourceSpec()); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java index bd335c9ae7..61bc9f927c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java @@ -99,7 +99,6 @@ void awaitStatusUpdated(String name) { () -> { SubResourceTestCustomResource cr = operator.get(SubResourceTestCustomResource.class, name); - assertThat(cr.getMetadata().getFinalizers()).hasSize(1); assertThat(cr).isNotNull(); assertThat(cr.getStatus()).isNotNull(); assertThat(cr.getStatus().getState()) @@ -112,7 +111,6 @@ public SubResourceTestCustomResource createTestCustomResource(String id) { resource.setMetadata( new ObjectMetaBuilder() .withName("subresource-" + id) - .withFinalizers(SubResourceTestCustomReconciler.FINALIZER_NAME) .build()); resource.setKind("SubresourceSample"); resource.setSpec(new SubResourceTestCustomResourceSpec()); diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/UpdatingResAndSubResIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/UpdatingResAndSubResIT.java index d86ad51d60..df885110d4 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/UpdatingResAndSubResIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/UpdatingResAndSubResIT.java @@ -54,11 +54,8 @@ void awaitStatusUpdated(String name) { () -> { DoubleUpdateTestCustomResource cr = operator.get(DoubleUpdateTestCustomResource.class, name); - assertThat(cr) .isNotNull(); - assertThat(cr.getMetadata().getFinalizers()) - .hasSize(1); assertThat(cr.getStatus()) .isNotNull(); assertThat(cr.getStatus().getState()) diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationServiceTest.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationServiceTest.java index d123aa4899..c5bf845853 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationServiceTest.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationServiceTest.java @@ -79,7 +79,7 @@ void returnsValuesFromControllerAnnotationFinalizer() { configuration.getResourceTypeName()); assertEquals( ReconcilerUtils.getDefaultFinalizerName(TestCustomResource.class), - configuration.getFinalizer()); + configuration.getFinalizerName()); assertEquals(TestCustomResource.class, configuration.getResourceClass()); assertFalse(configuration.isGenerationAware()); } @@ -88,7 +88,7 @@ void returnsValuesFromControllerAnnotationFinalizer() { void returnCustomerFinalizerNameIfSet() { final var reconciler = new TestCustomFinalizerReconciler(); final var configuration = configurationService.getConfigurationFor(reconciler); - assertEquals(CUSTOM_FINALIZER_NAME, configuration.getFinalizer()); + assertEquals(CUSTOM_FINALIZER_NAME, configuration.getFinalizerName()); } @Test diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResource.java new file mode 100644 index 0000000000..7a4b255d28 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResource.java @@ -0,0 +1,17 @@ +package io.javaoperatorsdk.operator.sample.cleanerforreconciler; + +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.Kind; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +@Kind("CleanerForReconcilerCustomResource") +@ShortNames("cfr") +public class CleanerForReconcilerCustomResource + extends CustomResource + implements Namespaced { +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerTestReconciler.java new file mode 100644 index 0000000000..fad1bb7798 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerTestReconciler.java @@ -0,0 +1,39 @@ +package io.javaoperatorsdk.operator.sample.cleanerforreconciler; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; + +@ControllerConfiguration +public class CleanerForReconcilerTestReconciler + implements Reconciler, + Cleaner, + TestExecutionInfoProvider { + + private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + private final AtomicInteger numberOfCleanupExecutions = new AtomicInteger(0); + + @Override + public UpdateControl reconcile( + CleanerForReconcilerCustomResource resource, + Context context) { + numberOfExecutions.addAndGet(1); + return UpdateControl.noUpdate(); + } + + public int getNumberOfExecutions() { + return numberOfExecutions.get(); + } + + public int getNumberOfCleanupExecutions() { + return numberOfCleanupExecutions.get(); + } + + @Override + public DeleteControl cleanup(CleanerForReconcilerCustomResource resource, + Context context) { + numberOfCleanupExecutions.addAndGet(1); + return DeleteControl.defaultDelete(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResource.java new file mode 100644 index 0000000000..9e18e657aa --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResource.java @@ -0,0 +1,17 @@ +package io.javaoperatorsdk.operator.sample.cleanermanageddependent; + +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.Kind; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +@Kind("CleanerForReconcilerCustomResource") +@ShortNames("cfr") +public class CleanerForManagedDependentCustomResource + extends CustomResource + implements Namespaced { +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentTestReconciler.java new file mode 100644 index 0000000000..6be29c5092 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentTestReconciler.java @@ -0,0 +1,28 @@ +package io.javaoperatorsdk.operator.sample.cleanermanageddependent; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; +import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; + +@ControllerConfiguration(dependents = {@Dependent(type = ConfigMapDependentResource.class)}) +public class CleanerForManagedDependentTestReconciler + implements Reconciler, + TestExecutionInfoProvider { + + private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + + @Override + public UpdateControl reconcile( + CleanerForManagedDependentCustomResource resource, + Context context) { + numberOfExecutions.addAndGet(1); + return UpdateControl.noUpdate(); + } + + public int getNumberOfExecutions() { + return numberOfExecutions.get(); + } + +} 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 new file mode 100644 index 0000000000..332e2e7534 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java @@ -0,0 +1,44 @@ +package io.javaoperatorsdk.operator.sample.cleanermanageddependent; + +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; + +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; + +public class ConfigMapDependentResource extends + CRUDKubernetesDependentResource { + + private static final AtomicInteger numberOfCleanupExecutions = new AtomicInteger(0); + + public ConfigMapDependentResource() { + super(ConfigMap.class); + } + + @Override + protected ConfigMap desired(CleanerForManagedDependentCustomResource primary, + Context context) { + + ConfigMap configMap = new ConfigMap(); + configMap.setMetadata(new ObjectMeta()); + configMap.getMetadata().setName(primary.getMetadata().getName()); + configMap.getMetadata().setNamespace(primary.getMetadata().getNamespace()); + HashMap data = new HashMap<>(); + data.put("key1", "val1"); + configMap.setData(data); + return configMap; + } + + @Override + public void delete(CleanerForManagedDependentCustomResource primary, + Context context) { + super.delete(primary, context); + numberOfCleanupExecutions.incrementAndGet(); + } + + public static int getNumberOfCleanupExecutions() { + return numberOfCleanupExecutions.get(); + } +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java index 19e00e8ba2..4c1ffc4312 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/createupdateeventfilter/CreateUpdateEventFilterTestReconciler.java @@ -15,9 +15,7 @@ import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER) +@ControllerConfiguration public class CreateUpdateEventFilterTestReconciler implements Reconciler, EventSourceInitializer, diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter.java index 58d2ed1ede..bba45a44ac 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter.java @@ -1,12 +1,12 @@ package io.javaoperatorsdk.operator.sample.customfilter; -import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.processing.Controller; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; public class CustomFlagFilter implements ResourceEventFilter { @Override - public boolean acceptChange(ControllerConfiguration configuration, + public boolean acceptChange(Controller configuration, CustomFilteringTestResource oldResource, CustomFilteringTestResource newResource) { return newResource.getSpec().isFilter1(); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter2.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter2.java index f38a8c9553..ae6b5d684f 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter2.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/customfilter/CustomFlagFilter2.java @@ -1,12 +1,12 @@ package io.javaoperatorsdk.operator.sample.customfilter; -import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; +import io.javaoperatorsdk.operator.processing.Controller; import io.javaoperatorsdk.operator.processing.event.source.controller.ResourceEventFilter; public class CustomFlagFilter2 implements ResourceEventFilter { @Override - public boolean acceptChange(ControllerConfiguration configuration, + public boolean acceptChange(Controller configuration, CustomFilteringTestResource oldResource, CustomFilteringTestResource newResource) { return newResource.getSpec().isFilter2(); } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/errorstatushandler/ErrorStatusHandlerTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/errorstatushandler/ErrorStatusHandlerTestReconciler.java index 17ea106104..412a784b7c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/errorstatushandler/ErrorStatusHandlerTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/errorstatushandler/ErrorStatusHandlerTestReconciler.java @@ -8,9 +8,7 @@ import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER) +@ControllerConfiguration public class ErrorStatusHandlerTestReconciler implements Reconciler, TestExecutionInfoProvider, ErrorStatusHandler { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java index 97a99eed35..8e7dc1a6f2 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/informereventsource/InformerEventSourceTestCustomReconciler.java @@ -14,13 +14,11 @@ import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - /** * Copies the config map value from spec into status. The main purpose is to test and demonstrate * sample usage of InformerEventSource */ -@ControllerConfiguration(finalizerName = NO_FINALIZER) +@ControllerConfiguration public class InformerEventSourceTestCustomReconciler implements Reconciler, EventSourceInitializer { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/maxinterval/MaxIntervalTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/maxinterval/MaxIntervalTestReconciler.java index f9a34371ce..f868148145 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/maxinterval/MaxIntervalTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/maxinterval/MaxIntervalTestReconciler.java @@ -6,11 +6,8 @@ import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER, - reconciliationMaxInterval = @ReconciliationMaxInterval(interval = 50, - timeUnit = TimeUnit.MILLISECONDS)) +@ControllerConfiguration(reconciliationMaxInterval = @ReconciliationMaxInterval(interval = 50, + timeUnit = TimeUnit.MILLISECONDS)) public class MaxIntervalTestReconciler implements Reconciler, TestExecutionInfoProvider { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler1.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler1.java index de733ec6db..f4d9236077 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler1.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler1.java @@ -8,9 +8,7 @@ import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER, labelSelector = "!version") +@ControllerConfiguration(labelSelector = "!version") public class MultiVersionCRDTestReconciler1 implements Reconciler { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler2.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler2.java index 138647029e..b9521bd8d1 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler2.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/multiversioncrd/MultiVersionCRDTestReconciler2.java @@ -8,11 +8,7 @@ import io.javaoperatorsdk.operator.api.reconciler.Reconciler; import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration( - finalizerName = NO_FINALIZER, - labelSelector = "version in (v2)") +@ControllerConfiguration(labelSelector = "version in (v2)") public class MultiVersionCRDTestReconciler2 implements Reconciler { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java index 7a7964623f..02b9770acd 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/observedgeneration/ObservedGenerationTestReconciler.java @@ -3,11 +3,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; +import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER) +@ControllerConfiguration public class ObservedGenerationTestReconciler implements Reconciler { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/retry/RetryTestCustomReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/retry/RetryTestCustomReconciler.java index 8ccd7c2160..a5273aac4c 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/retry/RetryTestCustomReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/retry/RetryTestCustomReconciler.java @@ -5,7 +5,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; @@ -16,8 +15,6 @@ public class RetryTestCustomReconciler implements Reconciler, TestExecutionInfoProvider { - public static final String FINALIZER_NAME = - ReconcilerUtils.getDefaultFinalizerName(RetryTestCustomResource.class); private static final Logger log = LoggerFactory.getLogger(RetryTestCustomReconciler.class); private final AtomicInteger numberOfExecutions = new AtomicInteger(0); @@ -34,9 +31,6 @@ public UpdateControl reconcile(RetryTestCustomResource Context context) { numberOfExecutions.addAndGet(1); - if (!resource.getMetadata().getFinalizers().contains(FINALIZER_NAME)) { - throw new IllegalStateException("Finalizer is not present."); - } log.info("Value: " + resource.getSpec().getValue()); if (numberOfExecutions.get() < numberOfExecutionFails.get() + 1) { diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestReconciler.java index 146c96c7db..78db3b16f7 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestReconciler.java @@ -19,7 +19,8 @@ @ControllerConfiguration(generationAwareEventProcessing = false) public class TestReconciler - implements Reconciler, TestExecutionInfoProvider, + implements Reconciler, Cleaner, + TestExecutionInfoProvider, KubernetesClientAware { private static final Logger log = LoggerFactory.getLogger(TestReconciler.class); @@ -28,21 +29,14 @@ public class TestReconciler ReconcilerUtils.getDefaultFinalizerName(TestCustomResource.class); private final AtomicInteger numberOfExecutions = new AtomicInteger(0); + private final AtomicInteger numberOfCleanupExecutions = new AtomicInteger(0); private KubernetesClient kubernetesClient; private boolean updateStatus; - public TestReconciler() { - this(true); - } - public TestReconciler(boolean updateStatus) { this.updateStatus = updateStatus; } - public boolean isUpdateStatus() { - return updateStatus; - } - public void setUpdateStatus(boolean updateStatus) { this.updateStatus = updateStatus; } @@ -60,6 +54,7 @@ public void setKubernetesClient(KubernetesClient kubernetesClient) { @Override public DeleteControl cleanup( TestCustomResource resource, Context context) { + numberOfCleanupExecutions.incrementAndGet(); Boolean delete = kubernetesClient .configMaps() @@ -139,4 +134,8 @@ private Map configMapData(TestCustomResource resource) { public int getNumberOfExecutions() { return numberOfExecutions.get(); } + + public int getNumberOfCleanupExecutions() { + return numberOfCleanupExecutions.get(); + } } 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 e740032d6e..074c454560 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 @@ -7,23 +7,14 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientException; import io.javaoperatorsdk.operator.ReconcilerUtils; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusHandler; -import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusUpdateControl; -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.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; +import io.javaoperatorsdk.operator.api.reconciler.*; 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; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER) +@ControllerConfiguration public class StandaloneDependentTestReconciler implements Reconciler, EventSourceInitializer, diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/subresource/SubResourceTestCustomReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/subresource/SubResourceTestCustomReconciler.java index e520e94411..1e76681f25 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/subresource/SubResourceTestCustomReconciler.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/subresource/SubResourceTestCustomReconciler.java @@ -5,7 +5,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; @@ -20,8 +19,6 @@ public class SubResourceTestCustomReconciler public static final int RECONCILER_MIN_EXEC_TIME = 300; - public static final String FINALIZER_NAME = - ReconcilerUtils.getDefaultFinalizerName(SubResourceTestCustomResource.class); private static final Logger log = LoggerFactory.getLogger(SubResourceTestCustomReconciler.class); private final AtomicInteger numberOfExecutions = new AtomicInteger(0); @@ -31,9 +28,6 @@ public class SubResourceTestCustomReconciler public UpdateControl reconcile( SubResourceTestCustomResource resource, Context context) { numberOfExecutions.addAndGet(1); - if (!resource.getMetadata().getFinalizers().contains(FINALIZER_NAME)) { - throw new IllegalStateException("Finalizer is not present."); - } log.info("Value: " + resource.getSpec().getValue()); ensureStatusExists(resource); diff --git a/operator-framework/src/test/resources/compile-fixtures/ReconcilerImplemented2Interfaces.java b/operator-framework/src/test/resources/compile-fixtures/ReconcilerImplemented2Interfaces.java index 5ab0596319..0adc9aee09 100644 --- a/operator-framework/src/test/resources/compile-fixtures/ReconcilerImplemented2Interfaces.java +++ b/operator-framework/src/test/resources/compile-fixtures/ReconcilerImplemented2Interfaces.java @@ -1,15 +1,13 @@ package io; import io.fabric8.kubernetes.client.CustomResource; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import io.javaoperatorsdk.operator.api.reconciler.*; + import java.io.Serializable; @ControllerConfiguration -public class ReconcilerImplemented2Interfaces implements Serializable, Reconciler { +public class ReconcilerImplemented2Interfaces implements Serializable, + Reconciler, Cleaner { public static class MyCustomResource extends CustomResource { } diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java index b52d7931da..f306292ff8 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/MySQLSchemaReconciler.java @@ -9,12 +9,10 @@ import io.javaoperatorsdk.operator.sample.dependent.SchemaDependentResource; import io.javaoperatorsdk.operator.sample.dependent.SecretDependentResource; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; import static io.javaoperatorsdk.operator.sample.dependent.SecretDependentResource.MYSQL_SECRET_USERNAME; import static java.lang.String.format; -// todo handle this, should work with finalizer -@ControllerConfiguration(finalizerName = NO_FINALIZER, +@ControllerConfiguration( dependents = { @Dependent(type = SecretDependentResource.class), @Dependent(type = SchemaDependentResource.class) diff --git a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java index 273cd086a1..b3155f9199 100644 --- a/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java +++ b/sample-operators/mysql-schema/src/main/java/io/javaoperatorsdk/operator/sample/dependent/SchemaDependentResource.java @@ -11,10 +11,9 @@ import io.fabric8.kubernetes.api.model.Secret; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceConfigurator; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; +import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; +import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.external.PerResourcePollingDependentResource; import io.javaoperatorsdk.operator.sample.MySQLDbConfig; import io.javaoperatorsdk.operator.sample.MySQLSchema; @@ -29,8 +28,10 @@ public class SchemaDependentResource extends PerResourcePollingDependentResource implements EventSourceProvider, DependentResourceConfigurator, - Creator, - Deleter { + Creator +// todo fix +// , Deleter +{ private static final Logger log = LoggerFactory.getLogger(SchemaDependentResource.class); @@ -74,7 +75,7 @@ private Connection getConnection() throws SQLException { return DriverManager.getConnection(connectURL, dbConfig.getUser(), dbConfig.getPassword()); } - @Override + // @Override public void delete(MySQLSchema primary, Context context) { try (Connection connection = getConnection()) { var userName = primary.getStatus() != null ? primary.getStatus().getUserName() : null; 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 60c4c4d2b0..7ee78deed7 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 @@ -7,8 +7,8 @@ import io.fabric8.kubernetes.api.model.Secret; import io.fabric8.kubernetes.api.model.SecretBuilder; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Matcher.Result; +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.PrimaryToSecondaryMapper; diff --git a/sample-operators/mysql-schema/src/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java b/sample-operators/mysql-schema/src/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java index b8e8b0566a..59f3bfcd98 100644 --- a/sample-operators/mysql-schema/src/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java +++ b/sample-operators/mysql-schema/src/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java @@ -39,6 +39,7 @@ class MySQLSchemaOperatorE2E { static final String MY_SQL_NS = "mysql"; private final static List infrastructure = new ArrayList<>(); + public static final String TEST_RESOURCE_NAME = "mydb1"; static { infrastructure.add( @@ -83,25 +84,12 @@ public MySQLSchemaOperatorE2E() throws FileNotFoundException {} @Test void test() throws IOException { // Opening a port-forward if running locally - LocalPortForward portForward = null; - if (isLocal()) { - String podName = - client - .pods() - .inNamespace(MY_SQL_NS) - .withLabel("app", "mysql") - .list() - .getItems() - .get(0) - .getMetadata() - .getName(); - - portForward = client.pods().inNamespace(MY_SQL_NS).withName(podName).portForward(3306, 3306); - } + LocalPortForward portForward = createLocalPortForward(); MySQLSchema testSchema = new MySQLSchema(); testSchema.setMetadata( - new ObjectMetaBuilder().withName("mydb1").withNamespace(operator.getNamespace()).build()); + new ObjectMetaBuilder().withName(TEST_RESOURCE_NAME).withNamespace(operator.getNamespace()) + .build()); testSchema.setSpec(new SchemaSpec()); testSchema.getSpec().setEncoding("utf8"); @@ -130,4 +118,22 @@ void test() throws IOException { portForward.close(); } } + + private LocalPortForward createLocalPortForward() { + if (isLocal()) { + String podName = + client + .pods() + .inNamespace(MY_SQL_NS) + .withLabel("app", "mysql") + .list() + .getItems() + .get(0) + .getMetadata() + .getName(); + + return client.pods().inNamespace(MY_SQL_NS).withName(podName).portForward(3306, 3306); + } + return null; + } } 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 75632f3e69..1e0c7c08d1 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,8 +5,8 @@ import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; +import io.javaoperatorsdk.operator.processing.dependent.Creator; +import io.javaoperatorsdk.operator.processing.dependent.Updater; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; 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 c52553851d..8efaadc0a8 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,8 +5,8 @@ import io.fabric8.kubernetes.api.model.ServiceBuilder; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; +import io.javaoperatorsdk.operator.processing.dependent.Creator; +import io.javaoperatorsdk.operator.processing.dependent.Updater; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; public class ServiceDependentResource extends KubernetesDependentResource diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java index dfad4533e3..30eb3c3848 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java @@ -13,14 +13,11 @@ import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - /** * Runs a specified number of Tomcat app server Pods. It uses a Deployment to create the Pods. Also * creates a Service over which the Pods can be accessed. */ @ControllerConfiguration( - finalizerName = NO_FINALIZER, dependents = { @Dependent(type = DeploymentDependentResource.class), @Dependent(type = ServiceDependentResource.class) diff --git a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java index 58d17235ae..68e3fbe135 100644 --- a/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java +++ b/sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/WebappReconciler.java @@ -18,23 +18,16 @@ import io.fabric8.kubernetes.client.dsl.ExecListener; import io.fabric8.kubernetes.client.dsl.ExecWatch; import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration; -import io.javaoperatorsdk.operator.api.reconciler.DeleteControl; -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.reconciler.*; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - -@ControllerConfiguration(finalizerName = NO_FINALIZER) -public class WebappReconciler implements Reconciler, EventSourceInitializer { +@ControllerConfiguration +public class WebappReconciler + implements Reconciler, Cleaner, EventSourceInitializer { private static final Logger log = LoggerFactory.getLogger(WebappReconciler.class); diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java index bc7bb83894..570f2ffb53 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java @@ -1,6 +1,8 @@ package io.javaoperatorsdk.operator.sample; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -16,11 +18,8 @@ import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; - /** Shows how to implement reconciler using the low level api directly. */ @ControllerConfiguration( - finalizerName = NO_FINALIZER, labelSelector = WebPageReconciler.LOW_LEVEL_LABEL_KEY) public class WebPageReconciler implements Reconciler, ErrorStatusHandler, EventSourceInitializer { diff --git a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconcilerDependentResources.java b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconcilerDependentResources.java index 90f747d158..7698c3a16d 100644 --- a/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconcilerDependentResources.java +++ b/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconcilerDependentResources.java @@ -22,7 +22,8 @@ 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.processing.dependent.kubernetes.CrudKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -30,12 +31,11 @@ import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper; import static io.javaoperatorsdk.operator.ReconcilerUtils.loadYaml; -import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER; /** * Shows how to implement reconciler using standalone dependent resources. */ -@ControllerConfiguration(finalizerName = NO_FINALIZER, +@ControllerConfiguration( labelSelector = WebPageReconcilerDependentResources.DEPENDENT_RESOURCE_LABEL_SELECTOR) public class WebPageReconcilerDependentResources implements Reconciler, ErrorStatusHandler, EventSourceInitializer { @@ -100,7 +100,7 @@ private void createDependentResources(KubernetesClient client) { .setLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR)); this.deploymentDR = - new CrudKubernetesDependentResource<>(Deployment.class) { + new CRUDKubernetesDependentResource<>(Deployment.class) { @Override protected Deployment desired(WebPage webPage, Context context) { @@ -132,7 +132,7 @@ protected Deployment desired(WebPage webPage, Context context) { .setLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR)); this.serviceDR = - new CrudKubernetesDependentResource<>(Service.class) { + new CRUDKubernetesDependentResource<>(Service.class) { @Override protected Service desired(WebPage webPage, Context context) { @@ -163,7 +163,7 @@ public static String serviceName(WebPage webPage) { } private class ConfigMapDependentResource - extends CrudKubernetesDependentResource + extends CRUKubernetesDependentResource implements PrimaryToSecondaryMapper { public ConfigMapDependentResource() { diff --git a/smoke-test-samples/common/src/main/java/io/javaoperatorsdk/operator/sample/CustomServiceReconciler.java b/smoke-test-samples/common/src/main/java/io/javaoperatorsdk/operator/sample/CustomServiceReconciler.java index a899c50756..9a5e188cba 100644 --- a/smoke-test-samples/common/src/main/java/io/javaoperatorsdk/operator/sample/CustomServiceReconciler.java +++ b/smoke-test-samples/common/src/main/java/io/javaoperatorsdk/operator/sample/CustomServiceReconciler.java @@ -29,12 +29,6 @@ public CustomServiceReconciler(KubernetesClient kubernetesClient) { this.kubernetesClient = kubernetesClient; } - @Override - public DeleteControl cleanup(CustomService resource, Context context) { - log.info("Cleaning up for: {}", resource.getMetadata().getName()); - return Reconciler.super.cleanup(resource, context); - } - @Override public UpdateControl reconcile( CustomService resource, Context context) { @@ -45,17 +39,20 @@ public UpdateControl reconcile( ServiceSpec serviceSpec = new ServiceSpec(); serviceSpec.setPorts(Collections.singletonList(servicePort)); + var service = new ServiceBuilder() + .withNewMetadata() + .withName(resource.getSpec().getName()) + .addToLabels("testLabel", resource.getSpec().getLabel()) + .endMetadata() + .withSpec(serviceSpec) + .build(); + service.addOwnerReference(resource); + kubernetesClient .services() .inNamespace(resource.getMetadata().getNamespace()) - .createOrReplace( - new ServiceBuilder() - .withNewMetadata() - .withName(resource.getSpec().getName()) - .addToLabels("testLabel", resource.getSpec().getLabel()) - .endMetadata() - .withSpec(serviceSpec) - .build()); + .createOrReplace(service); + return UpdateControl.updateResource(resource); } }