Skip to content

Commit f4b6b7f

Browse files
csviriiocaneldependabot[bot]metacosmlburgazzoli
committed
Reschedule delete (#600)
* chore: renaming vars named k8sClient to kubernetsClient * chore(deps): bump jandex-maven-plugin from 1.1.1 to 1.2.1 (#592) Bumps [jandex-maven-plugin](https://github.com/wildfly/jandex-maven-plugin) from 1.1.1 to 1.2.1. - [Release notes](https://github.com/wildfly/jandex-maven-plugin/releases) - [Commits](wildfly/jandex-maven-plugin@1.1.1...1.2.1) --- updated-dependencies: - dependency-name: org.jboss.jandex:jandex-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump mockito-core from 3.12.4 to 4.0.0 (#591) Bumps [mockito-core](https://github.com/mockito/mockito) from 3.12.4 to 4.0.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](mockito/mockito@v3.12.4...v4.0.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feature: Build PR on v2 * chore(ci): use Java 17 * chore(ci): use only Temurin distribution * chore: add generics to PostExecutionControl to reduce IDEs noise (#594) * chore: polish the junit5 extension (#593) * feat: Use informers as CustomResourceEventSource backbone and cache This is a major change and backbone of v2. We change also how the Resources are addressed both internally and from event source with CustomResourceID. Additional improvements also added. * feat: delete reschedule * fix: naming after review Co-authored-by: Ioannis Canellos <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Chris Laprun <[email protected]> Co-authored-by: Luca Burgazzoli <[email protected]>
1 parent 6a3503a commit f4b6b7f

File tree

14 files changed

+109
-50
lines changed

14 files changed

+109
-50
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.javaoperatorsdk.operator.api;
2+
3+
import java.util.Optional;
4+
import java.util.concurrent.TimeUnit;
5+
6+
public abstract class BaseControl<T extends BaseControl> {
7+
8+
private Long scheduleDelay = null;
9+
10+
public T rescheduleAfter(long delay) {
11+
this.scheduleDelay = delay;
12+
return (T) this;
13+
}
14+
15+
public T rescheduleAfter(long delay, TimeUnit timeUnit) {
16+
return rescheduleAfter(timeUnit.toMillis(delay));
17+
}
18+
19+
public Optional<Long> getScheduleDelay() {
20+
return Optional.ofNullable(scheduleDelay);
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
package io.javaoperatorsdk.operator.api;
22

3-
public enum DeleteControl {
4-
DEFAULT_DELETE, NO_FINALIZER_REMOVAL
3+
public class DeleteControl extends BaseControl<DeleteControl> {
4+
5+
private final boolean removeFinalizer;
6+
7+
private DeleteControl(boolean removeFinalizer) {
8+
this.removeFinalizer = removeFinalizer;
9+
}
10+
11+
public static DeleteControl defaultDelete() {
12+
return new DeleteControl(true);
13+
}
14+
15+
public static DeleteControl noFinalizerRemoval() {
16+
return new DeleteControl(false);
17+
}
18+
19+
public boolean isRemoveFinalizer() {
20+
return removeFinalizer;
21+
}
22+
23+
@Override
24+
public DeleteControl rescheduleAfter(long delay) {
25+
if (removeFinalizer == true) {
26+
throw new IllegalStateException("Cannot reschedule deleteResource if removing finalizer");
27+
}
28+
return super.rescheduleAfter(delay);
29+
}
530
}

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/ResourceController.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public interface ResourceController<R extends CustomResource> {
99
* The implementation should delete the associated component(s). Note that this is method is
1010
* called when an object is marked for deletion. After it's executed the custom resource finalizer
1111
* is automatically removed by the framework; unless the return value is
12-
* {@link DeleteControl#NO_FINALIZER_REMOVAL}, which indicates that the controller has determined
12+
* {@link DeleteControl#noFinalizerRemoval()}, which indicates that the controller has determined
1313
* that the resource should not be deleted yet, in which case it is up to the controller to
1414
* restore the resource's status so that it's not marked for deletion anymore.
1515
*
@@ -21,13 +21,13 @@ public interface ResourceController<R extends CustomResource> {
2121
*
2222
* @param resource the resource that is marked for deletion
2323
* @param context the context with which the operation is executed
24-
* @return {@link DeleteControl#DEFAULT_DELETE} - so the finalizer is automatically removed after
25-
* the call. {@link DeleteControl#NO_FINALIZER_REMOVAL} if you don't want to remove the
24+
* @return {@link DeleteControl#defaultDelete()} - so the finalizer is automatically removed after
25+
* the call. {@link DeleteControl#noFinalizerRemoval()} if you don't want to remove the
2626
* finalizer to indicate that the resource should not be deleted after all, in which case
2727
* the controller should restore the resource's state appropriately.
2828
*/
2929
default DeleteControl deleteResource(R resource, Context<R> context) {
30-
return DeleteControl.DEFAULT_DELETE;
30+
return DeleteControl.defaultDelete();
3131
}
3232

3333
/**

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/UpdateControl.java

+1-18
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
package io.javaoperatorsdk.operator.api;
22

3-
import java.util.Optional;
4-
import java.util.concurrent.TimeUnit;
5-
63
import io.fabric8.kubernetes.client.CustomResource;
74

8-
public class UpdateControl<T extends CustomResource> {
5+
public class UpdateControl<T extends CustomResource> extends BaseControl<UpdateControl<T>> {
96

107
private final T customResource;
118
private final boolean updateStatusSubResource;
129
private final boolean updateCustomResource;
13-
private Long reScheduleDelay = null;
1410

1511
private UpdateControl(
1612
T customResource, boolean updateStatusSubResource, boolean updateCustomResource) {
@@ -47,19 +43,6 @@ public static <T extends CustomResource> UpdateControl<T> noUpdate() {
4743
return new UpdateControl<>(null, false, false);
4844
}
4945

50-
public UpdateControl<T> withReSchedule(long delay, TimeUnit timeUnit) {
51-
return withReSchedule(timeUnit.toMillis(delay));
52-
}
53-
54-
public UpdateControl<T> withReSchedule(long delay) {
55-
this.reScheduleDelay = delay;
56-
return this;
57-
}
58-
59-
public Optional<Long> getReScheduleDelay() {
60-
return Optional.ofNullable(reScheduleDelay);
61-
}
62-
6346
public T getCustomResource() {
6447
return customResource;
6548
}

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/ConfiguredController.java

+2-9
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,8 @@ public String controllerName() {
5252
}
5353

5454
@Override
55-
public String successTypeName(DeleteControl result) {
56-
switch (result) {
57-
case DEFAULT_DELETE:
58-
return "delete";
59-
case NO_FINALIZER_REMOVAL:
60-
return "finalizerNotRemoved";
61-
default:
62-
return "unknown";
63-
}
55+
public String successTypeName(DeleteControl deleteControl) {
56+
return deleteControl.isRemoveFinalizer() ? "delete" : "finalizerNotRemoved";
6457
}
6558

6659
@Override

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/EventDispatcher.java

+14-8
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88
import io.fabric8.kubernetes.client.KubernetesClientException;
99
import io.fabric8.kubernetes.client.dsl.MixedOperation;
1010
import io.fabric8.kubernetes.client.dsl.Resource;
11-
import io.javaoperatorsdk.operator.api.Context;
12-
import io.javaoperatorsdk.operator.api.DefaultContext;
13-
import io.javaoperatorsdk.operator.api.DeleteControl;
14-
import io.javaoperatorsdk.operator.api.ResourceController;
15-
import io.javaoperatorsdk.operator.api.UpdateControl;
11+
import io.javaoperatorsdk.operator.api.*;
1612
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
1713
import io.javaoperatorsdk.operator.processing.event.EventList;
1814

@@ -152,10 +148,16 @@ private PostExecutionControl<R> createPostExecutionControl(R updatedCustomResour
152148
} else {
153149
postExecutionControl = PostExecutionControl.defaultDispatch();
154150
}
155-
updateControl.getReScheduleDelay().ifPresent(postExecutionControl::withReSchedule);
151+
updatePostExecutionControlWithReschedule(postExecutionControl, updateControl);
156152
return postExecutionControl;
157153
}
158154

155+
private void updatePostExecutionControlWithReschedule(
156+
PostExecutionControl<R> postExecutionControl,
157+
BaseControl<?> baseControl) {
158+
baseControl.getScheduleDelay().ifPresent(postExecutionControl::withReSchedule);
159+
}
160+
159161
private PostExecutionControl<R> handleDelete(R resource, Context<R> context) {
160162
log.debug(
161163
"Executing delete for resource: {} with version: {}",
@@ -165,7 +167,9 @@ private PostExecutionControl<R> handleDelete(R resource, Context<R> context) {
165167
DeleteControl deleteControl = controller.deleteResource(resource, context);
166168
final var useFinalizer = configuration().useFinalizer();
167169
if (useFinalizer) {
168-
if (deleteControl == DeleteControl.DEFAULT_DELETE
170+
// note that we don't reschedule here even if instructed. Removing finalizer means that
171+
// cleanup is finished, nothing left to done
172+
if (deleteControl.isRemoveFinalizer()
169173
&& resource.hasFinalizer(configuration().getFinalizer())) {
170174
R customResource = removeFinalizer(resource);
171175
return PostExecutionControl.customResourceUpdated(customResource);
@@ -177,7 +181,9 @@ private PostExecutionControl<R> handleDelete(R resource, Context<R> context) {
177181
getVersion(resource),
178182
deleteControl,
179183
useFinalizer);
180-
return PostExecutionControl.defaultDispatch();
184+
PostExecutionControl<R> postExecutionControl = PostExecutionControl.defaultDispatch();
185+
updatePostExecutionControlWithReschedule(postExecutionControl, deleteControl);
186+
return postExecutionControl;
181187
}
182188

183189
private void updateCustomResourceWithFinalizer(R resource) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javaoperatorsdk.operator.api;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
6+
class DeleteControlTest {
7+
8+
@Test
9+
void cannotReScheduleForDefaultDelete() {
10+
Assertions.assertThrows(IllegalStateException.class, () -> {
11+
DeleteControl.defaultDelete().rescheduleAfter(1000L);
12+
});
13+
}
14+
15+
}

Diff for: operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/EventDispatcherTest.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void setup() {
6666
when(controller.createOrUpdateResource(eq(testCustomResource), any()))
6767
.thenReturn(UpdateControl.updateCustomResource(testCustomResource));
6868
when(controller.deleteResource(eq(testCustomResource), any()))
69-
.thenReturn(DeleteControl.DEFAULT_DELETE);
69+
.thenReturn(DeleteControl.defaultDelete());
7070
when(customResourceFacade.replaceWithLock(any())).thenReturn(null);
7171
}
7272

@@ -202,7 +202,7 @@ void doesNotRemovesTheSetFinalizerIfTheDeleteNotMethodInstructsIt() {
202202
testCustomResource.addFinalizer(DEFAULT_FINALIZER);
203203

204204
when(controller.deleteResource(eq(testCustomResource), any()))
205-
.thenReturn(DeleteControl.NO_FINALIZER_REMOVAL);
205+
.thenReturn(DeleteControl.noFinalizerRemoval());
206206
markForDeletion(testCustomResource);
207207

208208
eventDispatcher.handleExecution(
@@ -297,14 +297,29 @@ void setReScheduleToPostExecutionControlFromUpdateControl() {
297297

298298
when(controller.createOrUpdateResource(eq(testCustomResource), any()))
299299
.thenReturn(
300-
UpdateControl.updateStatusSubResource(testCustomResource).withReSchedule(1000L));
300+
UpdateControl.updateStatusSubResource(testCustomResource).rescheduleAfter(1000L));
301301

302302
PostExecutionControl control = eventDispatcher.handleExecution(
303303
executionScopeWithCREvent(ADDED, testCustomResource));
304304

305305
assertThat(control.getReScheduleDelay().get()).isEqualTo(1000L);
306306
}
307307

308+
@Test
309+
void reScheduleOnDeleteWithoutFinalizerRemoval() {
310+
testCustomResource.addFinalizer(DEFAULT_FINALIZER);
311+
markForDeletion(testCustomResource);
312+
313+
when(controller.deleteResource(eq(testCustomResource), any()))
314+
.thenReturn(
315+
DeleteControl.noFinalizerRemoval().rescheduleAfter(1000L));
316+
317+
PostExecutionControl control = eventDispatcher.handleExecution(
318+
executionScopeWithCREvent(UPDATED, testCustomResource));
319+
320+
assertThat(control.getReScheduleDelay().get()).isEqualTo(1000L);
321+
}
322+
308323
private void markForDeletion(CustomResource customResource) {
309324
customResource.getMetadata().setDeletionTimestamp("2019-8-10");
310325
}

Diff for: operator-framework-core/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestCustomResourceController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public DeleteControl deleteResource(
5757
resource.getSpec().getConfigMapName(),
5858
resource.getMetadata().getName());
5959
}
60-
return DeleteControl.DEFAULT_DELETE;
60+
return DeleteControl.defaultDelete();
6161
}
6262

6363
@Override

Diff for: operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/simple/TestCustomResourceController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public DeleteControl deleteResource(
8181
resource.getSpec().getConfigMapName(),
8282
resource.getMetadata().getName());
8383
}
84-
return DeleteControl.DEFAULT_DELETE;
84+
return DeleteControl.defaultDelete();
8585
}
8686

8787
@Override

Diff for: operator-framework/src/test/resources/compile-fixtures/ControllerImplemented2Interfaces.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ public UpdateControl<MyCustomResource> createOrUpdateResource(MyCustomResource c
2121

2222
@Override
2323
public DeleteControl deleteResource(MyCustomResource customResource, Context<MyCustomResource> context) {
24-
return DeleteControl.DEFAULT_DELETE;
24+
return DeleteControl.defaultDelete();
2525
}
2626
}

Diff for: operator-framework/src/test/resources/compile-fixtures/ControllerImplementedIntermediateAbstractClass.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ public UpdateControl<AbstractController.MyCustomResource> createOrUpdateResource
1818

1919
public DeleteControl deleteResource(AbstractController.MyCustomResource customResource,
2020
Context<AbstractController.MyCustomResource> context) {
21-
return DeleteControl.DEFAULT_DELETE;
21+
return DeleteControl.defaultDelete();
2222
}
2323
}

Diff for: operator-framework/src/test/resources/compile-fixtures/MultilevelController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public UpdateControl<MultilevelController.MyCustomResource> createOrUpdateResour
2222

2323
public DeleteControl deleteResource(MultilevelController.MyCustomResource customResource,
2424
Context<MultilevelController.MyCustomResource> context) {
25-
return DeleteControl.DEFAULT_DELETE;
25+
return DeleteControl.defaultDelete();
2626
}
2727

2828
}

Diff for: samples/common/src/main/java/io/javaoperatorsdk/operator/sample/CustomServiceController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public CustomServiceController(KubernetesClient kubernetesClient) {
3636
@Override
3737
public DeleteControl deleteResource(CustomService resource, Context<CustomService> context) {
3838
log.info("Execution deleteResource for: {}", resource.getMetadata().getName());
39-
return DeleteControl.DEFAULT_DELETE;
39+
return DeleteControl.defaultDelete();
4040
}
4141

4242
@Override

0 commit comments

Comments
 (0)