Skip to content

Commit c295061

Browse files
committed
feat: ResourceIDMapper for external event sources, external dependents and bulk dependents
Signed-off-by: Attila Mészáros <a_meszaros@apple.com>
1 parent a620cbe commit c295061

File tree

13 files changed

+114
-44
lines changed

13 files changed

+114
-44
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package io.javaoperatorsdk.operator.processing;
1717

18+
import io.fabric8.kubernetes.api.model.HasMetadata;
19+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
1820
import io.javaoperatorsdk.operator.processing.event.source.ExternalResourceCachingEventSource;
1921

2022
/** Provides id for the target resource. */
@@ -29,11 +31,11 @@ public interface ResourceIDMapper<R, ID> {
2931
* @return static id mapper, all resources are mapped for same id.
3032
* @param <T> secondary resource type
3133
*/
32-
static <T> ResourceIDMapper<T, String> singleResourceCacheKeyMapper() {
34+
static <R> ResourceIDMapper<R, String> singleResourceCacheKeyMapper() {
3335
return r -> "id";
3436
}
3537

36-
static <T, ID> ResourceIDMapper<T, ID> resourceIdProviderMapper() {
38+
static <R, ID> ResourceIDMapper<R, ID> resourceIdProviderMapper() {
3739
return r -> {
3840
if (r instanceof ResourceIDProvider resourceIDProvider) {
3941
return (ID) resourceIDProvider.resourceId();
@@ -43,4 +45,8 @@ static <T, ID> ResourceIDMapper<T, ID> resourceIdProviderMapper() {
4345
}
4446
};
4547
}
48+
49+
static <R extends HasMetadata> ResourceIDMapper<R, ResourceID> kubernetesResourceIdMapper() {
50+
return ResourceID::fromResource;
51+
}
4652
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ protected AbstractDependentResource(String name) {
6363

6464
dependentResourceReconciler =
6565
this instanceof BulkDependentResource
66-
? new BulkDependentResourceReconciler<>((BulkDependentResource<R, P>) this)
66+
? new BulkDependentResourceReconciler<>((BulkDependentResource<R, P, ?>) this)
6767
: new SingleDependentResourceReconciler<>(this);
6868
this.name = name == null ? DependentResource.defaultNameFor(this.getClass()) : name;
6969
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@
2727
* implementing this interface will typically also implement one or more additional interfaces such
2828
* as {@link Creator}, {@link Updater}, {@link Deleter}.
2929
*
30+
* @param <ID> type of the id to distinguish resource
3031
* @param <R> the dependent resource type
3132
* @param <P> the primary resource type
3233
*/
33-
public interface BulkDependentResource<R, P extends HasMetadata> {
34+
public interface BulkDependentResource<R, P extends HasMetadata, ID> {
3435

3536
/**
3637
* Retrieves a map of desired secondary resources associated with the specified primary resource,
@@ -42,7 +43,7 @@ public interface BulkDependentResource<R, P extends HasMetadata> {
4243
* @return a Map associating desired secondary resources with the specified primary via arbitrary
4344
* identifiers
4445
*/
45-
default Map<String, R> desiredResources(P primary, Context<P> context) {
46+
default Map<ID, R> desiredResources(P primary, Context<P> context) {
4647
throw new IllegalStateException(
4748
"Implement desiredResources in case a non read-only bulk dependent resource");
4849
}
@@ -57,7 +58,7 @@ default Map<String, R> desiredResources(P primary, Context<P> context) {
5758
* @return a Map associating actual secondary resources with the specified primary via arbitrary
5859
* identifiers
5960
*/
60-
Map<String, R> getSecondaryResources(P primary, Context<P> context);
61+
Map<ID, R> getSecondaryResources(P primary, Context<P> context);
6162

6263
/**
6364
* Deletes the actual resource identified by the specified key if it's not in the set of desired
@@ -69,7 +70,7 @@ default Map<String, R> desiredResources(P primary, Context<P> context) {
6970
* @param key key of the resource
7071
* @param context actual context
7172
*/
72-
void deleteTargetResource(P primary, R resource, String key, Context<P> context);
73+
void deleteTargetResource(P primary, R resource, ID key, Context<P> context);
7374

7475
/**
7576
* Determines whether the specified secondary resource matches the desired state with target index

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,19 @@
2929
import io.javaoperatorsdk.operator.api.reconciler.dependent.ReconcileResult;
3030
import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
3131

32-
class BulkDependentResourceReconciler<R, P extends HasMetadata>
32+
class BulkDependentResourceReconciler<R, P extends HasMetadata, ID>
3333
implements DependentResourceReconciler<R, P> {
3434

35-
private final BulkDependentResource<R, P> bulkDependentResource;
35+
private final BulkDependentResource<R, P, ID> bulkDependentResource;
3636

37-
BulkDependentResourceReconciler(BulkDependentResource<R, P> bulkDependentResource) {
37+
BulkDependentResourceReconciler(BulkDependentResource<R, P, ID> bulkDependentResource) {
3838
this.bulkDependentResource = bulkDependentResource;
3939
}
4040

4141
@Override
4242
public ReconcileResult<R> reconcile(P primary, Context<P> context) {
4343

44-
Map<String, R> actualResources = bulkDependentResource.getSecondaryResources(primary, context);
44+
Map<ID, R> actualResources = bulkDependentResource.getSecondaryResources(primary, context);
4545
if (!(bulkDependentResource instanceof Creator<?, ?>)
4646
&& !(bulkDependentResource instanceof Deleter<?>)
4747
&& !(bulkDependentResource instanceof Updater<?, ?>)) {
@@ -73,7 +73,7 @@ public void delete(P primary, Context<P> context) {
7373
}
7474

7575
private void deleteExtraResources(
76-
Set<String> expectedKeys, Map<String, R> actualResources, P primary, Context<P> context) {
76+
Set<ID> expectedKeys, Map<ID, R> actualResources, P primary, Context<P> context) {
7777
actualResources.forEach(
7878
(key, value) -> {
7979
if (!expectedKeys.contains(key)) {
@@ -90,13 +90,13 @@ private void deleteExtraResources(
9090
* @param <P>
9191
*/
9292
@Ignore
93-
private static class BulkDependentResourceInstance<R, P extends HasMetadata>
93+
private static class BulkDependentResourceInstance<R, P extends HasMetadata, ID>
9494
extends AbstractDependentResource<R, P> implements Creator<R, P>, Deleter<P>, Updater<R, P> {
95-
private final BulkDependentResource<R, P> bulkDependentResource;
95+
private final BulkDependentResource<R, P, ID> bulkDependentResource;
9696
private final R desired;
9797

9898
private BulkDependentResourceInstance(
99-
BulkDependentResource<R, P> bulkDependentResource, R desired) {
99+
BulkDependentResource<R, P, ID> bulkDependentResource, R desired) {
100100
this.bulkDependentResource = bulkDependentResource;
101101
this.desired = desired;
102102
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
import io.fabric8.kubernetes.api.model.HasMetadata;
1919
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
2020

21-
public interface CRUDBulkDependentResource<R, P extends HasMetadata>
22-
extends BulkDependentResource<R, P>, Creator<R, P>, BulkUpdater<R, P>, Deleter<P> {}
21+
public interface CRUDBulkDependentResource<R, P extends HasMetadata, ID>
22+
extends BulkDependentResource<R, P, ID>, Creator<R, P>, BulkUpdater<R, P>, Deleter<P> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright Java Operator SDK Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.javaoperatorsdk.operator.processing.dependent;
17+
18+
import io.fabric8.kubernetes.api.model.HasMetadata;
19+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
20+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
21+
22+
public interface CRUDKubernetesBulkDependentResource<R, P extends HasMetadata>
23+
extends BulkDependentResource<R, P, ResourceID>, Creator<R, P>, BulkUpdater<R, P>, Deleter<P> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright Java Operator SDK Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.javaoperatorsdk.operator.processing.dependent;
17+
18+
import java.util.Map;
19+
import java.util.function.Function;
20+
import java.util.function.Predicate;
21+
import java.util.stream.Collectors;
22+
23+
import io.fabric8.kubernetes.api.model.HasMetadata;
24+
import io.javaoperatorsdk.operator.api.reconciler.Context;
25+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
26+
import io.javaoperatorsdk.operator.processing.ResourceIDMapper;
27+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
28+
29+
public interface KubernetesBulkDependentResource<R extends HasMetadata, P extends HasMetadata>
30+
extends BulkDependentResource<R, P, ResourceID>, DependentResource<R, P> {
31+
32+
@Override
33+
default Map<ResourceID, R> getSecondaryResources(P primary, Context<P> context) {
34+
return context
35+
.getSecondaryResourcesAsStream(resourceType())
36+
.filter(secondaryResourceFilter(primary, context))
37+
.collect(
38+
Collectors.toMap(
39+
cm -> ResourceIDMapper.kubernetesResourceIdMapper().idFor(cm),
40+
Function.identity()));
41+
}
42+
43+
default Predicate<R> secondaryResourceFilter(P primary, Context<P> context) {
44+
return r -> true;
45+
}
46+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ protected void handleDelete(P primary, R secondary, Context<P> context) {
205205
}
206206

207207
@SuppressWarnings("unused")
208-
public void deleteTargetResource(P primary, R resource, String key, Context<P> context) {
208+
public void deleteTargetResource(P primary, R resource, ResourceID key, Context<P> context) {
209209
context.getClient().resource(resource).delete();
210210
}
211211

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,30 @@
2323
import io.fabric8.kubernetes.api.model.ConfigMap;
2424
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
2525
import io.javaoperatorsdk.operator.api.reconciler.Context;
26+
import io.javaoperatorsdk.operator.processing.ResourceIDMapper;
2627
import io.javaoperatorsdk.operator.processing.dependent.*;
2728
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource;
29+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
2830

2931
/** Not using CRUDKubernetesDependentResource so the delete functionality can be tested. */
3032
public class ConfigMapDeleterBulkDependentResource
3133
extends KubernetesDependentResource<ConfigMap, BulkDependentTestCustomResource>
32-
implements CRUDBulkDependentResource<ConfigMap, BulkDependentTestCustomResource> {
34+
implements CRUDKubernetesBulkDependentResource<ConfigMap, BulkDependentTestCustomResource> {
3335

3436
public static final String LABEL_KEY = "bulk";
3537
public static final String LABEL_VALUE = "true";
3638
public static final String ADDITIONAL_DATA_KEY = "additionalData";
3739
public static final String INDEX_DELIMITER = "-";
3840

3941
@Override
40-
public Map<String, ConfigMap> desiredResources(
42+
public Map<ResourceID, ConfigMap> desiredResources(
4143
BulkDependentTestCustomResource primary, Context<BulkDependentTestCustomResource> context) {
4244
var number = primary.getSpec().getNumberOfResources();
43-
Map<String, ConfigMap> res = new HashMap<>();
45+
Map<ResourceID, ConfigMap> res = new HashMap<>();
4446
for (int i = 0; i < number; i++) {
4547
var key = Integer.toString(i);
46-
res.put(key, desired(primary, key));
48+
var desired = desired(primary, key);
49+
res.put(ResourceIDMapper.kubernetesResourceIdMapper().idFor(desired), desired);
4750
}
4851
return res;
4952
}
@@ -62,15 +65,12 @@ public ConfigMap desired(BulkDependentTestCustomResource primary, String key) {
6265
}
6366

6467
@Override
65-
public Map<String, ConfigMap> getSecondaryResources(
68+
public Map<ResourceID, ConfigMap> getSecondaryResources(
6669
BulkDependentTestCustomResource primary, Context<BulkDependentTestCustomResource> context) {
6770
return context
6871
.getSecondaryResourcesAsStream(ConfigMap.class)
6972
.filter(cm -> getName(cm).startsWith(primary.getMetadata().getName()))
70-
.collect(
71-
Collectors.toMap(
72-
cm -> getName(cm).substring(getName(cm).lastIndexOf(INDEX_DELIMITER) + 1),
73-
Function.identity()));
73+
.collect(Collectors.toMap(ResourceID::fromResource, Function.identity()));
7474
}
7575

7676
private static String getName(ConfigMap cm) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
public class ExternalBulkDependentResource
3434
extends PollingDependentResource<ExternalResource, BulkDependentTestCustomResource, String>
35-
implements BulkDependentResource<ExternalResource, BulkDependentTestCustomResource>,
35+
implements BulkDependentResource<ExternalResource, BulkDependentTestCustomResource, String>,
3636
Creator<ExternalResource, BulkDependentTestCustomResource>,
3737
Deleter<BulkDependentTestCustomResource>,
3838
BulkUpdater<ExternalResource, BulkDependentTestCustomResource> {

0 commit comments

Comments
 (0)