Skip to content

Commit 8cf411b

Browse files
committed
refactor: isolate bulk dependent resource handling more
1 parent 7442012 commit 8cf411b

File tree

6 files changed

+159
-58
lines changed

6 files changed

+159
-58
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/AbstractDependentResource.java

Lines changed: 15 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
1212
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
1313
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
14+
import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
1415
import io.javaoperatorsdk.operator.processing.event.ResourceID;
1516

1617
@Ignore
@@ -20,61 +21,32 @@ public abstract class AbstractDependentResource<R, P extends HasMetadata>
2021

2122
private final boolean creatable = this instanceof Creator;
2223
private final boolean updatable = this instanceof Updater;
23-
private final boolean bulk = this instanceof BulkDependentResource;
2424

2525
protected Creator<R, P> creator;
2626
protected Updater<R, P> updater;
27-
protected BulkDependentResource<R, P> bulkDependentResource;
2827
private ResourceDiscriminator<R, P> resourceDiscriminator;
28+
private final DependentResourceReconciler<R, P> dependentResourceReconciler;
2929

30-
@SuppressWarnings({"unchecked", "rawtypes"})
30+
@SuppressWarnings({"unchecked"})
3131
protected AbstractDependentResource() {
3232
creator = creatable ? (Creator<R, P>) this : null;
3333
updater = updatable ? (Updater<R, P>) this : null;
3434

35-
bulkDependentResource = bulk ? (BulkDependentResource) this : null;
35+
dependentResourceReconciler = this instanceof BulkDependentResource
36+
? new BulkDependentResourceReconciler<>((BulkDependentResource<R, P>) this)
37+
: new SingleDependentResourceReconciler<>(this);
3638
}
3739

38-
3940
@Override
4041
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
41-
if (bulk) {
42-
final var targetResources = bulkDependentResource.desiredResources(primary, context);
43-
44-
Map<String, R> actualResources =
45-
bulkDependentResource.getSecondaryResources(primary, context);
46-
47-
deleteBulkResourcesIfRequired(targetResources.keySet(), actualResources, primary, context);
48-
final List<ReconcileResult<R>> results = new ArrayList<>(targetResources.size());
49-
50-
targetResources.forEach((key, resource) -> {
51-
results.add(reconcileIndexAware(primary, actualResources.get(key), resource, key, context));
52-
});
53-
54-
return ReconcileResult.aggregatedResult(results);
55-
} else {
56-
var actualResource = getSecondaryResource(primary, context);
57-
return reconcileIndexAware(primary, actualResource.orElse(null), null, null, context);
58-
}
42+
return dependentResourceReconciler.reconcile(primary, context);
5943
}
6044

