Skip to content

Commit a8137e5

Browse files
authored
fix: allow configuration of field manager / item store (#783)
Fixes #780 Signed-off-by: Chris Laprun <[email protected]>
1 parent bebcb15 commit a8137e5

File tree

6 files changed

+99
-11
lines changed

6 files changed

+99
-11
lines changed

core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/QuarkusControllerConfigurationBuildStep.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.fabric8.kubernetes.api.model.HasMetadata;
1616
import io.fabric8.kubernetes.api.model.rbac.PolicyRule;
1717
import io.fabric8.kubernetes.api.model.rbac.PolicyRuleBuilder;
18+
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
1819
import io.javaoperatorsdk.operator.ReconcilerUtils;
1920
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
2021
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver;
@@ -169,6 +170,8 @@ static QuarkusControllerConfiguration createConfiguration(
169170
Class<? extends RateLimiter> rateLimiterClass = DefaultRateLimiter.class;
170171
Class<?> rateLimiterConfigurationClass = null;
171172
Long nullableInformerListLimit = null;
173+
String fieldManager = null;
174+
ItemStore<?> itemStore = null;
172175
if (controllerAnnotation != null) {
173176
final var intervalFromAnnotation = ConfigurationUtils.annotationValueOrDefault(
174177
controllerAnnotation, "maxReconciliationInterval", AnnotationValue::asNested,
@@ -207,6 +210,10 @@ static QuarkusControllerConfiguration createConfiguration(
207210
nullableInformerListLimit = ConfigurationUtils.annotationValueOrDefault(
208211
controllerAnnotation, "informerListLimit", AnnotationValue::asLong,
209212
() -> null);
213+
fieldManager = ConfigurationUtils.annotationValueOrDefault(controllerAnnotation, "fieldManager",
214+
AnnotationValue::asString, () -> null);
215+
itemStore = ConfigurationUtils.instantiateImplementationClass(controllerAnnotation, "itemStore", ItemStore.class,
216+
ItemStore.class, true, index);
210217
}
211218

212219
// check if we have additional RBAC rules to handle
@@ -266,7 +273,7 @@ static QuarkusControllerConfiguration createConfiguration(
266273
finalFilter,
267274
maxReconciliationInterval,
268275
onAddFilter, onUpdateFilter, genericFilter, retryClass, retryConfigurationClass, rateLimiterClass,
269-
rateLimiterConfigurationClass, dependentResources, null, additionalRBACRules);
276+
rateLimiterConfigurationClass, dependentResources, null, additionalRBACRules, fieldManager, itemStore);
270277

271278
if (hasDependents) {
272279
dependentResourceInfos.forEach(dependent -> {

core/runtime/src/main/java/io/quarkiverse/operatorsdk/runtime/QuarkusControllerConfiguration.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import io.fabric8.kubernetes.api.model.HasMetadata;
99
import io.fabric8.kubernetes.api.model.rbac.PolicyRule;
10+
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
1011
import io.javaoperatorsdk.operator.ReconcilerUtils;
1112
import io.javaoperatorsdk.operator.api.config.AnnotationConfigurable;
1213
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
@@ -74,6 +75,8 @@ public DefaultRateLimiter(Duration refreshPeriod, int limitForPeriod) {
7475
private final Optional<OnUpdateFilter<? super R>> onUpdateFilter;
7576
private final Optional<GenericFilter<? super R>> genericFilter;
7677
private final List<PolicyRule> additionalRBACRules;
78+
private final String fieldManager;
79+
private final Optional<ItemStore<R>> itemStore;
7780
private Class<? extends Annotation> retryConfigurationClass;
7881
private Class<? extends Retry> retryClass;
7982
private Class<? extends Annotation> rateLimiterConfigurationClass;
@@ -107,7 +110,7 @@ public QuarkusControllerConfiguration(
107110
Class<? extends Retry> retryClass, Class<? extends Annotation> retryConfigurationClass,
108111
Class<? extends RateLimiter> rateLimiterClass, Class<? extends Annotation> rateLimiterConfigurationClass,
109112
Map<String, DependentResourceSpecMetadata<?, ?, ?>> dependentsMetadata, ManagedWorkflow<R> workflow,
110-
List<PolicyRule> additionalRBACRules) {
113+
List<PolicyRule> additionalRBACRules, String fieldManager, ItemStore<R> nullableItemStore) {
111114
this.associatedReconcilerClassName = associatedReconcilerClassName;
112115
this.name = name;
113116
this.resourceTypeName = resourceTypeName;
@@ -138,6 +141,9 @@ public QuarkusControllerConfiguration(
138141
this.rateLimiterClass = rateLimiterClass;
139142
this.rateLimiter = DefaultRateLimiter.class.equals(rateLimiterClass) ? new DefaultRateLimiter() : null;
140143
this.rateLimiterConfigurationClass = rateLimiterConfigurationClass;
144+
145+
this.fieldManager = fieldManager != null ? fieldManager : ControllerConfiguration.super.fieldManager();
146+
this.itemStore = Optional.ofNullable(nullableItemStore);
141147
}
142148

143149
@Override
@@ -409,4 +415,26 @@ private void configure(Class<? extends Reconciler> reconcilerClass, Class<? exte
409415
public List<PolicyRule> getAdditionalRBACRules() {
410416
return additionalRBACRules;
411417
}
418+
419+
@SuppressWarnings("unused")
420+
// this is needed by Quarkus for the RecordableConstructor
421+
public String getFieldManager() {
422+
return fieldManager;
423+
}
424+
425+
@Override
426+
public String fieldManager() {
427+
return fieldManager;
428+
}
429+
430+
@Override
431+
public Optional<ItemStore<R>> getItemStore() {
432+
return itemStore;
433+
}
434+
435+
@SuppressWarnings("unused")
436+
// this is needed by Quarkus for the RecordableConstructor
437+
public ItemStore<R> getNullableItemStore() {
438+
return itemStore.orElse(null);
439+
}
412440
}

integration-tests/src/main/java/io/quarkiverse/operatorsdk/it/CustomRateLimiterReconciler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
77
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
88

9-
@ControllerConfiguration(name = CustomRateLimiterReconciler.NAME, rateLimiter = CustomRateLimiter.class)
9+
@ControllerConfiguration(name = CustomRateLimiterReconciler.NAME, rateLimiter = CustomRateLimiter.class, itemStore = NullItemStore.class)
1010
@CustomRateConfiguration(42)
1111
public class CustomRateLimiterReconciler implements Reconciler<ResourceQuota> {
1212

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package io.quarkiverse.operatorsdk.it;
2+
3+
import java.util.stream.Stream;
4+
5+
import io.fabric8.kubernetes.api.model.ResourceQuota;
6+
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
7+
import io.quarkus.runtime.annotations.RegisterForReflection;
8+
9+
@RegisterForReflection // for proper serialization in native mode
10+
public class NullItemStore implements ItemStore<ResourceQuota> {
11+
12+
public static final String NAME = "NullItemStoreName";
13+
14+
// so that it appears in the JSON configuration and we can check against it
15+
public String getName() {
16+
return NAME;
17+
}
18+
19+
@Override
20+
public String getKey(ResourceQuota resourceQuota) {
21+
return null;
22+
}
23+
24+
@Override
25+
public ResourceQuota put(String s, ResourceQuota resourceQuota) {
26+
return null;
27+
}
28+
29+
@Override
30+
public ResourceQuota remove(String s) {
31+
return null;
32+
}
33+
34+
@Override
35+
public Stream<String> keySet() {
36+
return null;
37+
}
38+
39+
@Override
40+
public Stream<ResourceQuota> values() {
41+
return null;
42+
}
43+
44+
@Override
45+
public int size() {
46+
return 0;
47+
}
48+
49+
@Override
50+
public ResourceQuota get(String s) {
51+
return null;
52+
}
53+
}

integration-tests/src/main/java/io/quarkiverse/operatorsdk/it/OperatorSDKResource.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.fasterxml.jackson.annotation.JsonProperty;
1919

2020
import io.fabric8.kubernetes.api.model.HasMetadata;
21+
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
2122
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
2223
import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
2324
import io.javaoperatorsdk.operator.api.config.Version;
@@ -230,6 +231,10 @@ public long maxReconciliationIntervalSeconds() {
230231
public RateLimiter getRateLimiter() {
231232
return conf.getRateLimiter();
232233
}
234+
235+
public ItemStore<?> getItemStore() {
236+
return conf.getItemStore().orElse(null);
237+
}
233238
}
234239

235240
static class JSONDependentResourceSpec {

integration-tests/src/test/java/io/quarkiverse/operatorsdk/it/OperatorSDKResourceTest.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@
22

33
import static io.restassured.RestAssured.given;
44
import static org.hamcrest.MatcherAssert.assertThat;
5-
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
6-
import static org.hamcrest.Matchers.equalTo;
7-
import static org.hamcrest.Matchers.hasItem;
8-
import static org.hamcrest.Matchers.hasItems;
9-
import static org.hamcrest.Matchers.hasSize;
10-
import static org.hamcrest.Matchers.is;
11-
import static org.hamcrest.Matchers.startsWith;
5+
import static org.hamcrest.Matchers.*;
126

137
import org.junit.jupiter.api.BeforeAll;
148
import org.junit.jupiter.api.Test;
@@ -289,6 +283,7 @@ void customRateLimiterConfiguredViaCustomAnnotationShouldWork() {
289283
.then()
290284
.statusCode(200)
291285
.body(
292-
"rateLimiter.value", equalTo(42));
286+
"rateLimiter.value", equalTo(42),
287+
"itemStore.name", equalTo(NullItemStore.NAME));
293288
}
294289
}

0 commit comments

Comments
 (0)