Skip to content

Commit 408a527

Browse files
committed
cluster scope
1 parent 2d77939 commit 408a527

10 files changed

+208
-63
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,26 @@
11
package io.javaoperatorsdk.operator.processing.event.source.cache;
22

3-
import java.time.Duration;
43
import java.util.stream.IntStream;
54

65
import org.junit.jupiter.api.Test;
7-
import org.junit.jupiter.api.extension.RegisterExtension;
86

97
import io.fabric8.kubernetes.api.model.ConfigMap;
10-
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
11-
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
8+
import io.fabric8.kubernetes.client.CustomResource;
129
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
13-
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.BoundedCacheTestCustomResource;
14-
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.BoundedCacheTestReconciler;
15-
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.BoundedCacheTestSpec;
10+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestSpec;
11+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestStatus;
1612

17-
import static io.javaoperatorsdk.operator.processing.event.source.cache.sample.BoundedCacheTestReconciler.DATA_KEY;
13+
import static io.javaoperatorsdk.operator.processing.event.source.cache.sample.AbstractTestReconciler.DATA_KEY;
1814
import static org.assertj.core.api.Assertions.assertThat;
1915
import static org.awaitility.Awaitility.await;
2016

21-
class CaffeinBoundedCacheIT {
17+
public abstract class BoundedCacheTestBase<P extends CustomResource<BoundedCacheTestSpec, BoundedCacheTestStatus>> {
2218

2319
public static final int NUMBER_OF_RESOURCE_TO_TEST = 3;
2420
public static final String RESOURCE_NAME_PREFIX = "test-";
2521
public static final String INITIAL_DATA_PREFIX = "data-";
2622
public static final String UPDATED_PREFIX = "updatedPrefix";
2723

28-
@RegisterExtension
29-
LocallyRunOperatorExtension extension =
30-
LocallyRunOperatorExtension.builder().withReconciler(new BoundedCacheTestReconciler(), o -> {
31-
o.withItemStore(CaffeinBoundedItemStores.boundedItemStore(
32-
new KubernetesClientBuilder().build(), BoundedCacheTestCustomResource.class,
33-
Duration.ofMinutes(1),
34-
1));
35-
})
36-
.build();
37-
3824
@Test
3925
void reconciliationWorksWithLimitedCache() {
4026
createTestResources();
@@ -52,23 +38,23 @@ void reconciliationWorksWithLimitedCache() {
5238

5339
private void assertConfigMapsDeleted() {
5440
await().untilAsserted(() -> IntStream.range(0, NUMBER_OF_RESOURCE_TO_TEST).forEach(i -> {
55-
var cm = extension.get(ConfigMap.class, RESOURCE_NAME_PREFIX + i);
41+
var cm = extension().get(ConfigMap.class, RESOURCE_NAME_PREFIX + i);
5642
assertThat(cm).isNull();
5743
}));
5844
}
5945

6046
private void deleteTestResources() {
6147
IntStream.range(0, NUMBER_OF_RESOURCE_TO_TEST).forEach(i -> {
62-
var cm = extension.get(BoundedCacheTestCustomResource.class, RESOURCE_NAME_PREFIX + i);
63-
extension.delete(cm);
48+
var cm = extension().get(customResourceClass(), RESOURCE_NAME_PREFIX + i);
49+
extension().delete(cm);
6450
});
6551
}
6652

6753
private void updateTestResources() {
6854
IntStream.range(0, NUMBER_OF_RESOURCE_TO_TEST).forEach(i -> {
69-
var cm = extension.get(ConfigMap.class, RESOURCE_NAME_PREFIX + i);
55+
var cm = extension().get(ConfigMap.class, RESOURCE_NAME_PREFIX + i);
7056
cm.getData().put(DATA_KEY, UPDATED_PREFIX + i);
71-
extension.replace(cm);
57+
extension().replace(cm);
7258
});
7359
}
7460

@@ -78,25 +64,21 @@ void assertConfigMapData(String dataPrefix) {
7864
}
7965

8066
private void assertConfigMap(int i, String prefix) {
81-
var cm = extension.get(ConfigMap.class, RESOURCE_NAME_PREFIX + i);
67+
var cm = extension().get(ConfigMap.class, RESOURCE_NAME_PREFIX + i);
8268
assertThat(cm).isNotNull();
8369
assertThat(cm.getData().get(DATA_KEY)).isEqualTo(prefix + i);
8470
}
8571

8672
private void createTestResources() {
8773
IntStream.range(0, NUMBER_OF_RESOURCE_TO_TEST).forEach(i -> {
88-
extension.create(createTestResource(i));
74+
extension().create(createTestResource(i));
8975
});
9076
}
9177

92-
BoundedCacheTestCustomResource createTestResource(int index) {
93-
var res = new BoundedCacheTestCustomResource();
94-
res.setMetadata(new ObjectMetaBuilder()
95-
.withName(RESOURCE_NAME_PREFIX + index)
96-
.build());
97-
res.setSpec(new BoundedCacheTestSpec());
98-
res.getSpec().setData(INITIAL_DATA_PREFIX + index);
99-
return res;
100-
}
78+
abstract P createTestResource(int index);
79+
80+
abstract Class<P> customResourceClass();
81+
82+
abstract LocallyRunOperatorExtension extension();
10183

10284
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.javaoperatorsdk.operator.processing.event.source.cache;
2+
3+
import java.time.Duration;
4+
5+
import org.junit.jupiter.api.extension.RegisterExtension;
6+
7+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
8+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
9+
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
10+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.clusterscope.BoundedCacheClusterScopeTestCustomResource;
11+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.clusterscope.BoundedCacheClusterScopeTestReconciler;
12+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestSpec;
13+
14+
public class CaffeinBoundedCacheClusterScopeIT
15+
extends BoundedCacheTestBase<BoundedCacheClusterScopeTestCustomResource> {
16+
17+
@RegisterExtension
18+
LocallyRunOperatorExtension extension =
19+
LocallyRunOperatorExtension.builder()
20+
.withReconciler(new BoundedCacheClusterScopeTestReconciler(), o -> {
21+
o.withItemStore(CaffeinBoundedItemStores.boundedItemStore(
22+
new KubernetesClientBuilder().build(),
23+
BoundedCacheClusterScopeTestCustomResource.class,
24+
Duration.ofMinutes(1),
25+
1));
26+
})
27+
.build();
28+
29+
@Override
30+
BoundedCacheClusterScopeTestCustomResource createTestResource(int index) {
31+
var res = new BoundedCacheClusterScopeTestCustomResource();
32+
res.setMetadata(new ObjectMetaBuilder()
33+
.withName(RESOURCE_NAME_PREFIX + index)
34+
.build());
35+
res.setSpec(new BoundedCacheTestSpec());
36+
res.getSpec().setData(INITIAL_DATA_PREFIX + index);
37+
return res;
38+
}
39+
40+
@Override
41+
Class<BoundedCacheClusterScopeTestCustomResource> customResourceClass() {
42+
return BoundedCacheClusterScopeTestCustomResource.class;
43+
}
44+
45+
@Override
46+
LocallyRunOperatorExtension extension() {
47+
return extension;
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.javaoperatorsdk.operator.processing.event.source.cache;
2+
3+
import java.time.Duration;
4+
5+
import org.junit.jupiter.api.extension.RegisterExtension;
6+
7+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
8+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
9+
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
10+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestCustomResource;
11+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestReconciler;
12+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestSpec;
13+
14+
import static io.javaoperatorsdk.operator.processing.event.source.cache.BoundedCacheTestBase.INITIAL_DATA_PREFIX;
15+
import static io.javaoperatorsdk.operator.processing.event.source.cache.BoundedCacheTestBase.RESOURCE_NAME_PREFIX;
16+
17+
class CaffeinBoundedCacheNamespacedIT extends BoundedCacheTestBase<BoundedCacheTestCustomResource> {
18+
19+
@RegisterExtension
20+
LocallyRunOperatorExtension extension =
21+
LocallyRunOperatorExtension.builder().withReconciler(new BoundedCacheTestReconciler(), o -> {
22+
o.withItemStore(CaffeinBoundedItemStores.boundedItemStore(
23+
new KubernetesClientBuilder().build(), BoundedCacheTestCustomResource.class,
24+
Duration.ofMinutes(1),
25+
1));
26+
})
27+
.build();
28+
29+
BoundedCacheTestCustomResource createTestResource(int index) {
30+
var res = new BoundedCacheTestCustomResource();
31+
res.setMetadata(new ObjectMetaBuilder()
32+
.withName(RESOURCE_NAME_PREFIX + index)
33+
.build());
34+
res.setSpec(new BoundedCacheTestSpec());
35+
res.getSpec().setData(INITIAL_DATA_PREFIX + index);
36+
return res;
37+
}
38+
39+
@Override
40+
Class<BoundedCacheTestCustomResource> customResourceClass() {
41+
return BoundedCacheTestCustomResource.class;
42+
}
43+
44+
@Override
45+
LocallyRunOperatorExtension extension() {
46+
return extension;
47+
}
48+
49+
}
Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,38 @@
66
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
88

9-
import io.fabric8.kubernetes.api.model.ConfigMap;
10-
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
11-
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
9+
import io.fabric8.kubernetes.api.model.*;
10+
import io.fabric8.kubernetes.client.CustomResource;
1211
import io.fabric8.kubernetes.client.KubernetesClient;
1312
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
1413
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
1514
import io.javaoperatorsdk.operator.api.reconciler.*;
15+
import io.javaoperatorsdk.operator.api.reconciler.Context;
1616
import io.javaoperatorsdk.operator.junit.KubernetesClientAware;
1717
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
1818
import io.javaoperatorsdk.operator.processing.event.source.cache.CaffeinBoundedItemStores;
19+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.clusterscope.BoundedCacheClusterScopeTestReconciler;
20+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestSpec;
21+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestStatus;
1922
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
23+
import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers;
2024

21-
@ControllerConfiguration
22-
public class BoundedCacheTestReconciler implements Reconciler<BoundedCacheTestCustomResource>,
23-
EventSourceInitializer<BoundedCacheTestCustomResource>, KubernetesClientAware {
25+
public abstract class AbstractTestReconciler<P extends CustomResource<BoundedCacheTestSpec, BoundedCacheTestStatus>>
26+
implements KubernetesClientAware, Reconciler<P>,
27+
EventSourceInitializer<P> {
2428

25-
private static final Logger log = LoggerFactory.getLogger(BoundedCacheTestReconciler.class);
29+
private static final Logger log =
30+
LoggerFactory.getLogger(BoundedCacheClusterScopeTestReconciler.class);
2631

2732
public static final String DATA_KEY = "dataKey";
28-
private KubernetesClient client;
33+
public static final String DEFAULT_NAMESPACE = "default";
34+
35+
protected KubernetesClient client;
2936

3037
@Override
31-
public UpdateControl<BoundedCacheTestCustomResource> reconcile(
32-
BoundedCacheTestCustomResource resource,
33-
Context<BoundedCacheTestCustomResource> context) {
38+
public UpdateControl<P> reconcile(
39+
P resource,
40+
Context<P> context) {
3441
var maybeConfigMap = context.getSecondaryResource(ConfigMap.class);
3542
maybeConfigMap.ifPresentOrElse(
3643
cm -> updateConfigMapIfNeeded(cm, resource),
@@ -40,55 +47,70 @@ public UpdateControl<BoundedCacheTestCustomResource> reconcile(
4047
return UpdateControl.patchStatus(resource);
4148
}
4249

43-
private void updateConfigMapIfNeeded(ConfigMap cm, BoundedCacheTestCustomResource resource) {
50+
protected void updateConfigMapIfNeeded(ConfigMap cm, P resource) {
4451
var data = cm.getData().get(DATA_KEY);
4552
if (data == null || data.equals(resource.getSpec().getData())) {
4653
cm.setData(Map.of(DATA_KEY, resource.getSpec().getData()));
4754
client.configMaps().resource(cm).replace();
4855
}
4956
}
5057

51-
private void createConfigMap(BoundedCacheTestCustomResource resource) {
58+
protected void createConfigMap(P resource) {
5259
var cm = new ConfigMapBuilder()
5360
.withMetadata(new ObjectMetaBuilder()
5461
.withName(resource.getMetadata().getName())
55-
.withNamespace(resource.getMetadata().getNamespace())
62+
.withNamespace(resource instanceof Namespaced ? resource.getMetadata().getNamespace()
63+
: DEFAULT_NAMESPACE)
5664
.build())
5765
.withData(Map.of(DATA_KEY, resource.getSpec().getData()))
5866
.build();
59-
cm.addOwnerReference(resource);
67+
68+
if (resource instanceof Namespaced) {
69+
cm.getMetadata()
70+
.setLabels(Map.of(Mappers.DEFAULT_ANNOTATION_FOR_NAME, resource.getMetadata().getName()));
71+
} else {
72+
cm.addOwnerReference(resource);
73+
}
74+
75+
6076
client.configMaps().resource(cm).create();
6177
}
6278

79+
@Override
80+
public KubernetesClient getKubernetesClient() {
81+
return client;
82+
}
83+
84+
@Override
85+
public void setKubernetesClient(KubernetesClient kubernetesClient) {
86+
this.client = kubernetesClient;
87+
}
88+
6389
@Override
6490
public Map<String, EventSource> prepareEventSources(
65-
EventSourceContext<BoundedCacheTestCustomResource> context) {
91+
EventSourceContext<P> context) {
6692

6793
var boundedItemStore =
6894
CaffeinBoundedItemStores.boundedItemStore(new KubernetesClientBuilder().build(),
6995
ConfigMap.class, Duration.ofMinutes(1),
7096
1);
7197

7298
var es = new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class, context)
99+
.withSecondaryToPrimaryMapper(
100+
Namespaced.class.isAssignableFrom(customResourceClass()) ? Mappers.fromOwnerReference()
101+
: Mappers.fromDefaultAnnotations())
73102
.withItemStore(boundedItemStore)
74103
.build(), context);
75104

76105
return EventSourceInitializer.nameEventSources(es);
77106
}
78107

79-
private void ensureStatus(BoundedCacheTestCustomResource resource) {
108+
private void ensureStatus(P resource) {
80109
if (resource.getStatus() == null) {
81110
resource.setStatus(new BoundedCacheTestStatus());
82111
}
83112
}
84113

85-
@Override
86-
public KubernetesClient getKubernetesClient() {
87-
return client;
88-
}
114+
protected abstract Class<P> customResourceClass();
89115

90-
@Override
91-
public void setKubernetesClient(KubernetesClient kubernetesClient) {
92-
this.client = kubernetesClient;
93-
}
94116
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javaoperatorsdk.operator.processing.event.source.cache.sample.clusterscope;
2+
3+
import io.fabric8.kubernetes.client.CustomResource;
4+
import io.fabric8.kubernetes.model.annotation.Group;
5+
import io.fabric8.kubernetes.model.annotation.ShortNames;
6+
import io.fabric8.kubernetes.model.annotation.Version;
7+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestSpec;
8+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope.BoundedCacheTestStatus;
9+
10+
@Group("sample.javaoperatorsdk")
11+
@Version("v1")
12+
@ShortNames("bccs")
13+
public class BoundedCacheClusterScopeTestCustomResource
14+
extends CustomResource<BoundedCacheTestSpec, BoundedCacheTestStatus> {
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.javaoperatorsdk.operator.processing.event.source.cache.sample.clusterscope;
2+
3+
import io.javaoperatorsdk.operator.api.reconciler.*;
4+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.AbstractTestReconciler;
5+
6+
@ControllerConfiguration
7+
public class BoundedCacheClusterScopeTestReconciler extends
8+
AbstractTestReconciler<BoundedCacheClusterScopeTestCustomResource> {
9+
10+
@Override
11+
protected Class<BoundedCacheClusterScopeTestCustomResource> customResourceClass() {
12+
return BoundedCacheClusterScopeTestCustomResource.class;
13+
}
14+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.javaoperatorsdk.operator.processing.event.source.cache.sample;
1+
package io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope;
22

33
import io.fabric8.kubernetes.api.model.Namespaced;
44
import io.fabric8.kubernetes.client.CustomResource;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.javaoperatorsdk.operator.processing.event.source.cache.sample.namespacescope;
2+
3+
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
4+
import io.javaoperatorsdk.operator.processing.event.source.cache.sample.AbstractTestReconciler;
5+
6+
@ControllerConfiguration
7+
public class BoundedCacheTestReconciler
8+
extends AbstractTestReconciler<BoundedCacheTestCustomResource> {
9+
10+
@Override
11+
protected Class<BoundedCacheTestCustomResource> customResourceClass() {
12+
return BoundedCacheTestCustomResource.class;
13+
}
14+
}

0 commit comments

Comments
 (0)