8
8
import java .util .List ;
9
9
import java .util .Optional ;
10
10
import java .util .Set ;
11
+ import java .util .function .BiPredicate ;
11
12
import java .util .function .Function ;
13
+ import java .util .function .Predicate ;
12
14
import java .util .stream .Collectors ;
13
15
14
16
import io .fabric8 .kubernetes .api .model .HasMetadata ;
27
29
import io .javaoperatorsdk .operator .processing .dependent .workflow .Condition ;
28
30
import io .javaoperatorsdk .operator .processing .event .source .controller .ResourceEventFilter ;
29
31
import io .javaoperatorsdk .operator .processing .event .source .controller .ResourceEventFilters ;
32
+ import io .javaoperatorsdk .operator .processing .event .source .filter .VoidGenericFilter ;
33
+ import io .javaoperatorsdk .operator .processing .event .source .filter .VoidOnAddFilter ;
34
+ import io .javaoperatorsdk .operator .processing .event .source .filter .VoidOnDeleteFilter ;
35
+ import io .javaoperatorsdk .operator .processing .event .source .filter .VoidOnUpdateFilter ;
30
36
31
37
import static io .javaoperatorsdk .operator .api .reconciler .Constants .DEFAULT_NAMESPACES_SET ;
32
38
33
39
@ SuppressWarnings ("rawtypes" )
34
- public class AnnotationControllerConfiguration <R extends HasMetadata >
35
- implements io .javaoperatorsdk .operator .api .config .ControllerConfiguration <R > {
40
+ public class AnnotationControllerConfiguration <P extends HasMetadata >
41
+ implements io .javaoperatorsdk .operator .api .config .ControllerConfiguration <P > {
36
42
37
- protected final Reconciler <R > reconciler ;
43
+ protected final Reconciler <P > reconciler ;
38
44
private final ControllerConfiguration annotation ;
39
45
private List <DependentResourceSpec > specs ;
40
- private Class <R > resourceClass ;
46
+ private Class <P > resourceClass ;
41
47
42
- public AnnotationControllerConfiguration (Reconciler <R > reconciler ) {
48
+ public AnnotationControllerConfiguration (Reconciler <P > reconciler ) {
43
49
this .reconciler = reconciler ;
44
50
this .annotation = reconciler .getClass ().getAnnotation (ControllerConfiguration .class );
45
51
if (annotation == null ) {
@@ -84,10 +90,10 @@ public Set<String> getNamespaces() {
84
90
85
91
@ Override
86
92
@ SuppressWarnings ("unchecked" )
87
- public Class <R > getResourceClass () {
93
+ public Class <P > getResourceClass () {
88
94
if (resourceClass == null ) {
89
95
resourceClass =
90
- (Class <R >) Utils .getFirstTypeArgumentFromSuperClassOrInterface (reconciler .getClass (),
96
+ (Class <P >) Utils .getFirstTypeArgumentFromSuperClassOrInterface (reconciler .getClass (),
91
97
Reconciler .class );
92
98
}
93
99
return resourceClass ;
@@ -105,16 +111,16 @@ public String getAssociatedReconcilerClassName() {
105
111
106
112
@ SuppressWarnings ("unchecked" )
107
113
@ Override
108
- public ResourceEventFilter <R > getEventFilter () {
109
- ResourceEventFilter <R > answer = null ;
114
+ public ResourceEventFilter <P > getEventFilter () {
115
+ ResourceEventFilter <P > answer = null ;
110
116
111
- Class <ResourceEventFilter <R >>[] filterTypes =
112
- (Class <ResourceEventFilter <R >>[]) valueOrDefault (annotation ,
117
+ Class <ResourceEventFilter <P >>[] filterTypes =
118
+ (Class <ResourceEventFilter <P >>[]) valueOrDefault (annotation ,
113
119
ControllerConfiguration ::eventFilters , new Object [] {});
114
120
if (filterTypes .length > 0 ) {
115
121
for (var filterType : filterTypes ) {
116
122
try {
117
- ResourceEventFilter <R > filter = filterType .getConstructor ().newInstance ();
123
+ ResourceEventFilter <P > filter = filterType .getConstructor ().newInstance ();
118
124
119
125
if (answer == null ) {
120
126
answer = filter ;
@@ -144,17 +150,55 @@ public Optional<Duration> reconciliationMaxInterval() {
144
150
}
145
151
}
146
152
147
- public static <T > T valueOrDefault (
148
- ControllerConfiguration controllerConfiguration ,
149
- Function <ControllerConfiguration , T > mapper ,
150
- T defaultValue ) {
151
- if (controllerConfiguration == null ) {
152
- return defaultValue ;
153
+ @ Override
154
+ @ SuppressWarnings ("unchecked" )
155
+ public Optional <Predicate <P >> onAddFilter () {
156
+ return (Optional <Predicate <P >>) createFilter (annotation .onAddFilter (), FilterType .onAdd ,
157
+ annotation .getClass ().getSimpleName ());
158
+ }
159
+
160
+ private enum FilterType {
161
+ onAdd (VoidOnAddFilter .class ), onUpdate (VoidOnUpdateFilter .class ), onDelete (
162
+ VoidOnDeleteFilter .class ), generic (VoidGenericFilter .class );
163
+
164
+ final Class <?> defaultValue ;
165
+
166
+ FilterType (Class <?> defaultValue ) {
167
+ this .defaultValue = defaultValue ;
168
+ }
169
+ }
170
+
171
+ private <T > Optional <T > createFilter (Class <T > filter , FilterType filterType , String origin ) {
172
+ if (filterType .defaultValue .equals (filter )) {
173
+ return Optional .empty ();
153
174
} else {
154
- return mapper .apply (controllerConfiguration );
175
+ try {
176
+ var instance = (T ) filter .getDeclaredConstructor ().newInstance ();
177
+ return Optional .of (instance );
178
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException
179
+ | NoSuchMethodException e ) {
180
+ throw new OperatorException (
181
+ "Couldn't create " + filterType + " filter from " + filter .getName () + " class in "
182
+ + origin + " for reconciler " + getName (),
183
+ e );
184
+ }
155
185
}
156
186
}
157
187
188
+ @ SuppressWarnings ("unchecked" )
189
+ @ Override
190
+ public Optional <BiPredicate <P , P >> onUpdateFilter () {
191
+ return (Optional <BiPredicate <P , P >>) createFilter (annotation .onUpdateFilter (),
192
+ FilterType .onUpdate , annotation .getClass ().getSimpleName ());
193
+ }
194
+
195
+ @ SuppressWarnings ("unchecked" )
196
+ @ Override
197
+ public Optional <Predicate <P >> genericFilter () {
198
+ return (Optional <Predicate <P >>) createFilter (annotation .genericFilter (),
199
+ FilterType .generic , annotation .getClass ().getSimpleName ());
200
+ }
201
+
158
202
@ SuppressWarnings ({"rawtypes" , "unchecked" })
159
203
@ Override
160
204
public List <DependentResourceSpec > getDependentResources () {
@@ -223,26 +267,59 @@ private String getName(Dependent dependent, Class<? extends DependentResource> d
223
267
return name ;
224
268
}
225
269
270
+ @ SuppressWarnings ("rawtypes" )
226
271
private Object createKubernetesResourceConfig (Class <? extends DependentResource > dependentType ) {
272
+
227
273
Object config ;
228
274
final var kubeDependent = dependentType .getAnnotation (KubernetesDependent .class );
229
275
230
276
var namespaces = getNamespaces ();
231
277
var configuredNS = false ;
232
- if (kubeDependent != null && !Arrays .equals (KubernetesDependent .DEFAULT_NAMESPACES ,
233
- kubeDependent .namespaces ())) {
234
- namespaces = Set .of (kubeDependent .namespaces ());
235
- configuredNS = true ;
236
- }
237
-
238
278
String labelSelector = null ;
279
+ Predicate <? extends HasMetadata > onAddFilter = null ;
280
+ BiPredicate <? extends HasMetadata , ? extends HasMetadata > onUpdateFilter = null ;
281
+ BiPredicate <? extends HasMetadata , Boolean > onDeleteFilter = null ;
282
+ Predicate <? extends HasMetadata > genericFilter = null ;
239
283
if (kubeDependent != null ) {
284
+ if (!Arrays .equals (KubernetesDependent .DEFAULT_NAMESPACES ,
285
+ kubeDependent .namespaces ())) {
286
+ namespaces = Set .of (kubeDependent .namespaces ());
287
+ configuredNS = true ;
288
+ }
289
+
240
290
final var fromAnnotation = kubeDependent .labelSelector ();
241
291
labelSelector = Constants .NO_VALUE_SET .equals (fromAnnotation ) ? null : fromAnnotation ;
292
+
293
+ final var kubeDependentName = KubernetesDependent .class .getSimpleName ();
294
+ onAddFilter = createFilter (kubeDependent .onAddFilter (), FilterType .onAdd , kubeDependentName )
295
+ .orElse (null );
296
+ onUpdateFilter =
297
+ createFilter (kubeDependent .onUpdateFilter (), FilterType .onUpdate , kubeDependentName )
298
+ .orElse (null );
299
+ onDeleteFilter =
300
+ createFilter (kubeDependent .onDeleteFilter (), FilterType .onDelete , kubeDependentName )
301
+ .orElse (null );
302
+ genericFilter =
303
+ createFilter (kubeDependent .genericFilter (), FilterType .generic , kubeDependentName )
304
+ .orElse (null );
242
305
}
243
306
244
307
config =
245
- new KubernetesDependentResourceConfig (namespaces , labelSelector , configuredNS );
308
+ new KubernetesDependentResourceConfig (namespaces , labelSelector , configuredNS , onAddFilter ,
309
+ onUpdateFilter , onDeleteFilter , genericFilter );
310
+
246
311
return config ;
247
312
}
313
+
314
+ public static <T > T valueOrDefault (
315
+ ControllerConfiguration controllerConfiguration ,
316
+ Function <ControllerConfiguration , T > mapper ,
317
+ T defaultValue ) {
318
+ if (controllerConfiguration == null ) {
319
+ return defaultValue ;
320
+ } else {
321
+ return mapper .apply (controllerConfiguration );
322
+ }
323
+ }
324
+
248
325
}
0 commit comments