Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Augment error behaviour #920

Merged
merged 9 commits into from
Jan 31, 2023
Merged

Conversation

mihaialexandrescu
Copy link
Contributor

@mihaialexandrescu mihaialexandrescu commented Jan 26, 2023

Q A
Bug fix? no
New feature? yes
API breaks? no
Deprecations? no
Related tickets
License Apache 2.0

What's in this PR?

This PR aims to improve the errors implementations (in the errorfactory and webhooks packages).
Along the way, I'm also renaming a couple of variables and functions to better reflect their usage.

The custom error types from the errorfactory package can be improved and brought up to date (to Go > 1.13 recommendations) by adding an Unwrap() method for each one of these types returning the embedded error so that errors that could be wrapped inside can be inspected and matched on with all of their details, not just the string representation, with errors.Is() and errors.As().
I'm also adding a unit test for the Unwrap() behaviour.

The constant error message strings from the webhooks package don't need to be exported, but, because we still have to do some string matching, we can add exported matching functions for all them much like we have right now for 2 of them (IsAdmissionCantConnect(error) bool and IsInvalidReplicationFactor(error) bool). This will facilitate and hide the details of the string matching that we need to do.
I'm also adding unit tests for these new functions.

The changes made to the controllers package reflect the updated usage pattern of the errors from the errorfactory package. Without these, that code no longer works correctly.
The previous model that performed a type switch on the error returned by emperror/errors.Cause(err) no longer works because the error types from the errorfactory package can now Unwrap() and return the errors inside, not just stopping the unwrap immediately and returning the outer type. Because we no longer break the error chain, the "last" error in the chain (deemed as "Cause") is no longer the type from the errorfactory package but whatever it wraps or further.
Now, we can and should use the standard errors.As(...) function instead which doesn't require the type we seek to be at the very end of the chain but anywhere inside the chain of wrapped errors. Yes, we currently use the As(...) function from the emperror/errors package but that translates directly to the errors.As(...) from the standard library.

Additional context

Currently, in koperator we have 2 patterns for our own errors:

  1. Custom error types in koperator/pkg/errorfactory/errorfactory.go

These embed the builtin "error" type and wrap external errors passed in to the errorfactory.New function alongside lists of "details". We make use of the emperror/errors module which returns error types that can be chained (have both Error() and Unwrap() methods).
Right now errors like APIFailure (used like in koperator/pkg/k8sutil/resource.go) can be inspected or matched on for type but we lose the details of the error(s) wrapped inside. This can be improved by adding an Unwrap() method for each one of these types returning the embedded error.

  1. The error strings in koperator/pkg/webhooks/errors.go

These are unexported constant strings used during the validating webhook functions. These are used as parts of the strings of some log and error messages.

These end up used to create either an error or a field.Error (k8s.io/apimachinery/pkg/util/validation/field). In both situations, the ValidateCreate and ValidateUpdate sets of methods return errors that, underneath, are of StatusError type (apimachinery/pkg/api/errors/errors.go) from apimachinery. This type hides all other details from the wrapped errors except for the accumulated string. Sometimes the error chain is broken even earlier by other error types from apimachinery.
The downside to the error types we end up returning from the webhook functions is that we don't have a reasonable solution to avoid doing string matching to discriminate between errors.

@mihaialexandrescu mihaialexandrescu marked this pull request as ready for review January 27, 2023 10:21
@mihaialexandrescu mihaialexandrescu requested a review from a team as a code owner January 27, 2023 10:21
pregnor
pregnor previously approved these changes Jan 27, 2023
Copy link
Member

@pregnor pregnor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a minor recommendation.

pkg/webhooks/errors_test.go Outdated Show resolved Hide resolved
Copy link
Member

@panyuenlau panyuenlau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great and loving the newly added tests! Just some quick comments

pkg/webhooks/errors.go Outdated Show resolved Hide resolved
pkg/webhooks/errors.go Show resolved Hide resolved
pkg/errorfactory/errorfactory.go Show resolved Hide resolved
pkg/webhooks/errors_test.go Outdated Show resolved Hide resolved
@mihaialexandrescu mihaialexandrescu merged commit b070277 into master Jan 31, 2023
@mihaialexandrescu mihaialexandrescu deleted the feat/augment_error_behavior branch January 31, 2023 15:53
bartam1 pushed a commit that referenced this pull request Feb 17, 2023
* add Unwrap method to package errorfactory and a unit test for it

* temporary: add webhooks err check functions and unit tests

* rename removingStorageMsg var and add comment about the use of errorDuringValidationMsg

* sanitize error unit tests and reorder public error check functions

* refactor to use errors.As instead of errors.Cause which no longer fits

* replace pkg alias apiErrors with apierrors in pkg webhooks

* camelCase testName and testCases in errors_test.go from pkg webhooks

* add comment for Unwrap method and shorten public error comparison functions in pkg webhooks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants