Skip to content

Commit 45b187d

Browse files
authored
fix: decouple DependentResource creation from configuration (#883)
The idea is to delay instantiation until needed and rely on DependentResourceControllerFactory for this purpose instead. Not sure if we actually need to use an interface there or not.
1 parent eeea472 commit 45b187d

File tree

11 files changed

+181
-106
lines changed

11 files changed

+181
-106
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ default ResourceEventFilter<R> getEventFilter() {
4848
return ResourceEventFilters.passthrough();
4949
}
5050

51-
default List<DependentResource> getDependentResources() {
51+
default List<DependentResourceConfiguration> getDependentResources() {
5252
return Collections.emptyList();
5353
}
5454

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class DefaultControllerConfiguration<R extends HasMetadata>
1818
private final boolean generationAware;
1919
private final RetryConfiguration retryConfiguration;
2020
private final ResourceEventFilter<R> resourceEventFilter;
21-
private final List<DependentResource> dependents;
21+
private final List<DependentResourceConfiguration> dependents;
2222

2323
// NOSONAR constructor is meant to provide all information
2424
public DefaultControllerConfiguration(
@@ -33,7 +33,7 @@ public DefaultControllerConfiguration(
3333
ResourceEventFilter<R> resourceEventFilter,
3434
Class<R> resourceClass,
3535
ConfigurationService service,
36-
List<DependentResource> dependents) {
36+
List<DependentResourceConfiguration> dependents) {
3737
super(labelSelector, resourceClass, namespaces);
3838
this.associatedControllerClassName = associatedControllerClassName;
3939
this.name = name;
@@ -96,7 +96,7 @@ public ResourceEventFilter<R> getEventFilter() {
9696
}
9797

9898
@Override
99-
public List<DependentResource> getDependentResources() {
99+
public List<DependentResourceConfiguration> getDependentResources() {
100100
return dependents;
101101
}
102102
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ public DefaultResourceConfiguration(String labelSelector, Class<R> resourceClass
2323
public DefaultResourceConfiguration(String labelSelector, Class<R> resourceClass,
2424
Set<String> namespaces) {
2525
this.labelSelector = labelSelector;
26-
this.resourceClass = resourceClass == null ? ResourceConfiguration.super.getResourceClass()
27-
: resourceClass;
26+
this.resourceClass = resourceClass;
2827
this.namespaces = namespaces != null ? namespaces : Collections.emptySet();
2928
this.watchAllNamespaces = this.namespaces.isEmpty();
3029
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.javaoperatorsdk.operator.api.config;
2+
3+
import io.fabric8.kubernetes.api.model.HasMetadata;
4+
5+
public interface DependentResourceConfiguration<R, P extends HasMetadata> {
6+
7+
Class<? extends DependentResource<R, P>> getDependentResourceClass();
8+
9+
Class<R> getResourceClass();
10+
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
import io.fabric8.kubernetes.api.model.HasMetadata;
44
import io.javaoperatorsdk.operator.api.config.DependentResource;
5+
import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration;
56
import io.javaoperatorsdk.operator.api.reconciler.Context;
67
import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
78
import io.javaoperatorsdk.operator.processing.event.source.EventSource;
89

9-
public class DependentResourceController<R, P extends HasMetadata>
10+
public class DependentResourceController<R, P extends HasMetadata, C extends DependentResourceConfiguration<R, P>>
1011
implements DependentResource<R, P>, Builder<R, P>, Updater<R, P>, Persister<R, P>,
1112
Cleaner<R, P> {
1213

@@ -15,14 +16,16 @@ public class DependentResourceController<R, P extends HasMetadata>
1516
private final Cleaner<R, P> cleaner;
1617
private final Persister<R, P> persister;
1718
private final DependentResource<R, P> delegate;
19+
private final C configuration;
1820

1921
@SuppressWarnings("unchecked")
20-
public DependentResourceController(DependentResource<R, P> delegate) {
22+
public DependentResourceController(DependentResource<R, P> delegate, C configuration) {
2123
this.delegate = delegate;
2224
builder = (delegate instanceof Builder) ? (Builder<R, P>) delegate : null;
2325
updater = (delegate instanceof Updater) ? (Updater<R, P>) delegate : null;
2426
cleaner = (delegate instanceof Cleaner) ? (Cleaner<R, P>) delegate : null;
2527
persister = initPersister(delegate);
28+
this.configuration = configuration;
2629
}
2730

2831
@SuppressWarnings("unchecked")
@@ -84,4 +87,8 @@ public void createOrReplace(R dependentResource, Context context) {
8487
public R getFor(P primary, Context context) {
8588
return persister.getFor(primary, context);
8689
}
90+
91+
public C getConfiguration() {
92+
return configuration;
93+
}
8794
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
package io.javaoperatorsdk.operator.api.reconciler.dependent;
22

3+
import java.lang.reflect.InvocationTargetException;
4+
35
import io.fabric8.kubernetes.api.model.HasMetadata;
4-
import io.javaoperatorsdk.operator.api.config.DependentResource;
6+
import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration;
57

68
public interface DependentResourceControllerFactory<P extends HasMetadata> {
79

8-
default <R> DependentResourceController<R, P> from(DependentResource<R, P> dependent) {
9-
// todo: this needs to be cleaned-up / redesigned
10-
return dependent instanceof DependentResourceController
11-
? (DependentResourceController<R, P>) dependent
12-
: new DependentResourceController<>(dependent);
10+
default <T extends DependentResourceController<R, P, C>, R, C extends DependentResourceConfiguration<R, P>> T from(
11+
C config) {
12+
try {
13+
final var dependentResource = config.getDependentResourceClass().getConstructor()
14+
.newInstance();
15+
if (config instanceof KubernetesDependentResourceConfiguration) {
16+
return (T) new KubernetesDependentResourceController(dependentResource,
17+
(KubernetesDependentResourceConfiguration) config);
18+
} else {
19+
return (T) new DependentResourceController(dependentResource, config);
20+
}
21+
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException
22+
| IllegalAccessException e) {
23+
throw new IllegalArgumentException(e);
24+
}
1325
}
1426
}

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

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,64 @@
44

55
import io.fabric8.kubernetes.api.model.HasMetadata;
66
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
7+
import io.javaoperatorsdk.operator.api.config.DependentResource;
8+
import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration;
79
import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier;
810
import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever;
911
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerConfiguration;
1012

11-
public class KubernetesDependentResourceConfiguration<R extends HasMetadata, P extends HasMetadata>
12-
extends InformerConfiguration<R, P> {
13+
public interface KubernetesDependentResourceConfiguration<R extends HasMetadata, P extends HasMetadata>
14+
extends InformerConfiguration<R, P>, DependentResourceConfiguration<R, P> {
1315

14-
private final boolean owned;
16+
class DefaultKubernetesDependentResourceConfiguration<R extends HasMetadata, P extends HasMetadata>
17+
extends DefaultInformerConfiguration<R, P>
18+
implements KubernetesDependentResourceConfiguration<R, P> {
1519

16-
protected KubernetesDependentResourceConfiguration(
17-
ConfigurationService service,
18-
String labelSelector, Class<R> resourceClass,
19-
PrimaryResourcesRetriever<R> secondaryToPrimaryResourcesIdSet,
20-
AssociatedSecondaryResourceIdentifier<P> associatedWith,
21-
boolean skipUpdateEventPropagationIfNoChange, Set<String> namespaces, boolean owned) {
22-
super(service, labelSelector, resourceClass, secondaryToPrimaryResourcesIdSet, associatedWith,
23-
skipUpdateEventPropagationIfNoChange, namespaces);
24-
this.owned = owned;
20+
private final boolean owned;
21+
private final Class<DependentResource<R, P>> dependentResourceClass;
22+
23+
protected DefaultKubernetesDependentResourceConfiguration(
24+
ConfigurationService service,
25+
String labelSelector, Class<R> resourceClass,
26+
PrimaryResourcesRetriever<R> secondaryToPrimaryResourcesIdSet,
27+
AssociatedSecondaryResourceIdentifier<P> associatedWith,
28+
boolean skipUpdateEventPropagationIfNoChange, Set<String> namespaces, boolean owned,
29+
Class<DependentResource<R, P>> dependentResourceClass) {
30+
super(service, labelSelector, resourceClass, secondaryToPrimaryResourcesIdSet, associatedWith,
31+
skipUpdateEventPropagationIfNoChange, namespaces);
32+
this.owned = owned;
33+
this.dependentResourceClass = dependentResourceClass;
34+
}
35+
36+
public boolean isOwned() {
37+
return owned;
38+
}
39+
40+
@Override
41+
public Class<? extends DependentResource<R, P>> getDependentResourceClass() {
42+
return dependentResourceClass;
43+
}
44+
45+
@Override
46+
public Class<R> getResourceClass() {
47+
return super.getResourceClass();
48+
}
2549
}
2650

27-
public static <R extends HasMetadata, P extends HasMetadata> KubernetesDependentResourceConfiguration<R, P> from(
28-
InformerConfiguration<R, P> cfg, boolean owned) {
29-
return new KubernetesDependentResourceConfiguration<>(cfg.getConfigurationService(),
51+
static <R extends HasMetadata, P extends HasMetadata> KubernetesDependentResourceConfiguration<R, P> from(
52+
InformerConfiguration<R, P> cfg, boolean owned,
53+
Class<? extends DependentResource> dependentResourceClass) {
54+
return new DefaultKubernetesDependentResourceConfiguration<R, P>(cfg.getConfigurationService(),
3055
cfg.getLabelSelector(), cfg.getResourceClass(), cfg.getPrimaryResourcesRetriever(),
3156
cfg.getAssociatedResourceIdentifier(), cfg.isSkipUpdateEventPropagationIfNoChange(),
32-
cfg.getNamespaces(), owned);
57+
cfg.getNamespaces(), owned,
58+
(Class<DependentResource<R, P>>) dependentResourceClass);
3359
}
3460

35-
public boolean isOwned() {
36-
return owned;
61+
boolean isOwned();
62+
63+
@Override
64+
default Class<R> getResourceClass() {
65+
return InformerConfiguration.super.getResourceClass();
3766
}
3867
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@
1212
import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
1313

1414
public class KubernetesDependentResourceController<R extends HasMetadata, P extends HasMetadata>
15-
extends DependentResourceController<R, P> {
15+
extends DependentResourceController<R, P, KubernetesDependentResourceConfiguration<R, P>> {
16+
1617
private final KubernetesDependentResourceConfiguration<R, P> configuration;
1718
private KubernetesClient client;
1819
private InformerEventSource<R, P> informer;
1920

2021

2122
public KubernetesDependentResourceController(DependentResource<R, P> delegate,
2223
KubernetesDependentResourceConfiguration<R, P> configuration) {
23-
super(delegate);
24+
super(delegate, configuration);
2425
// todo: check if we can validate that types actually match properly
2526
final var associatedPrimaries =
2627
(delegate instanceof PrimaryResourcesRetriever)
@@ -36,7 +37,8 @@ public KubernetesDependentResourceController(DependentResource<R, P> delegate,
3637
.withAssociatedSecondaryResourceIdentifier(associatedSecondary)
3738
.build();
3839
this.configuration =
39-
KubernetesDependentResourceConfiguration.from(augmented, configuration.isOwned());
40+
KubernetesDependentResourceConfiguration.from(augmented, configuration.isOwned(),
41+
configuration.getDependentResourceClass());
4042
}
4143

4244
@Override
@@ -69,6 +71,6 @@ public R getFor(P primary, Context context) {
6971
}
7072

7173
public boolean owned() {
72-
return configuration.isOwned();
74+
return getConfiguration().isOwned();
7375
}
7476
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import io.fabric8.kubernetes.api.model.HasMetadata;
1010
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
11-
import io.javaoperatorsdk.operator.api.config.DependentResource;
11+
import io.javaoperatorsdk.operator.api.config.DependentResourceConfiguration;
1212
import io.javaoperatorsdk.operator.api.reconciler.Context;
1313
import io.javaoperatorsdk.operator.api.reconciler.ContextInitializer;
1414
import io.javaoperatorsdk.operator.api.reconciler.DeleteControl;
@@ -42,13 +42,14 @@ public DependentResourceManager(Controller<R> controller) {
4242

4343
@Override
4444
public List<EventSource> prepareEventSources(EventSourceContext<R> context) {
45-
final List<DependentResource> configured = configuration.getDependentResources();
45+
final List<DependentResourceConfiguration> configured = configuration.getDependentResources();
4646
dependents = new ArrayList<>(configured.size());
4747

4848
List<EventSource> sources = new ArrayList<>(configured.size() + 5);
4949
configured.forEach(dependent -> {
50-
dependents.add(configuration.dependentFactory().from(dependent));
51-
sources.add(dependent.initEventSource(context));
50+
final var dependentResourceController = configuration.dependentFactory().from(dependent);
51+
dependents.add(dependentResourceController);
52+
sources.add(dependentResourceController.initEventSource(context));
5253
});
5354

5455
return sources;

0 commit comments

Comments
 (0)