diff --git a/cache/manager.go b/cache/manager.go index e89b20e51c89..74eb4271089b 100644 --- a/cache/manager.go +++ b/cache/manager.go @@ -519,7 +519,16 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, sess session.Gr return nil, errors.Wrapf(err, "failed to add snapshot %s to lease", id) } - if err := cm.Snapshotter.Prepare(ctx, id, parentSnapshotID); err != nil { + if cm.Snapshotter.Name() == "stargz" && parent != nil { + if rerr := parent.withRemoteSnapshotLabelsStargzMode(ctx, sess, func() { + err = cm.Snapshotter.Prepare(ctx, id, parentSnapshotID) + }); rerr != nil { + return nil, rerr + } + } else { + err = cm.Snapshotter.Prepare(ctx, id, parentSnapshotID) + } + if err != nil { return nil, errors.Wrapf(err, "failed to prepare %s", id) } diff --git a/cache/refs.go b/cache/refs.go index a17f6e10deb6..d7905d7ed1c3 100644 --- a/cache/refs.go +++ b/cache/refs.go @@ -155,8 +155,18 @@ func (cr *cacheRecord) isLazy(ctx context.Context) (bool, error) { _, err := cr.cm.ContentStore.Info(ctx, digest.Digest(dgst)) if errors.Is(err, errdefs.ErrNotFound) { return true, nil + } else if err != nil { + return false, err } - return false, err + + // If the snapshot is a remote snapshot, this layer is lazy. + if info, err := cr.cm.Snapshotter.Stat(ctx, getSnapshotID(cr.md)); err == nil { + if _, ok := info.Labels["containerd.io/snapshot/remote"]; ok { + return true, nil + } + } + + return false, nil } func (cr *cacheRecord) IdentityMapping() *idtools.IdentityMapping { @@ -381,6 +391,20 @@ func (sr *immutableRef) Mount(ctx context.Context, readonly bool, s session.Grou sr.mu.Lock() defer sr.mu.Unlock() + + if sr.cm.Snapshotter.Name() == "stargz" { + var ( + m snapshot.Mountable + rerr error + ) + if err := sr.withRemoteSnapshotLabelsStargzMode(ctx, s, func() { + m, rerr = sr.mount(ctx, readonly) + }); err != nil { + return nil, err + } + return m, rerr + } + return sr.mount(ctx, readonly) } @@ -400,66 +424,154 @@ func (sr *immutableRef) Extract(ctx context.Context, s session.Group) (rerr erro } if sr.cm.Snapshotter.Name() == "stargz" { - if _, err := sr.prepareRemoteSnapshots(ctx, sr.descHandlers); err != nil { + if err := sr.withRemoteSnapshotLabelsStargzMode(ctx, s, func() { + if rerr = sr.prepareRemoteSnapshotsStargzMode(ctx, s); rerr != nil { + return + } + rerr = sr.extract(ctx, sr.descHandlers, s) + }); err != nil { return err } + return rerr } return sr.extract(ctx, sr.descHandlers, s) } -func (sr *immutableRef) prepareRemoteSnapshots(ctx context.Context, dhs DescHandlers) (bool, error) { - ok, err := sr.sizeG.Do(ctx, sr.ID()+"-prepare-remote-snapshot", func(ctx context.Context) (_ interface{}, rerr error) { - snapshotID := getSnapshotID(sr.md) - if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil { - return true, nil +func (sr *immutableRef) withRemoteSnapshotLabelsStargzMode(ctx context.Context, s session.Group, f func()) error { + dhs := sr.descHandlers + for _, r := range sr.parentRefChain() { + r := r + info, err := r.cm.Snapshotter.Stat(ctx, getSnapshotID(r.md)) + if err != nil && !errdefs.IsNotFound(err) { + return err + } else if errdefs.IsNotFound(err) { + continue // This snpashot doesn't exist; skip + } else if _, ok := info.Labels["containerd.io/snapshot/remote"]; !ok { + continue // This isn't a remote snapshot; skip } - desc, err := sr.ociDesc() + desc, err := r.ociDesc() if err != nil { - return false, err + return err } dh := dhs[desc.Digest] if dh == nil { - return false, nil + continue // no info passed; skip } - parentID := "" - if sr.parent != nil { - if ok, err := sr.parent.prepareRemoteSnapshots(ctx, dhs); !ok { - return false, err + // Append temporary labels (based on dh.SnapshotLabels) as hints for remote snapshots. + // For avoiding collosion among calls, keys of these tmp labels contain an unique ID. + flds, labels := makeTmpLabelsStargzMode(snapshots.FilterInheritedLabels(dh.SnapshotLabels), s) + info.Labels = labels + if _, err := r.cm.Snapshotter.Update(ctx, info, flds...); err != nil { + return errors.Wrapf(err, "failed to add tmp remote labels for remote snapshot") + } + defer func() { + for k := range info.Labels { + info.Labels[k] = "" // Remove labels appended in this call + } + if _, err := r.cm.Snapshotter.Update(ctx, info, flds...); err != nil { + logrus.Warn(errors.Wrapf(err, "failed to remove tmp remote labels")) + } + }() + + continue + } + + f() + + return nil +} + +func (sr *immutableRef) prepareRemoteSnapshotsStargzMode(ctx context.Context, s session.Group) error { + _, err := sr.sizeG.Do(ctx, sr.ID()+"-prepare-remote-snapshot", func(ctx context.Context) (_ interface{}, rerr error) { + dhs := sr.descHandlers + for _, r := range sr.parentRefChain() { + r := r + snapshotID := getSnapshotID(r.md) + if _, err := r.cm.Snapshotter.Stat(ctx, snapshotID); err == nil { + continue + } + + desc, err := r.ociDesc() + if err != nil { + return nil, err + } + dh := dhs[desc.Digest] + if dh == nil { + // We cannot prepare remote snapshots without descHandler. + return nil, nil + } + + // tmpLabels contains dh.SnapshotLabels + session IDs. All keys contain + // an unique ID for avoiding the collision among snapshotter API calls to + // this snapshot. tmpLabels will be removed at the end of this function. + defaultLabels := snapshots.FilterInheritedLabels(dh.SnapshotLabels) + if defaultLabels == nil { + defaultLabels = make(map[string]string) } - parentID = getSnapshotID(sr.parent.md) - } - - // Hint labels to the snapshotter - labels := dh.SnapshotLabels - if labels == nil { - labels = make(map[string]string) - } - labels["containerd.io/snapshot.ref"] = snapshotID - opt := snapshots.WithLabels(labels) - - // Try to preapre the remote snapshot - key := fmt.Sprintf("tmp-%s %s", identity.NewID(), sr.Info().ChainID) - if err = sr.cm.Snapshotter.Prepare(ctx, key, parentID, opt); err != nil { - if errdefs.IsAlreadyExists(err) { - // Check if the targeting snapshot ID has been prepared as a remote - // snapshot in the snapshotter. - if _, err := sr.cm.Snapshotter.Stat(ctx, snapshotID); err == nil { - // We can use this remote snapshot without unlazying. - // Try the next layer as well. - return true, nil + tmpFields, tmpLabels := makeTmpLabelsStargzMode(defaultLabels, s) + defaultLabels["containerd.io/snapshot.ref"] = snapshotID + + // Prepare remote snapshots + var ( + key = fmt.Sprintf("tmp-%s %s", identity.NewID(), r.Info().ChainID) + opts = []snapshots.Opt{ + snapshots.WithLabels(defaultLabels), + snapshots.WithLabels(tmpLabels), } + ) + parentID := "" + if r.parent != nil { + parentID = getSnapshotID(r.parent.md) } + if err = r.cm.Snapshotter.Prepare(ctx, key, parentID, opts...); err != nil { + if errdefs.IsAlreadyExists(err) { + // Check if the targeting snapshot ID has been prepared as + // a remote snapshot in the snapshotter. + info, err := r.cm.Snapshotter.Stat(ctx, snapshotID) + if err == nil { // usable as remote snapshot without unlazying. + defer func() { + // Remove tmp labels appended in this func + for k := range tmpLabels { + info.Labels[k] = "" + } + if _, err := r.cm.Snapshotter.Update(ctx, info, tmpFields...); err != nil { + logrus.Warn(errors.Wrapf(err, + "failed to remove tmp remote labels after prepare")) + } + }() + + // Try the next layer as well. + continue + } + } + } + + // This layer and all upper layers cannot be prepared without unlazying. + break } - // This layer cannot be prepared without unlazying. - return false, nil + return nil, nil }) - if err != nil { - return false, err + return err +} + +func makeTmpLabelsStargzMode(labels map[string]string, s session.Group) (fields []string, res map[string]string) { + res = make(map[string]string) + // Append unique ID to labels for avoiding collision of labels among calls + id := identity.NewID() + for k, v := range labels { + tmpKey := k + "." + id + fields = append(fields, "labels."+tmpKey) + res[tmpKey] = v + } + for i, sid := range session.AllSessionIDs(s) { + sidKey := "containerd.io/snapshot/remote/stargz.session." + fmt.Sprintf("%d", i) + "." + id + fields = append(fields, "labels."+sidKey) + res[sidKey] = sid } - return ok.(bool), err + return } func (sr *immutableRef) extract(ctx context.Context, dhs DescHandlers, s session.Group) error { @@ -725,6 +837,19 @@ func (sr *mutableRef) Mount(ctx context.Context, readonly bool, s session.Group) sr.mu.Lock() defer sr.mu.Unlock() + if sr.cm.Snapshotter.Name() == "stargz" && sr.parent != nil { + var ( + m snapshot.Mountable + rerr error + ) + if err := sr.parent.withRemoteSnapshotLabelsStargzMode(ctx, s, func() { + m, rerr = sr.mount(ctx, readonly) + }); err != nil { + return nil, err + } + return m, rerr + } + return sr.mount(ctx, readonly) } diff --git a/cmd/buildkitd/main.go b/cmd/buildkitd/main.go index e1b62c3a9918..a6ac76834ff9 100644 --- a/cmd/buildkitd/main.go +++ b/cmd/buildkitd/main.go @@ -69,6 +69,7 @@ func init() { type workerInitializerOpt struct { config *config.Config configMetaData *toml.MetaData + sessionManager *session.Manager } type workerInitializer struct { @@ -592,6 +593,7 @@ func newController(c *cli.Context, cfg *config.Config, md *toml.MetaData) (*cont wc, err := newWorkerController(c, workerInitializerOpt{ config: cfg, configMetaData: md, + sessionManager: sessionManager, }) if err != nil { return nil, err diff --git a/cmd/buildkitd/main_oci_worker.go b/cmd/buildkitd/main_oci_worker.go index 9d7d0172dd9c..3a22eca515ee 100644 --- a/cmd/buildkitd/main_oci_worker.go +++ b/cmd/buildkitd/main_oci_worker.go @@ -4,16 +4,19 @@ package main import ( "context" + "fmt" "os" "os/exec" "path/filepath" "strconv" + "strings" "time" "github.com/BurntSushi/toml" snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1" "github.com/containerd/containerd/defaults" "github.com/containerd/containerd/pkg/dialer" + "github.com/containerd/containerd/reference" "github.com/containerd/containerd/remotes/docker" ctdsnapshot "github.com/containerd/containerd/snapshots" "github.com/containerd/containerd/snapshots/native" @@ -28,8 +31,10 @@ import ( remotesn "github.com/containerd/stargz-snapshotter/snapshot" "github.com/moby/buildkit/cmd/buildkitd/config" "github.com/moby/buildkit/executor/oci" + "github.com/moby/buildkit/session" "github.com/moby/buildkit/util/network/cniprovider" "github.com/moby/buildkit/util/network/netproviders" + "github.com/moby/buildkit/util/resolver" "github.com/moby/buildkit/worker" "github.com/moby/buildkit/worker/base" "github.com/moby/buildkit/worker/runc" @@ -245,7 +250,7 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker } hosts := resolverFunc(common.config) - snFactory, err := snapshotterFactory(common.config.Root, cfg, hosts, common.configMetaData) + snFactory, err := snapshotterFactory(common.config.Root, cfg, common.sessionManager, hosts, common.configMetaData) if err != nil { return nil, err } @@ -303,7 +308,7 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker return []worker.Worker{w}, nil } -func snapshotterFactory(commonRoot string, cfg config.OCIConfig, hosts docker.RegistryHosts, cfgMeta *toml.MetaData) (runc.SnapshotterFactory, error) { +func snapshotterFactory(commonRoot string, cfg config.OCIConfig, sm *session.Manager, hosts docker.RegistryHosts, cfgMeta *toml.MetaData) (runc.SnapshotterFactory, error) { var ( name = cfg.Snapshotter address = cfg.ProxySnapshotterPath @@ -368,22 +373,6 @@ func snapshotterFactory(commonRoot string, cfg config.OCIConfig, hosts docker.Re return fuseoverlayfs.NewSnapshotter(root) } case "stargz": - // Pass the registry configuration to stargz snapshotter - sgzhosts := func(host string) ([]docker.RegistryHost, error) { - base, err := hosts(host) - if err != nil { - return nil, err - } - for i := range base { - if base[i].Authorizer == nil { - // Default authorizer that don't fetch creds via session - // TODO(ktock): use session-based authorizer - base[i].Authorizer = docker.NewDockerAuthorizer( - docker.WithAuthClient(base[i].Client)) - } - } - return base, nil - } sgzCfg := sgzconf.Config{} if cfgMeta != nil { if err := cfgMeta.PrimitiveDecode(cfg.StargzSnapshotterConfig, &sgzCfg); err != nil { @@ -393,11 +382,8 @@ func snapshotterFactory(commonRoot string, cfg config.OCIConfig, hosts docker.Re snFactory.New = func(root string) (ctdsnapshot.Snapshotter, error) { fs, err := sgzfs.NewFilesystem(filepath.Join(root, "stargz"), sgzCfg, - sgzfs.WithGetSources( - // provides source info based on the registry config and - // default labels. - sgzsource.FromDefaultLabels(sgzhosts), - ), + // Source info based on the buildkit's registry config and session + sgzfs.WithGetSources(sourceWithSession(hosts, sm)), ) if err != nil { return nil, err @@ -421,3 +407,74 @@ func validOCIBinary() bool { } return true } + +const ( + // targetRefLabel is a label which contains image reference. + targetRefLabel = "containerd.io/snapshot/remote/stargz.reference" + + // targetDigestLabel is a label which contains layer digest. + targetDigestLabel = "containerd.io/snapshot/remote/stargz.digest" + + // targetImageLayersLabel is a label which contains layer digests contained in + // the target image. + targetImageLayersLabel = "containerd.io/snapshot/remote/stargz.layers" + + // targetSessionLabel is a labeld which contains session IDs usable for + // authenticating the target snapshot. + targetSessionLabel = "containerd.io/snapshot/remote/stargz.session" +) + +// sourceWithSession returns a callback which implements a converter from labels to the +// typed snapshot source info. This callback is called everytime the snapshotter resolves a +// snapshot. This callback returns configuration that is based on buildkitd's registry config +// and utilizes the session-based authorizer. +func sourceWithSession(hosts docker.RegistryHosts, sm *session.Manager) sgzsource.GetSources { + return func(labels map[string]string) (src []sgzsource.Source, err error) { + // labels contains multiple source candidates with unique IDs appended on each call + // to the snapshotter API. So, first, get all these IDs + var ids []string + for k := range labels { + if strings.HasPrefix(k, targetRefLabel+".") { + ids = append(ids, strings.TrimPrefix(k, targetRefLabel+".")) + } + } + + // Parse all labels + for _, id := range ids { + // Parse session labels + ref, ok := labels[targetRefLabel+"."+id] + if !ok { + continue + } + named, err := reference.Parse(ref) + if err != nil { + continue + } + var sids []string + for i := 0; ; i++ { + sidKey := targetSessionLabel + "." + fmt.Sprintf("%d", i) + "." + id + sid, ok := labels[sidKey] + if !ok { + break + } + sids = append(sids, sid) + } + + // Get source information based on labels and RegistryHosts containing + // session-based authorizer. + parse := sgzsource.FromDefaultLabels(func(ref reference.Spec) ([]docker.RegistryHost, error) { + return resolver.DefaultPool.GetResolver(hosts, named.String(), "pull", sm, session.NewGroup(sids...)). + HostsFunc(ref.Hostname()) + }) + if s, err := parse(map[string]string{ + targetRefLabel: ref, + targetDigestLabel: labels[targetDigestLabel+"."+id], + targetImageLayersLabel: labels[targetImageLayersLabel+"."+id], + }); err == nil { + src = append(src, s...) + } + } + + return src, nil + } +} diff --git a/go.mod b/go.mod index be13d55a8b6e..6a38820b03ec 100644 --- a/go.mod +++ b/go.mod @@ -8,14 +8,14 @@ require ( github.com/Microsoft/hcsshim v0.8.16 github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58 // indirect github.com/containerd/console v1.0.2 - github.com/containerd/containerd v1.5.0 + github.com/containerd/containerd v1.5.2 github.com/containerd/continuity v0.1.0 github.com/containerd/fuse-overlayfs-snapshotter v1.0.2 github.com/containerd/go-cni v1.0.2 github.com/containerd/go-runc v1.0.0 - github.com/containerd/stargz-snapshotter v0.5.0 + github.com/containerd/stargz-snapshotter v0.6.4 github.com/containerd/typeurl v1.0.2 - github.com/coreos/go-systemd/v22 v22.1.0 + github.com/coreos/go-systemd/v22 v22.3.2 github.com/docker/cli v20.10.7+incompatible github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v20.10.7+incompatible @@ -50,7 +50,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.5.0 github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 - github.com/sirupsen/logrus v1.7.0 + github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 github.com/tonistiigi/fsutil v0.0.0-20210525040343-5dfbf5db66b9 github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea diff --git a/go.sum b/go.sum index 0b1673aec084..35e9d5a1661b 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,8 @@ github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7 github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.0 h1:p9b9VlMObAOuIuZ3EakDGMsq8V59VBlTXi8b8DCLa6o= -github.com/containerd/containerd v1.5.0/go.mod h1:kYiJ+LvywDUKzyax6+UKCk5xwQNCfcGR6KsSdShdg5U= +github.com/containerd/containerd v1.5.2 h1:MG/Bg1pbmMb61j3wHCFWPxESXHieiKr2xG64px/k8zQ= +github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -170,10 +170,10 @@ github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/stargz-snapshotter v0.5.0 h1:JcffikoW/RjJ+9kfYyiqmaKvI6lUuiPmSAKVInHQ4i0= -github.com/containerd/stargz-snapshotter v0.5.0/go.mod h1:4MqZBKHJQeqJHcofN65D5kK2lKzjtd1bK6gT9Qm4WFY= -github.com/containerd/stargz-snapshotter/estargz v0.5.0 h1:mtV2MU17r1MmXJIS9uUUNg5m/XU0a/gsnmznkZRkA3s= -github.com/containerd/stargz-snapshotter/estargz v0.5.0/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= +github.com/containerd/stargz-snapshotter v0.6.4 h1:mox1Ozl/LicA5j0O5Xk9Q8z+nOQQLnClarhxokyw9hI= +github.com/containerd/stargz-snapshotter v0.6.4/go.mod h1:1t0SF1gAHJhCSftWKDLVitvfF3c2qhL5hymG7C50wto= +github.com/containerd/stargz-snapshotter/estargz v0.6.4 h1:lhJppIf4ULGQXbcjUJIy1sq79UegNTEebDTtfU8MlcA= +github.com/containerd/stargz-snapshotter/estargz v0.6.4/go.mod h1:83VWDqHnurTKliEB0YvWMiCfLDwv4Cjj1X9Vk98GJZw= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -211,15 +211,15 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= @@ -235,15 +235,15 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.7+incompatible h1:pv/3NqibQKphWZiAskMzdz8w0PRbtTaEB+f6NwdU7Is= github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= @@ -303,6 +303,7 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblf github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.7.3 h1:I0EKY9l8HZCXTMYC4F80vwT6KNypV9uYKP3Alm/hjmQ= github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= @@ -328,6 +329,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -378,13 +381,15 @@ github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1 github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hanwen/go-fuse v1.0.0 h1:GxS9Zrn6c35/BnfiVsZVWmsG803xwE7eVRDvcf/BEVc= github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok= -github.com/hanwen/go-fuse/v2 v2.0.4-0.20201208195215-4a458845028b h1:WEjjS1Vt8Oslac2LQ9nldgcm0Dx0VGMY21YVveK2ZUA= -github.com/hanwen/go-fuse/v2 v2.0.4-0.20201208195215-4a458845028b/go.mod h1:0EQM6aH2ctVpvZ6a+onrQ/vaykxh2GH7hy3e13vzTUY= +github.com/hanwen/go-fuse/v2 v2.1.0 h1:+32ffteETaLYClUj0a3aHjZ1hOPxxaNEHiZiujuDaek= +github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= @@ -417,20 +422,21 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -475,8 +481,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -487,14 +491,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -529,6 +531,7 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.1/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -591,8 +594,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -907,7 +911,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -919,9 +922,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/util/resolver/pool.go b/util/resolver/pool.go index 20344eaa35f1..810e9620498b 100644 --- a/util/resolver/pool.go +++ b/util/resolver/pool.go @@ -105,7 +105,7 @@ func newResolver(hosts docker.RegistryHosts, handler *authHandlerNS, sm *session handler: handler, } r.Resolver = docker.NewResolver(docker.ResolverOptions{ - Hosts: r.hostsFunc, + Hosts: r.HostsFunc, }) return r } @@ -123,7 +123,8 @@ type Resolver struct { mode source.ResolveMode } -func (r *Resolver) hostsFunc(host string) ([]docker.RegistryHost, error) { +// HostsFunc implements registry configuration of this Resolver +func (r *Resolver) HostsFunc(host string) ([]docker.RegistryHost, error) { return func(domain string) ([]docker.RegistryHost, error) { v, err := r.handler.g.Do(context.TODO(), domain, func(ctx context.Context) (interface{}, error) { // long lock not needed because flightcontrol.Do diff --git a/vendor/github.com/containerd/containerd/Makefile b/vendor/github.com/containerd/containerd/Makefile index 1c2fd39a8c98..ef7b7606edf5 100644 --- a/vendor/github.com/containerd/containerd/Makefile +++ b/vendor/github.com/containerd/containerd/Makefile @@ -13,6 +13,9 @@ # limitations under the License. +# Go command to use for build +GO ?= go + # Root directory of the project (absolute path). ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST)))) @@ -26,9 +29,9 @@ REVISION=$(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet PACKAGE=github.com/containerd/containerd SHIM_CGO_ENABLED ?= 0 -ifneq "$(strip $(shell command -v go 2>/dev/null))" "" - GOOS ?= $(shell go env GOOS) - GOARCH ?= $(shell go env GOARCH) +ifneq "$(strip $(shell command -v $(GO) 2>/dev/null))" "" + GOOS ?= $(shell $(GO) env GOOS) + GOARCH ?= $(shell $(GO) env GOARCH) else ifeq ($(GOOS),) # approximate GOOS for the platform if we don't have Go and GOOS isn't @@ -85,7 +88,7 @@ GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revi SHIM_GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -X $(PKG)/version.Package=$(PACKAGE) -extldflags "-static" $(EXTRA_LDFLAGS)' # Project packages. -PACKAGES=$(shell go list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration) +PACKAGES=$(shell $(GO) list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration) TEST_REQUIRES_ROOT_PACKAGES=$(filter \ ${PACKAGES}, \ $(shell \ @@ -122,7 +125,7 @@ TESTFLAGS ?= $(TESTFLAGS_RACE) $(EXTRA_TESTFLAGS) TESTFLAGS_PARALLEL ?= 8 # Use this to replace `go test` with, for instance, `gotestsum` -GOTEST ?= go test +GOTEST ?= $(GO) test OUTPUTDIR = $(join $(ROOTDIR), _output) CRIDIR=$(OUTPUTDIR)/cri @@ -143,7 +146,7 @@ AUTHORS: .mailmap .git/HEAD generate: protos @echo "$(WHALE) $@" - @PATH="${ROOTDIR}/bin:${PATH}" go generate -x ${PACKAGES} + @PATH="${ROOTDIR}/bin:${PATH}" $(GO) generate -x ${PACKAGES} protos: bin/protoc-gen-gogoctrd ## generate protobuf @echo "$(WHALE) $@" @@ -170,7 +173,7 @@ proto-fmt: ## check format of proto files build: ## build the go packages @echo "$(WHALE) $@" - @go build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} ${EXTRA_FLAGS} ${GO_LDFLAGS} ${PACKAGES} + @$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} ${EXTRA_FLAGS} ${GO_LDFLAGS} ${PACKAGES} test: ## run tests, except integration tests and tests that require root @echo "$(WHALE) $@" @@ -182,12 +185,12 @@ root-test: ## run tests, except integration tests integration: ## run integration tests @echo "$(WHALE) $@" - @cd "${ROOTDIR}/integration/client" && go mod download && $(GOTEST) -v ${TESTFLAGS} -test.root -parallel ${TESTFLAGS_PARALLEL} . + @cd "${ROOTDIR}/integration/client" && $(GO) mod download && $(GOTEST) -v ${TESTFLAGS} -test.root -parallel ${TESTFLAGS_PARALLEL} . # TODO integrate cri integration bucket with coverage bin/cri-integration.test: @echo "$(WHALE) $@" - @go test -c ./integration -o bin/cri-integration.test + @$(GO) test -c ./integration -o bin/cri-integration.test cri-integration: binaries bin/cri-integration.test ## run cri integration tests @echo "$(WHALE) $@" @@ -196,13 +199,13 @@ cri-integration: binaries bin/cri-integration.test ## run cri integration tests benchmark: ## run benchmarks tests @echo "$(WHALE) $@" - @go test ${TESTFLAGS} -bench . -run Benchmark -test.root + @$(GO) test ${TESTFLAGS} -bench . -run Benchmark -test.root FORCE: define BUILD_BINARY @echo "$(WHALE) $@" -@go build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@ ${GO_LDFLAGS} ${GO_TAGS} ./$< +@$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@ ${GO_LDFLAGS} ${GO_TAGS} ./$< endef # Build a binary from a cmd. @@ -211,15 +214,15 @@ bin/%: cmd/% FORCE bin/containerd-shim: cmd/containerd-shim FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 @echo "$(WHALE) bin/containerd-shim" - @CGO_ENABLED=${SHIM_CGO_ENABLED} go build ${GO_BUILD_FLAGS} -o bin/containerd-shim ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim + @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o bin/containerd-shim ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim bin/containerd-shim-runc-v1: cmd/containerd-shim-runc-v1 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 @echo "$(WHALE) bin/containerd-shim-runc-v1" - @CGO_ENABLED=${SHIM_CGO_ENABLED} go build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runc-v1 ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v1 + @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runc-v1 ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v1 bin/containerd-shim-runc-v2: cmd/containerd-shim-runc-v2 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 @echo "$(WHALE) bin/containerd-shim-runc-v2" - @CGO_ENABLED=${SHIM_CGO_ENABLED} go build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runc-v2 ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v2 + @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runc-v2 ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v2 binaries: $(BINARIES) ## build binaries @echo "$(WHALE) $@" @@ -235,11 +238,11 @@ genman: man/containerd.8 man/ctr.8 man/containerd.8: FORCE @echo "$(WHALE) $@" - go run cmd/gen-manpages/main.go $(@F) $(@D) + $(GO) run cmd/gen-manpages/main.go $(@F) $(@D) man/ctr.8: FORCE @echo "$(WHALE) $@" - go run cmd/gen-manpages/main.go $(@F) $(@D) + $(GO) run cmd/gen-manpages/main.go $(@F) $(@D) man/%: docs/man/%.md FORCE @echo "$(WHALE) $@" @@ -365,9 +368,9 @@ endif coverage: ## generate coverprofiles from the unit tests, except tests that require root @echo "$(WHALE) $@" @rm -f coverage.txt - @go test -i ${TESTFLAGS} ${PACKAGES} 2> /dev/null + @$(GO) test -i ${TESTFLAGS} ${PACKAGES} 2> /dev/null @( for pkg in ${PACKAGES}; do \ - go test ${TESTFLAGS} \ + $(GO) test ${TESTFLAGS} \ -cover \ -coverprofile=profile.out \ -covermode=atomic $$pkg || exit; \ @@ -379,9 +382,9 @@ coverage: ## generate coverprofiles from the unit tests, except tests that requi root-coverage: ## generate coverage profiles for unit tests that require root @echo "$(WHALE) $@" - @go test -i ${TESTFLAGS} ${TEST_REQUIRES_ROOT_PACKAGES} 2> /dev/null + @$(GO) test -i ${TESTFLAGS} ${TEST_REQUIRES_ROOT_PACKAGES} 2> /dev/null @( for pkg in ${TEST_REQUIRES_ROOT_PACKAGES}; do \ - go test ${TESTFLAGS} \ + $(GO) test ${TESTFLAGS} \ -cover \ -coverprofile=profile.out \ -covermode=atomic $$pkg -test.root || exit; \ @@ -393,8 +396,8 @@ root-coverage: ## generate coverage profiles for unit tests that require root vendor: ## vendor @echo "$(WHALE) $@" - @go mod tidy - @go mod vendor + @$(GO) mod tidy + @$(GO) mod vendor help: ## this help @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort diff --git a/vendor/github.com/containerd/containerd/Vagrantfile b/vendor/github.com/containerd/containerd/Vagrantfile index d054fa262c82..573b34c6f24b 100644 --- a/vendor/github.com/containerd/containerd/Vagrantfile +++ b/vendor/github.com/containerd/containerd/Vagrantfile @@ -77,7 +77,7 @@ Vagrant.configure("2") do |config| config.vm.provision "install-golang", type: "shell", run: "once" do |sh| sh.upload_path = "/tmp/vagrant-install-golang" sh.env = { - 'GO_VERSION': ENV['GO_VERSION'] || "1.16.3", + 'GO_VERSION': ENV['GO_VERSION'] || "1.16.4", } sh.inline = <<~SHELL #!/usr/bin/env bash diff --git a/vendor/github.com/containerd/containerd/go.mod b/vendor/github.com/containerd/containerd/go.mod index d145bcdeb3ca..fa3845121202 100644 --- a/vendor/github.com/containerd/containerd/go.mod +++ b/vendor/github.com/containerd/containerd/go.mod @@ -46,6 +46,8 @@ require ( github.com/pelletier/go-toml v1.8.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 + github.com/prometheus/procfs v0.6.0 // indirect; temporarily force v0.6.0, which was previously defined in imgcrypt as explicit version + github.com/satori/go.uuid v1.2.0 // indirect github.com/sirupsen/logrus v1.7.0 github.com/stretchr/testify v1.6.1 github.com/tchap/go-patricia v2.2.6+incompatible @@ -68,6 +70,9 @@ require ( // When updating replace rules, make sure to also update the rules in integration/client/go.mod replace ( + // prevent transitional dependencies due to containerd having a circular + // dependency on itself through plugins. see .empty-mod/go.mod for details + github.com/containerd/containerd => ./.empty-mod/ github.com/gogo/googleapis => github.com/gogo/googleapis v1.3.2 github.com/golang/protobuf => github.com/golang/protobuf v1.3.5 // urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092 diff --git a/vendor/github.com/containerd/containerd/go.sum b/vendor/github.com/containerd/containerd/go.sum index dfacbc3790f8..2cae0be392a4 100644 --- a/vendor/github.com/containerd/containerd/go.sum +++ b/vendor/github.com/containerd/containerd/go.sum @@ -21,9 +21,7 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= @@ -36,29 +34,17 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -66,22 +52,13 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -91,120 +68,57 @@ github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOo github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= github.com/containerd/aufs v1.0.0 h1:2oeJiwX5HstO7shSrPZjrohJZLzK36wvpdmzDRkL/LY= github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= github.com/containerd/btrfs v1.0.0 h1:osn1exbzdub9L5SouXO5swW4ea/xVdJZ3wokxN5GrnA= github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-cni v1.0.2 h1:YbJAhpTevL2v6u8JC1NhCYRwf+3Vzxcc5vGnYoJ7VeE= github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= github.com/containerd/imgcrypt v1.1.1 h1:LBwiTfoUsdiEGAR1TpvxE+Gzt7469oVu87iR3mv3Byc= github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0 h1:6QioHRlThlKh2RkRTR4kIT3PKAcrLo3gIWnjkM4dQmQ= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9U= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= github.com/containerd/zfs v1.0.0 h1:cXLJbx+4Jj7rNsTiqVfm6i+RNLx6FFA2fMmDlEf+Wm8= github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII3Epo9TmI= github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1 h1:FD1tADPls2EEi3flPc2OegIY1M9pUa9r2Quag7HMLV8= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= github.com/containers/ocicrypt v1.1.1 h1:prL8l9w3ntVqXvNH1CiNn5ENjcCnr38JqpSyvKKB4GI= github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -221,23 +135,14 @@ github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjI github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= @@ -258,14 +163,11 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -281,18 +183,14 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8 github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c h1:RBUpb2b14UnmRHNd2uHz20ZHLDK+SW5Us/vWF5IHRaY= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.3.2 h1:kX1es4djPJrsDhY7aZKJy7aZasdcB5oSOEphMjSB53c= github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -318,7 +216,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -340,9 +237,6 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -353,10 +247,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -365,14 +257,10 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -380,13 +268,11 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -405,7 +291,6 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -419,7 +304,6 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -439,48 +323,30 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM= github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d h1:pNa8metDkwZjb9g4T8s+krQ+HRgZAkqnXml+wNir/+s= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -488,41 +354,34 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= @@ -538,16 +397,12 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -566,19 +421,15 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOHPEbXzO3vnmx2gok1Tfs31Q8GQqKLc8vVqyQq/I= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible h1:JvoDL7JSoIP2HDE8AbDH3zC8QBPxmzYe32HHy5yQ+Ck= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= @@ -587,25 +438,16 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= @@ -622,17 +464,13 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -666,7 +504,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -677,12 +514,10 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -690,7 +525,6 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -709,7 +543,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -723,27 +556,20 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -757,9 +583,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -768,7 +592,6 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -793,7 +616,6 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -827,7 +649,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -843,7 +664,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= @@ -852,7 +672,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -865,7 +684,6 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -892,29 +710,16 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6 h1:bgdZrW++LqgrLikWYNruIKAtltXbSCX2l5mJu11hrVE= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6 h1:R5p3SlhaABYShQSO6LpPsYHjV05Q+79eBUR0Ut/f4tk= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6 h1:NnVriMMOpqQX+dshbDoZixqmBhfgrPk2uOh2fzp9vHE= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6 h1:nJZOfolnsVtDtbGJNCxzOtKUAu7zvXjB8+pMo9UNxZo= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6 h1:G0inASS5vAqCpzs7M4Sp9dv9d0aElpz39zDHbSB4f4g= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.6 h1:iXX0K2pRrbR8yXbZtDK/bSnmg/uSqIFiVJK1x4LUOMc= k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= @@ -922,13 +727,11 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c= diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go index 2edefa3c725c..aca0c4562d71 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/version/version.go @@ -23,7 +23,7 @@ var ( Package = "github.com/containerd/containerd" // Version holds the complete version number. Filled in at linking time. - Version = "1.5.0+unknown" + Version = "1.5.2+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/github.com/containerd/stargz-snapshotter/cache/cache.go b/vendor/github.com/containerd/stargz-snapshotter/cache/cache.go index b6e000fb6329..9f9c9d3e70c7 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/cache/cache.go +++ b/vendor/github.com/containerd/stargz-snapshotter/cache/cache.go @@ -20,12 +20,14 @@ import ( "bytes" "fmt" "io" + "io/ioutil" "os" "path/filepath" "sync" "github.com/containerd/stargz-snapshotter/util/lrucache" "github.com/containerd/stargz-snapshotter/util/namedmutex" + "github.com/hashicorp/go-multierror" "github.com/pkg/errors" ) @@ -61,12 +63,32 @@ type DirectoryCacheConfig struct { // TODO: contents validation. +// BlobCache represents a cache for bytes data type BlobCache interface { - // Add adds the passed data to the cache - Add(key string, p []byte, opts ...Option) + // Add returns a writer to add contents to cache + Add(key string, opts ...Option) (Writer, error) - // FetchAt fetches the specified range of data from the cache - FetchAt(key string, offset int64, p []byte, opts ...Option) (n int, err error) + // Get returns a reader to read the specified contents + // from cache + Get(key string, opts ...Option) (Reader, error) + + // Close closes the cache + Close() error +} + +// Reader provides the data cached. +type Reader interface { + io.ReaderAt + Close() error +} + +// Writer enables the client to cache byte data. Commit() must be +// called after data is fully written to Write(). To abort the written +// data, Abort() must be called. +type Writer interface { + io.WriteCloser + Commit() error + Abort() error } type cacheOpt struct { @@ -123,12 +145,17 @@ func NewDirectoryCache(directory string, config DirectoryCacheConfig) (BlobCache if err := os.MkdirAll(directory, 0700); err != nil { return nil, err } + wipdir := filepath.Join(directory, "wip") + if err := os.MkdirAll(wipdir, 0700); err != nil { + return nil, err + } dc := &directoryCache{ - cache: dataCache, - fileCache: fdCache, - wipLock: new(namedmutex.NamedMutex), - directory: directory, - bufPool: bufPool, + cache: dataCache, + fileCache: fdCache, + wipLock: new(namedmutex.NamedMutex), + directory: directory, + wipDirectory: wipdir, + bufPool: bufPool, } dc.syncAdd = config.SyncAdd return dc, nil @@ -136,17 +163,25 @@ func NewDirectoryCache(directory string, config DirectoryCacheConfig) (BlobCache // directoryCache is a cache implementation which backend is a directory. type directoryCache struct { - cache *lrucache.Cache - fileCache *lrucache.Cache - directory string - wipLock *namedmutex.NamedMutex + cache *lrucache.Cache + fileCache *lrucache.Cache + wipDirectory string + directory string + wipLock *namedmutex.NamedMutex bufPool *sync.Pool syncAdd bool + + closed bool + closedMu sync.Mutex } -func (dc *directoryCache) FetchAt(key string, offset int64, p []byte, opts ...Option) (n int, err error) { +func (dc *directoryCache) Get(key string, opts ...Option) (Reader, error) { + if dc.isClosed() { + return nil, fmt.Errorf("cache is already closed") + } + opt := &cacheOpt{} for _, o := range opts { opt = o(opt) @@ -155,19 +190,24 @@ func (dc *directoryCache) FetchAt(key string, offset int64, p []byte, opts ...Op if !opt.direct { // Get data from memory if b, done, ok := dc.cache.Get(key); ok { - defer done() - data := b.(*bytes.Buffer).Bytes() - if int64(len(data)) < offset { - return 0, fmt.Errorf("invalid offset %d exceeds chunk size %d", - offset, len(data)) - } - return copy(p, data[offset:]), nil + return &reader{ + ReaderAt: bytes.NewReader(b.(*bytes.Buffer).Bytes()), + closeFunc: func() error { + done() + return nil + }, + }, nil } // Get data from disk. If the file is already opened, use it. if f, done, ok := dc.fileCache.Get(key); ok { - defer done() - return f.(*os.File).ReadAt(p, offset) + return &reader{ + ReaderAt: f.(*os.File), + closeFunc: func() error { + done() // file will be closed when it's evicted from the cache + return nil + }, + }, nil } } @@ -176,168 +216,219 @@ func (dc *directoryCache) FetchAt(key string, offset int64, p []byte, opts ...Op // or simply report the cache miss? file, err := os.Open(dc.cachePath(key)) if err != nil { - return 0, errors.Wrapf(err, "failed to open blob file for %q", key) - } - if n, err = file.ReadAt(p, offset); err == io.EOF { - err = nil + return nil, errors.Wrapf(err, "failed to open blob file for %q", key) } - // Cache the opened file for future use. If "direct" option is specified, this - // won't be done. This option is useful for preventing file cache from being - // polluted by data that won't be accessed immediately. + // If "direct" option is specified, do not cache the file on memory. + // This option is useful for preventing memory cache from being polluted by data + // that won't be accessed immediately. if opt.direct { - file.Close() - } else { - _, done, added := dc.fileCache.Add(key, file) - if !added { - file.Close() // file already exists in the cache. discard it. - } - done() // Release this immediately. This will be removed on eviction in lru cache. + return &reader{ + ReaderAt: file, + closeFunc: func() error { return file.Close() }, + }, nil } // TODO: should we cache the entire file data on memory? // but making I/O (possibly huge) on every fetching // might be costly. - - return n, err + return &reader{ + ReaderAt: file, + closeFunc: func() error { + _, done, added := dc.fileCache.Add(key, file) + defer done() // Release it immediately. Cleaned up on eviction. + if !added { + return file.Close() // file already exists in the cache. close it. + } + return nil + }, + }, nil } -func (dc *directoryCache) Add(key string, p []byte, opts ...Option) { +func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) { + if dc.isClosed() { + return nil, fmt.Errorf("cache is already closed") + } + opt := &cacheOpt{} for _, o := range opts { opt = o(opt) } - if !opt.direct { - // Cache the passed data on memory. This enables to serve this data even - // during writing it to the disk. If "direct" option is specified, this - // won't be done. This option is useful for preventing memory cache from being - // polluted by data that won't be accessed immediately. - b := dc.bufPool.Get().(*bytes.Buffer) - b.Reset() - b.Write(p) - _, done, added := dc.cache.Add(key, b) - if !added { - dc.bufPool.Put(b) // already exists in the cache. discard it. - } - done() // This will remain until it's evicted in lru cache. + wip, err := dc.wipFile(key) + if err != nil { + return nil, err + } + w := &writer{ + WriteCloser: wip, + commitFunc: func() error { + if dc.isClosed() { + return fmt.Errorf("cache is already closed") + } + // Commit the cache contents + c := dc.cachePath(key) + if err := os.MkdirAll(filepath.Dir(c), os.ModePerm); err != nil { + var allErr error + if err := os.Remove(wip.Name()); err != nil { + allErr = multierror.Append(allErr, err) + } + return multierror.Append(allErr, + errors.Wrapf(err, "failed to create cache directory %q", c)) + } + return os.Rename(wip.Name(), c) + }, + abortFunc: func() error { + return os.Remove(wip.Name()) + }, } - // Cache the passed data to disk. - b2 := dc.bufPool.Get().(*bytes.Buffer) - b2.Reset() - b2.Write(p) - addFunc := func() { - defer dc.bufPool.Put(b2) - - var ( - c = dc.cachePath(key) - wip = dc.wipPath(key) - ) - - dc.wipLock.Lock(key) - if _, err := os.Stat(wip); err == nil { - dc.wipLock.Unlock(key) - return // Write in progress - } - if _, err := os.Stat(c); err == nil { - dc.wipLock.Unlock(key) - return // Already exists. - } - - // Write the contents to a temporary file - if err := os.MkdirAll(filepath.Dir(wip), os.ModePerm); err != nil { - fmt.Printf("Warning: Failed to Create blob cache directory %q: %v\n", c, err) - dc.wipLock.Unlock(key) - return - } - wipfile, err := os.Create(wip) - if err != nil { - fmt.Printf("Warning: failed to prepare temp file for storing cache %q", key) - dc.wipLock.Unlock(key) - return - } - dc.wipLock.Unlock(key) - - defer func() { - wipfile.Close() - os.Remove(wipfile.Name()) - }() - want := b2.Len() - if _, err := io.CopyN(wipfile, b2, int64(want)); err != nil { - fmt.Printf("Warning: failed to write cache: %v\n", err) - return - } - - // Commit the cache contents - if err := os.MkdirAll(filepath.Dir(c), os.ModePerm); err != nil { - fmt.Printf("Warning: Failed to Create blob cache directory %q: %v\n", c, err) - return - } - if err := os.Rename(wipfile.Name(), c); err != nil { - fmt.Printf("Warning: failed to commit cache to %q: %v\n", c, err) - return - } - file, err := os.Open(c) - if err != nil { - fmt.Printf("Warning: failed to open cache on %q: %v\n", c, err) - return - } + // If "direct" option is specified, do not cache the passed data on memory. + // This option is useful for preventing memory cache from being polluted by data + // that won't be accessed immediately. + if opt.direct { + return w, nil + } - // Cache the opened file for future use. If "direct" option is specified, this - // won't be done. This option is useful for preventing file cache from being - // polluted by data that won't be accessed immediately. - if opt.direct { - file.Close() - } else { - _, done, added := dc.fileCache.Add(key, file) + b := dc.bufPool.Get().(*bytes.Buffer) + b.Reset() + memW := &writer{ + WriteCloser: nopWriteCloser(io.Writer(b)), + commitFunc: func() error { + if dc.isClosed() { + w.Close() + return fmt.Errorf("cache is already closed") + } + cached, done, added := dc.cache.Add(key, b) if !added { - file.Close() // already exists in the cache. discard it. + dc.bufPool.Put(b) // already exists in the cache. abort it. } - done() // This will remain until it's evicted in lru cache. - } + commit := func() error { + defer done() + defer w.Close() + n, err := w.Write(cached.(*bytes.Buffer).Bytes()) + if err != nil || n != cached.(*bytes.Buffer).Len() { + w.Abort() + return err + } + return w.Commit() + } + if dc.syncAdd { + return commit() + } + go func() { + if err := commit(); err != nil { + fmt.Println("failed to commit to file:", err) + } + }() + return nil + }, + abortFunc: func() error { + defer w.Close() + defer w.Abort() + dc.bufPool.Put(b) // abort it. + return nil + }, } - if dc.syncAdd { - addFunc() - } else { - go addFunc() + return memW, nil +} + +func (dc *directoryCache) Close() error { + dc.closedMu.Lock() + defer dc.closedMu.Unlock() + if dc.closed { + return nil } + dc.closed = true + if err := os.RemoveAll(dc.directory); err != nil { + return err + } + return nil +} + +func (dc *directoryCache) isClosed() bool { + dc.closedMu.Lock() + closed := dc.closed + dc.closedMu.Unlock() + return closed } func (dc *directoryCache) cachePath(key string) string { return filepath.Join(dc.directory, key[:2], key) } -func (dc *directoryCache) wipPath(key string) string { - return filepath.Join(dc.directory, key[:2], "w", key) +func (dc *directoryCache) wipFile(key string) (*os.File, error) { + return ioutil.TempFile(dc.wipDirectory, key+"-*") } func NewMemoryCache() BlobCache { - return &memoryCache{ - membuf: map[string]string{}, + return &MemoryCache{ + Membuf: map[string]*bytes.Buffer{}, } } -// memoryCache is a cache implementation which backend is a memory. -type memoryCache struct { - membuf map[string]string // read-only []byte map is more ideal but we don't have it in golang... +// MemoryCache is a cache implementation which backend is a memory. +type MemoryCache struct { + Membuf map[string]*bytes.Buffer mu sync.Mutex } -func (mc *memoryCache) FetchAt(key string, offset int64, p []byte, opts ...Option) (n int, err error) { +func (mc *MemoryCache) Get(key string, opts ...Option) (Reader, error) { mc.mu.Lock() defer mc.mu.Unlock() - - cache, ok := mc.membuf[key] + b, ok := mc.Membuf[key] if !ok { - return 0, fmt.Errorf("Missed cache: %q", key) + return nil, fmt.Errorf("Missed cache: %q", key) } - return copy(p, cache[offset:]), nil + return &reader{bytes.NewReader(b.Bytes()), func() error { return nil }}, nil } -func (mc *memoryCache) Add(key string, p []byte, opts ...Option) { - mc.mu.Lock() - defer mc.mu.Unlock() - mc.membuf[key] = string(p) +func (mc *MemoryCache) Add(key string, opts ...Option) (Writer, error) { + b := new(bytes.Buffer) + return &writer{ + WriteCloser: nopWriteCloser(io.Writer(b)), + commitFunc: func() error { + mc.mu.Lock() + defer mc.mu.Unlock() + mc.Membuf[key] = b + return nil + }, + abortFunc: func() error { return nil }, + }, nil +} + +func (mc *MemoryCache) Close() error { + return nil +} + +type reader struct { + io.ReaderAt + closeFunc func() error +} + +func (r *reader) Close() error { return r.closeFunc() } + +type writer struct { + io.WriteCloser + commitFunc func() error + abortFunc func() error +} + +func (w *writer) Commit() error { + return w.commitFunc() +} + +func (w *writer) Abort() error { + return w.abortFunc() +} + +type writeCloser struct { + io.Writer + closeFunc func() error +} + +func (w *writeCloser) Close() error { return w.closeFunc() } + +func nopWriteCloser(w io.Writer) io.WriteCloser { + return &writeCloser{w, func() error { return nil }} } diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go index 4ae47fcf9e3d..fc42b6c3488c 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go @@ -37,6 +37,7 @@ import ( "sync" "github.com/containerd/stargz-snapshotter/estargz/errorutil" + "github.com/klauspost/compress/zstd" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -112,11 +113,11 @@ func (b *Blob) TOCDigest() digest.Digest { return b.tocDigest } -// Build builds an eStargz blob which is an extended version of stargz, from tar blob passed -// through the argument. If there are some prioritized files are listed in the option, these -// files are grouped as "prioritized" and can be used for runtime optimization (e.g. prefetch). -// This function builds a blob in parallel, with dividing that blob into several (at least the -// number of runtime.GOMAXPROCS(0)) sub-blobs. +// Build builds an eStargz blob which is an extended version of stargz, from a blob (gzip, zstd +// or plain tar) passed through the argument. If there are some prioritized files are listed in +// the option, these files are grouped as "prioritized" and can be used for runtime optimization +// (e.g. prefetch). This function builds a blob in parallel, with dividing that blob into several +// (at least the number of runtime.GOMAXPROCS(0)) sub-blobs. func Build(tarBlob *io.SectionReader, opt ...Option) (_ *Blob, rErr error) { var opts options opts.compressionLevel = gzip.BestCompression // BestCompression by default @@ -133,6 +134,10 @@ func Build(tarBlob *io.SectionReader, opt ...Option) (_ *Blob, rErr error) { } } }() + tarBlob, err := decompressBlob(tarBlob, layerFiles) + if err != nil { + return nil, err + } entries, err := sortEntries(tarBlob, opts.prioritizedFiles, opts.missedPrioritizedFiles) if err != nil { return nil, err @@ -593,3 +598,42 @@ func (cr *countReader) currentPos() int64 { return *cr.cPos } + +func decompressBlob(org *io.SectionReader, tmp *tempFiles) (*io.SectionReader, error) { + if org.Size() < 4 { + return org, nil + } + src := make([]byte, 4) + if _, err := org.Read(src); err != nil && err != io.EOF { + return nil, err + } + var dR io.Reader + if bytes.Equal([]byte{0x1F, 0x8B, 0x08}, src[:3]) { + // gzip + dgR, err := gzip.NewReader(io.NewSectionReader(org, 0, org.Size())) + if err != nil { + return nil, err + } + defer dgR.Close() + dR = io.Reader(dgR) + } else if bytes.Equal([]byte{0x28, 0xb5, 0x2f, 0xfd}, src[:4]) { + // zstd + dzR, err := zstd.NewReader(io.NewSectionReader(org, 0, org.Size())) + if err != nil { + return nil, err + } + defer dzR.Close() + dR = io.Reader(dzR) + } else { + // uncompressed + return io.NewSectionReader(org, 0, org.Size()), nil + } + b, err := tmp.TempFile("", "uncompresseddata") + if err != nil { + return nil, err + } + if _, err := io.Copy(b, dR); err != nil { + return nil, err + } + return fileSectionReader(b) +} diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod index e8e01f5cc130..bf76d340301a 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.mod @@ -1,8 +1,9 @@ module github.com/containerd/stargz-snapshotter/estargz -go 1.15 +go 1.16 require ( + github.com/klauspost/compress v1.12.3 github.com/opencontainers/go-digest v1.0.0 github.com/pkg/errors v0.9.1 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum index d81890710b1e..793b74fda17e 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/go.sum @@ -1,3 +1,7 @@ +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/types.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/types.go index b0fb92db6612..680347a79cf1 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/types.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/types.go @@ -73,6 +73,12 @@ const ( // of an image manifest. TOCJSONDigestAnnotation = "containerd.io/snapshot/stargz/toc.digest" + // StoreUncompressedSizeAnnotation is an additional annotation key for eStargz to enable lazy + // pulling on containers/storage. Stargz Store is required to expose the layer's uncompressed size + // to the runtime but current OCI image doesn't ship this information by default. So we store this + // to the special annotation. + StoreUncompressedSizeAnnotation = "io.containers.estargz.uncompressed-size" + // PrefetchLandmark is a file entry which indicates the end position of // prefetch in the stargz file. PrefetchLandmark = ".prefetch.landmark" diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/fs.go b/vendor/github.com/containerd/stargz-snapshotter/fs/fs.go index 681faa471927..cb85c244e6f2 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/fs/fs.go +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/fs.go @@ -37,28 +37,23 @@ package fs import ( - "bytes" "context" - "encoding/json" "fmt" - "io" - "os" - "sort" + "os/exec" "strconv" - "strings" "sync" "syscall" "time" - "unsafe" "github.com/containerd/containerd/log" + "github.com/containerd/containerd/reference" "github.com/containerd/containerd/remotes/docker" "github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/fs/config" "github.com/containerd/stargz-snapshotter/fs/layer" fsmetrics "github.com/containerd/stargz-snapshotter/fs/metrics" "github.com/containerd/stargz-snapshotter/fs/source" - snbase "github.com/containerd/stargz-snapshotter/snapshot" + "github.com/containerd/stargz-snapshotter/snapshot" "github.com/containerd/stargz-snapshotter/task" metrics "github.com/docker/go-metrics" fusefs "github.com/hanwen/go-fuse/v2/fs" @@ -66,20 +61,11 @@ import ( digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" - "golang.org/x/sys/unix" ) -var opaqueXattrs = []string{"trusted.overlay.opaque", "user.overlay.opaque"} - const ( - blockSize = 4096 - whiteoutPrefix = ".wh." - whiteoutOpaqueDir = whiteoutPrefix + whiteoutPrefix + ".opq" - opaqueXattrValue = "y" - stateDirName = ".stargz-snapshotter" defaultMaxConcurrency = 2 - statFileMode = syscall.S_IFREG | 0400 // -r-------- - stateDirMode = syscall.S_IFDIR | 0500 // dr-x------ + fusermountBin = "fusermount" ) type Option func(*options) @@ -94,7 +80,7 @@ func WithGetSources(s source.GetSources) Option { } } -func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snbase.FileSystem, err error) { +func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snapshot.FileSystem, err error) { var fsOpts options for _, o := range opts { o(&fsOpts) @@ -105,8 +91,9 @@ func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snbase.Fil } getSources := fsOpts.getSources if getSources == nil { - getSources = source.FromDefaultLabels( - docker.ConfigureDefaultRegistries(docker.WithPlainHTTP(docker.MatchLocalhost))) + getSources = source.FromDefaultLabels(func(refspec reference.Spec) (hosts []docker.RegistryHost, _ error) { + return docker.ConfigureDefaultRegistries(docker.WithPlainHTTP(docker.MatchLocalhost))(refspec.Hostname()) + }) } tm := task.NewBackgroundTaskManager(maxConcurrency, 5*time.Second) r, err := layer.NewResolver(root, tm, cfg) @@ -196,7 +183,7 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s // Avoids to get canceled by client. ctx := log.WithLogger(context.Background(), log.G(ctx).WithField("mountpoint", mountpoint)) - _, err := fs.resolver.Resolve(ctx, preResolve.Hosts, preResolve.Name, desc) + err := fs.resolver.Cache(ctx, preResolve.Hosts, preResolve.Name, desc) if err != nil { log.G(ctx).WithError(err).Debug("failed to pre-resolve") } @@ -214,6 +201,11 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s log.G(ctx).Debug("failed to resolve layer (timeout)") return fmt.Errorf("failed to resolve layer (timeout)") } + defer func() { + if retErr != nil { + l.Done() // don't use this layer. + } + }() // Verify layer's content if fs.disableVerification { @@ -242,6 +234,11 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s // Verification must be done. Don't mount this layer. return fmt.Errorf("digest of TOC JSON must be passed") } + node, err := l.RootNode() + if err != nil { + log.G(ctx).WithError(err).Warnf("Failed to get root node") + return errors.Wrapf(err, "failed to get root node") + } // Register the mountpoint layer fs.layerMu.Lock() @@ -283,28 +280,28 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s }() } - // Mounting stargz + // mount the node to the specified mountpoint // TODO: bind mount the state directory as a read-only fs on snapshotter's side timeSec := time.Second - rawFS := fusefs.NewNodeFS(&node{ - fs: fs, - layer: l, - e: l.Root(), - s: newState(l), - root: mountpoint, - }, &fusefs.Options{ + rawFS := fusefs.NewNodeFS(node, &fusefs.Options{ AttrTimeout: &timeSec, EntryTimeout: &timeSec, NullPermissions: true, }) - server, err := fuse.NewServer(rawFS, mountpoint, &fuse.MountOptions{ - AllowOther: true, // allow users other than root&mounter to access fs - FsName: "stargz", // name this filesystem as "stargz" - Options: []string{"suid"}, // allow setuid inside container + mountOpts := &fuse.MountOptions{ + AllowOther: true, // allow users other than root&mounter to access fs + FsName: "stargz", // name this filesystem as "stargz" Debug: fs.debug, - }) + } + if _, err := exec.LookPath(fusermountBin); err == nil { + mountOpts.Options = []string{"suid"} // option for fusermount; allow setuid inside container + } else { + log.G(ctx).WithError(err).Debugf("%s not installed; trying direct mount", fusermountBin) + mountOpts.DirectMount = true + } + server, err := fuse.NewServer(rawFS, mountpoint, mountOpts) if err != nil { - log.G(ctx).WithError(err).Debug("failed to make filesstem server") + log.G(ctx).WithError(err).Debug("failed to make filesystem server") return err } @@ -381,11 +378,13 @@ func (fs *filesystem) check(ctx context.Context, l layer.Layer, labels map[strin func (fs *filesystem) Unmount(ctx context.Context, mountpoint string) error { fs.layerMu.Lock() - if _, ok := fs.layer[mountpoint]; !ok { + l, ok := fs.layer[mountpoint] + if !ok { fs.layerMu.Unlock() return fmt.Errorf("specified path %q isn't a mountpoint", mountpoint) } delete(fs.layer, mountpoint) // unregisters the corresponding layer + l.Done() fs.layerMu.Unlock() fs.metricsController.Remove(mountpoint) // The goroutine which serving the mountpoint possibly becomes not responding. @@ -405,571 +404,3 @@ func neighboringLayers(manifest ocispec.Manifest, target ocispec.Descriptor) (de } return } - -type fileReader interface { - OpenFile(name string) (io.ReaderAt, error) -} - -// node is a filesystem inode abstraction. -type node struct { - fusefs.Inode - fs *filesystem - layer fileReader - e *estargz.TOCEntry - s *state - root string - opaque bool // true if this node is an overlayfs opaque directory -} - -var _ = (fusefs.InodeEmbedder)((*node)(nil)) - -var _ = (fusefs.NodeReaddirer)((*node)(nil)) - -func (n *node) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) { - var ents []fuse.DirEntry - whiteouts := map[string]*estargz.TOCEntry{} - normalEnts := map[string]bool{} - n.e.ForeachChild(func(baseName string, ent *estargz.TOCEntry) bool { - - // We don't want to show prefetch landmarks in "/". - if n.e.Name == "" && (baseName == estargz.PrefetchLandmark || baseName == estargz.NoPrefetchLandmark) { - return true - } - - // We don't want to show whiteouts. - if strings.HasPrefix(baseName, whiteoutPrefix) { - if baseName == whiteoutOpaqueDir { - return true - } - // Add the overlayfs-compiant whiteout later. - whiteouts[baseName] = ent - return true - } - - // This is a normal entry. - normalEnts[baseName] = true - ents = append(ents, fuse.DirEntry{ - Mode: modeOfEntry(ent), - Name: baseName, - Ino: inodeOfEnt(ent), - }) - return true - }) - - // Append whiteouts if no entry replaces the target entry in the lower layer. - for w, ent := range whiteouts { - if !normalEnts[w[len(whiteoutPrefix):]] { - ents = append(ents, fuse.DirEntry{ - Mode: syscall.S_IFCHR, - Name: w[len(whiteoutPrefix):], - Ino: inodeOfEnt(ent), - }) - - } - } - - // Avoid undeterministic order of entries on each call - sort.Slice(ents, func(i, j int) bool { - return ents[i].Name < ents[j].Name - }) - - return fusefs.NewListDirStream(ents), 0 -} - -var _ = (fusefs.NodeLookuper)((*node)(nil)) - -func (n *node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fusefs.Inode, syscall.Errno) { - // We don't want to show prefetch landmarks in "/". - if n.e.Name == "" && (name == estargz.PrefetchLandmark || name == estargz.NoPrefetchLandmark) { - return nil, syscall.ENOENT - } - - // We don't want to show whiteouts. - if strings.HasPrefix(name, whiteoutPrefix) { - return nil, syscall.ENOENT - } - - // state directory - if n.e.Name == "" && name == stateDirName { - return n.NewInode(ctx, n.s, stateToAttr(n.s, &out.Attr)), 0 - } - - // lookup stargz TOCEntry - ce, ok := n.e.LookupChild(name) - if !ok { - // If the entry exists as a whiteout, show an overlayfs-styled whiteout node. - if wh, ok := n.e.LookupChild(fmt.Sprintf("%s%s", whiteoutPrefix, name)); ok { - return n.NewInode(ctx, &whiteout{ - e: wh, - }, entryToWhAttr(wh, &out.Attr)), 0 - } - return nil, syscall.ENOENT - } - var opaque bool - if _, ok := ce.LookupChild(whiteoutOpaqueDir); ok { - // This entry is an opaque directory so make it recognizable for overlayfs. - opaque = true - } - - return n.NewInode(ctx, &node{ - fs: n.fs, - layer: n.layer, - e: ce, - s: n.s, - root: n.root, - opaque: opaque, - }, entryToAttr(ce, &out.Attr)), 0 -} - -var _ = (fusefs.NodeOpener)((*node)(nil)) - -func (n *node) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { - ra, err := n.layer.OpenFile(n.e.Name) - if err != nil { - n.s.report(fmt.Errorf("failed to open node: %v", err)) - return nil, 0, syscall.EIO - } - return &file{ - n: n, - e: n.e, - ra: ra, - }, 0, 0 -} - -var _ = (fusefs.NodeGetattrer)((*node)(nil)) - -func (n *node) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { - entryToAttr(n.e, &out.Attr) - return 0 -} - -var _ = (fusefs.NodeGetxattrer)((*node)(nil)) - -func (n *node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { - for _, opaqueXattr := range opaqueXattrs { - if attr == opaqueXattr && n.opaque { - // This node is an opaque directory so give overlayfs-compliant indicator. - if len(dest) < len(opaqueXattrValue) { - return uint32(len(opaqueXattrValue)), syscall.ERANGE - } - return uint32(copy(dest, opaqueXattrValue)), 0 - } - } - if v, ok := n.e.Xattrs[attr]; ok { - if len(dest) < len(v) { - return uint32(len(v)), syscall.ERANGE - } - return uint32(copy(dest, v)), 0 - } - return 0, syscall.ENODATA -} - -var _ = (fusefs.NodeListxattrer)((*node)(nil)) - -func (n *node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { - var attrs []byte - if n.opaque { - // This node is an opaque directory so add overlayfs-compliant indicator. - for _, opaqueXattr := range opaqueXattrs { - attrs = append(attrs, []byte(opaqueXattr+"\x00")...) - } - } - for k := range n.e.Xattrs { - attrs = append(attrs, []byte(k+"\x00")...) - } - if len(dest) < len(attrs) { - return uint32(len(attrs)), syscall.ERANGE - } - return uint32(copy(dest, attrs)), 0 -} - -var _ = (fusefs.NodeReadlinker)((*node)(nil)) - -func (n *node) Readlink(ctx context.Context) ([]byte, syscall.Errno) { - return []byte(n.e.LinkName), 0 -} - -var _ = (fusefs.NodeStatfser)((*node)(nil)) - -func (n *node) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { - defaultStatfs(out) - return 0 -} - -// file is a file abstraction which implements file handle in go-fuse. -type file struct { - n *node - e *estargz.TOCEntry - ra io.ReaderAt -} - -var _ = (fusefs.FileReader)((*file)(nil)) - -func (f *file) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { - n, err := f.ra.ReadAt(dest, off) - if err != nil && err != io.EOF { - f.n.s.report(fmt.Errorf("failed to read node: %v", err)) - return nil, syscall.EIO - } - return fuse.ReadResultData(dest[:n]), 0 -} - -var _ = (fusefs.FileGetattrer)((*file)(nil)) - -func (f *file) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno { - entryToAttr(f.e, &out.Attr) - return 0 -} - -// whiteout is a whiteout abstraction compliant to overlayfs. -type whiteout struct { - fusefs.Inode - e *estargz.TOCEntry -} - -var _ = (fusefs.NodeGetattrer)((*whiteout)(nil)) - -func (w *whiteout) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { - entryToWhAttr(w.e, &out.Attr) - return 0 -} - -var _ = (fusefs.NodeStatfser)((*whiteout)(nil)) - -func (w *whiteout) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { - defaultStatfs(out) - return 0 -} - -// newState provides new state directory node. -// It creates statFile at the same time to give it stable inode number. -func newState(layer layer.Layer) *state { - info := layer.Info() - return &state{ - statFile: &statFile{ - name: info.Digest.String() + ".json", - statJSON: statJSON{ - Digest: info.Digest.String(), - Size: info.Size, - }, - layer: layer, - }, - } -} - -// state is a directory which contain a "state file" of this layer aming to -// observability. This filesystem uses it to report something(e.g. error) to -// the clients(e.g. Kubernetes's livenessProbe). -// This directory has mode "dr-x------ root root". -type state struct { - fusefs.Inode - statFile *statFile -} - -var _ = (fusefs.NodeReaddirer)((*state)(nil)) - -func (s *state) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) { - return fusefs.NewListDirStream([]fuse.DirEntry{ - { - Mode: statFileMode, - Name: s.statFile.name, - Ino: inodeOfStatFile(s.statFile), - }, - }), 0 -} - -var _ = (fusefs.NodeLookuper)((*state)(nil)) - -func (s *state) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fusefs.Inode, syscall.Errno) { - if name != s.statFile.name { - return nil, syscall.ENOENT - } - attr, errno := s.statFile.attr(&out.Attr) - if errno != 0 { - return nil, errno - } - return s.NewInode(ctx, s.statFile, attr), 0 -} - -var _ = (fusefs.NodeGetattrer)((*state)(nil)) - -func (s *state) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { - stateToAttr(s, &out.Attr) - return 0 -} - -var _ = (fusefs.NodeStatfser)((*state)(nil)) - -func (s *state) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { - defaultStatfs(out) - return 0 -} - -func (s *state) report(err error) { - s.statFile.report(err) -} - -type statJSON struct { - Error string `json:"error,omitempty"` - Digest string `json:"digest"` - // URL is excluded for potential security reason - Size int64 `json:"size"` - FetchedSize int64 `json:"fetchedSize"` - FetchedPercent float64 `json:"fetchedPercent"` // Fetched / Size * 100.0 -} - -// statFile is a file which contain something to be reported from this layer. -// This filesystem uses statFile.report() to report something(e.g. error) to -// the clients(e.g. Kubernetes's livenessProbe). -// This file has mode "-r-------- root root". -type statFile struct { - fusefs.Inode - name string - layer layer.Layer - statJSON statJSON - mu sync.Mutex -} - -var _ = (fusefs.NodeOpener)((*statFile)(nil)) - -func (sf *statFile) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { - return nil, 0, 0 -} - -var _ = (fusefs.NodeReader)((*statFile)(nil)) - -func (sf *statFile) Read(ctx context.Context, f fusefs.FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { - sf.mu.Lock() - defer sf.mu.Unlock() - st, err := sf.updateStatUnlocked() - if err != nil { - return nil, syscall.EIO - } - n, err := bytes.NewReader(st).ReadAt(dest, off) - if err != nil && err != io.EOF { - return nil, syscall.EIO - } - return fuse.ReadResultData(dest[:n]), 0 -} - -var _ = (fusefs.NodeGetattrer)((*statFile)(nil)) - -func (sf *statFile) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { - _, errno := sf.attr(&out.Attr) - return errno -} - -var _ = (fusefs.NodeStatfser)((*statFile)(nil)) - -func (sf *statFile) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { - defaultStatfs(out) - return 0 -} - -func (sf *statFile) report(err error) { - sf.mu.Lock() - defer sf.mu.Unlock() - sf.statJSON.Error = err.Error() -} - -func (sf *statFile) attr(out *fuse.Attr) (fusefs.StableAttr, syscall.Errno) { - sf.mu.Lock() - defer sf.mu.Unlock() - - st, err := sf.updateStatUnlocked() - if err != nil { - return fusefs.StableAttr{}, syscall.EIO - } - - return statFileToAttr(sf, uint64(len(st)), out), 0 -} - -func (sf *statFile) updateStatUnlocked() ([]byte, error) { - sf.statJSON.FetchedSize = sf.layer.Info().FetchedSize - sf.statJSON.FetchedPercent = float64(sf.statJSON.FetchedSize) / float64(sf.statJSON.Size) * 100.0 - j, err := json.Marshal(&sf.statJSON) - if err != nil { - return nil, err - } - j = append(j, []byte("\n")...) - return j, nil -} - -// inodeOfEnt calculates the inode number which is one-to-one conresspondence -// with the TOCEntry insntance. -func inodeOfEnt(e *estargz.TOCEntry) uint64 { - return uint64(uintptr(unsafe.Pointer(e))) -} - -// entryToAttr converts stargz's TOCEntry to go-fuse's Attr. -func entryToAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr { - out.Ino = inodeOfEnt(e) - out.Size = uint64(e.Size) - out.Blksize = blockSize - out.Blocks = out.Size / uint64(out.Blksize) - if out.Size%uint64(out.Blksize) > 0 { - out.Blocks++ - } - mtime := e.ModTime() - out.SetTimes(nil, &mtime, nil) - out.Mode = modeOfEntry(e) - out.Owner = fuse.Owner{Uid: uint32(e.UID), Gid: uint32(e.GID)} - out.Rdev = uint32(unix.Mkdev(uint32(e.DevMajor), uint32(e.DevMinor))) - out.Nlink = uint32(e.NumLink) - if out.Nlink == 0 { - out.Nlink = 1 // zero "NumLink" means one. - } - out.Padding = 0 // TODO - - return fusefs.StableAttr{ - Mode: out.Mode, - Ino: out.Ino, - // NOTE: The inode number is unique throughout the lifettime of - // this filesystem so we don't consider about generation at this - // moment. - } -} - -// entryToWhAttr converts stargz's TOCEntry to go-fuse's Attr of whiteouts. -func entryToWhAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr { - fi := e.Stat() - out.Ino = inodeOfEnt(e) - out.Size = 0 - out.Blksize = blockSize - out.Blocks = 0 - mtime := fi.ModTime() - out.SetTimes(nil, &mtime, nil) - out.Mode = syscall.S_IFCHR - out.Owner = fuse.Owner{Uid: 0, Gid: 0} - out.Rdev = uint32(unix.Mkdev(0, 0)) - out.Nlink = 1 - out.Padding = 0 // TODO - - return fusefs.StableAttr{ - Mode: out.Mode, - Ino: out.Ino, - // NOTE: The inode number is unique throughout the lifettime of - // this filesystem so we don't consider about generation at this - // moment. - } -} - -// inodeOfState calculates the inode number which is one-to-one conresspondence -// with the state directory insntance which was created on mount. -func inodeOfState(s *state) uint64 { - return uint64(uintptr(unsafe.Pointer(s))) -} - -// stateToAttr converts state directory to go-fuse's Attr. -func stateToAttr(s *state, out *fuse.Attr) fusefs.StableAttr { - out.Ino = inodeOfState(s) - out.Size = 0 - out.Blksize = blockSize - out.Blocks = 0 - out.Nlink = 1 - - // root can read and open it (dr-x------ root root). - out.Mode = stateDirMode - out.Owner = fuse.Owner{Uid: 0, Gid: 0} - - // dummy - out.Mtime = 0 - out.Mtimensec = 0 - out.Rdev = 0 - out.Padding = 0 - - return fusefs.StableAttr{ - Mode: out.Mode, - Ino: out.Ino, - // NOTE: The inode number is unique throughout the lifettime of - // this filesystem so we don't consider about generation at this - // moment. - } -} - -// inodeOfStatFile calculates the inode number which is one-to-one conresspondence -// with the stat file insntance which was created on mount. -func inodeOfStatFile(s *statFile) uint64 { - return uint64(uintptr(unsafe.Pointer(s))) -} - -// statFileToAttr converts stat file to go-fuse's Attr. -func statFileToAttr(sf *statFile, size uint64, out *fuse.Attr) fusefs.StableAttr { - out.Ino = inodeOfStatFile(sf) - out.Size = size - out.Blksize = blockSize - out.Blocks = out.Size / uint64(out.Blksize) - out.Nlink = 1 - - // Root can read it ("-r-------- root root"). - out.Mode = statFileMode - out.Owner = fuse.Owner{Uid: 0, Gid: 0} - - // dummy - out.Mtime = 0 - out.Mtimensec = 0 - out.Rdev = 0 - out.Padding = 0 - - return fusefs.StableAttr{ - Mode: out.Mode, - Ino: out.Ino, - // NOTE: The inode number is unique throughout the lifettime of - // this filesystem so we don't consider about generation at this - // moment. - } -} - -// modeOfEntry gets system's mode bits from TOCEntry -func modeOfEntry(e *estargz.TOCEntry) uint32 { - m := e.Stat().Mode() - - // Permission bits - res := uint32(m & os.ModePerm) - - // File type bits - switch m & os.ModeType { - case os.ModeDevice: - res |= syscall.S_IFBLK - case os.ModeDevice | os.ModeCharDevice: - res |= syscall.S_IFCHR - case os.ModeDir: - res |= syscall.S_IFDIR - case os.ModeNamedPipe: - res |= syscall.S_IFIFO - case os.ModeSymlink: - res |= syscall.S_IFLNK - case os.ModeSocket: - res |= syscall.S_IFSOCK - default: // regular file. - res |= syscall.S_IFREG - } - - // suid, sgid, sticky bits - if m&os.ModeSetuid != 0 { - res |= syscall.S_ISUID - } - if m&os.ModeSetgid != 0 { - res |= syscall.S_ISGID - } - if m&os.ModeSticky != 0 { - res |= syscall.S_ISVTX - } - - return res -} - -func defaultStatfs(stat *fuse.StatfsOut) { - - // http://man7.org/linux/man-pages/man2/statfs.2.html - stat.Blocks = 0 // dummy - stat.Bfree = 0 - stat.Bavail = 0 - stat.Files = 0 // dummy - stat.Ffree = 0 - stat.Bsize = blockSize - stat.NameLen = 1<<32 - 1 - stat.Frsize = blockSize - stat.Padding = 0 - stat.Spare = [6]uint32{} -} diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/layer/layer.go b/vendor/github.com/containerd/stargz-snapshotter/fs/layer/layer.go index db007f0900df..84b3cae1060e 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/fs/layer/layer.go +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/layer/layer.go @@ -27,6 +27,7 @@ import ( "context" "fmt" "io" + "io/ioutil" "os" "path/filepath" "sync" @@ -34,19 +35,20 @@ import ( "github.com/containerd/containerd/log" "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes/docker" "github.com/containerd/stargz-snapshotter/cache" "github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/fs/config" "github.com/containerd/stargz-snapshotter/fs/reader" "github.com/containerd/stargz-snapshotter/fs/remote" + "github.com/containerd/stargz-snapshotter/fs/source" "github.com/containerd/stargz-snapshotter/task" "github.com/containerd/stargz-snapshotter/util/lrucache" - "github.com/golang/groupcache/lru" + "github.com/containerd/stargz-snapshotter/util/namedmutex" + fusefs "github.com/hanwen/go-fuse/v2/fs" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" - "golang.org/x/sync/singleflight" + "github.com/sirupsen/logrus" ) const ( @@ -59,18 +61,17 @@ const ( // Layer represents a layer. type Layer interface { - // Info returns the information of this layer. Info() Info - // Root returns the root node of this layer. - Root() *estargz.TOCEntry + // RootNode returns the root node of this layer. + RootNode() (fusefs.InodeEmbedder, error) // Check checks if the layer is still connectable. Check() error // Refresh refreshes the layer connection. - Refresh(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error + Refresh(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error // Verify verifies this layer using the passed TOC Digest. Verify(tocDigest digest.Digest) (err error) @@ -78,15 +79,14 @@ type Layer interface { // SkipVerify skips verification for this layer. SkipVerify() - // OpenFile opens a file. - // Calling this function before calling Verify or SkipVerify will fail. - OpenFile(name string) (io.ReaderAt, error) - // Prefetch prefetches the specified size. If the layer is eStargz and contains landmark files, // the range indicated by these files is respected. // Calling this function before calling Verify or SkipVerify will fail. Prefetch(prefetchSize int64) error + // ReadAt reads this layer. + ReadAt([]byte, int64, ...remote.Option) (int, error) + // WaitForPrefetchCompletion waits untils Prefetch completes. WaitForPrefetchCompletion() error @@ -94,6 +94,10 @@ type Layer interface { // Fetching contents is done as a background task. // Calling this function before calling Verify or SkipVerify will fail. BackgroundFetch() error + + // Done releases the reference to this layer. The resources related to this layer will be + // discarded sooner or later. Queries after calling this function won't be serviced. + Done() } // Info is the current status of a layer. @@ -105,15 +109,16 @@ type Info struct { // Resolver resolves the layer location and provieds the handler of that layer. type Resolver struct { + rootDir string resolver *remote.Resolver prefetchTimeout time.Duration - layerCache *lru.Cache + layerCache *lrucache.Cache layerCacheMu sync.Mutex - blobCache *lru.Cache + blobCache *lrucache.Cache blobCacheMu sync.Mutex backgroundTaskManager *task.BackgroundTaskManager - fsCache cache.BlobCache - resolveG singleflight.Group + resolveLock *namedmutex.NamedMutex + config config.Config } // NewResolver returns a new layer resolver. @@ -127,27 +132,42 @@ func NewResolver(root string, backgroundTaskManager *task.BackgroundTaskManager, prefetchTimeout = defaultPrefetchTimeoutSec * time.Second } - // Prepare contents cache - fsCache, err := newCache(filepath.Join(root, "fscache"), cfg.FSCacheType, cfg) - if err != nil { - return nil, errors.Wrapf(err, "failed to create fs cache") + // layerCache caches resolved layers for future use. This is useful in a use-case where + // the filesystem resolves and caches all layers in an image (not only queried one) in parallel, + // before they are actually queried. + layerCache := lrucache.New(resolveResultEntry) + layerCache.OnEvicted = func(key string, value interface{}) { + if err := value.(*layer).close(); err != nil { + logrus.WithField("key", key).WithError(err).Warnf("failed to clean up layer") + return + } + logrus.WithField("key", key).Debugf("cleaned up layer") } - httpCache, err := newCache(filepath.Join(root, "httpcache"), cfg.HTTPCacheType, cfg) - if err != nil { - return nil, errors.Wrapf(err, "failed to create http cache") + + // blobCache caches resolved blobs for futural use. This is especially useful when a layer + // isn't eStargz/stargz (the *layer object won't be created/cached in this case). + blobCache := lrucache.New(resolveResultEntry) + blobCache.OnEvicted = func(key string, value interface{}) { + if err := value.(remote.Blob).Close(); err != nil { + logrus.WithField("key", key).WithError(err).Warnf("failed to clean up blob") + return + } + logrus.WithField("key", key).Debugf("cleaned up blob") } return &Resolver{ - resolver: remote.NewResolver(httpCache, cfg.BlobConfig), - fsCache: fsCache, - layerCache: lru.New(resolveResultEntry), - blobCache: lru.New(resolveResultEntry), + rootDir: root, + resolver: remote.NewResolver(cfg.BlobConfig), + layerCache: layerCache, + blobCache: blobCache, prefetchTimeout: prefetchTimeout, backgroundTaskManager: backgroundTaskManager, + config: cfg, + resolveLock: new(namedmutex.NamedMutex), }, nil } -func newCache(cachepath string, cacheType string, cfg config.Config) (cache.BlobCache, error) { +func newCache(root string, cacheType string, cfg config.Config) (cache.BlobCache, error) { if cacheType == memoryCacheType { return cache.NewMemoryCache(), nil } @@ -174,8 +194,16 @@ func newCache(cachepath string, cacheType string, cfg config.Config) (cache.Blob fCache.OnEvicted = func(key string, value interface{}) { value.(*os.File).Close() } + // create a cache on an unique directory + if err := os.MkdirAll(root, 0700); err != nil { + return nil, err + } + cachePath, err := ioutil.TempDir(root, "") + if err != nil { + return nil, errors.Wrapf(err, "failed to initialize directory cache") + } return cache.NewDirectoryCache( - cachepath, + cachePath, cache.DirectoryCacheConfig{ SyncAdd: dcc.SyncAdd, DataCache: dCache, @@ -186,107 +214,148 @@ func newCache(cachepath string, cacheType string, cfg config.Config) (cache.Blob } // Resolve resolves a layer based on the passed layer blob information. -func (r *Resolver) Resolve(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (_ Layer, retErr error) { +func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (_ Layer, retErr error) { name := refspec.String() + "/" + desc.Digest.String() + + // Wait if resolving this layer is already running. The result + // can hopefully get from the LRU cache. + r.resolveLock.Lock(name) + defer r.resolveLock.Unlock(name) + ctx = log.WithLogger(ctx, log.G(ctx).WithField("src", name)) // First, try to retrieve this layer from the underlying LRU cache. r.layerCacheMu.Lock() - c, ok := r.layerCache.Get(name) + c, done, ok := r.layerCache.Get(name) r.layerCacheMu.Unlock() - if ok && c.(*layer).Check() == nil { - return c.(*layer), nil + if ok { + if l := c.(*layer); l.Check() == nil { + log.G(ctx).Debugf("hit layer cache %q", name) + return &layerRef{l, done}, nil + } + // Cached layer is invalid + done() + r.layerCacheMu.Lock() + r.layerCache.Remove(name) + r.layerCacheMu.Unlock() } - resultChan := r.resolveG.DoChan(name, func() (interface{}, error) { - log.G(ctx).Debugf("resolving") + log.G(ctx).Debugf("resolving") - // Resolve the blob. - blobR, err := r.resolveBlob(ctx, hosts, refspec, desc) - if err != nil { - return nil, errors.Wrapf(err, "failed to resolve the blob") + // Resolve the blob. + blobR, err := r.resolveBlob(ctx, hosts, refspec, desc) + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve the blob") + } + defer func() { + if retErr != nil { + blobR.done() } + }() - // Get a reader for stargz archive. - // Each file's read operation is a prioritized task and all background tasks - // will be stopped during the execution so this can avoid being disturbed for - // NW traffic by background tasks. - sr := io.NewSectionReader(readerAtFunc(func(p []byte, offset int64) (n int, err error) { - r.backgroundTaskManager.DoPrioritizedTask() - defer r.backgroundTaskManager.DonePrioritizedTask() - return blobR.ReadAt(p, offset) - }), 0, blobR.Size()) - vr, root, err := reader.NewReader(sr, r.fsCache) - if err != nil { - return nil, errors.Wrap(err, "failed to read layer") + fsCache, err := newCache(filepath.Join(r.rootDir, "fscache"), r.config.FSCacheType, r.config) + if err != nil { + return nil, errors.Wrapf(err, "failed to create fs cache") + } + defer func() { + if retErr != nil { + fsCache.Close() } - - // Combine layer information together - l := newLayer(r, desc, blobR, vr, root) - r.layerCacheMu.Lock() - r.layerCache.Add(name, l) - r.layerCacheMu.Unlock() - - log.G(ctx).Debugf("resolved") - return l, nil - }) - - var res singleflight.Result - select { - case res = <-resultChan: - case <-time.After(30 * time.Second): - r.resolveG.Forget(name) - return nil, fmt.Errorf("failed to resolve layer (timeout)") + }() + + // Get a reader for stargz archive. + // Each file's read operation is a prioritized task and all background tasks + // will be stopped during the execution so this can avoid being disturbed for + // NW traffic by background tasks. + sr := io.NewSectionReader(readerAtFunc(func(p []byte, offset int64) (n int, err error) { + r.backgroundTaskManager.DoPrioritizedTask() + defer r.backgroundTaskManager.DonePrioritizedTask() + return blobR.ReadAt(p, offset) + }), 0, blobR.Size()) + vr, err := reader.NewReader(sr, fsCache) + if err != nil { + return nil, errors.Wrap(err, "failed to read layer") } - if res.Err != nil || res.Val == nil { - return nil, fmt.Errorf("failed to resolve layer: %v", res.Err) + + // Combine layer information together and cache it. + l := newLayer(r, desc, blobR, vr) + r.layerCacheMu.Lock() + cachedL, done2, added := r.layerCache.Add(name, l) + r.layerCacheMu.Unlock() + if !added { + l.close() // layer already exists in the cache. discrad this. } - return res.Val.(*layer), nil + log.G(ctx).Debugf("resolved") + return &layerRef{cachedL.(*layer), done2}, nil } // resolveBlob resolves a blob based on the passed layer blob information. -func (r *Resolver) resolveBlob(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (remote.Blob, error) { +func (r *Resolver) resolveBlob(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (_ *blobRef, retErr error) { name := refspec.String() + "/" + desc.Digest.String() - // Resolve the blob. The result will be cached for future use. This is effective - // in some failure cases including resolving is succeeded but the blob is non-stargz. - var blob remote.Blob + // Try to retrieve the blob from the underlying LRU cache. r.blobCacheMu.Lock() - c, ok := r.blobCache.Get(name) + c, done, ok := r.blobCache.Get(name) r.blobCacheMu.Unlock() if ok { if blob := c.(remote.Blob); blob.Check() == nil { - return blob, nil + return &blobRef{blob, done}, nil } + // invalid blob. discard this. + done() + r.blobCacheMu.Lock() + r.blobCache.Remove(name) + r.blobCacheMu.Unlock() } - var err error - blob, err = r.resolver.Resolve(ctx, hosts, refspec, desc) + httpCache, err := newCache(filepath.Join(r.rootDir, "httpcache"), r.config.HTTPCacheType, r.config) + if err != nil { + return nil, errors.Wrapf(err, "failed to create http cache") + } + defer func() { + if retErr != nil { + httpCache.Close() + } + }() + + // Resolve the blob and cache the result. + b, err := r.resolver.Resolve(ctx, hosts, refspec, desc, httpCache) if err != nil { - log.G(ctx).WithError(err).Debugf("failed to resolve source") return nil, errors.Wrap(err, "failed to resolve the source") } r.blobCacheMu.Lock() - r.blobCache.Add(name, blob) + cachedB, done, added := r.blobCache.Add(name, b) r.blobCacheMu.Unlock() + if !added { + b.Close() // blob already exists in the cache. discard this. + } + return &blobRef{cachedB.(remote.Blob), done}, nil +} - return blob, nil +// Cache is similar to Resolve but the result isn't returned. Instead, it'll be stored in the cache. +func (r *Resolver) Cache(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error { + l, err := r.Resolve(ctx, hosts, refspec, desc) + if err != nil { + return err + } + // Release this layer. However, this will remain on the cache until eviction. + // Until then, the client can reuse this (already pre-resolved) layer. + l.Done() + return nil } func newLayer( resolver *Resolver, desc ocispec.Descriptor, - blob remote.Blob, + blob *blobRef, vr *reader.VerifiableReader, - root *estargz.TOCEntry, ) *layer { return &layer{ resolver: resolver, desc: desc, blob: blob, verifiableReader: vr, - root: root, prefetchWaiter: newWaiter(), } } @@ -294,12 +363,14 @@ func newLayer( type layer struct { resolver *Resolver desc ocispec.Descriptor - blob remote.Blob + blob *blobRef verifiableReader *reader.VerifiableReader - root *estargz.TOCEntry prefetchWaiter *waiter r reader.Reader + + closed bool + closedMu sync.Mutex } func (l *layer) Info() Info { @@ -310,19 +381,24 @@ func (l *layer) Info() Info { } } -func (l *layer) Root() *estargz.TOCEntry { - return l.root -} - func (l *layer) Check() error { + if l.isClosed() { + return fmt.Errorf("layer is already closed") + } return l.blob.Check() } -func (l *layer) Refresh(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error { +func (l *layer) Refresh(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error { + if l.isClosed() { + return fmt.Errorf("layer is already closed") + } return l.blob.Refresh(ctx, hosts, refspec, desc) } func (l *layer) Verify(tocDigest digest.Digest) (err error) { + if l.isClosed() { + return fmt.Errorf("layer is already closed") + } l.r, err = l.verifiableReader.VerifyTOC(tocDigest) return } @@ -331,16 +407,12 @@ func (l *layer) SkipVerify() { l.r = l.verifiableReader.SkipVerify() } -func (l *layer) OpenFile(name string) (io.ReaderAt, error) { - if l.r == nil { - return nil, fmt.Errorf("layer hasn't been verified yet") - } - return l.r.OpenFile(name) -} - func (l *layer) Prefetch(prefetchSize int64) error { defer l.prefetchWaiter.done() // Notify the completion + if l.isClosed() { + return fmt.Errorf("layer is already closed") + } if l.r == nil { return fmt.Errorf("layer hasn't been verified yet") } @@ -372,10 +444,16 @@ func (l *layer) Prefetch(prefetchSize int64) error { } func (l *layer) WaitForPrefetchCompletion() error { + if l.isClosed() { + return fmt.Errorf("layer is already closed") + } return l.prefetchWaiter.wait(l.resolver.prefetchTimeout) } func (l *layer) BackgroundFetch() error { + if l.isClosed() { + return fmt.Errorf("layer is already closed") + } if l.r == nil { return fmt.Errorf("layer hasn't been verified yet") } @@ -397,6 +475,62 @@ func (l *layer) BackgroundFetch() error { ) } +func (l *layerRef) Done() { + l.done() +} + +func (l *layer) RootNode() (fusefs.InodeEmbedder, error) { + if l.isClosed() { + return nil, fmt.Errorf("layer is already closed") + } + if l.r == nil { + return nil, fmt.Errorf("layer hasn't been verified yet") + } + return newNode(l.desc.Digest, l.r, l.blob) +} + +func (l *layer) ReadAt(p []byte, offset int64, opts ...remote.Option) (int, error) { + return l.blob.ReadAt(p, offset, opts...) +} + +func (l *layer) close() error { + l.closedMu.Lock() + defer l.closedMu.Unlock() + if l.closed { + return nil + } + l.closed = true + defer l.blob.done() // Close reader first, then close the blob + l.verifiableReader.Close() + if l.r != nil { + return l.r.Close() + } + return nil +} + +func (l *layer) isClosed() bool { + l.closedMu.Lock() + closed := l.closed + l.closedMu.Unlock() + return closed +} + +// blobRef is a reference to the blob in the cache. Calling `done` decreases the reference counter +// of this blob in the underlying cache. When nobody refers to the blob in the cache, resources bound +// to this blob will be discarded. +type blobRef struct { + remote.Blob + done func() +} + +// layerRef is a reference to the layer in the cache. Calling `Done` or `done` decreases the +// reference counter of this blob in the underlying cache. When nobody refers to the layer in the +// cache, resources bound to this layer will be discarded. +type layerRef struct { + *layer + done func() +} + func newWaiter() *waiter { return &waiter{ completionCond: sync.NewCond(&sync.Mutex{}), diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/layer/node.go b/vendor/github.com/containerd/stargz-snapshotter/fs/layer/node.go new file mode 100644 index 000000000000..0bf73131c53b --- /dev/null +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/layer/node.go @@ -0,0 +1,628 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + Copyright 2019 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the NOTICE.md file. +*/ + +package layer + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "os" + "sort" + "strings" + "sync" + "syscall" + "unsafe" + + "github.com/containerd/stargz-snapshotter/estargz" + "github.com/containerd/stargz-snapshotter/fs/reader" + "github.com/containerd/stargz-snapshotter/fs/remote" + fusefs "github.com/hanwen/go-fuse/v2/fs" + "github.com/hanwen/go-fuse/v2/fuse" + digest "github.com/opencontainers/go-digest" + "golang.org/x/sys/unix" +) + +const ( + blockSize = 4096 + whiteoutPrefix = ".wh." + whiteoutOpaqueDir = whiteoutPrefix + whiteoutPrefix + ".opq" + opaqueXattrValue = "y" + stateDirName = ".stargz-snapshotter" + statFileMode = syscall.S_IFREG | 0400 // -r-------- + stateDirMode = syscall.S_IFDIR | 0500 // dr-x------ +) + +var opaqueXattrs = []string{"trusted.overlay.opaque", "user.overlay.opaque"} + +func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob) (fusefs.InodeEmbedder, error) { + root, ok := r.Lookup("") + if !ok { + return nil, fmt.Errorf("failed to get a TOCEntry of the root") + } + return &node{ + r: r, + e: root, + s: newState(layerDgst, blob), + }, nil +} + +// node is a filesystem inode abstraction. +type node struct { + fusefs.Inode + r reader.Reader + e *estargz.TOCEntry + s *state + opaque bool // true if this node is an overlayfs opaque directory +} + +var _ = (fusefs.InodeEmbedder)((*node)(nil)) + +var _ = (fusefs.NodeReaddirer)((*node)(nil)) + +func (n *node) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) { + var ents []fuse.DirEntry + whiteouts := map[string]*estargz.TOCEntry{} + normalEnts := map[string]bool{} + n.e.ForeachChild(func(baseName string, ent *estargz.TOCEntry) bool { + + // We don't want to show prefetch landmarks in "/". + if n.e.Name == "" && (baseName == estargz.PrefetchLandmark || baseName == estargz.NoPrefetchLandmark) { + return true + } + + // We don't want to show whiteouts. + if strings.HasPrefix(baseName, whiteoutPrefix) { + if baseName == whiteoutOpaqueDir { + return true + } + // Add the overlayfs-compiant whiteout later. + whiteouts[baseName] = ent + return true + } + + // This is a normal entry. + normalEnts[baseName] = true + ents = append(ents, fuse.DirEntry{ + Mode: modeOfEntry(ent), + Name: baseName, + Ino: inodeOfEnt(ent), + }) + return true + }) + + // Append whiteouts if no entry replaces the target entry in the lower layer. + for w, ent := range whiteouts { + if !normalEnts[w[len(whiteoutPrefix):]] { + ents = append(ents, fuse.DirEntry{ + Mode: syscall.S_IFCHR, + Name: w[len(whiteoutPrefix):], + Ino: inodeOfEnt(ent), + }) + + } + } + + // Avoid undeterministic order of entries on each call + sort.Slice(ents, func(i, j int) bool { + return ents[i].Name < ents[j].Name + }) + + return fusefs.NewListDirStream(ents), 0 +} + +var _ = (fusefs.NodeLookuper)((*node)(nil)) + +func (n *node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fusefs.Inode, syscall.Errno) { + // We don't want to show prefetch landmarks in "/". + if n.e.Name == "" && (name == estargz.PrefetchLandmark || name == estargz.NoPrefetchLandmark) { + return nil, syscall.ENOENT + } + + // We don't want to show whiteouts. + if strings.HasPrefix(name, whiteoutPrefix) { + return nil, syscall.ENOENT + } + + // state directory + if n.e.Name == "" && name == stateDirName { + return n.NewInode(ctx, n.s, stateToAttr(n.s, &out.Attr)), 0 + } + + // lookup stargz TOCEntry + ce, ok := n.e.LookupChild(name) + if !ok { + // If the entry exists as a whiteout, show an overlayfs-styled whiteout node. + if wh, ok := n.e.LookupChild(fmt.Sprintf("%s%s", whiteoutPrefix, name)); ok { + return n.NewInode(ctx, &whiteout{ + e: wh, + }, entryToWhAttr(wh, &out.Attr)), 0 + } + return nil, syscall.ENOENT + } + var opaque bool + if _, ok := ce.LookupChild(whiteoutOpaqueDir); ok { + // This entry is an opaque directory so make it recognizable for overlayfs. + opaque = true + } + + return n.NewInode(ctx, &node{ + r: n.r, + e: ce, + s: n.s, + opaque: opaque, + }, entryToAttr(ce, &out.Attr)), 0 +} + +var _ = (fusefs.NodeOpener)((*node)(nil)) + +func (n *node) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { + ra, err := n.r.OpenFile(n.e.Name) + if err != nil { + n.s.report(fmt.Errorf("failed to open node: %v", err)) + return nil, 0, syscall.EIO + } + return &file{ + n: n, + e: n.e, + ra: ra, + }, 0, 0 +} + +var _ = (fusefs.NodeGetattrer)((*node)(nil)) + +func (n *node) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { + entryToAttr(n.e, &out.Attr) + return 0 +} + +var _ = (fusefs.NodeGetxattrer)((*node)(nil)) + +func (n *node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { + for _, opaqueXattr := range opaqueXattrs { + if attr == opaqueXattr && n.opaque { + // This node is an opaque directory so give overlayfs-compliant indicator. + if len(dest) < len(opaqueXattrValue) { + return uint32(len(opaqueXattrValue)), syscall.ERANGE + } + return uint32(copy(dest, opaqueXattrValue)), 0 + } + } + if v, ok := n.e.Xattrs[attr]; ok { + if len(dest) < len(v) { + return uint32(len(v)), syscall.ERANGE + } + return uint32(copy(dest, v)), 0 + } + return 0, syscall.ENODATA +} + +var _ = (fusefs.NodeListxattrer)((*node)(nil)) + +func (n *node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { + var attrs []byte + if n.opaque { + // This node is an opaque directory so add overlayfs-compliant indicator. + for _, opaqueXattr := range opaqueXattrs { + attrs = append(attrs, []byte(opaqueXattr+"\x00")...) + } + } + for k := range n.e.Xattrs { + attrs = append(attrs, []byte(k+"\x00")...) + } + if len(dest) < len(attrs) { + return uint32(len(attrs)), syscall.ERANGE + } + return uint32(copy(dest, attrs)), 0 +} + +var _ = (fusefs.NodeReadlinker)((*node)(nil)) + +func (n *node) Readlink(ctx context.Context) ([]byte, syscall.Errno) { + return []byte(n.e.LinkName), 0 +} + +var _ = (fusefs.NodeStatfser)((*node)(nil)) + +func (n *node) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { + defaultStatfs(out) + return 0 +} + +// file is a file abstraction which implements file handle in go-fuse. +type file struct { + n *node + e *estargz.TOCEntry + ra io.ReaderAt +} + +var _ = (fusefs.FileReader)((*file)(nil)) + +func (f *file) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { + n, err := f.ra.ReadAt(dest, off) + if err != nil && err != io.EOF { + f.n.s.report(fmt.Errorf("failed to read node: %v", err)) + return nil, syscall.EIO + } + return fuse.ReadResultData(dest[:n]), 0 +} + +var _ = (fusefs.FileGetattrer)((*file)(nil)) + +func (f *file) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno { + entryToAttr(f.e, &out.Attr) + return 0 +} + +// whiteout is a whiteout abstraction compliant to overlayfs. +type whiteout struct { + fusefs.Inode + e *estargz.TOCEntry +} + +var _ = (fusefs.NodeGetattrer)((*whiteout)(nil)) + +func (w *whiteout) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { + entryToWhAttr(w.e, &out.Attr) + return 0 +} + +var _ = (fusefs.NodeStatfser)((*whiteout)(nil)) + +func (w *whiteout) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { + defaultStatfs(out) + return 0 +} + +// newState provides new state directory node. +// It creates statFile at the same time to give it stable inode number. +func newState(layerDigest digest.Digest, blob remote.Blob) *state { + return &state{ + statFile: &statFile{ + name: layerDigest.String() + ".json", + statJSON: statJSON{ + Digest: layerDigest.String(), + Size: blob.Size(), + }, + blob: blob, + }, + } +} + +// state is a directory which contain a "state file" of this layer aiming to +// observability. This filesystem uses it to report something(e.g. error) to +// the clients(e.g. Kubernetes's livenessProbe). +// This directory has mode "dr-x------ root root". +type state struct { + fusefs.Inode + statFile *statFile +} + +var _ = (fusefs.NodeReaddirer)((*state)(nil)) + +func (s *state) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) { + return fusefs.NewListDirStream([]fuse.DirEntry{ + { + Mode: statFileMode, + Name: s.statFile.name, + Ino: inodeOfStatFile(s.statFile), + }, + }), 0 +} + +var _ = (fusefs.NodeLookuper)((*state)(nil)) + +func (s *state) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fusefs.Inode, syscall.Errno) { + if name != s.statFile.name { + return nil, syscall.ENOENT + } + attr, errno := s.statFile.attr(&out.Attr) + if errno != 0 { + return nil, errno + } + return s.NewInode(ctx, s.statFile, attr), 0 +} + +var _ = (fusefs.NodeGetattrer)((*state)(nil)) + +func (s *state) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { + stateToAttr(s, &out.Attr) + return 0 +} + +var _ = (fusefs.NodeStatfser)((*state)(nil)) + +func (s *state) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { + defaultStatfs(out) + return 0 +} + +func (s *state) report(err error) { + s.statFile.report(err) +} + +type statJSON struct { + Error string `json:"error,omitempty"` + Digest string `json:"digest"` + // URL is excluded for potential security reason + Size int64 `json:"size"` + FetchedSize int64 `json:"fetchedSize"` + FetchedPercent float64 `json:"fetchedPercent"` // Fetched / Size * 100.0 +} + +// statFile is a file which contain something to be reported from this layer. +// This filesystem uses statFile.report() to report something(e.g. error) to +// the clients(e.g. Kubernetes's livenessProbe). +// This file has mode "-r-------- root root". +type statFile struct { + fusefs.Inode + name string + blob remote.Blob + statJSON statJSON + mu sync.Mutex +} + +var _ = (fusefs.NodeOpener)((*statFile)(nil)) + +func (sf *statFile) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) { + return nil, 0, 0 +} + +var _ = (fusefs.NodeReader)((*statFile)(nil)) + +func (sf *statFile) Read(ctx context.Context, f fusefs.FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { + sf.mu.Lock() + defer sf.mu.Unlock() + st, err := sf.updateStatUnlocked() + if err != nil { + return nil, syscall.EIO + } + n, err := bytes.NewReader(st).ReadAt(dest, off) + if err != nil && err != io.EOF { + return nil, syscall.EIO + } + return fuse.ReadResultData(dest[:n]), 0 +} + +var _ = (fusefs.NodeGetattrer)((*statFile)(nil)) + +func (sf *statFile) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno { + _, errno := sf.attr(&out.Attr) + return errno +} + +var _ = (fusefs.NodeStatfser)((*statFile)(nil)) + +func (sf *statFile) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { + defaultStatfs(out) + return 0 +} + +func (sf *statFile) report(err error) { + sf.mu.Lock() + defer sf.mu.Unlock() + sf.statJSON.Error = err.Error() +} + +func (sf *statFile) attr(out *fuse.Attr) (fusefs.StableAttr, syscall.Errno) { + sf.mu.Lock() + defer sf.mu.Unlock() + + st, err := sf.updateStatUnlocked() + if err != nil { + return fusefs.StableAttr{}, syscall.EIO + } + + return statFileToAttr(sf, uint64(len(st)), out), 0 +} + +func (sf *statFile) updateStatUnlocked() ([]byte, error) { + sf.statJSON.FetchedSize = sf.blob.FetchedSize() + sf.statJSON.FetchedPercent = float64(sf.statJSON.FetchedSize) / float64(sf.statJSON.Size) * 100.0 + j, err := json.Marshal(&sf.statJSON) + if err != nil { + return nil, err + } + j = append(j, []byte("\n")...) + return j, nil +} + +// inodeOfEnt calculates the inode number which is one-to-one correspondence +// with the TOCEntry instance. +func inodeOfEnt(e *estargz.TOCEntry) uint64 { + return uint64(uintptr(unsafe.Pointer(e))) +} + +// entryToAttr converts stargz's TOCEntry to go-fuse's Attr. +func entryToAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr { + out.Ino = inodeOfEnt(e) + out.Size = uint64(e.Size) + out.Blksize = blockSize + out.Blocks = out.Size / uint64(out.Blksize) + if out.Size%uint64(out.Blksize) > 0 { + out.Blocks++ + } + mtime := e.ModTime() + out.SetTimes(nil, &mtime, nil) + out.Mode = modeOfEntry(e) + out.Owner = fuse.Owner{Uid: uint32(e.UID), Gid: uint32(e.GID)} + out.Rdev = uint32(unix.Mkdev(uint32(e.DevMajor), uint32(e.DevMinor))) + out.Nlink = uint32(e.NumLink) + if out.Nlink == 0 { + out.Nlink = 1 // zero "NumLink" means one. + } + out.Padding = 0 // TODO + + return fusefs.StableAttr{ + Mode: out.Mode, + Ino: out.Ino, + // NOTE: The inode number is unique throughout the lifetime of + // this filesystem so we don't consider about generation at this + // moment. + } +} + +// entryToWhAttr converts stargz's TOCEntry to go-fuse's Attr of whiteouts. +func entryToWhAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr { + fi := e.Stat() + out.Ino = inodeOfEnt(e) + out.Size = 0 + out.Blksize = blockSize + out.Blocks = 0 + mtime := fi.ModTime() + out.SetTimes(nil, &mtime, nil) + out.Mode = syscall.S_IFCHR + out.Owner = fuse.Owner{Uid: 0, Gid: 0} + out.Rdev = uint32(unix.Mkdev(0, 0)) + out.Nlink = 1 + out.Padding = 0 // TODO + + return fusefs.StableAttr{ + Mode: out.Mode, + Ino: out.Ino, + // NOTE: The inode number is unique throughout the lifetime of + // this filesystem so we don't consider about generation at this + // moment. + } +} + +// inodeOfState calculates the inode number which is one-to-one correspondence +// with the state directory instance which was created on mount. +func inodeOfState(s *state) uint64 { + return uint64(uintptr(unsafe.Pointer(s))) +} + +// stateToAttr converts state directory to go-fuse's Attr. +func stateToAttr(s *state, out *fuse.Attr) fusefs.StableAttr { + out.Ino = inodeOfState(s) + out.Size = 0 + out.Blksize = blockSize + out.Blocks = 0 + out.Nlink = 1 + + // root can read and open it (dr-x------ root root). + out.Mode = stateDirMode + out.Owner = fuse.Owner{Uid: 0, Gid: 0} + + // dummy + out.Mtime = 0 + out.Mtimensec = 0 + out.Rdev = 0 + out.Padding = 0 + + return fusefs.StableAttr{ + Mode: out.Mode, + Ino: out.Ino, + // NOTE: The inode number is unique throughout the lifetime of + // this filesystem so we don't consider about generation at this + // moment. + } +} + +// inodeOfStatFile calculates the inode number which is one-to-one correspondence +// with the stat file instance which was created on mount. +func inodeOfStatFile(s *statFile) uint64 { + return uint64(uintptr(unsafe.Pointer(s))) +} + +// statFileToAttr converts stat file to go-fuse's Attr. +func statFileToAttr(sf *statFile, size uint64, out *fuse.Attr) fusefs.StableAttr { + out.Ino = inodeOfStatFile(sf) + out.Size = size + out.Blksize = blockSize + out.Blocks = out.Size / uint64(out.Blksize) + out.Nlink = 1 + + // Root can read it ("-r-------- root root"). + out.Mode = statFileMode + out.Owner = fuse.Owner{Uid: 0, Gid: 0} + + // dummy + out.Mtime = 0 + out.Mtimensec = 0 + out.Rdev = 0 + out.Padding = 0 + + return fusefs.StableAttr{ + Mode: out.Mode, + Ino: out.Ino, + // NOTE: The inode number is unique throughout the lifetime of + // this filesystem so we don't consider about generation at this + // moment. + } +} + +// modeOfEntry gets system's mode bits from TOCEntry +func modeOfEntry(e *estargz.TOCEntry) uint32 { + m := e.Stat().Mode() + + // Permission bits + res := uint32(m & os.ModePerm) + + // File type bits + switch m & os.ModeType { + case os.ModeDevice: + res |= syscall.S_IFBLK + case os.ModeDevice | os.ModeCharDevice: + res |= syscall.S_IFCHR + case os.ModeDir: + res |= syscall.S_IFDIR + case os.ModeNamedPipe: + res |= syscall.S_IFIFO + case os.ModeSymlink: + res |= syscall.S_IFLNK + case os.ModeSocket: + res |= syscall.S_IFSOCK + default: // regular file. + res |= syscall.S_IFREG + } + + // suid, sgid, sticky bits + if m&os.ModeSetuid != 0 { + res |= syscall.S_ISUID + } + if m&os.ModeSetgid != 0 { + res |= syscall.S_ISGID + } + if m&os.ModeSticky != 0 { + res |= syscall.S_ISVTX + } + + return res +} + +func defaultStatfs(stat *fuse.StatfsOut) { + + // http://man7.org/linux/man-pages/man2/statfs.2.html + stat.Blocks = 0 // dummy + stat.Bfree = 0 + stat.Bavail = 0 + stat.Files = 0 // dummy + stat.Ffree = 0 + stat.Bsize = blockSize + stat.NameLen = 1<<32 - 1 + stat.Frsize = blockSize + stat.Padding = 0 + stat.Spare = [6]uint32{} +} diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/reader/reader.go b/vendor/github.com/containerd/stargz-snapshotter/fs/reader/reader.go index dcd6a10cf9a8..f3c164b734f5 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/fs/reader/reader.go +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/reader/reader.go @@ -23,6 +23,7 @@ package reader import ( + "bufio" "bytes" "context" "crypto/sha256" @@ -46,6 +47,7 @@ type Reader interface { OpenFile(name string) (io.ReaderAt, error) Lookup(name string) (*estargz.TOCEntry, bool) Cache(opts ...CacheOption) error + Close() error } // VerifiableReader produces a Reader with a given verifier. @@ -67,6 +69,10 @@ func (vr *VerifiableReader) VerifyTOC(tocDigest digest.Digest) (Reader, error) { return vr.r, nil } +func (vr *VerifiableReader) Close() error { + return vr.r.Close() +} + type nopTOCEntryVerifier struct{} func (nev nopTOCEntryVerifier) Verifier(ce *estargz.TOCEntry) (digest.Verifier, error) { @@ -86,15 +92,10 @@ func (nv nopVerifier) Verified() bool { // NewReader creates a Reader based on the given stargz blob and cache implementation. // It returns VerifiableReader so the caller must provide a estargz.TOCEntryVerifier // to use for verifying file or chunk contained in this stargz blob. -func NewReader(sr *io.SectionReader, cache cache.BlobCache) (*VerifiableReader, *estargz.TOCEntry, error) { +func NewReader(sr *io.SectionReader, cache cache.BlobCache) (*VerifiableReader, error) { r, err := estargz.Open(sr) if err != nil { - return nil, nil, errors.Wrap(err, "failed to parse stargz") - } - - root, ok := r.Lookup("") - if !ok { - return nil, nil, fmt.Errorf("failed to get a TOCEntry of the root") + return nil, errors.Wrap(err, "failed to parse stargz") } vr := &reader{ @@ -108,7 +109,7 @@ func NewReader(sr *io.SectionReader, cache cache.BlobCache) (*VerifiableReader, }, } - return &VerifiableReader{vr}, root, nil + return &VerifiableReader{vr}, nil } type reader struct { @@ -117,9 +118,16 @@ type reader struct { cache cache.BlobCache bufPool sync.Pool verifier estargz.TOCEntryVerifier + + closed bool + closedMu sync.Mutex } func (gr *reader) OpenFile(name string) (io.ReaderAt, error) { + if gr.isClosed() { + return nil, fmt.Errorf("reader is already closed") + } + sr, err := gr.r.OpenFile(name) if err != nil { return nil, err @@ -143,6 +151,10 @@ func (gr *reader) Lookup(name string) (*estargz.TOCEntry, bool) { } func (gr *reader) Cache(opts ...CacheOption) (err error) { + if gr.isClosed() { + return fmt.Errorf("reader is already closed") + } + var cacheOpts cacheOptions for _, o := range opts { o(&cacheOpts) @@ -175,6 +187,23 @@ func (gr *reader) Cache(opts ...CacheOption) (err error) { return eg.Wait() } +func (gr *reader) Close() error { + gr.closedMu.Lock() + defer gr.closedMu.Unlock() + if gr.closed { + return nil + } + gr.closed = true + return gr.cache.Close() +} + +func (gr *reader) isClosed() bool { + gr.closedMu.Lock() + closed := gr.closed + gr.closedMu.Unlock() + return closed +} + func (gr *reader) cacheWithReader(ctx context.Context, currentDepth int, eg *errgroup.Group, sem *semaphore.Weighted, dir *estargz.TOCEntry, r *estargz.Reader, filter func(*estargz.TOCEntry) bool, opts ...cache.Option) (rErr error) { if currentDepth > maxWalkDepth { return fmt.Errorf("TOCEntry tree is too deep (depth:%d)", currentDepth) @@ -230,42 +259,44 @@ func (gr *reader) cacheWithReader(ctx context.Context, currentDepth int, eg *err return false } - eg.Go(func() error { + eg.Go(func() (retErr error) { defer sem.Release(1) // Check if the target chunks exists in the cache id := genID(e.Digest, ce.ChunkOffset, ce.ChunkSize) - if _, err := gr.cache.FetchAt(id, 0, nil, opts...); err == nil { - return nil + if r, err := gr.cache.Get(id, opts...); err == nil { + return r.Close() } // missed cache, needs to fetch and add it to the cache cr := io.NewSectionReader(sr, ce.ChunkOffset, ce.ChunkSize) - b := gr.bufPool.Get().(*bytes.Buffer) - defer gr.bufPool.Put(b) - b.Reset() - b.Grow(int(ce.ChunkSize)) v, err := gr.verifier.Verifier(ce) if err != nil { return errors.Wrapf(err, "verifier not found %q(off:%d,size:%d)", e.Name, ce.ChunkOffset, ce.ChunkSize) } - if _, err := io.CopyN(b, io.TeeReader(cr, v), ce.ChunkSize); err != nil { + br := bufio.NewReaderSize(io.TeeReader(cr, v), int(ce.ChunkSize)) + if _, err := br.Peek(int(ce.ChunkSize)); err != nil { + return fmt.Errorf("cacheWithReader.peek: %v", err) + } + w, err := gr.cache.Add(id, opts...) + if err != nil { + return err + } + defer w.Close() + if _, err := io.CopyN(w, br, ce.ChunkSize); err != nil { + w.Abort() return errors.Wrapf(err, - "failed to read file payload of %q (offset:%d,size:%d)", + "failed to cache file payload of %q (offset:%d,size:%d)", e.Name, ce.ChunkOffset, ce.ChunkSize) } - if int64(b.Len()) != ce.ChunkSize { - return fmt.Errorf("unexpected copied data size %d; want %d", - b.Len(), ce.ChunkSize) - } if !v.Verified() { + w.Abort() return fmt.Errorf("invalid chunk %q (offset:%d,size:%d)", e.Name, ce.ChunkOffset, ce.ChunkSize) } - gr.cache.Add(id, b.Bytes()[:ce.ChunkSize], opts...) - return nil + return w.Commit() }) } @@ -301,10 +332,14 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) { ) // Check if the content exists in the cache - n, err := sf.cache.FetchAt(id, lowerDiscard, p[nr:int64(nr)+expectedSize]) - if err == nil && int64(n) == expectedSize { - nr += n - continue + if r, err := sf.cache.Get(id); err == nil { + n, err := r.ReadAt(p[nr:int64(nr)+expectedSize], lowerDiscard) + if (err == nil || err == io.EOF) && int64(n) == expectedSize { + nr += n + r.Close() + continue + } + r.Close() } // We missed cache. Take it from underlying reader. @@ -324,7 +359,14 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) { } // Cache this chunk - sf.cache.Add(id, ip) + if w, err := sf.cache.Add(id); err == nil { + if cn, err := w.Write(ip); err != nil || cn != len(ip) { + w.Abort() + } else { + w.Commit() + } + w.Close() + } nr += n continue } @@ -346,8 +388,15 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) { } // Cache this chunk - sf.cache.Add(id, ip) - n = copy(p[nr:], ip[lowerDiscard:ce.ChunkSize-upperDiscard]) + if w, err := sf.cache.Add(id); err == nil { + if cn, err := w.Write(ip); err != nil || cn != len(ip) { + w.Abort() + } else { + w.Commit() + } + w.Close() + } + n := copy(p[nr:], ip[lowerDiscard:ce.ChunkSize-upperDiscard]) sf.gr.bufPool.Put(b) if int64(n) != expectedSize { return 0, fmt.Errorf("unexpected final data size %d; want %d", n, expectedSize) @@ -364,7 +413,7 @@ func (sf *file) verify(p []byte, ce *estargz.TOCEntry) error { return errors.Wrapf(err, "verifier not found %q (offset:%d,size:%d)", ce.Name, ce.ChunkOffset, ce.ChunkSize) } - if _, err := io.Copy(v, bytes.NewReader(p)); err != nil { + if _, err := v.Write(p); err != nil { return errors.Wrapf(err, "failed to verify %q (offset:%d,size:%d)", ce.Name, ce.ChunkOffset, ce.ChunkSize) } diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/remote/blob.go b/vendor/github.com/containerd/stargz-snapshotter/fs/remote/blob.go index eced44f0c116..4381c1a4781f 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/fs/remote/blob.go +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/remote/blob.go @@ -23,7 +23,6 @@ package remote import ( - "bytes" "context" "fmt" "io" @@ -33,8 +32,8 @@ import ( "time" "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes/docker" "github.com/containerd/stargz-snapshotter/cache" + "github.com/containerd/stargz-snapshotter/fs/source" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) @@ -47,7 +46,8 @@ type Blob interface { FetchedSize() int64 ReadAt(p []byte, offset int64, opts ...Option) (int, error) Cache(offset int64, size int64, opts ...Option) error - Refresh(ctx context.Context, host docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error + Refresh(ctx context.Context, host source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error + Close() error } type blob struct { @@ -66,9 +66,33 @@ type blob struct { fetchedRegionSetMu sync.Mutex resolver *Resolver + + closed bool + closedMu sync.Mutex +} + +func (b *blob) Close() error { + b.closedMu.Lock() + defer b.closedMu.Unlock() + if b.closed { + return nil + } + b.closed = true + return b.cache.Close() } -func (b *blob) Refresh(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error { +func (b *blob) isClosed() bool { + b.closedMu.Lock() + closed := b.closed + b.closedMu.Unlock() + return closed +} + +func (b *blob) Refresh(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error { + if b.isClosed() { + return fmt.Errorf("blob is already closed") + } + // refresh the fetcher new, newSize, err := newFetcher(ctx, hosts, refspec, desc) if err != nil { @@ -89,6 +113,10 @@ func (b *blob) Refresh(ctx context.Context, hosts docker.RegistryHosts, refspec } func (b *blob) Check() error { + if b.isClosed() { + return fmt.Errorf("blob is already closed") + } + now := time.Now() b.lastCheckMu.Lock() lastCheck := b.lastCheck @@ -124,6 +152,10 @@ func (b *blob) FetchedSize() int64 { } func (b *blob) Cache(offset int64, size int64, opts ...Option) error { + if b.isClosed() { + return fmt.Errorf("blob is already closed") + } + var cacheOpts options for _, o := range opts { o(&cacheOpts) @@ -136,9 +168,10 @@ func (b *blob) Cache(offset int64, size int64, opts ...Option) error { fetchReg := region{floor(offset, b.chunkSize), ceil(offset+size-1, b.chunkSize) - 1} discard := make(map[region]io.Writer) b.walkChunks(fetchReg, func(reg region) error { - if _, err := b.cache.FetchAt(fr.genID(reg), 0, nil, cacheOpts.cacheOpts...); err != nil { - discard[reg] = ioutil.Discard + if r, err := b.cache.Get(fr.genID(reg), cacheOpts.cacheOpts...); err == nil { + return r.Close() // nop if the cache hits } + discard[reg] = ioutil.Discard return nil }) if err := b.fetchRange(discard, &cacheOpts); err != nil { @@ -152,6 +185,10 @@ func (b *blob) Cache(offset int64, size int64, opts ...Option) error { // It tries to fetch as many chunks as possible from local cache. // We can configure this function with options. func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) { + if b.isClosed() { + return 0, fmt.Errorf("blob is already closed") + } + if len(p) == 0 || offset > b.size { return 0, nil } @@ -159,12 +196,6 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) { // Make the buffer chunk aligned allRegion := region{floor(offset, b.chunkSize), ceil(offset+int64(len(p))-1, b.chunkSize) - 1} allData := make(map[region]io.Writer) - var putBufs []*bytes.Buffer - defer func() { - for _, bf := range putBufs { - b.resolver.bufPool.Put(bf) - } - }() var readAtOpts options for _, o := range opts { @@ -177,7 +208,6 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) { fr := b.fetcher b.fetcherMu.Unlock() - var commits []func() error b.walkChunks(allRegion, func(chunk region) error { var ( base = positive(chunk.b - offset) @@ -187,42 +217,19 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) { ) // Check if the content exists in the cache - n, err := b.cache.FetchAt(fr.genID(chunk), lowerUnread, p[base:base+expectedSize], readAtOpts.cacheOpts...) - if err == nil && n == int(expectedSize) { - return nil + r, err := b.cache.Get(fr.genID(chunk), readAtOpts.cacheOpts...) + if err == nil { + defer r.Close() + n, err := r.ReadAt(p[base:base+expectedSize], lowerUnread) + if (err == nil || err == io.EOF) && int64(n) == expectedSize { + return nil + } } // We missed cache. Take it from remote registry. // We get the whole chunk here and add it to the cache so that following // reads against neighboring chunks can take the data without making HTTP requests. - if lowerUnread == 0 && upperUnread == 0 { - // We can directly store the result in the given buffer - allData[chunk] = &byteWriter{ - p: p[base : base+chunk.size()], - } - } else { - // Use temporally buffer for aligning this chunk - bf := b.resolver.bufPool.Get().(*bytes.Buffer) - putBufs = append(putBufs, bf) - bf.Reset() - bf.Grow(int(chunk.size())) - allData[chunk] = bf - - // Function for committing the buffered chunk into the result slice. - commits = append(commits, func() error { - if int64(bf.Len()) != chunk.size() { - return fmt.Errorf("unexpected data size %d; want %d", - bf.Len(), chunk.size()) - } - bb := bf.Bytes()[:chunk.size()] - n := copy(p[base:], bb[lowerUnread:chunk.size()-upperUnread]) - if int64(n) != expectedSize { - return fmt.Errorf("invalid copied data size %d; want %d", - n, expectedSize) - } - return nil - }) - } + allData[chunk] = newBytesWriter(p[base:base+expectedSize], lowerUnread) return nil }) @@ -231,13 +238,6 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) { return 0, err } - // Write all data to the result buffer - for _, c := range commits { - if err := c(); err != nil { - return 0, err - } - } - // Adjust the buffer size according to the blob size if remain := b.size - offset; int64(len(p)) >= remain { if remain < 0 { @@ -290,31 +290,32 @@ func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error { } else if err != nil { return errors.Wrapf(err, "failed to read multipart resp") } - if err := b.walkChunks(reg, func(chunk region) error { - - // Prepare the temporary buffer - bf := b.resolver.bufPool.Get().(*bytes.Buffer) - defer b.resolver.bufPool.Put(bf) - bf.Reset() - bf.Grow(int(chunk.size())) - w := io.Writer(bf) + if err := b.walkChunks(reg, func(chunk region) (retErr error) { + id := fr.genID(chunk) + cw, err := b.cache.Add(id, opts.cacheOpts...) + if err != nil { + return err + } + defer cw.Close() + w := io.Writer(cw) // If this chunk is one of the targets, write the content to the // passed reader too. if _, ok := fetched[chunk]; ok { - w = io.MultiWriter(bf, allData[chunk]) + w = io.MultiWriter(w, allData[chunk]) } // Copy the target chunk if _, err := io.CopyN(w, p, chunk.size()); err != nil { + cw.Abort() return err - } else if int64(bf.Len()) != chunk.size() { - return fmt.Errorf("unexpected fetched data size %d; want %d", - bf.Len(), chunk.size()) } // Add the target chunk to the cache - b.cache.Add(fr.genID(chunk), bf.Bytes()[:chunk.size()], opts.cacheOpts...) + if err := cw.Commit(); err != nil { + return err + } + b.fetchedRegionSetMu.Lock() b.fetchedRegionSet.add(chunk) b.fetchedRegionSetMu.Unlock() @@ -360,15 +361,42 @@ func (b *blob) walkChunks(allRegion region, walkFn walkFunc) error { return nil } -type byteWriter struct { - p []byte - n int +func newBytesWriter(dest []byte, destOff int64) io.Writer { + return &bytesWriter{ + dest: dest, + destOff: destOff, + current: 0, + } } -func (w *byteWriter) Write(p []byte) (int, error) { - n := copy(w.p[w.n:], p) - w.n += n - return n, nil +type bytesWriter struct { + dest []byte + destOff int64 + current int64 +} + +func (bw *bytesWriter) Write(p []byte) (int, error) { + defer func() { bw.current = bw.current + int64(len(p)) }() + + var ( + destBase = positive(bw.current - bw.destOff) + pBegin = positive(bw.destOff - bw.current) + pEnd = positive(bw.destOff + int64(len(bw.dest)) - bw.current) + ) + + if destBase > int64(len(bw.dest)) { + return len(p), nil + } + if pBegin >= int64(len(p)) { + return len(p), nil + } + if pEnd > int64(len(p)) { + pEnd = int64(len(p)) + } + + copy(bw.dest[destBase:], p[pBegin:pEnd]) + + return len(p), nil } func floor(n int64, unit int64) int64 { diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/remote/resolver.go b/vendor/github.com/containerd/stargz-snapshotter/fs/remote/resolver.go index 878936954719..9742fd68ed5b 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/fs/remote/resolver.go +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/remote/resolver.go @@ -23,7 +23,6 @@ package remote import ( - "bytes" "context" "crypto/sha256" "fmt" @@ -32,6 +31,7 @@ import ( "mime" "mime/multipart" "net/http" + "net/url" "path" "strconv" "strings" @@ -43,6 +43,7 @@ import ( "github.com/containerd/containerd/remotes/docker" "github.com/containerd/stargz-snapshotter/cache" "github.com/containerd/stargz-snapshotter/fs/config" + "github.com/containerd/stargz-snapshotter/fs/source" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) @@ -53,7 +54,7 @@ const ( defaultFetchTimeoutSec = 300 ) -func NewResolver(blobCache cache.BlobCache, cfg config.BlobConfig) *Resolver { +func NewResolver(cfg config.BlobConfig) *Resolver { if cfg.ChunkSize == 0 { // zero means "use default chunk size" cfg.ChunkSize = defaultChunkSize } @@ -68,23 +69,15 @@ func NewResolver(blobCache cache.BlobCache, cfg config.BlobConfig) *Resolver { } return &Resolver{ - bufPool: sync.Pool{ - New: func() interface{} { - return new(bytes.Buffer) - }, - }, - blobCache: blobCache, blobConfig: cfg, } } type Resolver struct { - blobCache cache.BlobCache blobConfig config.BlobConfig - bufPool sync.Pool } -func (r *Resolver) Resolve(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (Blob, error) { +func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor, blobCache cache.BlobCache) (Blob, error) { fetcher, size, err := newFetcher(ctx, hosts, refspec, desc) if err != nil { return nil, err @@ -93,7 +86,7 @@ func (r *Resolver) Resolve(ctx context.Context, hosts docker.RegistryHosts, refs fetcher: fetcher, size: size, chunkSize: r.blobConfig.ChunkSize, - cache: r.blobCache, + cache: blobCache, lastCheck: time.Now(), checkInterval: time.Duration(r.blobConfig.ValidInterval) * time.Second, resolver: r, @@ -101,8 +94,8 @@ func (r *Resolver) Resolve(ctx context.Context, hosts docker.RegistryHosts, refs }, nil } -func newFetcher(ctx context.Context, hosts docker.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (*fetcher, int64, error) { - reghosts, err := hosts(refspec.Hostname()) +func newFetcher(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (*fetcher, int64, error) { + reghosts, err := hosts(refspec) if err != nil { return nil, 0, err } @@ -110,7 +103,7 @@ func newFetcher(ctx context.Context, hosts docker.RegistryHosts, refspec referen return nil, 0, fmt.Errorf("Digest is mandatory in layer descriptor") } digest := desc.Digest - pullScope, err := docker.RepositoryScope(refspec, false) + pullScope, err := repositoryScope(refspec, false) if err != nil { return nil, 0, err } @@ -127,6 +120,7 @@ func newFetcher(ctx context.Context, hosts docker.RegistryHosts, refspec referen // Prepare transport with authorization functionality tr := host.Client.Transport + timeout := host.Client.Timeout if host.Authorizer != nil { tr = &transport{ inner: tr, @@ -141,7 +135,7 @@ func newFetcher(ctx context.Context, hosts docker.RegistryHosts, refspec referen path.Join(host.Host, host.Path), strings.TrimPrefix(refspec.Locator, refspec.Hostname()+"/"), digest) - url, err := redirect(ctx, blobURL, tr) + url, err := redirect(ctx, blobURL, tr, timeout) if err != nil { rErr = errors.Wrapf(rErr, "failed to redirect (host %q, ref:%q, digest:%q): %v", host.Host, refspec, digest, err) @@ -150,7 +144,7 @@ func newFetcher(ctx context.Context, hosts docker.RegistryHosts, refspec referen // Get size information // TODO: we should try to use the Size field in the descriptor here. - size, err := getSize(ctx, url, tr) + size, err := getSize(ctx, url, tr, timeout) if err != nil { rErr = errors.Wrapf(rErr, "failed to get size (host %q, ref:%q, digest:%q): %v", host.Host, refspec, digest, err) @@ -162,6 +156,7 @@ func newFetcher(ctx context.Context, hosts docker.RegistryHosts, refspec referen url: url, tr: tr, blobURL: blobURL, + timeout: timeout, }, size, nil } @@ -209,10 +204,12 @@ func (tr *transport) RoundTrip(req *http.Request) (*http.Response, error) { return resp, nil } -func redirect(ctx context.Context, blobURL string, tr http.RoundTripper) (url string, err error) { - ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - +func redirect(ctx context.Context, blobURL string, tr http.RoundTripper, timeout time.Duration) (url string, err error) { + if timeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, timeout) + defer cancel() + } // We use GET request for redirect. // gcr.io returns 200 on HEAD without Location header (2020). // ghcr.io returns 200 on HEAD without Location header (2020). @@ -243,9 +240,12 @@ func redirect(ctx context.Context, blobURL string, tr http.RoundTripper) (url st return } -func getSize(ctx context.Context, url string, tr http.RoundTripper) (int64, error) { - ctx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() +func getSize(ctx context.Context, url string, tr http.RoundTripper, timeout time.Duration) (int64, error) { + if timeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, timeout) + defer cancel() + } req, err := http.NewRequestWithContext(ctx, "HEAD", url, nil) if err != nil { return 0, err @@ -297,6 +297,7 @@ type fetcher struct { blobURL string singleRange bool singleRangeMu sync.Mutex + timeout time.Duration } type multipartReadCloser interface { @@ -393,8 +394,12 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti } func (f *fetcher) check() error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() + ctx := context.Background() + if f.timeout > 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, f.timeout) + defer cancel() + } f.urlMu.Lock() url := f.url f.urlMu.Unlock() @@ -416,8 +421,12 @@ func (f *fetcher) check() error { return nil } else if res.StatusCode == http.StatusForbidden { // Try to re-redirect this blob - rCtx, rCancel := context.WithTimeout(context.Background(), 10*time.Second) - defer rCancel() + rCtx := context.Background() + if f.timeout > 0 { + var rCancel context.CancelFunc + rCtx, rCancel = context.WithTimeout(rCtx, f.timeout) + defer rCancel() + } if err := f.refreshURL(rCtx); err == nil { return nil } @@ -428,7 +437,7 @@ func (f *fetcher) check() error { } func (f *fetcher) refreshURL(ctx context.Context) error { - newURL, err := redirect(ctx, f.blobURL, f.tr) + newURL, err := redirect(ctx, f.blobURL, f.tr, f.timeout) if err != nil { return err } @@ -549,3 +558,21 @@ func WithCacheOpts(cacheOpts ...cache.Option) Option { opts.cacheOpts = cacheOpts } } + +// NOTE: ported from https://github.com/containerd/containerd/blob/v1.5.2/remotes/docker/scope.go#L29-L42 +// TODO: import this from containerd package once we drop support to continerd v1.4.x +// +// repositoryScope returns a repository scope string such as "repository:foo/bar:pull" +// for "host/foo/bar:baz". +// When push is true, both pull and push are added to the scope. +func repositoryScope(refspec reference.Spec, push bool) (string, error) { + u, err := url.Parse("dummy://" + refspec.Locator) + if err != nil { + return "", err + } + s := "repository:" + strings.TrimPrefix(u.Path, "/") + ":pull" + if push { + s += ",push" + } + return s, nil +} diff --git a/vendor/github.com/containerd/stargz-snapshotter/fs/source/source.go b/vendor/github.com/containerd/stargz-snapshotter/fs/source/source.go index a3d6cf190ddf..f764984a67c9 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/fs/source/source.go +++ b/vendor/github.com/containerd/stargz-snapshotter/fs/source/source.go @@ -30,19 +30,22 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) -// GetSource is a function for converting snapshot labels into typed blob sources +// GetSources is a function for converting snapshot labels into typed blob sources // information. This package defines a default converter which provides source // information based on some labels but implementations aren't required to use labels. // Implementations are allowed to return several sources (registry config + image refs) // about the blob. type GetSources func(labels map[string]string) (source []Source, err error) +// RegistryHosts returns a list of registries that provides the specified image. +type RegistryHosts func(reference.Spec) ([]docker.RegistryHost, error) + // Source is a typed blob source information. This contains information about // a blob stored in registries and some contexts of the blob. type Source struct { // Hosts is a registry configuration where this blob is stored. - Hosts docker.RegistryHosts + Hosts RegistryHosts // Name is an image reference which contains this blob. Name reference.Spec @@ -71,7 +74,7 @@ const ( // FromDefaultLabels returns a function for converting snapshot labels to // source information based on labels. -func FromDefaultLabels(hosts docker.RegistryHosts) GetSources { +func FromDefaultLabels(hosts RegistryHosts) GetSources { return func(labels map[string]string) ([]Source, error) { refStr, ok := labels[targetRefLabel] if !ok { diff --git a/vendor/github.com/containerd/stargz-snapshotter/snapshot/overlayutils/check.go b/vendor/github.com/containerd/stargz-snapshotter/snapshot/overlayutils/check.go new file mode 100644 index 000000000000..ea57dbc0659e --- /dev/null +++ b/vendor/github.com/containerd/stargz-snapshotter/snapshot/overlayutils/check.go @@ -0,0 +1,173 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// ===== +// NOTE: This file is ported from https://github.com/containerd/containerd/blob/v1.5.2/snapshots/overlay/overlayutils/check.go +// TODO: import this from containerd package once we drop support to continerd v1.4.x +// ===== + +package overlayutils + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/containerd/containerd/log" + "github.com/containerd/containerd/mount" + userns "github.com/containerd/containerd/sys" + "github.com/containerd/continuity/fs" + "github.com/pkg/errors" +) + +// SupportsMultipleLowerDir checks if the system supports multiple lowerdirs, +// which is required for the overlay snapshotter. On 4.x kernels, multiple lowerdirs +// are always available (so this check isn't needed), and backported to RHEL and +// CentOS 3.x kernels (3.10.0-693.el7.x86_64 and up). This function is to detect +// support on those kernels, without doing a kernel version compare. +// +// Ported from moby overlay2. +func SupportsMultipleLowerDir(d string) error { + td, err := ioutil.TempDir(d, "multiple-lowerdir-check") + if err != nil { + return err + } + defer func() { + if err := os.RemoveAll(td); err != nil { + log.L.WithError(err).Warnf("Failed to remove check directory %v", td) + } + }() + + for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} { + if err := os.Mkdir(filepath.Join(td, dir), 0755); err != nil { + return err + } + } + + opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", filepath.Join(td, "lower2"), filepath.Join(td, "lower1"), filepath.Join(td, "upper"), filepath.Join(td, "work")) + m := mount.Mount{ + Type: "overlay", + Source: "overlay", + Options: []string{opts}, + } + dest := filepath.Join(td, "merged") + if err := m.Mount(dest); err != nil { + return errors.Wrap(err, "failed to mount overlay") + } + if err := mount.UnmountAll(dest, 0); err != nil { + log.L.WithError(err).Warnf("Failed to unmount check directory %v", dest) + } + return nil +} + +// Supported returns nil when the overlayfs is functional on the system with the root directory. +// Supported is not called during plugin initialization, but exposed for downstream projects which uses +// this snapshotter as a library. +func Supported(root string) error { + if err := os.MkdirAll(root, 0700); err != nil { + return err + } + supportsDType, err := fs.SupportsDType(root) + if err != nil { + return err + } + if !supportsDType { + return fmt.Errorf("%s does not support d_type. If the backing filesystem is xfs, please reformat with ftype=1 to enable d_type support", root) + } + return SupportsMultipleLowerDir(root) +} + +// NeedsUserXAttr returns whether overlayfs should be mounted with the "userxattr" mount option. +// +// The "userxattr" option is needed for mounting overlayfs inside a user namespace with kernel >= 5.11. +// +// The "userxattr" option is NOT needed for the initial user namespace (aka "the host"). +// +// Also, Ubuntu (since circa 2015) and Debian (since 10) with kernel < 5.11 can mount +// the overlayfs in a user namespace without the "userxattr" option. +// +// The corresponding kernel commit: https://github.com/torvalds/linux/commit/2d2f2d7322ff43e0fe92bf8cccdc0b09449bf2e1 +// > ovl: user xattr +// > +// > Optionally allow using "user.overlay." namespace instead of "trusted.overlay." +// > ... +// > Disable redirect_dir and metacopy options, because these would allow privilege escalation through direct manipulation of the +// > "user.overlay.redirect" or "user.overlay.metacopy" xattrs. +// > ... +// +// The "userxattr" support is not exposed in "/sys/module/overlay/parameters". +func NeedsUserXAttr(d string) (bool, error) { + if !userns.RunningInUserNS() { + // we are the real root (i.e., the root in the initial user NS), + // so we do never need "userxattr" opt. + return false, nil + } + + // TODO: add fast path for kernel >= 5.11 . + // + // Keep in mind that distro vendors might be going to backport the patch to older kernels. + // So we can't completely remove the check. + + tdRoot := filepath.Join(d, "userxattr-check") + if err := os.RemoveAll(tdRoot); err != nil { + log.L.WithError(err).Warnf("Failed to remove check directory %v", tdRoot) + } + + if err := os.MkdirAll(tdRoot, 0700); err != nil { + return false, err + } + + defer func() { + if err := os.RemoveAll(tdRoot); err != nil { + log.L.WithError(err).Warnf("Failed to remove check directory %v", tdRoot) + } + }() + + td, err := ioutil.TempDir(tdRoot, "") + if err != nil { + return false, err + } + + for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} { + if err := os.Mkdir(filepath.Join(td, dir), 0755); err != nil { + return false, err + } + } + + opts := []string{ + fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", filepath.Join(td, "lower2"), filepath.Join(td, "lower1"), filepath.Join(td, "upper"), filepath.Join(td, "work")), + "userxattr", + } + + m := mount.Mount{ + Type: "overlay", + Source: "overlay", + Options: opts, + } + + dest := filepath.Join(td, "merged") + if err := m.Mount(dest); err != nil { + // Probably the host is running Ubuntu/Debian kernel (< 5.11) with the userns patch but without the userxattr patch. + // Return false without error. + log.L.WithError(err).Debugf("cannot mount overlay with \"userxattr\", probably the kernel does not support userxattr") + return false, nil + } + if err := mount.UnmountAll(dest, 0); err != nil { + log.L.WithError(err).Warnf("Failed to unmount check directory %v", dest) + } + return true, nil +} diff --git a/vendor/github.com/containerd/stargz-snapshotter/snapshot/snapshot.go b/vendor/github.com/containerd/stargz-snapshotter/snapshot/snapshot.go index 7c18d3164649..3f6baca2dd0e 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/snapshot/snapshot.go +++ b/vendor/github.com/containerd/stargz-snapshotter/snapshot/snapshot.go @@ -29,9 +29,9 @@ import ( "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/snapshots" - "github.com/containerd/containerd/snapshots/overlay/overlayutils" "github.com/containerd/containerd/snapshots/storage" "github.com/containerd/continuity/fs" + "github.com/containerd/stargz-snapshotter/snapshot/overlayutils" "github.com/moby/sys/mountinfo" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -41,6 +41,7 @@ import ( const ( targetSnapshotLabel = "containerd.io/snapshot.ref" remoteLabel = "containerd.io/snapshot/remote" + remoteLabelVal = "remote snapshot" // remoteSnapshotLogKey is a key for log line, which indicates whether // `Prepare` method successfully prepared targeting remote snapshot or not, as @@ -249,7 +250,7 @@ func (o *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...s log.G(lCtx).WithField(remoteSnapshotLogKey, prepareFailed). WithError(err).Debug("failed to prepare remote snapshot") } else { - base.Labels[remoteLabel] = fmt.Sprintf("remote snapshot") // Mark this snapshot as remote + base.Labels[remoteLabel] = remoteLabelVal // Mark this snapshot as remote err := o.Commit(ctx, target, key, append(opts, snapshots.WithLabels(base.Labels))...) if err == nil || errdefs.IsAlreadyExists(err) { // count also AlreadyExists as "success" diff --git a/vendor/github.com/coreos/go-systemd/v22/activation/files.go b/vendor/github.com/coreos/go-systemd/v22/activation/files_unix.go similarity index 98% rename from vendor/github.com/coreos/go-systemd/v22/activation/files.go rename to vendor/github.com/coreos/go-systemd/v22/activation/files_unix.go index 29dd18defad8..fc7db98fb41b 100644 --- a/vendor/github.com/coreos/go-systemd/v22/activation/files.go +++ b/vendor/github.com/coreos/go-systemd/v22/activation/files_unix.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build !windows + // Package activation implements primitives for systemd socket activation. package activation diff --git a/vendor/github.com/coreos/go-systemd/v22/activation/files_windows.go b/vendor/github.com/coreos/go-systemd/v22/activation/files_windows.go new file mode 100644 index 000000000000..d391bf00c5ee --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/v22/activation/files_windows.go @@ -0,0 +1,21 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package activation + +import "os" + +func Files(unsetEnv bool) []*os.File { + return nil +} diff --git a/vendor/github.com/klauspost/compress/snappy/.gitignore b/vendor/github.com/golang/snappy/.gitignore similarity index 100% rename from vendor/github.com/klauspost/compress/snappy/.gitignore rename to vendor/github.com/golang/snappy/.gitignore diff --git a/vendor/github.com/klauspost/compress/snappy/AUTHORS b/vendor/github.com/golang/snappy/AUTHORS similarity index 90% rename from vendor/github.com/klauspost/compress/snappy/AUTHORS rename to vendor/github.com/golang/snappy/AUTHORS index bcfa19520af9..203e84ebab0d 100644 --- a/vendor/github.com/klauspost/compress/snappy/AUTHORS +++ b/vendor/github.com/golang/snappy/AUTHORS @@ -8,8 +8,10 @@ # Please keep the list sorted. +Amazon.com, Inc Damian Gryski Google Inc. Jan Mercl <0xjnml@gmail.com> +Klaus Post Rodolfo Carvalho Sebastien Binet diff --git a/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS b/vendor/github.com/golang/snappy/CONTRIBUTORS similarity index 95% rename from vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS rename to vendor/github.com/golang/snappy/CONTRIBUTORS index 931ae31606f8..d9914732b5fc 100644 --- a/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS +++ b/vendor/github.com/golang/snappy/CONTRIBUTORS @@ -28,7 +28,9 @@ Damian Gryski Jan Mercl <0xjnml@gmail.com> +Jonathan Swinney Kai Backman +Klaus Post Marc-Antoine Ruel Nigel Tao Rob Pike diff --git a/vendor/github.com/klauspost/compress/snappy/LICENSE b/vendor/github.com/golang/snappy/LICENSE similarity index 100% rename from vendor/github.com/klauspost/compress/snappy/LICENSE rename to vendor/github.com/golang/snappy/LICENSE diff --git a/vendor/github.com/klauspost/compress/snappy/README b/vendor/github.com/golang/snappy/README similarity index 100% rename from vendor/github.com/klauspost/compress/snappy/README rename to vendor/github.com/golang/snappy/README diff --git a/vendor/github.com/klauspost/compress/snappy/decode.go b/vendor/github.com/golang/snappy/decode.go similarity index 97% rename from vendor/github.com/klauspost/compress/snappy/decode.go rename to vendor/github.com/golang/snappy/decode.go index 72efb0353ddf..f1e04b172c57 100644 --- a/vendor/github.com/klauspost/compress/snappy/decode.go +++ b/vendor/github.com/golang/snappy/decode.go @@ -52,6 +52,8 @@ const ( // Otherwise, a newly allocated slice will be returned. // // The dst and src must not overlap. It is valid to pass a nil dst. +// +// Decode handles the Snappy block format, not the Snappy stream format. func Decode(dst, src []byte) ([]byte, error) { dLen, s, err := decodedLen(src) if err != nil { @@ -83,6 +85,8 @@ func NewReader(r io.Reader) *Reader { } // Reader is an io.Reader that can read Snappy-compressed bytes. +// +// Reader handles the Snappy stream format, not the Snappy block format. type Reader struct { r io.Reader err error diff --git a/vendor/github.com/klauspost/compress/snappy/decode_amd64.s b/vendor/github.com/golang/snappy/decode_amd64.s similarity index 98% rename from vendor/github.com/klauspost/compress/snappy/decode_amd64.s rename to vendor/github.com/golang/snappy/decode_amd64.s index 1c66e37234dc..e6179f65e351 100644 --- a/vendor/github.com/klauspost/compress/snappy/decode_amd64.s +++ b/vendor/github.com/golang/snappy/decode_amd64.s @@ -184,7 +184,9 @@ tagLit60Plus: // checks. In the asm version, we code it once instead of once per switch case. ADDQ CX, SI SUBQ $58, SI - CMPQ SI, R13 + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 JA errCorrupt // case x == 60: @@ -230,7 +232,9 @@ tagCopy4: ADDQ $5, SI // if uint(s) > uint(len(src)) { etc } - CMPQ SI, R13 + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 JA errCorrupt // length = 1 + int(src[s-5])>>2 @@ -247,7 +251,9 @@ tagCopy2: ADDQ $3, SI // if uint(s) > uint(len(src)) { etc } - CMPQ SI, R13 + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 JA errCorrupt // length = 1 + int(src[s-3])>>2 @@ -271,7 +277,9 @@ tagCopy: ADDQ $2, SI // if uint(s) > uint(len(src)) { etc } - CMPQ SI, R13 + MOVQ SI, BX + SUBQ R11, BX + CMPQ BX, R12 JA errCorrupt // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) diff --git a/vendor/github.com/golang/snappy/decode_arm64.s b/vendor/github.com/golang/snappy/decode_arm64.s new file mode 100644 index 000000000000..7a3ead17eacf --- /dev/null +++ b/vendor/github.com/golang/snappy/decode_arm64.s @@ -0,0 +1,494 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The asm code generally follows the pure Go code in decode_other.go, except +// where marked with a "!!!". + +// func decode(dst, src []byte) int +// +// All local variables fit into registers. The non-zero stack size is only to +// spill registers and push args when issuing a CALL. The register allocation: +// - R2 scratch +// - R3 scratch +// - R4 length or x +// - R5 offset +// - R6 &src[s] +// - R7 &dst[d] +// + R8 dst_base +// + R9 dst_len +// + R10 dst_base + dst_len +// + R11 src_base +// + R12 src_len +// + R13 src_base + src_len +// - R14 used by doCopy +// - R15 used by doCopy +// +// The registers R8-R13 (marked with a "+") are set at the start of the +// function, and after a CALL returns, and are not otherwise modified. +// +// The d variable is implicitly R7 - R8, and len(dst)-d is R10 - R7. +// The s variable is implicitly R6 - R11, and len(src)-s is R13 - R6. +TEXT ·decode(SB), NOSPLIT, $56-56 + // Initialize R6, R7 and R8-R13. + MOVD dst_base+0(FP), R8 + MOVD dst_len+8(FP), R9 + MOVD R8, R7 + MOVD R8, R10 + ADD R9, R10, R10 + MOVD src_base+24(FP), R11 + MOVD src_len+32(FP), R12 + MOVD R11, R6 + MOVD R11, R13 + ADD R12, R13, R13 + +loop: + // for s < len(src) + CMP R13, R6 + BEQ end + + // R4 = uint32(src[s]) + // + // switch src[s] & 0x03 + MOVBU (R6), R4 + MOVW R4, R3 + ANDW $3, R3 + MOVW $1, R1 + CMPW R1, R3 + BGE tagCopy + + // ---------------------------------------- + // The code below handles literal tags. + + // case tagLiteral: + // x := uint32(src[s] >> 2) + // switch + MOVW $60, R1 + LSRW $2, R4, R4 + CMPW R4, R1 + BLS tagLit60Plus + + // case x < 60: + // s++ + ADD $1, R6, R6 + +doLit: + // This is the end of the inner "switch", when we have a literal tag. + // + // We assume that R4 == x and x fits in a uint32, where x is the variable + // used in the pure Go decode_other.go code. + + // length = int(x) + 1 + // + // Unlike the pure Go code, we don't need to check if length <= 0 because + // R4 can hold 64 bits, so the increment cannot overflow. + ADD $1, R4, R4 + + // Prepare to check if copying length bytes will run past the end of dst or + // src. + // + // R2 = len(dst) - d + // R3 = len(src) - s + MOVD R10, R2 + SUB R7, R2, R2 + MOVD R13, R3 + SUB R6, R3, R3 + + // !!! Try a faster technique for short (16 or fewer bytes) copies. + // + // if length > 16 || len(dst)-d < 16 || len(src)-s < 16 { + // goto callMemmove // Fall back on calling runtime·memmove. + // } + // + // The C++ snappy code calls this TryFastAppend. It also checks len(src)-s + // against 21 instead of 16, because it cannot assume that all of its input + // is contiguous in memory and so it needs to leave enough source bytes to + // read the next tag without refilling buffers, but Go's Decode assumes + // contiguousness (the src argument is a []byte). + CMP $16, R4 + BGT callMemmove + CMP $16, R2 + BLT callMemmove + CMP $16, R3 + BLT callMemmove + + // !!! Implement the copy from src to dst as a 16-byte load and store. + // (Decode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only length bytes, but that's + // OK. If the input is a valid Snappy encoding then subsequent iterations + // will fix up the overrun. Otherwise, Decode returns a nil []byte (and a + // non-nil error), so the overrun will be ignored. + // + // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + LDP 0(R6), (R14, R15) + STP (R14, R15), 0(R7) + + // d += length + // s += length + ADD R4, R7, R7 + ADD R4, R6, R6 + B loop + +callMemmove: + // if length > len(dst)-d || length > len(src)-s { etc } + CMP R2, R4 + BGT errCorrupt + CMP R3, R4 + BGT errCorrupt + + // copy(dst[d:], src[s:s+length]) + // + // This means calling runtime·memmove(&dst[d], &src[s], length), so we push + // R7, R6 and R4 as arguments. Coincidentally, we also need to spill those + // three registers to the stack, to save local variables across the CALL. + MOVD R7, 8(RSP) + MOVD R6, 16(RSP) + MOVD R4, 24(RSP) + MOVD R7, 32(RSP) + MOVD R6, 40(RSP) + MOVD R4, 48(RSP) + CALL runtime·memmove(SB) + + // Restore local variables: unspill registers from the stack and + // re-calculate R8-R13. + MOVD 32(RSP), R7 + MOVD 40(RSP), R6 + MOVD 48(RSP), R4 + MOVD dst_base+0(FP), R8 + MOVD dst_len+8(FP), R9 + MOVD R8, R10 + ADD R9, R10, R10 + MOVD src_base+24(FP), R11 + MOVD src_len+32(FP), R12 + MOVD R11, R13 + ADD R12, R13, R13 + + // d += length + // s += length + ADD R4, R7, R7 + ADD R4, R6, R6 + B loop + +tagLit60Plus: + // !!! This fragment does the + // + // s += x - 58; if uint(s) > uint(len(src)) { etc } + // + // checks. In the asm version, we code it once instead of once per switch case. + ADD R4, R6, R6 + SUB $58, R6, R6 + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // case x == 60: + MOVW $61, R1 + CMPW R1, R4 + BEQ tagLit61 + BGT tagLit62Plus + + // x = uint32(src[s-1]) + MOVBU -1(R6), R4 + B doLit + +tagLit61: + // case x == 61: + // x = uint32(src[s-2]) | uint32(src[s-1])<<8 + MOVHU -2(R6), R4 + B doLit + +tagLit62Plus: + CMPW $62, R4 + BHI tagLit63 + + // case x == 62: + // x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + MOVHU -3(R6), R4 + MOVBU -1(R6), R3 + ORR R3<<16, R4 + B doLit + +tagLit63: + // case x == 63: + // x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + MOVWU -4(R6), R4 + B doLit + + // The code above handles literal tags. + // ---------------------------------------- + // The code below handles copy tags. + +tagCopy4: + // case tagCopy4: + // s += 5 + ADD $5, R6, R6 + + // if uint(s) > uint(len(src)) { etc } + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // length = 1 + int(src[s-5])>>2 + MOVD $1, R1 + ADD R4>>2, R1, R4 + + // offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + MOVWU -4(R6), R5 + B doCopy + +tagCopy2: + // case tagCopy2: + // s += 3 + ADD $3, R6, R6 + + // if uint(s) > uint(len(src)) { etc } + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // length = 1 + int(src[s-3])>>2 + MOVD $1, R1 + ADD R4>>2, R1, R4 + + // offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + MOVHU -2(R6), R5 + B doCopy + +tagCopy: + // We have a copy tag. We assume that: + // - R3 == src[s] & 0x03 + // - R4 == src[s] + CMP $2, R3 + BEQ tagCopy2 + BGT tagCopy4 + + // case tagCopy1: + // s += 2 + ADD $2, R6, R6 + + // if uint(s) > uint(len(src)) { etc } + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + MOVD R4, R5 + AND $0xe0, R5 + MOVBU -1(R6), R3 + ORR R5<<3, R3, R5 + + // length = 4 + int(src[s-2])>>2&0x7 + MOVD $7, R1 + AND R4>>2, R1, R4 + ADD $4, R4, R4 + +doCopy: + // This is the end of the outer "switch", when we have a copy tag. + // + // We assume that: + // - R4 == length && R4 > 0 + // - R5 == offset + + // if offset <= 0 { etc } + MOVD $0, R1 + CMP R1, R5 + BLE errCorrupt + + // if d < offset { etc } + MOVD R7, R3 + SUB R8, R3, R3 + CMP R5, R3 + BLT errCorrupt + + // if length > len(dst)-d { etc } + MOVD R10, R3 + SUB R7, R3, R3 + CMP R3, R4 + BGT errCorrupt + + // forwardCopy(dst[d:d+length], dst[d-offset:]); d += length + // + // Set: + // - R14 = len(dst)-d + // - R15 = &dst[d-offset] + MOVD R10, R14 + SUB R7, R14, R14 + MOVD R7, R15 + SUB R5, R15, R15 + + // !!! Try a faster technique for short (16 or fewer bytes) forward copies. + // + // First, try using two 8-byte load/stores, similar to the doLit technique + // above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is + // still OK if offset >= 8. Note that this has to be two 8-byte load/stores + // and not one 16-byte load/store, and the first store has to be before the + // second load, due to the overlap if offset is in the range [8, 16). + // + // if length > 16 || offset < 8 || len(dst)-d < 16 { + // goto slowForwardCopy + // } + // copy 16 bytes + // d += length + CMP $16, R4 + BGT slowForwardCopy + CMP $8, R5 + BLT slowForwardCopy + CMP $16, R14 + BLT slowForwardCopy + MOVD 0(R15), R2 + MOVD R2, 0(R7) + MOVD 8(R15), R3 + MOVD R3, 8(R7) + ADD R4, R7, R7 + B loop + +slowForwardCopy: + // !!! If the forward copy is longer than 16 bytes, or if offset < 8, we + // can still try 8-byte load stores, provided we can overrun up to 10 extra + // bytes. As above, the overrun will be fixed up by subsequent iterations + // of the outermost loop. + // + // The C++ snappy code calls this technique IncrementalCopyFastPath. Its + // commentary says: + // + // ---- + // + // The main part of this loop is a simple copy of eight bytes at a time + // until we've copied (at least) the requested amount of bytes. However, + // if d and d-offset are less than eight bytes apart (indicating a + // repeating pattern of length < 8), we first need to expand the pattern in + // order to get the correct results. For instance, if the buffer looks like + // this, with the eight-byte and patterns marked as + // intervals: + // + // abxxxxxxxxxxxx + // [------] d-offset + // [------] d + // + // a single eight-byte copy from to will repeat the pattern + // once, after which we can move two bytes without moving : + // + // ababxxxxxxxxxx + // [------] d-offset + // [------] d + // + // and repeat the exercise until the two no longer overlap. + // + // This allows us to do very well in the special case of one single byte + // repeated many times, without taking a big hit for more general cases. + // + // The worst case of extra writing past the end of the match occurs when + // offset == 1 and length == 1; the last copy will read from byte positions + // [0..7] and write to [4..11], whereas it was only supposed to write to + // position 1. Thus, ten excess bytes. + // + // ---- + // + // That "10 byte overrun" worst case is confirmed by Go's + // TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy + // and finishSlowForwardCopy algorithm. + // + // if length > len(dst)-d-10 { + // goto verySlowForwardCopy + // } + SUB $10, R14, R14 + CMP R14, R4 + BGT verySlowForwardCopy + +makeOffsetAtLeast8: + // !!! As above, expand the pattern so that offset >= 8 and we can use + // 8-byte load/stores. + // + // for offset < 8 { + // copy 8 bytes from dst[d-offset:] to dst[d:] + // length -= offset + // d += offset + // offset += offset + // // The two previous lines together means that d-offset, and therefore + // // R15, is unchanged. + // } + CMP $8, R5 + BGE fixUpSlowForwardCopy + MOVD (R15), R3 + MOVD R3, (R7) + SUB R5, R4, R4 + ADD R5, R7, R7 + ADD R5, R5, R5 + B makeOffsetAtLeast8 + +fixUpSlowForwardCopy: + // !!! Add length (which might be negative now) to d (implied by R7 being + // &dst[d]) so that d ends up at the right place when we jump back to the + // top of the loop. Before we do that, though, we save R7 to R2 so that, if + // length is positive, copying the remaining length bytes will write to the + // right place. + MOVD R7, R2 + ADD R4, R7, R7 + +finishSlowForwardCopy: + // !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative + // length means that we overrun, but as above, that will be fixed up by + // subsequent iterations of the outermost loop. + MOVD $0, R1 + CMP R1, R4 + BLE loop + MOVD (R15), R3 + MOVD R3, (R2) + ADD $8, R15, R15 + ADD $8, R2, R2 + SUB $8, R4, R4 + B finishSlowForwardCopy + +verySlowForwardCopy: + // verySlowForwardCopy is a simple implementation of forward copy. In C + // parlance, this is a do/while loop instead of a while loop, since we know + // that length > 0. In Go syntax: + // + // for { + // dst[d] = dst[d - offset] + // d++ + // length-- + // if length == 0 { + // break + // } + // } + MOVB (R15), R3 + MOVB R3, (R7) + ADD $1, R15, R15 + ADD $1, R7, R7 + SUB $1, R4, R4 + CBNZ R4, verySlowForwardCopy + B loop + + // The code above handles copy tags. + // ---------------------------------------- + +end: + // This is the end of the "for s < len(src)". + // + // if d != len(dst) { etc } + CMP R10, R7 + BNE errCorrupt + + // return 0 + MOVD $0, ret+48(FP) + RET + +errCorrupt: + // return decodeErrCodeCorrupt + MOVD $1, R2 + MOVD R2, ret+48(FP) + RET diff --git a/vendor/github.com/klauspost/compress/snappy/decode_amd64.go b/vendor/github.com/golang/snappy/decode_asm.go similarity index 93% rename from vendor/github.com/klauspost/compress/snappy/decode_amd64.go rename to vendor/github.com/golang/snappy/decode_asm.go index fcd192b849ed..7082b349199a 100644 --- a/vendor/github.com/klauspost/compress/snappy/decode_amd64.go +++ b/vendor/github.com/golang/snappy/decode_asm.go @@ -5,6 +5,7 @@ // +build !appengine // +build gc // +build !noasm +// +build amd64 arm64 package snappy diff --git a/vendor/github.com/klauspost/compress/snappy/decode_other.go b/vendor/github.com/golang/snappy/decode_other.go similarity index 98% rename from vendor/github.com/klauspost/compress/snappy/decode_other.go rename to vendor/github.com/golang/snappy/decode_other.go index 94a96c5d7b85..2f672be55743 100644 --- a/vendor/github.com/klauspost/compress/snappy/decode_other.go +++ b/vendor/github.com/golang/snappy/decode_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine !gc noasm +// +build !amd64,!arm64 appengine !gc noasm package snappy @@ -87,7 +87,7 @@ func decode(dst, src []byte) int { } // Copy from an earlier sub-slice of dst to a later sub-slice. // If no overlap, use the built-in copy: - if offset > length { + if offset >= length { copy(dst[d:d+length], dst[d-offset:]) d += length continue diff --git a/vendor/github.com/klauspost/compress/snappy/encode.go b/vendor/github.com/golang/snappy/encode.go similarity index 98% rename from vendor/github.com/klauspost/compress/snappy/encode.go rename to vendor/github.com/golang/snappy/encode.go index 8d393e904bb3..7f23657076c5 100644 --- a/vendor/github.com/klauspost/compress/snappy/encode.go +++ b/vendor/github.com/golang/snappy/encode.go @@ -15,6 +15,8 @@ import ( // Otherwise, a newly allocated slice will be returned. // // The dst and src must not overlap. It is valid to pass a nil dst. +// +// Encode handles the Snappy block format, not the Snappy stream format. func Encode(dst, src []byte) []byte { if n := MaxEncodedLen(len(src)); n < 0 { panic(ErrTooLarge) @@ -139,6 +141,8 @@ func NewBufferedWriter(w io.Writer) *Writer { } // Writer is an io.Writer that can write Snappy-compressed bytes. +// +// Writer handles the Snappy stream format, not the Snappy block format. type Writer struct { w io.Writer err error diff --git a/vendor/github.com/klauspost/compress/snappy/encode_amd64.s b/vendor/github.com/golang/snappy/encode_amd64.s similarity index 100% rename from vendor/github.com/klauspost/compress/snappy/encode_amd64.s rename to vendor/github.com/golang/snappy/encode_amd64.s diff --git a/vendor/github.com/golang/snappy/encode_arm64.s b/vendor/github.com/golang/snappy/encode_arm64.s new file mode 100644 index 000000000000..bf83667d711f --- /dev/null +++ b/vendor/github.com/golang/snappy/encode_arm64.s @@ -0,0 +1,722 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The asm code generally follows the pure Go code in encode_other.go, except +// where marked with a "!!!". + +// ---------------------------------------------------------------------------- + +// func emitLiteral(dst, lit []byte) int +// +// All local variables fit into registers. The register allocation: +// - R3 len(lit) +// - R4 n +// - R6 return value +// - R8 &dst[i] +// - R10 &lit[0] +// +// The 32 bytes of stack space is to call runtime·memmove. +// +// The unusual register allocation of local variables, such as R10 for the +// source pointer, matches the allocation used at the call site in encodeBlock, +// which makes it easier to manually inline this function. +TEXT ·emitLiteral(SB), NOSPLIT, $32-56 + MOVD dst_base+0(FP), R8 + MOVD lit_base+24(FP), R10 + MOVD lit_len+32(FP), R3 + MOVD R3, R6 + MOVW R3, R4 + SUBW $1, R4, R4 + + CMPW $60, R4 + BLT oneByte + CMPW $256, R4 + BLT twoBytes + +threeBytes: + MOVD $0xf4, R2 + MOVB R2, 0(R8) + MOVW R4, 1(R8) + ADD $3, R8, R8 + ADD $3, R6, R6 + B memmove + +twoBytes: + MOVD $0xf0, R2 + MOVB R2, 0(R8) + MOVB R4, 1(R8) + ADD $2, R8, R8 + ADD $2, R6, R6 + B memmove + +oneByte: + LSLW $2, R4, R4 + MOVB R4, 0(R8) + ADD $1, R8, R8 + ADD $1, R6, R6 + +memmove: + MOVD R6, ret+48(FP) + + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // R8, R10 and R3 as arguments. + MOVD R8, 8(RSP) + MOVD R10, 16(RSP) + MOVD R3, 24(RSP) + CALL runtime·memmove(SB) + RET + +// ---------------------------------------------------------------------------- + +// func emitCopy(dst []byte, offset, length int) int +// +// All local variables fit into registers. The register allocation: +// - R3 length +// - R7 &dst[0] +// - R8 &dst[i] +// - R11 offset +// +// The unusual register allocation of local variables, such as R11 for the +// offset, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·emitCopy(SB), NOSPLIT, $0-48 + MOVD dst_base+0(FP), R8 + MOVD R8, R7 + MOVD offset+24(FP), R11 + MOVD length+32(FP), R3 + +loop0: + // for length >= 68 { etc } + CMPW $68, R3 + BLT step1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVD $0xfe, R2 + MOVB R2, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUB $64, R3, R3 + B loop0 + +step1: + // if length > 64 { etc } + CMP $64, R3 + BLE step2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVD $0xee, R2 + MOVB R2, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUB $60, R3, R3 + +step2: + // if length >= 12 || offset >= 2048 { goto step3 } + CMP $12, R3 + BGE step3 + CMPW $2048, R11 + BGE step3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(R8) + LSRW $3, R11, R11 + AND $0xe0, R11, R11 + SUB $4, R3, R3 + LSLW $2, R3 + AND $0xff, R3, R3 + ORRW R3, R11, R11 + ORRW $1, R11, R11 + MOVB R11, 0(R8) + ADD $2, R8, R8 + + // Return the number of bytes written. + SUB R7, R8, R8 + MOVD R8, ret+40(FP) + RET + +step3: + // Emit the remaining copy, encoded as 3 bytes. + SUB $1, R3, R3 + AND $0xff, R3, R3 + LSLW $2, R3, R3 + ORRW $2, R3, R3 + MOVB R3, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + + // Return the number of bytes written. + SUB R7, R8, R8 + MOVD R8, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func extendMatch(src []byte, i, j int) int +// +// All local variables fit into registers. The register allocation: +// - R6 &src[0] +// - R7 &src[j] +// - R13 &src[len(src) - 8] +// - R14 &src[len(src)] +// - R15 &src[i] +// +// The unusual register allocation of local variables, such as R15 for a source +// pointer, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·extendMatch(SB), NOSPLIT, $0-48 + MOVD src_base+0(FP), R6 + MOVD src_len+8(FP), R14 + MOVD i+24(FP), R15 + MOVD j+32(FP), R7 + ADD R6, R14, R14 + ADD R6, R15, R15 + ADD R6, R7, R7 + MOVD R14, R13 + SUB $8, R13, R13 + +cmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMP R13, R7 + BHI cmp1 + MOVD (R15), R3 + MOVD (R7), R4 + CMP R4, R3 + BNE bsf + ADD $8, R15, R15 + ADD $8, R7, R7 + B cmp8 + +bsf: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. + // RBIT reverses the bit order, then CLZ counts the leading zeros, the + // combination of which finds the least significant bit which is set. + // The arm64 architecture is little-endian, and the shift by 3 converts + // a bit index to a byte index. + EOR R3, R4, R4 + RBIT R4, R4 + CLZ R4, R4 + ADD R4>>3, R7, R7 + + // Convert from &src[ret] to ret. + SUB R6, R7, R7 + MOVD R7, ret+40(FP) + RET + +cmp1: + // In src's tail, compare 1 byte at a time. + CMP R7, R14 + BLS extendMatchEnd + MOVB (R15), R3 + MOVB (R7), R4 + CMP R4, R3 + BNE extendMatchEnd + ADD $1, R15, R15 + ADD $1, R7, R7 + B cmp1 + +extendMatchEnd: + // Convert from &src[ret] to ret. + SUB R6, R7, R7 + MOVD R7, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func encodeBlock(dst, src []byte) (d int) +// +// All local variables fit into registers, other than "var table". The register +// allocation: +// - R3 . . +// - R4 . . +// - R5 64 shift +// - R6 72 &src[0], tableSize +// - R7 80 &src[s] +// - R8 88 &dst[d] +// - R9 96 sLimit +// - R10 . &src[nextEmit] +// - R11 104 prevHash, currHash, nextHash, offset +// - R12 112 &src[base], skip +// - R13 . &src[nextS], &src[len(src) - 8] +// - R14 . len(src), bytesBetweenHashLookups, &src[len(src)], x +// - R15 120 candidate +// - R16 . hash constant, 0x1e35a7bd +// - R17 . &table +// - . 128 table +// +// The second column (64, 72, etc) is the stack offset to spill the registers +// when calling other functions. We could pack this slightly tighter, but it's +// simpler to have a dedicated spill map independent of the function called. +// +// "var table [maxTableSize]uint16" takes up 32768 bytes of stack space. An +// extra 64 bytes, to call other functions, and an extra 64 bytes, to spill +// local variables (registers) during calls gives 32768 + 64 + 64 = 32896. +TEXT ·encodeBlock(SB), 0, $32896-56 + MOVD dst_base+0(FP), R8 + MOVD src_base+24(FP), R7 + MOVD src_len+32(FP), R14 + + // shift, tableSize := uint32(32-8), 1<<8 + MOVD $24, R5 + MOVD $256, R6 + MOVW $0xa7bd, R16 + MOVKW $(0x1e35<<16), R16 + +calcShift: + // for ; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + // shift-- + // } + MOVD $16384, R2 + CMP R2, R6 + BGE varTable + CMP R14, R6 + BGE varTable + SUB $1, R5, R5 + LSL $1, R6, R6 + B calcShift + +varTable: + // var table [maxTableSize]uint16 + // + // In the asm code, unlike the Go code, we can zero-initialize only the + // first tableSize elements. Each uint16 element is 2 bytes and each + // iterations writes 64 bytes, so we can do only tableSize/32 writes + // instead of the 2048 writes that would zero-initialize all of table's + // 32768 bytes. This clear could overrun the first tableSize elements, but + // it won't overrun the allocated stack size. + ADD $128, RSP, R17 + MOVD R17, R4 + + // !!! R6 = &src[tableSize] + ADD R6<<1, R17, R6 + +memclr: + STP.P (ZR, ZR), 64(R4) + STP (ZR, ZR), -48(R4) + STP (ZR, ZR), -32(R4) + STP (ZR, ZR), -16(R4) + CMP R4, R6 + BHI memclr + + // !!! R6 = &src[0] + MOVD R7, R6 + + // sLimit := len(src) - inputMargin + MOVD R14, R9 + SUB $15, R9, R9 + + // !!! Pre-emptively spill R5, R6 and R9 to the stack. Their values don't + // change for the rest of the function. + MOVD R5, 64(RSP) + MOVD R6, 72(RSP) + MOVD R9, 96(RSP) + + // nextEmit := 0 + MOVD R6, R10 + + // s := 1 + ADD $1, R7, R7 + + // nextHash := hash(load32(src, s), shift) + MOVW 0(R7), R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + +outer: + // for { etc } + + // skip := 32 + MOVD $32, R12 + + // nextS := s + MOVD R7, R13 + + // candidate := 0 + MOVD $0, R15 + +inner0: + // for { etc } + + // s := nextS + MOVD R13, R7 + + // bytesBetweenHashLookups := skip >> 5 + MOVD R12, R14 + LSR $5, R14, R14 + + // nextS = s + bytesBetweenHashLookups + ADD R14, R13, R13 + + // skip += bytesBetweenHashLookups + ADD R14, R12, R12 + + // if nextS > sLimit { goto emitRemainder } + MOVD R13, R3 + SUB R6, R3, R3 + CMP R9, R3 + BHI emitRemainder + + // candidate = int(table[nextHash]) + MOVHU 0(R17)(R11<<1), R15 + + // table[nextHash] = uint16(s) + MOVD R7, R3 + SUB R6, R3, R3 + + MOVH R3, 0(R17)(R11<<1) + + // nextHash = hash(load32(src, nextS), shift) + MOVW 0(R13), R11 + MULW R16, R11 + LSRW R5, R11, R11 + + // if load32(src, s) != load32(src, candidate) { continue } break + MOVW 0(R7), R3 + MOVW (R6)(R15*1), R4 + CMPW R4, R3 + BNE inner0 + +fourByteMatch: + // As per the encode_other.go code: + // + // A 4-byte match has been found. We'll later see etc. + + // !!! Jump to a fast path for short (<= 16 byte) literals. See the comment + // on inputMargin in encode.go. + MOVD R7, R3 + SUB R10, R3, R3 + CMP $16, R3 + BLE emitLiteralFastPath + + // ---------------------------------------- + // Begin inline of the emitLiteral call. + // + // d += emitLiteral(dst[d:], src[nextEmit:s]) + + MOVW R3, R4 + SUBW $1, R4, R4 + + MOVW $60, R2 + CMPW R2, R4 + BLT inlineEmitLiteralOneByte + MOVW $256, R2 + CMPW R2, R4 + BLT inlineEmitLiteralTwoBytes + +inlineEmitLiteralThreeBytes: + MOVD $0xf4, R1 + MOVB R1, 0(R8) + MOVW R4, 1(R8) + ADD $3, R8, R8 + B inlineEmitLiteralMemmove + +inlineEmitLiteralTwoBytes: + MOVD $0xf0, R1 + MOVB R1, 0(R8) + MOVB R4, 1(R8) + ADD $2, R8, R8 + B inlineEmitLiteralMemmove + +inlineEmitLiteralOneByte: + LSLW $2, R4, R4 + MOVB R4, 0(R8) + ADD $1, R8, R8 + +inlineEmitLiteralMemmove: + // Spill local variables (registers) onto the stack; call; unspill. + // + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // R8, R10 and R3 as arguments. + MOVD R8, 8(RSP) + MOVD R10, 16(RSP) + MOVD R3, 24(RSP) + + // Finish the "d +=" part of "d += emitLiteral(etc)". + ADD R3, R8, R8 + MOVD R7, 80(RSP) + MOVD R8, 88(RSP) + MOVD R15, 120(RSP) + CALL runtime·memmove(SB) + MOVD 64(RSP), R5 + MOVD 72(RSP), R6 + MOVD 80(RSP), R7 + MOVD 88(RSP), R8 + MOVD 96(RSP), R9 + MOVD 120(RSP), R15 + ADD $128, RSP, R17 + MOVW $0xa7bd, R16 + MOVKW $(0x1e35<<16), R16 + B inner1 + +inlineEmitLiteralEnd: + // End inline of the emitLiteral call. + // ---------------------------------------- + +emitLiteralFastPath: + // !!! Emit the 1-byte encoding "uint8(len(lit)-1)<<2". + MOVB R3, R4 + SUBW $1, R4, R4 + AND $0xff, R4, R4 + LSLW $2, R4, R4 + MOVB R4, (R8) + ADD $1, R8, R8 + + // !!! Implement the copy from lit to dst as a 16-byte load and store. + // (Encode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only len(lit) bytes, but that's + // OK. Subsequent iterations will fix up the overrun. + // + // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + LDP 0(R10), (R0, R1) + STP (R0, R1), 0(R8) + ADD R3, R8, R8 + +inner1: + // for { etc } + + // base := s + MOVD R7, R12 + + // !!! offset := base - candidate + MOVD R12, R11 + SUB R15, R11, R11 + SUB R6, R11, R11 + + // ---------------------------------------- + // Begin inline of the extendMatch call. + // + // s = extendMatch(src, candidate+4, s+4) + + // !!! R14 = &src[len(src)] + MOVD src_len+32(FP), R14 + ADD R6, R14, R14 + + // !!! R13 = &src[len(src) - 8] + MOVD R14, R13 + SUB $8, R13, R13 + + // !!! R15 = &src[candidate + 4] + ADD $4, R15, R15 + ADD R6, R15, R15 + + // !!! s += 4 + ADD $4, R7, R7 + +inlineExtendMatchCmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMP R13, R7 + BHI inlineExtendMatchCmp1 + MOVD (R15), R3 + MOVD (R7), R4 + CMP R4, R3 + BNE inlineExtendMatchBSF + ADD $8, R15, R15 + ADD $8, R7, R7 + B inlineExtendMatchCmp8 + +inlineExtendMatchBSF: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. + // RBIT reverses the bit order, then CLZ counts the leading zeros, the + // combination of which finds the least significant bit which is set. + // The arm64 architecture is little-endian, and the shift by 3 converts + // a bit index to a byte index. + EOR R3, R4, R4 + RBIT R4, R4 + CLZ R4, R4 + ADD R4>>3, R7, R7 + B inlineExtendMatchEnd + +inlineExtendMatchCmp1: + // In src's tail, compare 1 byte at a time. + CMP R7, R14 + BLS inlineExtendMatchEnd + MOVB (R15), R3 + MOVB (R7), R4 + CMP R4, R3 + BNE inlineExtendMatchEnd + ADD $1, R15, R15 + ADD $1, R7, R7 + B inlineExtendMatchCmp1 + +inlineExtendMatchEnd: + // End inline of the extendMatch call. + // ---------------------------------------- + + // ---------------------------------------- + // Begin inline of the emitCopy call. + // + // d += emitCopy(dst[d:], base-candidate, s-base) + + // !!! length := s - base + MOVD R7, R3 + SUB R12, R3, R3 + +inlineEmitCopyLoop0: + // for length >= 68 { etc } + MOVW $68, R2 + CMPW R2, R3 + BLT inlineEmitCopyStep1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVD $0xfe, R1 + MOVB R1, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUBW $64, R3, R3 + B inlineEmitCopyLoop0 + +inlineEmitCopyStep1: + // if length > 64 { etc } + MOVW $64, R2 + CMPW R2, R3 + BLE inlineEmitCopyStep2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVD $0xee, R1 + MOVB R1, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUBW $60, R3, R3 + +inlineEmitCopyStep2: + // if length >= 12 || offset >= 2048 { goto inlineEmitCopyStep3 } + MOVW $12, R2 + CMPW R2, R3 + BGE inlineEmitCopyStep3 + MOVW $2048, R2 + CMPW R2, R11 + BGE inlineEmitCopyStep3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(R8) + LSRW $8, R11, R11 + LSLW $5, R11, R11 + SUBW $4, R3, R3 + AND $0xff, R3, R3 + LSLW $2, R3, R3 + ORRW R3, R11, R11 + ORRW $1, R11, R11 + MOVB R11, 0(R8) + ADD $2, R8, R8 + B inlineEmitCopyEnd + +inlineEmitCopyStep3: + // Emit the remaining copy, encoded as 3 bytes. + SUBW $1, R3, R3 + LSLW $2, R3, R3 + ORRW $2, R3, R3 + MOVB R3, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + +inlineEmitCopyEnd: + // End inline of the emitCopy call. + // ---------------------------------------- + + // nextEmit = s + MOVD R7, R10 + + // if s >= sLimit { goto emitRemainder } + MOVD R7, R3 + SUB R6, R3, R3 + CMP R3, R9 + BLS emitRemainder + + // As per the encode_other.go code: + // + // We could immediately etc. + + // x := load64(src, s-1) + MOVD -1(R7), R14 + + // prevHash := hash(uint32(x>>0), shift) + MOVW R14, R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + + // table[prevHash] = uint16(s-1) + MOVD R7, R3 + SUB R6, R3, R3 + SUB $1, R3, R3 + + MOVHU R3, 0(R17)(R11<<1) + + // currHash := hash(uint32(x>>8), shift) + LSR $8, R14, R14 + MOVW R14, R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + + // candidate = int(table[currHash]) + MOVHU 0(R17)(R11<<1), R15 + + // table[currHash] = uint16(s) + ADD $1, R3, R3 + MOVHU R3, 0(R17)(R11<<1) + + // if uint32(x>>8) == load32(src, candidate) { continue } + MOVW (R6)(R15*1), R4 + CMPW R4, R14 + BEQ inner1 + + // nextHash = hash(uint32(x>>16), shift) + LSR $8, R14, R14 + MOVW R14, R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + + // s++ + ADD $1, R7, R7 + + // break out of the inner1 for loop, i.e. continue the outer loop. + B outer + +emitRemainder: + // if nextEmit < len(src) { etc } + MOVD src_len+32(FP), R3 + ADD R6, R3, R3 + CMP R3, R10 + BEQ encodeBlockEnd + + // d += emitLiteral(dst[d:], src[nextEmit:]) + // + // Push args. + MOVD R8, 8(RSP) + MOVD $0, 16(RSP) // Unnecessary, as the callee ignores it, but conservative. + MOVD $0, 24(RSP) // Unnecessary, as the callee ignores it, but conservative. + MOVD R10, 32(RSP) + SUB R10, R3, R3 + MOVD R3, 40(RSP) + MOVD R3, 48(RSP) // Unnecessary, as the callee ignores it, but conservative. + + // Spill local variables (registers) onto the stack; call; unspill. + MOVD R8, 88(RSP) + CALL ·emitLiteral(SB) + MOVD 88(RSP), R8 + + // Finish the "d +=" part of "d += emitLiteral(etc)". + MOVD 56(RSP), R1 + ADD R1, R8, R8 + +encodeBlockEnd: + MOVD dst_base+0(FP), R3 + SUB R3, R8, R8 + MOVD R8, d+48(FP) + RET diff --git a/vendor/github.com/klauspost/compress/snappy/encode_amd64.go b/vendor/github.com/golang/snappy/encode_asm.go similarity index 97% rename from vendor/github.com/klauspost/compress/snappy/encode_amd64.go rename to vendor/github.com/golang/snappy/encode_asm.go index 150d91bc8be5..107c1e71418f 100644 --- a/vendor/github.com/klauspost/compress/snappy/encode_amd64.go +++ b/vendor/github.com/golang/snappy/encode_asm.go @@ -5,6 +5,7 @@ // +build !appengine // +build gc // +build !noasm +// +build amd64 arm64 package snappy diff --git a/vendor/github.com/klauspost/compress/snappy/encode_other.go b/vendor/github.com/golang/snappy/encode_other.go similarity index 99% rename from vendor/github.com/klauspost/compress/snappy/encode_other.go rename to vendor/github.com/golang/snappy/encode_other.go index dbcae905e6e0..296d7f0beb0f 100644 --- a/vendor/github.com/klauspost/compress/snappy/encode_other.go +++ b/vendor/github.com/golang/snappy/encode_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine !gc noasm +// +build !amd64,!arm64 appengine !gc noasm package snappy diff --git a/vendor/github.com/golang/snappy/go.mod b/vendor/github.com/golang/snappy/go.mod new file mode 100644 index 000000000000..f6406bb2c76d --- /dev/null +++ b/vendor/github.com/golang/snappy/go.mod @@ -0,0 +1 @@ +module github.com/golang/snappy diff --git a/vendor/github.com/klauspost/compress/snappy/snappy.go b/vendor/github.com/golang/snappy/snappy.go similarity index 97% rename from vendor/github.com/klauspost/compress/snappy/snappy.go rename to vendor/github.com/golang/snappy/snappy.go index ea58ced88246..ece692ea4610 100644 --- a/vendor/github.com/klauspost/compress/snappy/snappy.go +++ b/vendor/github.com/golang/snappy/snappy.go @@ -17,7 +17,7 @@ // // The canonical, C++ implementation is at https://github.com/google/snappy and // it only implements the block format. -package snappy +package snappy // import "github.com/golang/snappy" import ( "hash/crc32" @@ -94,5 +94,5 @@ var crcTable = crc32.MakeTable(crc32.Castagnoli) // https://github.com/google/snappy/blob/master/framing_format.txt func crc(b []byte) uint32 { c := crc32.Update(0, crcTable, b) - return c>>15 | c<<17 + 0xa282ead8 + return uint32(c>>15|c<<17) + 0xa282ead8 } diff --git a/vendor/github.com/hanwen/go-fuse/v2/AUTHORS b/vendor/github.com/hanwen/go-fuse/v2/AUTHORS index 052128d3090b..49cafa6a7d35 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/AUTHORS +++ b/vendor/github.com/hanwen/go-fuse/v2/AUTHORS @@ -16,5 +16,6 @@ Patrick Crosby Paul Jolly Paul Warren Shayan Pooya +Tommy Lindgren Valient Gough Yongwoo Park diff --git a/vendor/github.com/hanwen/go-fuse/v2/fs/files.go b/vendor/github.com/hanwen/go-fuse/v2/fs/files.go index 67304a9e21cf..59d4963c0ade 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fs/files.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fs/files.go @@ -17,7 +17,9 @@ import ( ) // NewLoopbackFile creates a FileHandle out of a file descriptor. All -// operations are implemented. +// operations are implemented. When using the Fd from a *os.File, call +// syscall.Dup() on the fd, to avoid os.File's finalizer from closing +// the file descriptor. func NewLoopbackFile(fd int) FileHandle { return &loopbackFile{fd: fd} } diff --git a/vendor/github.com/hanwen/go-fuse/v2/fs/inode.go b/vendor/github.com/hanwen/go-fuse/v2/fs/inode.go index 3d81bcbb50fc..3ee00dbc4ddf 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fs/inode.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fs/inode.go @@ -583,8 +583,6 @@ retry: lockNodes(lockme...) if n.changeCounter != nChange { unlockNodes(lockme...) - // could avoid unlocking and relocking n here. - n.mu.Lock() continue retry } diff --git a/vendor/github.com/hanwen/go-fuse/v2/fs/loopback.go b/vendor/github.com/hanwen/go-fuse/v2/fs/loopback.go index 2cf607cbcd41..c8ff0557cffc 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fs/loopback.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fs/loopback.go @@ -13,39 +13,84 @@ import ( "github.com/hanwen/go-fuse/v2/fuse" ) -type loopbackRoot struct { - loopbackNode +// LoopbackRoot holds the parameters for creating a new loopback +// filesystem. Loopback filesystem delegate their operations to an +// underlying POSIX file system. +type LoopbackRoot struct { + // The path to the root of the underlying file system. + Path string + + // The device on which the Path resides. This must be set if + // the underlying filesystem crosses file systems. + Dev uint64 + + // NewNode returns a new InodeEmbedder to be used to respond + // to a LOOKUP/CREATE/MKDIR/MKNOD opcode. If not set, use a + // LoopbackNode. + NewNode func(rootData *LoopbackRoot, parent *Inode, name string, st *syscall.Stat_t) InodeEmbedder +} - rootPath string - rootDev uint64 +func (r *LoopbackRoot) newNode(parent *Inode, name string, st *syscall.Stat_t) InodeEmbedder { + if r.NewNode != nil { + return r.NewNode(r, parent, name, st) + } + return &LoopbackNode{ + RootData: r, + } +} + +func (r *LoopbackRoot) idFromStat(st *syscall.Stat_t) StableAttr { + // We compose an inode number by the underlying inode, and + // mixing in the device number. In traditional filesystems, + // the inode numbers are small. The device numbers are also + // small (typically 16 bit). Finally, we mask out the root + // device number of the root, so a loopback FS that does not + // encompass multiple mounts will reflect the inode numbers of + // the underlying filesystem + swapped := (uint64(st.Dev) << 32) | (uint64(st.Dev) >> 32) + swappedRootDev := (r.Dev << 32) | (r.Dev >> 32) + return StableAttr{ + Mode: uint32(st.Mode), + Gen: 1, + // This should work well for traditional backing FSes, + // not so much for other go-fuse FS-es + Ino: (swapped ^ swappedRootDev) ^ st.Ino, + } } -type loopbackNode struct { +// LoopbackNode is a filesystem node in a loopback file system. It is +// public so it can be used as a basis for other loopback based +// filesystems. See NewLoopbackFile or LoopbackRoot for more +// information. +type LoopbackNode struct { Inode + + // RootData points back to the root of the loopback filesystem. + RootData *LoopbackRoot } -var _ = (NodeStatfser)((*loopbackNode)(nil)) -var _ = (NodeStatfser)((*loopbackNode)(nil)) -var _ = (NodeGetattrer)((*loopbackNode)(nil)) -var _ = (NodeGetxattrer)((*loopbackNode)(nil)) -var _ = (NodeSetxattrer)((*loopbackNode)(nil)) -var _ = (NodeRemovexattrer)((*loopbackNode)(nil)) -var _ = (NodeListxattrer)((*loopbackNode)(nil)) -var _ = (NodeReadlinker)((*loopbackNode)(nil)) -var _ = (NodeOpener)((*loopbackNode)(nil)) -var _ = (NodeCopyFileRanger)((*loopbackNode)(nil)) -var _ = (NodeLookuper)((*loopbackNode)(nil)) -var _ = (NodeOpendirer)((*loopbackNode)(nil)) -var _ = (NodeReaddirer)((*loopbackNode)(nil)) -var _ = (NodeMkdirer)((*loopbackNode)(nil)) -var _ = (NodeMknoder)((*loopbackNode)(nil)) -var _ = (NodeLinker)((*loopbackNode)(nil)) -var _ = (NodeSymlinker)((*loopbackNode)(nil)) -var _ = (NodeUnlinker)((*loopbackNode)(nil)) -var _ = (NodeRmdirer)((*loopbackNode)(nil)) -var _ = (NodeRenamer)((*loopbackNode)(nil)) - -func (n *loopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { +var _ = (NodeStatfser)((*LoopbackNode)(nil)) +var _ = (NodeStatfser)((*LoopbackNode)(nil)) +var _ = (NodeGetattrer)((*LoopbackNode)(nil)) +var _ = (NodeGetxattrer)((*LoopbackNode)(nil)) +var _ = (NodeSetxattrer)((*LoopbackNode)(nil)) +var _ = (NodeRemovexattrer)((*LoopbackNode)(nil)) +var _ = (NodeListxattrer)((*LoopbackNode)(nil)) +var _ = (NodeReadlinker)((*LoopbackNode)(nil)) +var _ = (NodeOpener)((*LoopbackNode)(nil)) +var _ = (NodeCopyFileRanger)((*LoopbackNode)(nil)) +var _ = (NodeLookuper)((*LoopbackNode)(nil)) +var _ = (NodeOpendirer)((*LoopbackNode)(nil)) +var _ = (NodeReaddirer)((*LoopbackNode)(nil)) +var _ = (NodeMkdirer)((*LoopbackNode)(nil)) +var _ = (NodeMknoder)((*LoopbackNode)(nil)) +var _ = (NodeLinker)((*LoopbackNode)(nil)) +var _ = (NodeSymlinker)((*LoopbackNode)(nil)) +var _ = (NodeUnlinker)((*LoopbackNode)(nil)) +var _ = (NodeRmdirer)((*LoopbackNode)(nil)) +var _ = (NodeRenamer)((*LoopbackNode)(nil)) + +func (n *LoopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno { s := syscall.Statfs_t{} err := syscall.Statfs(n.path(), &s) if err != nil { @@ -55,26 +100,14 @@ func (n *loopbackNode) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall. return OK } -func (r *loopbackRoot) Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno { - st := syscall.Stat_t{} - err := syscall.Stat(r.rootPath, &st) - if err != nil { - return ToErrno(err) - } - out.FromStat(&st) - return OK -} - -func (n *loopbackNode) root() *loopbackRoot { - return n.Root().Operations().(*loopbackRoot) -} - -func (n *loopbackNode) path() string { +// path returns the full path to the file in the underlying file +// system. +func (n *LoopbackNode) path() string { path := n.Path(n.Root()) - return filepath.Join(n.root().rootPath, path) + return filepath.Join(n.RootData.Path, path) } -func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { +func (n *LoopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { p := filepath.Join(n.path(), name) st := syscall.Stat_t{} @@ -84,14 +117,14 @@ func (n *loopbackNode) Lookup(ctx context.Context, name string, out *fuse.EntryO } out.Attr.FromStat(&st) - node := &loopbackNode{} - ch := n.NewInode(ctx, node, n.root().idFromStat(&st)) + node := n.RootData.newNode(n.EmbeddedInode(), name, &st) + ch := n.NewInode(ctx, node, n.RootData.idFromStat(&st)) return ch, 0 } // preserveOwner sets uid and gid of `path` according to the caller information // in `ctx`. -func (n *loopbackNode) preserveOwner(ctx context.Context, path string) error { +func (n *LoopbackNode) preserveOwner(ctx context.Context, path string) error { if os.Getuid() != 0 { return nil } @@ -102,7 +135,7 @@ func (n *loopbackNode) preserveOwner(ctx context.Context, path string) error { return syscall.Lchown(path, int(caller.Uid), int(caller.Gid)) } -func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) { +func (n *LoopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) { p := filepath.Join(n.path(), name) err := syscall.Mknod(p, mode, int(rdev)) if err != nil { @@ -117,13 +150,13 @@ func (n *loopbackNode) Mknod(ctx context.Context, name string, mode, rdev uint32 out.Attr.FromStat(&st) - node := &loopbackNode{} - ch := n.NewInode(ctx, node, n.root().idFromStat(&st)) + node := n.RootData.newNode(n.EmbeddedInode(), name, &st) + ch := n.NewInode(ctx, node, n.RootData.idFromStat(&st)) return ch, 0 } -func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) { +func (n *LoopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.EntryOut) (*Inode, syscall.Errno) { p := filepath.Join(n.path(), name) err := os.Mkdir(p, os.FileMode(mode)) if err != nil { @@ -138,66 +171,39 @@ func (n *loopbackNode) Mkdir(ctx context.Context, name string, mode uint32, out out.Attr.FromStat(&st) - node := &loopbackNode{} - ch := n.NewInode(ctx, node, n.root().idFromStat(&st)) + node := n.RootData.newNode(n.EmbeddedInode(), name, &st) + ch := n.NewInode(ctx, node, n.RootData.idFromStat(&st)) return ch, 0 } -func (n *loopbackNode) Rmdir(ctx context.Context, name string) syscall.Errno { +func (n *LoopbackNode) Rmdir(ctx context.Context, name string) syscall.Errno { p := filepath.Join(n.path(), name) err := syscall.Rmdir(p) return ToErrno(err) } -func (n *loopbackNode) Unlink(ctx context.Context, name string) syscall.Errno { +func (n *LoopbackNode) Unlink(ctx context.Context, name string) syscall.Errno { p := filepath.Join(n.path(), name) err := syscall.Unlink(p) return ToErrno(err) } -func toLoopbackNode(op InodeEmbedder) *loopbackNode { - if r, ok := op.(*loopbackRoot); ok { - return &r.loopbackNode - } - return op.(*loopbackNode) -} - -func (n *loopbackNode) Rename(ctx context.Context, name string, newParent InodeEmbedder, newName string, flags uint32) syscall.Errno { - newParentLoopback := toLoopbackNode(newParent) +func (n *LoopbackNode) Rename(ctx context.Context, name string, newParent InodeEmbedder, newName string, flags uint32) syscall.Errno { if flags&RENAME_EXCHANGE != 0 { - return n.renameExchange(name, newParentLoopback, newName) + return n.renameExchange(name, newParent, newName) } p1 := filepath.Join(n.path(), name) - p2 := filepath.Join(newParentLoopback.path(), newName) + p2 := filepath.Join(n.RootData.Path, newParent.EmbeddedInode().Path(nil), newName) err := syscall.Rename(p1, p2) return ToErrno(err) } -func (r *loopbackRoot) idFromStat(st *syscall.Stat_t) StableAttr { - // We compose an inode number by the underlying inode, and - // mixing in the device number. In traditional filesystems, - // the inode numbers are small. The device numbers are also - // small (typically 16 bit). Finally, we mask out the root - // device number of the root, so a loopback FS that does not - // encompass multiple mounts will reflect the inode numbers of - // the underlying filesystem - swapped := (uint64(st.Dev) << 32) | (uint64(st.Dev) >> 32) - swappedRootDev := (r.rootDev << 32) | (r.rootDev >> 32) - return StableAttr{ - Mode: uint32(st.Mode), - Gen: 1, - // This should work well for traditional backing FSes, - // not so much for other go-fuse FS-es - Ino: (swapped ^ swappedRootDev) ^ st.Ino, - } -} - -var _ = (NodeCreater)((*loopbackNode)(nil)) +var _ = (NodeCreater)((*LoopbackNode)(nil)) -func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (inode *Inode, fh FileHandle, fuseFlags uint32, errno syscall.Errno) { +func (n *LoopbackNode) Create(ctx context.Context, name string, flags uint32, mode uint32, out *fuse.EntryOut) (inode *Inode, fh FileHandle, fuseFlags uint32, errno syscall.Errno) { p := filepath.Join(n.path(), name) flags = flags &^ syscall.O_APPEND fd, err := syscall.Open(p, int(flags)|os.O_CREATE, mode) @@ -211,15 +217,15 @@ func (n *loopbackNode) Create(ctx context.Context, name string, flags uint32, mo return nil, nil, 0, ToErrno(err) } - node := &loopbackNode{} - ch := n.NewInode(ctx, node, n.root().idFromStat(&st)) + node := n.RootData.newNode(n.EmbeddedInode(), name, &st) + ch := n.NewInode(ctx, node, n.RootData.idFromStat(&st)) lf := NewLoopbackFile(fd) out.FromStat(&st) return ch, lf, 0, 0 } -func (n *loopbackNode) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { +func (n *LoopbackNode) Symlink(ctx context.Context, target, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { p := filepath.Join(n.path(), name) err := syscall.Symlink(target, p) if err != nil { @@ -231,18 +237,17 @@ func (n *loopbackNode) Symlink(ctx context.Context, target, name string, out *fu syscall.Unlink(p) return nil, ToErrno(err) } - node := &loopbackNode{} - ch := n.NewInode(ctx, node, n.root().idFromStat(&st)) + node := n.RootData.newNode(n.EmbeddedInode(), name, &st) + ch := n.NewInode(ctx, node, n.RootData.idFromStat(&st)) out.Attr.FromStat(&st) return ch, 0 } -func (n *loopbackNode) Link(ctx context.Context, target InodeEmbedder, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { +func (n *LoopbackNode) Link(ctx context.Context, target InodeEmbedder, name string, out *fuse.EntryOut) (*Inode, syscall.Errno) { p := filepath.Join(n.path(), name) - targetNode := toLoopbackNode(target) - err := syscall.Link(targetNode.path(), p) + err := syscall.Link(filepath.Join(n.RootData.Path, target.EmbeddedInode().Path(nil)), p) if err != nil { return nil, ToErrno(err) } @@ -251,14 +256,14 @@ func (n *loopbackNode) Link(ctx context.Context, target InodeEmbedder, name stri syscall.Unlink(p) return nil, ToErrno(err) } - node := &loopbackNode{} - ch := n.NewInode(ctx, node, n.root().idFromStat(&st)) + node := n.RootData.newNode(n.EmbeddedInode(), name, &st) + ch := n.NewInode(ctx, node, n.RootData.idFromStat(&st)) out.Attr.FromStat(&st) return ch, 0 } -func (n *loopbackNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) { +func (n *LoopbackNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) { p := n.path() for l := 256; ; l *= 2 { @@ -274,7 +279,7 @@ func (n *loopbackNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) { } } -func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) { +func (n *LoopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) { flags = flags &^ syscall.O_APPEND p := n.path() f, err := syscall.Open(p, int(flags), 0) @@ -285,7 +290,7 @@ func (n *loopbackNode) Open(ctx context.Context, flags uint32) (fh FileHandle, f return lf, 0, 0 } -func (n *loopbackNode) Opendir(ctx context.Context) syscall.Errno { +func (n *LoopbackNode) Opendir(ctx context.Context) syscall.Errno { fd, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0755) if err != nil { return ToErrno(err) @@ -294,19 +299,25 @@ func (n *loopbackNode) Opendir(ctx context.Context) syscall.Errno { return OK } -func (n *loopbackNode) Readdir(ctx context.Context) (DirStream, syscall.Errno) { +func (n *LoopbackNode) Readdir(ctx context.Context) (DirStream, syscall.Errno) { return NewLoopbackDirStream(n.path()) } -func (n *loopbackNode) Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno { +func (n *LoopbackNode) Getattr(ctx context.Context, f FileHandle, out *fuse.AttrOut) syscall.Errno { if f != nil { return f.(FileGetattrer).Getattr(ctx, out) } + p := n.path() var err error st := syscall.Stat_t{} - err = syscall.Lstat(p, &st) + if &n.Inode == n.Root() { + err = syscall.Stat(p, &st) + } else { + err = syscall.Lstat(p, &st) + } + if err != nil { return ToErrno(err) } @@ -314,9 +325,9 @@ func (n *loopbackNode) Getattr(ctx context.Context, f FileHandle, out *fuse.Attr return OK } -var _ = (NodeSetattrer)((*loopbackNode)(nil)) +var _ = (NodeSetattrer)((*LoopbackNode)(nil)) -func (n *loopbackNode) Setattr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno { +func (n *LoopbackNode) Setattr(ctx context.Context, f FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno { p := n.path() fsa, ok := f.(FileSetattrer) if ok && fsa != nil { @@ -390,16 +401,17 @@ func (n *loopbackNode) Setattr(ctx context.Context, f FileHandle, in *fuse.SetAt // NewLoopbackRoot returns a root node for a loopback file system whose // root is at the given root. This node implements all NodeXxxxer // operations available. -func NewLoopbackRoot(root string) (InodeEmbedder, error) { +func NewLoopbackRoot(rootPath string) (InodeEmbedder, error) { var st syscall.Stat_t - err := syscall.Stat(root, &st) + err := syscall.Stat(rootPath, &st) if err != nil { return nil, err } - n := &loopbackRoot{ - rootPath: root, - rootDev: uint64(st.Dev), + root := &LoopbackRoot{ + Path: rootPath, + Dev: uint64(st.Dev), } - return n, nil + + return root.newNode(nil, "", &st), nil } diff --git a/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_darwin.go b/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_darwin.go index 40eabee09a93..739c5a59e23b 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_darwin.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_darwin.go @@ -16,23 +16,23 @@ import ( "github.com/hanwen/go-fuse/v2/internal/utimens" ) -func (n *loopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { +func (n *LoopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { return 0, syscall.ENOSYS } -func (n *loopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno { +func (n *LoopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno { return syscall.ENOSYS } -func (n *loopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno { +func (n *LoopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno { return syscall.ENOSYS } -func (n *loopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { +func (n *LoopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { return 0, syscall.ENOSYS } -func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newName string) syscall.Errno { +func (n *LoopbackNode) renameExchange(name string, newparent InodeEmbedder, newName string) syscall.Errno { return syscall.ENOSYS } @@ -111,7 +111,7 @@ func (f *loopbackFile) utimens(a *time.Time, m *time.Time) syscall.Errno { return ToErrno(err) } -func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle, +func (n *LoopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle, offIn uint64, out *Inode, fhOut FileHandle, offOut uint64, len uint64, flags uint64) (uint32, syscall.Errno) { return 0, syscall.ENOSYS diff --git a/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_linux.go b/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_linux.go index 590596a32ce5..5d0597a40285 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_linux.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fs/loopback_linux.go @@ -8,38 +8,40 @@ package fs import ( "context" + "path/filepath" "syscall" "golang.org/x/sys/unix" ) -func (n *loopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { +func (n *LoopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { sz, err := unix.Lgetxattr(n.path(), attr, dest) return uint32(sz), ToErrno(err) } -func (n *loopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno { +func (n *LoopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno { err := unix.Lsetxattr(n.path(), attr, data, int(flags)) return ToErrno(err) } -func (n *loopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno { +func (n *LoopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno { err := unix.Lremovexattr(n.path(), attr) return ToErrno(err) } -func (n *loopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { +func (n *LoopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { sz, err := unix.Llistxattr(n.path(), dest) return uint32(sz), ToErrno(err) } -func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newName string) syscall.Errno { +func (n *LoopbackNode) renameExchange(name string, newparent InodeEmbedder, newName string) syscall.Errno { fd1, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0) if err != nil { return ToErrno(err) } defer syscall.Close(fd1) - fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0) + p2 := filepath.Join(n.RootData.Path, newparent.EmbeddedInode().Path(nil)) + fd2, err := syscall.Open(p2, syscall.O_DIRECTORY, 0) defer syscall.Close(fd2) if err != nil { return ToErrno(err) @@ -52,22 +54,22 @@ func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newN // Double check that nodes didn't change from under us. inode := &n.Inode - if inode.Root() != inode && inode.StableAttr().Ino != n.root().idFromStat(&st).Ino { + if inode.Root() != inode && inode.StableAttr().Ino != n.RootData.idFromStat(&st).Ino { return syscall.EBUSY } if err := syscall.Fstat(fd2, &st); err != nil { return ToErrno(err) } - newinode := &newparent.Inode - if newinode.Root() != newinode && newinode.StableAttr().Ino != n.root().idFromStat(&st).Ino { + newinode := newparent.EmbeddedInode() + if newinode.Root() != newinode && newinode.StableAttr().Ino != n.RootData.idFromStat(&st).Ino { return syscall.EBUSY } return ToErrno(unix.Renameat2(fd1, name, fd2, newName, unix.RENAME_EXCHANGE)) } -func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle, +func (n *LoopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle, offIn uint64, out *Inode, fhOut FileHandle, offOut uint64, len uint64, flags uint64) (uint32, syscall.Errno) { lfIn, ok := fhIn.(*loopbackFile) diff --git a/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go b/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go index 36d75ae763ad..3274eaa6f33d 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go @@ -67,6 +67,12 @@ // Typically, each call of the API happens in its own // goroutine, so take care to make the file system thread-safe. // +// Be careful when you access the FUSE mount from the same process. An access can +// tie up two OS threads (one on the request side and one on the FUSE server side). +// This can deadlock if there is no free thread to handle the FUSE server side. +// Run your program with GOMAXPROCS=1 to make the problem easier to reproduce, +// see https://github.com/hanwen/go-fuse/issues/261 for an example of that +// problem. // // Higher level interfaces // diff --git a/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go b/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go index 685bb402615d..1112799bba91 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go @@ -9,89 +9,125 @@ import ( "fmt" "os" "os/exec" - "path/filepath" "strings" "syscall" + "unsafe" ) -func openFUSEDevice() (*os.File, error) { - fs, err := filepath.Glob("/dev/osxfuse*") +func unixgramSocketpair() (l, r *os.File, err error) { + fd, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) if err != nil { - return nil, err + return nil, nil, os.NewSyscallError("socketpair", + err.(syscall.Errno)) } - if len(fs) == 0 { - bin := oldLoadBin - if _, err := os.Stat(newLoadBin); err == nil { - bin = newLoadBin - } - - cmd := exec.Command(bin) - if err := cmd.Run(); err != nil { - return nil, err - } - fs, err = filepath.Glob("/dev/osxfuse*") - if err != nil { - return nil, err - } - } - - for _, fn := range fs { - f, err := os.OpenFile(fn, os.O_RDWR, 0) - if err != nil { - continue - } - return f, nil - } - - return nil, fmt.Errorf("all FUSE devices busy") + l = os.NewFile(uintptr(fd[0]), "socketpair-half1") + r = os.NewFile(uintptr(fd[1]), "socketpair-half2") + return } -const oldLoadBin = "/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs" -const newLoadBin = "/Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse" - -const oldMountBin = "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs" -const newMountBin = "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse" - +// Create a FUSE FS on the specified mount point. The returned +// mount point is always absolute. func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) { - f, err := openFUSEDevice() + local, remote, err := unixgramSocketpair() if err != nil { - return 0, err + return } - bin := oldMountBin - if _, err := os.Stat(newMountBin); err == nil { - bin = newMountBin + defer local.Close() + defer remote.Close() + + bin, err := fusermountBinary() + if err != nil { + return 0, err } - cmd := exec.Command(bin, "-o", strings.Join(opts.optionsStrings(), ","), "-o", fmt.Sprintf("iosize=%d", opts.MaxWrite), "3", mountPoint) - cmd.ExtraFiles = []*os.File{f} - cmd.Env = append(os.Environ(), "MOUNT_FUSEFS_CALL_BY_LIB=", "MOUNT_OSXFUSE_CALL_BY_LIB=", - "MOUNT_OSXFUSE_DAEMON_PATH="+os.Args[0], - "MOUNT_FUSEFS_DAEMON_PATH="+os.Args[0]) + cmd := exec.Command(bin, + "-o", strings.Join(opts.optionsStrings(), ","), + "-o", fmt.Sprintf("iosize=%d", opts.MaxWrite), + mountPoint) + cmd.ExtraFiles = []*os.File{remote} // fd would be (index + 3) + cmd.Env = append(os.Environ(), + "_FUSE_CALL_BY_LIB=", + "_FUSE_DAEMON_PATH="+os.Args[0], + "_FUSE_COMMFD=3", + "_FUSE_COMMVERS=2", + "MOUNT_OSXFUSE_CALL_BY_LIB=", + "MOUNT_OSXFUSE_DAEMON_PATH="+os.Args[0]) var out, errOut bytes.Buffer cmd.Stdout = &out cmd.Stderr = &errOut - if err := cmd.Start(); err != nil { - f.Close() - return 0, err + if err = cmd.Start(); err != nil { + return } + + fd, err = getConnection(local) + if err != nil { + return -1, err + } + go func() { - err := cmd.Wait() - if err != nil { - err = fmt.Errorf("mount_osxfusefs failed: %v. Stderr: %s, Stdout: %s", err, errOut.String(), out.String()) + // wait inside a goroutine or otherwise it would block forever for unknown reasons + if err := cmd.Wait(); err != nil { + err = fmt.Errorf("mount_osxfusefs failed: %v. Stderr: %s, Stdout: %s", + err, errOut.String(), out.String()) } ready <- err close(ready) }() - // The finalizer for f will close its fd so we return a dup. - defer f.Close() - return syscall.Dup(int(f.Fd())) + // golang sets CLOEXEC on file descriptors when they are + // acquired through normal operations (e.g. open). + // Buf for fd, we have to set CLOEXEC manually + syscall.CloseOnExec(fd) + + return fd, err } func unmount(dir string, opts *MountOptions) error { return syscall.Unmount(dir, 0) } + +func getConnection(local *os.File) (int, error) { + var data [4]byte + control := make([]byte, 4*256) + + // n, oobn, recvflags, from, errno - todo: error checking. + _, oobn, _, _, + err := syscall.Recvmsg( + int(local.Fd()), data[:], control[:], 0) + if err != nil { + return 0, err + } + + message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0])) + fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr)) + + if message.Type != syscall.SCM_RIGHTS { + return 0, fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type) + } + if oobn <= syscall.SizeofCmsghdr { + return 0, fmt.Errorf("getConnection: too short control message. Length: %d", oobn) + } + if fd < 0 { + return 0, fmt.Errorf("getConnection: fd < 0: %d", fd) + } + return int(fd), nil +} + +func fusermountBinary() (string, error) { + binPaths := []string{ + "/Library/Filesystems/macfuse.fs/Contents/Resources/mount_macfuse", + "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse", + } + + for _, path := range binPaths { + if _, err := os.Stat(path); err == nil { + return path, nil + } + } + + return "", fmt.Errorf("no FUSE mount utility found") +} diff --git a/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go b/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go index cdd062f18f33..c570d3d70170 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go @@ -28,7 +28,7 @@ func doPollHackLookup(ms *Server, req *request) { Fh: pollHackInode, } req.status = OK - case _OP_GETATTR: + case _OP_GETATTR, _OP_SETATTR: out := (*AttrOut)(req.outData()) out.Attr = attr req.status = OK diff --git a/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go b/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go index 94d6a90efa12..4b5c2428cc9d 100644 --- a/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go +++ b/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go @@ -21,6 +21,9 @@ import ( const ( // The kernel caps writes at 128k. MAX_KERNEL_WRITE = 128 * 1024 + + minMaxReaders = 2 + maxMaxReaders = 16 ) // Server contains the logic for reading from the FUSE device and @@ -40,6 +43,9 @@ type Server struct { opts *MountOptions + // maxReaders is the maximum number of goroutines reading requests + maxReaders int + // Pools for []byte buffers bufferPool @@ -161,9 +167,17 @@ func NewServer(fs RawFileSystem, mountPoint string, opts *MountOptions) (*Server } } + maxReaders := runtime.GOMAXPROCS(0) + if maxReaders < minMaxReaders { + maxReaders = minMaxReaders + } else if maxReaders > maxMaxReaders { + maxReaders = maxMaxReaders + } + ms := &Server{ fileSystem: fs, opts: &o, + maxReaders: maxReaders, retrieveTab: make(map[uint64]*retrieveCacheRequest), // OSX has races when multiple routines read from the // FUSE device: on unmount, sometime some reads do not @@ -238,9 +252,6 @@ func (ms *Server) DebugData() string { return fmt.Sprintf("readers: %d", r) } -// What is a good number? Maybe the number of CPUs? -const _MAX_READERS = 2 - // handleEINTR retries the given function until it doesn't return syscall.EINTR. // This is similar to the HANDLE_EINTR() macro from Chromium ( see // https://code.google.com/p/chromium/codesearch#chromium/src/base/posix/eintr_wrapper.h @@ -267,7 +278,7 @@ func (ms *Server) readRequest(exitIdle bool) (req *request, code Status) { dest := ms.readPool.Get().([]byte) ms.reqMu.Lock() - if ms.reqReaders > _MAX_READERS { + if ms.reqReaders > ms.maxReaders { ms.reqMu.Unlock() return nil, OK } diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE new file mode 100644 index 000000000000..c33dcc7c928c --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/LICENSE @@ -0,0 +1,354 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md new file mode 100644 index 000000000000..444df08f8e77 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/README.md @@ -0,0 +1,89 @@ +# errwrap + +`errwrap` is a package for Go that formalizes the pattern of wrapping errors +and checking if an error contains another error. + +There is a common pattern in Go of taking a returned `error` value and +then wrapping it (such as with `fmt.Errorf`) before returning it. The problem +with this pattern is that you completely lose the original `error` structure. + +Arguably the _correct_ approach is that you should make a custom structure +implementing the `error` interface, and have the original error as a field +on that structure, such [as this example](http://golang.org/pkg/os/#PathError). +This is a good approach, but you have to know the entire chain of possible +rewrapping that happens, when you might just care about one. + +`errwrap` formalizes this pattern (it doesn't matter what approach you use +above) by giving a single interface for wrapping errors, checking if a specific +error is wrapped, and extracting that error. + +## Installation and Docs + +Install using `go get github.com/hashicorp/errwrap`. + +Full documentation is available at +http://godoc.org/github.com/hashicorp/errwrap + +## Usage + +#### Basic Usage + +Below is a very basic example of its usage: + +```go +// A function that always returns an error, but wraps it, like a real +// function might. +func tryOpen() error { + _, err := os.Open("/i/dont/exist") + if err != nil { + return errwrap.Wrapf("Doesn't exist: {{err}}", err) + } + + return nil +} + +func main() { + err := tryOpen() + + // We can use the Contains helpers to check if an error contains + // another error. It is safe to do this with a nil error, or with + // an error that doesn't even use the errwrap package. + if errwrap.Contains(err, "does not exist") { + // Do something + } + if errwrap.ContainsType(err, new(os.PathError)) { + // Do something + } + + // Or we can use the associated `Get` functions to just extract + // a specific error. This would return nil if that specific error doesn't + // exist. + perr := errwrap.GetType(err, new(os.PathError)) +} +``` + +#### Custom Types + +If you're already making custom types that properly wrap errors, then +you can get all the functionality of `errwraps.Contains` and such by +implementing the `Wrapper` interface with just one function. Example: + +```go +type AppError { + Code ErrorCode + Err error +} + +func (e *AppError) WrappedErrors() []error { + return []error{e.Err} +} +``` + +Now this works: + +```go +err := &AppError{Err: fmt.Errorf("an error")} +if errwrap.ContainsType(err, fmt.Errorf("")) { + // This will work! +} +``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go new file mode 100644 index 000000000000..a733bef18c05 --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/errwrap.go @@ -0,0 +1,169 @@ +// Package errwrap implements methods to formalize error wrapping in Go. +// +// All of the top-level functions that take an `error` are built to be able +// to take any error, not just wrapped errors. This allows you to use errwrap +// without having to type-check and type-cast everywhere. +package errwrap + +import ( + "errors" + "reflect" + "strings" +) + +// WalkFunc is the callback called for Walk. +type WalkFunc func(error) + +// Wrapper is an interface that can be implemented by custom types to +// have all the Contains, Get, etc. functions in errwrap work. +// +// When Walk reaches a Wrapper, it will call the callback for every +// wrapped error in addition to the wrapper itself. Since all the top-level +// functions in errwrap use Walk, this means that all those functions work +// with your custom type. +type Wrapper interface { + WrappedErrors() []error +} + +// Wrap defines that outer wraps inner, returning an error type that +// can be cleanly used with the other methods in this package, such as +// Contains, GetAll, etc. +// +// This function won't modify the error message at all (the outer message +// will be used). +func Wrap(outer, inner error) error { + return &wrappedError{ + Outer: outer, + Inner: inner, + } +} + +// Wrapf wraps an error with a formatting message. This is similar to using +// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap +// errors, you should replace it with this. +// +// format is the format of the error message. The string '{{err}}' will +// be replaced with the original error message. +func Wrapf(format string, err error) error { + outerMsg := "" + if err != nil { + outerMsg = err.Error() + } + + outer := errors.New(strings.Replace( + format, "{{err}}", outerMsg, -1)) + + return Wrap(outer, err) +} + +// Contains checks if the given error contains an error with the +// message msg. If err is not a wrapped error, this will always return +// false unless the error itself happens to match this msg. +func Contains(err error, msg string) bool { + return len(GetAll(err, msg)) > 0 +} + +// ContainsType checks if the given error contains an error with +// the same concrete type as v. If err is not a wrapped error, this will +// check the err itself. +func ContainsType(err error, v interface{}) bool { + return len(GetAllType(err, v)) > 0 +} + +// Get is the same as GetAll but returns the deepest matching error. +func Get(err error, msg string) error { + es := GetAll(err, msg) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetType is the same as GetAllType but returns the deepest matching error. +func GetType(err error, v interface{}) error { + es := GetAllType(err, v) + if len(es) > 0 { + return es[len(es)-1] + } + + return nil +} + +// GetAll gets all the errors that might be wrapped in err with the +// given message. The order of the errors is such that the outermost +// matching error (the most recent wrap) is index zero, and so on. +func GetAll(err error, msg string) []error { + var result []error + + Walk(err, func(err error) { + if err.Error() == msg { + result = append(result, err) + } + }) + + return result +} + +// GetAllType gets all the errors that are the same type as v. +// +// The order of the return value is the same as described in GetAll. +func GetAllType(err error, v interface{}) []error { + var result []error + + var search string + if v != nil { + search = reflect.TypeOf(v).String() + } + Walk(err, func(err error) { + var needle string + if err != nil { + needle = reflect.TypeOf(err).String() + } + + if needle == search { + result = append(result, err) + } + }) + + return result +} + +// Walk walks all the wrapped errors in err and calls the callback. If +// err isn't a wrapped error, this will be called once for err. If err +// is a wrapped error, the callback will be called for both the wrapper +// that implements error as well as the wrapped error itself. +func Walk(err error, cb WalkFunc) { + if err == nil { + return + } + + switch e := err.(type) { + case *wrappedError: + cb(e.Outer) + Walk(e.Inner, cb) + case Wrapper: + cb(err) + + for _, err := range e.WrappedErrors() { + Walk(err, cb) + } + default: + cb(err) + } +} + +// wrappedError is an implementation of error that has both the +// outer and inner errors. +type wrappedError struct { + Outer error + Inner error +} + +func (w *wrappedError) Error() string { + return w.Outer.Error() +} + +func (w *wrappedError) WrappedErrors() []error { + return []error{w.Outer, w.Inner} +} diff --git a/vendor/github.com/hashicorp/errwrap/go.mod b/vendor/github.com/hashicorp/errwrap/go.mod new file mode 100644 index 000000000000..c9b84022cf7a --- /dev/null +++ b/vendor/github.com/hashicorp/errwrap/go.mod @@ -0,0 +1 @@ +module github.com/hashicorp/errwrap diff --git a/vendor/github.com/hashicorp/go-multierror/LICENSE b/vendor/github.com/hashicorp/go-multierror/LICENSE new file mode 100644 index 000000000000..82b4de97c7e3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. “Contributor” + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. “Contributor Version” + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor’s Contribution. + +1.3. “Contribution” + + means Covered Software of a particular Contributor. + +1.4. “Covered Software” + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. “Incompatible With Secondary Licenses” + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of version + 1.1 or earlier of the License, but not also under the terms of a + Secondary License. + +1.6. “Executable Form” + + means any form of the work other than Source Code Form. + +1.7. “Larger Work” + + means a work that combines Covered Software with other material, in a separate + file or files, that is not Covered Software. + +1.8. “License” + + means this document. + +1.9. “Licensable” + + means having the right to grant, to the maximum extent possible, whether at the + time of the initial grant or subsequently, any and all of the rights conveyed by + this License. + +1.10. “Modifications” + + means any of the following: + + a. any file in Source Code Form that results from an addition to, deletion + from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. “Patent Claims” of a Contributor + + means any patent claim(s), including without limitation, method, process, + and apparatus claims, in any patent Licensable by such Contributor that + would be infringed, but for the grant of the License, by the making, + using, selling, offering for sale, having made, import, or transfer of + either its Contributions or its Contributor Version. + +1.12. “Secondary License” + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. “Source Code Form” + + means the form of the work preferred for making modifications. + +1.14. “You” (or “Your”) + + means an individual or a legal entity exercising rights under this + License. For legal entities, “You” includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, “control” means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or as + part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its Contributions + or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become + effective for each Contribution on the date the Contributor first distributes + such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this + License. No additional rights or licenses will be implied from the distribution + or licensing of Covered Software under this License. Notwithstanding Section + 2.1(b) above, no patent license is granted by a Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party’s + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of its + Contributions. + + This License does not grant any rights in the trademarks, service marks, or + logos of any Contributor (except as may be necessary to comply with the + notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this License + (see Section 10.2) or under the terms of a Secondary License (if permitted + under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions + are its original creation(s) or it has sufficient rights to grant the + rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under applicable + copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under the + terms of this License. You must inform recipients that the Source Code Form + of the Covered Software is governed by the terms of this License, and how + they can obtain a copy of this License. You may not attempt to alter or + restrict the recipients’ rights in the Source Code Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this License, + or sublicense it under different terms, provided that the license for + the Executable Form does not attempt to limit or alter the recipients’ + rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for the + Covered Software. If the Larger Work is a combination of Covered Software + with a work governed by one or more Secondary Licenses, and the Covered + Software is not Incompatible With Secondary Licenses, this License permits + You to additionally distribute such Covered Software under the terms of + such Secondary License(s), so that the recipient of the Larger Work may, at + their option, further distribute the Covered Software under the terms of + either this License or such Secondary License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices (including + copyright notices, patent notices, disclaimers of warranty, or limitations + of liability) contained within the Source Code Form of the Covered + Software, except that You may alter any license notices to the extent + required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on behalf + of any Contributor. You must make it absolutely clear that any such + warranty, support, indemnity, or liability obligation is offered by You + alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, judicial + order, or regulation then You must: (a) comply with the terms of this License + to the maximum extent possible; and (b) describe the limitations and the code + they affect. Such description must be placed in a text file included with all + distributions of the Covered Software under this License. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing basis, + if such Contributor fails to notify You of the non-compliance by some + reasonable means prior to 60 days after You have come back into compliance. + Moreover, Your grants from a particular Contributor are reinstated on an + ongoing basis if such Contributor notifies You of the non-compliance by + some reasonable means, this is the first time You have received notice of + non-compliance with this License from such Contributor, and You become + compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, counter-claims, + and cross-claims) alleging that a Contributor Version directly or + indirectly infringes any patent, then the rights granted to You by any and + all Contributors for the Covered Software under Section 2.1 of this License + shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an “as is” basis, without + warranty of any kind, either expressed, implied, or statutory, including, + without limitation, warranties that the Covered Software is free of defects, + merchantable, fit for a particular purpose or non-infringing. The entire + risk as to the quality and performance of the Covered Software is with You. + Should any Covered Software prove defective in any respect, You (not any + Contributor) assume the cost of any necessary servicing, repair, or + correction. This disclaimer of warranty constitutes an essential part of this + License. No use of any Covered Software is authorized under this License + except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from such + party’s negligence to the extent applicable law prohibits such limitation. + Some jurisdictions do not allow the exclusion or limitation of incidental or + consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts of + a jurisdiction where the defendant maintains its principal place of business + and such litigation shall be governed by laws of that jurisdiction, without + reference to its conflict-of-law provisions. Nothing in this Section shall + prevent a party’s ability to bring cross-claims or counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject matter + hereof. If any provision of this License is held to be unenforceable, such + provision shall be reformed only to the extent necessary to make it + enforceable. Any law or regulation which provides that the language of a + contract shall be construed against the drafter shall not be used to construe + this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of + the License under which You originally received the Covered Software, or + under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a modified + version of this License if you rename the license and remove any + references to the name of the license steward (except to note that such + modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then +You may include the notice in a location (such as a LICENSE file in a relevant +directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - “Incompatible With Secondary Licenses” Notice + + This Source Code Form is “Incompatible + With Secondary Licenses”, as defined by + the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-multierror/Makefile b/vendor/github.com/hashicorp/go-multierror/Makefile new file mode 100644 index 000000000000..b97cd6ed02b5 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/Makefile @@ -0,0 +1,31 @@ +TEST?=./... + +default: test + +# test runs the test suite and vets the code. +test: generate + @echo "==> Running tests..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} + +# testrace runs the race checker +testrace: generate + @echo "==> Running tests (race)..." + @go list $(TEST) \ + | grep -v "/vendor/" \ + | xargs -n1 go test -timeout=60s -race ${TESTARGS} + +# updatedeps installs all the dependencies needed to run and build. +updatedeps: + @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" + +# generate runs `go generate` to build the dynamically generated source files. +generate: + @echo "==> Generating..." + @find . -type f -name '.DS_Store' -delete + @go list ./... \ + | grep -v "/vendor/" \ + | xargs -n1 go generate + +.PHONY: default test testrace updatedeps generate diff --git a/vendor/github.com/hashicorp/go-multierror/README.md b/vendor/github.com/hashicorp/go-multierror/README.md new file mode 100644 index 000000000000..71dd308ed811 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/README.md @@ -0,0 +1,150 @@ +# go-multierror + +[![CircleCI](https://img.shields.io/circleci/build/github/hashicorp/go-multierror/master)](https://circleci.com/gh/hashicorp/go-multierror) +[![Go Reference](https://pkg.go.dev/badge/github.com/hashicorp/go-multierror.svg)](https://pkg.go.dev/github.com/hashicorp/go-multierror) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/hashicorp/go-multierror) + +[circleci]: https://app.circleci.com/pipelines/github/hashicorp/go-multierror +[godocs]: https://pkg.go.dev/github.com/hashicorp/go-multierror + +`go-multierror` is a package for Go that provides a mechanism for +representing a list of `error` values as a single `error`. + +This allows a function in Go to return an `error` that might actually +be a list of errors. If the caller knows this, they can unwrap the +list and access the errors. If the caller doesn't know, the error +formats to a nice human-readable format. + +`go-multierror` is fully compatible with the Go standard library +[errors](https://golang.org/pkg/errors/) package, including the +functions `As`, `Is`, and `Unwrap`. This provides a standardized approach +for introspecting on error values. + +## Installation and Docs + +Install using `go get github.com/hashicorp/go-multierror`. + +Full documentation is available at +https://pkg.go.dev/github.com/hashicorp/go-multierror + +### Requires go version 1.13 or newer + +`go-multierror` requires go version 1.13 or newer. Go 1.13 introduced +[error wrapping](https://golang.org/doc/go1.13#error_wrapping), which +this library takes advantage of. + +If you need to use an earlier version of go, you can use the +[v1.0.0](https://github.com/hashicorp/go-multierror/tree/v1.0.0) +tag, which doesn't rely on features in go 1.13. + +If you see compile errors that look like the below, it's likely that +you're on an older version of go: + +``` +/go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As +/go/src/github.com/hashicorp/go-multierror/multierror.go:117:9: undefined: errors.Is +``` + +## Usage + +go-multierror is easy to use and purposely built to be unobtrusive in +existing Go applications/libraries that may not be aware of it. + +**Building a list of errors** + +The `Append` function is used to create a list of errors. This function +behaves a lot like the Go built-in `append` function: it doesn't matter +if the first argument is nil, a `multierror.Error`, or any other `error`, +the function behaves as you would expect. + +```go +var result error + +if err := step1(); err != nil { + result = multierror.Append(result, err) +} +if err := step2(); err != nil { + result = multierror.Append(result, err) +} + +return result +``` + +**Customizing the formatting of the errors** + +By specifying a custom `ErrorFormat`, you can customize the format +of the `Error() string` function: + +```go +var result *multierror.Error + +// ... accumulate errors here, maybe using Append + +if result != nil { + result.ErrorFormat = func([]error) string { + return "errors!" + } +} +``` + +**Accessing the list of errors** + +`multierror.Error` implements `error` so if the caller doesn't know about +multierror, it will work just fine. But if you're aware a multierror might +be returned, you can use type switches to access the list of errors: + +```go +if err := something(); err != nil { + if merr, ok := err.(*multierror.Error); ok { + // Use merr.Errors + } +} +``` + +You can also use the standard [`errors.Unwrap`](https://golang.org/pkg/errors/#Unwrap) +function. This will continue to unwrap into subsequent errors until none exist. + +**Extracting an error** + +The standard library [`errors.As`](https://golang.org/pkg/errors/#As) +function can be used directly with a multierror to extract a specific error: + +```go +// Assume err is a multierror value +err := somefunc() + +// We want to know if "err" has a "RichErrorType" in it and extract it. +var errRich RichErrorType +if errors.As(err, &errRich) { + // It has it, and now errRich is populated. +} +``` + +**Checking for an exact error value** + +Some errors are returned as exact errors such as the [`ErrNotExist`](https://golang.org/pkg/os/#pkg-variables) +error in the `os` package. You can check if this error is present by using +the standard [`errors.Is`](https://golang.org/pkg/errors/#Is) function. + +```go +// Assume err is a multierror value +err := somefunc() +if errors.Is(err, os.ErrNotExist) { + // err contains os.ErrNotExist +} +``` + +**Returning a multierror only if there are errors** + +If you build a `multierror.Error`, you can use the `ErrorOrNil` function +to return an `error` implementation only if there are errors to return: + +```go +var result *multierror.Error + +// ... accumulate errors here + +// Return the `error` only if errors were added to the multierror, otherwise +// return nil since there are no errors. +return result.ErrorOrNil() +``` diff --git a/vendor/github.com/hashicorp/go-multierror/append.go b/vendor/github.com/hashicorp/go-multierror/append.go new file mode 100644 index 000000000000..3e2589bfde0c --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/append.go @@ -0,0 +1,43 @@ +package multierror + +// Append is a helper function that will append more errors +// onto an Error in order to create a larger multi-error. +// +// If err is not a multierror.Error, then it will be turned into +// one. If any of the errs are multierr.Error, they will be flattened +// one level into err. +// Any nil errors within errs will be ignored. If err is nil, a new +// *Error will be returned. +func Append(err error, errs ...error) *Error { + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Go through each error and flatten + for _, e := range errs { + switch e := e.(type) { + case *Error: + if e != nil { + err.Errors = append(err.Errors, e.Errors...) + } + default: + if e != nil { + err.Errors = append(err.Errors, e) + } + } + } + + return err + default: + newErrs := make([]error, 0, len(errs)+1) + if err != nil { + newErrs = append(newErrs, err) + } + newErrs = append(newErrs, errs...) + + return Append(&Error{}, newErrs...) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/flatten.go b/vendor/github.com/hashicorp/go-multierror/flatten.go new file mode 100644 index 000000000000..aab8e9abec9d --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/flatten.go @@ -0,0 +1,26 @@ +package multierror + +// Flatten flattens the given error, merging any *Errors together into +// a single *Error. +func Flatten(err error) error { + // If it isn't an *Error, just return the error as-is + if _, ok := err.(*Error); !ok { + return err + } + + // Otherwise, make the result and flatten away! + flatErr := new(Error) + flatten(err, flatErr) + return flatErr +} + +func flatten(err error, flatErr *Error) { + switch err := err.(type) { + case *Error: + for _, e := range err.Errors { + flatten(e, flatErr) + } + default: + flatErr.Errors = append(flatErr.Errors, err) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/format.go b/vendor/github.com/hashicorp/go-multierror/format.go new file mode 100644 index 000000000000..47f13c49a673 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/format.go @@ -0,0 +1,27 @@ +package multierror + +import ( + "fmt" + "strings" +) + +// ErrorFormatFunc is a function callback that is called by Error to +// turn the list of errors into a string. +type ErrorFormatFunc func([]error) string + +// ListFormatFunc is a basic formatter that outputs the number of errors +// that occurred along with a bullet point list of the errors. +func ListFormatFunc(es []error) string { + if len(es) == 1 { + return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0]) + } + + points := make([]string, len(es)) + for i, err := range es { + points[i] = fmt.Sprintf("* %s", err) + } + + return fmt.Sprintf( + "%d errors occurred:\n\t%s\n\n", + len(es), strings.Join(points, "\n\t")) +} diff --git a/vendor/github.com/hashicorp/go-multierror/go.mod b/vendor/github.com/hashicorp/go-multierror/go.mod new file mode 100644 index 000000000000..141cc4ccb25c --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/go.mod @@ -0,0 +1,5 @@ +module github.com/hashicorp/go-multierror + +go 1.13 + +require github.com/hashicorp/errwrap v1.0.0 diff --git a/vendor/github.com/hashicorp/go-multierror/go.sum b/vendor/github.com/hashicorp/go-multierror/go.sum new file mode 100644 index 000000000000..e8238e9ec91e --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/go.sum @@ -0,0 +1,2 @@ +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/vendor/github.com/hashicorp/go-multierror/group.go b/vendor/github.com/hashicorp/go-multierror/group.go new file mode 100644 index 000000000000..9c29efb7f87e --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/group.go @@ -0,0 +1,38 @@ +package multierror + +import "sync" + +// Group is a collection of goroutines which return errors that need to be +// coalesced. +type Group struct { + mutex sync.Mutex + err *Error + wg sync.WaitGroup +} + +// Go calls the given function in a new goroutine. +// +// If the function returns an error it is added to the group multierror which +// is returned by Wait. +func (g *Group) Go(f func() error) { + g.wg.Add(1) + + go func() { + defer g.wg.Done() + + if err := f(); err != nil { + g.mutex.Lock() + g.err = Append(g.err, err) + g.mutex.Unlock() + } + }() +} + +// Wait blocks until all function calls from the Go method have returned, then +// returns the multierror. +func (g *Group) Wait() *Error { + g.wg.Wait() + g.mutex.Lock() + defer g.mutex.Unlock() + return g.err +} diff --git a/vendor/github.com/hashicorp/go-multierror/multierror.go b/vendor/github.com/hashicorp/go-multierror/multierror.go new file mode 100644 index 000000000000..f54574326461 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/multierror.go @@ -0,0 +1,121 @@ +package multierror + +import ( + "errors" + "fmt" +) + +// Error is an error type to track multiple errors. This is used to +// accumulate errors in cases and return them as a single "error". +type Error struct { + Errors []error + ErrorFormat ErrorFormatFunc +} + +func (e *Error) Error() string { + fn := e.ErrorFormat + if fn == nil { + fn = ListFormatFunc + } + + return fn(e.Errors) +} + +// ErrorOrNil returns an error interface if this Error represents +// a list of errors, or returns nil if the list of errors is empty. This +// function is useful at the end of accumulation to make sure that the value +// returned represents the existence of errors. +func (e *Error) ErrorOrNil() error { + if e == nil { + return nil + } + if len(e.Errors) == 0 { + return nil + } + + return e +} + +func (e *Error) GoString() string { + return fmt.Sprintf("*%#v", *e) +} + +// WrappedErrors returns the list of errors that this Error is wrapping. It is +// an implementation of the errwrap.Wrapper interface so that multierror.Error +// can be used with that library. +// +// This method is not safe to be called concurrently. Unlike accessing the +// Errors field directly, this function also checks if the multierror is nil to +// prevent a null-pointer panic. It satisfies the errwrap.Wrapper interface. +func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } + return e.Errors +} + +// Unwrap returns an error from Error (or nil if there are no errors). +// This error returned will further support Unwrap to get the next error, +// etc. The order will match the order of Errors in the multierror.Error +// at the time of calling. +// +// The resulting error supports errors.As/Is/Unwrap so you can continue +// to use the stdlib errors package to introspect further. +// +// This will perform a shallow copy of the errors slice. Any errors appended +// to this error after calling Unwrap will not be available until a new +// Unwrap is called on the multierror.Error. +func (e *Error) Unwrap() error { + // If we have no errors then we do nothing + if e == nil || len(e.Errors) == 0 { + return nil + } + + // If we have exactly one error, we can just return that directly. + if len(e.Errors) == 1 { + return e.Errors[0] + } + + // Shallow copy the slice + errs := make([]error, len(e.Errors)) + copy(errs, e.Errors) + return chain(errs) +} + +// chain implements the interfaces necessary for errors.Is/As/Unwrap to +// work in a deterministic way with multierror. A chain tracks a list of +// errors while accounting for the current represented error. This lets +// Is/As be meaningful. +// +// Unwrap returns the next error. In the cleanest form, Unwrap would return +// the wrapped error here but we can't do that if we want to properly +// get access to all the errors. Instead, users are recommended to use +// Is/As to get the correct error type out. +// +// Precondition: []error is non-empty (len > 0) +type chain []error + +// Error implements the error interface +func (e chain) Error() string { + return e[0].Error() +} + +// Unwrap implements errors.Unwrap by returning the next error in the +// chain or nil if there are no more errors. +func (e chain) Unwrap() error { + if len(e) == 1 { + return nil + } + + return e[1:] +} + +// As implements errors.As by attempting to map to the current value. +func (e chain) As(target interface{}) bool { + return errors.As(e[0], target) +} + +// Is implements errors.Is by comparing the current value directly. +func (e chain) Is(target error) bool { + return errors.Is(e[0], target) +} diff --git a/vendor/github.com/hashicorp/go-multierror/prefix.go b/vendor/github.com/hashicorp/go-multierror/prefix.go new file mode 100644 index 000000000000..5c477abe44f8 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/prefix.go @@ -0,0 +1,37 @@ +package multierror + +import ( + "fmt" + + "github.com/hashicorp/errwrap" +) + +// Prefix is a helper function that will prefix some text +// to the given error. If the error is a multierror.Error, then +// it will be prefixed to each wrapped error. +// +// This is useful to use when appending multiple multierrors +// together in order to give better scoping. +func Prefix(err error, prefix string) error { + if err == nil { + return nil + } + + format := fmt.Sprintf("%s {{err}}", prefix) + switch err := err.(type) { + case *Error: + // Typed nils can reach here, so initialize if we are nil + if err == nil { + err = new(Error) + } + + // Wrap each of the errors + for i, e := range err.Errors { + err.Errors[i] = errwrap.Wrapf(format, e) + } + + return err + default: + return errwrap.Wrapf(format, err) + } +} diff --git a/vendor/github.com/hashicorp/go-multierror/sort.go b/vendor/github.com/hashicorp/go-multierror/sort.go new file mode 100644 index 000000000000..fecb14e81c54 --- /dev/null +++ b/vendor/github.com/hashicorp/go-multierror/sort.go @@ -0,0 +1,16 @@ +package multierror + +// Len implements sort.Interface function for length +func (err Error) Len() int { + return len(err.Errors) +} + +// Swap implements sort.Interface function for swapping elements +func (err Error) Swap(i, j int) { + err.Errors[i], err.Errors[j] = err.Errors[j], err.Errors[i] +} + +// Less implements sort.Interface function for determining order +func (err Error) Less(i, j int) bool { + return err.Errors[i].Error() < err.Errors[j].Error() +} diff --git a/vendor/github.com/klauspost/compress/fse/compress.go b/vendor/github.com/klauspost/compress/fse/compress.go index 0d31f5ebc9ad..6f341914c67f 100644 --- a/vendor/github.com/klauspost/compress/fse/compress.go +++ b/vendor/github.com/klauspost/compress/fse/compress.go @@ -92,7 +92,6 @@ func (c *cState) init(bw *bitWriter, ct *cTable, tableLog uint8, first symbolTra im := int32((nbBitsOut << 16) - first.deltaNbBits) lu := (im >> nbBitsOut) + first.deltaFindState c.state = c.stateTable[lu] - return } // encode the output symbol provided and write it to the bitstream. diff --git a/vendor/github.com/klauspost/compress/huff0/compress.go b/vendor/github.com/klauspost/compress/huff0/compress.go index dea115b33413..0823c928cec8 100644 --- a/vendor/github.com/klauspost/compress/huff0/compress.go +++ b/vendor/github.com/klauspost/compress/huff0/compress.go @@ -536,7 +536,6 @@ func (s *Scratch) huffSort() { } nodes[pos&huffNodesMask] = nodeElt{count: c, symbol: byte(n)} } - return } func (s *Scratch) setMaxHeight(lastNonNull int) uint8 { diff --git a/vendor/github.com/klauspost/compress/snappy/runbench.cmd b/vendor/github.com/klauspost/compress/snappy/runbench.cmd deleted file mode 100644 index d24eb4b47c37..000000000000 --- a/vendor/github.com/klauspost/compress/snappy/runbench.cmd +++ /dev/null @@ -1,2 +0,0 @@ -del old.txt -go test -bench=. >>old.txt && go test -bench=. >>old.txt && go test -bench=. >>old.txt && benchstat -delta-test=ttest old.txt new.txt diff --git a/vendor/github.com/klauspost/compress/zstd/README.md b/vendor/github.com/klauspost/compress/zstd/README.md index 7680bfe1dd6c..787813fa9e2a 100644 --- a/vendor/github.com/klauspost/compress/zstd/README.md +++ b/vendor/github.com/klauspost/compress/zstd/README.md @@ -16,8 +16,7 @@ Currently the package is heavily optimized for 64 bit processors and will be sig Install using `go get -u github.com/klauspost/compress`. The package is located in `github.com/klauspost/compress/zstd`. -Godoc Documentation: https://godoc.org/github.com/klauspost/compress/zstd - +[![Go Reference](https://pkg.go.dev/badge/github.com/klauspost/compress/zstd.svg)](https://pkg.go.dev/github.com/klauspost/compress/zstd) ## Compressor @@ -152,8 +151,8 @@ This package: file out level insize outsize millis mb/s silesia.tar zskp 1 211947520 73101992 643 313.87 silesia.tar zskp 2 211947520 67504318 969 208.38 -silesia.tar zskp 3 211947520 65177448 1899 106.44 -silesia.tar zskp 4 211947520 61381950 8115 24.91 +silesia.tar zskp 3 211947520 64595893 2007 100.68 +silesia.tar zskp 4 211947520 60995370 7691 26.28 cgo zstd: silesia.tar zstd 1 211947520 73605392 543 371.56 @@ -171,8 +170,8 @@ https://files.klauspost.com/compress/gob-stream.7z file out level insize outsize millis mb/s gob-stream zskp 1 1911399616 235022249 3088 590.30 gob-stream zskp 2 1911399616 205669791 3786 481.34 -gob-stream zskp 3 1911399616 185792019 9324 195.48 -gob-stream zskp 4 1911399616 171537212 32113 56.76 +gob-stream zskp 3 1911399616 175034659 9636 189.17 +gob-stream zskp 4 1911399616 167273881 29337 62.13 gob-stream zstd 1 1911399616 249810424 2637 691.26 gob-stream zstd 3 1911399616 208192146 3490 522.31 gob-stream zstd 6 1911399616 193632038 6687 272.56 @@ -187,8 +186,8 @@ http://mattmahoney.net/dc/textdata.html file out level insize outsize millis mb/s enwik9 zskp 1 1000000000 343848582 3609 264.18 enwik9 zskp 2 1000000000 317276632 5746 165.97 -enwik9 zskp 3 1000000000 294540704 11725 81.34 -enwik9 zskp 4 1000000000 276609671 44029 21.66 +enwik9 zskp 3 1000000000 292243069 12162 78.41 +enwik9 zskp 4 1000000000 275241169 36430 26.18 enwik9 zstd 1 1000000000 358072021 3110 306.65 enwik9 zstd 3 1000000000 313734672 4784 199.35 enwik9 zstd 6 1000000000 295138875 10290 92.68 @@ -202,8 +201,8 @@ https://files.klauspost.com/compress/github-june-2days-2019.json.zst file out level insize outsize millis mb/s github-june-2days-2019.json zskp 1 6273951764 699045015 10620 563.40 github-june-2days-2019.json zskp 2 6273951764 617881763 11687 511.96 -github-june-2days-2019.json zskp 3 6273951764 537511906 29252 204.54 -github-june-2days-2019.json zskp 4 6273951764 512796117 97791 61.18 +github-june-2days-2019.json zskp 3 6273951764 524340691 34043 175.75 +github-june-2days-2019.json zskp 4 6273951764 503314661 93811 63.78 github-june-2days-2019.json zstd 1 6273951764 766284037 8450 708.00 github-june-2days-2019.json zstd 3 6273951764 661889476 10927 547.57 github-june-2days-2019.json zstd 6 6273951764 642756859 22996 260.18 @@ -217,8 +216,8 @@ https://files.klauspost.com/compress/rawstudio-mint14.7z file out level insize outsize millis mb/s rawstudio-mint14.tar zskp 1 8558382592 3667489370 20210 403.84 rawstudio-mint14.tar zskp 2 8558382592 3364592300 31873 256.07 -rawstudio-mint14.tar zskp 3 8558382592 3224594213 71751 113.75 -rawstudio-mint14.tar zskp 4 8558382592 3027332295 486243 16.79 +rawstudio-mint14.tar zskp 3 8558382592 3158085214 77675 105.08 +rawstudio-mint14.tar zskp 4 8558382592 3020370044 404956 20.16 rawstudio-mint14.tar zstd 1 8558382592 3609250104 17136 476.27 rawstudio-mint14.tar zstd 3 8558382592 3341679997 29262 278.92 rawstudio-mint14.tar zstd 6 8558382592 3235846406 77904 104.77 @@ -232,8 +231,8 @@ https://files.klauspost.com/compress/nyc-taxi-data-10M.csv.zst file out level insize outsize millis mb/s nyc-taxi-data-10M.csv zskp 1 3325605752 641339945 8925 355.35 nyc-taxi-data-10M.csv zskp 2 3325605752 591748091 11268 281.44 -nyc-taxi-data-10M.csv zskp 3 3325605752 538490114 19880 159.53 -nyc-taxi-data-10M.csv zskp 4 3325605752 495986829 89368 35.49 +nyc-taxi-data-10M.csv zskp 3 3325605752 530289687 25239 125.66 +nyc-taxi-data-10M.csv zskp 4 3325605752 490907191 65939 48.10 nyc-taxi-data-10M.csv zstd 1 3325605752 687399637 8233 385.18 nyc-taxi-data-10M.csv zstd 3 3325605752 598514411 10065 315.07 nyc-taxi-data-10M.csv zstd 6 3325605752 570522953 20038 158.27 @@ -405,13 +404,28 @@ BenchmarkDecoder_DecodeAllParallelCgo/comp-data.bin.zst-16 749938 This reflects the performance around May 2020, but this may be out of date. +## Zstd inside ZIP files + +It is possible to use zstandard to compress individual files inside zip archives. +While this isn't widely supported it can be useful for internal files. + +To support the compression and decompression of these files you must register a compressor and decompressor. + +It is highly recommended registering the (de)compressors on individual zip Reader/Writer and NOT +use the global registration functions. The main reason for this is that 2 registrations from +different packages will result in a panic. + +It is a good idea to only have a single compressor and decompressor, since they can be used for multiple zip +files concurrently, and using a single instance will allow reusing some resources. + +See [this example](https://pkg.go.dev/github.com/klauspost/compress/zstd#example-ZipCompressor) for +how to compress and decompress files inside zip archives. + # Contributions Contributions are always welcome. For new features/fixes, remember to add tests and for performance enhancements include benchmarks. -For sending files for reproducing errors use a service like [goobox](https://goobox.io/#/upload) or similar to share your files. - For general feedback and experience reports, feel free to open an issue or write me on [Twitter](https://twitter.com/sh0dan). This package includes the excellent [`github.com/cespare/xxhash`](https://github.com/cespare/xxhash) package Copyright (c) 2016 Caleb Spare. diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go index b51d922bda69..6cea054d2dfd 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -123,12 +123,10 @@ func newBlockDec(lowMem bool) *blockDec { // Input must be a start of a block and will be at the end of the block when returned. func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { b.WindowSize = windowSize - tmp := br.readSmall(3) - if tmp == nil { - if debug { - println("Reading block header:", io.ErrUnexpectedEOF) - } - return io.ErrUnexpectedEOF + tmp, err := br.readSmall(3) + if err != nil { + println("Reading block header:", err) + return err } bh := uint32(tmp[0]) | (uint32(tmp[1]) << 8) | (uint32(tmp[2]) << 16) b.Last = bh&1 != 0 @@ -179,7 +177,6 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { if cap(b.dst) <= maxSize { b.dst = make([]byte, 0, maxSize+1) } - var err error b.data, err = br.readBig(cSize, b.dataStorage) if err != nil { if debug { diff --git a/vendor/github.com/klauspost/compress/zstd/blockenc.go b/vendor/github.com/klauspost/compress/zstd/blockenc.go index 9647c64e53a0..e1be092f3267 100644 --- a/vendor/github.com/klauspost/compress/zstd/blockenc.go +++ b/vendor/github.com/klauspost/compress/zstd/blockenc.go @@ -386,9 +386,9 @@ func (b *blockEnc) encodeLits(lits []byte, raw bool) error { b.output = bh.appendTo(b.output) b.output = append(b.output, lits[0]) return nil + case nil: default: return err - case nil: } // Compressed... // Now, allow reuse @@ -528,11 +528,6 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { if debug { println("Adding literals RLE") } - default: - if debug { - println("Adding literals ERROR:", err) - } - return err case nil: // Compressed litLen... if reUsed { @@ -563,6 +558,11 @@ func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { if debug { println("Adding literals compressed") } + default: + if debug { + println("Adding literals ERROR:", err) + } + return err } // Sequence compression diff --git a/vendor/github.com/klauspost/compress/zstd/bytebuf.go b/vendor/github.com/klauspost/compress/zstd/bytebuf.go index 658ef78380e1..17e820a6a6d9 100644 --- a/vendor/github.com/klauspost/compress/zstd/bytebuf.go +++ b/vendor/github.com/klauspost/compress/zstd/bytebuf.go @@ -12,8 +12,8 @@ import ( type byteBuffer interface { // Read up to 8 bytes. - // Returns nil if no more input is available. - readSmall(n int) []byte + // Returns io.ErrUnexpectedEOF if this cannot be satisfied. + readSmall(n int) ([]byte, error) // Read >8 bytes. // MAY use the destination slice. @@ -29,17 +29,17 @@ type byteBuffer interface { // in-memory buffer type byteBuf []byte -func (b *byteBuf) readSmall(n int) []byte { +func (b *byteBuf) readSmall(n int) ([]byte, error) { if debugAsserts && n > 8 { panic(fmt.Errorf("small read > 8 (%d). use readBig", n)) } bb := *b if len(bb) < n { - return nil + return nil, io.ErrUnexpectedEOF } r := bb[:n] *b = bb[n:] - return r + return r, nil } func (b *byteBuf) readBig(n int, dst []byte) ([]byte, error) { @@ -81,19 +81,22 @@ type readerWrapper struct { tmp [8]byte } -func (r *readerWrapper) readSmall(n int) []byte { +func (r *readerWrapper) readSmall(n int) ([]byte, error) { if debugAsserts && n > 8 { panic(fmt.Errorf("small read > 8 (%d). use readBig", n)) } n2, err := io.ReadFull(r.r, r.tmp[:n]) // We only really care about the actual bytes read. - if n2 != n { + if err != nil { + if err == io.EOF { + return nil, io.ErrUnexpectedEOF + } if debug { println("readSmall: got", n2, "want", n, "err", err) } - return nil + return nil, err } - return r.tmp[:n] + return r.tmp[:n], nil } func (r *readerWrapper) readBig(n int, dst []byte) ([]byte, error) { diff --git a/vendor/github.com/klauspost/compress/zstd/decodeheader.go b/vendor/github.com/klauspost/compress/zstd/decodeheader.go index 87896c5eaa78..69736e8d4bb8 100644 --- a/vendor/github.com/klauspost/compress/zstd/decodeheader.go +++ b/vendor/github.com/klauspost/compress/zstd/decodeheader.go @@ -93,7 +93,7 @@ func (h *Header) Decode(in []byte) error { h.HasCheckSum = fhd&(1<<2) != 0 if fhd&(1<<3) != 0 { - return errors.New("Reserved bit set on frame header") + return errors.New("reserved bit set on frame header") } // Read Window_Descriptor @@ -174,7 +174,7 @@ func (h *Header) Decode(in []byte) error { if len(in) < 3 { return nil } - tmp, in := in[:3], in[3:] + tmp := in[:3] bh := uint32(tmp[0]) | (uint32(tmp[1]) << 8) | (uint32(tmp[2]) << 16) h.FirstBlock.Last = bh&1 != 0 blockType := blockType((bh >> 1) & 3) diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go index 1d41c25d2926..f593e464b66c 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -179,8 +179,7 @@ func (d *Decoder) Reset(r io.Reader) error { // If bytes buffer and < 1MB, do sync decoding anyway. if bb, ok := r.(byter); ok && bb.Len() < 1<<20 { - var bb2 byter - bb2 = bb + bb2 := bb if debug { println("*bytes.Buffer detected, doing sync decode, len:", bb.Len()) } @@ -237,20 +236,17 @@ func (d *Decoder) drainOutput() { println("current already flushed") return } - for { - select { - case v := <-d.current.output: - if v.d != nil { - if debug { - printf("re-adding decoder %p", v.d) - } - d.decoders <- v.d - } - if v.err == errEndOfStream { - println("current flushed") - d.current.flushed = true - return + for v := range d.current.output { + if v.d != nil { + if debug { + printf("re-adding decoder %p", v.d) } + d.decoders <- v.d + } + if v.err == errEndOfStream { + println("current flushed") + d.current.flushed = true + return } } } diff --git a/vendor/github.com/klauspost/compress/zstd/decoder_options.go b/vendor/github.com/klauspost/compress/zstd/decoder_options.go index 284d384492b1..c0fd058c28f5 100644 --- a/vendor/github.com/klauspost/compress/zstd/decoder_options.go +++ b/vendor/github.com/klauspost/compress/zstd/decoder_options.go @@ -6,7 +6,6 @@ package zstd import ( "errors" - "fmt" "runtime" ) @@ -43,7 +42,7 @@ func WithDecoderLowmem(b bool) DOption { func WithDecoderConcurrency(n int) DOption { return func(o *decoderOptions) error { if n <= 0 { - return fmt.Errorf("Concurrency must be at least 1") + return errors.New("concurrency must be at least 1") } o.concurrent = n return nil @@ -61,7 +60,7 @@ func WithDecoderMaxMemory(n uint64) DOption { return errors.New("WithDecoderMaxMemory must be at least 1") } if n > 1<<63 { - return fmt.Errorf("WithDecoderMaxmemory must be less than 1 << 63") + return errors.New("WithDecoderMaxmemory must be less than 1 << 63") } o.maxDecodedSize = n return nil diff --git a/vendor/github.com/klauspost/compress/zstd/enc_base.go b/vendor/github.com/klauspost/compress/zstd/enc_base.go index 2d4d893eb916..60f298648644 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_base.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_base.go @@ -150,14 +150,15 @@ func (e *fastBase) resetBase(d *dict, singleBlock bool) { } else { e.crc.Reset() } - if (!singleBlock || d.DictContentSize() > 0) && cap(e.hist) < int(e.maxMatchOff*2)+d.DictContentSize() { - l := e.maxMatchOff*2 + int32(d.DictContentSize()) - // Make it at least 1MB. - if l < 1<<20 { - l = 1 << 20 + if d != nil { + low := e.lowMem + if singleBlock { + e.lowMem = true } - e.hist = make([]byte, 0, l) + e.ensureHist(d.DictContentSize() + maxCompressedBlockSize) + e.lowMem = low } + // We offset current position so everything will be out of reach. // If above reset line, history will be purged. if e.cur < bufferReset { diff --git a/vendor/github.com/klauspost/compress/zstd/enc_best.go b/vendor/github.com/klauspost/compress/zstd/enc_best.go index fe3625c5f5e6..dc1eed5f00a0 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_best.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_best.go @@ -220,6 +220,20 @@ encodeLoop: best = bestOf(best, matchAt(candidateL.prev-e.cur, s, uint32(cv), -1)) best = bestOf(best, matchAt(candidateL2.offset-e.cur, s+1, uint32(cv2), -1)) best = bestOf(best, matchAt(candidateL2.prev-e.cur, s+1, uint32(cv2), -1)) + + // See if we can find a better match by checking where the current best ends. + // Use that offset to see if we can find a better full match. + if sAt := best.s + best.length; sAt < sLimit { + nextHashL := hash8(load6432(src, sAt), bestLongTableBits) + candidateEnd := e.longTable[nextHashL] + if pos := candidateEnd.offset - e.cur - best.length; pos >= 0 { + bestEnd := bestOf(best, matchAt(pos, best.s, load3232(src, best.s), -1)) + if pos := candidateEnd.prev - e.cur - best.length; pos >= 0 { + bestEnd = bestOf(bestEnd, matchAt(pos, best.s, load3232(src, best.s), -1)) + } + best = bestEnd + } + } } // We have a match, we can store the forward value diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go index c2ce4a2bac50..604954290e4b 100644 --- a/vendor/github.com/klauspost/compress/zstd/enc_better.go +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -412,8 +412,41 @@ encodeLoop: cv = load6432(src, s) } - // A 4-byte match has been found. Update recent offsets. - // We'll later see if more than 4 bytes. + // Try to find a better match by searching for a long match at the end of the current best match + if true && s+matched < sLimit { + nextHashL := hash8(load6432(src, s+matched), betterLongTableBits) + cv := load3232(src, s) + candidateL := e.longTable[nextHashL] + coffsetL := candidateL.offset - e.cur - matched + if coffsetL >= 0 && coffsetL < s && s-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + matched = matchedNext + if debugMatches { + println("long match at end-of-match") + } + } + } + + // Check prev long... + if true { + coffsetL = candidateL.prev - e.cur - matched + if coffsetL >= 0 && coffsetL < s && s-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + matched = matchedNext + if debugMatches { + println("prev long match at end-of-match") + } + } + } + } + } + // A match has been found. Update recent offsets. offset2 = offset1 offset1 = s - t @@ -905,9 +938,41 @@ encodeLoop: } cv = load6432(src, s) } + // Try to find a better match by searching for a long match at the end of the current best match + if s+matched < sLimit { + nextHashL := hash8(load6432(src, s+matched), betterLongTableBits) + cv := load3232(src, s) + candidateL := e.longTable[nextHashL] + coffsetL := candidateL.offset - e.cur - matched + if coffsetL >= 0 && coffsetL < s && s-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + matched = matchedNext + if debugMatches { + println("long match at end-of-match") + } + } + } - // A 4-byte match has been found. Update recent offsets. - // We'll later see if more than 4 bytes. + // Check prev long... + if true { + coffsetL = candidateL.prev - e.cur - matched + if coffsetL >= 0 && coffsetL < s && s-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + matched = matchedNext + if debugMatches { + println("prev long match at end-of-match") + } + } + } + } + } + // A match has been found. Update recent offsets. offset2 = offset1 offset1 = s - t diff --git a/vendor/github.com/klauspost/compress/zstd/encoder.go b/vendor/github.com/klauspost/compress/zstd/encoder.go index 6f0265099ecd..4871dd03affc 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder.go @@ -340,13 +340,13 @@ func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { println("ReadFrom: got EOF final block:", len(e.state.filling)) } return n, nil + case nil: default: if debug { println("ReadFrom: got error:", err) } e.state.err = err return n, err - case nil: } if len(src) > 0 { if debug { diff --git a/vendor/github.com/klauspost/compress/zstd/encoder_options.go b/vendor/github.com/klauspost/compress/zstd/encoder_options.go index 18a47eb03e88..16d4ab63c19d 100644 --- a/vendor/github.com/klauspost/compress/zstd/encoder_options.go +++ b/vendor/github.com/klauspost/compress/zstd/encoder_options.go @@ -73,7 +73,7 @@ func WithEncoderCRC(b bool) EOption { } // WithEncoderConcurrency will set the concurrency, -// meaning the maximum number of decoders to run concurrently. +// meaning the maximum number of encoders to run concurrently. // The value supplied must be at least 1. // By default this will be set to GOMAXPROCS. func WithEncoderConcurrency(n int) EOption { diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go index fc4a566d39aa..4dc151213997 100644 --- a/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -80,9 +80,14 @@ func (d *frameDec) reset(br byteBuffer) error { d.WindowSize = 0 var b []byte for { - b = br.readSmall(4) - if b == nil { + var err error + b, err = br.readSmall(4) + switch err { + case io.EOF, io.ErrUnexpectedEOF: return io.EOF + default: + return err + case nil: } if !bytes.Equal(b[1:4], skippableFrameMagic) || b[0]&0xf0 != 0x50 { if debug { @@ -92,14 +97,14 @@ func (d *frameDec) reset(br byteBuffer) error { break } // Read size to skip - b = br.readSmall(4) - if b == nil { - println("Reading Frame Size EOF") - return io.ErrUnexpectedEOF + b, err = br.readSmall(4) + if err != nil { + println("Reading Frame Size", err) + return err } n := uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) println("Skipping frame with", n, "bytes.") - err := br.skipN(int(n)) + err = br.skipN(int(n)) if err != nil { if debug { println("Reading discarded frame", err) @@ -121,7 +126,7 @@ func (d *frameDec) reset(br byteBuffer) error { d.SingleSegment = fhd&(1<<5) != 0 if fhd&(1<<3) != 0 { - return errors.New("Reserved bit set on frame header") + return errors.New("reserved bit set on frame header") } // Read Window_Descriptor @@ -147,12 +152,11 @@ func (d *frameDec) reset(br byteBuffer) error { if size == 3 { size = 4 } - b = br.readSmall(int(size)) - if b == nil { - if debug { - println("Reading Dictionary_ID", io.ErrUnexpectedEOF) - } - return io.ErrUnexpectedEOF + + b, err = br.readSmall(int(size)) + if err != nil { + println("Reading Dictionary_ID", err) + return err } var id uint32 switch size { @@ -187,10 +191,10 @@ func (d *frameDec) reset(br byteBuffer) error { } d.FrameContentSize = 0 if fcsSize > 0 { - b := br.readSmall(fcsSize) - if b == nil { - println("Reading Frame content", io.ErrUnexpectedEOF) - return io.ErrUnexpectedEOF + b, err = br.readSmall(fcsSize) + if err != nil { + println("Reading Frame content", err) + return err } switch fcsSize { case 1: @@ -307,10 +311,10 @@ func (d *frameDec) checkCRC() error { tmp[3] = byte(got >> 24) // We can overwrite upper tmp now - want := d.rawInput.readSmall(4) - if want == nil { - println("CRC missing?") - return io.ErrUnexpectedEOF + want, err := d.rawInput.readSmall(4) + if err != nil { + println("CRC missing?", err) + return err } if !bytes.Equal(tmp[:], want) { diff --git a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go index b80709d5ea8d..c74681b99984 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go +++ b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go @@ -708,7 +708,6 @@ func (c *cState) init(bw *bitWriter, ct *cTable, first symbolTransform) { im := int32((nbBitsOut << 16) - first.deltaNbBits) lu := (im >> nbBitsOut) + int32(first.deltaFindState) c.state = c.stateTable[lu] - return } // encode the output symbol provided and write it to the bitstream. diff --git a/vendor/github.com/klauspost/compress/zstd/fse_predefined.go b/vendor/github.com/klauspost/compress/zstd/fse_predefined.go index 6c17dc17f4fd..474cb77d2b99 100644 --- a/vendor/github.com/klauspost/compress/zstd/fse_predefined.go +++ b/vendor/github.com/klauspost/compress/zstd/fse_predefined.go @@ -59,7 +59,7 @@ func fillBase(dst []baseOffset, base uint32, bits ...uint8) { } for i, bit := range bits { if base > math.MaxInt32 { - panic(fmt.Sprintf("invalid decoding table, base overflows int32")) + panic("invalid decoding table, base overflows int32") } dst[i] = baseOffset{ diff --git a/vendor/github.com/klauspost/compress/zstd/seqenc.go b/vendor/github.com/klauspost/compress/zstd/seqenc.go index 36bcc3cc02eb..8014174a7713 100644 --- a/vendor/github.com/klauspost/compress/zstd/seqenc.go +++ b/vendor/github.com/klauspost/compress/zstd/seqenc.go @@ -35,7 +35,6 @@ func (s *seqCoders) setPrev(ll, ml, of *fseEncoder) { // Ensure we cannot reuse by accident prevEnc := *prev prevEnc.symbolLen = 0 - return } compareSwap(ll, &s.llEnc, &s.llPrev) compareSwap(ml, &s.mlEnc, &s.mlPrev) diff --git a/vendor/github.com/klauspost/compress/zstd/snappy.go b/vendor/github.com/klauspost/compress/zstd/snappy.go index c95fe5111c1a..9d9d1d567e68 100644 --- a/vendor/github.com/klauspost/compress/zstd/snappy.go +++ b/vendor/github.com/klauspost/compress/zstd/snappy.go @@ -10,8 +10,8 @@ import ( "hash/crc32" "io" + "github.com/golang/snappy" "github.com/klauspost/compress/huff0" - "github.com/klauspost/compress/snappy" ) const ( @@ -185,7 +185,6 @@ func (r *SnappyConverter) Convert(in io.Reader, w io.Writer) (int64, error) { r.block.reset(nil) r.block.literals, err = snappy.Decode(r.block.literals[:n], r.buf[snappyChecksumSize:chunkLen]) if err != nil { - println("snappy.Decode:", err) return written, err } err = r.block.encodeLits(r.block.literals, false) diff --git a/vendor/github.com/klauspost/compress/zstd/zip.go b/vendor/github.com/klauspost/compress/zstd/zip.go new file mode 100644 index 000000000000..9325b928ae2f --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/zip.go @@ -0,0 +1,121 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +package zstd + +import ( + "errors" + "io" + "sync" +) + +// ZipMethodWinZip is the method for Zstandard compressed data inside Zip files for WinZip. +// See https://www.winzip.com/win/en/comp_info.html +const ZipMethodWinZip = 93 + +// ZipMethodPKWare is the original method number used by PKWARE to indicate Zstandard compression. +// Deprecated: This has been deprecated by PKWARE, use ZipMethodWinZip instead for compression. +// See https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT +const ZipMethodPKWare = 20 + +var zipReaderPool sync.Pool + +// newZipReader cannot be used since we would leak goroutines... +func newZipReader(r io.Reader) io.ReadCloser { + dec, ok := zipReaderPool.Get().(*Decoder) + if ok { + dec.Reset(r) + } else { + d, err := NewReader(r, WithDecoderConcurrency(1), WithDecoderLowmem(true)) + if err != nil { + panic(err) + } + dec = d + } + return &pooledZipReader{dec: dec} +} + +type pooledZipReader struct { + mu sync.Mutex // guards Close and Read + dec *Decoder +} + +func (r *pooledZipReader) Read(p []byte) (n int, err error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.dec == nil { + return 0, errors.New("Read after Close") + } + dec, err := r.dec.Read(p) + + return dec, err +} + +func (r *pooledZipReader) Close() error { + r.mu.Lock() + defer r.mu.Unlock() + var err error + if r.dec != nil { + err = r.dec.Reset(nil) + zipReaderPool.Put(r.dec) + r.dec = nil + } + return err +} + +type pooledZipWriter struct { + mu sync.Mutex // guards Close and Read + enc *Encoder +} + +func (w *pooledZipWriter) Write(p []byte) (n int, err error) { + w.mu.Lock() + defer w.mu.Unlock() + if w.enc == nil { + return 0, errors.New("Write after Close") + } + return w.enc.Write(p) +} + +func (w *pooledZipWriter) Close() error { + w.mu.Lock() + defer w.mu.Unlock() + var err error + if w.enc != nil { + err = w.enc.Close() + zipReaderPool.Put(w.enc) + w.enc = nil + } + return err +} + +// ZipCompressor returns a compressor that can be registered with zip libraries. +// The provided encoder options will be used on all encodes. +func ZipCompressor(opts ...EOption) func(w io.Writer) (io.WriteCloser, error) { + var pool sync.Pool + return func(w io.Writer) (io.WriteCloser, error) { + enc, ok := pool.Get().(*Encoder) + if ok { + enc.Reset(w) + } else { + var err error + enc, err = NewWriter(w, opts...) + if err != nil { + return nil, err + } + } + return &pooledZipWriter{enc: enc}, nil + } +} + +// ZipDecompressor returns a decompressor that can be registered with zip libraries. +// See ZipCompressor for example. +func ZipDecompressor() func(r io.Reader) io.ReadCloser { + return func(r io.Reader) io.ReadCloser { + d, err := NewReader(r, WithDecoderConcurrency(1), WithDecoderLowmem(true)) + if err != nil { + panic(err) + } + return d.IOReadCloser() + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go index 9056beef271a..1ba308c8bf77 100644 --- a/vendor/github.com/klauspost/compress/zstd/zstd.go +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -5,6 +5,7 @@ package zstd import ( "bytes" + "encoding/binary" "errors" "log" "math" @@ -126,26 +127,15 @@ func matchLen(a, b []byte) int { } func load3232(b []byte, i int32) uint32 { - // Help the compiler eliminate bounds checks on the read so it can be done in a single read. - b = b[i:] - b = b[:4] - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + return binary.LittleEndian.Uint32(b[i:]) } func load6432(b []byte, i int32) uint64 { - // Help the compiler eliminate bounds checks on the read so it can be done in a single read. - b = b[i:] - b = b[:8] - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | - uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + return binary.LittleEndian.Uint64(b[i:]) } func load64(b []byte, i int) uint64 { - // Help the compiler eliminate bounds checks on the read so it can be done in a single read. - b = b[i:] - b = b[:8] - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | - uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + return binary.LittleEndian.Uint64(b[i:]) } type byter interface { diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml index 5e20aa4140c3..c1dbd5a3a3e2 100644 --- a/vendor/github.com/sirupsen/logrus/.travis.yml +++ b/vendor/github.com/sirupsen/logrus/.travis.yml @@ -4,14 +4,12 @@ git: depth: 1 env: - GO111MODULE=on -go: [1.13.x, 1.14.x] -os: [linux, osx] +go: 1.15.x +os: linux install: - ./travis/install.sh script: - - ./travis/cross_build.sh - - ./travis/lint.sh - - export GOMAXPROCS=4 - - export GORACE=halt_on_error=1 - - go test -race -v ./... - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi + - cd ci + - go run mage.go -v -w ../ crossBuild + - go run mage.go -v -w ../ lint + - go run mage.go -v -w ../ test diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md index 584026d67caa..7567f612898c 100644 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -1,3 +1,39 @@ +# 1.8.1 +Code quality: + * move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer + * improve timestamp format documentation + +Fixes: + * fix race condition on logger hooks + + +# 1.8.0 + +Correct versioning number replacing v1.7.1. + +# 1.7.1 + +Beware this release has introduced a new public API and its semver is therefore incorrect. + +Code quality: + * use go 1.15 in travis + * use magefile as task runner + +Fixes: + * small fixes about new go 1.13 error formatting system + * Fix for long time race condiction with mutating data hooks + +Features: + * build support for zos + +# 1.7.0 +Fixes: + * the dependency toward a windows terminal library has been removed + +Features: + * a new buffer pool management API has been added + * a set of `Fn()` functions have been added + # 1.6.0 Fixes: * end of line cleanup diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md index 5796706dbfa2..5152b6aa406f 100644 --- a/vendor/github.com/sirupsen/logrus/README.md +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -402,7 +402,7 @@ func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { // source of the official loggers. serialized, err := json.Marshal(entry.Data) if err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + return nil, fmt.Errorf("Failed to marshal fields to JSON, %w", err) } return append(serialized, '\n'), nil } diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go index 5a5cbfe7c897..07a1e5fa7249 100644 --- a/vendor/github.com/sirupsen/logrus/entry.go +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -78,6 +78,14 @@ func NewEntry(logger *Logger) *Entry { } } +func (entry *Entry) Dup() *Entry { + data := make(Fields, len(entry.Data)) + for k, v := range entry.Data { + data[k] = v + } + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, Context: entry.Context, err: entry.err} +} + // Returns the bytes representation of this entry from the formatter. func (entry *Entry) Bytes() ([]byte, error) { return entry.Logger.Formatter.Format(entry) @@ -123,11 +131,9 @@ func (entry *Entry) WithFields(fields Fields) *Entry { for k, v := range fields { isErrField := false if t := reflect.TypeOf(v); t != nil { - switch t.Kind() { - case reflect.Func: + switch { + case t.Kind() == reflect.Func, t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Func: isErrField = true - case reflect.Ptr: - isErrField = t.Elem().Kind() == reflect.Func } } if isErrField { @@ -212,68 +218,72 @@ func (entry Entry) HasCaller() (has bool) { entry.Caller != nil } -// This function is not declared with a pointer value because otherwise -// race conditions will occur when using multiple goroutines -func (entry Entry) log(level Level, msg string) { +func (entry *Entry) log(level Level, msg string) { var buffer *bytes.Buffer - // Default to now, but allow users to override if they want. - // - // We don't have to worry about polluting future calls to Entry#log() - // with this assignment because this function is declared with a - // non-pointer receiver. - if entry.Time.IsZero() { - entry.Time = time.Now() + newEntry := entry.Dup() + + if newEntry.Time.IsZero() { + newEntry.Time = time.Now() } - entry.Level = level - entry.Message = msg - entry.Logger.mu.Lock() - if entry.Logger.ReportCaller { - entry.Caller = getCaller() + newEntry.Level = level + newEntry.Message = msg + + newEntry.Logger.mu.Lock() + reportCaller := newEntry.Logger.ReportCaller + newEntry.Logger.mu.Unlock() + + if reportCaller { + newEntry.Caller = getCaller() } - entry.Logger.mu.Unlock() - entry.fireHooks() + newEntry.fireHooks() buffer = getBuffer() defer func() { - entry.Buffer = nil + newEntry.Buffer = nil putBuffer(buffer) }() buffer.Reset() - entry.Buffer = buffer + newEntry.Buffer = buffer - entry.write() + newEntry.write() - entry.Buffer = nil + newEntry.Buffer = nil // To avoid Entry#log() returning a value that only would make sense for // panic() to use in Entry#Panic(), we avoid the allocation by checking // directly here. if level <= PanicLevel { - panic(&entry) + panic(newEntry) } } func (entry *Entry) fireHooks() { + var tmpHooks LevelHooks entry.Logger.mu.Lock() - defer entry.Logger.mu.Unlock() - err := entry.Logger.Hooks.Fire(entry.Level, entry) + tmpHooks = make(LevelHooks, len(entry.Logger.Hooks)) + for k, v := range entry.Logger.Hooks { + tmpHooks[k] = v + } + entry.Logger.mu.Unlock() + + err := tmpHooks.Fire(entry.Level, entry) if err != nil { fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) } } func (entry *Entry) write() { - entry.Logger.mu.Lock() - defer entry.Logger.mu.Unlock() serialized, err := entry.Logger.Formatter.Format(entry) if err != nil { fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) return } - if _, err = entry.Logger.Out.Write(serialized); err != nil { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + if _, err := entry.Logger.Out.Write(serialized); err != nil { fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) } } @@ -319,7 +329,6 @@ func (entry *Entry) Fatal(args ...interface{}) { func (entry *Entry) Panic(args ...interface{}) { entry.Log(PanicLevel, args...) - panic(fmt.Sprint(args...)) } // Entry Printf family functions diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum index 1edc143bed02..694c18b84546 100644 --- a/vendor/github.com/sirupsen/logrus/go.sum +++ b/vendor/github.com/sirupsen/logrus/go.sum @@ -4,7 +4,5 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go index ba7f237112bd..c96dc5636bf0 100644 --- a/vendor/github.com/sirupsen/logrus/json_formatter.go +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -23,6 +23,9 @@ func (f FieldMap) resolve(key fieldKey) string { // JSONFormatter formats logs into parsable json type JSONFormatter struct { // TimestampFormat sets the format used for marshaling timestamps. + // The format to use is the same than for time.Format or time.Parse from the standard + // library. + // The standard Library already provides a set of predefined format. TimestampFormat string // DisableTimestamp allows disabling automatic timestamps in output @@ -118,7 +121,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { encoder.SetIndent("", " ") } if err := encoder.Encode(data); err != nil { - return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) + return nil, fmt.Errorf("failed to marshal fields to JSON, %w", err) } return b.Bytes(), nil diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go index dbf627c97541..337704457a28 100644 --- a/vendor/github.com/sirupsen/logrus/logger.go +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -12,7 +12,7 @@ import ( // LogFunction For big messages, it can be more efficient to pass a function // and only call it if the log level is actually enables rather than // generating the log message and then checking if the level is enabled -type LogFunction func()[]interface{} +type LogFunction func() []interface{} type Logger struct { // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go index cc4fe6e31776..04748b8515f1 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go +++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go @@ -1,4 +1,4 @@ -// +build linux aix +// +build linux aix zos // +build !js package logrus diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go index 3c28b54cabae..be2c6efe5ed0 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -53,7 +53,10 @@ type TextFormatter struct { // the time passed since beginning of execution. FullTimestamp bool - // TimestampFormat to use for display when a full timestamp is printed + // TimestampFormat to use for display when a full timestamp is printed. + // The format to use is the same than for time.Format or time.Parse from the standard + // library. + // The standard Library already provides a set of predefined format. TimestampFormat string // The fields are sorted by default for a consistent output. For applications @@ -235,6 +238,8 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin levelColor = yellow case ErrorLevel, FatalLevel, PanicLevel: levelColor = red + case InfoLevel: + levelColor = blue default: levelColor = blue } diff --git a/vendor/golang.org/x/sync/singleflight/singleflight.go b/vendor/golang.org/x/sync/singleflight/singleflight.go deleted file mode 100644 index 690eb8501347..000000000000 --- a/vendor/golang.org/x/sync/singleflight/singleflight.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package singleflight provides a duplicate function call suppression -// mechanism. -package singleflight // import "golang.org/x/sync/singleflight" - -import ( - "bytes" - "errors" - "fmt" - "runtime" - "runtime/debug" - "sync" -) - -// errGoexit indicates the runtime.Goexit was called in -// the user given function. -var errGoexit = errors.New("runtime.Goexit was called") - -// A panicError is an arbitrary value recovered from a panic -// with the stack trace during the execution of given function. -type panicError struct { - value interface{} - stack []byte -} - -// Error implements error interface. -func (p *panicError) Error() string { - return fmt.Sprintf("%v\n\n%s", p.value, p.stack) -} - -func newPanicError(v interface{}) error { - stack := debug.Stack() - - // The first line of the stack trace is of the form "goroutine N [status]:" - // but by the time the panic reaches Do the goroutine may no longer exist - // and its status will have changed. Trim out the misleading line. - if line := bytes.IndexByte(stack[:], '\n'); line >= 0 { - stack = stack[line+1:] - } - return &panicError{value: v, stack: stack} -} - -// call is an in-flight or completed singleflight.Do call -type call struct { - wg sync.WaitGroup - - // These fields are written once before the WaitGroup is done - // and are only read after the WaitGroup is done. - val interface{} - err error - - // forgotten indicates whether Forget was called with this call's key - // while the call was still in flight. - forgotten bool - - // These fields are read and written with the singleflight - // mutex held before the WaitGroup is done, and are read but - // not written after the WaitGroup is done. - dups int - chans []chan<- Result -} - -// Group represents a class of work and forms a namespace in -// which units of work can be executed with duplicate suppression. -type Group struct { - mu sync.Mutex // protects m - m map[string]*call // lazily initialized -} - -// Result holds the results of Do, so they can be passed -// on a channel. -type Result struct { - Val interface{} - Err error - Shared bool -} - -// Do executes and returns the results of the given function, making -// sure that only one execution is in-flight for a given key at a -// time. If a duplicate comes in, the duplicate caller waits for the -// original to complete and receives the same results. -// The return value shared indicates whether v was given to multiple callers. -func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { - g.mu.Lock() - if g.m == nil { - g.m = make(map[string]*call) - } - if c, ok := g.m[key]; ok { - c.dups++ - g.mu.Unlock() - c.wg.Wait() - - if e, ok := c.err.(*panicError); ok { - panic(e) - } else if c.err == errGoexit { - runtime.Goexit() - } - return c.val, c.err, true - } - c := new(call) - c.wg.Add(1) - g.m[key] = c - g.mu.Unlock() - - g.doCall(c, key, fn) - return c.val, c.err, c.dups > 0 -} - -// DoChan is like Do but returns a channel that will receive the -// results when they are ready. -// -// The returned channel will not be closed. -func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result { - ch := make(chan Result, 1) - g.mu.Lock() - if g.m == nil { - g.m = make(map[string]*call) - } - if c, ok := g.m[key]; ok { - c.dups++ - c.chans = append(c.chans, ch) - g.mu.Unlock() - return ch - } - c := &call{chans: []chan<- Result{ch}} - c.wg.Add(1) - g.m[key] = c - g.mu.Unlock() - - go g.doCall(c, key, fn) - - return ch -} - -// doCall handles the single call for a key. -func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { - normalReturn := false - recovered := false - - // use double-defer to distinguish panic from runtime.Goexit, - // more details see https://golang.org/cl/134395 - defer func() { - // the given function invoked runtime.Goexit - if !normalReturn && !recovered { - c.err = errGoexit - } - - c.wg.Done() - g.mu.Lock() - defer g.mu.Unlock() - if !c.forgotten { - delete(g.m, key) - } - - if e, ok := c.err.(*panicError); ok { - // In order to prevent the waiting channels from being blocked forever, - // needs to ensure that this panic cannot be recovered. - if len(c.chans) > 0 { - go panic(e) - select {} // Keep this goroutine around so that it will appear in the crash dump. - } else { - panic(e) - } - } else if c.err == errGoexit { - // Already in the process of goexit, no need to call again - } else { - // Normal return - for _, ch := range c.chans { - ch <- Result{c.val, c.err, c.dups > 0} - } - } - }() - - func() { - defer func() { - if !normalReturn { - // Ideally, we would wait to take a stack trace until we've determined - // whether this is a panic or a runtime.Goexit. - // - // Unfortunately, the only way we can distinguish the two is to see - // whether the recover stopped the goroutine from terminating, and by - // the time we know that, the part of the stack trace relevant to the - // panic has been discarded. - if r := recover(); r != nil { - c.err = newPanicError(r) - } - } - }() - - c.val, c.err = fn() - normalReturn = true - }() - - if !normalReturn { - recovered = true - } -} - -// Forget tells the singleflight to forget about a key. Future calls -// to Do for this key will call the function rather than waiting for -// an earlier call to complete. -func (g *Group) Forget(key string) { - g.mu.Lock() - if c, ok := g.m[key]; ok { - c.forgotten = true - } - delete(g.m, key) - g.mu.Unlock() -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 7344e0f484c8..631b67c5d8d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -43,7 +43,7 @@ github.com/cespare/xxhash/v2 github.com/containerd/cgroups/stats/v1 # github.com/containerd/console v1.0.2 github.com/containerd/console -# github.com/containerd/containerd v1.5.0 +# github.com/containerd/containerd v1.5.2 github.com/containerd/containerd github.com/containerd/containerd/api/services/containers/v1 github.com/containerd/containerd/api/services/content/v1 @@ -130,7 +130,7 @@ github.com/containerd/fuse-overlayfs-snapshotter github.com/containerd/go-cni # github.com/containerd/go-runc v1.0.0 github.com/containerd/go-runc -# github.com/containerd/stargz-snapshotter v0.5.0 +# github.com/containerd/stargz-snapshotter v0.6.4 github.com/containerd/stargz-snapshotter/cache github.com/containerd/stargz-snapshotter/fs github.com/containerd/stargz-snapshotter/fs/config @@ -140,10 +140,11 @@ github.com/containerd/stargz-snapshotter/fs/reader github.com/containerd/stargz-snapshotter/fs/remote github.com/containerd/stargz-snapshotter/fs/source github.com/containerd/stargz-snapshotter/snapshot +github.com/containerd/stargz-snapshotter/snapshot/overlayutils github.com/containerd/stargz-snapshotter/task github.com/containerd/stargz-snapshotter/util/lrucache github.com/containerd/stargz-snapshotter/util/namedmutex -# github.com/containerd/stargz-snapshotter/estargz v0.5.0 +# github.com/containerd/stargz-snapshotter/estargz v0.6.4 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil # github.com/containerd/ttrpc v1.0.2 @@ -158,7 +159,7 @@ github.com/containernetworking/cni/pkg/types/020 github.com/containernetworking/cni/pkg/types/current github.com/containernetworking/cni/pkg/utils github.com/containernetworking/cni/pkg/version -# github.com/coreos/go-systemd/v22 v22.1.0 +# github.com/coreos/go-systemd/v22 v22.3.2 github.com/coreos/go-systemd/v22/activation github.com/coreos/go-systemd/v22/daemon # github.com/cpuguy83/go-md2man/v2 v2.0.0 @@ -251,6 +252,8 @@ github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/struct github.com/golang/protobuf/ptypes/timestamp +# github.com/golang/snappy v0.0.3 +github.com/golang/snappy # github.com/google/go-cmp v0.5.4 github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp/internal/diff @@ -265,24 +268,27 @@ github.com/google/uuid github.com/grpc-ecosystem/go-grpc-middleware # github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc -# github.com/hanwen/go-fuse/v2 v2.0.4-0.20201208195215-4a458845028b +# github.com/hanwen/go-fuse/v2 v2.1.0 github.com/hanwen/go-fuse/v2/fs github.com/hanwen/go-fuse/v2/fuse github.com/hanwen/go-fuse/v2/internal github.com/hanwen/go-fuse/v2/internal/utimens github.com/hanwen/go-fuse/v2/splice +# github.com/hashicorp/errwrap v1.0.0 +github.com/hashicorp/errwrap # github.com/hashicorp/go-immutable-radix v1.0.0 => github.com/tonistiigi/go-immutable-radix v0.0.0-20170803185627-826af9ccf0fe github.com/hashicorp/go-immutable-radix +# github.com/hashicorp/go-multierror v1.1.1 +github.com/hashicorp/go-multierror # github.com/hashicorp/golang-lru v0.5.3 github.com/hashicorp/golang-lru/simplelru # github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee github.com/ishidawataru/sctp # github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 github.com/jaguilar/vt100 -# github.com/klauspost/compress v1.11.13 +# github.com/klauspost/compress v1.12.3 github.com/klauspost/compress/fse github.com/klauspost/compress/huff0 -github.com/klauspost/compress/snappy github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash # github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 @@ -346,7 +352,7 @@ github.com/russross/blackfriday/v2 github.com/serialx/hashring # github.com/shurcooL/sanitized_anchor_name v1.0.0 github.com/shurcooL/sanitized_anchor_name -# github.com/sirupsen/logrus v1.7.0 +# github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus # github.com/stretchr/testify v1.7.0 github.com/stretchr/testify/assert @@ -413,7 +419,6 @@ golang.org/x/net/trace # golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync/errgroup golang.org/x/sync/semaphore -golang.org/x/sync/singleflight # golang.org/x/sys v0.0.0-20210324051608-47abb6519492 golang.org/x/sys/cpu golang.org/x/sys/execabs