@@ -23,6 +23,7 @@ import (
23
23
"github.com/go-logr/logr"
24
24
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25
25
"k8s.io/apimachinery/pkg/runtime/schema"
26
+ "k8s.io/client-go/discovery"
26
27
27
28
"sigs.k8s.io/controller-runtime/pkg/client"
28
29
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
@@ -72,6 +73,7 @@ type ForInput struct {
72
73
predicates []predicate.Predicate
73
74
objectProjection objectProjection
74
75
err error
76
+ conditional bool
75
77
}
76
78
77
79
// For defines the type of Object being *reconciled*, and configures the ControllerManagedBy to respond to create / delete /
@@ -97,6 +99,7 @@ type OwnsInput struct {
97
99
object client.Object
98
100
predicates []predicate.Predicate
99
101
objectProjection objectProjection
102
+ conditional bool
100
103
}
101
104
102
105
// Owns defines types of Objects being *generated* by the ControllerManagedBy, and configures the ControllerManagedBy to respond to
@@ -118,6 +121,7 @@ type WatchesInput struct {
118
121
eventhandler handler.EventHandler
119
122
predicates []predicate.Predicate
120
123
objectProjection objectProjection
124
+ conditional bool
121
125
}
122
126
123
127
// Watches exposes the lower-level ControllerManagedBy Watches functions through the builder. Consider using
@@ -216,13 +220,48 @@ func (blder *Builder) project(obj client.Object, proj objectProjection) (client.
216
220
}
217
221
}
218
222
223
+ func (blder * Builder ) generateConditionalSource (typeForSrc client.Object ) (source.Source , error ) {
224
+ gvk , err := getGvk (blder .forInput .object , blder .mgr .GetScheme ())
225
+ if err != nil {
226
+ return nil , err
227
+ }
228
+ dc , err := discovery .NewDiscoveryClientForConfig (blder .mgr .GetConfig ())
229
+ if err != nil {
230
+ return nil , err
231
+ }
232
+ existsInDiscovery := func () bool {
233
+ resources , err := dc .ServerResourcesForGroupVersion (gvk .GroupVersion ().String ())
234
+ if err != nil {
235
+ return false
236
+ }
237
+ for _ , res := range resources .APIResources {
238
+ if res .Kind == gvk .Kind {
239
+ return true
240
+ }
241
+ }
242
+ return false
243
+ }
244
+ return & source.ConditionalKind {Kind : source.Kind {Type : typeForSrc }, DiscoveryCheck : existsInDiscovery }, nil
245
+
246
+ }
247
+
219
248
func (blder * Builder ) doWatch () error {
220
249
// Reconcile type
221
250
typeForSrc , err := blder .project (blder .forInput .object , blder .forInput .objectProjection )
222
251
if err != nil {
223
252
return err
224
253
}
225
- src := & source.Kind {Type : typeForSrc }
254
+
255
+ var src source.Source
256
+ if blder .forInput .conditional {
257
+ var err error
258
+ src , err = blder .generateConditionalSource (typeForSrc )
259
+ if err != nil {
260
+ return err
261
+ }
262
+ } else {
263
+ src = & source.Kind {Type : typeForSrc }
264
+ }
226
265
hdler := & handler.EnqueueRequestForObject {}
227
266
allPredicates := append (blder .globalPredicates , blder .forInput .predicates ... )
228
267
if err := blder .ctrl .Watch (src , hdler , allPredicates ... ); err != nil {
@@ -235,7 +274,17 @@ func (blder *Builder) doWatch() error {
235
274
if err != nil {
236
275
return err
237
276
}
238
- src := & source.Kind {Type : typeForSrc }
277
+
278
+ var src source.Source
279
+ if own .conditional {
280
+ var err error
281
+ src , err = blder .generateConditionalSource (typeForSrc )
282
+ if err != nil {
283
+ return err
284
+ }
285
+ } else {
286
+ src = & source.Kind {Type : typeForSrc }
287
+ }
239
288
hdler := & handler.EnqueueRequestForOwner {
240
289
OwnerType : blder .forInput .object ,
241
290
IsController : true ,
0 commit comments