Merge pull request #50671 from mmorel-35/github.com/hashicorp/go-multierror

chore: use errors.Join instead of github.com/hashicorp/go-multierror
This commit is contained in:
Rob Murray
2025-08-08 19:40:36 +01:00
committed by GitHub
8 changed files with 49 additions and 58 deletions

View File

@@ -69,6 +69,8 @@ linters:
desc: Use github.com/moby/sys/userns instead.
- pkg: "github.com/tonistiigi/fsutil"
desc: The fsutil module does not have a stable API, so we should not have a direct dependency unless necessary.
- pkg: "github.com/hashicorp/go-multierror"
desc: "Use errors.Join instead"
dupword:
ignore:

View File

@@ -2,16 +2,15 @@ package daemon
import (
"context"
"errors"
"fmt"
"os"
"github.com/containerd/log"
"github.com/hashicorp/go-multierror"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/v2/daemon/config"
"github.com/moby/moby/v2/errdefs"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"tags.cncf.io/container-device-interface/pkg/cdi"
)
@@ -118,11 +117,11 @@ func (c *cdiHandler) injectCDIDevices(s *specs.Spec, dev *deviceInstance) error
// getErrors returns a single error representation of errors that may have occurred while refreshing the CDI registry.
func (c *cdiHandler) getErrors() error {
var err *multierror.Error
for _, errs := range c.registry.GetErrors() {
err = multierror.Append(err, errs...)
var errs []error
for _, es := range c.registry.GetErrors() {
errs = append(errs, es...)
}
return err.ErrorOrNil()
return errors.Join(errs...)
}
// listDevices uses the CDI cache to list all discovered CDI devices.

View File

@@ -2,6 +2,7 @@ package containerd
import (
"context"
"errors"
"sort"
"strings"
@@ -11,14 +12,12 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/containerd/log"
"github.com/distribution/reference"
"github.com/hashicorp/go-multierror"
"github.com/moby/moby/api/types/filters"
"github.com/moby/moby/api/types/image"
"github.com/moby/moby/v2/daemon/container"
"github.com/moby/moby/v2/errdefs"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
var imagesAcceptedFilters = map[string]bool{
@@ -218,7 +217,7 @@ func (i *ImageService) pruneAll(ctx context.Context, imagesToPrune map[string]c8
span.SetAttributes(tracing.Attribute("count", len(imagesToPrune)))
defer span.End()
var errs error
var errs []error
for _, img := range imagesToPrune {
log.G(ctx).WithField("image", img).Debug("pruning image")
@@ -229,17 +228,17 @@ func (i *ImageService) pruneAll(ctx context.Context, imagesToPrune map[string]c8
return nil
})
if err != nil {
errs = multierror.Append(errs, err)
errs = append(errs, err)
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return &report, errs
return &report, errors.Join(errs...)
}
continue
}
err = i.images.Delete(ctx, img.Name, c8dimages.SynchronousDelete())
if err != nil && !cerrdefs.IsNotFound(err) {
errs = multierror.Append(errs, err)
errs = append(errs, err)
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return &report, errs
return &report, errors.Join(errs...)
}
continue
}
@@ -265,5 +264,5 @@ func (i *ImageService) pruneAll(ctx context.Context, imagesToPrune map[string]c8
}
}
return &report, errs
return &report, errors.Join(errs...)
}

View File

