Skip to content

Commit 3daacab

Browse files
committed
fix: bulk creation of dependent resource directly in abstract resource
1 parent 01f6512 commit 3daacab

File tree

3 files changed

+101
-13
lines changed

3 files changed

+101
-13
lines changed

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

+82-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.javaoperatorsdk.operator.processing.dependent;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
35
import java.util.Optional;
46

57
import org.slf4j.Logger;
@@ -24,23 +26,54 @@ public abstract class AbstractDependentResource<R, P extends HasMetadata>
2426
protected Creator<R, P> creator;
2527
protected Updater<R, P> updater;
2628

27-
// todo discuss, rather implement this as interface?
28-
private ResourceDiscriminator<R, P> resourceDiscriminator;
29+
protected List<ResourceDiscriminator<R, P>> resourceDiscriminator = new ArrayList<>(1);
30+
// used just for bulk creation
31+
protected BulkResourceDiscriminatorFactory<R, P> bulkResourceDiscriminatorFactory;
2932

3033
@SuppressWarnings("unchecked")
3134
public AbstractDependentResource() {
3235
creator = creatable ? (Creator<R, P>) this : null;
3336
updater = updatable ? (Updater<R, P>) this : null;
3437
}
3538

36-
@SuppressWarnings("unchecked")
3739
@Override
3840
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
39-
Optional<R> maybeActual = getSecondaryResource(primary, context);
41+
var count = count(primary, context);
42+
if (isBulkResourceCreation(primary, context)) {
43+
initDiscriminators(count);
44+
}
45+
for (int i = 0; i < count; i++) {
46+
reconcileWithIndex(primary, i, context);
47+
}
48+
// todo result
49+
return null;
50+
}
51+
52+
private void initDiscriminators(int count) {
53+
if (resourceDiscriminator.size() == count) {
54+
return;
55+
}
56+
if (resourceDiscriminator.size() < count) {
57+
for (int i = resourceDiscriminator.size() - 1; i < count; i++) {
58+
resourceDiscriminator.add(bulkResourceDiscriminatorFactory.createResourceDiscriminator(i));
59+
}
60+
}
61+
if (resourceDiscriminator.size() < count) {
62+
for (int i = resourceDiscriminator.size() - 1; i < count; i++) {
63+
resourceDiscriminator.add(bulkResourceDiscriminatorFactory.createResourceDiscriminator(i));
64+
}
65+
}
66+
if (resourceDiscriminator.size() > count) {
67+
resourceDiscriminator.subList(count, resourceDiscriminator.size()).clear();
68+
}
69+
}
70+
71+
protected ReconcileResult<R> reconcileWithIndex(P primary, int i, Context<P> context) {
72+
Optional<R> maybeActual = getSecondaryResource(primary, i, context);
4073
if (creatable || updatable) {
4174
if (maybeActual.isEmpty()) {
4275
if (creatable) {
43-
var desired = desired(primary, context);
76+
var desired = desired(primary, i, context);
4477
throwIfNull(desired, primary, "Desired");
4578
logForOperation("Creating", primary, desired);
4679
var createdResource = handleCreate(desired, primary, context);
@@ -49,7 +82,8 @@ public ReconcileResult<R> reconcile(P primary, Context<P> context) {
4982
} else {
5083
final var actual = maybeActual.get();
5184
if (updatable) {
52-
final var match = updater.match(actual, primary, context);
85+
// todo simplify matcher?
86+
final var match = updater.match(actual, primary, i, context);
5387
if (!match.matched()) {
5488
final var desired = match.computedDesired().orElse(desired(primary, context));
5589
throwIfNull(desired, primary, "Desired");
@@ -69,14 +103,27 @@ public ReconcileResult<R> reconcile(P primary, Context<P> context) {
69103
return ReconcileResult.noOperation(maybeActual.orElse(null));
70104
}
71105

106+
// todo check
72107
protected Optional<R> getSecondaryResource(P primary, Context<P> context) {
73-
if (resourceDiscriminator == null) {
108+
if (resourceDiscriminator.isEmpty()) {
74109
return context.getSecondaryResource(resourceType());
75110
} else {
76-
return context.getSecondaryResource(resourceType(), resourceDiscriminator);
111+
return context.getSecondaryResource(resourceType(), resourceDiscriminator.get(0));
77112
}
78113
}
79114

115+
protected Optional<R> getSecondaryResource(P primary, int index, Context<P> context) {
116+
if (index > 0 && resourceDiscriminator.isEmpty()) {
117+
throw new IllegalStateException(
118+
"Handling resources in bulk bot no resource discriminators set.");
119+
}
120+
if (!isBulkResourceCreation(primary, context)) {
121+
return getSecondaryResource(primary, context);
122+
}
123+
124+
return context.getSecondaryResource(resourceType(), resourceDiscriminator.get(index));
125+
}
126+
80127
private void throwIfNull(R desired, P primary, String descriptor) {
81128
if (desired == null) {
82129
throw new DependentResourceException(
@@ -112,7 +159,7 @@ protected R handleCreate(R desired, P primary, Context<P> context) {
112159
protected abstract void onCreated(ResourceID primaryResourceId, R created);
113160

114161
/**
115-
* Allows sub-classes to perform additional processing on the updated resource if needed.
162+
* Allows subclasses to perform additional processing on the updated resource if needed.
116163
*
117164
* @param primaryResourceId the {@link ResourceID} of the primary resource associated with the
118165
* newly updated resource
@@ -134,14 +181,36 @@ protected R desired(P primary, Context<P> context) {
134181
"desired method must be implemented if this DependentResource can be created and/or updated");
135182
}
136183

137-
// todo review & refactor configuration to cover all cases
138-
public ResourceDiscriminator<R, P> getResourceDiscriminator() {
139-
return resourceDiscriminator;
184+
protected R desired(P primary, int index, Context<P> context) {
185+
if (!isBulkResourceCreation(primary, context)) {
186+
return desired(primary, context);
187+
} else {
188+
throw new IllegalStateException(
189+
"desired() with index method must be implemented for bulk DependentResource creation");
190+
}
140191
}
141192

142193
public AbstractDependentResource<R, P> setResourceDiscriminator(
143194
ResourceDiscriminator<R, P> resourceDiscriminator) {
144-
this.resourceDiscriminator = resourceDiscriminator;
195+
this.resourceDiscriminator.add(resourceDiscriminator);
196+
return this;
197+
}
198+
199+
protected int count(P primary, Context<P> context) {
200+
return 1;
201+
}
202+
203+
protected boolean isBulkResourceCreation(P primary, Context<P> context) {
204+
return false;
205+
}
206+
207+
public BulkResourceDiscriminatorFactory<R, P> getBulkResourceDiscriminatorFactory() {
208+
return bulkResourceDiscriminatorFactory;
209+
}
210+
211+
public AbstractDependentResource<R, P> setBulkResourceDiscriminatorFactory(
212+
BulkResourceDiscriminatorFactory<R, P> bulkResourceDiscriminatorFactory) {
213+
this.bulkResourceDiscriminatorFactory = bulkResourceDiscriminatorFactory;
145214
return this;
146215
}
147216
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.javaoperatorsdk.operator.processing.dependent;
2+
3+
import io.fabric8.kubernetes.api.model.HasMetadata;
4+
import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
5+
6+
public interface BulkResourceDiscriminatorFactory<R, P extends HasMetadata> {
7+
8+
ResourceDiscriminator<R, P> createResourceDiscriminator(int index);
9+
10+
}

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

+9
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,13 @@ public interface Updater<R, P extends HasMetadata> {
88
R update(R actual, R desired, P primary, Context<P> context);
99

1010
Result<R> match(R actualResource, P primary, Context<P> context);
11+
12+
// todo change to simple desired matching?
13+
default Result<R> match(R actualResource, P primary, int index, Context<P> context) {
14+
if (index == 0) {
15+
return match(actualResource, primary, context);
16+
} else {
17+
throw new IllegalStateException("Implement this");
18+
}
19+
}
1120
}

0 commit comments

Comments
 (0)