24
24
public class Operator implements LifecycleAware {
25
25
private static final Logger log = LoggerFactory .getLogger (Operator .class );
26
26
27
- private final ControllerManager controllerManager ;
28
- private final LeaderElectionManager leaderElectionManager ;
29
- private final ConfigurationService configurationService ;
27
+ private ControllerManager controllerManager ;
28
+ private LeaderElectionManager leaderElectionManager ;
29
+ private ConfigurationService configurationService ;
30
30
private volatile boolean started = false ;
31
31
32
32
public Operator () {
33
- this (( KubernetesClient ) null );
33
+ init ( initConfigurationService ( null , null ), true );
34
34
}
35
35
36
36
Operator (KubernetesClient kubernetesClient ) {
37
- this (initConfigurationService (kubernetesClient , null ));
37
+ init (initConfigurationService (kubernetesClient , null ), false );
38
38
}
39
39
40
40
/**
@@ -46,12 +46,7 @@ public Operator() {
46
46
* operator
47
47
*/
48
48
public Operator (ConfigurationService configurationService ) {
49
- this .configurationService = configurationService ;
50
-
51
- final var executorServiceManager = configurationService .getExecutorServiceManager ();
52
- controllerManager = new ControllerManager (executorServiceManager );
53
-
54
- leaderElectionManager = new LeaderElectionManager (controllerManager , configurationService );
49
+ init (configurationService , false );
55
50
}
56
51
57
52
/**
@@ -62,10 +57,55 @@ public Operator(ConfigurationService configurationService) {
62
57
* {@link ConfigurationService} values
63
58
*/
64
59
public Operator (Consumer <ConfigurationServiceOverrider > overrider ) {
65
- this (initConfigurationService (null , overrider ));
60
+ init (initConfigurationService (null , overrider ), false );
61
+ }
62
+
63
+ /**
64
+ * In a deferred initialization scenario, the default constructor will typically be called to
65
+ * create a proxy instance, usually to be replaced at some later time when the dependents (in this
66
+ * case the ConfigurationService instance) are available. In this situation, we want to make it
67
+ * possible to not perform the initialization steps directly so this implementation makes it
68
+ * possible to not crash when a null ConfigurationService is passed only if deferred
69
+ * initialization is allowed
70
+ *
71
+ * @param configurationService the potentially {@code null} {@link ConfigurationService} to use
72
+ * for this operator
73
+ * @param allowDeferredInit whether or not deferred initialization of the configuration service is
74
+ * allowed
75
+ * @throws IllegalStateException if the specified configuration service is {@code null} but
76
+ * deferred initialization is not allowed
77
+ */
78
+ private void init (ConfigurationService configurationService , boolean allowDeferredInit ) {
79
+ if (configurationService == null ) {
80
+ if (!allowDeferredInit ) {
81
+ throw new IllegalStateException (
82
+ "Deferred initialization of ConfigurationService is not allowed" );
83
+ }
84
+ } else {
85
+ this .configurationService = configurationService ;
86
+
87
+ final var executorServiceManager = configurationService .getExecutorServiceManager ();
88
+ controllerManager = new ControllerManager (executorServiceManager );
89
+
90
+ leaderElectionManager = new LeaderElectionManager (controllerManager , configurationService );
91
+ }
66
92
}
67
93
68
- private static ConfigurationService initConfigurationService (
94
+ /**
95
+ * Overridable by subclasses to enable deferred configuration, useful to avoid unneeded processing
96
+ * in injection scenarios, typically returning {@code null} here instead of performing any
97
+ * configuration
98
+ *
99
+ * @param client a potentially {@code null} {@link KubernetesClient} to initialize the operator's
100
+ * {@link ConfigurationService} with
101
+ * @param overrider a potentially {@code null} {@link ConfigurationServiceOverrider} consumer to
102
+ * override the default {@link ConfigurationService} with
103
+ * @return a ready to use {@link ConfigurationService} using values provided by the specified
104
+ * overrides and kubernetes client, if provided or {@code null} in case deferred
105
+ * initialization is possible, in which case it is up to the extension to ensure that the
106
+ * {@link ConfigurationService} is properly set before the operator instance is used
107
+ */
108
+ protected ConfigurationService initConfigurationService (
69
109
KubernetesClient client , Consumer <ConfigurationServiceOverrider > overrider ) {
70
110
// initialize the client if the user didn't provide one
71
111
if (client == null ) {
@@ -232,8 +272,8 @@ public <P extends HasMetadata> RegisteredController<P> register(
232
272
*
233
273
* @param reconciler part of the reconciler to register
234
274
* @param configOverrider consumer to use to change config values
235
- * @return registered controller
236
275
* @param <P> the {@code HasMetadata} type associated with the reconciler
276
+ * @return registered controller
237
277
*/
238
278
public <P extends HasMetadata > RegisteredController <P > register (
239
279
Reconciler <P > reconciler , Consumer <ControllerConfigurationOverrider <P >> configOverrider ) {
@@ -266,4 +306,14 @@ boolean isStarted() {
266
306
public ConfigurationService getConfigurationService () {
267
307
return configurationService ;
268
308
}
309
+
310
+ /**
311
+ * Make it possible for extensions to set the {@link ConfigurationService} after the operator has
312
+ * been initialized
313
+ *
314
+ * @param configurationService the {@link ConfigurationService} to use for this operator
315
+ */
316
+ protected void setConfigurationService (ConfigurationService configurationService ) {
317
+ init (configurationService , false );
318
+ }
269
319
}
0 commit comments