@@ -10,7 +10,6 @@ import (
"strings"
"github.com/containerd/log"
"github.com/hashicorp/go-multierror"
"github.com/moby/sys/mount"
"github.com/moby/sys/symlink"
"golang.org/x/sys/unix"
@@ -215,10 +214,13 @@ func (vw *containerFSView) GoInFS(ctx context.Context, fn func()) error {
func (vw *containerFSView) Close() error {
runtime.SetFinalizer(vw, nil)
close(vw.todo)
err := multierror.Append(nil, <-vw.done)
err = multierror.Append(err, vw.ctr.UnmountVolumes(context.TODO(), vw.d.LogVolumeEvent))
err = multierror.Append(err, vw.d.Unmount(vw.ctr))
return err.ErrorOrNil()
var errs []error
errs = append(errs,
<-vw.done,
vw.ctr.UnmountVolumes(context.TODO(), vw.d.LogVolumeEvent),
vw.d.Unmount(vw.ctr),
)
return errors.Join(errs...)
}
// Stat returns the metadata for path, relative to the current working directory

View File

@@ -3,6 +3,7 @@ package remote
import (
"context"
"encoding/json"
"errors"
"io"
"os"
"path/filepath"
@@ -25,7 +26,6 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/containerd/log"
"github.com/containerd/typeurl/v2"
"github.com/hashicorp/go-multierror"
"github.com/moby/moby/v2/daemon/internal/libcontainerd/queue"
libcontainerdtypes "github.com/moby/moby/v2/daemon/internal/libcontainerd/types"
"github.com/moby/moby/v2/errdefs"
@@ -33,7 +33,7 @@ import (
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
pkgerrors "github.com/pkg/errors"
"go.opentelemetry.io/otel"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -113,7 +113,7 @@ func (c *container) AttachTask(ctx context.Context, attachStdio libcontainerdtyp
}
t, err := c.c8dCtr.Task(ctx, attachIO)
if err != nil {
return nil, errors.Wrap(wrapError(err), "error getting containerd task for container")
return nil, pkgerrors.Wrap(wrapError(err), "error getting containerd task for container")
}
return c.newTask(t), nil
}
@@ -132,7 +132,7 @@ func (c *client) NewContainer(ctx context.Context, id string, ociSpec *specs.Spe
ctr, err := c.client.NewContainer(ctx, id, opts...)
if err != nil {
if cerrdefs.IsAlreadyExists(err) {
return nil, errors.WithStack(errdefs.Conflict(errors.New("id already in use")))
return nil, pkgerrors.WithStack(errdefs.Conflict(errors.New("id already in use")))
}
return nil, wrapError(err)
}
@@ -177,10 +177,10 @@ func (c *container) NewTask(ctx context.Context, checkpointDir string, withStdin
}
}()
if err := tar.Close(); err != nil {
return nil, errors.Wrap(err, "failed to close checkpoint tar stream")
return nil, pkgerrors.Wrap(err, "failed to close checkpoint tar stream")
}
if err != nil {
return nil, errors.Wrapf(err, "failed to upload checkpoint to containerd")
return nil, pkgerrors.Wrapf(err, "failed to upload checkpoint to containerd")
}
}
@@ -189,13 +189,13 @@ func (c *container) NewTask(ctx context.Context, checkpointDir string, withStdin
// to refresh the metadata separately for spec and labels.
md, err := c.c8dCtr.Info(ctx, containerd.WithoutRefreshedMetadata)
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve metadata")
return nil, pkgerrors.Wrap(err, "failed to retrieve metadata")
}
bundle := md.Labels[DockerContainerBundlePath]
var spec specs.Spec
if err := json.Unmarshal(md.Spec.GetValue(), &spec); err != nil {
return nil, errors.Wrap(err, "failed to retrieve spec")
return nil, pkgerrors.Wrap(err, "failed to retrieve spec")
}
uid, gid := getSpecUser(&spec)
@@ -235,7 +235,7 @@ func (c *container) NewTask(ctx context.Context, checkpointDir string, withStdin
rio.Cancel()
rio.Close()
}
return nil, errors.Wrap(wrapError(err), "failed to create task for container")
return nil, pkgerrors.Wrap(wrapError(err), "failed to create task for container")
}
// Signal c.createIO that it can call CloseIO
@@ -289,7 +289,7 @@ func (t *task) Exec(ctx context.Context, processID string, spec *specs.Process,
if err != nil {
close(stdinCloseSync)
if cerrdefs.IsAlreadyExists(err) {
return nil, errors.WithStack(errdefs.Conflict(errors.New("id already in use")))
return nil, pkgerrors.WithStack(errdefs.Conflict(errors.New("id already in use")))
}
return nil, wrapError(err)
}
@@ -350,7 +350,7 @@ func (t *task) Summary(ctx context.Context) ([]libcontainerdtypes.Summary, error
for _, pi := range pis {
i, err := typeurl.UnmarshalAny(pi.Info)
if err != nil {
return nil, errors.Wrap(err, "unable to decode process details")
return nil, pkgerrors.Wrap(err, "unable to decode process details")
}
s, err := summaryFromInterface(i)
if err != nil {
@@ -440,11 +440,11 @@ func (t *task) CreateCheckpoint(ctx context.Context, checkpointDir string, exit
b, err := content.ReadBlob(ctx, t.ctr.client.client.ContentStore(), img.Target())
if err != nil {
return errdefs.System(errors.Wrapf(err, "failed to retrieve checkpoint data"))
return errdefs.System(pkgerrors.Wrapf(err, "failed to retrieve checkpoint data"))
}
var index ocispec.Index
if err := json.Unmarshal(b, &index); err != nil {
return errdefs.System(errors.Wrapf(err, "failed to decode checkpoint data"))
return errdefs.System(pkgerrors.Wrapf(err, "failed to decode checkpoint data"))
}
var cpDesc *ocispec.Descriptor
@@ -455,17 +455,17 @@ func (t *task) CreateCheckpoint(ctx context.Context, checkpointDir string, exit
}
}
if cpDesc == nil {
return errdefs.System(errors.Wrapf(err, "invalid checkpoint"))
return errdefs.System(pkgerrors.Wrapf(err, "invalid checkpoint"))
}
rat, err := t.ctr.client.client.ContentStore().ReaderAt(ctx, *cpDesc)
if err != nil {
return errdefs.System(errors.Wrapf(err, "failed to get checkpoint reader"))
return errdefs.System(pkgerrors.Wrapf(err, "failed to get checkpoint reader"))
}
defer rat.Close()
_, err = archive.Apply(ctx, checkpointDir, content.NewReader(rat))
if err != nil {
return errdefs.System(errors.Wrapf(err, "failed to read checkpoint reader"))
return errdefs.System(pkgerrors.Wrapf(err, "failed to read checkpoint reader"))
}
return err
@@ -476,7 +476,7 @@ func (c *client) LoadContainer(ctx context.Context, id string) (libcontainerdtyp
ctr, err := c.client.LoadContainer(ctx, id)
if err != nil {
if cerrdefs.IsNotFound(err) {
return nil, errors.WithStack(errdefs.NotFound(errors.New("no such container")))
return nil, pkgerrors.WithStack(errdefs.NotFound(errors.New("no such container")))
}
return nil, wrapError(err)
}
@@ -505,27 +505,20 @@ func (c *container) createIO(fifos *cio.FIFOSet, stdinCloseSync chan containerd.
if io.Stdin != nil {
var (
closeErr error
errs []error
stdinOnce sync.Once
)
pipe := io.Stdin
io.Stdin = ioutils.NewWriteCloserWrapper(pipe, func() error {
stdinOnce.Do(func() {
closeErr = pipe.Close()
errs = append(errs, pipe.Close())
select {
case p, ok := <-stdinCloseSync:
if !ok {
return
}
if err := closeStdin(context.Background(), p); err != nil {
if closeErr != nil {
closeErr = multierror.Append(closeErr, err)
} else {
// Avoid wrapping a single error in a multierror.
closeErr = err
}
}
errs = append(errs, closeStdin(context.Background(), p))
default:
// The process wasn't ready. Close its stdin asynchronously.
go func() {
@@ -541,7 +534,7 @@ func (c *container) createIO(fifos *cio.FIFOSet, stdinCloseSync chan containerd.
}()
}
})
return closeErr
return errors.Join(errs...)
})
}

View File

@@ -15,7 +15,6 @@ import (
"sync"
"github.com/containerd/log"
"github.com/hashicorp/go-multierror"
"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
"github.com/moby/moby/v2/daemon/libnetwork/drivers/overlay/overlayutils"
"github.com/moby/moby/v2/daemon/libnetwork/internal/countmap"
@@ -543,7 +542,7 @@ func (n *network) initSubnetSandbox(s *subnet) error {
}
if err := n.driver.programInput(s.vni, n.secure); err != nil {
if n.secure {
return multierror.Append(err, n.driver.programMangle(s.vni, false))
return errors.Join(err, n.driver.programMangle(s.vni, false))
}
}

View File

@@ -3,11 +3,11 @@ package daemon
import (
"context"
"encoding/json"
"errors"
"fmt"
"strconv"
"github.com/containerd/log"
"github.com/hashicorp/go-multierror"
"github.com/mitchellh/copystructure"
"github.com/moby/moby/api/types/events"
@@ -35,11 +35,11 @@ func (tx *reloadTxn) run(cbs []func() error) error {
tx.onCommit = nil
tx.onRollback = nil
var res *multierror.Error
var errs []error
for _, cb := range cbs {
res = multierror.Append(res, cb())
errs = append(errs, cb())
}
return res.ErrorOrNil()
return errors.Join(errs...)
}
// Commit calls all functions registered with OnCommit.
@@ -109,10 +109,7 @@ func (daemon *Daemon) Reload(conf *config.Config) error {
daemon.reloadNetworkDiagnosticPort,
} {
if err := reload(&txn, newCfg, conf, attributes); err != nil {
if rollbackErr := txn.Rollback(); rollbackErr != nil {
return multierror.Append(nil, err, rollbackErr)
}
return err
return errors.Join(err, txn.Rollback())
}
}

2
go.mod
View File

@@ -49,7 +49,6 @@ require (
github.com/gorilla/mux v1.8.1
github.com/hashicorp/go-immutable-radix/v2 v2.1.0
github.com/hashicorp/go-memdb v1.3.2
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/memberlist v0.4.0
github.com/hashicorp/serf v0.8.5
github.com/ishidawataru/sctp v0.0.0-20250708014235-1989182a9425
@@ -180,6 +179,7 @@ require (
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v0.5.5 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect