From c01b7d74d2b7a4d4702f8c2fdd23ccd0a7e0a5bf Mon Sep 17 00:00:00 2001 From: csviri Date: Mon, 14 Mar 2022 14:28:23 +0100 Subject: [PATCH 01/27] feat: separate cleaner interface from reconciler --- .../operator/api/reconciler/Cleaner.java | 32 +++++++++++++++++++ .../operator/api/reconciler/Reconciler.java | 25 --------------- 2 files changed, 32 insertions(+), 25 deletions(-) create mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java 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..62de7f2ea1 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/Cleaner.java @@ -0,0 +1,32 @@ +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. + */ + default DeleteControl cleanup(R resource, Context context) { + return DeleteControl.defaultDelete(); + } + +} 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(); - } } From 9dcfe42227b7bb72c2d5bb702da52c4d1338407f Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 10:48:15 +0100 Subject: [PATCH 02/27] fix: builds without tests --- .../operator/ReconcilerUtils.java | 2 +- .../AnnotationControllerConfiguration.java | 2 +- .../api/config/ControllerConfiguration.java | 7 +-- .../ControllerConfigurationOverrider.java | 2 +- .../DefaultControllerConfiguration.java | 2 +- .../operator/api/reconciler/Cleaner.java | 48 +++++++++---------- .../operator/api/reconciler/Constants.java | 1 - .../reconciler/ControllerConfiguration.java | 4 +- .../operator/processing/Controller.java | 17 ++++--- .../dependent/DependentResourceManager.java | 13 ++--- .../event/ReconciliationDispatcher.java | 25 ++++------ .../ControllerResourceEventSource.java | 2 +- .../controller/ResourceEventFilter.java | 18 +++---- .../controller/ResourceEventFilters.java | 10 ++-- .../operator/ReconcilerUtilsTest.java | 6 --- .../event/ReconciliationDispatcherTest.java | 15 ++++-- .../source/CustomResourceSelectorTest.java | 2 +- .../sample/simple/TestCustomReconciler.java | 3 +- .../DefaultConfigurationServiceTest.java | 4 +- ...CreateUpdateEventFilterTestReconciler.java | 4 +- .../sample/customfilter/CustomFlagFilter.java | 4 +- .../customfilter/CustomFlagFilter2.java | 4 +- .../ErrorStatusHandlerTestReconciler.java | 4 +- ...formerEventSourceTestCustomReconciler.java | 4 +- .../MaxIntervalTestReconciler.java | 7 +-- .../MultiVersionCRDTestReconciler1.java | 4 +- .../MultiVersionCRDTestReconciler2.java | 6 +-- .../ObservedGenerationTestReconciler.java | 9 ++-- .../sample/simple/TestReconciler.java | 3 +- .../StandaloneDependentTestReconciler.java | 4 +- .../ReconcilerImplemented2Interfaces.java | 10 ++-- .../sample/MySQLSchemaReconciler.java | 3 +- .../operator/sample/TomcatReconciler.java | 3 -- .../operator/sample/WebappReconciler.java | 15 ++---- .../operator/sample/WebPageReconciler.java | 8 ++-- .../WebPageReconcilerDependentResources.java | 3 +- .../sample/CustomServiceReconciler.java | 4 +- 37 files changed, 113 insertions(+), 169 deletions(-) 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 index 62de7f2ea1..e2e70a246d 100644 --- 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 @@ -2,31 +2,29 @@ import io.fabric8.kubernetes.api.model.HasMetadata; -public interface Cleaner { +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. - */ - default DeleteControl cleanup(R resource, Context context) { - return DeleteControl.defaultDelete(); - } + /** + * 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/ControllerConfiguration.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/ControllerConfiguration.java index 0feaa34b2d..c1b9aea7a7 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,7 @@ 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. * * @return the finalizer name */ 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 5fc1b9ede7..9dd1a985e7 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 @@ -3,6 +3,7 @@ import java.util.LinkedList; import java.util.List; +import io.javaoperatorsdk.operator.api.reconciler.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,21 +21,15 @@ import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.monitoring.Metrics; import io.javaoperatorsdk.operator.api.monitoring.Metrics.ControllerExecution; -import io.javaoperatorsdk.operator.api.reconciler.Context; -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.Ignore; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; +import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.processing.dependent.DependentResourceManager; import io.javaoperatorsdk.operator.processing.event.EventSourceManager; import io.javaoperatorsdk.operator.processing.event.source.EventSource; @SuppressWarnings({"unchecked"}) @Ignore -public class Controller

implements Reconciler

, +public class Controller

implements Reconciler

, Cleaner

, LifecycleAware, EventSourceInitializer

{ private static final Logger log = LoggerFactory.getLogger(Controller.class); @@ -80,7 +75,7 @@ public String successTypeName(DeleteControl deleteControl) { @Override public DeleteControl execute() { - return reconciler.cleanup(resource, context); + return ((Cleaner

) reconciler).cleanup(resource, context); } }); } catch (Exception e) { @@ -265,6 +260,10 @@ public void stop() { } } + public boolean useFinalizer() { + return reconciler instanceof Cleaner; + } + @SuppressWarnings("rawtypes") public List getDependents() { return dependents.getDependents(); diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index 3dd3a2860e..0b60f35678 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -12,14 +12,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ContextInitializer; -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.Ignore; -import io.javaoperatorsdk.operator.api.reconciler.Reconciler; -import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; +import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceConfigurator; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; @@ -30,7 +23,7 @@ @SuppressWarnings({"rawtypes", "unchecked"}) @Ignore public class DependentResourceManager

- implements EventSourceInitializer

, Reconciler

{ + implements EventSourceInitializer

, Reconciler

, Cleaner

{ private static final Logger log = LoggerFactory.getLogger(DependentResourceManager.class); @@ -73,7 +66,7 @@ public UpdateControl

reconcile(P resource, Context

context) { public DeleteControl cleanup(P resource, Context

context) { initContextIfNeeded(resource, context); dependents.forEach(dependent -> dependent.cleanup(resource, context)); - return Reconciler.super.cleanup(resource, context); + return DeleteControl.defaultDelete(); } private void initContextIfNeeded(P resource, Context 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 6ca6959bbb..ef44fe0af8 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; @@ -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 // 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..087a460c8b 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's configuration * @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,9 +32,9 @@ 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) -> { + : (Controller

configuration, P oldResource, P newResource) -> { boolean result = acceptChange(configuration, oldResource, newResource); return result && other.acceptChange(configuration, oldResource, newResource); }; @@ -48,9 +48,9 @@ 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) -> { + : (Controller

configuration, P oldResource, P newResource) -> { boolean result = acceptChange(configuration, oldResource, newResource); return result || other.acceptChange(configuration, 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/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/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/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/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/simple/TestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestReconciler.java index 146c96c7db..f05999ce46 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); 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 4a236e6e00..2b264ef8fb 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 @@ -14,9 +14,7 @@ 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/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..50f367ef39 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,11 @@ 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/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..33130939e9 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,9 @@ package io.javaoperatorsdk.operator.sample; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -16,11 +19,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 d9efec3b19..78c9aeaa11 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 @@ -18,12 +18,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 { 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..6320e85f99 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 @@ -15,7 +15,7 @@ /** A very simple sample controller that creates a service with a label. */ @ControllerConfiguration -public class CustomServiceReconciler implements Reconciler { +public class CustomServiceReconciler implements Reconciler, Cleaner { private static final Logger log = LoggerFactory.getLogger(CustomServiceReconciler.class); @@ -32,7 +32,7 @@ public CustomServiceReconciler(KubernetesClient kubernetesClient) { @Override public DeleteControl cleanup(CustomService resource, Context context) { log.info("Cleaning up for: {}", resource.getMetadata().getName()); - return Reconciler.super.cleanup(resource, context); + return DeleteControl.defaultDelete(); } @Override From 21cc19444ab2386b70d13de5e639bcb01de42f6e Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 11:16:48 +0100 Subject: [PATCH 03/27] wip --- .../controller/ControllerResourceEventSourceTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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..d31747fce9 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(); From ff1aa952a03aa6536d9f7667cfb4447e47460ef8 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 12:50:59 +0100 Subject: [PATCH 04/27] fix: unit tests --- .../source/controller/ControllerResourceEventSourceTest.java | 5 +++++ 1 file changed, 5 insertions(+) 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 d31747fce9..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 @@ -124,6 +124,11 @@ public TestController(boolean generationAware) { public EventSourceManager getEventSourceManager() { return eventSourceManager; } + + @Override + public boolean useFinalizer() { + return true; + } } private static class TestConfiguration extends From 14ec0d7192049e58788bbfe16d45a1a83d8d5363 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 13:34:57 +0100 Subject: [PATCH 05/27] fix: integration tests --- .../java/io/javaoperatorsdk/operator/EventSourceIT.java | 1 - .../src/test/java/io/javaoperatorsdk/operator/RetryIT.java | 1 - .../io/javaoperatorsdk/operator/SubResourceUpdateIT.java | 1 - .../operator/sample/retry/RetryTestCustomReconciler.java | 6 ------ .../sample/subresource/SubResourceTestCustomReconciler.java | 6 ------ 5 files changed, 15 deletions(-) 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 85e11c7287..401f92cc36 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java @@ -114,7 +114,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/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/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); From 94b68da917c02eddaddded466039d4667ae9049f Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 13:55:58 +0100 Subject: [PATCH 06/27] fix: integration tests --- .../java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java | 1 - .../io/javaoperatorsdk/operator/UpdatingResAndSubResIT.java | 3 --- 2 files changed, 4 deletions(-) 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 401f92cc36..008711c5e4 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/SubResourceUpdateIT.java @@ -101,7 +101,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()) 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()) From 6c33fa55cc24d24f08f344fd2c2116977fabafd1 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 14:06:03 +0100 Subject: [PATCH 07/27] fix: format --- .../operator/sample/simple/TestReconciler.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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 f05999ce46..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 @@ -29,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; } @@ -61,6 +54,7 @@ public void setKubernetesClient(KubernetesClient kubernetesClient) { @Override public DeleteControl cleanup( TestCustomResource resource, Context context) { + numberOfCleanupExecutions.incrementAndGet(); Boolean delete = kubernetesClient .configMaps() @@ -140,4 +134,8 @@ private Map configMapData(TestCustomResource resource) { public int getNumberOfExecutions() { return numberOfExecutions.get(); } + + public int getNumberOfCleanupExecutions() { + return numberOfCleanupExecutions.get(); + } } From 8416246e389316a3efeeead86f0019990b6c5f3a Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 14:20:31 +0100 Subject: [PATCH 08/27] fix: added integration test --- .../operator/ControllerExecutionIT.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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) From 396b5a1fdf789c883f6ca44e5ac27b142f502db9 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 15 Mar 2022 14:53:29 +0100 Subject: [PATCH 09/27] docs: update docs --- docs/documentation/features.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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) From 4831df75900f0f9e4bd2a0eca5b87e9b3003e7c0 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 16 Mar 2022 10:49:34 +0100 Subject: [PATCH 10/27] fix: format --- .../io/javaoperatorsdk/operator/processing/Controller.java | 3 +-- .../io/javaoperatorsdk/operator/sample/WebPageReconciler.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) 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 9dd1a985e7..fd0fb3c05f 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 @@ -3,7 +3,6 @@ import java.util.LinkedList; import java.util.List; -import io.javaoperatorsdk.operator.api.reconciler.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,8 +20,8 @@ import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.monitoring.Metrics; import io.javaoperatorsdk.operator.api.monitoring.Metrics.ControllerExecution; -import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.*; +import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource; import io.javaoperatorsdk.operator.processing.dependent.DependentResourceManager; import io.javaoperatorsdk.operator.processing.event.EventSourceManager; import io.javaoperatorsdk.operator.processing.event.source.EventSource; 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 33130939e9..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 @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; From 7360e66b3dcfa1e47f09bc0dd8b7d698199644ae Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 16 Mar 2022 13:42:27 +0100 Subject: [PATCH 11/27] fix: rename --- .../operator/processing/event/ReconciliationDispatcher.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ef44fe0af8..2e244b9a67 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 @@ -59,7 +59,7 @@ 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", getName(resource), @@ -75,7 +75,7 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) } } - private boolean shouldNotDispatchToDelete(R resource) { + private boolean shouldNotDispatchToCleanup(R resource) { // we don't dispatch to delete if the controller is configured to use a finalizer but that // finalizer is not present (which means it's already been removed) return !controller.useFinalizer() || (controller.useFinalizer() From aa1a2b6fe4e771c626c6b99331bf35acbf7eb121 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 16 Mar 2022 14:20:03 +0100 Subject: [PATCH 12/27] feat: separate cleaner interface for DependetResource --- .../dependent/AbstractDependentResource.java | 14 -------------- .../dependent/{Deleter.java => Cleaner.java} | 4 ++-- .../reconciler/dependent/DependentResource.java | 2 -- .../dependent/DependentResourceManager.java | 7 ++++++- .../external/AbstractSimpleDependentResource.java | 6 ++++-- .../CrudKubernetesDependentResource.java | 4 ++-- .../kubernetes/KubernetesDependentResource.java | 2 +- .../AbstractSimpleDependentResourceTest.java | 11 ++++++----- .../sample/dependent/SchemaDependentResource.java | 6 +++--- 9 files changed, 24 insertions(+), 32 deletions(-) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/{Deleter.java => Cleaner.java} (67%) 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/api/reconciler/dependent/AbstractDependentResource.java index 0a750d836c..67fa1d928d 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/api/reconciler/dependent/AbstractDependentResource.java @@ -13,16 +13,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 @@ -145,13 +142,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"); @@ -167,8 +157,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/Deleter.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java similarity index 67% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java index 0a1bfc1bab..5ec48c6af8 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/Cleaner.java @@ -4,6 +4,6 @@ import io.javaoperatorsdk.operator.api.reconciler.Context; @FunctionalInterface -public interface Deleter

{ - void delete(P primary, Context

context); +public interface Cleaner

{ + void cleanup(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/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index 0b60f35678..adef298d54 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -65,7 +65,12 @@ public UpdateControl

reconcile(P resource, Context

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

context) { initContextIfNeeded(resource, context); - dependents.forEach(dependent -> dependent.cleanup(resource, context)); + dependents.forEach(dependent -> { + if (dependent instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) { + ((io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner

) dependent) + .cleanup(resource, context); + } + }); return DeleteControl.defaultDelete(); } 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..0e941f7f67 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 @@ -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 cleanup(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 index 88e9bdc7ae..8b08217b24 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,8 +1,8 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; import io.fabric8.kubernetes.api.model.HasMetadata; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; /** @@ -13,5 +13,5 @@ */ public abstract class CrudKubernetesDependentResource extends - KubernetesDependentResource implements Creator, Updater, Deleter

{ + KubernetesDependentResource implements Creator, Updater, Cleaner

{ } 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 7ceadaf13c..276ebab50d 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 @@ -103,7 +103,7 @@ public Result match(R actualResource, P primary, Context

context) { return matcher.match(actualResource, primary, context); } - public void delete(P primary, Context

context) { + public void cleanup(P primary, Context

context) { if (!addOwnerReference) { var resource = getResource(primary); resource.ifPresent(r -> client.resource(r).delete()); 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..f7c2932fa7 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,8 +9,8 @@ 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.Cleaner; 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.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SampleExternalResource; @@ -92,7 +92,7 @@ private static class SimpleDependentResource extends AbstractSimpleDependentResource implements Creator, Updater, - Deleter { + Cleaner { private final Supplier supplier; @@ -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/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 f5a5e9ea18..4bdcd9f3a1 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,8 +11,8 @@ import io.fabric8.kubernetes.api.model.Secret; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; 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.processing.dependent.external.PerResourcePollingDependentResource; @@ -29,7 +29,7 @@ public class SchemaDependentResource implements EventSourceProvider, DependentResourceConfigurator, Creator, - Deleter { + Cleaner { private static final Logger log = LoggerFactory.getLogger(SchemaDependentResource.class); @@ -70,7 +70,7 @@ private Connection getConnection() throws SQLException { } @Override - public void delete(MySQLSchema primary, Context context) { + public void cleanup(MySQLSchema primary, Context context) { try (Connection connection = getConnection()) { var userName = primary.getStatus() != null ? primary.getStatus().getUserName() : null; SchemaService.deleteSchemaAndRelatedUser(connection, primary.getMetadata().getName(), From 6f5dfb82294112bf344392eb3c8cbd924146e24e Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 16 Mar 2022 14:29:25 +0100 Subject: [PATCH 13/27] refactor: dependent resources package structure --- .../operator/api/reconciler/Context.java | 2 +- .../operator/api/reconciler/DefaultContext.java | 2 +- .../operator/api/reconciler/dependent/Cleaner.java | 6 ++++++ .../api/reconciler/dependent/ReconcileResult.java | 4 ++-- .../{ => managed}/DependentResourceConfigurator.java | 2 +- .../{ => managed}/KubernetesClientAware.java | 2 +- .../ManagedDependentResourceContext.java | 3 ++- .../dependent/AbstractDependentResource.java | 3 ++- .../reconciler => processing}/dependent/Creator.java | 2 +- .../dependent/DependentResourceManager.java | 4 ++-- .../dependent/DesiredEqualsMatcher.java | 2 +- .../reconciler => processing}/dependent/Matcher.java | 2 +- .../reconciler => processing}/dependent/Updater.java | 4 ++-- .../external/AbstractCachingDependentResource.java | 2 +- .../external/AbstractSimpleDependentResource.java | 6 +++--- .../kubernetes/CrudKubernetesDependentResource.java | 4 ++-- .../kubernetes/GenericKubernetesResourceMatcher.java | 2 +- .../kubernetes/GenericResourceUpdatePreProcessor.java | 1 - .../kubernetes/KubernetesDependentResource.java | 11 +++++------ .../kubernetes}/ResourceUpdatePreProcessor.java | 2 +- .../external/AbstractSimpleDependentResourceTest.java | 4 ++-- .../GenericResourceUpdatePreProcessorTest.java | 1 - .../StandaloneDependentTestReconciler.java | 4 ++-- .../sample/dependent/SchemaDependentResource.java | 4 ++-- .../sample/dependent/SecretDependentResource.java | 4 ++-- .../operator/sample/DeploymentDependentResource.java | 4 ++-- .../operator/sample/ServiceDependentResource.java | 4 ++-- 27 files changed, 48 insertions(+), 43 deletions(-) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/{ => managed}/DependentResourceConfigurator.java (55%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/{ => managed}/KubernetesClientAware.java (69%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/{ => managed}/ManagedDependentResourceContext.java (96%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/AbstractDependentResource.java (97%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/Creator.java (79%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/DesiredEqualsMatcher.java (91%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/Matcher.java (92%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler => processing}/dependent/Updater.java (68%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/{api/reconciler/dependent => processing/dependent/kubernetes}/ResourceUpdatePreProcessor.java (78%) 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/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/dependent/Cleaner.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java index 5ec48c6af8..734859a874 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.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 Cleaner

{ void cleanup(P primary, Context

context); 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/api/reconciler/dependent/AbstractDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java similarity index 97% 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 67fa1d928d..3aaabc39d1 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 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/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index adef298d54..305ece4999 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -14,9 +14,9 @@ import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; import io.javaoperatorsdk.operator.api.reconciler.*; 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.Controller; import io.javaoperatorsdk.operator.processing.event.source.EventSource; 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 86f2c23d54..f0b1a7d169 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 @@ -4,8 +4,8 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.config.Utils; -import io.javaoperatorsdk.operator.api.reconciler.dependent.AbstractDependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; +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 0e941f7f67..79f1a420fb 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; diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CrudKubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CrudKubernetesDependentResource.java index 8b08217b24..75cabce6a4 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 @@ -2,8 +2,8 @@ import io.fabric8.kubernetes.api.model.HasMetadata; import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; -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; /** * Adaptor Class for standalone mode for resources that manages Create, Update and Delete 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 276ebab50d..b6c2d86fab 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 @@ -15,13 +15,12 @@ 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.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/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 f7c2932fa7..9fa4e68963 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 @@ -10,8 +10,8 @@ import io.javaoperatorsdk.operator.TestUtils; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; -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.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SampleExternalResource; import io.javaoperatorsdk.operator.processing.event.source.UpdatableCache; 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/src/test/java/io/javaoperatorsdk/operator/sample/standalonedependent/StandaloneDependentTestReconciler.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/standalonedependent/StandaloneDependentTestReconciler.java index 2b264ef8fb..421b8740c0 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 @@ -8,9 +8,9 @@ import io.fabric8.kubernetes.client.KubernetesClientException; import io.javaoperatorsdk.operator.ReconcilerUtils; import io.javaoperatorsdk.operator.api.reconciler.*; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater; 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; 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 4bdcd9f3a1..e59f38c472 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 @@ -12,9 +12,9 @@ import io.fabric8.kubernetes.api.model.Secret; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Creator; -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.*; import io.javaoperatorsdk.operator.sample.schema.Schema; 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 15fff4d65e..9d293607fb 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/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 b408a07ac9..949c9621fa 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 3b618906ab..4852fabacc 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 From b12f72875167770029eb5337b00086ec1b8c7d79 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 16 Mar 2022 16:36:59 +0100 Subject: [PATCH 14/27] fix: use finalizer if dependent resources are cleaners --- .../operator/processing/Controller.java | 54 ++++++++++--------- .../dependent/DependentResourceManager.java | 20 ++++++- 2 files changed, 47 insertions(+), 27 deletions(-) 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 fd0fb3c05f..309c511511 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 @@ -52,31 +52,35 @@ public Controller(Reconciler

reconciler, @Override public DeleteControl cleanup(P resource, Context

context) { - dependents.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 ((Cleaner

) 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() { + dependents.cleanup(resource, context); + if (reconciler instanceof Cleaner) { + return ((Cleaner

) reconciler).cleanup(resource, context); + } else { + return DeleteControl.defaultDelete(); + } + } + }); } catch (Exception e) { throw new OperatorException(e); } @@ -260,7 +264,7 @@ public void stop() { } public boolean useFinalizer() { - return reconciler instanceof Cleaner; + return reconciler instanceof Cleaner || dependents.requiresCleanup(); } @SuppressWarnings("rawtypes") diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index 305ece4999..b5b72aceb2 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -30,6 +30,7 @@ public class DependentResourceManager

private final Reconciler

reconciler; private final ControllerConfiguration

controllerConfiguration; private List dependents; + private boolean requiresCleanup; public DependentResourceManager(Controller

controller) { this.reconciler = controller.getReconciler(); @@ -52,6 +53,8 @@ public List prepareEventSources(EventSourceContext

context) { return dependentResource; }) .collect(Collectors.toList()); + // required cleanup inited here, so it has to be done only once + initRequiresCleanup(); return sources; } @@ -65,12 +68,14 @@ public UpdateControl

reconcile(P resource, Context

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

context) { initContextIfNeeded(resource, context); - dependents.forEach(dependent -> { + // cleanup in reverse order + for (int i = dependents.size() - 1; i >= 0; i--) { + var dependent = dependents.get(i); if (dependent instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) { ((io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner

) dependent) .cleanup(resource, context); } - }); + } return DeleteControl.defaultDelete(); } @@ -107,4 +112,15 @@ private DependentResource createAndConfigureFrom(DependentResourceSpec dependent public List getDependents() { return dependents; } + + private void initRequiresCleanup() { + requiresCleanup = getDependents().stream() + .filter(dr -> dr instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) + .findAny().isPresent(); + } + + public boolean requiresCleanup() { + return requiresCleanup; + } + } From bb1b1359f6b3eccad28843ca097f4b0c9914a836 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 17 Mar 2022 10:50:02 +0100 Subject: [PATCH 15/27] fix: mysql using the current approach without finalizer --- .../operator/processing/Controller.java | 3 +- .../dependent/SchemaDependentResource.java | 9 ++--- .../sample/MySQLSchemaOperatorE2E.java | 34 +++++++++++-------- 3 files changed, 25 insertions(+), 21 deletions(-) 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 309c511511..3586ae8d8e 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 @@ -88,8 +88,6 @@ public DeleteControl execute() { @Override public UpdateControl

reconcile(P resource, Context

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

result) { @Override public UpdateControl

execute() throws Exception { + dependents.reconcile(resource, context); return reconciler.reconcile(resource, context); } }); 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 e59f38c472..e737a14e0b 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,7 +11,6 @@ import io.fabric8.kubernetes.api.model.Secret; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; import io.javaoperatorsdk.operator.processing.dependent.Creator; @@ -28,8 +27,10 @@ public class SchemaDependentResource extends PerResourcePollingDependentResource implements EventSourceProvider, DependentResourceConfigurator, - Creator, - Cleaner { + Creator +// todo fix cleaner +// Cleaner +{ private static final Logger log = LoggerFactory.getLogger(SchemaDependentResource.class); @@ -69,7 +70,7 @@ private Connection getConnection() throws SQLException { return DriverManager.getConnection(connectURL, dbConfig.getUser(), dbConfig.getPassword()); } - @Override + // @Override public void cleanup(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/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java b/sample-operators/mysql-schema/src/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java index b8e8b0566a..cf4d4f7c9b 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 @@ -83,21 +83,7 @@ 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( @@ -130,4 +116,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; + } } From 49ef6c7aa7142e9082f4d2b441566fe80b1f9e98 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 17 Mar 2022 11:22:21 +0100 Subject: [PATCH 16/27] fix: reconciler cleaner IT --- .../operator/CleanerForReconcilerIT.java | 49 +++++++++++++++++++ .../CleanerForReconcilerCustomResource.java | 17 +++++++ ...anerForReconcilerCustomResourceStatus.java | 5 ++ .../CleanerForReconcilerTestReconciler.java | 39 +++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForReconcilerIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerTestReconciler.java 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/sample/cleanerforreconciler/CleanerForReconcilerCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResource.java new file mode 100644 index 0000000000..400ff74b90 --- /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/CleanerForReconcilerCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java new file mode 100644 index 0000000000..ef52cc26da --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java @@ -0,0 +1,5 @@ +package io.javaoperatorsdk.operator.sample.cleanerforreconciler; + +public class CleanerForReconcilerCustomResourceStatus { + +} 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(); + } +} From e41bf14177ee4b3219ebd8b3d6670cc9babf4587 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 17 Mar 2022 13:52:03 +0100 Subject: [PATCH 17/27] fix: managed dependent resource IT --- .../CruKubernetesDependentResource.java | 16 ++++++ ...nerForManagedDependentResourcesOnlyIT.java | 54 +++++++++++++++++++ ...anerForManagedDependentCustomResource.java | 17 ++++++ ...rManagedDependentCustomResourceStatus.java | 5 ++ ...anerForManagedDependentTestReconciler.java | 28 ++++++++++ .../ConfigMapDependentResource.java | 40 ++++++++++++++ .../sample/MySQLSchemaReconciler.java | 1 - .../WebPageReconcilerDependentResources.java | 3 +- 8 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CruKubernetesDependentResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResource.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentTestReconciler.java create mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java 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..8f26fe4aa5 --- /dev/null +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CruKubernetesDependentResource.java @@ -0,0 +1,16 @@ +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, Update and Delete + * + * @param Managed resource + * @param

Primary Resource + */ +public abstract class CruKubernetesDependentResource + extends + KubernetesDependentResource implements Creator, Updater { +} diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.java new file mode 100644 index 0000000000..dfd66b7ed1 --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.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 CleanerForManagedDependentResourcesOnlyIT { + + 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/sample/cleanermanageddependent/CleanerForManagedDependentCustomResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResource.java new file mode 100644 index 0000000000..a4e19a42ec --- /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/CleanerForManagedDependentCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java new file mode 100644 index 0000000000..18c711a44a --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java @@ -0,0 +1,5 @@ +package io.javaoperatorsdk.operator.sample.cleanermanageddependent; + +public class CleanerForManagedDependentCustomResourceStatus { + +} 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..bed4599cab --- /dev/null +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java @@ -0,0 +1,40 @@ +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); + + @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 cleanup(CleanerForManagedDependentCustomResource primary, + Context context) { + super.cleanup(primary, context); + numberOfCleanupExecutions.incrementAndGet(); + } + + public static int getNumberOfCleanupExecutions() { + return numberOfCleanupExecutions.get(); + } +} 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 50f367ef39..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 @@ -12,7 +12,6 @@ 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( dependents = { @Dependent(type = SecretDependentResource.class), 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 78c9aeaa11..9abeb10bfd 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 @@ -10,6 +10,7 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.api.reconciler.Context; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CruKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CrudKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; @@ -160,7 +161,7 @@ public static String serviceName(WebPage webPage) { } private class ConfigMapDependentResource - extends CrudKubernetesDependentResource + extends CruKubernetesDependentResource implements PrimaryToSecondaryMapper { From 1443d1d80bf0e1a9ba9bdc4e7aad752deedd4d0a Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 17 Mar 2022 14:27:29 +0100 Subject: [PATCH 18/27] fix: additional unit tests --- .../operator/processing/Controller.java | 11 ++++- .../operator/processing/ControllerTest.java | 46 ++++++++++++++----- 2 files changed, 45 insertions(+), 12 deletions(-) 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 3586ae8d8e..47d3ffb462 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 @@ -45,11 +45,20 @@ public Controller(Reconciler

reconciler, this.reconciler = reconciler; this.configuration = configuration; this.kubernetesClient = kubernetesClient; - eventSourceManager = new EventSourceManager<>(this); dependents = new DependentResourceManager<>(this); } + Controller(Reconciler

reconciler, ControllerConfiguration

configuration, + KubernetesClient kubernetesClient, + DependentResourceManager

dependents) { + this.reconciler = reconciler; + this.configuration = configuration; + this.kubernetesClient = kubernetesClient; + this.dependents = dependents; + eventSourceManager = new EventSourceManager<>(this); + } + @Override public DeleteControl cleanup(P resource, Context

context) { try { 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..db3a75437c 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,25 @@ 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.processing.dependent.DependentResourceManager; 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 +36,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 +52,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 +60,30 @@ 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(); + } + + @Test + void usesFinalizerIfReconcilerContainsDependentsWithCleanerImpl() { + Reconciler reconciler = mock(Reconciler.class); + var dependentResourceManager = mock(DependentResourceManager.class); + when(dependentResourceManager.requiresCleanup()).thenReturn(true); + when(configuration.getResourceClass()).thenReturn(TestCustomResource.class); + + final var controller = new Controller(reconciler, + configuration, MockKubernetesClient.client(TestCustomResource.class), + dependentResourceManager); + + assertThat(controller.useFinalizer()).isTrue(); + } + } From cf5c716c9ed3f28f21e1a6fe2d3e0b87be1d604e Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Thu, 17 Mar 2022 14:52:17 +0100 Subject: [PATCH 19/27] refactor: simplify --- .../dependent/DependentResourceManager.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index b5b72aceb2..ecb0f5eb77 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -12,7 +12,15 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.config.ControllerConfiguration; import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec; -import io.javaoperatorsdk.operator.api.reconciler.*; +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; +import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; +import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer; +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.DependentResource; import io.javaoperatorsdk.operator.api.reconciler.dependent.EventSourceProvider; import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; @@ -115,8 +123,7 @@ public List getDependents() { private void initRequiresCleanup() { requiresCleanup = getDependents().stream() - .filter(dr -> dr instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) - .findAny().isPresent(); + .anyMatch(dr -> dr instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner); } public boolean requiresCleanup() { From 2563bae4ebb13c128c4642ea4fa099d489161545 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Thu, 17 Mar 2022 15:05:40 +0100 Subject: [PATCH 20/27] refactor: avoid looping over dependents twice to check for Cleaner --- .../dependent/DependentResourceManager.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index ecb0f5eb77..d2f9fcbd5c 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -49,6 +49,7 @@ public DependentResourceManager(Controller

controller) { public List prepareEventSources(EventSourceContext

context) { final var dependentResources = controllerConfiguration.getDependentResources(); final var sources = new ArrayList(dependentResources.size()); + final boolean[] requiresCleanupHolder = new boolean[] {false}; dependents = dependentResources.stream() .map( @@ -58,11 +59,13 @@ public List prepareEventSources(EventSourceContext

context) { EventSourceProvider provider = (EventSourceProvider) dependentResource; sources.add(provider.initEventSource(context)); } + if (dependentResource instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) { + requiresCleanupHolder[0] = true; + } return dependentResource; }) .collect(Collectors.toList()); - // required cleanup inited here, so it has to be done only once - initRequiresCleanup(); + requiresCleanup = requiresCleanupHolder[0]; return sources; } @@ -121,11 +124,6 @@ public List getDependents() { return dependents; } - private void initRequiresCleanup() { - requiresCleanup = getDependents().stream() - .anyMatch(dr -> dr instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner); - } - public boolean requiresCleanup() { return requiresCleanup; } From 3a68a0957e609861e851167ca2e612cfa096bb0b Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 17 Mar 2022 16:20:51 +0100 Subject: [PATCH 21/27] fix: class rename --- ...ource.java => CRUDKubernetesDependentResource.java} | 4 ++-- ...source.java => CRUKubernetesDependentResource.java} | 4 ++-- .../ConfigMapDependentResource.java | 4 ++-- .../sample/dependent/SchemaDependentResource.java | 7 +++---- .../operator/sample/MySQLSchemaOperatorE2E.java | 9 ++++++++- .../sample/WebPageReconcilerDependentResources.java | 10 +++++----- 6 files changed, 22 insertions(+), 16 deletions(-) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/{CrudKubernetesDependentResource.java => CRUDKubernetesDependentResource.java} (86%) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/{CruKubernetesDependentResource.java => CRUKubernetesDependentResource.java} (85%) 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 86% 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 75cabce6a4..8ad08c4a12 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 @@ -6,12 +6,12 @@ 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 +public abstract class CRUDKubernetesDependentResource extends KubernetesDependentResource implements Creator, Updater, Cleaner

{ } 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 similarity index 85% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CruKubernetesDependentResource.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUKubernetesDependentResource.java index 8f26fe4aa5..ff0052995f 100644 --- 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 @@ -5,12 +5,12 @@ 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. * * @param Managed resource * @param

Primary Resource */ -public abstract class CruKubernetesDependentResource +public abstract class CRUKubernetesDependentResource extends KubernetesDependentResource implements Creator, Updater { } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java index bed4599cab..31c63666c8 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java @@ -6,10 +6,10 @@ import io.fabric8.kubernetes.api.model.ConfigMap; import io.fabric8.kubernetes.api.model.ObjectMeta; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CrudKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; public class ConfigMapDependentResource extends - CrudKubernetesDependentResource { + CRUDKubernetesDependentResource { private static final AtomicInteger numberOfCleanupExecutions = new AtomicInteger(0); 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 e737a14e0b..3d9e1db0eb 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 @@ -6,6 +6,7 @@ import java.util.Base64; import java.util.Optional; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,9 +28,7 @@ public class SchemaDependentResource extends PerResourcePollingDependentResource implements EventSourceProvider, DependentResourceConfigurator, - Creator -// todo fix cleaner -// Cleaner + Creator, Cleaner { private static final Logger log = LoggerFactory.getLogger(SchemaDependentResource.class); @@ -70,7 +69,7 @@ private Connection getConnection() throws SQLException { return DriverManager.getConnection(connectURL, dbConfig.getUser(), dbConfig.getPassword()); } - // @Override + @Override public void cleanup(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/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java b/sample-operators/mysql-schema/src/test/java/io/javaoperatorsdk/operator/sample/MySQLSchemaOperatorE2E.java index cf4d4f7c9b..15d4e64efe 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 @@ -3,6 +3,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -39,6 +40,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( @@ -87,7 +89,7 @@ void test() throws IOException { 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"); @@ -112,6 +114,11 @@ void test() throws IOException { assertThat(updatedSchema.getStatus().getUserName(), is(notNullValue())); }); + operator.delete(MySQLSchema.class, testSchema); + + await().atMost(Duration.ofSeconds(45)).until(() -> + operator.get(MySQLSchema.class, TEST_RESOURCE_NAME) == null); + if (portForward != null) { portForward.close(); } 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 9abeb10bfd..19f1f80065 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 @@ -10,8 +10,8 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CruKubernetesDependentResource; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CrudKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -88,7 +88,7 @@ private void createDependentResources(KubernetesClient client) { .setLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR)); this.deploymentDR = - new CrudKubernetesDependentResource<>() { + new CRUDKubernetesDependentResource<>() { @Override protected Deployment desired(WebPage webPage, Context context) { @@ -125,7 +125,7 @@ protected Class resourceType() { .setLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR)); this.serviceDR = - new CrudKubernetesDependentResource<>() { + new CRUDKubernetesDependentResource<>() { @Override protected Service desired(WebPage webPage, Context context) { @@ -161,7 +161,7 @@ public static String serviceName(WebPage webPage) { } private class ConfigMapDependentResource - extends CruKubernetesDependentResource + extends CRUKubernetesDependentResource implements PrimaryToSecondaryMapper { From 6935c2e9f737daecbff871dac4e647e1bb77f274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Fri, 18 Mar 2022 08:35:32 +0100 Subject: [PATCH 22/27] Update operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CruKubernetesDependentResource.java Co-authored-by: Chris Laprun --- .../dependent/kubernetes/CruKubernetesDependentResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 8f26fe4aa5..11a7c3e8ae 100644 --- 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 @@ -5,7 +5,7 @@ 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 and Update * * @param Managed resource * @param

Primary Resource From 46168389628a577a06b90fbca372703455858086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Fri, 18 Mar 2022 08:47:39 +0100 Subject: [PATCH 23/27] Update operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/controller/ResourceEventFilter.java Co-authored-by: Chris Laprun --- .../processing/event/source/controller/ResourceEventFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 087a460c8b..85297931a2 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 @@ -17,7 +17,7 @@ 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 controller 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} From 09c20f92effc047f240a53bba9099cbe5309d75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20M=C3=A9sz=C3=A1ros?= Date: Fri, 18 Mar 2022 08:49:28 +0100 Subject: [PATCH 24/27] Update operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sébastien CROCQUESEL <88554524+scrocquesel@users.noreply.github.com> --- .../operator/processing/event/ReconciliationDispatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2e244b9a67..25953ad0bd 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 @@ -76,7 +76,7 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) } private boolean shouldNotDispatchToCleanup(R resource) { - // we don't dispatch to delete if the controller is configured to use a finalizer but that + // 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 !controller.useFinalizer() || (controller.useFinalizer() && !resource.hasFinalizer(configuration().getFinalizerName())); From a024bc32ea24a0e29aad9321f36e4835bc04b890 Mon Sep 17 00:00:00 2001 From: csviri Date: Fri, 18 Mar 2022 09:11:49 +0100 Subject: [PATCH 25/27] fix: fixes from CR --- .../reconciler/ControllerConfiguration.java | 5 +++- .../dependent/{Cleaner.java => Deleter.java} | 4 +-- .../dependent/DependentResourceManager.java | 9 ++++--- .../AbstractSimpleDependentResource.java | 2 +- .../CRUDKubernetesDependentResource.java | 4 +-- .../KubernetesDependentResource.java | 2 +- .../event/ReconciliationDispatcher.java | 2 +- .../controller/ResourceEventFilter.java | 12 ++++----- .../AbstractSimpleDependentResourceTest.java | 6 ++--- ...erForManagedDependentResourcesOnlyIT.java} | 2 +- .../ConfigMapDependentResource.java | 6 ++--- .../dependent/SchemaDependentResource.java | 9 ++++--- .../sample/MySQLSchemaOperatorE2E.java | 9 ++----- .../WebPageReconcilerDependentResources.java | 2 +- .../sample/CustomServiceReconciler.java | 27 +++++++++---------- 15 files changed, 49 insertions(+), 52 deletions(-) rename operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/{Cleaner.java => Deleter.java} (78%) rename operator-framework/src/test/java/io/javaoperatorsdk/operator/{CleanerForManagedDependentResourcesOnlyIT.java => DeleterForManagedDependentResourcesOnlyIT.java} (97%) 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 c1b9aea7a7..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,7 +15,10 @@ String name() default Constants.EMPTY_STRING; /** - * Optional finalizer name, if it is not provided, one will be automatically generated. + * 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/dependent/Cleaner.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java similarity index 78% rename from operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java rename to operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java index 734859a874..f6bd2682ca 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Cleaner.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/Deleter.java @@ -10,6 +10,6 @@ * @param

primary resource type */ @FunctionalInterface -public interface Cleaner

{ - void cleanup(P primary, Context

context); +public interface Deleter

{ + void delete(P primary, Context

context); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java index d2f9fcbd5c..10aea26785 100644 --- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java +++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/DependentResourceManager.java @@ -21,6 +21,7 @@ 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.EventSourceProvider; import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator; @@ -59,7 +60,7 @@ public List prepareEventSources(EventSourceContext

context) { EventSourceProvider provider = (EventSourceProvider) dependentResource; sources.add(provider.initEventSource(context)); } - if (dependentResource instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) { + if (dependentResource instanceof Deleter) { requiresCleanupHolder[0] = true; } return dependentResource; @@ -82,9 +83,9 @@ public DeleteControl cleanup(P resource, Context

context) { // cleanup in reverse order for (int i = dependents.size() - 1; i >= 0; i--) { var dependent = dependents.get(i); - if (dependent instanceof io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner) { - ((io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner

) dependent) - .cleanup(resource, context); + if (dependent instanceof Deleter) { + ((Deleter

) dependent) + .delete(resource, context); } } return DeleteControl.defaultDelete(); 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 79f1a420fb..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 @@ -51,7 +51,7 @@ public ReconcileResult reconcile(P primary, Context

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

context) { + public final void delete(P primary, Context

context) { deleteResource(primary, context); cache.remove(ResourceID.fromResource(primary)); } diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/CRUDKubernetesDependentResource.java index 8ad08c4a12..77969866dc 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,7 +1,7 @@ package io.javaoperatorsdk.operator.processing.dependent.kubernetes; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.Updater; @@ -13,5 +13,5 @@ */ public abstract class CRUDKubernetesDependentResource extends - KubernetesDependentResource implements Creator, Updater, Cleaner

{ + KubernetesDependentResource implements Creator, Updater, Deleter

{ } 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 b6c2d86fab..f26dbfe2b3 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 @@ -102,7 +102,7 @@ public Result match(R actualResource, P primary, Context

context) { return matcher.match(actualResource, primary, context); } - public void cleanup(P primary, Context

context) { + public void delete(P primary, Context

context) { if (!addOwnerReference) { var resource = getResource(primary); resource.ifPresent(r -> client.resource(r).delete()); 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 2e244b9a67..3e04fee700 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 @@ -61,7 +61,7 @@ private PostExecutionControl handleDispatch(ExecutionScope executionScope) final var markedForDeletion = resource.isMarkedForDeletion(); 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(); 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 087a460c8b..e75b2514d7 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 @@ -34,9 +34,9 @@ public interface ResourceEventFilter

{ */ default ResourceEventFilter

and(ResourceEventFilter

other) { return other == null ? this - : (Controller

configuration, P oldResource, P 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); }; } @@ -50,9 +50,9 @@ default ResourceEventFilter

and(ResourceEventFilter

other) { */ default ResourceEventFilter

or(ResourceEventFilter

other) { return other == null ? this - : (Controller

configuration, P oldResource, P 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/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 9fa4e68963..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,7 +9,7 @@ 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.Cleaner; +import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter; import io.javaoperatorsdk.operator.processing.dependent.Creator; import io.javaoperatorsdk.operator.processing.dependent.Updater; import io.javaoperatorsdk.operator.processing.event.ResourceID; @@ -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()); } @@ -92,7 +92,7 @@ private static class SimpleDependentResource extends AbstractSimpleDependentResource implements Creator, Updater, - Cleaner { + Deleter { private final Supplier supplier; diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/DeleterForManagedDependentResourcesOnlyIT.java similarity index 97% rename from operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.java rename to operator-framework/src/test/java/io/javaoperatorsdk/operator/DeleterForManagedDependentResourcesOnlyIT.java index dfd66b7ed1..94c7c7798d 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/CleanerForManagedDependentResourcesOnlyIT.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/DeleterForManagedDependentResourcesOnlyIT.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -class CleanerForManagedDependentResourcesOnlyIT { +class DeleterForManagedDependentResourcesOnlyIT { public static final String TEST_RESOURCE_NAME = "cleaner-for-reconciler-test1"; diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java index 31c63666c8..dc5ad0ee07 100644 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java +++ b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/ConfigMapDependentResource.java @@ -9,7 +9,7 @@ import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; public class ConfigMapDependentResource extends - CRUDKubernetesDependentResource { + CRUDKubernetesDependentResource { private static final AtomicInteger numberOfCleanupExecutions = new AtomicInteger(0); @@ -28,9 +28,9 @@ protected ConfigMap desired(CleanerForManagedDependentCustomResource primary, } @Override - public void cleanup(CleanerForManagedDependentCustomResource primary, + public void delete(CleanerForManagedDependentCustomResource primary, Context context) { - super.cleanup(primary, context); + super.delete(primary, context); numberOfCleanupExecutions.incrementAndGet(); } 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 3d9e1db0eb..0f8199ba84 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 @@ -6,7 +6,6 @@ import java.util.Base64; import java.util.Optional; -import io.javaoperatorsdk.operator.api.reconciler.dependent.Cleaner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +27,9 @@ public class SchemaDependentResource extends PerResourcePollingDependentResource implements EventSourceProvider, DependentResourceConfigurator, - Creator, Cleaner + Creator +// todo fix +// , Deleter { private static final Logger log = LoggerFactory.getLogger(SchemaDependentResource.class); @@ -69,8 +70,8 @@ private Connection getConnection() throws SQLException { return DriverManager.getConnection(connectURL, dbConfig.getUser(), dbConfig.getPassword()); } - @Override - public void cleanup(MySQLSchema primary, Context context) { + // @Override + public void delete(MySQLSchema primary, Context context) { try (Connection connection = getConnection()) { var userName = primary.getStatus() != null ? primary.getStatus().getUserName() : null; SchemaService.deleteSchemaAndRelatedUser(connection, primary.getMetadata().getName(), 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 15d4e64efe..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 @@ -3,7 +3,6 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -89,7 +88,8 @@ void test() throws IOException { MySQLSchema testSchema = new MySQLSchema(); testSchema.setMetadata( - new ObjectMetaBuilder().withName(TEST_RESOURCE_NAME).withNamespace(operator.getNamespace()).build()); + new ObjectMetaBuilder().withName(TEST_RESOURCE_NAME).withNamespace(operator.getNamespace()) + .build()); testSchema.setSpec(new SchemaSpec()); testSchema.getSpec().setEncoding("utf8"); @@ -114,11 +114,6 @@ void test() throws IOException { assertThat(updatedSchema.getStatus().getUserName(), is(notNullValue())); }); - operator.delete(MySQLSchema.class, testSchema); - - await().atMost(Duration.ofSeconds(45)).until(() -> - operator.get(MySQLSchema.class, TEST_RESOURCE_NAME) == null); - if (portForward != null) { portForward.close(); } 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 19f1f80065..6c345c856c 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 @@ -10,8 +10,8 @@ import io.fabric8.kubernetes.client.KubernetesClient; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource; +import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource; import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig; import io.javaoperatorsdk.operator.processing.event.ResourceID; 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 6320e85f99..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 @@ -15,7 +15,7 @@ /** A very simple sample controller that creates a service with a label. */ @ControllerConfiguration -public class CustomServiceReconciler implements Reconciler, Cleaner { +public class CustomServiceReconciler implements Reconciler { private static final Logger log = LoggerFactory.getLogger(CustomServiceReconciler.class); @@ -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 DeleteControl.defaultDelete(); - } - @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); } } From de52b3c609ae5128f3d7e13dace89e724895c7e2 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 18 Mar 2022 18:39:21 +0100 Subject: [PATCH 26/27] refactor: minor optimizations --- .../operator/processing/Controller.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) 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 fcdce3b9fa..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,7 +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.*; +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; @@ -52,6 +52,8 @@ public class Controller

implements Reconciler

, Cleaner 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, @@ -63,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") @@ -115,12 +127,13 @@ public String successTypeName(DeleteControl deleteControl) { @Override public DeleteControl execute() { - dependents.forEach(d -> { - if (d instanceof Deleter) { - ((Deleter

) d).delete(resource, context); - } - }); - if (reconciler instanceof Cleaner) { + 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(); @@ -314,11 +327,7 @@ public void stop() { } public boolean useFinalizer() { - return reconciler instanceof Cleaner || dependentsRequireCleanup(); - } - - private boolean dependentsRequireCleanup() { - return dependents.stream().anyMatch(d -> d instanceof Deleter); + return isCleaner || hasDeleterDependents; } @SuppressWarnings("rawtypes") From 606480e34c51cec9e9e748dd496f933c603c9547 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 18 Mar 2022 18:47:34 +0100 Subject: [PATCH 27/27] refactor: remove unneeded classes --- .../CleanerForReconcilerCustomResource.java | 2 +- .../CleanerForReconcilerCustomResourceStatus.java | 5 ----- .../CleanerForManagedDependentCustomResource.java | 2 +- .../CleanerForManagedDependentCustomResourceStatus.java | 5 ----- 4 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java delete mode 100644 operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java 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 index 400ff74b90..7a4b255d28 100644 --- 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 @@ -12,6 +12,6 @@ @Kind("CleanerForReconcilerCustomResource") @ShortNames("cfr") public class CleanerForReconcilerCustomResource - extends CustomResource + extends CustomResource implements Namespaced { } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java deleted file mode 100644 index ef52cc26da..0000000000 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanerforreconciler/CleanerForReconcilerCustomResourceStatus.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.javaoperatorsdk.operator.sample.cleanerforreconciler; - -public class CleanerForReconcilerCustomResourceStatus { - -} 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 index a4e19a42ec..9e18e657aa 100644 --- 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 @@ -12,6 +12,6 @@ @Kind("CleanerForReconcilerCustomResource") @ShortNames("cfr") public class CleanerForManagedDependentCustomResource - extends CustomResource + extends CustomResource implements Namespaced { } diff --git a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java b/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java deleted file mode 100644 index 18c711a44a..0000000000 --- a/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/cleanermanageddependent/CleanerForManagedDependentCustomResourceStatus.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.javaoperatorsdk.operator.sample.cleanermanageddependent; - -public class CleanerForManagedDependentCustomResourceStatus { - -}