Skip to content

Commit 6bf0d3b

Browse files
pwittrockdroot
authored andcommitted
Provide helpful error message if informer isn't found in manager.
1 parent 07d1fe7 commit 6bf0d3b

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

pkg/controller/informers/informersindex.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ limitations under the License.
1717
package informers
1818

1919
import (
20+
"fmt"
2021
"reflect"
2122

22-
"fmt"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2424
"k8s.io/client-go/tools/cache"
2525
)

pkg/controller/listeningqueue.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ func (q *listeningQueue) addEventHandler(obj metav1.Object, eh eventhandlers.Eve
6868
func (q *listeningQueue) lookupInformer(obj metav1.Object) (cache.SharedInformer, error) {
6969
i := q.informerProvider.GetInformer(obj)
7070
if i == nil {
71-
return i, fmt.Errorf("Could not find SharedInformer for %T in %s", obj, q.informerProvider)
71+
return i, fmt.Errorf("Could not find SharedInformer for %T in %s. Must register with "+
72+
"// +kubebuilder:informer:", obj, q.informerProvider)
7273
}
7374
return i, nil
7475
}

pkg/controller/manager.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ package controller
1818

1919
import (
2020
"fmt"
21+
"os"
22+
"reflect"
23+
"runtime"
24+
"strings"
2125
"sync"
2226

2327
"github.com/kubernetes-sigs/kubebuilder/pkg/controller/informers"
@@ -68,7 +72,11 @@ func AddInformerProvider(object metav1.Object, informerProvider informers.Inform
6872
// GetInformer returns the Informer for an object
6973
func (m *ControllerManager) GetInformer(object metav1.Object) cache.SharedInformer {
7074
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
7280
}
7381

7482
// GetInformerProvider returns the InformerProvider for the object type
@@ -129,3 +137,52 @@ func RunInformersAndControllers(options run.RunArguments) {
129137
func (m *ControllerManager) String() string {
130138
return fmt.Sprintf("ControllerManager SharedInformers: %v", m.sharedInformersByResource)
131139
}
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("\nWARNING: %s\nWARNING: 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

Comments
 (0)