diff --git a/internal/error/error.go b/internal/error/error.go index 4333c460..ef8827a5 100644 --- a/internal/error/error.go +++ b/internal/error/error.go @@ -16,16 +16,54 @@ limitations under the License. package error -import "time" +import ( + "time" + + corev1 "k8s.io/api/core/v1" +) + +// EventTypeNone indicates no error event. It can be used to disable error +// events. +const EventTypeNone = "None" + +// Config is the error configuration. It is embedded in the errors and can be +// used to configure how the error should be handled. These configurations +// mostly define actions to be taken on the errors. Not all the configurations +// may apply to every error. +type Config struct { + // Event is the event type of an error. It is used to configure what type of + // event an error should result in. + // Valid values: + // - EventTypeNone + // - corev1.EventTypeNormal + // - corev1.EventTypeWarning + Event string + // Log is used to configure if an error should be logged. The log level is + // derived from the Event type. + // None event - info log + // Normal event - info log + // Warning event - error log + Log bool + // Notification is used to emit an error as a notification alert to a + // a notification service. + Notification bool + // Ignore is used to suppress the error for no-op reconciliations. It may + // be applicable to non-contextual errors only. + Ignore bool +} // Stalling is the reconciliation stalled state error. It contains an error -// and a reason for the stalled condition. +// and a reason for the stalled condition. It is a contextual error used to +// express the scenario of a reconciliation which contributes to the result of +// reconciliation. type Stalling struct { // Reason is the stalled condition reason string. Reason string // Err is the error that caused stalling. This can be used as the message in // stalled condition. Err error + // Config is the error handler configuration. + Config } // Error implements error interface. @@ -38,8 +76,24 @@ func (se *Stalling) Unwrap() error { return se.Err } +// NewStalling constructs a new Stalling error with default configurations. +func NewStalling(err error, reason string) *Stalling { + // Stalling errors are not returned to the runtime. Log it explicitly. + // Since this failure requires user interaction, send warning notification. + return &Stalling{ + Reason: reason, + Err: err, + Config: Config{ + Event: corev1.EventTypeWarning, + Log: true, + Notification: true, + }, + } +} + // Event is an error event. It can be used to construct an event to be // recorded. +// TODO: Replace usage of this with Generic error in all the reconcilers. type Event struct { // Reason is the reason for the event error. Reason string @@ -58,7 +112,10 @@ func (ee *Event) Unwrap() error { } // Waiting is the reconciliation wait state error. It contains an error, wait -// duration and a reason for the wait. +// duration and a reason for the wait. It is a contextual error used to express +// the scenario of a reconciliation which contributes to the result of +// reconciliation. It is for scenarios where a reconciliation needs to wait for +// something else to take place first. type Waiting struct { // RequeueAfter is the wait duration after which to requeue. RequeueAfter time.Duration @@ -66,9 +123,11 @@ type Waiting struct { Reason string // Err is the error that caused the wait. Err error + // Config is the error handler configuration. + Config } -// Error implement error interface. +// Error implements error interface. func (we *Waiting) Error() string { return we.Err.Error() } @@ -77,3 +136,53 @@ func (we *Waiting) Error() string { func (we *Waiting) Unwrap() error { return we.Err } + +// NewWaiting constructs a new Stalling error with default configurations. +func NewWaiting(err error, reason string) *Waiting { + // Waiting errors are not returned to the runtime. Log it explicitly. + // Since this failure results in reconciliation delay, send warning + // notification. + return &Waiting{ + Reason: reason, + Err: err, + Config: Config{ + Event: corev1.EventTypeNormal, + Log: true, + }, + } +} + +// Generic error is a generic reconcile error. It can be used in scenarios that +// don't have any special contextual meaning. +type Generic struct { + // Reason is the reason for the generic error. + Reason string + // Error is the error that caused the generic error. + Err error + // Config is the error handler configuration. + Config +} + +// Error implements error interface. +func (g *Generic) Error() string { + return g.Err.Error() +} + +// Unwrap returns the underlying error. +func (g *Generic) Unwrap() error { + return g.Err +} + +// NewGeneric constructs a new Stalling error with default configurations. +func NewGeneric(err error, reason string) *Generic { + // Since it's a error, ensure to log and send failure notification. + return &Generic{ + Reason: reason, + Err: err, + Config: Config{ + Event: corev1.EventTypeWarning, + Log: true, + Notification: true, + }, + } +}