Skip to content

Remove hashicorp/go-multierror dependency#8992

Merged
fuweid merged 2 commits intocontainerd:mainfrom
djdongjin:remove-hashicorp-multierror
Aug 23, 2023
Merged

Remove hashicorp/go-multierror dependency#8992
fuweid merged 2 commits intocontainerd:mainfrom
djdongjin:remove-hashicorp-multierror

Conversation

@djdongjin
Copy link
Copy Markdown
Member

@djdongjin djdongjin commented Aug 19, 2023

Remove github.com/hashicorp/go-multierror and replace with errors.Join in std.

Some concept equivalents:

var errs multierror.Error = var errs []error
errs = multierror.Append(errs, err) = errs = append(errs, err)
multierror.ErrorOrNil(errs) = errors.Join(errs)
errs.WrappedErrors() = err.(interface{ Unwrap() []error }).Unwrap()

One behavior difference between multierror.Append and errors.Join is that the former will append to an existing multierror if it is (so the new one has a length of N + 1), while the latter will create a new joinError which includes previous error and the new one (so the new one has a length of 2)

https://go.dev/play/p/ryeimUucDyb

I think the recommended use pattern of errors.Join is to have a errs [] error to save all the errors along the way and a errors.Join(errs...) at the end to produce one joinError.

https://pkg.go.dev/errors#Join

golang/go#60209

golang/go#53435 (comment)

@k8s-ci-robot
Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@djdongjin djdongjin force-pushed the remove-hashicorp-multierror branch from 1597909 to 2ab1bd7 Compare August 19, 2023 07:55
@djdongjin
Copy link
Copy Markdown
Member Author

/test all

@AkihiroSuda
Copy link
Copy Markdown
Member

/retest

1 similar comment
@djdongjin
Copy link
Copy Markdown
Member Author

/retest

status, sErr := dmsetup.Status(s.pool.poolName)
if sErr != nil {
multierror.Append(err, sErr)
errs = append(errs, sErr)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The previous code actually has a bug. If err is a error type, multierror.Append(err, sErr) will create a new multierror.Error type and append sErr there. It should be err = multierror.Append(err, sErr).

@djdongjin djdongjin force-pushed the remove-hashicorp-multierror branch from 2ab1bd7 to 4da1749 Compare August 21, 2023 00:57
Signed-off-by: Jin Dong <jin.dong@databricks.com>
@djdongjin djdongjin force-pushed the remove-hashicorp-multierror branch from 4da1749 to cd8c8ae Compare August 21, 2023 00:59
result = append(result, fn())
}
err = multierror.Flatten(result)
err = errors.Join(result...)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

multierror.Flatten is only called here, so not sure if it's necessary. If so, maybe we can write a simple helper to do that.

@djdongjin
Copy link
Copy Markdown
Member Author

/test all

@djdongjin djdongjin marked this pull request as ready for review August 21, 2023 15:45
return e.Errors[0]
if joinErr, ok := e.(interface{ Unwrap() []error }); ok {
if errs := joinErr.Unwrap(); len(errs) == 1 {
return errs[0]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If I recall this right, we required this unwrapping helper for error comparisons to work. Which can now be replaced with error.Is. I wonder if we can now remove this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

thanks for the context. I remember there're 2 places where the unwrap is used. Let me take a look at both.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Digging into a little bit, unwrapError was introduced in #4437. At that time it seems multierror 1.0.0 is used (or at least older than 1.1.0).

My guess is unwrapError was required to expose the underlying unix.ENODATA error within multierror which was handled below

if e != nil && !errors.Is(e, unix.ENODATA) {

It was needed because at that time, errors.Is seems not work with multierror:

In this playground with multierror 1.0.0, errors.Is returns false: https://go.dev/play/p/29rAHWAV310
In this playground with multierror 1.1.0, errors.Is returns true: https://go.dev/play/p/UpFMxRkmjcc

And now since errors.Is works with both multierror 1.1.0 and errors.Join, we can safely remove this regardless :)

Signed-off-by: Jin Dong <jin.dong@databricks.com>
Comment on lines -144 to -147
// Unwrap if just one error
if len(result.Errors) == 1 {
return result.Errors[0]
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I also removed this Unwrap since most cases don't have such Unwrap logic unless specifically needed.

Only such case I found is the code below (to handle cleanupErr separately).

var cerr podsandbox.CleanupErr
if errors.As(err, &cerr) {
cleanupErr = fmt.Errorf("failed to cleanup sandbox: %w", cerr)
// Strip last error as cleanup error to handle separately
if merr, ok := err.(*multierror.Error); ok {
if errs := merr.WrappedErrors(); len(errs) > 0 {
err = errs[0]
}
}
}

Copy link
Copy Markdown
Member

@mxpv mxpv left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Member

@fuweid fuweid left a comment

Choose a reason for hiding this comment

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

Changes look good.

@fuweid fuweid merged commit 738c153 into containerd:main Aug 23, 2023
@djdongjin djdongjin deleted the remove-hashicorp-multierror branch August 24, 2023 23:34
@djdongjin
Copy link
Copy Markdown
Member Author

/cherry-pick release/1.7

@k8s-infra-cherrypick-robot
Copy link
Copy Markdown

@djdongjin: #8992 failed to apply on top of branch "release/1.7":

Applying: Remove hashicorp/go-multierror
Using index info to reconstruct a base tree...
M	go.mod
M	pkg/cri/sbserver/podsandbox/sandbox_run.go
M	pkg/cri/sbserver/sandbox_run.go
M	pkg/cri/sbserver/sandbox_stats_list.go
M	pkg/cri/server/sandbox_stats_list.go
M	pkg/process/io.go
M	runtime/v2/shim.go
M	snapshots/devmapper/pool_device.go
M	snapshots/devmapper/snapshotter.go
M	snapshots/devmapper/snapshotter_test.go
M	snapshots/storage/metastore.go
Falling back to patching base and 3-way merge...
Auto-merging snapshots/storage/metastore.go
CONFLICT (content): Merge conflict in snapshots/storage/metastore.go
Auto-merging snapshots/devmapper/snapshotter_test.go
Auto-merging snapshots/devmapper/snapshotter.go
CONFLICT (content): Merge conflict in snapshots/devmapper/snapshotter.go
Auto-merging snapshots/devmapper/pool_device.go
Auto-merging runtime/v2/shim.go
Auto-merging pkg/process/io.go
CONFLICT (content): Merge conflict in pkg/process/io.go
Auto-merging pkg/cri/server/sandbox_stats_list.go
CONFLICT (content): Merge conflict in pkg/cri/server/sandbox_stats_list.go
Auto-merging pkg/cri/sbserver/sandbox_stats_list.go
CONFLICT (content): Merge conflict in pkg/cri/sbserver/sandbox_stats_list.go
Auto-merging pkg/cri/sbserver/sandbox_run.go
CONFLICT (content): Merge conflict in pkg/cri/sbserver/sandbox_run.go
Auto-merging pkg/cri/sbserver/podsandbox/sandbox_run.go
Auto-merging go.mod
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"
Patch failed at 0001 Remove hashicorp/go-multierror

Details

In response to this:

/cherry-pick release/1.7

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants