Skip to content

Commit bbd3af1

Browse files
committed
feat: process the DR configuration when the spec is created
Signed-off-by: Chris Laprun <claprun@redhat.com>
1 parent a9692d5 commit bbd3af1

File tree

19 files changed

+304
-215
lines changed

19 files changed

+304
-215
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.javaoperatorsdk.operator.OperatorException;
1818
import io.javaoperatorsdk.operator.ReconcilerUtils;
1919
import io.javaoperatorsdk.operator.api.config.Utils.Configurator;
20+
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver;
2021
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
2122
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
2223
import io.javaoperatorsdk.operator.api.reconciler.Constants;
@@ -224,7 +225,13 @@ private static List<DependentResourceSpec> dependentResources(
224225
Utils.instantiate(dependent.reconcilePrecondition(), Condition.class, context),
225226
Utils.instantiate(dependent.deletePostcondition(), Condition.class, context),
226227
Utils.instantiate(dependent.activationCondition(), Condition.class, context),
227-
eventSourceName, null); // todo: actually compute the configuration
228+
eventSourceName);
229+
230+
// extract potential configuration
231+
final var configuration = DependentResourceConfigurationResolver
232+
.extractConfigurationFromConfigured(spec, parent, dependentType);
233+
spec.setConfiguration(configuration);
234+
228235
specsMap.put(dependentName, spec);
229236
}
230237
return specsMap.values().stream().toList();

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ControllerConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import io.fabric8.kubernetes.api.model.HasMetadata;
88
import io.javaoperatorsdk.operator.ReconcilerUtils;
9+
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
910
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
1011
import io.javaoperatorsdk.operator.api.reconciler.MaxReconciliationInterval;
1112
import io.javaoperatorsdk.operator.processing.event.rate.LinearRateLimiter;
@@ -100,4 +101,5 @@ default String fieldManager() {
100101
return getName();
101102
}
102103