61-
@SuppressWarnings({"rawtypes"})
62-
protected void deleteBulkResourcesIfRequired(Set targetKeys, Map<String, R> actualResources,
63-
P primary, Context<P> context) {
64-
actualResources.forEach((key, value) -> {
65-
if (!targetKeys.contains(key)) {
66-
bulkDependentResource.deleteBulkResource(primary, value, key, context);
67-
}
68-
});
69-
}
70-
71-
protected ReconcileResult<R> reconcileIndexAware(P primary, R actualResource, R desiredResource,
72-
String key,
73-
Context<P> context) {
45+
protected ReconcileResult<R> reconcile(P primary, R resource, Context<P> context) {
7446
if (creatable || updatable) {
7547
if (actualResource == null) {
7648
if (creatable) {
77-
var desired = bulkAwareDesired(primary, desiredResource, context);
49+
var desired = desired(primary, context);
7850
throwIfNull(desired, primary, "Desired");
7951
logForOperation("Creating", primary, desired);
8052
var createdResource = handleCreate(desired, primary, context);
@@ -83,15 +55,10 @@ protected ReconcileResult<R> reconcileIndexAware(P primary, R actualResource, R
8355
} else {
8456
if (updatable) {
8557
final Matcher.Result<R> match;
86-
if (bulk) {
87-
match =
88-
bulkDependentResource.match(actualResource, desiredResource, primary, key, context);
89-
} else {
90-
match = updater.match(actualResource, primary, context);
91-
}
58+
match = match(resource, primary, context);
9259
if (!match.matched()) {
9360
final var desired =
94-
match.computedDesired().orElse(bulkAwareDesired(primary, desiredResource, context));
61+
match.computedDesired().orElse(desired(primary, context));
9562
throwIfNull(desired, primary, "Desired");
9663
logForOperation("Updating", primary, desired);
9764
var updatedResource = handleUpdate(actualResource, desired, primary, context);
@@ -110,9 +77,8 @@ protected ReconcileResult<R> reconcileIndexAware(P primary, R actualResource, R
11077
return ReconcileResult.noOperation(actualResource);
11178
}
11279

113-
private R bulkAwareDesired(P primary, R alreadyComputedDesire, Context<P> context) {
114-
return bulk ? alreadyComputedDesire
115-
: desired(primary, context);
80+
public Result<R> match(R resource, P primary, Context<P> context) {
81+
return updater.match(resource, primary, context);
11682
}
11783

11884
@Override
@@ -179,12 +145,7 @@ protected R desired(P primary, Context<P> context) {
179145
}
180146

181147
public void delete(P primary, Context<P> context) {
182-
if (bulk) {
183-
var actualResources = bulkDependentResource.getSecondaryResources(primary, context);
184-
deleteBulkResourcesIfRequired(Collections.emptySet(), actualResources, primary, context);
185-
} else {
186-
handleDelete(primary, context);
187-
}
148+
dependentResourceReconciler.delete(primary, context);
188149
}
189150

190151
protected void handleDelete(P primary, Context<P> context) {
@@ -200,11 +161,8 @@ protected boolean isCreatable() {
200161
return creatable;
201162
}
202163

164+
@SuppressWarnings("unused")
203165
protected boolean isUpdatable() {
204166
return updatable;
205167
}
206-
207-
protected boolean isBulk() {
208-
return bulk;
209-
}
210168
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/BulkDependentResource.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ public interface BulkDependentResource<R, P extends HasMetadata>
1717
extends Creator<R, P>, Deleter<P> {
1818

1919
/**
20-
* @return number of resources to create
20+
* Retrieves a map of desired secondary resources associated with the specified primary resource,
21+
* identified by an arbitrary key.
22+
*
23+
* @param primary the primary resource with which we want to identify which secondary resources
24+
* are associated
25+
* @param context the {@link Context} associated with the current reconciliation
26+
* @return a Map associating bulk secondary resources with the specified primary via arbitrary
27+
* identifiers
2128
*/
2229
Map<String, R> desiredResources(P primary, Context<P> context);
2330

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package io.javaoperatorsdk.operator.processing.dependent;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Set;
8+
9+
import io.fabric8.kubernetes.api.model.HasMetadata;
10+
import io.javaoperatorsdk.operator.api.reconciler.Context;
11+
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
12+
import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
13+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
14+
15+
class BulkDependentResourceReconciler<R, P extends HasMetadata>
16+
implements DependentResourceReconciler<R, P> {
17+
18+
private final BulkDependentResource<R, P> bulkDependentResource;
19+
20+
BulkDependentResourceReconciler(BulkDependentResource<R, P> bulkDependentResource) {
21+
this.bulkDependentResource = bulkDependentResource;
22+
}
23+
24+
@Override
25+
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
26+
final var targetKeys = bulkDependentResource.desiredResourceKeys(primary, context);
27+
Map<String, R> actualResources =
28+
bulkDependentResource.getSecondaryResources(primary, context);
29+
30+
deleteBulkResourcesIfRequired(targetKeys, actualResources, primary, context);
31+
32+
final List<ReconcileResult<R>> results = new ArrayList<>(targetKeys.size());
33+
actualResources.forEach((key, value) -> {
34+
final var instance = new BulkDependentResourceInstance<>(key, bulkDependentResource);
35+
results.add(instance.reconcile(primary, value, context));
36+
});
37+
38+
return ReconcileResult.aggregatedResult(results);
39+
}
40+
41+
@Override
42+
public void delete(P primary, Context<P> context) {
43+
var actualResources = bulkDependentResource.getSecondaryResources(primary, context);
44+
deleteBulkResourcesIfRequired(Collections.emptySet(), actualResources, primary, context);
45+
}
46+
47+
protected void deleteBulkResourcesIfRequired(Set<String> expectedKeys,
48+
Map<String, R> actualResources, P primary, Context<P> context) {
49+
actualResources.forEach((key, value) -> {
50+
if (!expectedKeys.contains(key)) {
51+
bulkDependentResource.deleteBulkResource(primary, value, key, context);
52+
}
53+
});
54+
}
55+
56+
private static class BulkDependentResourceInstance<R, P extends HasMetadata>
57+
extends AbstractDependentResource<R, P> {
58+
private final String key;
59+
private final BulkDependentResource<R, P> bulkDependentResource;
60+
61+
private BulkDependentResourceInstance(String key,
62+
BulkDependentResource<R, P> bulkDependentResource) {
63+
this.key = key;
64+
this.bulkDependentResource = bulkDependentResource;
65+
}
66+
67+
@SuppressWarnings("unchecked")
68+
private AbstractDependentResource<R, P> asAbstractDependentResource() {
69+
return (AbstractDependentResource<R, P>) bulkDependentResource;
70+
}
71+
72+
@Override
73+
protected R desired(P primary, Context<P> context) {
74+
return bulkDependentResource.desired(primary, key, context);
75+
}
76+
77+
@Override
78+
public Result<R> match(R resource, P primary, Context<P> context) {
79+
return bulkDependentResource.match(resource, primary, key, context);
80+
}
81+
82+
@Override
83+
protected void onCreated(ResourceID primaryResourceId, R created) {
84+
asAbstractDependentResource().onCreated(primaryResourceId, created);
85+
}
86+
87+
@Override
88+
protected void onUpdated(ResourceID primaryResourceId, R updated, R actual) {
89+
asAbstractDependentResource().onUpdated(primaryResourceId, updated, actual);
90+
}
91+
92+
@Override
93+
public Class<R> resourceType() {
94+
return asAbstractDependentResource().resourceType();
95+
}
96+
}
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.javaoperatorsdk.operator.processing.dependent;
2+
3+
import io.fabric8.kubernetes.api.model.HasMetadata;
4+
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
6+
7+
interface DependentResourceReconciler<R, P extends HasMetadata> {
8+
9+
ReconcileResult<R> reconcile(P primary, Context<P> context);
10+
11+
void delete(P primary, Context<P> context);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.javaoperatorsdk.operator.processing.dependent;
2+
3+
import io.fabric8.kubernetes.api.model.HasMetadata;
4+
import io.javaoperatorsdk.operator.api.reconciler.Context;
5+
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
6+
7+
class SingleDependentResourceReconciler<R, P extends HasMetadata>
8+
implements DependentResourceReconciler<R, P> {
9+
10+
private final AbstractDependentResource<R, P> instance;
11+
12+
SingleDependentResourceReconciler(AbstractDependentResource<R, P> dependentResource) {
13+
this.instance = dependentResource;
14+
}
15+
16+
@Override
17+
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
18+
final var maybeActual = instance.getSecondaryResource(primary, context);
19+
return instance.reconcile(primary, maybeActual.orElse(null), context);
20+
}
21+
22+
@Override
23+
public void delete(P primary, Context<P> context) {
24+
instance.handleDelete(primary, context);
25+
}
26+
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ protected void handleDelete(P primary, Context<P> context) {
148148
resource.ifPresent(r -> client.resource(r).delete());
149149
}
150150

151+
@SuppressWarnings("unused")
151152
public void deleteBulkResource(P primary, R resource, String key, Context<P> context) {
152153
client.resource(resource).delete();
153154
}

0 commit comments

Comments
 (0)