@@ -18,6 +18,10 @@ package controller
18
18
19
19
import (
20
20
"fmt"
21
+ "os"
22
+ "reflect"
23
+ "runtime"
24
+ "strings"
21
25
"sync"
22
26
23
27
"github.com/kubernetes-sigs/kubebuilder/pkg/controller/informers"
@@ -68,7 +72,11 @@ func AddInformerProvider(object metav1.Object, informerProvider informers.Inform
68
72
// GetInformer returns the Informer for an object
69
73
func (m * ControllerManager ) GetInformer (object metav1.Object ) cache.SharedInformer {
70
74
m .once .Do (m .init )
71
- return m .sharedInformersByResource .Get (object )
75
+ si := m .sharedInformersByResource .Get (object )
76
+ if si == nil {
77
+ warningMissingInformer (object )
78
+ }
79
+ return si
72
80
}
73
81
74
82
// GetInformerProvider returns the InformerProvider for the object type
@@ -129,3 +137,52 @@ func RunInformersAndControllers(options run.RunArguments) {
129
137
func (m * ControllerManager ) String () string {
130
138
return fmt .Sprintf ("ControllerManager SharedInformers: %v" , m .sharedInformersByResource )
131
139
}
140
+
141
+ // warningMissingInformer prints a warning message to stderr that an informer was not registered
142
+ func warningMissingInformer (obj interface {}) {
143
+ // Get the type of the object
144
+ t := reflect .TypeOf (reflect .Indirect (reflect .ValueOf (obj )).Interface ())
145
+
146
+ // Parse the GVK from the object
147
+ path := t .PkgPath ()
148
+ groupversion := strings .Split (path , "/" )
149
+ group := groupversion [len (groupversion )- 2 ]
150
+ version := groupversion [len (groupversion )- 1 ]
151
+ kind := t .Name ()
152
+
153
+ // Create a helpful error message
154
+ msg := fmt .Sprintf ("\n WARNING: %s\n WARNING: Informer for %s.%s.%s not registered! " +
155
+ "Must register informer with a // +kubebuilder:informers:group=%s,version=%s,kind=%s annotation on the" +
156
+ "Controller struct.\n " ,
157
+ provideControllerLine (), group , version , kind , group , version , kind )
158
+ fmt .Fprint (os .Stderr , msg )
159
+ }
160
+
161
+ // provideControllerLine returns a string with the file and line number where "ProvideController" was called
162
+ // in the call stack
163
+ func provideControllerLine () string {
164
+ ok := true
165
+ var file string
166
+ var pc uintptr
167
+ var line int
168
+ for i := 0 ; ok ; i ++ {
169
+ pc , file , line , ok = runtime .Caller (i )
170
+ if ! ok {
171
+ break
172
+ }
173
+ f := runtime .FuncForPC (pc )
174
+ if f == nil {
175
+ ok = false
176
+ break
177
+ }
178
+ parts := strings .Split (f .Name (), "." )
179
+ fn := parts [len (parts )- 1 ]
180
+ if fn == "ProvideController" {
181
+ break
182
+ }
183
+ }
184
+ if ok {
185
+ return fmt .Sprintf ("%s:%v" , file , line )
186
+ }
187
+ return ""
188
+ }
0 commit comments