104+
<C> C getConfigurationFor(DependentResourceSpec<?, P, C> spec);
103105
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ResolvedControllerConfiguration.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
import io.fabric8.kubernetes.api.model.HasMetadata;
1111
import io.fabric8.kubernetes.client.informers.cache.ItemStore;
12-
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationProvider;
1312
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
1413
import io.javaoperatorsdk.operator.api.config.workflow.WorkflowSpec;
1514
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
@@ -22,8 +21,7 @@
2221
@SuppressWarnings("rawtypes")
2322
public class ResolvedControllerConfiguration<P extends HasMetadata>
2423
extends DefaultResourceConfiguration<P>
25-
implements io.javaoperatorsdk.operator.api.config.ControllerConfiguration<P>,
26-
DependentResourceConfigurationProvider {
24+
implements io.javaoperatorsdk.operator.api.config.ControllerConfiguration<P> {
2725

2826
private final String name;
2927
private final boolean generationAware;
@@ -168,8 +166,15 @@ public ConfigurationService getConfigurationService() {
168166
}
169167

170168
@Override
171-
public Object getConfigurationFor(DependentResourceSpec spec) {
172-
return configurations.get(spec);
169+
@SuppressWarnings("unchecked")
170+
public <C> C getConfigurationFor(DependentResourceSpec<?, P, C> spec) {
171+
// first check if there's an overridden configuration at the controller level
172+
var config = configurations.get(spec);
173+
if (config == null) {
174+
// if not, check the spec for configuration
175+
config = spec.getConfiguration().orElse(null);
176+
}
177+
return (C) config;
173178
}
174179

175180
@Override

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/ConfigurationConverter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
public interface ConfigurationConverter<A extends Annotation, C> {
99

10-
C configFrom(A configAnnotation, ControllerConfiguration<?> parentConfiguration,
11-
DependentResourceSpec<?, ?, ?> spec, DependentResource<?, ?> dependentResource);
10+
C configFrom(A configAnnotation, DependentResourceSpec<?, ?, C> spec,
11+
ControllerConfiguration<?> parentConfiguration,
12+
Class<? extends DependentResource<?, ?>> dependentResourceClass);
1213
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceConfigurationResolver.java

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
99
import io.javaoperatorsdk.operator.api.config.Utils;
1010
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
11-
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource;
1211

1312
@SuppressWarnings({"rawtypes", "unchecked"})
1413
public class DependentResourceConfigurationResolver {
@@ -20,34 +19,11 @@ private DependentResourceConfigurationResolver() {}
2019
private static final Map<Class<? extends ConfigurationConverter>, ConfigurationConverter> knownConverters =
2120
new HashMap<>();
2221

23-
public static <C extends ControllerConfiguration<? extends HasMetadata>> void configure(
24-
DependentResource dependentResource, DependentResourceSpec spec, C parentConfiguration) {
25-
if (dependentResource instanceof ConfiguredDependentResource configurator) {
26-
final var config = configurationFor(spec, parentConfiguration, dependentResource);
27-
configurator.configureWith(config);
28-
}
29-
}
30-
31-
public static <C extends ControllerConfiguration<? extends HasMetadata>> Object configurationFor(
32-
DependentResourceSpec spec, C parentConfiguration, DependentResource dependentResource) {
3322

34-
// first check if the parent configuration has potentially already resolved the configuration
35-
if (parentConfiguration instanceof DependentResourceConfigurationProvider provider) {
36-
final var configuration = provider.getConfigurationFor(spec);
37-
if (configuration != null) {
38-
return configuration;
39-
}
40-
}
41-
42-
// find Configured-annotated class if it exists
43-
return extractConfigurationFromConfigured(spec, parentConfiguration, dependentResource);
44-
}
45-
46-
protected static <C extends ControllerConfiguration<? extends HasMetadata>> Object extractConfigurationFromConfigured(
23+
public static <C extends ControllerConfiguration<?>> Object extractConfigurationFromConfigured(
4724
DependentResourceSpec spec,
4825
C parentConfiguration,
49-
DependentResource dependentResource) {
50-
Class<? extends DependentResource> dependentResourceClass = spec.getDependentResourceClass();
26+
Class<? extends DependentResource> dependentResourceClass) {
5127
var converterAnnotationPair = converters.get(dependentResourceClass);
5228

5329
Annotation configAnnotation;
@@ -78,7 +54,8 @@ protected static <C extends ControllerConfiguration<? extends HasMetadata>> Obje
7854

7955
// always called even if the annotation is null so that implementations can provide default
8056
// values
81-
return converter.configFrom(configAnnotation, parentConfiguration, spec, dependentResource);
57+
return converter.configFrom(configAnnotation, spec, parentConfiguration,
58+
dependentResourceClass);
8259
}
8360

8461
private static ConfiguredClassPair getConfigured(

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/dependent/DependentResourceSpec.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ public class DependentResourceSpec<R, P extends HasMetadata, C> {
2525
private final Condition<?, ?> activationCondition;
2626

2727
private final String useEventSourceWithName;
28-
private final C nullableConfiguation;
28+
private C nullableConfiguation;
2929

3030
public DependentResourceSpec(Class<? extends DependentResource<R, P>> dependentResourceClass,
3131
String name, Set<String> dependsOn, Condition<?, ?> readyCondition,
3232
Condition<?, ?> reconcileCondition, Condition<?, ?> deletePostCondition,
33-
Condition<?, ?> activationCondition, String useEventSourceWithName, C nullableConfiguration) {
33+
Condition<?, ?> activationCondition, String useEventSourceWithName) {
3434
this.dependentResourceClass = dependentResourceClass;
3535
this.name = name;
3636
this.dependsOn = dependsOn;
@@ -39,7 +39,6 @@ public DependentResourceSpec(Class<? extends DependentResource<R, P>> dependentR
3939
this.deletePostCondition = deletePostCondition;
4040
this.activationCondition = activationCondition;
4141
this.useEventSourceWithName = useEventSourceWithName;
42-
this.nullableConfiguation = nullableConfiguration;
4342
}
4443

4544
public Class<? extends DependentResource<R, P>> getDependentResourceClass() {
@@ -104,4 +103,8 @@ public Optional<String> getUseEventSourceWithName() {
104103
public Optional<C> getConfiguration() {
105104
return Optional.ofNullable(nullableConfiguation);
106105
}
106+
107+
public void setConfiguration(C configuration) {
108+
this.nullableConfiguation = configuration;
109+
}
107110
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/informer/InformerConfiguration.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import io.javaoperatorsdk.operator.api.config.ResourceConfiguration;
1313
import io.javaoperatorsdk.operator.api.config.Utils;
1414
import io.javaoperatorsdk.operator.processing.GroupVersionKind;
15+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericKubernetesDependentResource;
16+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.InformerConfigSpec;
1517
import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper;
1618
import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
1719
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
@@ -152,7 +154,7 @@ static boolean inheritsNamespacesFromController(Set<String> namespaces) {
152154
class InformerConfigurationBuilder<R extends HasMetadata> {
153155

154156
private final Class<R> resourceClass;
155-
private final GroupVersionKind groupVersionKind;
157+
private GroupVersionKind groupVersionKind;
156158
private final Class<? extends HasMetadata> primaryResourceClass;
157159
private String name;
158160
private PrimaryToSecondaryMapper<?> primaryToSecondaryMapper;
@@ -191,6 +193,23 @@ public InformerConfigurationBuilder<R> withName(String name) {
191193
return this;
192194
}
193195

196+
@SuppressWarnings("unchecked")
197+
public InformerConfigurationBuilder<R> withConfig(InformerConfigSpec<R> spec) {
198+
groupVersionKind = spec.groupVersionKind();
199+
if (groupVersionKind != null
200+
&& !GenericKubernetesResource.class.isAssignableFrom(resourceClass)) {
201+
throw new IllegalStateException("If GroupVersionKind is set, the resource type must be "
202+
+ GenericKubernetesDependentResource.class.getSimpleName());
203+
}
204+
205+
return withGenericFilter(spec.genericFilter())
206+
.withLabelSelector(spec.labelSelector())
207+
.withNamespaces(spec.namespaces())
208+
.withOnAddFilter(spec.onAddFilter())
209+
.withOnUpdateFilter(spec.onUpdateFilter())
210+
.withOnDeleteFilter(spec.onDeleteFilter());
211+
}
212+
194213
public <P extends HasMetadata> InformerConfigurationBuilder<R> withPrimaryToSecondaryMapper(
195214
PrimaryToSecondaryMapper<P> primaryToSecondaryMapper) {
196215
this.primaryToSecondaryMapper = primaryToSecondaryMapper;

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/DependentResourceFactory.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,28 @@
33
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
44
import io.javaoperatorsdk.operator.api.config.Utils;
55
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
6-
7-
import static io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver.configure;
6+
import io.javaoperatorsdk.operator.api.reconciler.dependent.managed.ConfiguredDependentResource;
87

98
@SuppressWarnings({"rawtypes", "unchecked"})
109
public interface DependentResourceFactory<C extends ControllerConfiguration<?>> {
1110

1211
DependentResourceFactory DEFAULT = new DependentResourceFactory() {};
1312

14-
default DependentResource createFrom(DependentResourceSpec spec, C configuration) {
13+
default DependentResource createFrom(DependentResourceSpec spec, C controllerConfiguration) {
1514
final var dependentResourceClass = spec.getDependentResourceClass();
1615
return Utils.instantiateAndConfigureIfNeeded(dependentResourceClass,
1716
DependentResource.class,
18-
Utils.contextFor(configuration, dependentResourceClass, Dependent.class),
19-
(instance) -> configure(instance, spec, configuration));
17+
Utils.contextFor(controllerConfiguration, dependentResourceClass, Dependent.class),
18+
(instance) -> configure(instance, spec, controllerConfiguration));
19+
}
20+
21+
default void configure(DependentResource instance, DependentResourceSpec spec,
22+
C controllerConfiguration) {
23+
if (instance instanceof ConfiguredDependentResource configurable) {
24+
final var config = controllerConfiguration.getConfigurationFor(spec);
25+
if (config != null) {
26+
configurable.configureWith(config);
27+
}
28+
}
2029
}
2130
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/ConfiguredDependentResource.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Optional;
44

5+
56
public interface ConfiguredDependentResource<C> {
67
void configureWith(C config);
78

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package io.javaoperatorsdk.operator.processing.dependent.kubernetes;
2+
3+
import java.util.Set;
4+
5+
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
6+
import io.javaoperatorsdk.operator.api.reconciler.Constants;
7+
import io.javaoperatorsdk.operator.processing.GroupVersionKind;
8+
import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper;
9+
import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
10+
import io.javaoperatorsdk.operator.processing.event.source.filter.GenericFilter;
11+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnAddFilter;
12+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnDeleteFilter;
13+
import io.javaoperatorsdk.operator.processing.event.source.filter.OnUpdateFilter;
14+
15+
16+
public class InformerConfigSpec<R> {
17+
18+
private final String name;
19+
private final OnAddFilter<R> onAddFilter;
20+
private final OnUpdateFilter<R> onUpdateFilter;
21+
private final OnDeleteFilter<R> onDeleteFilter;
22+
private final GenericFilter<R> genericFilter;
23+
private final Set<String> namespaces;
24+
private final String labelSelector;
25+
private final GroupVersionKind groupVersionKind;
26+
private final boolean followControllerNamespacesOnChange;
27+
private final SecondaryToPrimaryMapper<R> secondaryToPrimaryMapper;
28+
private final PrimaryToSecondaryMapper<?> primaryToSecondaryMapper;
29+
30+
InformerConfigSpec(String name, SecondaryToPrimaryMapper<R> secondaryToPrimaryMapper) {
31+
this(name, Constants.SAME_AS_CONTROLLER_NAMESPACES_SET, null,
32+
InformerConfiguration.DEFAULT_FOLLOW_CONTROLLER_NAMESPACES_ON_CHANGE, null,
33+
null, null, null, null, secondaryToPrimaryMapper, null);
34+
}
35+
36+
public InformerConfigSpec(String name,
37+
Set<String> namespaces,
38+
String labelSelector,
39+
boolean followControllerNamespacesOnChange,
40+
OnAddFilter<R> onAddFilter,
41+
OnUpdateFilter<R> onUpdateFilter,
42+
OnDeleteFilter<R> onDeleteFilter,
43+
GenericFilter<R> genericFilter, GroupVersionKind groupVersionKind,
44+
SecondaryToPrimaryMapper<R> secondaryToPrimaryMapper,
45+
PrimaryToSecondaryMapper<?> primaryToSecondaryMapper) {
46+
this.name = name;
47+
this.namespaces = namespaces;
48+
this.labelSelector = labelSelector;
49+
this.followControllerNamespacesOnChange = followControllerNamespacesOnChange;
50+
this.onAddFilter = onAddFilter;
51+
this.onUpdateFilter = onUpdateFilter;
52+
this.onDeleteFilter = onDeleteFilter;
53+
this.genericFilter = genericFilter;
54+
this.groupVersionKind = groupVersionKind;
55+
this.secondaryToPrimaryMapper = secondaryToPrimaryMapper;
56+
this.primaryToSecondaryMapper = primaryToSecondaryMapper;
57+
}
58+
59+
public String name() {
60+
return name;
61+
}
62+
63+
public GroupVersionKind groupVersionKind() {
64+
return groupVersionKind;
65+
}
66+
67+
public Set<String> namespaces() {
68+
return namespaces;
69+
}
70+
71+
public String labelSelector() {
72+
return labelSelector;
73+
}
74+
75+
public boolean followControllerNamespacesOnChange() {
76+
return followControllerNamespacesOnChange;
77+
}
78+
79+
@SuppressWarnings("rawtypes")
80+
public OnAddFilter onAddFilter() {
81+
return onAddFilter;
82+
}
83+
84+
public OnUpdateFilter<R> onUpdateFilter() {
85+
return onUpdateFilter;
86+
}
87+
88+
public OnDeleteFilter<R> onDeleteFilter() {
89+
return onDeleteFilter;
90+
}
91+
92+
public GenericFilter<R> genericFilter() {
93+
return genericFilter;
94+
}
95+
96+
public SecondaryToPrimaryMapper<R> secondaryToPrimaryMapper() {
97+
return secondaryToPrimaryMapper;
98+
}
99+
100+
public PrimaryToSecondaryMapper<?> primaryToSecondaryMapper() {
101+
return primaryToSecondaryMapper;
102+
}
103+
}

0 commit comments

Comments
 (0)