Skip to content

Separate interface for cleanup part of reconciler and Dependent Resources #1035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Mar 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c01b7d7
feat: separate cleaner interface from reconciler
csviri Mar 14, 2022
9dcfe42
fix: builds without tests
csviri Mar 15, 2022
21cc194
wip
csviri Mar 15, 2022
ff1aa95
fix: unit tests
csviri Mar 15, 2022
14ec0d7
fix: integration tests
csviri Mar 15, 2022
94b68da
fix: integration tests
csviri Mar 15, 2022
6c33fa5
fix: format
csviri Mar 15, 2022
8416246
fix: added integration test
csviri Mar 15, 2022
396b5a1
docs: update docs
csviri Mar 15, 2022
4831df7
fix: format
csviri Mar 16, 2022
7360e66
fix: rename
csviri Mar 16, 2022
aa1a2b6
feat: separate cleaner interface for DependetResource
csviri Mar 16, 2022
6f5dfb8
refactor: dependent resources package structure
csviri Mar 16, 2022
b12f728
fix: use finalizer if dependent resources are cleaners
csviri Mar 16, 2022
bb1b135
fix: mysql using the current approach without finalizer
csviri Mar 17, 2022
49ef6c7
fix: reconciler cleaner IT
csviri Mar 17, 2022
e41bf14
fix: managed dependent resource IT
csviri Mar 17, 2022
1443d1d
fix: additional unit tests
csviri Mar 17, 2022
cf5c716
refactor: simplify
metacosm Mar 17, 2022
2563bae
refactor: avoid looping over dependents twice to check for Cleaner
metacosm Mar 17, 2022
3a68a09
fix: class rename
csviri Mar 17, 2022
da8424b
Merge branch 'separate-cleanup' of github.com:java-operator-sdk/java-…
csviri Mar 17, 2022
ae75dcf
Merge branch 'separate-cleanup' of github.com:java-operator-sdk/java-…
csviri Mar 18, 2022
6935c2e
Update operator-framework-core/src/main/java/io/javaoperatorsdk/opera…
csviri Mar 18, 2022
4616838
Update operator-framework-core/src/main/java/io/javaoperatorsdk/opera…
csviri Mar 18, 2022
09c20f9
Update operator-framework-core/src/main/java/io/javaoperatorsdk/opera…
csviri Mar 18, 2022
a024bc3
fix: fixes from CR
csviri Mar 18, 2022
e3dd811
Merge branch 'separate-cleanup' of github.com:java-operator-sdk/java-…
csviri Mar 18, 2022
6024cd0
Merge branch 'next' into separate-cleanup
csviri Mar 18, 2022
de52b3c
refactor: minor optimizations
metacosm Mar 18, 2022
606480e
refactor: remove unneeded classes
metacosm Mar 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions docs/documentation/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<P>`](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.
Expand All @@ -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.

Expand All @@ -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
Expand All @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<? extends HasMetadata> resourceClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -18,7 +17,7 @@ default String getName() {
return ReconcilerUtils.getDefaultReconcilerName(getAssociatedReconcilerClassName());
}

default String getFinalizer() {
default String getFinalizerName() {
return ReconcilerUtils.getDefaultFinalizerName(getResourceClass());
}

Expand All @@ -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}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class ControllerConfigurationOverrider<R extends HasMetadata> {
private final List<DependentResourceSpec<?, ?>> dependentResourceSpecs;

private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
finalizer = original.getFinalizer();
finalizer = original.getFinalizerName();
generationAware = original.isGenerationAware();
namespaces = new HashSet<>(original.getNamespaces());
retry = original.getRetryConfiguration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public String getResourceTypeName() {
}

@Override
public String getFinalizer() {
public String getFinalizerName() {
return finalizer;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.javaoperatorsdk.operator.api.reconciler;

import io.fabric8.kubernetes.api.model.HasMetadata;

public interface Cleaner<P extends HasMetadata> {

/**
* 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.
*
* <p>
* 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<P> context);

}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<P extends HasMetadata> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
String name() default Constants.EMPTY_STRING;

/**
* Optional finalizer name, if it is not provided, one will be automatically generated. If the
* provided value is the value specified by {@link Constants#NO_FINALIZER}, then no finalizer will
* be added to custom resources.
* Optional finalizer name, if it is not provided, one will be automatically generated. Note that
* finalizers are only added when Reconciler implement {@link Cleaner} interface, or at least one
* managed dependent resource implement
* {@link io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter} interface.
*
* @return the finalizer name
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<P extends HasMetadata> implements Context<P> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,4 @@ public interface Reconciler<R extends HasMetadata> {
*/
UpdateControl<R> reconcile(R resource, Context<R> 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.
*
* <p>
* 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<R> context) {
return DeleteControl.defaultDelete();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 <P> primary resource type
*/
@FunctionalInterface
public interface Deleter<P extends HasMetadata> {
void delete(P primary, Context<P> context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@
public interface DependentResource<R, P extends HasMetadata> {
ReconcileResult<R> reconcile(P primary, Context<P> context);

default void cleanup(P primary, Context<P> context) {}

Optional<R> getResource(P primaryResource);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

public class ReconcileResult<R> {

private R resource;
private Operation operation;
private final R resource;
private final Operation operation;

public static <T> ReconcileResult<T> resourceCreated(T resource) {
return new ReconcileResult<>(resource, Operation.CREATED);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.javaoperatorsdk.operator.api.reconciler.dependent;
package io.javaoperatorsdk.operator.api.reconciler.dependent.managed;

public interface DependentResourceConfigurator<C> {
void configureWith(C config);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand Down
Loading