diff --git a/pkg/gameservers/controller.go b/pkg/gameservers/controller.go index 16835b268e..00460aacb7 100644 --- a/pkg/gameservers/controller.go +++ b/pkg/gameservers/controller.go @@ -754,6 +754,9 @@ func (c *Controller) syncGameServerStartingState(ctx context.Context, gs *agones if err != nil { return nil, err } + if pod.Spec.NodeName == "" { + return gs, workerqueue.NewDebugError(errors.Errorf("node not yet populated for Pod %s", pod.ObjectMeta.Name)) + } node, err := c.nodeLister.Get(pod.Spec.NodeName) if err != nil { return gs, errors.Wrapf(err, "error retrieving node %s for Pod %s", pod.Spec.NodeName, pod.ObjectMeta.Name) @@ -803,6 +806,9 @@ func (c *Controller) syncGameServerRequestReadyState(ctx context.Context, gs *ag addressPopulated := false if gs.Status.NodeName == "" { addressPopulated = true + if pod.Spec.NodeName == "" { + return gs, workerqueue.NewDebugError(errors.Errorf("node not yet populated for Pod %s", pod.ObjectMeta.Name)) + } node, err := c.nodeLister.Get(pod.Spec.NodeName) if err != nil { return gs, errors.Wrapf(err, "error retrieving node %s for Pod %s", pod.Spec.NodeName, pod.ObjectMeta.Name) diff --git a/pkg/gameservers/migration.go b/pkg/gameservers/migration.go index 510b71dc59..1f4579482b 100644 --- a/pkg/gameservers/migration.go +++ b/pkg/gameservers/migration.go @@ -168,6 +168,9 @@ func (mc *MigrationController) syncGameServer(ctx context.Context, key string) e return nil } + if pod.Spec.NodeName == "" { + return workerqueue.NewDebugError(errors.Errorf("node not yet populated for Pod %s", pod.ObjectMeta.Name)) + } node, err := mc.nodeLister.Get(pod.Spec.NodeName) if err != nil { return errors.Wrapf(err, "error retrieving node %s for Pod %s", pod.Spec.NodeName, pod.ObjectMeta.Name) diff --git a/pkg/util/workerqueue/workerqueue.go b/pkg/util/workerqueue/workerqueue.go index c9225d1487..8df0b8b605 100644 --- a/pkg/util/workerqueue/workerqueue.go +++ b/pkg/util/workerqueue/workerqueue.go @@ -37,6 +37,32 @@ const ( workFx = time.Second ) +// debugError is a marker type for errors that that should only be logged at a Debug level. +// Useful if you want a Handler to be retried, but not logged at an Error level. +type debugError struct { + err error +} + +// NewDebugError returns a debugError wrapper around an error. +func NewDebugError(err error) error { + return &debugError{err: err} +} + +// Error returns the error string +func (l *debugError) Error() string { + if l.err == nil { + return "" + } + return l.err.Error() +} + +// isDebugError returns if the error is a debug error or not +func isDebugError(err error) bool { + cause := errors.Cause(err) + _, ok := cause.(*debugError) + return ok +} + // Handler is the handler for processing the work queue // This is usually a syncronisation handler for a controller or related type Handler func(context.Context, string) error @@ -153,7 +179,8 @@ func (wq *WorkerQueue) processNextWorkItem(ctx context.Context) bool { if err := wq.SyncHandler(ctx, key); err != nil { // Conflicts are expected, so only show them in debug operations. - if k8serror.IsConflict(errors.Cause(err)) { + // Also check is debugError for other expected errors. + if k8serror.IsConflict(errors.Cause(err)) || isDebugError(err) { wq.logger.WithField(wq.keyName, obj).Debug(err) } else { runtime.HandleError(wq.logger.WithField(wq.keyName, obj), err) diff --git a/pkg/util/workerqueue/workerqueue_test.go b/pkg/util/workerqueue/workerqueue_test.go index 2d15a78bbd..5624404861 100644 --- a/pkg/util/workerqueue/workerqueue_test.go +++ b/pkg/util/workerqueue/workerqueue_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/heptiolabs/healthcheck" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/util/wait" @@ -194,3 +195,16 @@ func TestWorkerQueueEnqueueAfter(t *testing.T) { assert.Fail(t, "should have got a queue'd message by now") } } + +func TestDebugError(t *testing.T) { + err := errors.New("not a debug error") + assert.False(t, isDebugError(err)) + + err = NewDebugError(err) + assert.True(t, isDebugError(err)) + assert.EqualError(t, err, "not a debug error") + + err = NewDebugError(nil) + assert.True(t, isDebugError(err)) + assert.EqualError(t, err, "") +}