Skip to content

Commit e5e2bf3

Browse files
committed
refactor: isolate bulk dependent resource handling more
1 parent 0092f0a commit e5e2bf3

File tree

8 files changed

+166
-59
lines changed

8 files changed

+166
-59
lines changed

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

Lines changed: 15 additions & 52 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,58 +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 targetKeys = bulkDependentResource.targetKeys(primary, context);
43-
Map<String, R> actualResources =
44-
bulkDependentResource.getSecondaryResources(primary, context);
45-
46-
deleteBulkResourcesIfRequired(targetKeys, actualResources, primary, context);
47-
final List<ReconcileResult<R>> results = new ArrayList<>(targetKeys.size());
48-
49-
for (String key : targetKeys) {
50-
results.add(reconcileIndexAware(primary, actualResources.get(key), key, context));
51-
}
52-
return ReconcileResult.aggregatedResult(results);
53-
} else {
54-
var actualResource = getSecondaryResource(primary, context);
55-
return reconcileIndexAware(primary, actualResource.orElse(null), null, context);
56-
}
42+
return dependentResourceReconciler.reconcile(primary, context);
5743
}
5844

59-
@SuppressWarnings({"rawtypes"})
60-
protected void deleteBulkResourcesIfRequired(Set targetKeys, Map<String, R> actualResources,
61-
P primary, Context<P> context) {
62-
actualResources.forEach((key, value) -> {
63-
if (!targetKeys.contains(key)) {
64-
bulkDependentResource.deleteBulkResource(primary, value, key, context);
65-
}
66-
});
67-
}
68-
69-
protected ReconcileResult<R> reconcileIndexAware(P primary, R resource, String key,
70-
Context<P> context) {
45+
protected ReconcileResult<R> reconcile(P primary, R resource, Context<P> context) {
7146
if (creatable || updatable) {
7247
if (resource == null) {
7348
if (creatable) {
74-
var desired = desiredIndexAware(primary, key, context);
49+
var desired = desired(primary, context);
7550
throwIfNull(desired, primary, "Desired");
7651
logForOperation("Creating", primary, desired);
7752
var createdResource = handleCreate(desired, primary, context);
@@ -80,14 +55,10 @@ protected ReconcileResult<R> reconcileIndexAware(P primary, R resource, String k
8055
} else {
8156
if (updatable) {
8257
final Matcher.Result<R> match;
83-
if (bulk) {
84-
match = bulkDependentResource.match(resource, primary, key, context);
85-
} else {
86-
match = updater.match(resource, primary, context);
87-
}
58+
match = match(resource, primary, context);
8859
if (!match.matched()) {
8960
final var desired =
90-
match.computedDesired().orElse(desiredIndexAware(primary, key, context));
61+
match.computedDesired().orElse(desired(primary, context));
9162
throwIfNull(desired, primary, "Desired");
9263
logForOperation("Updating", primary, desired);
9364
var updatedResource = handleUpdate(resource, desired, primary, context);
@@ -105,9 +76,8 @@ protected ReconcileResult<R> reconcileIndexAware(P primary, R resource, String k
10576
return ReconcileResult.noOperation(resource);
10677
}
10778

108-
private R desiredIndexAware(P primary, String key, Context<P> context) {
109-
return bulk ? bulkDependentResource.desired(primary, key, context)
110-
: desired(primary, context);
79+
public Result<R> match(R resource, P primary, Context<P> context) {
80+
return updater.match(resource, primary, context);
11181
}
11282

11383
@Override
@@ -174,12 +144,7 @@ protected R desired(P primary, Context<P> context) {
174144
}
175145

176146
public void delete(P primary, Context<P> context) {
177-
if (bulk) {
178-
var actualResources = bulkDependentResource.getSecondaryResources(primary, context);
179-
deleteBulkResourcesIfRequired(Collections.emptySet(), actualResources, primary, context);
180-
} else {
181-
handleDelete(primary, context);
182-
}
147+
dependentResourceReconciler.delete(primary, context);
183148
}
184149

185150
protected void handleDelete(P primary, Context<P> context) {
@@ -195,11 +160,9 @@ protected boolean isCreatable() {
195160
return creatable;
196161
}
197162

163+
@SuppressWarnings("unused")
198164
protected boolean isUpdatable() {
199165
return updatable;
200166
}
201167

202-
protected boolean isBulk() {
203-
return bulk;
204-
}
205168
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@ public interface BulkDependentResource<R, P extends HasMetadata>
1818
extends Creator<R, P>, Deleter<P> {
1919

2020
/**
21-
* @return number of resources to create
21+
* Retrieves the Set of keys identifying the set of secondary resources associated with the
22+
* specified primary resource.
23+
*
24+
* @param primary the primary resource with which we want to identify which secondary resources
25+
* are associated
26+
* @param context the {@link Context} associated with the current reconciliation
27+
* @return a Set of identifiers allowing to associate a bulk secondary resource with the specified
28+
* primary
2229
*/
23-
Set<String> targetKeys(P primary, Context<P> context);
30+
Set<String> desiredResourceKeys(P primary, Context<P> context);
2431

2532
Map<String, R> getSecondaryResources(P primary, Context<P> context);
2633

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: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.DependentResourceConfigurator;
2020
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.KubernetesClientAware;
2121
import io.javaoperatorsdk.operator.processing.dependent.AbstractEventSourceHolderDependentResource;
22+
import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource;
2223
import io.javaoperatorsdk.operator.processing.dependent.Matcher;
2324
import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
2425
import io.javaoperatorsdk.operator.processing.event.ResourceID;
@@ -139,17 +140,18 @@ public Result<R> match(R actualResource, P primary, Context<P> context) {
139140
return matcher.match(actualResource, primary, context);
140141
}
141142

143+
@SuppressWarnings("unchecked")
142144
public Result<R> match(R actualResource, P primary, String key, Context<P> context) {
143-
final var desired = bulkDependentResource.desired(primary, key, context);
144-
return GenericKubernetesResourceMatcher.match((R) desired, actualResource, false);
145+
final var desired = ((BulkDependentResource<R, P>) this).desired(primary, key, context);
146+
return GenericKubernetesResourceMatcher.match(desired, actualResource, false);
145147
}
146148

147149
protected void handleDelete(P primary, Context<P> context) {
148150
var resource = getSecondaryResource(primary, context);
149151
resource.ifPresent(r -> client.resource(r).delete());
150152
}
151153

152-
154+
@SuppressWarnings("unused")
153155
public void deleteBulkResource(P primary, R resource, String key, Context<P> context) {
154156
client.resource(resource).delete();
155157
}

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/ConfigMapDeleterBulkDependentResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public ConfigMapDeleterBulkDependentResource() {
3232
}
3333

3434
@Override
35-
public Set<String> targetKeys(BulkDependentTestCustomResource primary,
35+
public Set<String> desiredResourceKeys(BulkDependentTestCustomResource primary,
3636
Context<BulkDependentTestCustomResource> context) {
3737
var number = primary.getSpec().getNumberOfResources();
3838
Set<String> res = new HashSet<>();

operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/bulkdependent/external/ExternalBulkDependentResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ private ResourceID toResourceID(ExternalResource externalResource) {
6060
}
6161

6262
@Override
63-
public Set<String> targetKeys(BulkDependentTestCustomResource primary,
63+
public Set<String> desiredResourceKeys(BulkDependentTestCustomResource primary,
6464
Context<BulkDependentTestCustomResource> context) {
6565
var number = primary.getSpec().getNumberOfResources();
6666
Set<String> res = new HashSet<>();

0 commit comments

Comments
 (0)