14
14
import io .fabric8 .kubernetes .api .model .HasMetadata ;
15
15
import io .fabric8 .kubernetes .client .KubernetesClient ;
16
16
import io .fabric8 .kubernetes .client .informers .cache .ItemStore ;
17
- import io .javaoperatorsdk .operator .OperatorException ;
18
17
import io .javaoperatorsdk .operator .ReconcilerUtils ;
19
18
import io .javaoperatorsdk .operator .api .config .Utils .Configurator ;
20
19
import io .javaoperatorsdk .operator .api .config .dependent .DependentResourceConfigurationResolver ;
33
32
import io .javaoperatorsdk .operator .processing .retry .Retry ;
34
33
35
34
import static io .javaoperatorsdk .operator .api .config .ControllerConfiguration .CONTROLLER_NAME_AS_FIELD_MANAGER ;
36
- import static io .javaoperatorsdk .operator .api .reconciler .Constants .DEFAULT_NAMESPACES_SET ;
37
35
38
36
public class BaseConfigurationService extends AbstractConfigurationService {
39
37
@@ -57,88 +55,6 @@ public BaseConfigurationService() {
57
55
this (Utils .VERSION );
58
56
}
59
57
60
- @ SuppressWarnings ({"unchecked" , "rawtypes" })
61
- private static List <DependentResourceSpec > dependentResources (
62
- Workflow annotation ,
63
- ControllerConfiguration <?> controllerConfiguration ) {
64
- final var dependents = annotation .dependents ();
65
-
66
-
67
- if (dependents == null || dependents .length == 0 ) {
68
- return Collections .emptyList ();
69
- }
70
-
71
- final var specsMap = new LinkedHashMap <String , DependentResourceSpec >(dependents .length );
72
- for (Dependent dependent : dependents ) {
73
- final Class <? extends DependentResource > dependentType = dependent .type ();
74
-
75
- final var dependentName = getName (dependent .name (), dependentType );
76
- var spec = specsMap .get (dependentName );
77
- if (spec != null ) {
78
- throw new IllegalArgumentException (
79
- "A DependentResource named '" + dependentName + "' already exists: " + spec );
80
- }
81
-
82
- final var name = controllerConfiguration .getName ();
83
-
84
- var eventSourceName = dependent .useEventSourceWithName ();
85
- eventSourceName = Constants .NO_VALUE_SET .equals (eventSourceName ) ? null : eventSourceName ;
86
- final var context = Utils .contextFor (name , dependentType , null );
87
- spec = new DependentResourceSpec (dependentType , dependentName ,
88
- Set .of (dependent .dependsOn ()),
89
- Utils .instantiate (dependent .readyPostcondition (), Condition .class , context ),
90
- Utils .instantiate (dependent .reconcilePrecondition (), Condition .class , context ),
91
- Utils .instantiate (dependent .deletePostcondition (), Condition .class , context ),
92
- Utils .instantiate (dependent .activationCondition (), Condition .class , context ),
93
- eventSourceName );
94
-
95
- // extract potential configuration
96
- DependentResourceConfigurationResolver .configureSpecFromConfigured (spec ,
97
- controllerConfiguration ,
98
- dependentType );
99
-
100
- specsMap .put (dependentName , spec );
101
- }
102
- return specsMap .values ().stream ().toList ();
103
- }
104
-
105
- private static <T > T valueOrDefault (
106
- io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration controllerConfiguration ,
107
- Function <io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration , T > mapper ,
108
- T defaultValue ) {
109
- if (controllerConfiguration == null ) {
110
- return defaultValue ;
111
- } else {
112
- return mapper .apply (controllerConfiguration );
113
- }
114
- }
115
-
116
- @ SuppressWarnings ("rawtypes" )
117
- private static String getName (String name , Class <? extends DependentResource > dependentType ) {
118
- if (name .isBlank ()) {
119
- name = DependentResource .defaultNameFor (dependentType );
120
- }
121
- return name ;
122
- }
123
-
124
- @ SuppressWarnings ("unused" )
125
- private static <T > Configurator <T > configuratorFor (Class <T > instanceType ,
126
- Reconciler <?> reconciler ) {
127
- return instance -> configureFromAnnotatedReconciler (instance , reconciler );
128
- }
129
-
130
- @ SuppressWarnings ({"unchecked" , "rawtypes" })
131
- private static void configureFromAnnotatedReconciler (Object instance , Reconciler <?> reconciler ) {
132
- if (instance instanceof AnnotationConfigurable configurable ) {
133
- final Class <? extends Annotation > configurationClass =
134
- (Class <? extends Annotation >) Utils .getFirstTypeArgumentFromSuperClassOrInterface (
135
- instance .getClass (), AnnotationConfigurable .class );
136
- final var configAnnotation = reconciler .getClass ().getAnnotation (configurationClass );
137
- if (configAnnotation != null ) {
138
- configurable .initFrom (configAnnotation );
139
- }
140
- }
141
- }
142
58
143
59
@ Override
144
60
protected void logMissingReconcilerWarning (String reconcilerKey , String reconcilersNameMessage ) {
@@ -193,96 +109,119 @@ protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconcile
193
109
final var annotation = reconciler .getClass ().getAnnotation (
194
110
io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration .class );
195
111
196
- if (annotation == null ) {
197
- throw new OperatorException (
198
- "Missing mandatory @"
199
- + io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration .class
200
- .getSimpleName ()
201
- +
202
- " annotation for reconciler: " + reconciler );
112
+ ResolvedControllerConfiguration <P > config = controllerConfiguration (reconciler , annotation );
113
+
114
+ final var workflowAnnotation = reconciler .getClass ().getAnnotation (
115
+ io .javaoperatorsdk .operator .api .reconciler .Workflow .class );
116
+ if (workflowAnnotation != null ) {
117
+ final var specs = dependentResources (workflowAnnotation , config );
118
+ WorkflowSpec workflowSpec = new WorkflowSpec () {
119
+ @ Override
120
+ public List <DependentResourceSpec > getDependentResourceSpecs () {
121
+ return specs ;
122
+ }
123
+
124
+ @ Override
125
+ public boolean isExplicitInvocation () {
126
+ return workflowAnnotation .explicitInvocation ();
127
+ }
128
+
129
+ @ Override
130
+ public boolean handleExceptionsInReconciler () {
131
+ return workflowAnnotation .handleExceptionsInReconciler ();
132
+ }
133
+
134
+ };
135
+ config .setWorkflowSpec (workflowSpec );
203
136
}
137
+
138
+ return config ;
139
+ }
140
+
141
+ @ SuppressWarnings ({"unchecked" })
142
+ private <P extends HasMetadata > ResolvedControllerConfiguration <P > controllerConfiguration (
143
+ Reconciler <P > reconciler ,
144
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration annotation ) {
204
145
Class <Reconciler <P >> reconcilerClass = (Class <Reconciler <P >>) reconciler .getClass ();
205
146
final var resourceClass = getResourceClassResolver ().getPrimaryResourceClass (reconcilerClass );
206
147
207
148
final var name = ReconcilerUtils .getNameFor (reconciler );
208
- final var generationAware = valueOrDefault (
149
+ final var generationAware = valueOrDefaultFromAnnotation (
209
150
annotation ,
210
151
io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::generationAwareEventProcessing ,
211
- true );
152
+ "generationAwareEventProcessing" );
212
153
final var associatedReconcilerClass =
213
154
ResolvedControllerConfiguration .getAssociatedReconcilerClassName (reconciler .getClass ());
214
155
215
156
final var context = Utils .contextFor (name );
216
- final Class <? extends Retry > retryClass = annotation .retry ();
157
+ final Class <? extends Retry > retryClass =
158
+ valueOrDefaultFromAnnotation (annotation ,
159
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::retry ,
160
+ "retry" );
217
161
final var retry = Utils .instantiateAndConfigureIfNeeded (retryClass , Retry .class ,
218
162
context , configuratorFor (Retry .class , reconciler ));
219
163
220
- final Class <? extends RateLimiter > rateLimiterClass = annotation .rateLimiter ();
164
+
165
+ final Class <? extends RateLimiter > rateLimiterClass = valueOrDefaultFromAnnotation (annotation ,
166
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::rateLimiter ,
167
+ "rateLimiter" );
221
168
final var rateLimiter = Utils .instantiateAndConfigureIfNeeded (rateLimiterClass ,
222
169
RateLimiter .class , context , configuratorFor (RateLimiter .class , reconciler ));
223
170
224
- final var reconciliationInterval = annotation .maxReconciliationInterval ();
171
+ final var reconciliationInterval = valueOrDefaultFromAnnotation (annotation ,
172
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::maxReconciliationInterval ,
173
+ "maxReconciliationInterval" );
225
174
long interval = -1 ;
226
175
TimeUnit timeUnit = null ;
227
176
if (reconciliationInterval != null && reconciliationInterval .interval () > 0 ) {
228
177
interval = reconciliationInterval .interval ();
229
178
timeUnit = reconciliationInterval .timeUnit ();
230
179
}
231
180
181
+ var fieldManager = valueOrDefaultFromAnnotation (annotation ,
182
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::fieldManager ,
183
+ "fieldManager" );
232
184
final var dependentFieldManager =
233
- annotation . fieldManager () .equals (CONTROLLER_NAME_AS_FIELD_MANAGER ) ? name
234
- : annotation . fieldManager () ;
185
+ fieldManager .equals (CONTROLLER_NAME_AS_FIELD_MANAGER ) ? name
186
+ : fieldManager ;
235
187
188
+ var informerListLimitValue = valueOrDefaultFromAnnotation (annotation ,
189
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::informerListLimit ,
190
+ "informerListLimit" );
236
191
final var informerListLimit =
237
- annotation . informerListLimit () == Constants .NO_LONG_VALUE_SET ? null
238
- : annotation . informerListLimit () ;
192
+ informerListLimitValue == Constants .NO_LONG_VALUE_SET ? null
193
+ : informerListLimitValue ;
239
194
240
- final var config = new ResolvedControllerConfiguration <P >(
195
+ return new ResolvedControllerConfiguration <P >(
241
196
resourceClass , name , generationAware ,
242
197
associatedReconcilerClass , retry , rateLimiter ,
243
198
ResolvedControllerConfiguration .getMaxReconciliationInterval (interval , timeUnit ),
244
- Utils .instantiate (annotation .onAddFilter (), OnAddFilter .class , context ),
245
- Utils .instantiate (annotation .onUpdateFilter (), OnUpdateFilter .class , context ),
246
- Utils .instantiate (annotation .genericFilter (), GenericFilter .class , context ),
247
- Set .of (valueOrDefault (annotation ,
199
+ Utils .instantiate (valueOrDefaultFromAnnotation (annotation ,
200
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::onAddFilter ,
201
+ "onAddFilter" ), OnAddFilter .class , context ),
202
+ Utils .instantiate (valueOrDefaultFromAnnotation (annotation ,
203
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::onUpdateFilter ,
204
+ "onUpdateFilter" ), OnUpdateFilter .class , context ),
205
+ Utils .instantiate (valueOrDefaultFromAnnotation (annotation ,
206
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::genericFilter ,
207
+ "genericFilter" ), GenericFilter .class , context ),
208
+ Set .of (valueOrDefaultFromAnnotation (annotation ,
248
209
io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::namespaces ,
249
- DEFAULT_NAMESPACES_SET . toArray ( String []:: new ) )),
250
- valueOrDefault (annotation ,
210
+ "namespaces" )),
211
+ valueOrDefaultFromAnnotation (annotation ,
251
212
io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::finalizerName ,
252
- Constants . NO_VALUE_SET ),
253
- valueOrDefault (annotation ,
213
+ "finalizerName" ),
214
+ valueOrDefaultFromAnnotation (annotation ,
254
215
io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::labelSelector ,
255
- Constants . NO_VALUE_SET ),
216
+ "labelSelector" ),
256
217
null ,
257
- Utils .instantiate (annotation .itemStore (), ItemStore .class , context ), dependentFieldManager ,
218
+ Utils .instantiate (
219
+ valueOrDefaultFromAnnotation (annotation ,
220
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration ::itemStore ,
221
+ "itemStore" ),
222
+ ItemStore .class , context ),
223
+ dependentFieldManager ,
258
224
this , informerListLimit );
259
-
260
-
261
- final var workflowAnnotation = reconciler .getClass ().getAnnotation (
262
- io .javaoperatorsdk .operator .api .reconciler .Workflow .class );
263
- if (workflowAnnotation != null ) {
264
- final var specs = dependentResources (workflowAnnotation , config );
265
- WorkflowSpec workflowSpec = new WorkflowSpec () {
266
- @ Override
267
- public List <DependentResourceSpec > getDependentResourceSpecs () {
268
- return specs ;
269
- }
270
-
271
- @ Override
272
- public boolean isExplicitInvocation () {
273
- return workflowAnnotation .explicitInvocation ();
274
- }
275
-
276
- @ Override
277
- public boolean handleExceptionsInReconciler () {
278
- return workflowAnnotation .handleExceptionsInReconciler ();
279
- }
280
-
281
- };
282
- config .setWorkflowSpec (workflowSpec );
283
- }
284
-
285
- return config ;
286
225
}
287
226
288
227
protected boolean createIfNeeded () {
@@ -293,4 +232,48 @@ protected boolean createIfNeeded() {
293
232
public boolean checkCRDAndValidateLocalModel () {
294
233
return Utils .shouldCheckCRDAndValidateLocalModel ();
295
234
}
235
+
236
+ @ SuppressWarnings ("unchecked" )
237
+ private static <T > T valueOrDefaultFromAnnotation (
238
+ io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration controllerConfiguration ,
239
+ Function <io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration , T > mapper ,
240
+ String defaultMethodName ) {
241
+ try {
242
+ if (controllerConfiguration == null ) {
243
+ return (T ) io .javaoperatorsdk .operator .api .reconciler .ControllerConfiguration .class
244
+ .getDeclaredMethod (defaultMethodName ).getDefaultValue ();
245
+ } else {
246
+ return mapper .apply (controllerConfiguration );
247
+ }
248
+ } catch (NoSuchMethodException e ) {
249
+ throw new RuntimeException (e );
250
+ }
251
+ }
252
+
253
+ @ SuppressWarnings ("rawtypes" )
254
+ private static String getName (String name , Class <? extends DependentResource > dependentType ) {
255
+ if (name .isBlank ()) {
256
+ name = DependentResource .defaultNameFor (dependentType );
257
+ }
258
+ return name ;
259
+ }
260
+
261
+ @ SuppressWarnings ("unused" )
262
+ private static <T > Configurator <T > configuratorFor (Class <T > instanceType ,
263
+ Reconciler <?> reconciler ) {
264
+ return instance -> configureFromAnnotatedReconciler (instance , reconciler );
265
+ }
266
+
267
+ @ SuppressWarnings ({"unchecked" , "rawtypes" })
268
+ private static void configureFromAnnotatedReconciler (Object instance , Reconciler <?> reconciler ) {
269
+ if (instance instanceof AnnotationConfigurable configurable ) {
270
+ final Class <? extends Annotation > configurationClass =
271
+ (Class <? extends Annotation >) Utils .getFirstTypeArgumentFromSuperClassOrInterface (
272
+ instance .getClass (), AnnotationConfigurable .class );
273
+ final var configAnnotation = reconciler .getClass ().getAnnotation (configurationClass );
274
+ if (configAnnotation != null ) {
275
+ configurable .initFrom (configAnnotation );
276
+ }
277
+ }
278
+ }
296
279
}
0 commit comments