diff --git a/builder/builder-next/adapters/containerimage/pull.go b/builder/builder-next/adapters/containerimage/pull.go index f187f5c16f0b6..f94b4ebe9eb69 100644 --- a/builder/builder-next/adapters/containerimage/pull.go +++ b/builder/builder-next/adapters/containerimage/pull.go @@ -34,6 +34,7 @@ import ( "github.com/moby/buildkit/util/flightcontrol" "github.com/moby/buildkit/util/imageutil" "github.com/moby/buildkit/util/progress" + "github.com/moby/buildkit/util/resolver" "github.com/moby/buildkit/util/tracing" digest "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" @@ -51,6 +52,7 @@ type SourceOpt struct { DownloadManager distribution.RootFSDownloadManager MetadataStore metadata.V2MetadataService ImageStore image.Store + ResolverOpt resolver.ResolveOptionsFunc } type imageSource struct { @@ -71,11 +73,16 @@ func (is *imageSource) ID() string { return source.DockerImageScheme } -func (is *imageSource) getResolver(ctx context.Context) remotes.Resolver { - return docker.NewResolver(docker.ResolverOptions{ +func (is *imageSource) getResolver(ctx context.Context, rfn resolver.ResolveOptionsFunc, ref string) remotes.Resolver { + opt := docker.ResolverOptions{ Client: tracing.DefaultClient, Credentials: is.getCredentialsFromSession(ctx), - }) + } + if rfn != nil { + opt = rfn(ref) + } + r := docker.NewResolver(opt) + return r } func (is *imageSource) getCredentialsFromSession(ctx context.Context) func(string) (string, string, error) { @@ -118,7 +125,7 @@ func (is *imageSource) resolveRemote(ctx context.Context, ref string, platform * dt []byte } res, err := is.g.Do(ctx, ref, func(ctx context.Context) (interface{}, error) { - dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(ctx), is.ContentStore, platform) + dgst, dt, err := imageutil.Config(ctx, ref, is.getResolver(ctx, is.ResolverOpt, ref), is.ContentStore, platform) if err != nil { return nil, err } @@ -181,7 +188,7 @@ func (is *imageSource) Resolve(ctx context.Context, id source.Identifier) (sourc p := &puller{ src: imageIdentifier, is: is, - resolver: is.getResolver(ctx), + resolver: is.getResolver(ctx, is.ResolverOpt, imageIdentifier.Reference.String()), platform: platform, } return p, nil diff --git a/builder/builder-next/adapters/snapshot/layer.go b/builder/builder-next/adapters/snapshot/layer.go index d0aa6f28fae8c..ffde5eec51108 100644 --- a/builder/builder-next/adapters/snapshot/layer.go +++ b/builder/builder-next/adapters/snapshot/layer.go @@ -5,10 +5,10 @@ import ( "os" "path/filepath" - "github.com/boltdb/bolt" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/ioutils" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" "golang.org/x/sync/errgroup" ) diff --git a/builder/builder-next/adapters/snapshot/snapshot.go b/builder/builder-next/adapters/snapshot/snapshot.go index d8efb759c294c..e5e6942653d70 100644 --- a/builder/builder-next/adapters/snapshot/snapshot.go +++ b/builder/builder-next/adapters/snapshot/snapshot.go @@ -7,7 +7,6 @@ import ( "strings" "sync" - "github.com/boltdb/bolt" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/snapshots" "github.com/docker/docker/daemon/graphdriver" @@ -16,6 +15,7 @@ import ( "github.com/moby/buildkit/snapshot" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) var keyParent = []byte("parent") diff --git a/builder/builder-next/builder.go b/builder/builder-next/builder.go index 7bd93c05fc671..a51d8ec52c79b 100644 --- a/builder/builder-next/builder.go +++ b/builder/builder-next/builder.go @@ -13,16 +13,19 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/backend" "github.com/docker/docker/builder" + "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/images" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/system" "github.com/docker/libnetwork" controlapi "github.com/moby/buildkit/api/services/control" + "github.com/moby/buildkit/client" "github.com/moby/buildkit/control" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver/llbsolver" "github.com/moby/buildkit/util/entitlements" + "github.com/moby/buildkit/util/resolver" "github.com/moby/buildkit/util/tracing" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -55,6 +58,8 @@ type Opt struct { Dist images.DistributionServices NetworkController libnetwork.NetworkController DefaultCgroupParent string + ResolverOpt resolver.ResolveOptionsFunc + BuilderConfig config.BuilderConfig } // Builder can build using BuildKit backend @@ -132,43 +137,18 @@ func (b *Builder) Prune(ctx context.Context, opts types.BuildCachePruneOptions) return 0, nil, err } - var unusedFor time.Duration - unusedForValues := opts.Filters.Get("unused-for") - - switch len(unusedForValues) { - case 0: - - case 1: - var err error - unusedFor, err = time.ParseDuration(unusedForValues[0]) - if err != nil { - return 0, nil, errors.Wrap(err, "unused-for filter expects a duration (e.g., '24h')") - } - - default: - return 0, nil, errMultipleFilterValues - } - - bkFilter := make([]string, 0, opts.Filters.Len()) - for cacheField := range cacheFields { - values := opts.Filters.Get(cacheField) - switch len(values) { - case 0: - bkFilter = append(bkFilter, cacheField) - case 1: - bkFilter = append(bkFilter, cacheField+"=="+values[0]) - default: - return 0, nil, errMultipleFilterValues - } + pi, err := toBuildkitPruneInfo(opts) + if err != nil { + return 0, nil, err } eg.Go(func() error { defer close(ch) return b.controller.Prune(&controlapi.PruneRequest{ - All: opts.All, - KeepDuration: int64(unusedFor), - KeepBytes: opts.KeepStorage, - Filter: bkFilter, + All: pi.All, + KeepDuration: int64(pi.KeepDuration), + KeepBytes: pi.KeepBytes, + Filter: pi.Filter, }, &pruneProxy{ streamProxy: streamProxy{ctx: ctx}, ch: ch, @@ -529,3 +509,41 @@ func toBuildkitExtraHosts(inp []string) (string, error) { } return strings.Join(hosts, ","), nil } + +func toBuildkitPruneInfo(opts types.BuildCachePruneOptions) (client.PruneInfo, error) { + var unusedFor time.Duration + unusedForValues := opts.Filters.Get("unused-for") + + switch len(unusedForValues) { + case 0: + + case 1: + var err error + unusedFor, err = time.ParseDuration(unusedForValues[0]) + if err != nil { + return client.PruneInfo{}, errors.Wrap(err, "unused-for filter expects a duration (e.g., '24h')") + } + + default: + return client.PruneInfo{}, errMultipleFilterValues + } + + bkFilter := make([]string, 0, opts.Filters.Len()) + for cacheField := range cacheFields { + values := opts.Filters.Get(cacheField) + switch len(values) { + case 0: + bkFilter = append(bkFilter, cacheField) + case 1: + bkFilter = append(bkFilter, cacheField+"=="+values[0]) + default: + return client.PruneInfo{}, errMultipleFilterValues + } + } + return client.PruneInfo{ + All: opts.All, + KeepDuration: unusedFor, + KeepBytes: opts.KeepStorage, + Filter: bkFilter, + }, nil +} diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go index 808b0b884f050..5aafba2e4a525 100644 --- a/builder/builder-next/controller.go +++ b/builder/builder-next/controller.go @@ -6,15 +6,19 @@ import ( "path/filepath" "github.com/containerd/containerd/content/local" + "github.com/docker/docker/api/types" "github.com/docker/docker/builder/builder-next/adapters/containerimage" "github.com/docker/docker/builder/builder-next/adapters/snapshot" containerimageexp "github.com/docker/docker/builder/builder-next/exporter" "github.com/docker/docker/builder/builder-next/imagerefchecker" mobyworker "github.com/docker/docker/builder/builder-next/worker" + "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/graphdriver" + units "github.com/docker/go-units" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/metadata" registryremotecache "github.com/moby/buildkit/cache/remotecache/registry" + "github.com/moby/buildkit/client" "github.com/moby/buildkit/control" "github.com/moby/buildkit/exporter" "github.com/moby/buildkit/frontend" @@ -22,7 +26,7 @@ import ( "github.com/moby/buildkit/frontend/gateway" "github.com/moby/buildkit/frontend/gateway/forwarder" "github.com/moby/buildkit/snapshot/blobmapping" - "github.com/moby/buildkit/solver/boltdbcachestorage" + "github.com/moby/buildkit/solver/bboltcachestorage" "github.com/moby/buildkit/worker" "github.com/pkg/errors" ) @@ -97,6 +101,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) { MetadataStore: dist.V2MetadataService, ImageStore: dist.ImageStore, ReferenceStore: dist.ReferenceStore, + ResolverOpt: opt.ResolverOpt, }) if err != nil { return nil, err @@ -121,17 +126,23 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) { return nil, err } - cacheStorage, err := boltdbcachestorage.NewStore(filepath.Join(opt.Root, "cache.db")) + cacheStorage, err := bboltcachestorage.NewStore(filepath.Join(opt.Root, "cache.db")) if err != nil { return nil, err } + gcPolicy, err := getGCPolicy(opt.BuilderConfig, root) + if err != nil { + return nil, errors.Wrap(err, "could not get builder GC policy") + } + wopt := mobyworker.Opt{ ID: "moby", SessionManager: opt.SessionManager, MetadataStore: md, ContentStore: store, CacheManager: cm, + GCPolicy: gcPolicy, Snapshotter: snapshotter, Executor: exec, ImageSource: src, @@ -160,7 +171,48 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) { WorkerController: wc, Frontends: frontends, CacheKeyStorage: cacheStorage, - ResolveCacheImporterFunc: registryremotecache.ResolveCacheImporterFunc(opt.SessionManager), + ResolveCacheImporterFunc: registryremotecache.ResolveCacheImporterFunc(opt.SessionManager, opt.ResolverOpt), // TODO: set ResolveCacheExporterFunc for exporting cache }) } + +func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, error) { + var gcPolicy []client.PruneInfo + if conf.GC.Enabled { + var ( + defaultKeepStorage int64 + err error + ) + + if conf.GC.DefaultKeepStorage != "" { + defaultKeepStorage, err = units.RAMInBytes(conf.GC.DefaultKeepStorage) + if err != nil { + return nil, errors.Wrapf(err, "could not parse '%s' as Builder.GC.DefaultKeepStorage config", conf.GC.DefaultKeepStorage) + } + } + + if conf.GC.Policy == nil { + gcPolicy = mobyworker.DefaultGCPolicy(root, defaultKeepStorage) + } else { + gcPolicy = make([]client.PruneInfo, len(conf.GC.Policy)) + for i, p := range conf.GC.Policy { + b, err := units.RAMInBytes(p.KeepStorage) + if err != nil { + return nil, err + } + if b == 0 { + b = defaultKeepStorage + } + gcPolicy[i], err = toBuildkitPruneInfo(types.BuildCachePruneOptions{ + All: p.All, + KeepStorage: b, + Filters: p.Filter, + }) + if err != nil { + return nil, err + } + } + } + } + return gcPolicy, nil +} diff --git a/builder/builder-next/worker/gc.go b/builder/builder-next/worker/gc.go new file mode 100644 index 0000000000000..13e65f0e6f1cd --- /dev/null +++ b/builder/builder-next/worker/gc.go @@ -0,0 +1,51 @@ +package worker + +import ( + "math" + + "github.com/moby/buildkit/client" +) + +const defaultCap int64 = 2e9 // 2GB + +// tempCachePercent represents the percentage ratio of the cache size in bytes to temporarily keep for a short period of time (couple of days) +// over the total cache size in bytes. Because there is no perfect value, a mathematically pleasing one was chosen. +// The value is approximately 13.8 +const tempCachePercent = math.E * math.Pi * math.Phi + +// DefaultGCPolicy returns a default builder GC policy +func DefaultGCPolicy(p string, defaultKeepBytes int64) []client.PruneInfo { + keep := defaultKeepBytes + if defaultKeepBytes == 0 { + keep = detectDefaultGCCap(p) + } + + tempCacheKeepBytes := int64(math.Round(float64(keep) / 100. * float64(tempCachePercent))) + const minTempCacheKeepBytes = 512 * 1e6 // 512MB + if tempCacheKeepBytes < minTempCacheKeepBytes { + tempCacheKeepBytes = minTempCacheKeepBytes + } + + return []client.PruneInfo{ + // if build cache uses more than 512MB delete the most easily reproducible data after it has not been used for 2 days + { + Filter: []string{"type==source.local,type==exec.cachemount,type==source.git.checkout"}, + KeepDuration: 48 * 3600, // 48h + KeepBytes: tempCacheKeepBytes, + }, + // remove any data not used for 60 days + { + KeepDuration: 60 * 24 * 3600, // 60d + KeepBytes: keep, + }, + // keep the unshared build cache under cap + { + KeepBytes: keep, + }, + // if previous policies were insufficient start deleting internal data to keep build cache under cap + { + All: true, + KeepBytes: keep, + }, + } +} diff --git a/builder/builder-next/worker/gc_unix.go b/builder/builder-next/worker/gc_unix.go new file mode 100644 index 0000000000000..7457a06654e60 --- /dev/null +++ b/builder/builder-next/worker/gc_unix.go @@ -0,0 +1,17 @@ +// +build !windows + +package worker + +import ( + "syscall" +) + +func detectDefaultGCCap(root string) int64 { + var st syscall.Statfs_t + if err := syscall.Statfs(root, &st); err != nil { + return defaultCap + } + diskSize := int64(st.Bsize) * int64(st.Blocks) // nolint unconvert + avail := diskSize / 10 + return (avail/(1<<30) + 1) * 1e9 // round up +} diff --git a/builder/builder-next/worker/gc_windows.go b/builder/builder-next/worker/gc_windows.go new file mode 100644 index 0000000000000..1ffcce41dbc11 --- /dev/null +++ b/builder/builder-next/worker/gc_windows.go @@ -0,0 +1,7 @@ +// +build windows + +package worker + +func detectDefaultGCCap(root string) int64 { + return defaultCap +} diff --git a/builder/builder-next/worker/worker.go b/builder/builder-next/worker/worker.go index e2aae3a63f759..28d0d8bea645e 100644 --- a/builder/builder-next/worker/worker.go +++ b/builder/builder-next/worker/worker.go @@ -137,8 +137,12 @@ func (w *Worker) GCPolicy() []client.PruneInfo { } // LoadRef loads a reference by ID -func (w *Worker) LoadRef(id string) (cache.ImmutableRef, error) { - return w.CacheManager.Get(context.TODO(), id) +func (w *Worker) LoadRef(id string, hidden bool) (cache.ImmutableRef, error) { + var opts []cache.RefOption + if hidden { + opts = append(opts, cache.NoUpdateLastUsed) + } + return w.CacheManager.Get(context.TODO(), id, opts...) } // ResolveOp converts a LLB vertex into a LLB operation diff --git a/builder/fscache/fscache.go b/builder/fscache/fscache.go index 92c3ea4adbeb1..2216c338b7e74 100644 --- a/builder/fscache/fscache.go +++ b/builder/fscache/fscache.go @@ -12,7 +12,6 @@ import ( "sync" "time" - "github.com/boltdb/bolt" "github.com/docker/docker/builder" "github.com/docker/docker/builder/remotecontext" "github.com/docker/docker/pkg/archive" @@ -23,6 +22,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/tonistiigi/fsutil" + bolt "go.etcd.io/bbolt" "golang.org/x/sync/singleflight" ) diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 416d9df46c7f6..aba6b1e06c4b9 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -291,6 +291,8 @@ func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, e Dist: d.DistributionServices(), NetworkController: d.NetworkController(), DefaultCgroupParent: cgroupParent, + ResolverOpt: d.NewResolveOptionsFunc(), + BuilderConfig: config.Builder, }) if err != nil { return opts, err diff --git a/daemon/cluster/noderunner.go b/daemon/cluster/noderunner.go index f4746563d4563..071d8af5a7b7e 100644 --- a/daemon/cluster/noderunner.go +++ b/daemon/cluster/noderunner.go @@ -3,7 +3,6 @@ package cluster // import "github.com/docker/docker/daemon/cluster" import ( "context" "fmt" - "net" "path/filepath" "runtime" "strings" @@ -14,6 +13,7 @@ import ( "github.com/docker/docker/daemon/cluster/executor/container" lncluster "github.com/docker/libnetwork/cluster" swarmapi "github.com/docker/swarmkit/api" + "github.com/docker/swarmkit/manager/allocator/cnmallocator" swarmnode "github.com/docker/swarmkit/node" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -115,12 +115,6 @@ func (n *nodeRunner) start(conf nodeStartConfig) error { joinAddr = conf.RemoteAddr } - var defaultAddrPool []*net.IPNet - for _, address := range conf.DefaultAddressPool { - if _, b, err := net.ParseCIDR(address); err == nil { - defaultAddrPool = append(defaultAddrPool, b) - } - } // Hostname is not set here. Instead, it is obtained from // the node description that is reported periodically swarmnodeConfig := swarmnode.Config{ @@ -128,11 +122,13 @@ func (n *nodeRunner) start(conf nodeStartConfig) error { ListenControlAPI: control, ListenRemoteAPI: conf.ListenAddr, AdvertiseRemoteAPI: conf.AdvertiseAddr, - DefaultAddrPool: defaultAddrPool, - SubnetSize: int(conf.SubnetSize), - JoinAddr: joinAddr, - StateDir: n.cluster.root, - JoinToken: conf.joinToken, + NetworkConfig: &cnmallocator.NetworkConfig{ + DefaultAddrPool: conf.DefaultAddressPool, + SubnetSize: conf.SubnetSize, + }, + JoinAddr: joinAddr, + StateDir: n.cluster.root, + JoinToken: conf.joinToken, Executor: container.NewExecutor( n.cluster.config.Backend, n.cluster.config.PluginBackend, diff --git a/daemon/config/builder.go b/daemon/config/builder.go new file mode 100644 index 0000000000000..ac85e76b303d7 --- /dev/null +++ b/daemon/config/builder.go @@ -0,0 +1,22 @@ +package config + +import "github.com/docker/docker/api/types/filters" + +// BuilderGCRule represents a GC rule for buildkit cache +type BuilderGCRule struct { + All bool `json:",omitempty"` + Filter filters.Args `json:",omitempty"` + KeepStorage string `json:",omitempty"` +} + +// BuilderGCConfig contains GC config for a buildkit builder +type BuilderGCConfig struct { + Enabled bool `json:",omitempty"` + Policy []BuilderGCRule `json:",omitempty"` + DefaultKeepStorage string `json:",omitempty"` +} + +// BuilderConfig contains config for the builder +type BuilderConfig struct { + GC BuilderGCConfig `json:",omitempty"` +} diff --git a/daemon/config/config.go b/daemon/config/config.go index 9f215e30683d6..8b2c844a579f0 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -55,6 +55,7 @@ var flatOptions = map[string]bool{ "runtimes": true, "default-ulimits": true, "features": true, + "builder": true, } // skipValidateOptions contains configuration keys @@ -62,6 +63,7 @@ var flatOptions = map[string]bool{ // for unknown flag validation. var skipValidateOptions = map[string]bool{ "features": true, + "builder": true, } // skipDuplicates contains configuration keys that @@ -225,6 +227,8 @@ type CommonConfig struct { // Features contains a list of feature key value pairs indicating what features are enabled or disabled. // If a certain feature doesn't appear in this list then it's unset (i.e. neither true nor false). Features map[string]bool `json:"features,omitempty"` + + Builder BuilderConfig `json:"builder,omitempty"` } // IsValueSet returns true if a configuration value diff --git a/daemon/daemon.go b/daemon/daemon.go index 1c6ed80f051a7..a307863017ab7 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -9,6 +9,7 @@ import ( "context" "fmt" "io/ioutil" + "math/rand" "net" "os" "path" @@ -23,6 +24,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/defaults" "github.com/containerd/containerd/pkg/dialer" + "github.com/containerd/containerd/remotes/docker" + "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/swarm" @@ -36,6 +39,8 @@ import ( "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/network" "github.com/docker/docker/errdefs" + "github.com/moby/buildkit/util/resolver" + "github.com/moby/buildkit/util/tracing" "github.com/sirupsen/logrus" // register graph drivers _ "github.com/docker/docker/daemon/graphdriver/register" @@ -141,6 +146,57 @@ func (daemon *Daemon) Features() *map[string]bool { return &daemon.configStore.Features } +// NewResolveOptionsFunc returns a call back function to resolve "registry-mirrors" and +// "insecure-registries" for buildkit +func (daemon *Daemon) NewResolveOptionsFunc() resolver.ResolveOptionsFunc { + return func(ref string) docker.ResolverOptions { + var ( + registryKey = "docker.io" + mirrors = make([]string, len(daemon.configStore.Mirrors)) + m = map[string]resolver.RegistryConf{} + ) + // must trim "https://" or "http://" prefix + for i, v := range daemon.configStore.Mirrors { + v = strings.TrimPrefix(v, "https://") + v = strings.TrimPrefix(v, "http://") + mirrors[i] = v + } + // set "registry-mirrors" + m[registryKey] = resolver.RegistryConf{Mirrors: mirrors} + // set "insecure-registries" + for _, v := range daemon.configStore.InsecureRegistries { + v = strings.TrimPrefix(v, "http://") + m[v] = resolver.RegistryConf{ + PlainHTTP: true, + } + } + def := docker.ResolverOptions{ + Client: tracing.DefaultClient, + } + + parsed, err := reference.ParseNormalizedNamed(ref) + if err != nil { + return def + } + host := reference.Domain(parsed) + + c, ok := m[host] + if !ok { + return def + } + + if len(c.Mirrors) > 0 { + def.Host = func(string) (string, error) { + return c.Mirrors[rand.Intn(len(c.Mirrors))], nil + } + } + + def.PlainHTTP = c.PlainHTTP + + return def + } +} + func (daemon *Daemon) restore() error { containers := make(map[string]*container.Container) diff --git a/daemon/images/service.go b/daemon/images/service.go index 263217dccd060..e8df5cb649858 100644 --- a/daemon/images/service.go +++ b/daemon/images/service.go @@ -205,8 +205,6 @@ func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) { if err == nil { if _, ok := layerRefs[l.ChainID()]; ok { allLayersSize += size - } else { - logrus.Warnf("found leaked image layer %v", l.ChainID()) } } else { logrus.Warnf("failed to get diff size for layer %v", l.ChainID()) diff --git a/vendor.conf b/vendor.conf index 309b406f26f3e..ebebbcb026905 100644 --- a/vendor.conf +++ b/vendor.conf @@ -26,7 +26,7 @@ github.com/imdario/mergo v0.3.6 golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca # buildkit -github.com/moby/buildkit a9fe50acf16dd05d1f9877b27068884543ad7a1f +github.com/moby/buildkit 39404586a50d1b9d0fb1c578cf0f4de7bdb7afe5 github.com/tonistiigi/fsutil b19464cd1b6a00773b4f2eb7acf9c30426f9df42 github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7 @@ -47,7 +47,7 @@ github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372 github.com/hashicorp/go-sockaddr 6d291a969b86c4b633730bfc6b8b9d64c3aafed9 github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 -github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef +github.com/docker/libkv 458977154600b9f23984d9f4b82e79570b5ae12b github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 github.com/vishvananda/netlink b2de5d10e38ecce8607e6b438b6d174f389a004e @@ -59,9 +59,9 @@ github.com/coreos/etcd v3.2.1 github.com/coreos/go-semver v0.2.0 github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065 github.com/hashicorp/consul v0.5.2 -github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904 github.com/miekg/dns v1.0.7 github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb +go.etcd.io/bbolt v1.3.1-etcd.8 # get graph and distribution packages github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5 @@ -114,18 +114,19 @@ github.com/googleapis/gax-go v2.0.0 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9 # containerd -github.com/containerd/containerd v1.2.0-beta.2 +github.com/containerd/containerd v1.2.0-rc.0 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c -github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b +github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 -github.com/containerd/go-runc edcf3de1f4971445c42d61f20d506b30612aa031 +github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef +github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch # cluster -github.com/docker/swarmkit cfa742c8abe6f8e922f6e4e920153c408e7d9c3b +github.com/docker/swarmkit 3044c576a8a970d3079492b585054f29e96e27f1 github.com/gogo/protobuf v1.0.0 github.com/cloudflare/cfssl 1.3.2 github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2 diff --git a/vendor/github.com/containerd/containerd/README.md b/vendor/github.com/containerd/containerd/README.md index d068fa3afdea0..c4d9dffdbdc58 100644 --- a/vendor/github.com/containerd/containerd/README.md +++ b/vendor/github.com/containerd/containerd/README.md @@ -2,6 +2,7 @@ [![GoDoc](https://godoc.org/github.com/containerd/containerd?status.svg)](https://godoc.org/github.com/containerd/containerd) [![Build Status](https://travis-ci.org/containerd/containerd.svg?branch=master)](https://travis-ci.org/containerd/containerd) +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/containerd/containerd?branch=master&svg=true)](https://ci.appveyor.com/project/mlaventure/containerd-3g73f?branch=master) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fcontainerd%2Fcontainerd?ref=badge_shield) [![Go Report Card](https://goreportcard.com/badge/github.com/containerd/containerd)](https://goreportcard.com/report/github.com/containerd/containerd) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1271/badge)](https://bestpractices.coreinfrastructure.org/projects/1271) @@ -223,7 +224,7 @@ This will be the best place to discuss design and implementation. For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development. -**Slack:** https://dockr.ly/community +**Slack:** https://join.slack.com/t/dockercommunity/shared_invite/enQtNDM4NjAwNDMyOTUwLWZlMDZmYWRjZjk4Zjc5ZGQ5NWZkOWI1Yjk2NGE3ZWVlYjYxM2VhYjczOWIyZDFhZTE3NTUwZWQzMjhmNGYyZTg ### Reporting security issues diff --git a/vendor/github.com/containerd/containerd/api/services/content/v1/content.pb.go b/vendor/github.com/containerd/containerd/api/services/content/v1/content.pb.go index b539ae1aee4e3..ec08c3b233d27 100644 --- a/vendor/github.com/containerd/containerd/api/services/content/v1/content.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/content/v1/content.pb.go @@ -443,7 +443,7 @@ type ContentClient interface { // Only one active stream may exist at a time for each ref. // // Once a write stream has started, it may only write to a single ref, thus - // once a stream is started, the ref may be ommitted on subsequent writes. + // once a stream is started, the ref may be omitted on subsequent writes. // // For any write transaction represented by a ref, only a single write may // be made to a given offset. If overlapping writes occur, it is an error. @@ -658,7 +658,7 @@ type ContentServer interface { // Only one active stream may exist at a time for each ref. // // Once a write stream has started, it may only write to a single ref, thus - // once a stream is started, the ref may be ommitted on subsequent writes. + // once a stream is started, the ref may be omitted on subsequent writes. // // For any write transaction represented by a ref, only a single write may // be made to a given offset. If overlapping writes occur, it is an error. diff --git a/vendor/github.com/containerd/containerd/api/services/content/v1/content.proto b/vendor/github.com/containerd/containerd/api/services/content/v1/content.proto index 4f1187145bb48..086b3e39b1fe7 100644 --- a/vendor/github.com/containerd/containerd/api/services/content/v1/content.proto +++ b/vendor/github.com/containerd/containerd/api/services/content/v1/content.proto @@ -55,7 +55,7 @@ service Content { // Only one active stream may exist at a time for each ref. // // Once a write stream has started, it may only write to a single ref, thus - // once a stream is started, the ref may be ommitted on subsequent writes. + // once a stream is started, the ref may be omitted on subsequent writes. // // For any write transaction represented by a ref, only a single write may // be made to a given offset. If overlapping writes occur, it is an error. diff --git a/vendor/github.com/containerd/containerd/api/services/events/v1/events.pb.go b/vendor/github.com/containerd/containerd/api/services/events/v1/events.pb.go index 0173f394ea9a5..d6a7b38a87419 100644 --- a/vendor/github.com/containerd/containerd/api/services/events/v1/events.pb.go +++ b/vendor/github.com/containerd/containerd/api/services/events/v1/events.pb.go @@ -141,7 +141,7 @@ type EventsClient interface { // Forward sends an event that has already been packaged into an envelope // with a timestamp and namespace. // - // This is useful if earlier timestamping is required or when fowarding on + // This is useful if earlier timestamping is required or when forwarding on // behalf of another component, namespace or publisher. Forward(ctx context.Context, in *ForwardRequest, opts ...grpc.CallOption) (*google_protobuf2.Empty, error) // Subscribe to a stream of events, possibly returning only that match any @@ -223,7 +223,7 @@ type EventsServer interface { // Forward sends an event that has already been packaged into an envelope // with a timestamp and namespace. // - // This is useful if earlier timestamping is required or when fowarding on + // This is useful if earlier timestamping is required or when forwarding on // behalf of another component, namespace or publisher. Forward(context.Context, *ForwardRequest) (*google_protobuf2.Empty, error) // Subscribe to a stream of events, possibly returning only that match any diff --git a/vendor/github.com/containerd/containerd/api/services/events/v1/events.proto b/vendor/github.com/containerd/containerd/api/services/events/v1/events.proto index 58f2dadeb5733..1959c8e39551b 100644 --- a/vendor/github.com/containerd/containerd/api/services/events/v1/events.proto +++ b/vendor/github.com/containerd/containerd/api/services/events/v1/events.proto @@ -20,7 +20,7 @@ service Events { // Forward sends an event that has already been packaged into an envelope // with a timestamp and namespace. // - // This is useful if earlier timestamping is required or when fowarding on + // This is useful if earlier timestamping is required or when forwarding on // behalf of another component, namespace or publisher. rpc Forward(ForwardRequest) returns (google.protobuf.Empty); diff --git a/vendor/github.com/containerd/containerd/archive/compression/compression.go b/vendor/github.com/containerd/containerd/archive/compression/compression.go index bd50f083b201f..bd64e0353d059 100644 --- a/vendor/github.com/containerd/containerd/archive/compression/compression.go +++ b/vendor/github.com/containerd/containerd/archive/compression/compression.go @@ -20,9 +20,15 @@ import ( "bufio" "bytes" "compress/gzip" + "context" "fmt" "io" + "os" + "os/exec" + "strconv" "sync" + + "github.com/containerd/containerd/log" ) type ( @@ -37,6 +43,13 @@ const ( Gzip ) +const disablePigzEnv = "CONTAINERD_DISABLE_PIGZ" + +var ( + initPigz sync.Once + unpigzPath string +) + var ( bufioReader32KPool = &sync.Pool{ New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) }, @@ -120,11 +133,18 @@ func DecompressStream(archive io.Reader) (DecompressReadCloser, error) { readBufWrapper := &readCloserWrapper{buf, compression, closer} return readBufWrapper, nil case Gzip: - gzReader, err := gzip.NewReader(buf) + ctx, cancel := context.WithCancel(context.Background()) + gzReader, err := gzipDecompress(ctx, buf) if err != nil { + cancel() return nil, err } - readBufWrapper := &readCloserWrapper{gzReader, compression, closer} + + readBufWrapper := &readCloserWrapper{gzReader, compression, func() error { + cancel() + return closer() + }} + return readBufWrapper, nil default: return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension()) @@ -151,3 +171,67 @@ func (compression *Compression) Extension() string { } return "" } + +func gzipDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) { + initPigz.Do(func() { + if unpigzPath = detectPigz(); unpigzPath != "" { + log.L.Debug("using pigz for decompression") + } + }) + + if unpigzPath == "" { + return gzip.NewReader(buf) + } + + return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf) +} + +func cmdStream(cmd *exec.Cmd, in io.Reader) (io.ReadCloser, error) { + reader, writer := io.Pipe() + + cmd.Stdin = in + cmd.Stdout = writer + + var errBuf bytes.Buffer + cmd.Stderr = &errBuf + + if err := cmd.Start(); err != nil { + return nil, err + } + + go func() { + if err := cmd.Wait(); err != nil { + writer.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String())) + } else { + writer.Close() + } + }() + + return reader, nil +} + +func detectPigz() string { + path, err := exec.LookPath("unpigz") + if err != nil { + log.L.WithError(err).Debug("unpigz not found, falling back to go gzip") + return "" + } + + // Check if pigz disabled via CONTAINERD_DISABLE_PIGZ env variable + value := os.Getenv(disablePigzEnv) + if value == "" { + return path + } + + disable, err := strconv.ParseBool(value) + if err != nil { + log.L.WithError(err).Warnf("could not parse %s: %s", disablePigzEnv, value) + return path + } + + if disable { + return "" + } + + return path +} diff --git a/vendor/github.com/containerd/containerd/cio/io.go b/vendor/github.com/containerd/containerd/cio/io.go index 10ad36ba87d89..a9c6d2b156c62 100644 --- a/vendor/github.com/containerd/containerd/cio/io.go +++ b/vendor/github.com/containerd/containerd/cio/io.go @@ -141,6 +141,15 @@ func NewCreator(opts ...Opt) Creator { if err != nil { return nil, err } + if streams.Stdin == nil { + fifos.Stdin = "" + } + if streams.Stdout == nil { + fifos.Stdout = "" + } + if streams.Stderr == nil { + fifos.Stderr = "" + } return copyIO(fifos, streams) } } diff --git a/vendor/github.com/containerd/containerd/container_opts_unix.go b/vendor/github.com/containerd/containerd/container_opts_unix.go index a4935b2b454e5..c0622f67fe8df 100644 --- a/vendor/github.com/containerd/containerd/container_opts_unix.go +++ b/vendor/github.com/containerd/containerd/container_opts_unix.go @@ -20,25 +20,21 @@ package containerd import ( "context" - "encoding/json" "fmt" "os" "path/filepath" "syscall" - "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/platforms" - "github.com/containerd/containerd/runtime/linux/runctypes" "github.com/gogo/protobuf/proto" protobuf "github.com/gogo/protobuf/types" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/specs-go/v1" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) @@ -105,44 +101,6 @@ func WithCheckpoint(im Image, snapshotKey string) NewContainerOpts { } } -// WithTaskCheckpoint allows a task to be created with live runtime and memory data from a -// previous checkpoint. Additional software such as CRIU may be required to -// restore a task from a checkpoint -func WithTaskCheckpoint(im Image) NewTaskOpts { - return func(ctx context.Context, c *Client, info *TaskInfo) error { - desc := im.Target() - id := desc.Digest - index, err := decodeIndex(ctx, c.ContentStore(), desc) - if err != nil { - return err - } - for _, m := range index.Manifests { - if m.MediaType == images.MediaTypeContainerd1Checkpoint { - info.Checkpoint = &types.Descriptor{ - MediaType: m.MediaType, - Size_: m.Size, - Digest: m.Digest, - } - return nil - } - } - return fmt.Errorf("checkpoint not found in index %s", id) - } -} - -func decodeIndex(ctx context.Context, store content.Provider, desc ocispec.Descriptor) (*v1.Index, error) { - var index v1.Index - p, err := content.ReadBlob(ctx, store, desc) - if err != nil { - return nil, err - } - if err := json.Unmarshal(p, &index); err != nil { - return nil, err - } - - return &index, nil -} - // WithRemappedSnapshot creates a new snapshot and remaps the uid/gid for the // filesystem to be used by a container with user namespaces func WithRemappedSnapshot(id string, i Image, uid, gid uint32) NewContainerOpts { @@ -221,19 +179,3 @@ func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc { return os.Lchown(path, u, g) } } - -// WithNoPivotRoot instructs the runtime not to you pivot_root -func WithNoPivotRoot(_ context.Context, _ *Client, info *TaskInfo) error { - if info.Options == nil { - info.Options = &runctypes.CreateOptions{ - NoPivotRoot: true, - } - return nil - } - copts, ok := info.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("invalid options type, expected runctypes.CreateOptions") - } - copts.NoPivotRoot = true - return nil -} diff --git a/vendor/github.com/containerd/containerd/content/helpers.go b/vendor/github.com/containerd/containerd/content/helpers.go index 819b7ea1e320f..3e231408d55ec 100644 --- a/vendor/github.com/containerd/containerd/content/helpers.go +++ b/vendor/github.com/containerd/containerd/content/helpers.go @@ -70,7 +70,7 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, desc o cw, err := OpenWriter(ctx, cs, WithRef(ref), WithDescriptor(desc)) if err != nil { if !errdefs.IsAlreadyExists(err) { - return err + return errors.Wrap(err, "failed to open writer") } return nil // all ready present @@ -127,7 +127,7 @@ func OpenWriter(ctx context.Context, cs Ingester, opts ...WriterOpt) (Writer, er func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error { ws, err := cw.Status() if err != nil { - return err + return errors.Wrap(err, "failed to get status") } if ws.Offset > 0 { @@ -138,7 +138,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige } if _, err := copyWithBuffer(cw, r); err != nil { - return err + return errors.Wrap(err, "failed to copy") } if err := cw.Commit(ctx, size, expected, opts...); err != nil { diff --git a/vendor/github.com/containerd/containerd/content/local/store.go b/vendor/github.com/containerd/containerd/content/local/store.go index 6df3df6184ce7..7fa9bb736a9e3 100644 --- a/vendor/github.com/containerd/containerd/content/local/store.go +++ b/vendor/github.com/containerd/containerd/content/local/store.go @@ -33,6 +33,8 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/filters" "github.com/containerd/containerd/log" + + "github.com/containerd/continuity" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" @@ -651,5 +653,5 @@ func writeTimestampFile(p string, t time.Time) error { return err } - return ioutil.WriteFile(p, b, 0666) + return continuity.AtomicWriteFile(p, b, 0666) } diff --git a/vendor/github.com/containerd/containerd/content/local/writer.go b/vendor/github.com/containerd/containerd/content/local/writer.go index a6579a9d21027..10df4a4c54084 100644 --- a/vendor/github.com/containerd/containerd/content/local/writer.go +++ b/vendor/github.com/containerd/containerd/content/local/writer.go @@ -132,11 +132,11 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, // clean up!! defer os.RemoveAll(w.path) + if _, err := os.Stat(target); err == nil { + // collision with the target file! + return errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", dgst) + } if err := os.Rename(ingest, target); err != nil { - if os.IsExist(err) { - // collision with the target file! - return errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", dgst) - } return err } commitTime := time.Now() diff --git a/vendor/github.com/containerd/containerd/content/proxy/content_writer.go b/vendor/github.com/containerd/containerd/content/proxy/content_writer.go index 6d35ba61a87c4..5434a156864cd 100644 --- a/vendor/github.com/containerd/containerd/content/proxy/content_writer.go +++ b/vendor/github.com/containerd/containerd/content/proxy/content_writer.go @@ -57,7 +57,7 @@ func (rw *remoteWriter) Status() (content.Status, error) { Action: contentapi.WriteActionStat, }) if err != nil { - return content.Status{}, errors.Wrap(err, "error getting writer status") + return content.Status{}, errors.Wrap(errdefs.FromGRPC(err), "error getting writer status") } return content.Status{ @@ -82,7 +82,7 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) { Data: p, }) if err != nil { - return 0, err + return 0, errors.Wrap(errdefs.FromGRPC(err), "failed to send write") } n = int(resp.Offset - offset) @@ -112,7 +112,7 @@ func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest. Labels: base.Labels, }) if err != nil { - return errdefs.FromGRPC(err) + return errors.Wrap(errdefs.FromGRPC(err), "commit failed") } if size != 0 && resp.Offset != size { diff --git a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go b/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go index 2a1806cf876f7..4619681f45922 100644 --- a/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go +++ b/vendor/github.com/containerd/containerd/contrib/seccomp/seccomp.go @@ -30,7 +30,7 @@ import ( ) // WithProfile receives the name of a file stored on disk comprising a json -// formated seccomp profile, as specified by the opencontainers/runtime-spec. +// formatted seccomp profile, as specified by the opencontainers/runtime-spec. // The profile is read from the file, unmarshaled, and set to the spec. func WithProfile(profile string) oci.SpecOpts { return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { diff --git a/vendor/github.com/containerd/containerd/events/exchange/exchange.go b/vendor/github.com/containerd/containerd/events/exchange/exchange.go index 51c760f04566a..95d21b7df6bfe 100644 --- a/vendor/github.com/containerd/containerd/events/exchange/exchange.go +++ b/vendor/github.com/containerd/containerd/events/exchange/exchange.go @@ -52,7 +52,7 @@ var _ events.Subscriber = &Exchange{} // Forward accepts an envelope to be direcly distributed on the exchange. // -// This is useful when an event is forwaded on behalf of another namespace or +// This is useful when an event is forwarded on behalf of another namespace or // when the event is propagated on behalf of another publisher. func (e *Exchange) Forward(ctx context.Context, envelope *events.Envelope) (err error) { if err := validateEnvelope(envelope); err != nil { diff --git a/vendor/github.com/containerd/containerd/export.go b/vendor/github.com/containerd/containerd/export.go new file mode 100644 index 0000000000000..bfc25316ca943 --- /dev/null +++ b/vendor/github.com/containerd/containerd/export.go @@ -0,0 +1,58 @@ +/* + 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. +*/ + +package containerd + +import ( + "context" + "io" + + "github.com/containerd/containerd/images" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" +) + +type exportOpts struct { +} + +// ExportOpt allows the caller to specify export-specific options +type ExportOpt func(c *exportOpts) error + +func resolveExportOpt(opts ...ExportOpt) (exportOpts, error) { + var eopts exportOpts + for _, o := range opts { + if err := o(&eopts); err != nil { + return eopts, err + } + } + return eopts, nil +} + +// Export exports an image to a Tar stream. +// OCI format is used by default. +// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc. +// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream. +func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocispec.Descriptor, opts ...ExportOpt) (io.ReadCloser, error) { + _, err := resolveExportOpt(opts...) // unused now + if err != nil { + return nil, err + } + pr, pw := io.Pipe() + go func() { + pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed")) + }() + return pr, nil +} diff --git a/vendor/github.com/containerd/containerd/images/archive/importer.go b/vendor/github.com/containerd/containerd/images/archive/importer.go new file mode 100644 index 0000000000000..59514c66a74f3 --- /dev/null +++ b/vendor/github.com/containerd/containerd/images/archive/importer.go @@ -0,0 +1,254 @@ +/* + 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. +*/ + +// Package archive provides a Docker and OCI compatible importer +package archive + +import ( + "archive/tar" + "bytes" + "context" + "encoding/json" + "io" + "io/ioutil" + "path" + + "github.com/containerd/containerd/archive/compression" + "github.com/containerd/containerd/content" + "github.com/containerd/containerd/images" + "github.com/containerd/containerd/log" + digest "github.com/opencontainers/go-digest" + specs "github.com/opencontainers/image-spec/specs-go" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" +) + +// ImportIndex imports an index from a tar achive image bundle +// - implements Docker v1.1, v1.2 and OCI v1. +// - prefers OCI v1 when provided +// - creates OCI index for Docker formats +// - normalizes Docker references and adds as OCI ref name +// e.g. alpine:latest -> docker.io/library/alpine:latest +// - existing OCI reference names are untouched +// - TODO: support option to compress layers on ingest +func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error) { + var ( + tr = tar.NewReader(reader) + + ociLayout ocispec.ImageLayout + mfsts []struct { + Config string + RepoTags []string + Layers []string + } + symlinks = make(map[string]string) + blobs = make(map[string]ocispec.Descriptor) + ) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return ocispec.Descriptor{}, err + } + if hdr.Typeflag == tar.TypeSymlink { + symlinks[hdr.Name] = path.Join(path.Dir(hdr.Name), hdr.Linkname) + } + + if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA { + if hdr.Typeflag != tar.TypeDir { + log.G(ctx).WithField("file", hdr.Name).Debug("file type ignored") + } + continue + } + + hdrName := path.Clean(hdr.Name) + if hdrName == ocispec.ImageLayoutFile { + if err = onUntarJSON(tr, &ociLayout); err != nil { + return ocispec.Descriptor{}, errors.Wrapf(err, "untar oci layout %q", hdr.Name) + } + } else if hdrName == "manifest.json" { + if err = onUntarJSON(tr, &mfsts); err != nil { + return ocispec.Descriptor{}, errors.Wrapf(err, "untar manifest %q", hdr.Name) + } + } else { + dgst, err := onUntarBlob(ctx, tr, store, hdr.Size, "tar-"+hdrName) + if err != nil { + return ocispec.Descriptor{}, errors.Wrapf(err, "failed to ingest %q", hdr.Name) + } + + blobs[hdrName] = ocispec.Descriptor{ + Digest: dgst, + Size: hdr.Size, + } + } + } + + // If OCI layout was given, interpret the tar as an OCI layout. + // When not provided, the layout of the tar will be interpretted + // as Docker v1.1 or v1.2. + if ociLayout.Version != "" { + if ociLayout.Version != ocispec.ImageLayoutVersion { + return ocispec.Descriptor{}, errors.Errorf("unsupported OCI version %s", ociLayout.Version) + } + + idx, ok := blobs["index.json"] + if !ok { + return ocispec.Descriptor{}, errors.Errorf("missing index.json in OCI layout %s", ocispec.ImageLayoutVersion) + } + + idx.MediaType = ocispec.MediaTypeImageIndex + return idx, nil + } + + for name, linkname := range symlinks { + desc, ok := blobs[linkname] + if !ok { + return ocispec.Descriptor{}, errors.Errorf("no target for symlink layer from %q to %q", name, linkname) + } + blobs[name] = desc + } + + var idx ocispec.Index + for _, mfst := range mfsts { + config, ok := blobs[mfst.Config] + if !ok { + return ocispec.Descriptor{}, errors.Errorf("image config %q not found", mfst.Config) + } + config.MediaType = ocispec.MediaTypeImageConfig + + layers, err := resolveLayers(ctx, store, mfst.Layers, blobs) + if err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "failed to resolve layers") + } + + manifest := ocispec.Manifest{ + Versioned: specs.Versioned{ + SchemaVersion: 2, + }, + Config: config, + Layers: layers, + } + + desc, err := writeManifest(ctx, store, manifest, ocispec.MediaTypeImageManifest) + if err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "write docker manifest") + } + + platforms, err := images.Platforms(ctx, store, desc) + if err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "unable to resolve platform") + } + if len(platforms) > 0 { + // Only one platform can be resolved from non-index manifest, + // The platform can only come from the config included above, + // if the config has no platform it can be safely ommitted. + desc.Platform = &platforms[0] + } + + if len(mfst.RepoTags) == 0 { + idx.Manifests = append(idx.Manifests, desc) + } else { + // Add descriptor per tag + for _, ref := range mfst.RepoTags { + mfstdesc := desc + + normalized, err := normalizeReference(ref) + if err != nil { + return ocispec.Descriptor{}, err + } + + mfstdesc.Annotations = map[string]string{ + ocispec.AnnotationRefName: normalized, + } + + idx.Manifests = append(idx.Manifests, mfstdesc) + } + } + } + + return writeManifest(ctx, store, idx, ocispec.MediaTypeImageIndex) +} + +func onUntarJSON(r io.Reader, j interface{}) error { + b, err := ioutil.ReadAll(r) + if err != nil { + return err + } + if err := json.Unmarshal(b, j); err != nil { + return err + } + return nil +} + +func onUntarBlob(ctx context.Context, r io.Reader, store content.Ingester, size int64, ref string) (digest.Digest, error) { + dgstr := digest.Canonical.Digester() + + if err := content.WriteBlob(ctx, store, ref, io.TeeReader(r, dgstr.Hash()), ocispec.Descriptor{Size: size}); err != nil { + return "", err + } + + return dgstr.Digest(), nil +} + +func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor) ([]ocispec.Descriptor, error) { + var layers []ocispec.Descriptor + for _, f := range layerFiles { + desc, ok := blobs[f] + if !ok { + return nil, errors.Errorf("layer %q not found", f) + } + + // Open blob, resolve media type + ra, err := store.ReaderAt(ctx, desc) + if err != nil { + return nil, errors.Wrapf(err, "failed to open %q (%s)", f, desc.Digest) + } + s, err := compression.DecompressStream(content.NewReader(ra)) + if err != nil { + return nil, errors.Wrapf(err, "failed to detect compression for %q", f) + } + if s.GetCompression() == compression.Uncompressed { + // TODO: Support compressing and writing back to content store + desc.MediaType = ocispec.MediaTypeImageLayer + } else { + desc.MediaType = ocispec.MediaTypeImageLayerGzip + } + s.Close() + + layers = append(layers, desc) + } + return layers, nil +} + +func writeManifest(ctx context.Context, cs content.Ingester, manifest interface{}, mediaType string) (ocispec.Descriptor, error) { + manifestBytes, err := json.Marshal(manifest) + if err != nil { + return ocispec.Descriptor{}, err + } + + desc := ocispec.Descriptor{ + MediaType: mediaType, + Digest: digest.FromBytes(manifestBytes), + Size: int64(len(manifestBytes)), + } + if err := content.WriteBlob(ctx, cs, "manifest-"+desc.Digest.String(), bytes.NewReader(manifestBytes), desc); err != nil { + return ocispec.Descriptor{}, err + } + + return desc, nil +} diff --git a/vendor/github.com/containerd/containerd/images/archive/reference.go b/vendor/github.com/containerd/containerd/images/archive/reference.go new file mode 100644 index 0000000000000..0b1310181e426 --- /dev/null +++ b/vendor/github.com/containerd/containerd/images/archive/reference.go @@ -0,0 +1,86 @@ +/* + 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. +*/ + +package archive + +import ( + "strings" + + "github.com/containerd/cri/pkg/util" + digest "github.com/opencontainers/go-digest" + "github.com/pkg/errors" +) + +// FilterRefPrefix restricts references to having the given image +// prefix. Tag-only references will have the prefix prepended. +func FilterRefPrefix(image string) func(string) string { + return refTranslator(image, true) +} + +// AddRefPrefix prepends the given image prefix to tag-only references, +// while leaving returning full references unmodified. +func AddRefPrefix(image string) func(string) string { + return refTranslator(image, false) +} + +// refTranslator creates a reference which only has a tag or verifies +// a full reference. +func refTranslator(image string, checkPrefix bool) func(string) string { + return func(ref string) string { + // Check if ref is full reference + if strings.ContainsAny(ref, "/:@") { + // If not prefixed, don't include image + if checkPrefix && !isImagePrefix(ref, image) { + return "" + } + return ref + } + return image + ":" + ref + } +} + +func isImagePrefix(s, prefix string) bool { + if !strings.HasPrefix(s, prefix) { + return false + } + if len(s) > len(prefix) { + switch s[len(prefix)] { + case '/', ':', '@': + // Prevent matching partial namespaces + default: + return false + } + } + return true +} + +func normalizeReference(ref string) (string, error) { + // TODO: Replace this function to not depend on reference package + normalized, err := util.NormalizeImageRef(ref) + if err != nil { + return "", errors.Wrapf(err, "normalize image ref %q", ref) + } + + return normalized.String(), nil +} + +// DigestTranslator creates a digest reference by adding the +// digest to an image name +func DigestTranslator(prefix string) func(digest.Digest) string { + return func(dgst digest.Digest) string { + return prefix + "@" + dgst.String() + } +} diff --git a/vendor/github.com/containerd/containerd/images/importexport.go b/vendor/github.com/containerd/containerd/images/importexport.go index 04a55fd383fd3..843adcadc7ecf 100644 --- a/vendor/github.com/containerd/containerd/images/importexport.go +++ b/vendor/github.com/containerd/containerd/images/importexport.go @@ -27,7 +27,7 @@ import ( // Importer is the interface for image importer. type Importer interface { // Import imports an image from a tar stream. - Import(ctx context.Context, store content.Store, reader io.Reader) ([]Image, error) + Import(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error) } // Exporter is the interface for image exporter. diff --git a/vendor/github.com/containerd/containerd/import.go b/vendor/github.com/containerd/containerd/import.go index e4ac00cee3c07..3650568240976 100644 --- a/vendor/github.com/containerd/containerd/import.go +++ b/vendor/github.com/containerd/containerd/import.go @@ -18,36 +18,61 @@ package containerd import ( "context" + "encoding/json" "io" + "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/images/archive" + digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) type importOpts struct { + indexName string + imageRefT func(string) string + dgstRefT func(digest.Digest) string } // ImportOpt allows the caller to specify import specific options -type ImportOpt func(c *importOpts) error +type ImportOpt func(*importOpts) error + +// WithImageRefTranslator is used to translate the index reference +// to an image reference for the image store. +func WithImageRefTranslator(f func(string) string) ImportOpt { + return func(c *importOpts) error { + c.imageRefT = f + return nil + } +} -func resolveImportOpt(opts ...ImportOpt) (importOpts, error) { - var iopts importOpts - for _, o := range opts { - if err := o(&iopts); err != nil { - return iopts, err - } +// WithDigestRef is used to create digest images for each +// manifest in the index. +func WithDigestRef(f func(digest.Digest) string) ImportOpt { + return func(c *importOpts) error { + c.dgstRefT = f + return nil + } +} + +// WithIndexName creates a tag pointing to the imported index +func WithIndexName(name string) ImportOpt { + return func(c *importOpts) error { + c.indexName = name + return nil } - return iopts, nil } // Import imports an image from a Tar stream using reader. // Caller needs to specify importer. Future version may use oci.v1 as the default. // Note that unreferrenced blobs may be imported to the content store as well. -func (c *Client) Import(ctx context.Context, importer images.Importer, reader io.Reader, opts ...ImportOpt) ([]Image, error) { - _, err := resolveImportOpt(opts...) // unused now - if err != nil { - return nil, err +func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt) ([]images.Image, error) { + var iopts importOpts + for _, o := range opts { + if err := o(&iopts); err != nil { + return nil, err + } } ctx, done, err := c.WithLease(ctx) @@ -56,63 +81,86 @@ func (c *Client) Import(ctx context.Context, importer images.Importer, reader io } defer done(ctx) - imgrecs, err := importer.Import(ctx, c.ContentStore(), reader) + index, err := archive.ImportIndex(ctx, c.ContentStore(), reader) if err != nil { - // is.Update() is not called on error return nil, err } - is := c.ImageService() - var images []Image - for _, imgrec := range imgrecs { - if updated, err := is.Update(ctx, imgrec, "target"); err != nil { - if !errdefs.IsNotFound(err) { - return nil, err - } + var ( + imgs []images.Image + cs = c.ContentStore() + is = c.ImageService() + ) + + if iopts.indexName != "" { + imgs = append(imgs, images.Image{ + Name: iopts.indexName, + Target: index, + }) + } - created, err := is.Create(ctx, imgrec) - if err != nil { - return nil, err - } + var handler images.HandlerFunc + handler = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + // Only save images at top level + if desc.Digest != index.Digest { + return images.Children(ctx, cs, desc) + } + + p, err := content.ReadBlob(ctx, cs, desc) + if err != nil { + return nil, err + } - imgrec = created - } else { - imgrec = updated + var idx ocispec.Index + if err := json.Unmarshal(p, &idx); err != nil { + return nil, err } - images = append(images, NewImage(c, imgrec)) + for _, m := range idx.Manifests { + if ref := m.Annotations[ocispec.AnnotationRefName]; ref != "" { + if iopts.imageRefT != nil { + ref = iopts.imageRefT(ref) + } + if ref != "" { + imgs = append(imgs, images.Image{ + Name: ref, + Target: m, + }) + } + } + if iopts.dgstRefT != nil { + ref := iopts.dgstRefT(m.Digest) + if ref != "" { + imgs = append(imgs, images.Image{ + Name: ref, + Target: m, + }) + } + } + } + + return idx.Manifests, nil } - return images, nil -} -type exportOpts struct { -} + handler = images.SetChildrenLabels(cs, handler) + if err := images.Walk(ctx, handler, index); err != nil { + return nil, err + } -// ExportOpt allows the caller to specify export-specific options -type ExportOpt func(c *exportOpts) error + for i := range imgs { + img, err := is.Update(ctx, imgs[i], "target") + if err != nil { + if !errdefs.IsNotFound(err) { + return nil, err + } -func resolveExportOpt(opts ...ExportOpt) (exportOpts, error) { - var eopts exportOpts - for _, o := range opts { - if err := o(&eopts); err != nil { - return eopts, err + img, err = is.Create(ctx, imgs[i]) + if err != nil { + return nil, err + } } + imgs[i] = img } - return eopts, nil -} -// Export exports an image to a Tar stream. -// OCI format is used by default. -// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc. -// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream. -func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocispec.Descriptor, opts ...ExportOpt) (io.ReadCloser, error) { - _, err := resolveExportOpt(opts...) // unused now - if err != nil { - return nil, err - } - pr, pw := io.Pipe() - go func() { - pw.CloseWithError(exporter.Export(ctx, c.ContentStore(), desc, pw)) - }() - return pr, nil + return imgs, nil } diff --git a/vendor/github.com/containerd/containerd/install.go b/vendor/github.com/containerd/containerd/install.go index 2aa8b039469be..5e4c6a2c8d40e 100644 --- a/vendor/github.com/containerd/containerd/install.go +++ b/vendor/github.com/containerd/containerd/install.go @@ -33,25 +33,14 @@ import ( // Install a binary image into the opt service func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts) error { - resp, err := c.IntrospectionService().Plugins(ctx, &introspectionapi.PluginsRequest{ - Filters: []string{ - "id==opt", - }, - }) - if err != nil { - return err - } - if len(resp.Plugins) != 1 { - return errors.New("opt service not enabled") - } - path := resp.Plugins[0].Exports["path"] - if path == "" { - return errors.New("opt path not exported") - } var config InstallConfig for _, o := range opts { o(&config) } + path, err := c.getInstallPath(ctx, config) + if err != nil { + return err + } var ( cs = image.ContentStore() platform = platforms.Default() @@ -89,3 +78,25 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts) } return nil } + +func (c *Client) getInstallPath(ctx context.Context, config InstallConfig) (string, error) { + if config.Path != "" { + return config.Path, nil + } + resp, err := c.IntrospectionService().Plugins(ctx, &introspectionapi.PluginsRequest{ + Filters: []string{ + "id==opt", + }, + }) + if err != nil { + return "", err + } + if len(resp.Plugins) != 1 { + return "", errors.New("opt service not enabled") + } + path := resp.Plugins[0].Exports["path"] + if path == "" { + return "", errors.New("opt path not exported") + } + return path, nil +} diff --git a/vendor/github.com/containerd/containerd/install_opts.go b/vendor/github.com/containerd/containerd/install_opts.go index b11e7f3d6d0fe..b0c9213cb277a 100644 --- a/vendor/github.com/containerd/containerd/install_opts.go +++ b/vendor/github.com/containerd/containerd/install_opts.go @@ -25,6 +25,8 @@ type InstallConfig struct { Libs bool // Replace will overwrite existing binaries or libs in the opt directory Replace bool + // Path to install libs and binaries to + Path string } // WithInstallLibs installs libs from the image @@ -36,3 +38,10 @@ func WithInstallLibs(c *InstallConfig) { func WithInstallReplace(c *InstallConfig) { c.Replace = true } + +// WithInstallPath sets the optional install path +func WithInstallPath(path string) InstallOpts { + return func(c *InstallConfig) { + c.Path = path + } +} diff --git a/vendor/github.com/containerd/containerd/metadata/bolt.go b/vendor/github.com/containerd/containerd/metadata/bolt.go index 156a33593f43c..6ea4608663612 100644 --- a/vendor/github.com/containerd/containerd/metadata/bolt.go +++ b/vendor/github.com/containerd/containerd/metadata/bolt.go @@ -19,8 +19,8 @@ package metadata import ( "context" - "github.com/boltdb/bolt" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type transactionKey struct{} diff --git a/vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go b/vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go index 4b2ede8763605..1240188577be1 100644 --- a/vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go +++ b/vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go @@ -19,8 +19,8 @@ package boltutil import ( "time" - "github.com/boltdb/bolt" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) var ( diff --git a/vendor/github.com/containerd/containerd/metadata/buckets.go b/vendor/github.com/containerd/containerd/metadata/buckets.go index fcf4c29597f3d..51d40a7f36017 100644 --- a/vendor/github.com/containerd/containerd/metadata/buckets.go +++ b/vendor/github.com/containerd/containerd/metadata/buckets.go @@ -17,11 +17,11 @@ package metadata import ( - "github.com/boltdb/bolt" digest "github.com/opencontainers/go-digest" + bolt "go.etcd.io/bbolt" ) -// The layout where a "/" delineates a bucket is desribed in the following +// The layout where a "/" delineates a bucket is described in the following // section. Please try to follow this as closely as possible when adding // functionality. We can bolster this with helpers and more structure if that // becomes an issue. @@ -164,11 +164,11 @@ func getSnapshotterBucket(tx *bolt.Tx, namespace, snapshotter string) *bolt.Buck } func createBlobBucket(tx *bolt.Tx, namespace string, dgst digest.Digest) (*bolt.Bucket, error) { - bkt, err := createBucketIfNotExists(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectContent, bucketKeyObjectBlob, []byte(dgst.String())) + bkt, err := createBucketIfNotExists(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectContent, bucketKeyObjectBlob) if err != nil { return nil, err } - return bkt, nil + return bkt.CreateBucket([]byte(dgst.String())) } func getBlobsBucket(tx *bolt.Tx, namespace string) *bolt.Bucket { diff --git a/vendor/github.com/containerd/containerd/metadata/containers.go b/vendor/github.com/containerd/containerd/metadata/containers.go index 2c9726fc27349..6e5622c36f577 100644 --- a/vendor/github.com/containerd/containerd/metadata/containers.go +++ b/vendor/github.com/containerd/containerd/metadata/containers.go @@ -21,7 +21,6 @@ import ( "strings" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/filters" @@ -32,6 +31,7 @@ import ( "github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/types" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type containerStore struct { diff --git a/vendor/github.com/containerd/containerd/metadata/content.go b/vendor/github.com/containerd/containerd/metadata/content.go index 7293f1bfae29d..ac4440060b820 100644 --- a/vendor/github.com/containerd/containerd/metadata/content.go +++ b/vendor/github.com/containerd/containerd/metadata/content.go @@ -23,7 +23,6 @@ import ( "sync" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/filters" @@ -34,6 +33,7 @@ import ( digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type contentStore struct { @@ -592,9 +592,6 @@ func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, } size = nw.desc.Size actual = nw.desc.Digest - if getBlobBucket(tx, nw.namespace, actual) != nil { - return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual) - } } else { status, err := nw.w.Status() if err != nil { @@ -606,18 +603,16 @@ func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, size = status.Offset actual = nw.w.Digest() - if err := nw.w.Commit(ctx, size, expected); err != nil { - if !errdefs.IsAlreadyExists(err) { - return "", err - } - if getBlobBucket(tx, nw.namespace, actual) != nil { - return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual) - } + if err := nw.w.Commit(ctx, size, expected); err != nil && !errdefs.IsAlreadyExists(err) { + return "", err } } bkt, err := createBlobBucket(tx, nw.namespace, actual) if err != nil { + if err == bolt.ErrBucketExists { + return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual) + } return "", err } diff --git a/vendor/github.com/containerd/containerd/metadata/db.go b/vendor/github.com/containerd/containerd/metadata/db.go index 0ea8ad78ff731..507d6d22d0110 100644 --- a/vendor/github.com/containerd/containerd/metadata/db.go +++ b/vendor/github.com/containerd/containerd/metadata/db.go @@ -23,12 +23,12 @@ import ( "sync" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/content" "github.com/containerd/containerd/gc" "github.com/containerd/containerd/log" "github.com/containerd/containerd/snapshots" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) const ( @@ -43,7 +43,7 @@ const ( // dbVersion represents updates to the schema // version which are additions and compatible with // prior version of the same schema. - dbVersion = 2 + dbVersion = 3 ) // DB represents a metadata database backed by a bolt diff --git a/vendor/github.com/containerd/containerd/metadata/gc.go b/vendor/github.com/containerd/containerd/metadata/gc.go index eb4d0c7c339ba..a670ce1a3e097 100644 --- a/vendor/github.com/containerd/containerd/metadata/gc.go +++ b/vendor/github.com/containerd/containerd/metadata/gc.go @@ -23,10 +23,10 @@ import ( "strings" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/gc" "github.com/containerd/containerd/log" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) const ( diff --git a/vendor/github.com/containerd/containerd/metadata/images.go b/vendor/github.com/containerd/containerd/metadata/images.go index 62b1179cd33b6..6ae9dc85541c9 100644 --- a/vendor/github.com/containerd/containerd/metadata/images.go +++ b/vendor/github.com/containerd/containerd/metadata/images.go @@ -23,7 +23,6 @@ import ( "strings" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/filters" "github.com/containerd/containerd/images" @@ -33,6 +32,7 @@ import ( digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type imageStore struct { diff --git a/vendor/github.com/containerd/containerd/metadata/leases.go b/vendor/github.com/containerd/containerd/metadata/leases.go index 8835065d1ea4b..635c3b3c37e4e 100644 --- a/vendor/github.com/containerd/containerd/metadata/leases.go +++ b/vendor/github.com/containerd/containerd/metadata/leases.go @@ -20,7 +20,6 @@ import ( "context" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/filters" "github.com/containerd/containerd/leases" @@ -28,6 +27,7 @@ import ( "github.com/containerd/containerd/namespaces" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) // LeaseManager manages the create/delete lifecyle of leases diff --git a/vendor/github.com/containerd/containerd/metadata/migrations.go b/vendor/github.com/containerd/containerd/metadata/migrations.go index 3ffda6b3bfd84..34febdd159650 100644 --- a/vendor/github.com/containerd/containerd/metadata/migrations.go +++ b/vendor/github.com/containerd/containerd/metadata/migrations.go @@ -16,7 +16,7 @@ package metadata -import "github.com/boltdb/bolt" +import bolt "go.etcd.io/bbolt" type migration struct { schema string @@ -45,6 +45,11 @@ var migrations = []migration{ version: 2, migrate: migrateIngests, }, + { + schema: "v1", + version: 3, + migrate: noOpMigration, + }, } // addChildLinks Adds children key to the snapshotters to enforce snapshot @@ -154,3 +159,10 @@ func migrateIngests(tx *bolt.Tx) error { return nil } + +// noOpMigration was for a database change from boltdb/bolt which is no +// longer being supported, to go.etcd.io/bbolt which is the currently +// maintained repo for boltdb. +func noOpMigration(tx *bolt.Tx) error { + return nil +} diff --git a/vendor/github.com/containerd/containerd/metadata/namespaces.go b/vendor/github.com/containerd/containerd/metadata/namespaces.go index 000bef6c9cf56..74951eb5c5b62 100644 --- a/vendor/github.com/containerd/containerd/metadata/namespaces.go +++ b/vendor/github.com/containerd/containerd/metadata/namespaces.go @@ -19,11 +19,11 @@ package metadata import ( "context" - "github.com/boltdb/bolt" "github.com/containerd/containerd/errdefs" l "github.com/containerd/containerd/labels" "github.com/containerd/containerd/namespaces" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type namespaceStore struct { diff --git a/vendor/github.com/containerd/containerd/metadata/snapshot.go b/vendor/github.com/containerd/containerd/metadata/snapshot.go index fda380a6abc78..75b80b0bc59c3 100644 --- a/vendor/github.com/containerd/containerd/metadata/snapshot.go +++ b/vendor/github.com/containerd/containerd/metadata/snapshot.go @@ -23,7 +23,6 @@ import ( "sync" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/labels" "github.com/containerd/containerd/log" @@ -32,6 +31,7 @@ import ( "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/snapshots" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type snapshotter struct { diff --git a/vendor/github.com/containerd/containerd/mount/mount_windows.go b/vendor/github.com/containerd/containerd/mount/mount_windows.go index f7c97894b4377..5de25c4e0a8f0 100644 --- a/vendor/github.com/containerd/containerd/mount/mount_windows.go +++ b/vendor/github.com/containerd/containerd/mount/mount_windows.go @@ -32,6 +32,10 @@ var ( // Mount to the provided target func (m *Mount) Mount(target string) error { + if m.Type != "windows-layer" { + return errors.Errorf("invalid windows mount type: '%s'", m.Type) + } + home, layerID := filepath.Split(m.Source) parentLayerPaths, err := m.GetParentPaths() diff --git a/vendor/github.com/containerd/containerd/oci/spec.go b/vendor/github.com/containerd/containerd/oci/spec.go index ffd0bffca0821..b83f40ac65a31 100644 --- a/vendor/github.com/containerd/containerd/oci/spec.go +++ b/vendor/github.com/containerd/containerd/oci/spec.go @@ -18,11 +18,27 @@ package oci import ( "context" + "path/filepath" + "runtime" + + "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/containers" specs "github.com/opencontainers/runtime-spec/specs-go" ) +const ( + rwm = "rwm" + defaultRootfsPath = "rootfs" +) + +var ( + defaultUnixEnv = []string{ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + } +) + // Spec is a type alias to the OCI runtime spec to allow third part SpecOpts // to be created without the "issues" with go vendoring and package imports type Spec = specs.Spec @@ -30,12 +46,36 @@ type Spec = specs.Spec // GenerateSpec will generate a default spec from the provided image // for use as a containerd container func GenerateSpec(ctx context.Context, client Client, c *containers.Container, opts ...SpecOpts) (*Spec, error) { - s, err := createDefaultSpec(ctx, c.ID) - if err != nil { + return GenerateSpecWithPlatform(ctx, client, platforms.DefaultString(), c, opts...) +} + +// GenerateSpecWithPlatform will generate a default spec from the provided image +// for use as a containerd container in the platform requested. +func GenerateSpecWithPlatform(ctx context.Context, client Client, platform string, c *containers.Container, opts ...SpecOpts) (*Spec, error) { + var s Spec + if err := generateDefaultSpecWithPlatform(ctx, platform, c.ID, &s); err != nil { return nil, err } - return s, ApplyOpts(ctx, client, c, s, opts...) + return &s, ApplyOpts(ctx, client, c, &s, opts...) +} + +func generateDefaultSpecWithPlatform(ctx context.Context, platform, id string, s *Spec) error { + plat, err := platforms.Parse(platform) + if err != nil { + return err + } + + if plat.OS == "windows" { + err = populateDefaultWindowsSpec(ctx, s, id) + } else { + err = populateDefaultUnixSpec(ctx, s, id) + if err == nil && runtime.GOOS == "windows" { + // To run LCOW we have a Linux and Windows section. Add an empty one now. + s.Windows = &specs.Windows{} + } + } + return err } // ApplyOpts applys the options to the given spec, injecting data from the @@ -50,7 +90,174 @@ func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *S return nil } -func createDefaultSpec(ctx context.Context, id string) (*Spec, error) { - var s Spec - return &s, populateDefaultSpec(ctx, &s, id) +func defaultUnixCaps() []string { + return []string{ + "CAP_CHOWN", + "CAP_DAC_OVERRIDE", + "CAP_FSETID", + "CAP_FOWNER", + "CAP_MKNOD", + "CAP_NET_RAW", + "CAP_SETGID", + "CAP_SETUID", + "CAP_SETFCAP", + "CAP_SETPCAP", + "CAP_NET_BIND_SERVICE", + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE", + } +} + +func defaultUnixNamespaces() []specs.LinuxNamespace { + return []specs.LinuxNamespace{ + { + Type: specs.PIDNamespace, + }, + { + Type: specs.IPCNamespace, + }, + { + Type: specs.UTSNamespace, + }, + { + Type: specs.MountNamespace, + }, + { + Type: specs.NetworkNamespace, + }, + } +} + +func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error { + ns, err := namespaces.NamespaceRequired(ctx) + if err != nil { + return err + } + + *s = Spec{ + Version: specs.Version, + Root: &specs.Root{ + Path: defaultRootfsPath, + }, + Process: &specs.Process{ + Env: defaultUnixEnv, + Cwd: "/", + NoNewPrivileges: true, + User: specs.User{ + UID: 0, + GID: 0, + }, + Capabilities: &specs.LinuxCapabilities{ + Bounding: defaultUnixCaps(), + Permitted: defaultUnixCaps(), + Inheritable: defaultUnixCaps(), + Effective: defaultUnixCaps(), + }, + Rlimits: []specs.POSIXRlimit{ + { + Type: "RLIMIT_NOFILE", + Hard: uint64(1024), + Soft: uint64(1024), + }, + }, + }, + Mounts: []specs.Mount{ + { + Destination: "/proc", + Type: "proc", + Source: "proc", + Options: []string{"nosuid", "noexec", "nodev"}, + }, + { + Destination: "/dev", + Type: "tmpfs", + Source: "tmpfs", + Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, + }, + { + Destination: "/dev/pts", + Type: "devpts", + Source: "devpts", + Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"}, + }, + { + Destination: "/dev/shm", + Type: "tmpfs", + Source: "shm", + Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"}, + }, + { + Destination: "/dev/mqueue", + Type: "mqueue", + Source: "mqueue", + Options: []string{"nosuid", "noexec", "nodev"}, + }, + { + Destination: "/sys", + Type: "sysfs", + Source: "sysfs", + Options: []string{"nosuid", "noexec", "nodev", "ro"}, + }, + { + Destination: "/run", + Type: "tmpfs", + Source: "tmpfs", + Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, + }, + }, + Linux: &specs.Linux{ + MaskedPaths: []string{ + "/proc/acpi", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/sys/firmware", + "/proc/scsi", + }, + ReadonlyPaths: []string{ + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger", + }, + CgroupsPath: filepath.Join("/", ns, id), + Resources: &specs.LinuxResources{ + Devices: []specs.LinuxDeviceCgroup{ + { + Allow: false, + Access: rwm, + }, + }, + }, + Namespaces: defaultUnixNamespaces(), + }, + } + return nil +} + +func populateDefaultWindowsSpec(ctx context.Context, s *Spec, id string) error { + *s = Spec{ + Version: specs.Version, + Root: &specs.Root{}, + Process: &specs.Process{ + Cwd: `C:\`, + ConsoleSize: &specs.Box{ + Width: 80, + Height: 20, + }, + }, + Windows: &specs.Windows{ + IgnoreFlushesDuringBoot: true, + Network: &specs.WindowsNetwork{ + AllowUnqualifiedDNSQuery: true, + }, + }, + } + return nil } diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts.go b/vendor/github.com/containerd/containerd/oci/spec_opts.go index fd2cfb0392d05..a1694cbcfc5b6 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts.go +++ b/vendor/github.com/containerd/containerd/oci/spec_opts.go @@ -19,12 +19,25 @@ package oci import ( "context" "encoding/json" + "fmt" "io/ioutil" + "os" + "path/filepath" + "strconv" "strings" "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/content" + "github.com/containerd/containerd/images" + "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/platforms" + "github.com/containerd/continuity/fs" + "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/runc/libcontainer/user" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" + "github.com/syndtr/gocapability/capability" ) // SpecOpts sets spec specific information to a newly generated OCI spec @@ -49,13 +62,45 @@ func setProcess(s *Spec) { } } +// setRoot sets Root to empty if unset +func setRoot(s *Spec) { + if s.Root == nil { + s.Root = &specs.Root{} + } +} + +// setLinux sets Linux to empty if unset +func setLinux(s *Spec) { + if s.Linux == nil { + s.Linux = &specs.Linux{} + } +} + +// setCapabilities sets Linux Capabilities to empty if unset +func setCapabilities(s *Spec) { + setProcess(s) + if s.Process.Capabilities == nil { + s.Process.Capabilities = &specs.LinuxCapabilities{} + } +} + // WithDefaultSpec returns a SpecOpts that will populate the spec with default // values. // // Use as the first option to clear the spec, then apply options afterwards. func WithDefaultSpec() SpecOpts { return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { - return populateDefaultSpec(ctx, s, c.ID) + return generateDefaultSpecWithPlatform(ctx, platforms.DefaultString(), c.ID, s) + } +} + +// WithDefaultSpecForPlatform returns a SpecOpts that will populate the spec +// with default values for a given platform. +// +// Use as the first option to clear the spec, then apply options afterwards. +func WithDefaultSpecForPlatform(platform string) SpecOpts { + return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { + return generateDefaultSpecWithPlatform(ctx, platform, c.ID, s) } } @@ -81,6 +126,55 @@ func WithSpecFromFile(filename string) SpecOpts { } } +// WithEnv appends environment variables +func WithEnv(environmentVariables []string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + if len(environmentVariables) > 0 { + setProcess(s) + s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, environmentVariables) + } + return nil + } +} + +// replaceOrAppendEnvValues returns the defaults with the overrides either +// replaced by env key or appended to the list +func replaceOrAppendEnvValues(defaults, overrides []string) []string { + cache := make(map[string]int, len(defaults)) + for i, e := range defaults { + parts := strings.SplitN(e, "=", 2) + cache[parts[0]] = i + } + + for _, value := range overrides { + // Values w/o = means they want this env to be removed/unset. + if !strings.Contains(value, "=") { + if i, exists := cache[value]; exists { + defaults[i] = "" // Used to indicate it should be removed + } + continue + } + + // Just do a normal set/update + parts := strings.SplitN(value, "=", 2) + if i, exists := cache[parts[0]]; exists { + defaults[i] = value + } else { + defaults = append(defaults, value) + } + } + + // Now remove all entries that we want to "unset" + for i := 0; i < len(defaults); i++ { + if defaults[i] == "" { + defaults = append(defaults[:i], defaults[i+1:]...) + i-- + } + } + + return defaults +} + // WithProcessArgs replaces the args on the generated spec func WithProcessArgs(args ...string) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { @@ -99,6 +193,32 @@ func WithProcessCwd(cwd string) SpecOpts { } } +// WithTTY sets the information on the spec as well as the environment variables for +// using a TTY +func WithTTY(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + s.Process.Terminal = true + if s.Linux != nil { + s.Process.Env = append(s.Process.Env, "TERM=xterm") + } + + return nil +} + +// WithTTYSize sets the information on the spec as well as the environment variables for +// using a TTY +func WithTTYSize(width, height int) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + if s.Process.ConsoleSize == nil { + s.Process.ConsoleSize = &specs.Box{} + } + s.Process.ConsoleSize.Width = uint(width) + s.Process.ConsoleSize.Height = uint(height) + return nil + } +} + // WithHostname sets the container's hostname func WithHostname(name string) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { @@ -107,59 +227,787 @@ func WithHostname(name string) SpecOpts { } } -// WithEnv appends environment variables -func WithEnv(environmentVariables []string) SpecOpts { +// WithMounts appends mounts +func WithMounts(mounts []specs.Mount) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - if len(environmentVariables) > 0 { - setProcess(s) - s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, environmentVariables) + s.Mounts = append(s.Mounts, mounts...) + return nil + } +} + +// WithHostNamespace allows a task to run inside the host's linux namespace +func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + for i, n := range s.Linux.Namespaces { + if n.Type == ns { + s.Linux.Namespaces = append(s.Linux.Namespaces[:i], s.Linux.Namespaces[i+1:]...) + return nil + } } return nil } } -// WithMounts appends mounts -func WithMounts(mounts []specs.Mount) SpecOpts { +// WithLinuxNamespace uses the passed in namespace for the spec. If a namespace of the same type already exists in the +// spec, the existing namespace is replaced by the one provided. +func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts { return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - s.Mounts = append(s.Mounts, mounts...) + setLinux(s) + for i, n := range s.Linux.Namespaces { + if n.Type == ns.Type { + before := s.Linux.Namespaces[:i] + after := s.Linux.Namespaces[i+1:] + s.Linux.Namespaces = append(before, ns) + s.Linux.Namespaces = append(s.Linux.Namespaces, after...) + return nil + } + } + s.Linux.Namespaces = append(s.Linux.Namespaces, ns) return nil } } -// replaceOrAppendEnvValues returns the defaults with the overrides either -// replaced by env key or appended to the list -func replaceOrAppendEnvValues(defaults, overrides []string) []string { - cache := make(map[string]int, len(defaults)) - for i, e := range defaults { - parts := strings.SplitN(e, "=", 2) - cache[parts[0]] = i +// WithNewPrivileges turns off the NoNewPrivileges feature flag in the spec +func WithNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + s.Process.NoNewPrivileges = false + + return nil +} + +// WithImageConfig configures the spec to from the configuration of an Image +func WithImageConfig(image Image) SpecOpts { + return WithImageConfigArgs(image, nil) +} + +// WithImageConfigArgs configures the spec to from the configuration of an Image with additional args that +// replaces the CMD of the image +func WithImageConfigArgs(image Image, args []string) SpecOpts { + return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { + ic, err := image.Config(ctx) + if err != nil { + return err + } + var ( + ociimage v1.Image + config v1.ImageConfig + ) + switch ic.MediaType { + case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config: + p, err := content.ReadBlob(ctx, image.ContentStore(), ic) + if err != nil { + return err + } + + if err := json.Unmarshal(p, &ociimage); err != nil { + return err + } + config = ociimage.Config + default: + return fmt.Errorf("unknown image config media type %s", ic.MediaType) + } + + setProcess(s) + if s.Linux != nil { + s.Process.Env = append(s.Process.Env, config.Env...) + cmd := config.Cmd + if len(args) > 0 { + cmd = args + } + s.Process.Args = append(config.Entrypoint, cmd...) + + cwd := config.WorkingDir + if cwd == "" { + cwd = "/" + } + s.Process.Cwd = cwd + if config.User != "" { + if err := WithUser(config.User)(ctx, client, c, s); err != nil { + return err + } + return WithAdditionalGIDs(fmt.Sprintf("%d", s.Process.User.UID))(ctx, client, c, s) + } + // we should query the image's /etc/group for additional GIDs + // even if there is no specified user in the image config + return WithAdditionalGIDs("root")(ctx, client, c, s) + } else if s.Windows != nil { + s.Process.Env = config.Env + s.Process.Args = append(config.Entrypoint, config.Cmd...) + s.Process.User = specs.User{ + Username: config.User, + } + } else { + return errors.New("spec does not contain Linux or Windows section") + } + return nil } +} - for _, value := range overrides { - // Values w/o = means they want this env to be removed/unset. - if !strings.Contains(value, "=") { - if i, exists := cache[value]; exists { - defaults[i] = "" // Used to indicate it should be removed +// WithRootFSPath specifies unmanaged rootfs path. +func WithRootFSPath(path string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setRoot(s) + s.Root.Path = path + // Entrypoint is not set here (it's up to caller) + return nil + } +} + +// WithRootFSReadonly sets specs.Root.Readonly to true +func WithRootFSReadonly() SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setRoot(s) + s.Root.Readonly = true + return nil + } +} + +// WithNoNewPrivileges sets no_new_privileges on the process for the container +func WithNoNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + s.Process.NoNewPrivileges = true + return nil +} + +// WithHostHostsFile bind-mounts the host's /etc/hosts into the container as readonly +func WithHostHostsFile(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + s.Mounts = append(s.Mounts, specs.Mount{ + Destination: "/etc/hosts", + Type: "bind", + Source: "/etc/hosts", + Options: []string{"rbind", "ro"}, + }) + return nil +} + +// WithHostResolvconf bind-mounts the host's /etc/resolv.conf into the container as readonly +func WithHostResolvconf(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + s.Mounts = append(s.Mounts, specs.Mount{ + Destination: "/etc/resolv.conf", + Type: "bind", + Source: "/etc/resolv.conf", + Options: []string{"rbind", "ro"}, + }) + return nil +} + +// WithHostLocaltime bind-mounts the host's /etc/localtime into the container as readonly +func WithHostLocaltime(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + s.Mounts = append(s.Mounts, specs.Mount{ + Destination: "/etc/localtime", + Type: "bind", + Source: "/etc/localtime", + Options: []string{"rbind", "ro"}, + }) + return nil +} + +// WithUserNamespace sets the uid and gid mappings for the task +// this can be called multiple times to add more mappings to the generated spec +func WithUserNamespace(container, host, size uint32) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + var hasUserns bool + setLinux(s) + for _, ns := range s.Linux.Namespaces { + if ns.Type == specs.UserNamespace { + hasUserns = true + break } - continue } + if !hasUserns { + s.Linux.Namespaces = append(s.Linux.Namespaces, specs.LinuxNamespace{ + Type: specs.UserNamespace, + }) + } + mapping := specs.LinuxIDMapping{ + ContainerID: container, + HostID: host, + Size: size, + } + s.Linux.UIDMappings = append(s.Linux.UIDMappings, mapping) + s.Linux.GIDMappings = append(s.Linux.GIDMappings, mapping) + return nil + } +} - // Just do a normal set/update - parts := strings.SplitN(value, "=", 2) - if i, exists := cache[parts[0]]; exists { - defaults[i] = value +// WithCgroup sets the container's cgroup path +func WithCgroup(path string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + s.Linux.CgroupsPath = path + return nil + } +} + +// WithNamespacedCgroup uses the namespace set on the context to create a +// root directory for containers in the cgroup with the id as the subcgroup +func WithNamespacedCgroup() SpecOpts { + return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { + namespace, err := namespaces.NamespaceRequired(ctx) + if err != nil { + return err + } + setLinux(s) + s.Linux.CgroupsPath = filepath.Join("/", namespace, c.ID) + return nil + } +} + +// WithUser sets the user to be used within the container. +// It accepts a valid user string in OCI Image Spec v1.0.0: +// user, uid, user:group, uid:gid, uid:group, user:gid +func WithUser(userstr string) SpecOpts { + return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { + setProcess(s) + parts := strings.Split(userstr, ":") + switch len(parts) { + case 1: + v, err := strconv.Atoi(parts[0]) + if err != nil { + // if we cannot parse as a uint they try to see if it is a username + return WithUsername(userstr)(ctx, client, c, s) + } + return WithUserID(uint32(v))(ctx, client, c, s) + case 2: + var ( + username string + groupname string + ) + var uid, gid uint32 + v, err := strconv.Atoi(parts[0]) + if err != nil { + username = parts[0] + } else { + uid = uint32(v) + } + if v, err = strconv.Atoi(parts[1]); err != nil { + groupname = parts[1] + } else { + gid = uint32(v) + } + if username == "" && groupname == "" { + s.Process.User.UID, s.Process.User.GID = uid, gid + return nil + } + f := func(root string) error { + if username != "" { + user, err := getUserFromPath(root, func(u user.User) bool { + return u.Name == username + }) + if err != nil { + return err + } + uid = uint32(user.Uid) + } + if groupname != "" { + gid, err = getGIDFromPath(root, func(g user.Group) bool { + return g.Name == groupname + }) + if err != nil { + return err + } + } + s.Process.User.UID, s.Process.User.GID = uid, gid + return nil + } + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !isRootfsAbs(s.Root.Path) { + return errors.New("rootfs absolute path is required") + } + return f(s.Root.Path) + } + if c.Snapshotter == "" { + return errors.New("no snapshotter set for container") + } + if c.SnapshotKey == "" { + return errors.New("rootfs snapshot not created for container") + } + snapshotter := client.SnapshotService(c.Snapshotter) + mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) + if err != nil { + return err + } + return mount.WithTempMount(ctx, mounts, f) + default: + return fmt.Errorf("invalid USER value %s", userstr) + } + } +} + +// WithUIDGID allows the UID and GID for the Process to be set +func WithUIDGID(uid, gid uint32) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + s.Process.User.UID = uid + s.Process.User.GID = gid + return nil + } +} + +// WithUserID sets the correct UID and GID for the container based +// on the image's /etc/passwd contents. If /etc/passwd does not exist, +// or uid is not found in /etc/passwd, it sets the requested uid, +// additionally sets the gid to 0, and does not return an error. +func WithUserID(uid uint32) SpecOpts { + return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { + setProcess(s) + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !isRootfsAbs(s.Root.Path) { + return errors.Errorf("rootfs absolute path is required") + } + user, err := getUserFromPath(s.Root.Path, func(u user.User) bool { + return u.Uid == int(uid) + }) + if err != nil { + if os.IsNotExist(err) || err == errNoUsersFound { + s.Process.User.UID, s.Process.User.GID = uid, 0 + return nil + } + return err + } + s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) + return nil + + } + if c.Snapshotter == "" { + return errors.Errorf("no snapshotter set for container") + } + if c.SnapshotKey == "" { + return errors.Errorf("rootfs snapshot not created for container") + } + snapshotter := client.SnapshotService(c.Snapshotter) + mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) + if err != nil { + return err + } + return mount.WithTempMount(ctx, mounts, func(root string) error { + user, err := getUserFromPath(root, func(u user.User) bool { + return u.Uid == int(uid) + }) + if err != nil { + if os.IsNotExist(err) || err == errNoUsersFound { + s.Process.User.UID, s.Process.User.GID = uid, 0 + return nil + } + return err + } + s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) + return nil + }) + } +} + +// WithUsername sets the correct UID and GID for the container +// based on the the image's /etc/passwd contents. If /etc/passwd +// does not exist, or the username is not found in /etc/passwd, +// it returns error. +func WithUsername(username string) SpecOpts { + return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { + setProcess(s) + if s.Linux != nil { + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !isRootfsAbs(s.Root.Path) { + return errors.Errorf("rootfs absolute path is required") + } + user, err := getUserFromPath(s.Root.Path, func(u user.User) bool { + return u.Name == username + }) + if err != nil { + return err + } + s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) + return nil + } + if c.Snapshotter == "" { + return errors.Errorf("no snapshotter set for container") + } + if c.SnapshotKey == "" { + return errors.Errorf("rootfs snapshot not created for container") + } + snapshotter := client.SnapshotService(c.Snapshotter) + mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) + if err != nil { + return err + } + return mount.WithTempMount(ctx, mounts, func(root string) error { + user, err := getUserFromPath(root, func(u user.User) bool { + return u.Name == username + }) + if err != nil { + return err + } + s.Process.User.UID, s.Process.User.GID = uint32(user.Uid), uint32(user.Gid) + return nil + }) + } else if s.Windows != nil { + s.Process.User.Username = username } else { - defaults = append(defaults, value) + return errors.New("spec does not contain Linux or Windows section") } + return nil } +} - // Now remove all entries that we want to "unset" - for i := 0; i < len(defaults); i++ { - if defaults[i] == "" { - defaults = append(defaults[:i], defaults[i+1:]...) - i-- +// WithAdditionalGIDs sets the OCI spec's additionalGids array to any additional groups listed +// for a particular user in the /etc/groups file of the image's root filesystem +// The passed in user can be either a uid or a username. +func WithAdditionalGIDs(userstr string) SpecOpts { + return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { + setProcess(s) + setAdditionalGids := func(root string) error { + var username string + uid, err := strconv.Atoi(userstr) + if err == nil { + user, err := getUserFromPath(root, func(u user.User) bool { + return u.Uid == uid + }) + if err != nil { + if os.IsNotExist(err) || err == errNoUsersFound { + return nil + } + return err + } + username = user.Name + } else { + username = userstr + } + gids, err := getSupplementalGroupsFromPath(root, func(g user.Group) bool { + // we only want supplemental groups + if g.Name == username { + return false + } + for _, entry := range g.List { + if entry == username { + return true + } + } + return false + }) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + s.Process.User.AdditionalGids = gids + return nil } + if c.Snapshotter == "" && c.SnapshotKey == "" { + if !isRootfsAbs(s.Root.Path) { + return errors.Errorf("rootfs absolute path is required") + } + return setAdditionalGids(s.Root.Path) + } + if c.Snapshotter == "" { + return errors.Errorf("no snapshotter set for container") + } + if c.SnapshotKey == "" { + return errors.Errorf("rootfs snapshot not created for container") + } + snapshotter := client.SnapshotService(c.Snapshotter) + mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) + if err != nil { + return err + } + return mount.WithTempMount(ctx, mounts, setAdditionalGids) } +} - return defaults +// WithCapabilities sets Linux capabilities on the process +func WithCapabilities(caps []string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setCapabilities(s) + + s.Process.Capabilities.Bounding = caps + s.Process.Capabilities.Effective = caps + s.Process.Capabilities.Permitted = caps + s.Process.Capabilities.Inheritable = caps + + return nil + } +} + +// WithAllCapabilities sets all linux capabilities for the process +var WithAllCapabilities = WithCapabilities(getAllCapabilities()) + +func getAllCapabilities() []string { + last := capability.CAP_LAST_CAP + // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap + if last == capability.Cap(63) { + last = capability.CAP_BLOCK_SUSPEND + } + var caps []string + for _, cap := range capability.List() { + if cap > last { + continue + } + caps = append(caps, "CAP_"+strings.ToUpper(cap.String())) + } + return caps +} + +// WithAmbientCapabilities set the Linux ambient capabilities for the process +// Ambient capabilities should only be set for non-root users or the caller should +// understand how these capabilities are used and set +func WithAmbientCapabilities(caps []string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setCapabilities(s) + + s.Process.Capabilities.Ambient = caps + return nil + } +} + +var errNoUsersFound = errors.New("no users found") + +func getUserFromPath(root string, filter func(user.User) bool) (user.User, error) { + ppath, err := fs.RootPath(root, "/etc/passwd") + if err != nil { + return user.User{}, err + } + users, err := user.ParsePasswdFileFilter(ppath, filter) + if err != nil { + return user.User{}, err + } + if len(users) == 0 { + return user.User{}, errNoUsersFound + } + return users[0], nil +} + +var errNoGroupsFound = errors.New("no groups found") + +func getGIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err error) { + gpath, err := fs.RootPath(root, "/etc/group") + if err != nil { + return 0, err + } + groups, err := user.ParseGroupFileFilter(gpath, filter) + if err != nil { + return 0, err + } + if len(groups) == 0 { + return 0, errNoGroupsFound + } + g := groups[0] + return uint32(g.Gid), nil +} + +func getSupplementalGroupsFromPath(root string, filter func(user.Group) bool) ([]uint32, error) { + gpath, err := fs.RootPath(root, "/etc/group") + if err != nil { + return []uint32{}, err + } + groups, err := user.ParseGroupFileFilter(gpath, filter) + if err != nil { + return []uint32{}, err + } + if len(groups) == 0 { + // if there are no additional groups; just return an empty set + return []uint32{}, nil + } + addlGids := []uint32{} + for _, grp := range groups { + addlGids = append(addlGids, uint32(grp.Gid)) + } + return addlGids, nil +} + +func isRootfsAbs(root string) bool { + return filepath.IsAbs(root) } + +// WithMaskedPaths sets the masked paths option +func WithMaskedPaths(paths []string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + s.Linux.MaskedPaths = paths + return nil + } +} + +// WithReadonlyPaths sets the read only paths option +func WithReadonlyPaths(paths []string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + s.Linux.ReadonlyPaths = paths + return nil + } +} + +// WithWriteableSysfs makes any sysfs mounts writeable +func WithWriteableSysfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + for i, m := range s.Mounts { + if m.Type == "sysfs" { + var options []string + for _, o := range m.Options { + if o == "ro" { + o = "rw" + } + options = append(options, o) + } + s.Mounts[i].Options = options + } + } + return nil +} + +// WithWriteableCgroupfs makes any cgroup mounts writeable +func WithWriteableCgroupfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + for i, m := range s.Mounts { + if m.Type == "cgroup" { + var options []string + for _, o := range m.Options { + if o == "ro" { + o = "rw" + } + options = append(options, o) + } + s.Mounts[i].Options = options + } + } + return nil +} + +// WithSelinuxLabel sets the process SELinux label +func WithSelinuxLabel(label string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + s.Process.SelinuxLabel = label + return nil + } +} + +// WithApparmorProfile sets the Apparmor profile for the process +func WithApparmorProfile(profile string) SpecOpts { + return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setProcess(s) + s.Process.ApparmorProfile = profile + return nil + } +} + +// WithSeccompUnconfined clears the seccomp profile +func WithSeccompUnconfined(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + s.Linux.Seccomp = nil + return nil +} + +// WithParentCgroupDevices uses the default cgroup setup to inherit the container's parent cgroup's +// allowed and denied devices +func WithParentCgroupDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + if s.Linux.Resources == nil { + s.Linux.Resources = &specs.LinuxResources{} + } + s.Linux.Resources.Devices = nil + return nil +} + +// WithDefaultUnixDevices adds the default devices for unix such as /dev/null, /dev/random to +// the container's resource cgroup spec +func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { + setLinux(s) + if s.Linux.Resources == nil { + s.Linux.Resources = &specs.LinuxResources{} + } + intptr := func(i int64) *int64 { + return &i + } + s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, []specs.LinuxDeviceCgroup{ + { + // "/dev/null", + Type: "c", + Major: intptr(1), + Minor: intptr(3), + Access: rwm, + Allow: true, + }, + { + // "/dev/random", + Type: "c", + Major: intptr(1), + Minor: intptr(8), + Access: rwm, + Allow: true, + }, + { + // "/dev/full", + Type: "c", + Major: intptr(1), + Minor: intptr(7), + Access: rwm, + Allow: true, + }, + { + // "/dev/tty", + Type: "c", + Major: intptr(5), + Minor: intptr(0), + Access: rwm, + Allow: true, + }, + { + // "/dev/zero", + Type: "c", + Major: intptr(1), + Minor: intptr(5), + Access: rwm, + Allow: true, + }, + { + // "/dev/urandom", + Type: "c", + Major: intptr(1), + Minor: intptr(9), + Access: rwm, + Allow: true, + }, + { + // "/dev/console", + Type: "c", + Major: intptr(5), + Minor: intptr(1), + Access: rwm, + Allow: true, + }, + // /dev/pts/ - pts namespaces are "coming soon" + { + Type: "c", + Major: intptr(136), + Access: rwm, + Allow: true, + }, + { + Type: "c", + Major: intptr(5), + Minor: intptr(2), + Access: rwm, + Allow: true, + }, + { + // tuntap + Type: "c", + Major: intptr(10), + Minor: intptr(200), + Access: rwm, + Allow: true, + }, + }...) + return nil +} + +// WithPrivileged sets up options for a privileged container +// TODO(justincormack) device handling +var WithPrivileged = Compose( + WithAllCapabilities, + WithMaskedPaths(nil), + WithReadonlyPaths(nil), + WithWriteableSysfs, + WithWriteableCgroupfs, + WithSelinuxLabel(""), + WithApparmorProfile(""), + WithSeccompUnconfined, +) diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go b/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go deleted file mode 100644 index 592da651d2995..0000000000000 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go +++ /dev/null @@ -1,733 +0,0 @@ -// +build !windows - -/* - 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. -*/ - -package oci - -import ( - "context" - "encoding/json" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/continuity/fs" - "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/runc/libcontainer/user" - specs "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" - "github.com/syndtr/gocapability/capability" -) - -// WithTTY sets the information on the spec as well as the environment variables for -// using a TTY -func WithTTY(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setProcess(s) - s.Process.Terminal = true - s.Process.Env = append(s.Process.Env, "TERM=xterm") - return nil -} - -// setRoot sets Root to empty if unset -func setRoot(s *Spec) { - if s.Root == nil { - s.Root = &specs.Root{} - } -} - -// setLinux sets Linux to empty if unset -func setLinux(s *Spec) { - if s.Linux == nil { - s.Linux = &specs.Linux{} - } -} - -// setCapabilities sets Linux Capabilities to empty if unset -func setCapabilities(s *Spec) { - setProcess(s) - if s.Process.Capabilities == nil { - s.Process.Capabilities = &specs.LinuxCapabilities{} - } -} - -// WithHostNamespace allows a task to run inside the host's linux namespace -func WithHostNamespace(ns specs.LinuxNamespaceType) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - for i, n := range s.Linux.Namespaces { - if n.Type == ns { - s.Linux.Namespaces = append(s.Linux.Namespaces[:i], s.Linux.Namespaces[i+1:]...) - return nil - } - } - return nil - } -} - -// WithLinuxNamespace uses the passed in namespace for the spec. If a namespace of the same type already exists in the -// spec, the existing namespace is replaced by the one provided. -func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - for i, n := range s.Linux.Namespaces { - if n.Type == ns.Type { - before := s.Linux.Namespaces[:i] - after := s.Linux.Namespaces[i+1:] - s.Linux.Namespaces = append(before, ns) - s.Linux.Namespaces = append(s.Linux.Namespaces, after...) - return nil - } - } - s.Linux.Namespaces = append(s.Linux.Namespaces, ns) - return nil - } -} - -// WithImageConfig configures the spec to from the configuration of an Image -func WithImageConfig(image Image) SpecOpts { - return WithImageConfigArgs(image, nil) -} - -// WithImageConfigArgs configures the spec to from the configuration of an Image with additional args that -// replaces the CMD of the image -func WithImageConfigArgs(image Image, args []string) SpecOpts { - return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { - ic, err := image.Config(ctx) - if err != nil { - return err - } - var ( - ociimage v1.Image - config v1.ImageConfig - ) - switch ic.MediaType { - case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config: - p, err := content.ReadBlob(ctx, image.ContentStore(), ic) - if err != nil { - return err - } - - if err := json.Unmarshal(p, &ociimage); err != nil { - return err - } - config = ociimage.Config - default: - return fmt.Errorf("unknown image config media type %s", ic.MediaType) - } - - setProcess(s) - s.Process.Env = append(s.Process.Env, config.Env...) - cmd := config.Cmd - if len(args) > 0 { - cmd = args - } - s.Process.Args = append(config.Entrypoint, cmd...) - - cwd := config.WorkingDir - if cwd == "" { - cwd = "/" - } - s.Process.Cwd = cwd - if config.User != "" { - return WithUser(config.User)(ctx, client, c, s) - } - return nil - } -} - -// WithRootFSPath specifies unmanaged rootfs path. -func WithRootFSPath(path string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setRoot(s) - s.Root.Path = path - // Entrypoint is not set here (it's up to caller) - return nil - } -} - -// WithRootFSReadonly sets specs.Root.Readonly to true -func WithRootFSReadonly() SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setRoot(s) - s.Root.Readonly = true - return nil - } -} - -// WithNoNewPrivileges sets no_new_privileges on the process for the container -func WithNoNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setProcess(s) - s.Process.NoNewPrivileges = true - return nil -} - -// WithHostHostsFile bind-mounts the host's /etc/hosts into the container as readonly -func WithHostHostsFile(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - s.Mounts = append(s.Mounts, specs.Mount{ - Destination: "/etc/hosts", - Type: "bind", - Source: "/etc/hosts", - Options: []string{"rbind", "ro"}, - }) - return nil -} - -// WithHostResolvconf bind-mounts the host's /etc/resolv.conf into the container as readonly -func WithHostResolvconf(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - s.Mounts = append(s.Mounts, specs.Mount{ - Destination: "/etc/resolv.conf", - Type: "bind", - Source: "/etc/resolv.conf", - Options: []string{"rbind", "ro"}, - }) - return nil -} - -// WithHostLocaltime bind-mounts the host's /etc/localtime into the container as readonly -func WithHostLocaltime(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - s.Mounts = append(s.Mounts, specs.Mount{ - Destination: "/etc/localtime", - Type: "bind", - Source: "/etc/localtime", - Options: []string{"rbind", "ro"}, - }) - return nil -} - -// WithUserNamespace sets the uid and gid mappings for the task -// this can be called multiple times to add more mappings to the generated spec -func WithUserNamespace(container, host, size uint32) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - var hasUserns bool - setLinux(s) - for _, ns := range s.Linux.Namespaces { - if ns.Type == specs.UserNamespace { - hasUserns = true - break - } - } - if !hasUserns { - s.Linux.Namespaces = append(s.Linux.Namespaces, specs.LinuxNamespace{ - Type: specs.UserNamespace, - }) - } - mapping := specs.LinuxIDMapping{ - ContainerID: container, - HostID: host, - Size: size, - } - s.Linux.UIDMappings = append(s.Linux.UIDMappings, mapping) - s.Linux.GIDMappings = append(s.Linux.GIDMappings, mapping) - return nil - } -} - -// WithCgroup sets the container's cgroup path -func WithCgroup(path string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - s.Linux.CgroupsPath = path - return nil - } -} - -// WithNamespacedCgroup uses the namespace set on the context to create a -// root directory for containers in the cgroup with the id as the subcgroup -func WithNamespacedCgroup() SpecOpts { - return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { - namespace, err := namespaces.NamespaceRequired(ctx) - if err != nil { - return err - } - setLinux(s) - s.Linux.CgroupsPath = filepath.Join("/", namespace, c.ID) - return nil - } -} - -// WithUser sets the user to be used within the container. -// It accepts a valid user string in OCI Image Spec v1.0.0: -// user, uid, user:group, uid:gid, uid:group, user:gid -func WithUser(userstr string) SpecOpts { - return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { - setProcess(s) - parts := strings.Split(userstr, ":") - switch len(parts) { - case 1: - v, err := strconv.Atoi(parts[0]) - if err != nil { - // if we cannot parse as a uint they try to see if it is a username - return WithUsername(userstr)(ctx, client, c, s) - } - return WithUserID(uint32(v))(ctx, client, c, s) - case 2: - var ( - username string - groupname string - ) - var uid, gid uint32 - v, err := strconv.Atoi(parts[0]) - if err != nil { - username = parts[0] - } else { - uid = uint32(v) - } - if v, err = strconv.Atoi(parts[1]); err != nil { - groupname = parts[1] - } else { - gid = uint32(v) - } - if username == "" && groupname == "" { - s.Process.User.UID, s.Process.User.GID = uid, gid - return nil - } - f := func(root string) error { - if username != "" { - uid, _, err = getUIDGIDFromPath(root, func(u user.User) bool { - return u.Name == username - }) - if err != nil { - return err - } - } - if groupname != "" { - gid, err = getGIDFromPath(root, func(g user.Group) bool { - return g.Name == groupname - }) - if err != nil { - return err - } - } - s.Process.User.UID, s.Process.User.GID = uid, gid - return nil - } - if c.Snapshotter == "" && c.SnapshotKey == "" { - if !isRootfsAbs(s.Root.Path) { - return errors.New("rootfs absolute path is required") - } - return f(s.Root.Path) - } - if c.Snapshotter == "" { - return errors.New("no snapshotter set for container") - } - if c.SnapshotKey == "" { - return errors.New("rootfs snapshot not created for container") - } - snapshotter := client.SnapshotService(c.Snapshotter) - mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) - if err != nil { - return err - } - return mount.WithTempMount(ctx, mounts, f) - default: - return fmt.Errorf("invalid USER value %s", userstr) - } - } -} - -// WithUIDGID allows the UID and GID for the Process to be set -func WithUIDGID(uid, gid uint32) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setProcess(s) - s.Process.User.UID = uid - s.Process.User.GID = gid - return nil - } -} - -// WithUserID sets the correct UID and GID for the container based -// on the image's /etc/passwd contents. If /etc/passwd does not exist, -// or uid is not found in /etc/passwd, it sets the requested uid, -// additionally sets the gid to 0, and does not return an error. -func WithUserID(uid uint32) SpecOpts { - return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { - setProcess(s) - if c.Snapshotter == "" && c.SnapshotKey == "" { - if !isRootfsAbs(s.Root.Path) { - return errors.Errorf("rootfs absolute path is required") - } - uuid, ugid, err := getUIDGIDFromPath(s.Root.Path, func(u user.User) bool { - return u.Uid == int(uid) - }) - if err != nil { - if os.IsNotExist(err) || err == errNoUsersFound { - s.Process.User.UID, s.Process.User.GID = uid, 0 - return nil - } - return err - } - s.Process.User.UID, s.Process.User.GID = uuid, ugid - return nil - - } - if c.Snapshotter == "" { - return errors.Errorf("no snapshotter set for container") - } - if c.SnapshotKey == "" { - return errors.Errorf("rootfs snapshot not created for container") - } - snapshotter := client.SnapshotService(c.Snapshotter) - mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) - if err != nil { - return err - } - return mount.WithTempMount(ctx, mounts, func(root string) error { - uuid, ugid, err := getUIDGIDFromPath(root, func(u user.User) bool { - return u.Uid == int(uid) - }) - if err != nil { - if os.IsNotExist(err) || err == errNoUsersFound { - s.Process.User.UID, s.Process.User.GID = uid, 0 - return nil - } - return err - } - s.Process.User.UID, s.Process.User.GID = uuid, ugid - return nil - }) - } -} - -// WithUsername sets the correct UID and GID for the container -// based on the the image's /etc/passwd contents. If /etc/passwd -// does not exist, or the username is not found in /etc/passwd, -// it returns error. -func WithUsername(username string) SpecOpts { - return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) { - setProcess(s) - if c.Snapshotter == "" && c.SnapshotKey == "" { - if !isRootfsAbs(s.Root.Path) { - return errors.Errorf("rootfs absolute path is required") - } - uid, gid, err := getUIDGIDFromPath(s.Root.Path, func(u user.User) bool { - return u.Name == username - }) - if err != nil { - return err - } - s.Process.User.UID, s.Process.User.GID = uid, gid - return nil - } - if c.Snapshotter == "" { - return errors.Errorf("no snapshotter set for container") - } - if c.SnapshotKey == "" { - return errors.Errorf("rootfs snapshot not created for container") - } - snapshotter := client.SnapshotService(c.Snapshotter) - mounts, err := snapshotter.Mounts(ctx, c.SnapshotKey) - if err != nil { - return err - } - return mount.WithTempMount(ctx, mounts, func(root string) error { - uid, gid, err := getUIDGIDFromPath(root, func(u user.User) bool { - return u.Name == username - }) - if err != nil { - return err - } - s.Process.User.UID, s.Process.User.GID = uid, gid - return nil - }) - } -} - -// WithCapabilities sets Linux capabilities on the process -func WithCapabilities(caps []string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setCapabilities(s) - - s.Process.Capabilities.Bounding = caps - s.Process.Capabilities.Effective = caps - s.Process.Capabilities.Permitted = caps - s.Process.Capabilities.Inheritable = caps - - return nil - } -} - -// WithAllCapabilities sets all linux capabilities for the process -var WithAllCapabilities = WithCapabilities(getAllCapabilities()) - -func getAllCapabilities() []string { - last := capability.CAP_LAST_CAP - // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap - if last == capability.Cap(63) { - last = capability.CAP_BLOCK_SUSPEND - } - var caps []string - for _, cap := range capability.List() { - if cap > last { - continue - } - caps = append(caps, "CAP_"+strings.ToUpper(cap.String())) - } - return caps -} - -// WithAmbientCapabilities set the Linux ambient capabilities for the process -// Ambient capabilities should only be set for non-root users or the caller should -// understand how these capabilities are used and set -func WithAmbientCapabilities(caps []string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setCapabilities(s) - - s.Process.Capabilities.Ambient = caps - return nil - } -} - -var errNoUsersFound = errors.New("no users found") - -func getUIDGIDFromPath(root string, filter func(user.User) bool) (uid, gid uint32, err error) { - ppath, err := fs.RootPath(root, "/etc/passwd") - if err != nil { - return 0, 0, err - } - users, err := user.ParsePasswdFileFilter(ppath, filter) - if err != nil { - return 0, 0, err - } - if len(users) == 0 { - return 0, 0, errNoUsersFound - } - u := users[0] - return uint32(u.Uid), uint32(u.Gid), nil -} - -var errNoGroupsFound = errors.New("no groups found") - -func getGIDFromPath(root string, filter func(user.Group) bool) (gid uint32, err error) { - gpath, err := fs.RootPath(root, "/etc/group") - if err != nil { - return 0, err - } - groups, err := user.ParseGroupFileFilter(gpath, filter) - if err != nil { - return 0, err - } - if len(groups) == 0 { - return 0, errNoGroupsFound - } - g := groups[0] - return uint32(g.Gid), nil -} - -func isRootfsAbs(root string) bool { - return filepath.IsAbs(root) -} - -// WithMaskedPaths sets the masked paths option -func WithMaskedPaths(paths []string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - s.Linux.MaskedPaths = paths - return nil - } -} - -// WithReadonlyPaths sets the read only paths option -func WithReadonlyPaths(paths []string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - s.Linux.ReadonlyPaths = paths - return nil - } -} - -// WithWriteableSysfs makes any sysfs mounts writeable -func WithWriteableSysfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - for i, m := range s.Mounts { - if m.Type == "sysfs" { - var options []string - for _, o := range m.Options { - if o == "ro" { - o = "rw" - } - options = append(options, o) - } - s.Mounts[i].Options = options - } - } - return nil -} - -// WithWriteableCgroupfs makes any cgroup mounts writeable -func WithWriteableCgroupfs(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - for i, m := range s.Mounts { - if m.Type == "cgroup" { - var options []string - for _, o := range m.Options { - if o == "ro" { - o = "rw" - } - options = append(options, o) - } - s.Mounts[i].Options = options - } - } - return nil -} - -// WithSelinuxLabel sets the process SELinux label -func WithSelinuxLabel(label string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setProcess(s) - s.Process.SelinuxLabel = label - return nil - } -} - -// WithApparmorProfile sets the Apparmor profile for the process -func WithApparmorProfile(profile string) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setProcess(s) - s.Process.ApparmorProfile = profile - return nil - } -} - -// WithSeccompUnconfined clears the seccomp profile -func WithSeccompUnconfined(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - s.Linux.Seccomp = nil - return nil -} - -// WithParentCgroupDevices uses the default cgroup setup to inherit the container's parent cgroup's -// allowed and denied devices -func WithParentCgroupDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - if s.Linux.Resources == nil { - s.Linux.Resources = &specs.LinuxResources{} - } - s.Linux.Resources.Devices = nil - return nil -} - -// WithDefaultUnixDevices adds the default devices for unix such as /dev/null, /dev/random to -// the container's resource cgroup spec -func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setLinux(s) - if s.Linux.Resources == nil { - s.Linux.Resources = &specs.LinuxResources{} - } - intptr := func(i int64) *int64 { - return &i - } - s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, []specs.LinuxDeviceCgroup{ - { - // "/dev/null", - Type: "c", - Major: intptr(1), - Minor: intptr(3), - Access: rwm, - Allow: true, - }, - { - // "/dev/random", - Type: "c", - Major: intptr(1), - Minor: intptr(8), - Access: rwm, - Allow: true, - }, - { - // "/dev/full", - Type: "c", - Major: intptr(1), - Minor: intptr(7), - Access: rwm, - Allow: true, - }, - { - // "/dev/tty", - Type: "c", - Major: intptr(5), - Minor: intptr(0), - Access: rwm, - Allow: true, - }, - { - // "/dev/zero", - Type: "c", - Major: intptr(1), - Minor: intptr(5), - Access: rwm, - Allow: true, - }, - { - // "/dev/urandom", - Type: "c", - Major: intptr(1), - Minor: intptr(9), - Access: rwm, - Allow: true, - }, - { - // "/dev/console", - Type: "c", - Major: intptr(5), - Minor: intptr(1), - Access: rwm, - Allow: true, - }, - // /dev/pts/ - pts namespaces are "coming soon" - { - Type: "c", - Major: intptr(136), - Access: rwm, - Allow: true, - }, - { - Type: "c", - Major: intptr(5), - Minor: intptr(2), - Access: rwm, - Allow: true, - }, - { - // tuntap - Type: "c", - Major: intptr(10), - Minor: intptr(200), - Access: rwm, - Allow: true, - }, - }...) - return nil -} - -// WithPrivileged sets up options for a privileged container -// TODO(justincormack) device handling -var WithPrivileged = Compose( - WithAllCapabilities, - WithMaskedPaths(nil), - WithReadonlyPaths(nil), - WithWriteableSysfs, - WithWriteableCgroupfs, - WithSelinuxLabel(""), - WithApparmorProfile(""), - WithSeccompUnconfined, -) diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go b/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go deleted file mode 100644 index 3688a582d29ea..0000000000000 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go +++ /dev/null @@ -1,89 +0,0 @@ -// +build windows - -/* - 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. -*/ - -package oci - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/opencontainers/image-spec/specs-go/v1" - specs "github.com/opencontainers/runtime-spec/specs-go" -) - -// WithImageConfig configures the spec to from the configuration of an Image -func WithImageConfig(image Image) SpecOpts { - return func(ctx context.Context, client Client, _ *containers.Container, s *Spec) error { - setProcess(s) - ic, err := image.Config(ctx) - if err != nil { - return err - } - var ( - ociimage v1.Image - config v1.ImageConfig - ) - switch ic.MediaType { - case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config: - p, err := content.ReadBlob(ctx, image.ContentStore(), ic) - if err != nil { - return err - } - if err := json.Unmarshal(p, &ociimage); err != nil { - return err - } - config = ociimage.Config - default: - return fmt.Errorf("unknown image config media type %s", ic.MediaType) - } - s.Process.Env = config.Env - s.Process.Args = append(config.Entrypoint, config.Cmd...) - s.Process.User = specs.User{ - Username: config.User, - } - return nil - } -} - -// WithTTY sets the information on the spec as well as the environment variables for -// using a TTY -func WithTTY(width, height int) SpecOpts { - return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error { - setProcess(s) - s.Process.Terminal = true - if s.Process.ConsoleSize == nil { - s.Process.ConsoleSize = &specs.Box{} - } - s.Process.ConsoleSize.Width = uint(width) - s.Process.ConsoleSize.Height = uint(height) - return nil - } -} - -// WithUsername sets the username on the process -func WithUsername(username string) SpecOpts { - return func(ctx context.Context, client Client, c *containers.Container, s *Spec) error { - setProcess(s) - s.Process.User.Username = username - return nil - } -} diff --git a/vendor/github.com/containerd/containerd/oci/spec_unix.go b/vendor/github.com/containerd/containerd/oci/spec_unix.go deleted file mode 100644 index cb69434cbaed5..0000000000000 --- a/vendor/github.com/containerd/containerd/oci/spec_unix.go +++ /dev/null @@ -1,188 +0,0 @@ -// +build !windows - -/* - 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. -*/ - -package oci - -import ( - "context" - "path/filepath" - - "github.com/containerd/containerd/namespaces" - specs "github.com/opencontainers/runtime-spec/specs-go" -) - -const ( - rwm = "rwm" - defaultRootfsPath = "rootfs" -) - -var ( - defaultEnv = []string{ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - } -) - -func defaultCaps() []string { - return []string{ - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_FSETID", - "CAP_FOWNER", - "CAP_MKNOD", - "CAP_NET_RAW", - "CAP_SETGID", - "CAP_SETUID", - "CAP_SETFCAP", - "CAP_SETPCAP", - "CAP_NET_BIND_SERVICE", - "CAP_SYS_CHROOT", - "CAP_KILL", - "CAP_AUDIT_WRITE", - } -} - -func defaultNamespaces() []specs.LinuxNamespace { - return []specs.LinuxNamespace{ - { - Type: specs.PIDNamespace, - }, - { - Type: specs.IPCNamespace, - }, - { - Type: specs.UTSNamespace, - }, - { - Type: specs.MountNamespace, - }, - { - Type: specs.NetworkNamespace, - }, - } -} - -func populateDefaultSpec(ctx context.Context, s *Spec, id string) error { - ns, err := namespaces.NamespaceRequired(ctx) - if err != nil { - return err - } - - *s = Spec{ - Version: specs.Version, - Root: &specs.Root{ - Path: defaultRootfsPath, - }, - Process: &specs.Process{ - Env: defaultEnv, - Cwd: "/", - NoNewPrivileges: true, - User: specs.User{ - UID: 0, - GID: 0, - }, - Capabilities: &specs.LinuxCapabilities{ - Bounding: defaultCaps(), - Permitted: defaultCaps(), - Inheritable: defaultCaps(), - Effective: defaultCaps(), - }, - Rlimits: []specs.POSIXRlimit{ - { - Type: "RLIMIT_NOFILE", - Hard: uint64(1024), - Soft: uint64(1024), - }, - }, - }, - Mounts: []specs.Mount{ - { - Destination: "/proc", - Type: "proc", - Source: "proc", - }, - { - Destination: "/dev", - Type: "tmpfs", - Source: "tmpfs", - Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, - }, - { - Destination: "/dev/pts", - Type: "devpts", - Source: "devpts", - Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"}, - }, - { - Destination: "/dev/shm", - Type: "tmpfs", - Source: "shm", - Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"}, - }, - { - Destination: "/dev/mqueue", - Type: "mqueue", - Source: "mqueue", - Options: []string{"nosuid", "noexec", "nodev"}, - }, - { - Destination: "/sys", - Type: "sysfs", - Source: "sysfs", - Options: []string{"nosuid", "noexec", "nodev", "ro"}, - }, - { - Destination: "/run", - Type: "tmpfs", - Source: "tmpfs", - Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, - }, - }, - Linux: &specs.Linux{ - MaskedPaths: []string{ - "/proc/acpi", - "/proc/kcore", - "/proc/keys", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/sys/firmware", - "/proc/scsi", - }, - ReadonlyPaths: []string{ - "/proc/asound", - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger", - }, - CgroupsPath: filepath.Join("/", ns, id), - Resources: &specs.LinuxResources{ - Devices: []specs.LinuxDeviceCgroup{ - { - Allow: false, - Access: rwm, - }, - }, - }, - Namespaces: defaultNamespaces(), - }, - } - return nil -} diff --git a/vendor/github.com/containerd/containerd/platforms/defaults.go b/vendor/github.com/containerd/containerd/platforms/defaults.go index b8d9c8277ffc6..a14d80e58cbf7 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults.go @@ -22,11 +22,6 @@ import ( specs "github.com/opencontainers/image-spec/specs-go/v1" ) -// Default returns the default matcher for the platform. -func Default() MatchComparer { - return Only(DefaultSpec()) -} - // DefaultString returns the default string specifier for the platform. func DefaultString() string { return Format(DefaultSpec()) diff --git a/vendor/github.com/containerd/containerd/oci/spec_windows.go b/vendor/github.com/containerd/containerd/platforms/defaults_unix.go similarity index 54% rename from vendor/github.com/containerd/containerd/oci/spec_windows.go rename to vendor/github.com/containerd/containerd/platforms/defaults_unix.go index d0236585dcad9..e8a7d5ffa0d69 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_windows.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults_unix.go @@ -1,3 +1,5 @@ +// +build !windows + /* Copyright The containerd Authors. @@ -14,31 +16,9 @@ limitations under the License. */ -package oci - -import ( - "context" - - specs "github.com/opencontainers/runtime-spec/specs-go" -) +package platforms -func populateDefaultSpec(ctx context.Context, s *Spec, id string) error { - *s = Spec{ - Version: specs.Version, - Root: &specs.Root{}, - Process: &specs.Process{ - Cwd: `C:\`, - ConsoleSize: &specs.Box{ - Width: 80, - Height: 20, - }, - }, - Windows: &specs.Windows{ - IgnoreFlushesDuringBoot: true, - Network: &specs.WindowsNetwork{ - AllowUnqualifiedDNSQuery: true, - }, - }, - } - return nil +// Default returns the default matcher for the platform. +func Default() MatchComparer { + return Only(DefaultSpec()) } diff --git a/vendor/github.com/containerd/containerd/task_opts_windows.go b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go similarity index 63% rename from vendor/github.com/containerd/containerd/task_opts_windows.go rename to vendor/github.com/containerd/containerd/platforms/defaults_windows.go index 60836bc8facda..0defbd36c0424 100644 --- a/vendor/github.com/containerd/containerd/task_opts_windows.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go @@ -1,3 +1,5 @@ +// +build windows + /* Copyright The containerd Authors. @@ -14,18 +16,16 @@ limitations under the License. */ -package containerd +package platforms import ( - "context" - - specs "github.com/opencontainers/runtime-spec/specs-go" + specs "github.com/opencontainers/image-spec/specs-go/v1" ) -// WithResources sets the provided resources on the spec for task updates -func WithResources(resources *specs.WindowsResources) UpdateTaskOpts { - return func(ctx context.Context, client *Client, r *UpdateTaskInfo) error { - r.Resources = resources - return nil - } +// Default returns the default matcher for the platform. +func Default() MatchComparer { + return Ordered(DefaultSpec(), specs.Platform{ + OS: "linux", + Architecture: "amd64", + }) } diff --git a/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go b/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go index 1509e696cd1a3..4a2ce3c393b4c 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go @@ -117,7 +117,7 @@ func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int } } else { // TODO: Should any cases where use of content range - // without the proper header be considerd? + // without the proper header be considered? // 206 responses? // Discard up to offset diff --git a/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go b/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go index 5a77789537dad..9175b6a7a4935 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go @@ -134,7 +134,7 @@ func (hrs *httpReadSeeker) reader() (io.Reader, error) { // There is an edge case here where offset == size of the content. If // we seek, we will probably get an error for content that cannot be // sought (?). In that case, we should err on committing the content, - // as the length is already satisified but we just return the empty + // as the length is already satisfied but we just return the empty // reader instead. hrs.rc = ioutil.NopCloser(bytes.NewReader([]byte{})) diff --git a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go index 3155d6ec35d88..45ac1933fd9f4 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go @@ -272,8 +272,14 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro return err } - // TODO: Check if blob -> diff id mapping already exists - // TODO: Check if blob empty label exists + reuse, err := c.reuseLabelBlobState(ctx, desc) + if err != nil { + return err + } + + if reuse { + return nil + } ra, err := c.contentStore.ReaderAt(ctx, desc) if err != nil { @@ -343,6 +349,17 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro state := calc.State() + cinfo := content.Info{ + Digest: desc.Digest, + Labels: map[string]string{ + "containerd.io/uncompressed": state.diffID.String(), + }, + } + + if _, err := c.contentStore.Update(ctx, cinfo, "labels.containerd.io/uncompressed"); err != nil { + return errors.Wrap(err, "failed to update uncompressed label") + } + c.mu.Lock() c.blobMap[desc.Digest] = state c.layerBlobs[state.diffID] = desc @@ -351,6 +368,40 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro return nil } +func (c *Converter) reuseLabelBlobState(ctx context.Context, desc ocispec.Descriptor) (bool, error) { + cinfo, err := c.contentStore.Info(ctx, desc.Digest) + if err != nil { + return false, errors.Wrap(err, "failed to get blob info") + } + desc.Size = cinfo.Size + + diffID, ok := cinfo.Labels["containerd.io/uncompressed"] + if !ok { + return false, nil + } + + bState := blobState{empty: false} + + if bState.diffID, err = digest.Parse(diffID); err != nil { + log.G(ctx).WithField("id", desc.Digest).Warnf("failed to parse digest from label containerd.io/uncompressed: %v", diffID) + return false, nil + } + + // NOTE: there is no need to read header to get compression method + // because there are only two kinds of methods. + if bState.diffID == desc.Digest { + desc.MediaType = images.MediaTypeDockerSchema2Layer + } else { + desc.MediaType = images.MediaTypeDockerSchema2LayerGzip + } + + c.mu.Lock() + c.blobMap[desc.Digest] = bState + c.layerBlobs[bState.diffID] = desc + c.mu.Unlock() + return true, nil +} + func (c *Converter) schema1ManifestHistory() ([]ocispec.History, []digest.Digest, error) { if c.pulledManifest == nil { return nil, nil, errors.New("missing schema 1 manifest for conversion") diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go index 9e5261adb3839..96c425dd96837 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec.go @@ -147,7 +147,7 @@ func (e *execProcess) start(ctx context.Context) (err error) { return errors.Wrap(err, "creating new NULL IO") } } else { - if e.io, err = runc.NewPipeIO(e.parent.IoUID, e.parent.IoGID); err != nil { + if e.io, err = runc.NewPipeIO(e.parent.IoUID, e.parent.IoGID, withConditionalIO(e.stdio)); err != nil { return errors.Wrap(err, "failed to create runc io pipes") } } diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go index 617ec0d978554..ac5467552844e 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/exec_state.go @@ -60,11 +60,11 @@ func (s *execCreatedState) Start(ctx context.Context) error { } func (s *execCreatedState) Delete(ctx context.Context) error { - s.p.mu.Lock() - defer s.p.mu.Unlock() if err := s.p.delete(ctx); err != nil { return err } + s.p.mu.Lock() + defer s.p.mu.Unlock() return s.transition("deleted") } @@ -168,11 +168,11 @@ func (s *execStoppedState) Start(ctx context.Context) error { } func (s *execStoppedState) Delete(ctx context.Context) error { - s.p.mu.Lock() - defer s.p.mu.Unlock() if err := s.p.delete(ctx); err != nil { return err } + s.p.mu.Lock() + defer s.p.mu.Unlock() return s.transition("deleted") } diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go index fe11285c7a94d..5bf5f83443d88 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/init.go @@ -123,7 +123,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { return errors.Wrap(err, "creating new NULL IO") } } else { - if p.io, err = runc.NewPipeIO(p.IoUID, p.IoGID); err != nil { + if p.io, err = runc.NewPipeIO(p.IoUID, p.IoGID, withConditionalIO(p.stdio)); err != nil { return errors.Wrap(err, "failed to create OCI runtime io pipes") } } @@ -228,7 +228,7 @@ func (p *Init) Status(ctx context.Context) (string, error) { defer p.mu.Unlock() c, err := p.runtime.State(ctx, p.id) if err != nil { - if os.IsNotExist(err) { + if strings.Contains(err.Error(), "does not exist") { return "stopped", nil } return "", p.runtimeError(err, "OCI runtime state failed") @@ -249,7 +249,6 @@ func (p *Init) setExited(status int) { } func (p *Init) delete(context context.Context) error { - p.KillAll(context) p.wg.Wait() err := p.runtime.Delete(context, p.id, nil) // ignore errors if a runtime has already deleted the process @@ -400,3 +399,11 @@ func (p *Init) runtimeError(rErr error, msg string) error { return errors.Errorf("%s: %s", msg, rMsg) } } + +func withConditionalIO(c proc.Stdio) runc.IOOpt { + return func(o *runc.IOOption) { + o.OpenStdin = c.Stdin != "" + o.OpenStdout = c.Stdout != "" + o.OpenStderr = c.Stderr != "" + } +} diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go index c9b7145c8669f..71f6ee1bb3a60 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/proc/io.go @@ -109,7 +109,6 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w i.dest(fw, fr) } if stdin == "" { - rio.Stdin().Close() return nil } f, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go index 6c08fe9781329..d19b8e5168098 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/runtime.go @@ -26,7 +26,6 @@ import ( "path/filepath" "time" - "github.com/boltdb/bolt" eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/containers" @@ -49,6 +48,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" "golang.org/x/sys/unix" ) @@ -204,7 +204,7 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts log.G(ctx).WithError(err).WithFields(logrus.Fields{ "id": id, "namespace": namespace, - }).Warn("failed to clen up after killed shim") + }).Warn("failed to clean up after killed shim") } } shimopt = ShimRemote(r.config, r.address, cgroup, exitHandler) @@ -248,8 +248,7 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts if err != nil { return nil, errdefs.FromGRPC(err) } - t, err := newTask(id, namespace, int(cr.Pid), s, r.events, - proc.NewRunc(ropts.RuntimeRoot, sopts.Bundle, namespace, rt, ropts.CriuPath, ropts.SystemdCgroup), r.tasks, bundle) + t, err := newTask(id, namespace, int(cr.Pid), s, r.events, r.tasks, bundle) if err != nil { return nil, err } @@ -341,15 +340,8 @@ func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) { } continue } - ropts, err := r.getRuncOptions(ctx, id) - if err != nil { - log.G(ctx).WithError(err).WithField("id", id). - Error("get runtime options") - continue - } - t, err := newTask(id, ns, pid, s, r.events, - proc.NewRunc(ropts.RuntimeRoot, bundle.path, ns, ropts.Runtime, ropts.CriuPath, ropts.SystemdCgroup), r.tasks, bundle) + t, err := newTask(id, ns, pid, s, r.events, r.tasks, bundle) if err != nil { log.G(ctx).WithError(err).Error("loading task type") continue diff --git a/vendor/github.com/containerd/containerd/runtime/v1/linux/task.go b/vendor/github.com/containerd/containerd/runtime/v1/linux/task.go index e90110997eb1e..38da35c085f8f 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/linux/task.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/linux/task.go @@ -31,8 +31,7 @@ import ( "github.com/containerd/containerd/log" "github.com/containerd/containerd/runtime" "github.com/containerd/containerd/runtime/v1/shim/client" - shim "github.com/containerd/containerd/runtime/v1/shim/v1" - runc "github.com/containerd/go-runc" + "github.com/containerd/containerd/runtime/v1/shim/v1" "github.com/containerd/ttrpc" "github.com/containerd/typeurl" "github.com/gogo/protobuf/types" @@ -52,7 +51,7 @@ type Task struct { bundle *bundle } -func newTask(id, namespace string, pid int, shim *client.Client, events *exchange.Exchange, runtime *runc.Runc, list *runtime.TaskList, bundle *bundle) (*Task, error) { +func newTask(id, namespace string, pid int, shim *client.Client, events *exchange.Exchange, list *runtime.TaskList, bundle *bundle) (*Task, error) { var ( err error cg cgroups.Cgroup diff --git a/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go b/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go index c0e7c868a6fbd..d76d5803d6830 100644 --- a/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go +++ b/vendor/github.com/containerd/containerd/runtime/v1/shim/service.go @@ -20,7 +20,9 @@ package shim import ( "context" + "encoding/json" "fmt" + "io/ioutil" "os" "path/filepath" "sync" @@ -41,6 +43,7 @@ import ( runc "github.com/containerd/go-runc" "github.com/containerd/typeurl" ptypes "github.com/gogo/protobuf/types" + specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" @@ -221,19 +224,21 @@ func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteR // DeleteProcess deletes an exec'd process func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessRequest) (*shimapi.DeleteResponse, error) { - s.mu.Lock() - defer s.mu.Unlock() if r.ID == s.id { return nil, status.Errorf(codes.InvalidArgument, "cannot delete init process with DeleteProcess") } + s.mu.Lock() p := s.processes[r.ID] + s.mu.Unlock() if p == nil { return nil, errors.Wrapf(errdefs.ErrNotFound, "process %s", r.ID) } if err := p.Delete(ctx); err != nil { return nil, err } + s.mu.Lock() delete(s.processes, r.ID) + s.mu.Unlock() return &shimapi.DeleteResponse{ ExitStatus: uint32(p.ExitStatus()), ExitedAt: p.ExitedAt(), @@ -507,13 +512,22 @@ func (s *Service) processExits() { func (s *Service) checkProcesses(e runc.Exit) { s.mu.Lock() defer s.mu.Unlock() + + shouldKillAll, err := shouldKillAllOnExit(s.bundle) + if err != nil { + log.G(s.context).WithError(err).Error("failed to check shouldKillAll") + } + for _, p := range s.processes { if p.Pid() == e.Pid { - if ip, ok := p.(*proc.Init); ok { - // Ensure all children are killed - if err := ip.KillAll(s.context); err != nil { - log.G(s.context).WithError(err).WithField("id", ip.ID()). - Error("failed to kill init's children") + + if shouldKillAll { + if ip, ok := p.(*proc.Init); ok { + // Ensure all children are killed + if err := ip.KillAll(s.context); err != nil { + log.G(s.context).WithError(err).WithField("id", ip.ID()). + Error("failed to kill init's children") + } } } p.SetExited(e.Status) @@ -529,6 +543,25 @@ func (s *Service) checkProcesses(e runc.Exit) { } } +func shouldKillAllOnExit(bundlePath string) (bool, error) { + var bundleSpec specs.Spec + bundleConfigContents, err := ioutil.ReadFile(filepath.Join(bundlePath, "config.json")) + if err != nil { + return false, err + } + json.Unmarshal(bundleConfigContents, &bundleSpec) + + if bundleSpec.Linux != nil { + for _, ns := range bundleSpec.Linux.Namespaces { + if ns.Type == specs.PIDNamespace { + return false, nil + } + } + } + + return true, nil +} + func (s *Service) getContainerPids(ctx context.Context, id string) ([]uint32, error) { s.mu.Lock() defer s.mu.Unlock() diff --git a/vendor/github.com/containerd/containerd/services/server/server.go b/vendor/github.com/containerd/containerd/services/server/server.go index 3b2852e429d09..ed10766f3d9c1 100644 --- a/vendor/github.com/containerd/containerd/services/server/server.go +++ b/vendor/github.com/containerd/containerd/services/server/server.go @@ -29,7 +29,6 @@ import ( "sync" "time" - "github.com/boltdb/bolt" csapi "github.com/containerd/containerd/api/services/content/v1" ssapi "github.com/containerd/containerd/api/services/snapshots/v1" "github.com/containerd/containerd/content" @@ -46,6 +45,7 @@ import ( metrics "github.com/docker/go-metrics" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" "google.golang.org/grpc" ) diff --git a/vendor/github.com/containerd/containerd/sys/socket_unix.go b/vendor/github.com/containerd/containerd/sys/socket_unix.go index 0dbca0e333580..90fa55c482f96 100644 --- a/vendor/github.com/containerd/containerd/sys/socket_unix.go +++ b/vendor/github.com/containerd/containerd/sys/socket_unix.go @@ -42,7 +42,7 @@ func CreateUnixSocket(path string) (net.Listener, error) { return net.Listen("unix", path) } -// GetLocalListener returns a listerner out of a unix socket. +// GetLocalListener returns a listener out of a unix socket. func GetLocalListener(path string, uid, gid int) (net.Listener, error) { // Ensure parent directory is created if err := mkdirAs(filepath.Dir(path), uid, gid); err != nil { diff --git a/vendor/github.com/containerd/containerd/task.go b/vendor/github.com/containerd/containerd/task.go index 750075f8dbdfa..6806e1162081e 100644 --- a/vendor/github.com/containerd/containerd/task.go +++ b/vendor/github.com/containerd/containerd/task.go @@ -607,8 +607,11 @@ func writeContent(ctx context.Context, store content.Ingester, mediaType, ref st if err != nil { return d, err } + if err := writer.Commit(ctx, size, "", opts...); err != nil { - return d, err + if !errdefs.IsAlreadyExists(err) { + return d, err + } } return v1.Descriptor{ MediaType: mediaType, diff --git a/vendor/github.com/containerd/containerd/task_opts.go b/vendor/github.com/containerd/containerd/task_opts.go index 9e998a3498043..ce861ea51dde8 100644 --- a/vendor/github.com/containerd/containerd/task_opts.go +++ b/vendor/github.com/containerd/containerd/task_opts.go @@ -18,10 +18,18 @@ package containerd import ( "context" + "encoding/json" + "fmt" "syscall" + "github.com/containerd/containerd/api/types" + "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/images" "github.com/containerd/containerd/mount" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" ) // NewTaskOpts allows the caller to set options on a new task @@ -35,6 +43,44 @@ func WithRootFS(mounts []mount.Mount) NewTaskOpts { } } +// WithTaskCheckpoint allows a task to be created with live runtime and memory data from a +// previous checkpoint. Additional software such as CRIU may be required to +// restore a task from a checkpoint +func WithTaskCheckpoint(im Image) NewTaskOpts { + return func(ctx context.Context, c *Client, info *TaskInfo) error { + desc := im.Target() + id := desc.Digest + index, err := decodeIndex(ctx, c.ContentStore(), desc) + if err != nil { + return err + } + for _, m := range index.Manifests { + if m.MediaType == images.MediaTypeContainerd1Checkpoint { + info.Checkpoint = &types.Descriptor{ + MediaType: m.MediaType, + Size_: m.Size, + Digest: m.Digest, + } + return nil + } + } + return fmt.Errorf("checkpoint not found in index %s", id) + } +} + +func decodeIndex(ctx context.Context, store content.Provider, desc imagespec.Descriptor) (*imagespec.Index, error) { + var index imagespec.Index + p, err := content.ReadBlob(ctx, store, desc) + if err != nil { + return nil, err + } + if err := json.Unmarshal(p, &index); err != nil { + return nil, err + } + + return &index, nil +} + // WithCheckpointName sets the image name for the checkpoint func WithCheckpointName(name string) CheckpointTaskOpts { return func(r *CheckpointTaskInfo) error { @@ -92,3 +138,19 @@ func WithKillExecID(execID string) KillOpts { return nil } } + +// WithResources sets the provided resources for task updates. Resources must be +// either a *specs.LinuxResources or a *specs.WindowsResources +func WithResources(resources interface{}) UpdateTaskOpts { + return func(ctx context.Context, client *Client, r *UpdateTaskInfo) error { + switch resources.(type) { + case *specs.LinuxResources: + case *specs.WindowsResources: + default: + return errors.New("WithResources requires a *specs.LinuxResources or *specs.WindowsResources") + } + + r.Resources = resources + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/task_opts_linux.go b/vendor/github.com/containerd/containerd/task_opts_unix.go similarity index 72% rename from vendor/github.com/containerd/containerd/task_opts_linux.go rename to vendor/github.com/containerd/containerd/task_opts_unix.go index 551cb996c196c..f8652be3bc69d 100644 --- a/vendor/github.com/containerd/containerd/task_opts_linux.go +++ b/vendor/github.com/containerd/containerd/task_opts_unix.go @@ -1,3 +1,5 @@ +// +build !windows + /* Copyright The containerd Authors. @@ -18,20 +20,11 @@ package containerd import ( "context" - "errors" "github.com/containerd/containerd/runtime/linux/runctypes" - "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" ) -// WithResources sets the provided resources for task updates -func WithResources(resources *specs.LinuxResources) UpdateTaskOpts { - return func(ctx context.Context, client *Client, r *UpdateTaskInfo) error { - r.Resources = resources - return nil - } -} - // WithNoNewKeyring causes tasks not to be created with a new keyring for secret storage. // There is an upper limit on the number of keyrings in a linux system func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error { @@ -46,3 +39,19 @@ func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error { opts.NoNewKeyring = true return nil } + +// WithNoPivotRoot instructs the runtime not to you pivot_root +func WithNoPivotRoot(_ context.Context, _ *Client, info *TaskInfo) error { + if info.Options == nil { + info.Options = &runctypes.CreateOptions{ + NoPivotRoot: true, + } + return nil + } + opts, ok := info.Options.(*runctypes.CreateOptions) + if !ok { + return errors.New("invalid options type, expected runctypes.CreateOptions") + } + opts.NoPivotRoot = true + return nil +} diff --git a/vendor/github.com/containerd/containerd/vendor.conf b/vendor/github.com/containerd/containerd/vendor.conf index 094a1bed5ac4c..1bcd620ea3c3f 100644 --- a/vendor/github.com/containerd/containerd/vendor.conf +++ b/vendor/github.com/containerd/containerd/vendor.conf @@ -1,10 +1,10 @@ -github.com/containerd/go-runc acb7c88cac264acca9b5eae187a117f4d77a1292 +github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244 -github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b +github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6 github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 @@ -19,7 +19,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.0 github.com/gogo/protobuf v1.0.0 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef github.com/golang/protobuf v1.1.0 -github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce # v1.0.1-43-gd810dbc +github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd github.com/sirupsen/logrus v1.0.0 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c @@ -34,17 +34,17 @@ github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 github.com/Microsoft/go-winio v0.4.10 github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55 -github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 gotest.tools v2.1.0 github.com/google/go-cmp v0.1.0 +go.etcd.io/bbolt v1.3.1-etcd.8 # cri dependencies -github.com/containerd/cri v1.11.1 -github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534 +github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch +github.com/containerd/go-cni 6d7b509a054a3cb1c35ed1865d4fde2f0cb547cd github.com/blang/semver v3.1.0 github.com/containernetworking/cni v0.6.0 github.com/containernetworking/plugins v0.7.0 @@ -52,32 +52,33 @@ github.com/davecgh/go-spew v1.1.0 github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621 github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 -github.com/emicklei/go-restful ff4f55a206334ef123e4f79bbf348980da81ca46 -github.com/ghodss/yaml 73d445a93680fa1a78ae23a5839bad48f32ba1ee +github.com/emicklei/go-restful v2.2.1 +github.com/ghodss/yaml v1.0.0 github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f -github.com/json-iterator/go f2b4162afba35581b6d4a50d3b8f34e33c144682 -github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd +github.com/json-iterator/go 1.1.5 +github.com/modern-go/reflect2 1.0.1 github.com/modern-go/concurrent 1.0.3 github.com/opencontainers/runtime-tools v0.6.0 -github.com/opencontainers/selinux 4a2974bf1ee960774ffd517717f1f45325af0206 +github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 -github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc +github.com/tchap/go-patricia v2.2.6 github.com/xeipuuv/gojsonpointer 4e3ac2762d5f479393488629ee9370b50873b3a6 github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874 golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067 +golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4 golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 -gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77 -k8s.io/api 9e5ffd1f1320950b238cfce291b926411f0af722 -k8s.io/apimachinery ed135c5b96450fd24e5e981c708114fbbd950697 -k8s.io/apiserver a90e3a95c2e91b944bfca8225c4e0d12e42a9eb5 -k8s.io/client-go 03bfb9bdcfe5482795b999f39ca3ed9ad42ce5bb -k8s.io/kubernetes v1.11.0 -k8s.io/utils 733eca437aa39379e4bcc25e726439dfca40fcff +gopkg.in/yaml.v2 v2.2.1 +k8s.io/api 012f271b5d41baad56190c5f1ae19bff16df0fd8 +k8s.io/apimachinery 6429050ef506887d121f3e7306e894f8900d8a63 +k8s.io/apiserver e9312c15296b6c2c923ebd5031ff5d1d5fd022d7 +k8s.io/client-go 37c3c02ec96533daec0dbda1f39a6b1d68505c79 +k8s.io/kubernetes v1.12.0-beta.1 +k8s.io/utils 982821ea41da7e7c15f3d3738921eb2e7e241ccd # zfs dependencies github.com/containerd/zfs 9a0b8b8b5982014b729cd34eb7cd7a11062aa6ec @@ -85,4 +86,4 @@ github.com/mistifyio/go-zfs 166add352731e515512690329794ee593f1aaff2 github.com/pborman/uuid c65b2f87fee37d1c7854c9164a450713c28d50cd # aufs dependencies -github.com/containerd/aufs a7fbd554da7a9eafbe5a460a421313a9fd18d988 +github.com/containerd/aufs ffa39970e26ad01d81f540b21e65f9c1841a5f92 diff --git a/vendor/github.com/containerd/continuity/context.go b/vendor/github.com/containerd/continuity/context.go new file mode 100644 index 0000000000000..45b73dc9ed7ba --- /dev/null +++ b/vendor/github.com/containerd/continuity/context.go @@ -0,0 +1,657 @@ +package continuity + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "path/filepath" + "strings" + + "github.com/containerd/continuity/devices" + driverpkg "github.com/containerd/continuity/driver" + "github.com/containerd/continuity/pathdriver" + + "github.com/opencontainers/go-digest" +) + +var ( + // ErrNotFound represents the resource not found + ErrNotFound = fmt.Errorf("not found") + // ErrNotSupported represents the resource not supported + ErrNotSupported = fmt.Errorf("not supported") +) + +// Context represents a file system context for accessing resources. The +// responsibility of the context is to convert system specific resources to +// generic Resource objects. Most of this is safe path manipulation, as well +// as extraction of resource details. +type Context interface { + Apply(Resource) error + Verify(Resource) error + Resource(string, os.FileInfo) (Resource, error) + Walk(filepath.WalkFunc) error +} + +// SymlinkPath is intended to give the symlink target value +// in a root context. Target and linkname are absolute paths +// not under the given root. +type SymlinkPath func(root, linkname, target string) (string, error) + +// ContextOptions represents options to create a new context. +type ContextOptions struct { + Digester Digester + Driver driverpkg.Driver + PathDriver pathdriver.PathDriver + Provider ContentProvider +} + +// context represents a file system context for accessing resources. +// Generally, all path qualified access and system considerations should land +// here. +type context struct { + driver driverpkg.Driver + pathDriver pathdriver.PathDriver + root string + digester Digester + provider ContentProvider +} + +// NewContext returns a Context associated with root. The default driver will +// be used, as returned by NewDriver. +func NewContext(root string) (Context, error) { + return NewContextWithOptions(root, ContextOptions{}) +} + +// NewContextWithOptions returns a Context associate with the root. +func NewContextWithOptions(root string, options ContextOptions) (Context, error) { + // normalize to absolute path + pathDriver := options.PathDriver + if pathDriver == nil { + pathDriver = pathdriver.LocalPathDriver + } + + root = pathDriver.FromSlash(root) + root, err := pathDriver.Abs(pathDriver.Clean(root)) + if err != nil { + return nil, err + } + + driver := options.Driver + if driver == nil { + driver, err = driverpkg.NewSystemDriver() + if err != nil { + return nil, err + } + } + + digester := options.Digester + if digester == nil { + digester = simpleDigester{digest.Canonical} + } + + // Check the root directory. Need to be a little careful here. We are + // allowing a link for now, but this may have odd behavior when + // canonicalizing paths. As long as all files are opened through the link + // path, this should be okay. + fi, err := driver.Stat(root) + if err != nil { + return nil, err + } + + if !fi.IsDir() { + return nil, &os.PathError{Op: "NewContext", Path: root, Err: os.ErrInvalid} + } + + return &context{ + root: root, + driver: driver, + pathDriver: pathDriver, + digester: digester, + provider: options.Provider, + }, nil +} + +// Resource returns the resource as path p, populating the entry with info +// from fi. The path p should be the path of the resource in the context, +// typically obtained through Walk or from the value of Resource.Path(). If fi +// is nil, it will be resolved. +func (c *context) Resource(p string, fi os.FileInfo) (Resource, error) { + fp, err := c.fullpath(p) + if err != nil { + return nil, err + } + + if fi == nil { + fi, err = c.driver.Lstat(fp) + if err != nil { + return nil, err + } + } + + base, err := newBaseResource(p, fi) + if err != nil { + return nil, err + } + + base.xattrs, err = c.resolveXAttrs(fp, fi, base) + if err == ErrNotSupported { + log.Printf("resolving xattrs on %s not supported", fp) + } else if err != nil { + return nil, err + } + + // TODO(stevvooe): Handle windows alternate data streams. + + if fi.Mode().IsRegular() { + dgst, err := c.digest(p) + if err != nil { + return nil, err + } + + return newRegularFile(*base, base.paths, fi.Size(), dgst) + } + + if fi.Mode().IsDir() { + return newDirectory(*base) + } + + if fi.Mode()&os.ModeSymlink != 0 { + // We handle relative links vs absolute links by including a + // beginning slash for absolute links. Effectively, the bundle's + // root is treated as the absolute link anchor. + target, err := c.driver.Readlink(fp) + if err != nil { + return nil, err + } + + return newSymLink(*base, target) + } + + if fi.Mode()&os.ModeNamedPipe != 0 { + return newNamedPipe(*base, base.paths) + } + + if fi.Mode()&os.ModeDevice != 0 { + deviceDriver, ok := c.driver.(driverpkg.DeviceInfoDriver) + if !ok { + log.Printf("device extraction not supported %s", fp) + return nil, ErrNotSupported + } + + // character and block devices merely need to recover the + // major/minor device number. + major, minor, err := deviceDriver.DeviceInfo(fi) + if err != nil { + return nil, err + } + + return newDevice(*base, base.paths, major, minor) + } + + log.Printf("%q (%v) is not supported", fp, fi.Mode()) + return nil, ErrNotFound +} + +func (c *context) verifyMetadata(resource, target Resource) error { + if target.Mode() != resource.Mode() { + return fmt.Errorf("resource %q has incorrect mode: %v != %v", target.Path(), target.Mode(), resource.Mode()) + } + + if target.UID() != resource.UID() { + return fmt.Errorf("unexpected uid for %q: %v != %v", target.Path(), target.UID(), resource.GID()) + } + + if target.GID() != resource.GID() { + return fmt.Errorf("unexpected gid for %q: %v != %v", target.Path(), target.GID(), target.GID()) + } + + if xattrer, ok := resource.(XAttrer); ok { + txattrer, tok := target.(XAttrer) + if !tok { + return fmt.Errorf("resource %q has xattrs but target does not support them", resource.Path()) + } + + // For xattrs, only ensure that we have those defined in the resource + // and their values match. We can ignore other xattrs. In other words, + // we only verify that target has the subset defined by resource. + txattrs := txattrer.XAttrs() + for attr, value := range xattrer.XAttrs() { + tvalue, ok := txattrs[attr] + if !ok { + return fmt.Errorf("resource %q target missing xattr %q", resource.Path(), attr) + } + + if !bytes.Equal(value, tvalue) { + return fmt.Errorf("xattr %q value differs for resource %q", attr, resource.Path()) + } + } + } + + switch r := resource.(type) { + case RegularFile: + // TODO(stevvooe): Another reason to use a record-based approach. We + // have to do another type switch to get this to work. This could be + // fixed with an Equal function, but let's study this a little more to + // be sure. + t, ok := target.(RegularFile) + if !ok { + return fmt.Errorf("resource %q target not a regular file", r.Path()) + } + + if t.Size() != r.Size() { + return fmt.Errorf("resource %q target has incorrect size: %v != %v", t.Path(), t.Size(), r.Size()) + } + case Directory: + t, ok := target.(Directory) + if !ok { + return fmt.Errorf("resource %q target not a directory", t.Path()) + } + case SymLink: + t, ok := target.(SymLink) + if !ok { + return fmt.Errorf("resource %q target not a symlink", t.Path()) + } + + if t.Target() != r.Target() { + return fmt.Errorf("resource %q target has mismatched target: %q != %q", t.Path(), t.Target(), r.Target()) + } + case Device: + t, ok := target.(Device) + if !ok { + return fmt.Errorf("resource %q is not a device", t.Path()) + } + + if t.Major() != r.Major() || t.Minor() != r.Minor() { + return fmt.Errorf("resource %q has mismatched major/minor numbers: %d,%d != %d,%d", t.Path(), t.Major(), t.Minor(), r.Major(), r.Minor()) + } + case NamedPipe: + t, ok := target.(NamedPipe) + if !ok { + return fmt.Errorf("resource %q is not a named pipe", t.Path()) + } + default: + return fmt.Errorf("cannot verify resource: %v", resource) + } + + return nil +} + +// Verify the resource in the context. An error will be returned a discrepancy +// is found. +func (c *context) Verify(resource Resource) error { + fp, err := c.fullpath(resource.Path()) + if err != nil { + return err + } + + fi, err := c.driver.Lstat(fp) + if err != nil { + return err + } + + target, err := c.Resource(resource.Path(), fi) + if err != nil { + return err + } + + if target.Path() != resource.Path() { + return fmt.Errorf("resource paths do not match: %q != %q", target.Path(), resource.Path()) + } + + if err := c.verifyMetadata(resource, target); err != nil { + return err + } + + if h, isHardlinkable := resource.(Hardlinkable); isHardlinkable { + hardlinkKey, err := newHardlinkKey(fi) + if err == errNotAHardLink { + if len(h.Paths()) > 1 { + return fmt.Errorf("%q is not a hardlink to %q", h.Paths()[1], resource.Path()) + } + } else if err != nil { + return err + } + + for _, path := range h.Paths()[1:] { + fpLink, err := c.fullpath(path) + if err != nil { + return err + } + + fiLink, err := c.driver.Lstat(fpLink) + if err != nil { + return err + } + + targetLink, err := c.Resource(path, fiLink) + if err != nil { + return err + } + + hardlinkKeyLink, err := newHardlinkKey(fiLink) + if err != nil { + return err + } + + if hardlinkKeyLink != hardlinkKey { + return fmt.Errorf("%q is not a hardlink to %q", path, resource.Path()) + } + + if err := c.verifyMetadata(resource, targetLink); err != nil { + return err + } + } + } + + switch r := resource.(type) { + case RegularFile: + t, ok := target.(RegularFile) + if !ok { + return fmt.Errorf("resource %q target not a regular file", r.Path()) + } + + // TODO(stevvooe): This may need to get a little more sophisticated + // for digest comparison. We may want to actually calculate the + // provided digests, rather than the implementations having an + // overlap. + if !digestsMatch(t.Digests(), r.Digests()) { + return fmt.Errorf("digests for resource %q do not match: %v != %v", t.Path(), t.Digests(), r.Digests()) + } + } + + return nil +} + +func (c *context) checkoutFile(fp string, rf RegularFile) error { + if c.provider == nil { + return fmt.Errorf("no file provider") + } + var ( + r io.ReadCloser + err error + ) + for _, dgst := range rf.Digests() { + r, err = c.provider.Reader(dgst) + if err == nil { + break + } + } + if err != nil { + return fmt.Errorf("file content could not be provided: %v", err) + } + defer r.Close() + + return atomicWriteFile(fp, r, rf.Size(), rf.Mode()) +} + +// Apply the resource to the contexts. An error will be returned if the +// operation fails. Depending on the resource type, the resource may be +// created. For resource that cannot be resolved, an error will be returned. +func (c *context) Apply(resource Resource) error { + fp, err := c.fullpath(resource.Path()) + if err != nil { + return err + } + + if !strings.HasPrefix(fp, c.root) { + return fmt.Errorf("resource %v escapes root", resource) + } + + var chmod = true + fi, err := c.driver.Lstat(fp) + if err != nil { + if !os.IsNotExist(err) { + return err + } + } + + switch r := resource.(type) { + case RegularFile: + if fi == nil { + if err := c.checkoutFile(fp, r); err != nil { + return fmt.Errorf("error checking out file %q: %v", resource.Path(), err) + } + chmod = false + } else { + if !fi.Mode().IsRegular() { + return fmt.Errorf("file %q should be a regular file, but is not", resource.Path()) + } + if fi.Size() != r.Size() { + if err := c.checkoutFile(fp, r); err != nil { + return fmt.Errorf("error checking out file %q: %v", resource.Path(), err) + } + } else { + for _, dgst := range r.Digests() { + f, err := os.Open(fp) + if err != nil { + return fmt.Errorf("failure opening file for read %q: %v", resource.Path(), err) + } + compared, err := dgst.Algorithm().FromReader(f) + if err == nil && dgst != compared { + if err := c.checkoutFile(fp, r); err != nil { + return fmt.Errorf("error checking out file %q: %v", resource.Path(), err) + } + break + } + if err1 := f.Close(); err == nil { + err = err1 + } + if err != nil { + return fmt.Errorf("error checking digest for %q: %v", resource.Path(), err) + } + } + } + } + case Directory: + if fi == nil { + if err := c.driver.Mkdir(fp, resource.Mode()); err != nil { + return err + } + } else if !fi.Mode().IsDir() { + return fmt.Errorf("%q should be a directory, but is not", resource.Path()) + } + + case SymLink: + var target string // only possibly set if target resource is a symlink + + if fi != nil { + if fi.Mode()&os.ModeSymlink != 0 { + target, err = c.driver.Readlink(fp) + if err != nil { + return err + } + } + } + + if target != r.Target() { + if fi != nil { + if err := c.driver.Remove(fp); err != nil { // RemoveAll in case of directory? + return err + } + } + + if err := c.driver.Symlink(r.Target(), fp); err != nil { + return err + } + } + + case Device: + if fi == nil { + if err := c.driver.Mknod(fp, resource.Mode(), int(r.Major()), int(r.Minor())); err != nil { + return err + } + } else if (fi.Mode() & os.ModeDevice) == 0 { + return fmt.Errorf("%q should be a device, but is not", resource.Path()) + } else { + major, minor, err := devices.DeviceInfo(fi) + if err != nil { + return err + } + if major != r.Major() || minor != r.Minor() { + if err := c.driver.Remove(fp); err != nil { + return err + } + + if err := c.driver.Mknod(fp, resource.Mode(), int(r.Major()), int(r.Minor())); err != nil { + return err + } + } + } + + case NamedPipe: + if fi == nil { + if err := c.driver.Mkfifo(fp, resource.Mode()); err != nil { + return err + } + } else if (fi.Mode() & os.ModeNamedPipe) == 0 { + return fmt.Errorf("%q should be a named pipe, but is not", resource.Path()) + } + } + + if h, isHardlinkable := resource.(Hardlinkable); isHardlinkable { + for _, path := range h.Paths() { + if path == resource.Path() { + continue + } + + lp, err := c.fullpath(path) + if err != nil { + return err + } + + if _, fi := c.driver.Lstat(lp); fi == nil { + c.driver.Remove(lp) + } + if err := c.driver.Link(fp, lp); err != nil { + return err + } + } + } + + // Update filemode if file was not created + if chmod { + if err := c.driver.Lchmod(fp, resource.Mode()); err != nil { + return err + } + } + + if err := c.driver.Lchown(fp, resource.UID(), resource.GID()); err != nil { + return err + } + + if xattrer, ok := resource.(XAttrer); ok { + // For xattrs, only ensure that we have those defined in the resource + // and their values are set. We can ignore other xattrs. In other words, + // we only set xattres defined by resource but never remove. + + if _, ok := resource.(SymLink); ok { + lxattrDriver, ok := c.driver.(driverpkg.LXAttrDriver) + if !ok { + return fmt.Errorf("unsupported symlink xattr for resource %q", resource.Path()) + } + if err := lxattrDriver.LSetxattr(fp, xattrer.XAttrs()); err != nil { + return err + } + } else { + xattrDriver, ok := c.driver.(driverpkg.XAttrDriver) + if !ok { + return fmt.Errorf("unsupported xattr for resource %q", resource.Path()) + } + if err := xattrDriver.Setxattr(fp, xattrer.XAttrs()); err != nil { + return err + } + } + } + + return nil +} + +// Walk provides a convenience function to call filepath.Walk correctly for +// the context. Otherwise identical to filepath.Walk, the path argument is +// corrected to be contained within the context. +func (c *context) Walk(fn filepath.WalkFunc) error { + root := c.root + fi, err := c.driver.Lstat(c.root) + if err == nil && fi.Mode()&os.ModeSymlink != 0 { + root, err = c.driver.Readlink(c.root) + if err != nil { + return err + } + } + return c.pathDriver.Walk(root, func(p string, fi os.FileInfo, err error) error { + contained, err := c.containWithRoot(p, root) + return fn(contained, fi, err) + }) +} + +// fullpath returns the system path for the resource, joined with the context +// root. The path p must be a part of the context. +func (c *context) fullpath(p string) (string, error) { + p = c.pathDriver.Join(c.root, p) + if !strings.HasPrefix(p, c.root) { + return "", fmt.Errorf("invalid context path") + } + + return p, nil +} + +// contain cleans and santizes the filesystem path p to be an absolute path, +// effectively relative to the context root. +func (c *context) contain(p string) (string, error) { + return c.containWithRoot(p, c.root) +} + +// containWithRoot cleans and santizes the filesystem path p to be an absolute path, +// effectively relative to the passed root. Extra care should be used when calling this +// instead of contain. This is needed for Walk, as if context root is a symlink, +// it must be evaluated prior to the Walk +func (c *context) containWithRoot(p string, root string) (string, error) { + sanitized, err := c.pathDriver.Rel(root, p) + if err != nil { + return "", err + } + + // ZOMBIES(stevvooe): In certain cases, we may want to remap these to a + // "containment error", so the caller can decide what to do. + return c.pathDriver.Join("/", c.pathDriver.Clean(sanitized)), nil +} + +// digest returns the digest of the file at path p, relative to the root. +func (c *context) digest(p string) (digest.Digest, error) { + f, err := c.driver.Open(c.pathDriver.Join(c.root, p)) + if err != nil { + return "", err + } + defer f.Close() + + return c.digester.Digest(f) +} + +// resolveXAttrs attempts to resolve the extended attributes for the resource +// at the path fp, which is the full path to the resource. If the resource +// cannot have xattrs, nil will be returned. +func (c *context) resolveXAttrs(fp string, fi os.FileInfo, base *resource) (map[string][]byte, error) { + if fi.Mode().IsRegular() || fi.Mode().IsDir() { + xattrDriver, ok := c.driver.(driverpkg.XAttrDriver) + if !ok { + log.Println("xattr extraction not supported") + return nil, ErrNotSupported + } + + return xattrDriver.Getxattr(fp) + } + + if fi.Mode()&os.ModeSymlink != 0 { + lxattrDriver, ok := c.driver.(driverpkg.LXAttrDriver) + if !ok { + log.Println("xattr extraction for symlinks not supported") + return nil, ErrNotSupported + } + + return lxattrDriver.LGetxattr(fp) + } + + return nil, nil +} diff --git a/vendor/github.com/containerd/continuity/digests.go b/vendor/github.com/containerd/continuity/digests.go new file mode 100644 index 0000000000000..355b08039d1e9 --- /dev/null +++ b/vendor/github.com/containerd/continuity/digests.go @@ -0,0 +1,88 @@ +package continuity + +import ( + "fmt" + "io" + "sort" + + "github.com/opencontainers/go-digest" +) + +// Digester produces a digest for a given read stream +type Digester interface { + Digest(io.Reader) (digest.Digest, error) +} + +// ContentProvider produces a read stream for a given digest +type ContentProvider interface { + Reader(digest.Digest) (io.ReadCloser, error) +} + +type simpleDigester struct { + algorithm digest.Algorithm +} + +func (sd simpleDigester) Digest(r io.Reader) (digest.Digest, error) { + digester := sd.algorithm.Digester() + + if _, err := io.Copy(digester.Hash(), r); err != nil { + return "", err + } + + return digester.Digest(), nil +} + +// uniqifyDigests sorts and uniqifies the provided digest, ensuring that the +// digests are not repeated and no two digests with the same algorithm have +// different values. Because a stable sort is used, this has the effect of +// "zipping" digest collections from multiple resources. +func uniqifyDigests(digests ...digest.Digest) ([]digest.Digest, error) { + sort.Stable(digestSlice(digests)) // stable sort is important for the behavior here. + seen := map[digest.Digest]struct{}{} + algs := map[digest.Algorithm][]digest.Digest{} // detect different digests. + + var out []digest.Digest + // uniqify the digests + for _, d := range digests { + if _, ok := seen[d]; ok { + continue + } + + seen[d] = struct{}{} + algs[d.Algorithm()] = append(algs[d.Algorithm()], d) + + if len(algs[d.Algorithm()]) > 1 { + return nil, fmt.Errorf("conflicting digests for %v found", d.Algorithm()) + } + + out = append(out, d) + } + + return out, nil +} + +// digestsMatch compares the two sets of digests to see if they match. +func digestsMatch(as, bs []digest.Digest) bool { + all := append(as, bs...) + + uniqified, err := uniqifyDigests(all...) + if err != nil { + // the only error uniqifyDigests returns is when the digests disagree. + return false + } + + disjoint := len(as) + len(bs) + if len(uniqified) == disjoint { + // if these two sets have the same cardinality, we know both sides + // didn't share any digests. + return false + } + + return true +} + +type digestSlice []digest.Digest + +func (p digestSlice) Len() int { return len(p) } +func (p digestSlice) Less(i, j int) bool { return p[i] < p[j] } +func (p digestSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/vendor/github.com/containerd/continuity/driver/driver_unix.go b/vendor/github.com/containerd/continuity/driver/driver_unix.go index 67493ade0897b..c7d4e6ba151d4 100644 --- a/vendor/github.com/containerd/continuity/driver/driver_unix.go +++ b/vendor/github.com/containerd/continuity/driver/driver_unix.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "os" - "path/filepath" "sort" "github.com/containerd/continuity/devices" @@ -26,18 +25,6 @@ func (d *driver) Mkfifo(path string, mode os.FileMode) error { return devices.Mknod(path, mode, 0, 0) } -// Lchmod changes the mode of an file not following symlinks. -func (d *driver) Lchmod(path string, mode os.FileMode) (err error) { - if !filepath.IsAbs(path) { - path, err = filepath.Abs(path) - if err != nil { - return - } - } - - return sysx.Fchmodat(0, path, uint32(mode), sysx.AtSymlinkNofollow) -} - // Getxattr returns all of the extended attributes for the file at path p. func (d *driver) Getxattr(p string) (map[string][]byte, error) { xattrs, err := sysx.Listxattr(p) diff --git a/vendor/github.com/containerd/continuity/driver/lchmod_linux.go b/vendor/github.com/containerd/continuity/driver/lchmod_linux.go new file mode 100644 index 0000000000000..39ffe9cc32252 --- /dev/null +++ b/vendor/github.com/containerd/continuity/driver/lchmod_linux.go @@ -0,0 +1,19 @@ +package driver + +import ( + "os" + + "golang.org/x/sys/unix" +) + +// Lchmod changes the mode of a file not following symlinks. +func (d *driver) Lchmod(path string, mode os.FileMode) error { + // On Linux, file mode is not supported for symlinks, + // and fchmodat() does not support AT_SYMLINK_NOFOLLOW, + // so symlinks need to be skipped entirely. + if st, err := os.Stat(path); err == nil && st.Mode()&os.ModeSymlink != 0 { + return nil + } + + return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0) +} diff --git a/vendor/github.com/containerd/continuity/driver/lchmod_unix.go b/vendor/github.com/containerd/continuity/driver/lchmod_unix.go new file mode 100644 index 0000000000000..1b539f78e3970 --- /dev/null +++ b/vendor/github.com/containerd/continuity/driver/lchmod_unix.go @@ -0,0 +1,14 @@ +// +build darwin freebsd solaris + +package driver + +import ( + "os" + + "golang.org/x/sys/unix" +) + +// Lchmod changes the mode of a file not following symlinks. +func (d *driver) Lchmod(path string, mode os.FileMode) error { + return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW) +} diff --git a/vendor/github.com/containerd/continuity/fs/du.go b/vendor/github.com/containerd/continuity/fs/du.go index 26f53331547fe..f8fc9a9946209 100644 --- a/vendor/github.com/containerd/continuity/fs/du.go +++ b/vendor/github.com/containerd/continuity/fs/du.go @@ -10,8 +10,8 @@ type Usage struct { // DiskUsage counts the number of inodes and disk usage for the resources under // path. -func DiskUsage(roots ...string) (Usage, error) { - return diskUsage(roots...) +func DiskUsage(ctx context.Context, roots ...string) (Usage, error) { + return diskUsage(ctx, roots...) } // DiffUsage counts the numbers of inodes and disk usage in the diff --git a/vendor/github.com/containerd/continuity/fs/du_unix.go b/vendor/github.com/containerd/continuity/fs/du_unix.go index fe3426d2783f2..9f6bc55fd9b32 100644 --- a/vendor/github.com/containerd/continuity/fs/du_unix.go +++ b/vendor/github.com/containerd/continuity/fs/du_unix.go @@ -24,7 +24,7 @@ func newInode(stat *syscall.Stat_t) inode { } } -func diskUsage(roots ...string) (Usage, error) { +func diskUsage(ctx context.Context, roots ...string) (Usage, error) { var ( size int64 @@ -37,6 +37,12 @@ func diskUsage(roots ...string) (Usage, error) { return err } + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + inoKey := newInode(fi.Sys().(*syscall.Stat_t)) if _, ok := inodes[inoKey]; !ok { inodes[inoKey] = struct{}{} diff --git a/vendor/github.com/containerd/continuity/fs/du_windows.go b/vendor/github.com/containerd/continuity/fs/du_windows.go index 3f852fc15eee1..faa443fedacc3 100644 --- a/vendor/github.com/containerd/continuity/fs/du_windows.go +++ b/vendor/github.com/containerd/continuity/fs/du_windows.go @@ -8,7 +8,7 @@ import ( "path/filepath" ) -func diskUsage(roots ...string) (Usage, error) { +func diskUsage(ctx context.Context, roots ...string) (Usage, error) { var ( size int64 ) @@ -21,6 +21,12 @@ func diskUsage(roots ...string) (Usage, error) { return err } + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + size += fi.Size() return nil }); err != nil { diff --git a/vendor/github.com/containerd/continuity/groups_unix.go b/vendor/github.com/containerd/continuity/groups_unix.go new file mode 100644 index 0000000000000..e15c14ff89a8c --- /dev/null +++ b/vendor/github.com/containerd/continuity/groups_unix.go @@ -0,0 +1,113 @@ +package continuity + +import ( + "bufio" + "fmt" + "io" + "os" + "strconv" + "strings" +) + +// TODO(stevvooe): This needs a lot of work before we can call it useful. + +type groupIndex struct { + byName map[string]*group + byGID map[int]*group +} + +func getGroupIndex() (*groupIndex, error) { + f, err := os.Open("/etc/group") + if err != nil { + return nil, err + } + defer f.Close() + + groups, err := parseGroups(f) + if err != nil { + return nil, err + } + + return newGroupIndex(groups), nil +} + +func newGroupIndex(groups []group) *groupIndex { + gi := &groupIndex{ + byName: make(map[string]*group), + byGID: make(map[int]*group), + } + + for i, group := range groups { + gi.byGID[group.gid] = &groups[i] + gi.byName[group.name] = &groups[i] + } + + return gi +} + +type group struct { + name string + gid int + members []string +} + +func getGroupName(gid int) (string, error) { + f, err := os.Open("/etc/group") + if err != nil { + return "", err + } + defer f.Close() + + groups, err := parseGroups(f) + if err != nil { + return "", err + } + + for _, group := range groups { + if group.gid == gid { + return group.name, nil + } + } + + return "", fmt.Errorf("no group for gid") +} + +// parseGroups parses an /etc/group file for group names, ids and membership. +// This is unix specific. +func parseGroups(rd io.Reader) ([]group, error) { + var groups []group + scanner := bufio.NewScanner(rd) + + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "#") { + continue // skip comment + } + + parts := strings.SplitN(scanner.Text(), ":", 4) + + if len(parts) != 4 { + return nil, fmt.Errorf("bad entry: %q", scanner.Text()) + } + + name, _, sgid, smembers := parts[0], parts[1], parts[2], parts[3] + + gid, err := strconv.Atoi(sgid) + if err != nil { + return nil, fmt.Errorf("bad gid: %q", gid) + } + + members := strings.Split(smembers, ",") + + groups = append(groups, group{ + name: name, + gid: gid, + members: members, + }) + } + + if scanner.Err() != nil { + return nil, scanner.Err() + } + + return groups, nil +} diff --git a/vendor/github.com/containerd/continuity/hardlinks.go b/vendor/github.com/containerd/continuity/hardlinks.go new file mode 100644 index 0000000000000..8b39bd0612ac2 --- /dev/null +++ b/vendor/github.com/containerd/continuity/hardlinks.go @@ -0,0 +1,57 @@ +package continuity + +import ( + "fmt" + "os" +) + +var ( + errNotAHardLink = fmt.Errorf("invalid hardlink") +) + +type hardlinkManager struct { + hardlinks map[hardlinkKey][]Resource +} + +func newHardlinkManager() *hardlinkManager { + return &hardlinkManager{ + hardlinks: map[hardlinkKey][]Resource{}, + } +} + +// Add attempts to add the resource to the hardlink manager. If the resource +// cannot be considered as a hardlink candidate, errNotAHardLink is returned. +func (hlm *hardlinkManager) Add(fi os.FileInfo, resource Resource) error { + if _, ok := resource.(Hardlinkable); !ok { + return errNotAHardLink + } + + key, err := newHardlinkKey(fi) + if err != nil { + return err + } + + hlm.hardlinks[key] = append(hlm.hardlinks[key], resource) + + return nil +} + +// Merge processes the current state of the hardlink manager and merges any +// shared nodes into hardlinked resources. +func (hlm *hardlinkManager) Merge() ([]Resource, error) { + var resources []Resource + for key, linked := range hlm.hardlinks { + if len(linked) < 1 { + return nil, fmt.Errorf("no hardlink entrys for dev, inode pair: %#v", key) + } + + merged, err := Merge(linked...) + if err != nil { + return nil, fmt.Errorf("error merging hardlink: %v", err) + } + + resources = append(resources, merged) + } + + return resources, nil +} diff --git a/vendor/github.com/containerd/continuity/hardlinks_unix.go b/vendor/github.com/containerd/continuity/hardlinks_unix.go new file mode 100644 index 0000000000000..1d81a3f963ed9 --- /dev/null +++ b/vendor/github.com/containerd/continuity/hardlinks_unix.go @@ -0,0 +1,36 @@ +// +build linux darwin freebsd solaris + +package continuity + +import ( + "fmt" + "os" + "syscall" +) + +// hardlinkKey provides a tuple-key for managing hardlinks. This is system- +// specific. +type hardlinkKey struct { + dev uint64 + inode uint64 +} + +// newHardlinkKey returns a hardlink key for the provided file info. If the +// resource does not represent a possible hardlink, errNotAHardLink will be +// returned. +func newHardlinkKey(fi os.FileInfo) (hardlinkKey, error) { + sys, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return hardlinkKey{}, fmt.Errorf("cannot resolve (*syscall.Stat_t) from os.FileInfo") + } + + if sys.Nlink < 2 { + // NOTE(stevvooe): This is not always true for all filesystems. We + // should somehow detect this and provided a slow "polyfill" that + // leverages os.SameFile if we detect a filesystem where link counts + // is not really supported. + return hardlinkKey{}, errNotAHardLink + } + + return hardlinkKey{dev: uint64(sys.Dev), inode: uint64(sys.Ino)}, nil +} diff --git a/vendor/github.com/containerd/continuity/hardlinks_windows.go b/vendor/github.com/containerd/continuity/hardlinks_windows.go new file mode 100644 index 0000000000000..be516c560a31a --- /dev/null +++ b/vendor/github.com/containerd/continuity/hardlinks_windows.go @@ -0,0 +1,12 @@ +package continuity + +import "os" + +type hardlinkKey struct{} + +func newHardlinkKey(fi os.FileInfo) (hardlinkKey, error) { + // NOTE(stevvooe): Obviously, this is not yet implemented. However, the + // makings of an implementation are available in src/os/types_windows.go. More + // investigation needs to be done to figure out exactly how to do this. + return hardlinkKey{}, errNotAHardLink +} diff --git a/vendor/github.com/containerd/continuity/ioutils.go b/vendor/github.com/containerd/continuity/ioutils.go new file mode 100644 index 0000000000000..3a25bde39af97 --- /dev/null +++ b/vendor/github.com/containerd/continuity/ioutils.go @@ -0,0 +1,47 @@ +package continuity + +import ( + "bytes" + "io" + "io/ioutil" + "os" + "path/filepath" +) + +// AtomicWriteFile atomically writes data to a file by first writing to a +// temp file and calling rename. +func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { + buf := bytes.NewBuffer(data) + return atomicWriteFile(filename, buf, int64(len(data)), perm) +} + +// atomicWriteFile writes data to a file by first writing to a temp +// file and calling rename. +func atomicWriteFile(filename string, r io.Reader, dataSize int64, perm os.FileMode) error { + f, err := ioutil.TempFile(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) + if err != nil { + return err + } + err = os.Chmod(f.Name(), perm) + if err != nil { + f.Close() + return err + } + n, err := io.Copy(f, r) + if err == nil && n < dataSize { + f.Close() + return io.ErrShortWrite + } + if err != nil { + f.Close() + return err + } + if err := f.Sync(); err != nil { + f.Close() + return err + } + if err := f.Close(); err != nil { + return err + } + return os.Rename(f.Name(), filename) +} diff --git a/vendor/github.com/containerd/continuity/manifest.go b/vendor/github.com/containerd/continuity/manifest.go new file mode 100644 index 0000000000000..f704f048b847f --- /dev/null +++ b/vendor/github.com/containerd/continuity/manifest.go @@ -0,0 +1,144 @@ +package continuity + +import ( + "fmt" + "io" + "log" + "os" + "sort" + + pb "github.com/containerd/continuity/proto" + "github.com/golang/protobuf/proto" +) + +// Manifest provides the contents of a manifest. Users of this struct should +// not typically modify any fields directly. +type Manifest struct { + // Resources specifies all the resources for a manifest in order by path. + Resources []Resource +} + +func Unmarshal(p []byte) (*Manifest, error) { + var bm pb.Manifest + + if err := proto.Unmarshal(p, &bm); err != nil { + return nil, err + } + + var m Manifest + for _, b := range bm.Resource { + r, err := fromProto(b) + if err != nil { + return nil, err + } + + m.Resources = append(m.Resources, r) + } + + return &m, nil +} + +func Marshal(m *Manifest) ([]byte, error) { + var bm pb.Manifest + for _, resource := range m.Resources { + bm.Resource = append(bm.Resource, toProto(resource)) + } + + return proto.Marshal(&bm) +} + +func MarshalText(w io.Writer, m *Manifest) error { + var bm pb.Manifest + for _, resource := range m.Resources { + bm.Resource = append(bm.Resource, toProto(resource)) + } + + return proto.MarshalText(w, &bm) +} + +// BuildManifest creates the manifest for the given context +func BuildManifest(ctx Context) (*Manifest, error) { + resourcesByPath := map[string]Resource{} + hardlinks := newHardlinkManager() + + if err := ctx.Walk(func(p string, fi os.FileInfo, err error) error { + if err != nil { + return fmt.Errorf("error walking %s: %v", p, err) + } + + if p == string(os.PathSeparator) { + // skip root + return nil + } + + resource, err := ctx.Resource(p, fi) + if err != nil { + if err == ErrNotFound { + return nil + } + log.Printf("error getting resource %q: %v", p, err) + return err + } + + // add to the hardlink manager + if err := hardlinks.Add(fi, resource); err == nil { + // Resource has been accepted by hardlink manager so we don't add + // it to the resourcesByPath until we merge at the end. + return nil + } else if err != errNotAHardLink { + // handle any other case where we have a proper error. + return fmt.Errorf("adding hardlink %s: %v", p, err) + } + + resourcesByPath[p] = resource + + return nil + }); err != nil { + return nil, err + } + + // merge and post-process the hardlinks. + hardlinked, err := hardlinks.Merge() + if err != nil { + return nil, err + } + + for _, resource := range hardlinked { + resourcesByPath[resource.Path()] = resource + } + + var resources []Resource + for _, resource := range resourcesByPath { + resources = append(resources, resource) + } + + sort.Stable(ByPath(resources)) + + return &Manifest{ + Resources: resources, + }, nil +} + +// VerifyManifest verifies all the resources in a manifest +// against files from the given context. +func VerifyManifest(ctx Context, manifest *Manifest) error { + for _, resource := range manifest.Resources { + if err := ctx.Verify(resource); err != nil { + return err + } + } + + return nil +} + +// ApplyManifest applies on the resources in a manifest to +// the given context. +func ApplyManifest(ctx Context, manifest *Manifest) error { + for _, resource := range manifest.Resources { + if err := ctx.Apply(resource); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/containerd/continuity/proto/gen.go b/vendor/github.com/containerd/continuity/proto/gen.go new file mode 100644 index 0000000000000..8f26ff501f6dc --- /dev/null +++ b/vendor/github.com/containerd/continuity/proto/gen.go @@ -0,0 +1,3 @@ +package proto + +//go:generate protoc --go_out=. manifest.proto diff --git a/vendor/github.com/containerd/continuity/proto/manifest.pb.go b/vendor/github.com/containerd/continuity/proto/manifest.pb.go new file mode 100644 index 0000000000000..24317766257ad --- /dev/null +++ b/vendor/github.com/containerd/continuity/proto/manifest.pb.go @@ -0,0 +1,181 @@ +// Code generated by protoc-gen-go. +// source: manifest.proto +// DO NOT EDIT! + +/* +Package proto is a generated protocol buffer package. + +It is generated from these files: + manifest.proto + +It has these top-level messages: + Manifest + Resource + XAttr + ADSEntry +*/ +package proto + +import proto1 "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto1.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package + +// Manifest specifies the entries in a container bundle, keyed and sorted by +// path. +type Manifest struct { + Resource []*Resource `protobuf:"bytes,1,rep,name=resource" json:"resource,omitempty"` +} + +func (m *Manifest) Reset() { *m = Manifest{} } +func (m *Manifest) String() string { return proto1.CompactTextString(m) } +func (*Manifest) ProtoMessage() {} +func (*Manifest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Manifest) GetResource() []*Resource { + if m != nil { + return m.Resource + } + return nil +} + +type Resource struct { + // Path specifies the path from the bundle root. If more than one + // path is present, the entry may represent a hardlink, rather than using + // a link target. The path format is operating system specific. + Path []string `protobuf:"bytes,1,rep,name=path" json:"path,omitempty"` + // Uid specifies the user id for the resource. + Uid int64 `protobuf:"varint,2,opt,name=uid" json:"uid,omitempty"` + // Gid specifies the group id for the resource. + Gid int64 `protobuf:"varint,3,opt,name=gid" json:"gid,omitempty"` + // user and group are not currently used but their field numbers have been + // reserved for future use. As such, they are marked as deprecated. + User string `protobuf:"bytes,4,opt,name=user" json:"user,omitempty"` + Group string `protobuf:"bytes,5,opt,name=group" json:"group,omitempty"` + // Mode defines the file mode and permissions. We've used the same + // bit-packing from Go's os package, + // http://golang.org/pkg/os/#FileMode, since they've done the work of + // creating a cross-platform layout. + Mode uint32 `protobuf:"varint,6,opt,name=mode" json:"mode,omitempty"` + // Size specifies the size in bytes of the resource. This is only valid + // for regular files. + Size uint64 `protobuf:"varint,7,opt,name=size" json:"size,omitempty"` + // Digest specifies the content digest of the target file. Only valid for + // regular files. The strings are formatted in OCI style, i.e. :. + // For detailed information about the format, please refer to OCI Image Spec: + // https://github.com/opencontainers/image-spec/blob/master/descriptor.md#digests-and-verification + // The digests are sorted in lexical order and implementations may choose + // which algorithms they prefer. + Digest []string `protobuf:"bytes,8,rep,name=digest" json:"digest,omitempty"` + // Target defines the target of a hard or soft link. Absolute links start + // with a slash and specify the resource relative to the bundle root. + // Relative links do not start with a slash and are relative to the + // resource path. + Target string `protobuf:"bytes,9,opt,name=target" json:"target,omitempty"` + // Major specifies the major device number for character and block devices. + Major uint64 `protobuf:"varint,10,opt,name=major" json:"major,omitempty"` + // Minor specifies the minor device number for character and block devices. + Minor uint64 `protobuf:"varint,11,opt,name=minor" json:"minor,omitempty"` + // Xattr provides storage for extended attributes for the target resource. + Xattr []*XAttr `protobuf:"bytes,12,rep,name=xattr" json:"xattr,omitempty"` + // Ads stores one or more alternate data streams for the target resource. + Ads []*ADSEntry `protobuf:"bytes,13,rep,name=ads" json:"ads,omitempty"` +} + +func (m *Resource) Reset() { *m = Resource{} } +func (m *Resource) String() string { return proto1.CompactTextString(m) } +func (*Resource) ProtoMessage() {} +func (*Resource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Resource) GetXattr() []*XAttr { + if m != nil { + return m.Xattr + } + return nil +} + +func (m *Resource) GetAds() []*ADSEntry { + if m != nil { + return m.Ads + } + return nil +} + +// XAttr encodes extended attributes for a resource. +type XAttr struct { + // Name specifies the attribute name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Data specifies the associated data for the attribute. + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *XAttr) Reset() { *m = XAttr{} } +func (m *XAttr) String() string { return proto1.CompactTextString(m) } +func (*XAttr) ProtoMessage() {} +func (*XAttr) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +// ADSEntry encodes information for a Windows Alternate Data Stream. +type ADSEntry struct { + // Name specifices the stream name. + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Data specifies the stream data. + // See also the description about the digest below. + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + // Digest is a CAS representation of the stream data. + // + // At least one of data or digest MUST be specified, and either one of them + // SHOULD be specified. + // + // How to access the actual data using the digest is implementation-specific, + // and implementations can choose not to implement digest. + // So, digest SHOULD be used only when the stream data is large. + Digest string `protobuf:"bytes,3,opt,name=digest" json:"digest,omitempty"` +} + +func (m *ADSEntry) Reset() { *m = ADSEntry{} } +func (m *ADSEntry) String() string { return proto1.CompactTextString(m) } +func (*ADSEntry) ProtoMessage() {} +func (*ADSEntry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func init() { + proto1.RegisterType((*Manifest)(nil), "proto.Manifest") + proto1.RegisterType((*Resource)(nil), "proto.Resource") + proto1.RegisterType((*XAttr)(nil), "proto.XAttr") + proto1.RegisterType((*ADSEntry)(nil), "proto.ADSEntry") +} + +func init() { proto1.RegisterFile("manifest.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 317 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x90, 0x4f, 0x4b, 0xf3, 0x40, + 0x10, 0xc6, 0x49, 0x93, 0xf4, 0x4d, 0xa7, 0xed, 0xab, 0x2c, 0x52, 0xe6, 0x18, 0x73, 0x0a, 0x08, + 0x15, 0xf4, 0xe0, 0xb9, 0xa2, 0x17, 0xc1, 0xcb, 0x7a, 0xf1, 0xba, 0xba, 0x6b, 0x5c, 0x21, 0xd9, + 0xb0, 0xd9, 0x80, 0xfa, 0xe5, 0xfc, 0x6a, 0x32, 0xb3, 0x69, 0xd1, 0x9b, 0xa7, 0x3c, 0xcf, 0x6f, + 0xfe, 0x64, 0xf6, 0x81, 0xff, 0xad, 0xea, 0xec, 0x8b, 0x19, 0xc2, 0xb6, 0xf7, 0x2e, 0x38, 0x91, + 0xf3, 0xa7, 0xba, 0x82, 0xe2, 0x7e, 0x2a, 0x88, 0x33, 0x28, 0xbc, 0x19, 0xdc, 0xe8, 0x9f, 0x0d, + 0x26, 0x65, 0x5a, 0x2f, 0x2f, 0x8e, 0x62, 0xf3, 0x56, 0x4e, 0x58, 0x1e, 0x1a, 0xaa, 0xaf, 0x19, + 0x14, 0x7b, 0x2c, 0x04, 0x64, 0xbd, 0x0a, 0xaf, 0x3c, 0xb5, 0x90, 0xac, 0xc5, 0x31, 0xa4, 0xa3, + 0xd5, 0x38, 0x2b, 0x93, 0x3a, 0x95, 0x24, 0x89, 0x34, 0x56, 0x63, 0x1a, 0x49, 0x63, 0xb5, 0xd8, + 0x40, 0x36, 0x0e, 0xc6, 0x63, 0x56, 0x26, 0xf5, 0xe2, 0x7a, 0x86, 0x89, 0x64, 0x2f, 0x10, 0xf2, + 0xc6, 0xbb, 0xb1, 0xc7, 0xfc, 0x50, 0x88, 0x80, 0xfe, 0xd4, 0x3a, 0x6d, 0x70, 0x5e, 0x26, 0xf5, + 0x5a, 0xb2, 0x26, 0x36, 0xd8, 0x4f, 0x83, 0xff, 0xca, 0xa4, 0xce, 0x24, 0x6b, 0xb1, 0x81, 0xb9, + 0xb6, 0x8d, 0x19, 0x02, 0x16, 0x7c, 0xd3, 0xe4, 0x88, 0x07, 0xe5, 0x1b, 0x13, 0x70, 0x41, 0xab, + 0xe5, 0xe4, 0xc4, 0x09, 0xe4, 0xad, 0x7a, 0x73, 0x1e, 0x81, 0x97, 0x44, 0xc3, 0xd4, 0x76, 0xce, + 0xe3, 0x72, 0xa2, 0x64, 0x44, 0x05, 0xf9, 0xbb, 0x0a, 0xc1, 0xe3, 0x8a, 0x43, 0x5a, 0x4d, 0x21, + 0x3d, 0xee, 0x42, 0xf0, 0x32, 0x96, 0xc4, 0x29, 0xa4, 0x4a, 0x0f, 0xb8, 0xfe, 0x15, 0xe3, 0xee, + 0xe6, 0xe1, 0xb6, 0x0b, 0xfe, 0x43, 0x52, 0xad, 0x3a, 0x87, 0x9c, 0x47, 0xe8, 0xfe, 0x4e, 0xb5, + 0x94, 0x39, 0x5d, 0xc4, 0x9a, 0x98, 0x56, 0x41, 0x71, 0x7c, 0x2b, 0xc9, 0xba, 0xba, 0x83, 0x62, + 0xbf, 0xe1, 0xaf, 0x33, 0x3f, 0x72, 0x48, 0xe3, 0x7b, 0xa3, 0x7b, 0x9a, 0xf3, 0x45, 0x97, 0xdf, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xef, 0x27, 0x99, 0xf7, 0x17, 0x02, 0x00, 0x00, +} diff --git a/vendor/github.com/containerd/continuity/proto/manifest.proto b/vendor/github.com/containerd/continuity/proto/manifest.proto new file mode 100644 index 0000000000000..66ef80f054ed7 --- /dev/null +++ b/vendor/github.com/containerd/continuity/proto/manifest.proto @@ -0,0 +1,97 @@ +syntax = "proto3"; + +package proto; + +// Manifest specifies the entries in a container bundle, keyed and sorted by +// path. +message Manifest { + repeated Resource resource = 1; +} + +message Resource { + // Path specifies the path from the bundle root. If more than one + // path is present, the entry may represent a hardlink, rather than using + // a link target. The path format is operating system specific. + repeated string path = 1; + + // NOTE(stevvooe): Need to define clear precedence for user/group/uid/gid precedence. + + // Uid specifies the user id for the resource. + int64 uid = 2; + + // Gid specifies the group id for the resource. + int64 gid = 3; + + // user and group are not currently used but their field numbers have been + // reserved for future use. As such, they are marked as deprecated. + string user = 4 [deprecated=true]; // "deprecated" stands for "reserved" here + string group = 5 [deprecated=true]; // "deprecated" stands for "reserved" here + + // Mode defines the file mode and permissions. We've used the same + // bit-packing from Go's os package, + // http://golang.org/pkg/os/#FileMode, since they've done the work of + // creating a cross-platform layout. + uint32 mode = 6; + + // NOTE(stevvooe): Beyond here, we start defining type specific fields. + + // Size specifies the size in bytes of the resource. This is only valid + // for regular files. + uint64 size = 7; + + // Digest specifies the content digest of the target file. Only valid for + // regular files. The strings are formatted in OCI style, i.e. :. + // For detailed information about the format, please refer to OCI Image Spec: + // https://github.com/opencontainers/image-spec/blob/master/descriptor.md#digests-and-verification + // The digests are sorted in lexical order and implementations may choose + // which algorithms they prefer. + repeated string digest = 8; + + // Target defines the target of a hard or soft link. Absolute links start + // with a slash and specify the resource relative to the bundle root. + // Relative links do not start with a slash and are relative to the + // resource path. + string target = 9; + + // Major specifies the major device number for character and block devices. + uint64 major = 10; + + // Minor specifies the minor device number for character and block devices. + uint64 minor = 11; + + // Xattr provides storage for extended attributes for the target resource. + repeated XAttr xattr = 12; + + // Ads stores one or more alternate data streams for the target resource. + repeated ADSEntry ads = 13; + +} + +// XAttr encodes extended attributes for a resource. +message XAttr { + // Name specifies the attribute name. + string name = 1; + + // Data specifies the associated data for the attribute. + bytes data = 2; +} + +// ADSEntry encodes information for a Windows Alternate Data Stream. +message ADSEntry { + // Name specifices the stream name. + string name = 1; + + // Data specifies the stream data. + // See also the description about the digest below. + bytes data = 2; + + // Digest is a CAS representation of the stream data. + // + // At least one of data or digest MUST be specified, and either one of them + // SHOULD be specified. + // + // How to access the actual data using the digest is implementation-specific, + // and implementations can choose not to implement digest. + // So, digest SHOULD be used only when the stream data is large. + string digest = 3; +} diff --git a/vendor/github.com/containerd/continuity/resource.go b/vendor/github.com/containerd/continuity/resource.go new file mode 100644 index 0000000000000..3643effb342a3 --- /dev/null +++ b/vendor/github.com/containerd/continuity/resource.go @@ -0,0 +1,574 @@ +package continuity + +import ( + "errors" + "fmt" + "os" + "reflect" + "sort" + + pb "github.com/containerd/continuity/proto" + "github.com/opencontainers/go-digest" +) + +// TODO(stevvooe): A record based model, somewhat sketched out at the bottom +// of this file, will be more flexible. Another possibly is to tie the package +// interface directly to the protobuf type. This will have efficiency +// advantages at the cost coupling the nasty codegen types to the exported +// interface. + +type Resource interface { + // Path provides the primary resource path relative to the bundle root. In + // cases where resources have more than one path, such as with hard links, + // this will return the primary path, which is often just the first entry. + Path() string + + // Mode returns the + Mode() os.FileMode + + UID() int64 + GID() int64 +} + +// ByPath provides the canonical sort order for a set of resources. Use with +// sort.Stable for deterministic sorting. +type ByPath []Resource + +func (bp ByPath) Len() int { return len(bp) } +func (bp ByPath) Swap(i, j int) { bp[i], bp[j] = bp[j], bp[i] } +func (bp ByPath) Less(i, j int) bool { return bp[i].Path() < bp[j].Path() } + +type XAttrer interface { + XAttrs() map[string][]byte +} + +// Hardlinkable is an interface that a resource type satisfies if it can be a +// hardlink target. +type Hardlinkable interface { + // Paths returns all paths of the resource, including the primary path + // returned by Resource.Path. If len(Paths()) > 1, the resource is a hard + // link. + Paths() []string +} + +type RegularFile interface { + Resource + XAttrer + Hardlinkable + + Size() int64 + Digests() []digest.Digest +} + +// Merge two or more Resources into new file. Typically, this should be +// used to merge regular files as hardlinks. If the files are not identical, +// other than Paths and Digests, the merge will fail and an error will be +// returned. +func Merge(fs ...Resource) (Resource, error) { + if len(fs) < 1 { + return nil, fmt.Errorf("please provide a resource to merge") + } + + if len(fs) == 1 { + return fs[0], nil + } + + var paths []string + var digests []digest.Digest + bypath := map[string][]Resource{} + + // The attributes are all compared against the first to make sure they + // agree before adding to the above collections. If any of these don't + // correctly validate, the merge fails. + prototype := fs[0] + xattrs := make(map[string][]byte) + + // initialize xattrs for use below. All files must have same xattrs. + if prototypeXAttrer, ok := prototype.(XAttrer); ok { + for attr, value := range prototypeXAttrer.XAttrs() { + xattrs[attr] = value + } + } + + for _, f := range fs { + h, isHardlinkable := f.(Hardlinkable) + if !isHardlinkable { + return nil, errNotAHardLink + } + + if f.Mode() != prototype.Mode() { + return nil, fmt.Errorf("modes do not match: %v != %v", f.Mode(), prototype.Mode()) + } + + if f.UID() != prototype.UID() { + return nil, fmt.Errorf("uid does not match: %v != %v", f.UID(), prototype.UID()) + } + + if f.GID() != prototype.GID() { + return nil, fmt.Errorf("gid does not match: %v != %v", f.GID(), prototype.GID()) + } + + if xattrer, ok := f.(XAttrer); ok { + fxattrs := xattrer.XAttrs() + if !reflect.DeepEqual(fxattrs, xattrs) { + return nil, fmt.Errorf("resource %q xattrs do not match: %v != %v", f, fxattrs, xattrs) + } + } + + for _, p := range h.Paths() { + pfs, ok := bypath[p] + if !ok { + // ensure paths are unique by only appending on a new path. + paths = append(paths, p) + } + + bypath[p] = append(pfs, f) + } + + if regFile, isRegFile := f.(RegularFile); isRegFile { + prototypeRegFile, prototypeIsRegFile := prototype.(RegularFile) + if !prototypeIsRegFile { + return nil, errors.New("prototype is not a regular file") + } + + if regFile.Size() != prototypeRegFile.Size() { + return nil, fmt.Errorf("size does not match: %v != %v", regFile.Size(), prototypeRegFile.Size()) + } + + digests = append(digests, regFile.Digests()...) + } else if device, isDevice := f.(Device); isDevice { + prototypeDevice, prototypeIsDevice := prototype.(Device) + if !prototypeIsDevice { + return nil, errors.New("prototype is not a device") + } + + if device.Major() != prototypeDevice.Major() { + return nil, fmt.Errorf("major number does not match: %v != %v", device.Major(), prototypeDevice.Major()) + } + if device.Minor() != prototypeDevice.Minor() { + return nil, fmt.Errorf("minor number does not match: %v != %v", device.Minor(), prototypeDevice.Minor()) + } + } else if _, isNamedPipe := f.(NamedPipe); isNamedPipe { + _, prototypeIsNamedPipe := prototype.(NamedPipe) + if !prototypeIsNamedPipe { + return nil, errors.New("prototype is not a named pipe") + } + } else { + return nil, errNotAHardLink + } + } + + sort.Stable(sort.StringSlice(paths)) + + // Choose a "canonical" file. Really, it is just the first file to sort + // against. We also effectively select the very first digest as the + // "canonical" one for this file. + first := bypath[paths[0]][0] + + resource := resource{ + paths: paths, + mode: first.Mode(), + uid: first.UID(), + gid: first.GID(), + xattrs: xattrs, + } + + switch typedF := first.(type) { + case RegularFile: + var err error + digests, err = uniqifyDigests(digests...) + if err != nil { + return nil, err + } + + return ®ularFile{ + resource: resource, + size: typedF.Size(), + digests: digests, + }, nil + case Device: + return &device{ + resource: resource, + major: typedF.Major(), + minor: typedF.Minor(), + }, nil + + case NamedPipe: + return &namedPipe{ + resource: resource, + }, nil + + default: + return nil, errNotAHardLink + } +} + +type Directory interface { + Resource + XAttrer + + // Directory is a no-op method to identify directory objects by interface. + Directory() +} + +type SymLink interface { + Resource + + // Target returns the target of the symlink contained in the . + Target() string +} + +type NamedPipe interface { + Resource + Hardlinkable + XAttrer + + // Pipe is a no-op method to allow consistent resolution of NamedPipe + // interface. + Pipe() +} + +type Device interface { + Resource + Hardlinkable + XAttrer + + Major() uint64 + Minor() uint64 +} + +type resource struct { + paths []string + mode os.FileMode + uid, gid int64 + xattrs map[string][]byte +} + +var _ Resource = &resource{} + +func (r *resource) Path() string { + if len(r.paths) < 1 { + return "" + } + + return r.paths[0] +} + +func (r *resource) Mode() os.FileMode { + return r.mode +} + +func (r *resource) UID() int64 { + return r.uid +} + +func (r *resource) GID() int64 { + return r.gid +} + +type regularFile struct { + resource + size int64 + digests []digest.Digest +} + +var _ RegularFile = ®ularFile{} + +// newRegularFile returns the RegularFile, using the populated base resource +// and one or more digests of the content. +func newRegularFile(base resource, paths []string, size int64, dgsts ...digest.Digest) (RegularFile, error) { + if !base.Mode().IsRegular() { + return nil, fmt.Errorf("not a regular file") + } + + base.paths = make([]string, len(paths)) + copy(base.paths, paths) + + // make our own copy of digests + ds := make([]digest.Digest, len(dgsts)) + copy(ds, dgsts) + + return ®ularFile{ + resource: base, + size: size, + digests: ds, + }, nil +} + +func (rf *regularFile) Paths() []string { + paths := make([]string, len(rf.paths)) + copy(paths, rf.paths) + return paths +} + +func (rf *regularFile) Size() int64 { + return rf.size +} + +func (rf *regularFile) Digests() []digest.Digest { + digests := make([]digest.Digest, len(rf.digests)) + copy(digests, rf.digests) + return digests +} + +func (rf *regularFile) XAttrs() map[string][]byte { + xattrs := make(map[string][]byte, len(rf.xattrs)) + + for attr, value := range rf.xattrs { + xattrs[attr] = append(xattrs[attr], value...) + } + + return xattrs +} + +type directory struct { + resource +} + +var _ Directory = &directory{} + +func newDirectory(base resource) (Directory, error) { + if !base.Mode().IsDir() { + return nil, fmt.Errorf("not a directory") + } + + return &directory{ + resource: base, + }, nil +} + +func (d *directory) Directory() {} + +func (d *directory) XAttrs() map[string][]byte { + xattrs := make(map[string][]byte, len(d.xattrs)) + + for attr, value := range d.xattrs { + xattrs[attr] = append(xattrs[attr], value...) + } + + return xattrs +} + +type symLink struct { + resource + target string +} + +var _ SymLink = &symLink{} + +func newSymLink(base resource, target string) (SymLink, error) { + if base.Mode()&os.ModeSymlink == 0 { + return nil, fmt.Errorf("not a symlink") + } + + return &symLink{ + resource: base, + target: target, + }, nil +} + +func (l *symLink) Target() string { + return l.target +} + +type namedPipe struct { + resource +} + +var _ NamedPipe = &namedPipe{} + +func newNamedPipe(base resource, paths []string) (NamedPipe, error) { + if base.Mode()&os.ModeNamedPipe == 0 { + return nil, fmt.Errorf("not a namedpipe") + } + + base.paths = make([]string, len(paths)) + copy(base.paths, paths) + + return &namedPipe{ + resource: base, + }, nil +} + +func (np *namedPipe) Pipe() {} + +func (np *namedPipe) Paths() []string { + paths := make([]string, len(np.paths)) + copy(paths, np.paths) + return paths +} + +func (np *namedPipe) XAttrs() map[string][]byte { + xattrs := make(map[string][]byte, len(np.xattrs)) + + for attr, value := range np.xattrs { + xattrs[attr] = append(xattrs[attr], value...) + } + + return xattrs +} + +type device struct { + resource + major, minor uint64 +} + +var _ Device = &device{} + +func newDevice(base resource, paths []string, major, minor uint64) (Device, error) { + if base.Mode()&os.ModeDevice == 0 { + return nil, fmt.Errorf("not a device") + } + + base.paths = make([]string, len(paths)) + copy(base.paths, paths) + + return &device{ + resource: base, + major: major, + minor: minor, + }, nil +} + +func (d *device) Paths() []string { + paths := make([]string, len(d.paths)) + copy(paths, d.paths) + return paths +} + +func (d *device) XAttrs() map[string][]byte { + xattrs := make(map[string][]byte, len(d.xattrs)) + + for attr, value := range d.xattrs { + xattrs[attr] = append(xattrs[attr], value...) + } + + return xattrs +} + +func (d device) Major() uint64 { + return d.major +} + +func (d device) Minor() uint64 { + return d.minor +} + +// toProto converts a resource to a protobuf record. We'd like to push this +// the individual types but we want to keep this all together during +// prototyping. +func toProto(resource Resource) *pb.Resource { + b := &pb.Resource{ + Path: []string{resource.Path()}, + Mode: uint32(resource.Mode()), + Uid: resource.UID(), + Gid: resource.GID(), + } + + if xattrer, ok := resource.(XAttrer); ok { + // Sorts the XAttrs by name for consistent ordering. + keys := []string{} + xattrs := xattrer.XAttrs() + for k := range xattrs { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + b.Xattr = append(b.Xattr, &pb.XAttr{Name: k, Data: xattrs[k]}) + } + } + + switch r := resource.(type) { + case RegularFile: + b.Path = r.Paths() + b.Size = uint64(r.Size()) + + for _, dgst := range r.Digests() { + b.Digest = append(b.Digest, dgst.String()) + } + case SymLink: + b.Target = r.Target() + case Device: + b.Major, b.Minor = r.Major(), r.Minor() + b.Path = r.Paths() + case NamedPipe: + b.Path = r.Paths() + } + + // enforce a few stability guarantees that may not be provided by the + // resource implementation. + sort.Strings(b.Path) + + return b +} + +// fromProto converts from a protobuf Resource to a Resource interface. +func fromProto(b *pb.Resource) (Resource, error) { + base := &resource{ + paths: b.Path, + mode: os.FileMode(b.Mode), + uid: b.Uid, + gid: b.Gid, + } + + base.xattrs = make(map[string][]byte, len(b.Xattr)) + + for _, attr := range b.Xattr { + base.xattrs[attr.Name] = attr.Data + } + + switch { + case base.Mode().IsRegular(): + dgsts := make([]digest.Digest, len(b.Digest)) + for i, dgst := range b.Digest { + // TODO(stevvooe): Should we be validating at this point? + dgsts[i] = digest.Digest(dgst) + } + + return newRegularFile(*base, b.Path, int64(b.Size), dgsts...) + case base.Mode().IsDir(): + return newDirectory(*base) + case base.Mode()&os.ModeSymlink != 0: + return newSymLink(*base, b.Target) + case base.Mode()&os.ModeNamedPipe != 0: + return newNamedPipe(*base, b.Path) + case base.Mode()&os.ModeDevice != 0: + return newDevice(*base, b.Path, b.Major, b.Minor) + } + + return nil, fmt.Errorf("unknown resource record (%#v): %s", b, base.Mode()) +} + +// NOTE(stevvooe): An alternative model that supports inline declaration. +// Convenient for unit testing where inline declarations may be desirable but +// creates an awkward API for the standard use case. + +// type ResourceKind int + +// const ( +// ResourceRegularFile = iota + 1 +// ResourceDirectory +// ResourceSymLink +// Resource +// ) + +// type Resource struct { +// Kind ResourceKind +// Paths []string +// Mode os.FileMode +// UID string +// GID string +// Size int64 +// Digests []digest.Digest +// Target string +// Major, Minor int +// XAttrs map[string][]byte +// } + +// type RegularFile struct { +// Paths []string +// Size int64 +// Digests []digest.Digest +// Perm os.FileMode // os.ModePerm + sticky, setuid, setgid +// } diff --git a/vendor/github.com/containerd/continuity/resource_unix.go b/vendor/github.com/containerd/continuity/resource_unix.go new file mode 100644 index 0000000000000..4144643e02b78 --- /dev/null +++ b/vendor/github.com/containerd/continuity/resource_unix.go @@ -0,0 +1,37 @@ +// +build linux darwin freebsd solaris + +package continuity + +import ( + "fmt" + "os" + "syscall" +) + +// newBaseResource returns a *resource, populated with data from p and fi, +// where p will be populated directly. +func newBaseResource(p string, fi os.FileInfo) (*resource, error) { + // TODO(stevvooe): This need to be resolved for the container's root, + // where here we are really getting the host OS's value. We need to allow + // this be passed in and fixed up to make these uid/gid mappings portable. + // Either this can be part of the driver or we can achieve it through some + // other mechanism. + sys, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + // TODO(stevvooe): This may not be a hard error for all platforms. We + // may want to move this to the driver. + return nil, fmt.Errorf("unable to resolve syscall.Stat_t from (os.FileInfo).Sys(): %#v", fi) + } + + return &resource{ + paths: []string{p}, + mode: fi.Mode(), + + uid: int64(sys.Uid), + gid: int64(sys.Gid), + + // NOTE(stevvooe): Population of shared xattrs field is deferred to + // the resource types that populate it. Since they are a property of + // the context, they must set there. + }, nil +} diff --git a/vendor/github.com/containerd/continuity/resource_windows.go b/vendor/github.com/containerd/continuity/resource_windows.go new file mode 100644 index 0000000000000..7b44414ac5a3a --- /dev/null +++ b/vendor/github.com/containerd/continuity/resource_windows.go @@ -0,0 +1,12 @@ +package continuity + +import "os" + +// newBaseResource returns a *resource, populated with data from p and fi, +// where p will be populated directly. +func newBaseResource(p string, fi os.FileInfo) (*resource, error) { + return &resource{ + paths: []string{p}, + mode: fi.Mode(), + }, nil +} diff --git a/vendor/github.com/containerd/continuity/sysx/README.md b/vendor/github.com/containerd/continuity/sysx/README.md new file mode 100644 index 0000000000000..ad7aee5331682 --- /dev/null +++ b/vendor/github.com/containerd/continuity/sysx/README.md @@ -0,0 +1,3 @@ +This package is for internal use only. It is intended to only have +temporary changes before they are upstreamed to golang.org/x/sys/ +(a.k.a. https://github.com/golang/sys). diff --git a/vendor/github.com/containerd/continuity/sysx/asm.s b/vendor/github.com/containerd/continuity/sysx/asm.s deleted file mode 100644 index 8ed2fdb94b1d8..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/asm.s +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2014 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 !gccgo - -#include "textflag.h" - -TEXT ·use(SB),NOSPLIT,$0 - RET diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_darwin.go b/vendor/github.com/containerd/continuity/sysx/chmod_darwin.go deleted file mode 100644 index e3ae2b7bbf4b5..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_darwin.go +++ /dev/null @@ -1,18 +0,0 @@ -package sysx - -const ( - // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in - AtSymlinkNofollow = 0x20 -) - -const ( - - // SYS_FCHMODAT defined from golang.org/sys/unix - SYS_FCHMODAT = 467 -) - -// These functions will be generated by generate.sh -// $ GOOS=darwin GOARCH=386 ./generate.sh chmod -// $ GOOS=darwin GOARCH=amd64 ./generate.sh chmod - -//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go b/vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go deleted file mode 100644 index 5a8cf5b57db01..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_darwin_386.go +++ /dev/null @@ -1,25 +0,0 @@ -// mksyscall.pl -l32 chmod_darwin.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -package sysx - -import ( - "syscall" - "unsafe" -) - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - use(unsafe.Pointer(_p0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go b/vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go deleted file mode 100644 index 3287d1d5799aa..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_darwin_amd64.go +++ /dev/null @@ -1,25 +0,0 @@ -// mksyscall.pl chmod_darwin.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -package sysx - -import ( - "syscall" - "unsafe" -) - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - use(unsafe.Pointer(_p0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go b/vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go deleted file mode 100644 index b64a708be1b51..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_freebsd.go +++ /dev/null @@ -1,17 +0,0 @@ -package sysx - -const ( - // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in - AtSymlinkNofollow = 0x200 -) - -const ( - - // SYS_FCHMODAT defined from golang.org/sys/unix - SYS_FCHMODAT = 490 -) - -// These functions will be generated by generate.sh -// $ GOOS=freebsd GOARCH=amd64 ./generate.sh chmod - -//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go b/vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go deleted file mode 100644 index 5a271abb1e7fb..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_freebsd_amd64.go +++ /dev/null @@ -1,25 +0,0 @@ -// mksyscall.pl chmod_freebsd.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -package sysx - -import ( - "syscall" - "unsafe" -) - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall.Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) - use(unsafe.Pointer(_p0)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_linux.go b/vendor/github.com/containerd/continuity/sysx/chmod_linux.go deleted file mode 100644 index 89df6d38ef150..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_linux.go +++ /dev/null @@ -1,12 +0,0 @@ -package sysx - -import "syscall" - -const ( - // AtSymlinkNoFollow defined from AT_SYMLINK_NOFOLLOW in /usr/include/linux/fcntl.h - AtSymlinkNofollow = 0x100 -) - -func Fchmodat(dirfd int, path string, mode uint32, flags int) error { - return syscall.Fchmodat(dirfd, path, mode, flags) -} diff --git a/vendor/github.com/containerd/continuity/sysx/chmod_solaris.go b/vendor/github.com/containerd/continuity/sysx/chmod_solaris.go deleted file mode 100644 index 3ba6e5edc8a35..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/chmod_solaris.go +++ /dev/null @@ -1,11 +0,0 @@ -package sysx - -import "golang.org/x/sys/unix" - -const ( - AtSymlinkNofollow = unix.AT_SYMLINK_NOFOLLOW -) - -func Fchmodat(dirfd int, path string, mode uint32, flags int) error { - return unix.Fchmodat(dirfd, path, mode, flags) -} diff --git a/vendor/github.com/containerd/continuity/sysx/sys.go b/vendor/github.com/containerd/continuity/sysx/sys.go deleted file mode 100644 index 0bb1676283836..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/sys.go +++ /dev/null @@ -1,37 +0,0 @@ -package sysx - -import ( - "syscall" - "unsafe" -) - -var _zero uintptr - -// use is a no-op, but the compiler cannot see that it is. -// Calling use(p) ensures that p is kept live until that point. -//go:noescape -func use(p unsafe.Pointer) - -// Do the interface allocations only once for common -// Errno values. -var ( - errEAGAIN error = syscall.EAGAIN - errEINVAL error = syscall.EINVAL - errENOENT error = syscall.ENOENT -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return nil - case syscall.EAGAIN: - return errEAGAIN - case syscall.EINVAL: - return errEINVAL - case syscall.ENOENT: - return errENOENT - } - return e -} diff --git a/vendor/github.com/containerd/continuity/sysx/xattr.go b/vendor/github.com/containerd/continuity/sysx/xattr.go index 20937c2d4d94b..a59efee9ae790 100644 --- a/vendor/github.com/containerd/continuity/sysx/xattr.go +++ b/vendor/github.com/containerd/continuity/sysx/xattr.go @@ -1,14 +1,56 @@ +// +build linux darwin + package sysx import ( "bytes" - "fmt" "syscall" + + "golang.org/x/sys/unix" ) -const defaultXattrBufferSize = 5 +// Listxattr calls syscall listxattr and reads all content +// and returns a string array +func Listxattr(path string) ([]string, error) { + return listxattrAll(path, unix.Listxattr) +} + +// Removexattr calls syscall removexattr +func Removexattr(path string, attr string) (err error) { + return unix.Removexattr(path, attr) +} + +// Setxattr calls syscall setxattr +func Setxattr(path string, attr string, data []byte, flags int) (err error) { + return unix.Setxattr(path, attr, data, flags) +} + +// Getxattr calls syscall getxattr +func Getxattr(path, attr string) ([]byte, error) { + return getxattrAll(path, attr, unix.Getxattr) +} -var ErrNotSupported = fmt.Errorf("not supported") +// LListxattr lists xattrs, not following symlinks +func LListxattr(path string) ([]string, error) { + return listxattrAll(path, unix.Llistxattr) +} + +// LRemovexattr removes an xattr, not following symlinks +func LRemovexattr(path string, attr string) (err error) { + return unix.Lremovexattr(path, attr) +} + +// LSetxattr sets an xattr, not following symlinks +func LSetxattr(path string, attr string, data []byte, flags int) (err error) { + return unix.Lsetxattr(path, attr, data, flags) +} + +// LGetxattr gets an xattr, not following symlinks +func LGetxattr(path, attr string) ([]byte, error) { + return getxattrAll(path, attr, unix.Lgetxattr) +} + +const defaultXattrBufferSize = 5 type listxattrFunc func(path string, dest []byte) (int, error) diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go b/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go deleted file mode 100644 index 1164a7d11c1cd..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_darwin.go +++ /dev/null @@ -1,71 +0,0 @@ -package sysx - -// These functions will be generated by generate.sh -// $ GOOS=darwin GOARCH=386 ./generate.sh xattr -// $ GOOS=darwin GOARCH=amd64 ./generate.sh xattr - -//sys getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) -//sys setxattr(path string, attr string, data []byte, flags int) (err error) -//sys removexattr(path string, attr string, options int) (err error) -//sys listxattr(path string, dest []byte, options int) (sz int, err error) -//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) - -const ( - xattrNoFollow = 0x01 -) - -func listxattrFollow(path string, dest []byte) (sz int, err error) { - return listxattr(path, dest, 0) -} - -// Listxattr calls syscall getxattr -func Listxattr(path string) ([]string, error) { - return listxattrAll(path, listxattrFollow) -} - -// Removexattr calls syscall getxattr -func Removexattr(path string, attr string) (err error) { - return removexattr(path, attr, 0) -} - -// Setxattr calls syscall setxattr -func Setxattr(path string, attr string, data []byte, flags int) (err error) { - return setxattr(path, attr, data, flags) -} - -func getxattrFollow(path, attr string, dest []byte) (sz int, err error) { - return getxattr(path, attr, dest, 0, 0) -} - -// Getxattr calls syscall getxattr -func Getxattr(path, attr string) ([]byte, error) { - return getxattrAll(path, attr, getxattrFollow) -} - -func listxattrNoFollow(path string, dest []byte) (sz int, err error) { - return listxattr(path, dest, xattrNoFollow) -} - -// LListxattr calls syscall listxattr with XATTR_NOFOLLOW -func LListxattr(path string) ([]string, error) { - return listxattrAll(path, listxattrNoFollow) -} - -// LRemovexattr calls syscall removexattr with XATTR_NOFOLLOW -func LRemovexattr(path string, attr string) (err error) { - return removexattr(path, attr, xattrNoFollow) -} - -// Setxattr calls syscall setxattr with XATTR_NOFOLLOW -func LSetxattr(path string, attr string, data []byte, flags int) (err error) { - return setxattr(path, attr, data, flags|xattrNoFollow) -} - -func getxattrNoFollow(path, attr string, dest []byte) (sz int, err error) { - return getxattr(path, attr, dest, 0, xattrNoFollow) -} - -// LGetxattr calls syscall getxattr with XATTR_NOFOLLOW -func LGetxattr(path, attr string) ([]byte, error) { - return getxattrAll(path, attr, getxattrNoFollow) -} diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_darwin_386.go b/vendor/github.com/containerd/continuity/sysx/xattr_darwin_386.go deleted file mode 100644 index aa896b57fc47a..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_darwin_386.go +++ /dev/null @@ -1,111 +0,0 @@ -// mksyscall.pl -l32 xattr_darwin.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -package sysx - -import ( - "syscall" - "unsafe" -) - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(attr) - if err != nil { - return - } - var _p2 unsafe.Pointer - if len(dest) > 0 { - _p2 = unsafe.Pointer(&dest[0]) - } else { - _p2 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) - use(unsafe.Pointer(_p0)) - use(unsafe.Pointer(_p1)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data []byte, flags int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(attr) - if err != nil { - return - } - var _p2 unsafe.Pointer - if len(data) > 0 { - _p2 = unsafe.Pointer(&data[0]) - } else { - _p2 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) - use(unsafe.Pointer(_p0)) - use(unsafe.Pointer(_p1)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - use(unsafe.Pointer(_p0)) - use(unsafe.Pointer(_p1)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest []byte, options int) (sz int, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(dest) > 0 { - _p1 = unsafe.Pointer(&dest[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) - use(unsafe.Pointer(_p0)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_darwin_amd64.go b/vendor/github.com/containerd/continuity/sysx/xattr_darwin_amd64.go deleted file mode 100644 index 6ff27e270340e..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_darwin_amd64.go +++ /dev/null @@ -1,111 +0,0 @@ -// mksyscall.pl xattr_darwin.go -// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT - -package sysx - -import ( - "syscall" - "unsafe" -) - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func getxattr(path string, attr string, dest []byte, pos int, options int) (sz int, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(attr) - if err != nil { - return - } - var _p2 unsafe.Pointer - if len(dest) > 0 { - _p2 = unsafe.Pointer(&dest[0]) - } else { - _p2 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), uintptr(pos), uintptr(options)) - use(unsafe.Pointer(_p0)) - use(unsafe.Pointer(_p1)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func setxattr(path string, attr string, data []byte, flags int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(attr) - if err != nil { - return - } - var _p2 unsafe.Pointer - if len(data) > 0 { - _p2 = unsafe.Pointer(&data[0]) - } else { - _p2 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0) - use(unsafe.Pointer(_p0)) - use(unsafe.Pointer(_p1)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func removexattr(path string, attr string, options int) (err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(attr) - if err != nil { - return - } - _, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(options)) - use(unsafe.Pointer(_p0)) - use(unsafe.Pointer(_p1)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func listxattr(path string, dest []byte, options int) (sz int, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(dest) > 0 { - _p1 = unsafe.Pointer(&dest[0]) - } else { - _p1 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall.Syscall6(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)), uintptr(options), 0, 0) - use(unsafe.Pointer(_p0)) - sz = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_freebsd.go b/vendor/github.com/containerd/continuity/sysx/xattr_freebsd.go deleted file mode 100644 index e8017d317f3ae..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_freebsd.go +++ /dev/null @@ -1,12 +0,0 @@ -package sysx - -import ( - "errors" -) - -// Initial stub version for FreeBSD. FreeBSD has a different -// syscall API from Darwin and Linux for extended attributes; -// it is also not widely used. It is not exposed at all by the -// Go syscall package, so we need to implement directly eventually. - -var unsupported = errors.New("extended attributes unsupported on FreeBSD") diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_linux.go b/vendor/github.com/containerd/continuity/sysx/xattr_linux.go deleted file mode 100644 index 311b896d9e39f..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_linux.go +++ /dev/null @@ -1,44 +0,0 @@ -package sysx - -import "golang.org/x/sys/unix" - -// Listxattr calls syscall listxattr and reads all content -// and returns a string array -func Listxattr(path string) ([]string, error) { - return listxattrAll(path, unix.Listxattr) -} - -// Removexattr calls syscall removexattr -func Removexattr(path string, attr string) (err error) { - return unix.Removexattr(path, attr) -} - -// Setxattr calls syscall setxattr -func Setxattr(path string, attr string, data []byte, flags int) (err error) { - return unix.Setxattr(path, attr, data, flags) -} - -// Getxattr calls syscall getxattr -func Getxattr(path, attr string) ([]byte, error) { - return getxattrAll(path, attr, unix.Getxattr) -} - -// LListxattr lists xattrs, not following symlinks -func LListxattr(path string) ([]string, error) { - return listxattrAll(path, unix.Llistxattr) -} - -// LRemovexattr removes an xattr, not following symlinks -func LRemovexattr(path string, attr string) (err error) { - return unix.Lremovexattr(path, attr) -} - -// LSetxattr sets an xattr, not following symlinks -func LSetxattr(path string, attr string, data []byte, flags int) (err error) { - return unix.Lsetxattr(path, attr, data, flags) -} - -// LGetxattr gets an xattr, not following symlinks -func LGetxattr(path, attr string) ([]byte, error) { - return getxattrAll(path, attr, unix.Lgetxattr) -} diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_openbsd.go b/vendor/github.com/containerd/continuity/sysx/xattr_openbsd.go deleted file mode 100644 index 723619977d5bb..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_openbsd.go +++ /dev/null @@ -1,7 +0,0 @@ -package sysx - -import ( - "errors" -) - -var unsupported = errors.New("extended attributes unsupported on OpenBSD") diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_solaris.go b/vendor/github.com/containerd/continuity/sysx/xattr_solaris.go deleted file mode 100644 index fc523fcbbe171..0000000000000 --- a/vendor/github.com/containerd/continuity/sysx/xattr_solaris.go +++ /dev/null @@ -1,12 +0,0 @@ -package sysx - -import ( - "errors" -) - -// Initial stub version for Solaris. Solaris has a different -// syscall API from Darwin and Linux for extended attributes; -// it is also not widely used. It is not exposed at all by the -// Go syscall package, so we need to implement directly eventually. - -var unsupported = errors.New("extended attributes unsupported on Solaris") diff --git a/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go b/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go index c8389bc136695..4f6a12e355926 100644 --- a/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go +++ b/vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go @@ -1,7 +1,14 @@ -// +build freebsd openbsd solaris +// +build !linux,!darwin package sysx +import ( + "errors" + "runtime" +) + +var unsupported = errors.New("extended attributes unsupported on " + runtime.GOOS) + // Listxattr calls syscall listxattr and reads all content // and returns a string array func Listxattr(path string) ([]string, error) { diff --git a/vendor/github.com/containerd/continuity/vendor.conf b/vendor/github.com/containerd/continuity/vendor.conf index 7c80deec5833b..5bd88d5fd76df 100644 --- a/vendor/github.com/containerd/continuity/vendor.conf +++ b/vendor/github.com/containerd/continuity/vendor.conf @@ -10,4 +10,4 @@ github.com/spf13/pflag 4c012f6dcd9546820e378d0bdda4d8fc772cdfea golang.org/x/crypto 9f005a07e0d31d45e6656d241bb5c0f2efd4bc94 golang.org/x/net a337091b0525af65de94df2eb7e98bd9962dcbe2 golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c -golang.org/x/sys 665f6529cca930e27b831a0d1dafffbe1c172924 +golang.org/x/sys 77b0e4315053a57ed2962443614bdb28db152054 diff --git a/vendor/github.com/containerd/cri/LICENSE b/vendor/github.com/containerd/cri/LICENSE new file mode 100644 index 0000000000000..8dada3edaf50d --- /dev/null +++ b/vendor/github.com/containerd/cri/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/vendor/github.com/containerd/cri/README.md b/vendor/github.com/containerd/cri/README.md new file mode 100644 index 0000000000000..a97c2fe3da60c --- /dev/null +++ b/vendor/github.com/containerd/cri/README.md @@ -0,0 +1,176 @@ +# cri +

+ + +

+ +*Note: The standalone `cri-containerd` binary is end-of-life. `cri-containerd` is +transitioning from a standalone binary that talks to containerd to a plugin within +containerd. This github branch is for the `cri` plugin. See +[standalone-cri-containerd branch](https://github.com/containerd/cri/tree/standalone-cri-containerd) +for information about the standalone version of `cri-containerd`.* + +*Note: You need to [drain your node](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/) before upgrading from standalone `cri-containerd` to containerd with `cri` plugin.* + +[![Build Status](https://api.travis-ci.org/containerd/cri.svg?style=flat-square)](https://travis-ci.org/containerd/cri) +[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/cri)](https://goreportcard.com/report/github.com/containerd/cri) + +`cri` is a [containerd](https://containerd.io/) plugin implementation of Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto). + +With it, you could run Kubernetes using containerd as the container runtime. +![cri](./docs/cri.png) +## Current Status +`cri` is a native plugin of containerd 1.1 and above. It is built into containerd and enabled by default. + +`cri` is in GA: +* It is feature complete. +* It (the GA version) works with Kubernetes 1.10 and above. +* It has passed all [CRI validation tests](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md). +* It has passed all [node e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-node-tests.md). +* It has passed all [e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-tests.md). + +See [test dashboard](https://k8s-testgrid.appspot.com/sig-node-containerd) +## Support Metrics +| CRI-Containerd Version | Containerd Version | Kubernetes Version | CRI Version | +|:----------------------:|:------------------:|:------------------:|:-----------:| +| v1.0.0-alpha.x | | 1.7, 1.8 | v1alpha1 | +| v1.0.0-beta.x | | 1.9 | v1alpha1 | +| End-Of-Life | v1.1 | 1.10+ | v1alpha2 | +| | HEAD | 1.10+ | v1alpha2 | + +## Production Quality Cluster on GCE +For a production quality cluster on GCE brought up with `kube-up.sh` refer [here](docs/kube-up.md). +## Installing with Ansible and Kubeadm +For a multi node cluster installer and bring up steps using ansible and kubeadm refer [here](contrib/ansible/README.md). +## Custom Installation +For non ansible users, you can download the `cri-containerd` release tarball and deploy +kubernetes cluster using kubeadm as described [here](docs/installation.md). +## Getting Started for Developers +### Binary Dependencies and Specifications +The current release of the `cri` plugin has the following dependencies: +* [containerd](https://github.com/containerd/containerd) +* [runc](https://github.com/opencontainers/runc) +* [CNI](https://github.com/containernetworking/cni) + +See [versions](./vendor.conf) of these dependencies `cri` is tested with. + +As containerd and runc move to their respective general availability releases, +we will do our best to rebase/retest `cri` with these releases on a +weekly/monthly basis. Similarly, given that `cri` uses the Open +Container Initiative (OCI) [image](https://github.com/opencontainers/image-spec) +and [runtime](https://github.com/opencontainers/runtime-spec) specifications, we +will also do our best to update `cri` to the latest releases of these +specifications as appropriate. +### Install Dependencies +1. Install development libraries: +* **libseccomp development library.** Required by `cri` and runc seccomp support. `libseccomp-dev` (Ubuntu, Debian) / `libseccomp-devel` +(Fedora, CentOS, RHEL). On releases of Ubuntu <=Trusty and Debian <=jessie a +backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty. +* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL) +2. Install **`socat`** (required by portforward). +2. Install and setup a go 1.10 development environment. +3. Make a local clone of this repository. +4. Install binary dependencies by running the following command from your cloned `cri/` project directory: +```bash +# Note: install.deps installs the above mentioned runc, containerd, and CNI +# binary dependencies. install.deps is only provided for general use and ease of +# testing. To customize `runc` and `containerd` build tags and/or to configure +# `cni`, please follow instructions in their documents. +make install.deps +``` +### Build and Install `cri` +To build and install a version of containerd with the `cri` plugin, enter the +following commands from your `cri` project directory: +```bash +make +sudo make install +``` +*NOTE: The version of containerd built and installed from the `Makefile` is only for +testing purposes. The version tag carries the suffix "-TEST".* +#### Build Tags +`cri` supports optional build tags for compiling support of various features. +To add build tags to the make option the `BUILD_TAGS` variable must be set. + +```bash +make BUILD_TAGS='seccomp apparmor' +``` + +| Build Tag | Feature | Dependency | +|-----------|------------------------------------|---------------------------------| +| seccomp | syscall filtering | libseccomp development library | +| selinux | selinux process and mount labeling | | +| apparmor | apparmor profile support | | +### Validate Your `cri` Setup +A Kubernetes incubator project called [cri-tools](https://github.com/kubernetes-sigs/cri-tools) +includes programs for exercising CRI implementations such as the `cri` plugin. +More importantly, cri-tools includes the program `critest` which is used for running +[CRI Validation Testing](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md). + +Run the CRI Validation test to validate your installation of `containerd` with `cri` built in: +```bash +make test-cri +``` +### Running a Kubernetes local cluster +If you already have a working development environment for supported Kubernetes +version, you can try `cri` in a local cluster: + +1. Start the version of `containerd` with `cri` plugin that you built and installed +above as root in a first terminal: +```bash +sudo containerd +``` +2. From the Kubernetes project directory startup a local cluster using `containerd`: +```bash +CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='unix:///run/containerd/containerd.sock' ./hack/local-up-cluster.sh +``` +### Test +See [here](./docs/testing.md) for information about test. +## Using crictl +See [here](./docs/crictl.md) for information about using `crictl` to debug +pods, containers, and images. +## Configurations +See [here](./docs/config.md) for information about how to configure cri plugins +and [here](https://github.com/containerd/containerd/blob/master/docs/man/containerd-config.1.md) +for information about how to configure containerd +## Documentation +See [here](./docs) for additional documentation. +## Contributing +Interested in contributing? Check out the [documentation](./CONTRIBUTING.md). + +## Communication +This project was originally established in April of 2017 in the Kubernetes +Incubator program. After reaching the Beta stage, In January of 2018, the +project was merged into [containerd](https://github.com/containerd/containerd). + +For async communication and long running discussions please use issues and pull +requests on this github repo. This will be the best place to discuss design and +implementation. + +For sync communication we have a community slack with a #containerd channel that +everyone is welcome to join and chat about development. + +**Slack:** https://dockr.ly/community + +## Other Communications +As this project is tightly coupled to CRI and CRI-Tools and they are Kubernetes +projects, some of our project communications take place in the Kubernetes' SIG: +`sig-node.` + +For more information about `sig-node`, `CRI`, and the `CRI-Tools` projects: +* [sig-node community site](https://github.com/kubernetes/community/tree/master/sig-node) +* Slack: `#sig-node` channel in Kubernetes (kubernetes.slack.com) +* Mailing List: https://groups.google.com/forum/#!forum/kubernetes-sig-node + +### Reporting Security Issues + +__If you are reporting a security issue, please reach out discreetly at security@containerd.io__. + +## Licenses +The containerd codebase is released under the [Apache 2.0 license](https://github.com/containerd/containerd/blob/master/LICENSE.code). +The README.md file, and files in the "docs" folder are licensed under the +Creative Commons Attribution 4.0 International License under the terms and +conditions set forth in the file "[LICENSE.docs](https://github.com/containerd/containerd/blob/master/LICENSE.docs)". You may obtain a duplicate +copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/. + +## Code of Conduct +This project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). diff --git a/vendor/github.com/containerd/cri/pkg/util/deep_copy.go b/vendor/github.com/containerd/cri/pkg/util/deep_copy.go new file mode 100644 index 0000000000000..5fdee984b5288 --- /dev/null +++ b/vendor/github.com/containerd/cri/pkg/util/deep_copy.go @@ -0,0 +1,42 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +package util + +import ( + "encoding/json" + + "github.com/pkg/errors" +) + +// DeepCopy makes a deep copy from src into dst. +func DeepCopy(dst interface{}, src interface{}) error { + if dst == nil { + return errors.New("dst cannot be nil") + } + if src == nil { + return errors.New("src cannot be nil") + } + bytes, err := json.Marshal(src) + if err != nil { + return errors.Wrap(err, "unable to marshal src") + } + err = json.Unmarshal(bytes, dst) + if err != nil { + return errors.Wrap(err, "unable to unmarshal into dst") + } + return nil +} diff --git a/vendor/github.com/containerd/cri/pkg/util/id.go b/vendor/github.com/containerd/cri/pkg/util/id.go new file mode 100644 index 0000000000000..11b0a70a65c28 --- /dev/null +++ b/vendor/github.com/containerd/cri/pkg/util/id.go @@ -0,0 +1,29 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +package util + +import ( + "encoding/hex" + "math/rand" +) + +// GenerateID generates a random unique id. +func GenerateID() string { + b := make([]byte, 32) + rand.Read(b) + return hex.EncodeToString(b) +} diff --git a/vendor/github.com/containerd/cri/pkg/util/image.go b/vendor/github.com/containerd/cri/pkg/util/image.go new file mode 100644 index 0000000000000..0f471fc42243b --- /dev/null +++ b/vendor/github.com/containerd/cri/pkg/util/image.go @@ -0,0 +1,50 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +package util + +import ( + "github.com/docker/distribution/reference" +) + +// NormalizeImageRef normalizes the image reference following the docker convention. This is added +// mainly for backward compatibility. +// The reference returned can only be either tagged or digested. For reference contains both tag +// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@ +// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as +// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa. +func NormalizeImageRef(ref string) (reference.Named, error) { + named, err := reference.ParseNormalizedNamed(ref) + if err != nil { + return nil, err + } + if _, ok := named.(reference.NamedTagged); ok { + if canonical, ok := named.(reference.Canonical); ok { + // The reference is both tagged and digested, only + // return digested. + newNamed, err := reference.WithName(canonical.Name()) + if err != nil { + return nil, err + } + newCanonical, err := reference.WithDigest(newNamed, canonical.Digest()) + if err != nil { + return nil, err + } + return newCanonical, nil + } + } + return reference.TagNameOnly(named), nil +} diff --git a/vendor/github.com/containerd/cri/pkg/util/strings.go b/vendor/github.com/containerd/cri/pkg/util/strings.go new file mode 100644 index 0000000000000..d5cbc2e8ef30d --- /dev/null +++ b/vendor/github.com/containerd/cri/pkg/util/strings.go @@ -0,0 +1,59 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +package util + +import "strings" + +// InStringSlice checks whether a string is inside a string slice. +// Comparison is case insensitive. +func InStringSlice(ss []string, str string) bool { + for _, s := range ss { + if strings.ToLower(s) == strings.ToLower(str) { + return true + } + } + return false +} + +// SubtractStringSlice subtracts string from string slice. +// Comparison is case insensitive. +func SubtractStringSlice(ss []string, str string) []string { + var res []string + for _, s := range ss { + if strings.ToLower(s) == strings.ToLower(str) { + continue + } + res = append(res, s) + } + return res +} + +// MergeStringSlices merges 2 string slices into one and remove duplicated elements. +func MergeStringSlices(a []string, b []string) []string { + set := map[string]struct{}{} + for _, s := range a { + set[s] = struct{}{} + } + for _, s := range b { + set[s] = struct{}{} + } + var ss []string + for s := range set { + ss = append(ss, s) + } + return ss +} diff --git a/vendor/github.com/containerd/cri/vendor.conf b/vendor/github.com/containerd/cri/vendor.conf new file mode 100644 index 0000000000000..a9ffca873aee3 --- /dev/null +++ b/vendor/github.com/containerd/cri/vendor.conf @@ -0,0 +1,78 @@ +github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 +github.com/blang/semver v3.1.0 +github.com/boltdb/bolt v1.3.1 +github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895 +github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 +github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 +github.com/containerd/containerd 1950f791d9225ffe061c77e74e292bcb3c428a04 +github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537 +github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c +github.com/containerd/go-cni 6d7b509a054a3cb1c35ed1865d4fde2f0cb547cd +github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 +github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d +github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 +github.com/containernetworking/cni v0.6.0 +github.com/containernetworking/plugins v0.7.0 +github.com/coreos/go-systemd v14 +github.com/davecgh/go-spew v1.1.0 +github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621 +github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00 +github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 +github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098 +github.com/docker/go-units v0.3.1 +github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528 +github.com/emicklei/go-restful v2.2.1 +github.com/ghodss/yaml v1.0.0 +github.com/godbus/dbus v3 +github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef +github.com/gogo/protobuf v1.0.0 +github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed +github.com/golang/protobuf v1.1.0 +github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c +github.com/grpc-ecosystem/go-grpc-prometheus v1.1 +github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55 +github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f +github.com/json-iterator/go 1.1.5 +github.com/matttproud/golang_protobuf_extensions v1.0.0 +github.com/Microsoft/go-winio v0.4.10 +github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55 +github.com/modern-go/concurrent 1.0.3 +github.com/modern-go/reflect2 1.0.1 +github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7 +github.com/opencontainers/image-spec v1.0.1 +github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd +github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce +github.com/opencontainers/runtime-tools v0.6.0 +github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a +github.com/pkg/errors v0.8.0 +github.com/pmezard/go-difflib v1.0.0 +github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823 +github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c +github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563 +github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd +github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 +github.com/sirupsen/logrus v1.0.0 +github.com/stretchr/testify v1.1.4 +github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 +github.com/tchap/go-patricia v2.2.6 +github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c +github.com/xeipuuv/gojsonpointer 4e3ac2762d5f479393488629ee9370b50873b3a6 +github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b +github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874 +golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067 +golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac +golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4 +golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c +golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys +golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 +golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 +google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 +google.golang.org/grpc v1.12.0 +gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 +gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77 +k8s.io/api 012f271b5d41baad56190c5f1ae19bff16df0fd8 +k8s.io/apimachinery 6429050ef506887d121f3e7306e894f8900d8a63 +k8s.io/apiserver e9312c15296b6c2c923ebd5031ff5d1d5fd022d7 +k8s.io/client-go 37c3c02ec96533daec0dbda1f39a6b1d68505c79 +k8s.io/kubernetes v1.12.0-beta.1 +k8s.io/utils 982821ea41da7e7c15f3d3738921eb2e7e241ccd diff --git a/vendor/github.com/containerd/go-runc/console.go b/vendor/github.com/containerd/go-runc/console.go index 09973e9d6b138..ff223e4276658 100644 --- a/vendor/github.com/containerd/go-runc/console.go +++ b/vendor/github.com/containerd/go-runc/console.go @@ -1,3 +1,5 @@ +// +build !windows + /* Copyright The containerd Authors. diff --git a/vendor/github.com/containerd/go-runc/io.go b/vendor/github.com/containerd/go-runc/io.go index 1b59a7ef9b64c..6cf0410c9d33e 100644 --- a/vendor/github.com/containerd/go-runc/io.go +++ b/vendor/github.com/containerd/go-runc/io.go @@ -20,9 +20,6 @@ import ( "io" "os" "os/exec" - - "github.com/pkg/errors" - "golang.org/x/sys/unix" ) type IO interface { @@ -37,49 +34,22 @@ type StartCloser interface { CloseAfterStart() error } -// NewPipeIO creates pipe pairs to be used with runc -func NewPipeIO(uid, gid int) (i IO, err error) { - var pipes []*pipe - // cleanup in case of an error - defer func() { - if err != nil { - for _, p := range pipes { - p.Close() - } - } - }() - stdin, err := newPipe() - if err != nil { - return nil, err - } - pipes = append(pipes, stdin) - if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil { - return nil, errors.Wrap(err, "failed to chown stdin") - } +// IOOpt sets I/O creation options +type IOOpt func(*IOOption) - stdout, err := newPipe() - if err != nil { - return nil, err - } - pipes = append(pipes, stdout) - if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil { - return nil, errors.Wrap(err, "failed to chown stdout") - } +// IOOption holds I/O creation options +type IOOption struct { + OpenStdin bool + OpenStdout bool + OpenStderr bool +} - stderr, err := newPipe() - if err != nil { - return nil, err +func defaultIOOption() *IOOption { + return &IOOption{ + OpenStdin: true, + OpenStdout: true, + OpenStderr: true, } - pipes = append(pipes, stderr) - if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil { - return nil, errors.Wrap(err, "failed to chown stderr") - } - - return &pipeIO{ - in: stdin, - out: stdout, - err: stderr, - }, nil } func newPipe() (*pipe, error) { @@ -99,9 +69,9 @@ type pipe struct { } func (p *pipe) Close() error { - err := p.r.Close() - if werr := p.w.Close(); err == nil { - err = werr + err := p.w.Close() + if rerr := p.r.Close(); err == nil { + err = rerr } return err } @@ -113,14 +83,23 @@ type pipeIO struct { } func (i *pipeIO) Stdin() io.WriteCloser { + if i.in == nil { + return nil + } return i.in.w } func (i *pipeIO) Stdout() io.ReadCloser { + if i.out == nil { + return nil + } return i.out.r } func (i *pipeIO) Stderr() io.ReadCloser { + if i.err == nil { + return nil + } return i.err.r } @@ -131,28 +110,38 @@ func (i *pipeIO) Close() error { i.out, i.err, } { - if cerr := v.Close(); err == nil { - err = cerr + if v != nil { + if cerr := v.Close(); err == nil { + err = cerr + } } } return err } func (i *pipeIO) CloseAfterStart() error { - for _, f := range []*os.File{ - i.out.w, - i.err.w, + for _, f := range []*pipe{ + i.out, + i.err, } { - f.Close() + if f != nil { + f.w.Close() + } } return nil } // Set sets the io to the exec.Cmd func (i *pipeIO) Set(cmd *exec.Cmd) { - cmd.Stdin = i.in.r - cmd.Stdout = i.out.w - cmd.Stderr = i.err.w + if i.in != nil { + cmd.Stdin = i.in.r + } + if i.out != nil { + cmd.Stdout = i.out.w + } + if i.err != nil { + cmd.Stderr = i.err.w + } } func NewSTDIO() (IO, error) { diff --git a/vendor/github.com/containerd/go-runc/io_unix.go b/vendor/github.com/containerd/go-runc/io_unix.go new file mode 100644 index 0000000000000..567cd072e5f88 --- /dev/null +++ b/vendor/github.com/containerd/go-runc/io_unix.go @@ -0,0 +1,76 @@ +// +build !windows + +/* + 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. +*/ + +package runc + +import ( + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +// NewPipeIO creates pipe pairs to be used with runc +func NewPipeIO(uid, gid int, opts ...IOOpt) (i IO, err error) { + option := defaultIOOption() + for _, o := range opts { + o(option) + } + var ( + pipes []*pipe + stdin, stdout, stderr *pipe + ) + // cleanup in case of an error + defer func() { + if err != nil { + for _, p := range pipes { + p.Close() + } + } + }() + if option.OpenStdin { + if stdin, err = newPipe(); err != nil { + return nil, err + } + pipes = append(pipes, stdin) + if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil { + return nil, errors.Wrap(err, "failed to chown stdin") + } + } + if option.OpenStdout { + if stdout, err = newPipe(); err != nil { + return nil, err + } + pipes = append(pipes, stdout) + if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil { + return nil, errors.Wrap(err, "failed to chown stdout") + } + } + if option.OpenStderr { + if stderr, err = newPipe(); err != nil { + return nil, err + } + pipes = append(pipes, stderr) + if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil { + return nil, errors.Wrap(err, "failed to chown stderr") + } + } + return &pipeIO{ + in: stdin, + out: stdout, + err: stderr, + }, nil +} diff --git a/vendor/github.com/containerd/go-runc/io_windows.go b/vendor/github.com/containerd/go-runc/io_windows.go new file mode 100644 index 0000000000000..fc56ac4f301a0 --- /dev/null +++ b/vendor/github.com/containerd/go-runc/io_windows.go @@ -0,0 +1,62 @@ +// +build windows + +/* + 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. +*/ + +package runc + +// NewPipeIO creates pipe pairs to be used with runc +func NewPipeIO(opts ...IOOpt) (i IO, err error) { + option := defaultIOOption() + for _, o := range opts { + o(option) + } + var ( + pipes []*pipe + stdin, stdout, stderr *pipe + ) + // cleanup in case of an error + defer func() { + if err != nil { + for _, p := range pipes { + p.Close() + } + } + }() + if option.OpenStdin { + if stdin, err = newPipe(); err != nil { + return nil, err + } + pipes = append(pipes, stdin) + } + if option.OpenStdout { + if stdout, err = newPipe(); err != nil { + return nil, err + } + pipes = append(pipes, stdout) + } + if option.OpenStderr { + if stderr, err = newPipe(); err != nil { + return nil, err + } + pipes = append(pipes, stderr) + } + return &pipeIO{ + in: stdin, + out: stdout, + err: stderr, + }, nil +} diff --git a/vendor/github.com/containerd/go-runc/runc.go b/vendor/github.com/containerd/go-runc/runc.go index ac9c89d8054fe..96262afab3964 100644 --- a/vendor/github.com/containerd/go-runc/runc.go +++ b/vendor/github.com/containerd/go-runc/runc.go @@ -608,9 +608,8 @@ func parseVersion(data []byte) (Version, error) { var v Version parts := strings.Split(strings.TrimSpace(string(data)), "\n") if len(parts) != 3 { - return v, ErrParseRuncVersion + return v, nil } - for i, p := range []struct { dest *string split string diff --git a/vendor/github.com/docker/libkv/README.md b/vendor/github.com/docker/libkv/README.md index baad81b4f829a..ff2cc446d3369 100644 --- a/vendor/github.com/docker/libkv/README.md +++ b/vendor/github.com/docker/libkv/README.md @@ -90,7 +90,7 @@ Calls like `WatchTree` may return different events (or number of events) dependi Only `Consul` and `etcd` have support for TLS and you should build and provide your own `config.TLS` object to feed the client. Support is planned for `zookeeper`. -##Roadmap +## Roadmap - Make the API nicer to use (using `options`) - Provide more options (`consistency` for example) @@ -98,10 +98,10 @@ Only `Consul` and `etcd` have support for TLS and you should build and provide y - Better key formatting - New backends? -##Contributing +## Contributing Want to hack on libkv? [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) apply. -##Copyright and license +## Copyright and license Copyright © 2014-2016 Docker, Inc. All rights reserved, except as follows. Code is released under the Apache 2.0 license. The README.md file, and files in the "docs" folder are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file "LICENSE.docs". You may obtain a duplicate copy of the same license, titled CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/. diff --git a/vendor/github.com/docker/libkv/store/boltdb/boltdb.go b/vendor/github.com/docker/libkv/store/boltdb/boltdb.go index cdfd74f8789c7..d62979cb7205d 100644 --- a/vendor/github.com/docker/libkv/store/boltdb/boltdb.go +++ b/vendor/github.com/docker/libkv/store/boltdb/boltdb.go @@ -10,9 +10,9 @@ import ( "sync/atomic" "time" - "github.com/boltdb/bolt" "github.com/docker/libkv" "github.com/docker/libkv/store" + bolt "go.etcd.io/bbolt" ) var ( diff --git a/vendor/github.com/docker/libkv/store/etcd/etcd.go b/vendor/github.com/docker/libkv/store/etcd/etcd.go index c932ca665efb3..ec407b0788e5b 100644 --- a/vendor/github.com/docker/libkv/store/etcd/etcd.go +++ b/vendor/github.com/docker/libkv/store/etcd/etcd.go @@ -1,6 +1,7 @@ package etcd import ( + "context" "crypto/tls" "errors" "log" @@ -9,8 +10,6 @@ import ( "strings" "time" - "golang.org/x/net/context" - etcd "github.com/coreos/etcd/client" "github.com/docker/libkv" "github.com/docker/libkv/store" @@ -30,13 +29,29 @@ type Etcd struct { } type etcdLock struct { - client etcd.KeysAPI - stopLock chan struct{} + client etcd.KeysAPI + key string + value string + ttl time.Duration + + // Closed when the caller wants to stop renewing the lock. I'm not sure + // why this is even used - you could just call the Unlock() method. stopRenew chan struct{} - key string - value string - last *etcd.Response - ttl time.Duration + // When the lock is held, this is the last modified index of the key. + // Used for conditional updates when extending the lock TTL and when + // conditionall deleteing when Unlock() is called. + lastIndex uint64 + // When the lock is held, this function will cancel the locked context. + // This is called both by the Unlock() method in order to stop the + // background holding goroutine and in a deferred call in that background + // holding goroutine in case the lock is lost due to an error or the + // stopRenew channel is closed. Calling this function also closes the chan + // returned by the Lock() method. + cancel context.CancelFunc + // Used to sync the Unlock() call with the background holding goroutine. + // This channel is closed when that background goroutine exits, signalling + // that it is okay to conditionally delete the key. + doneHolding chan struct{} } const ( @@ -472,112 +487,97 @@ func (s *Etcd) NewLock(key string, options *store.LockOptions) (lock store.Locke // doing so. It returns a channel that is closed if our // lock is lost or if an error occurs func (l *etcdLock) Lock(stopChan chan struct{}) (<-chan struct{}, error) { - - // Lock holder channel - lockHeld := make(chan struct{}) - stopLocking := l.stopRenew - + // Conditional Set - only if the key does not exist. setOpts := &etcd.SetOptions{ - TTL: l.ttl, + TTL: l.ttl, + PrevExist: etcd.PrevNoExist, } for { - setOpts.PrevExist = etcd.PrevNoExist resp, err := l.client.Set(context.Background(), l.key, l.value, setOpts) - if err != nil { - if etcdError, ok := err.(etcd.Error); ok { - if etcdError.Code != etcd.ErrorCodeNodeExist { - return nil, err - } - setOpts.PrevIndex = ^uint64(0) - } - } else { - setOpts.PrevIndex = resp.Node.ModifiedIndex - } - - setOpts.PrevExist = etcd.PrevExist - l.last, err = l.client.Set(context.Background(), l.key, l.value, setOpts) - if err == nil { - // Leader section - l.stopLock = stopLocking - go l.holdLock(l.key, lockHeld, stopLocking) - break - } else { - // If this is a legitimate error, return - if etcdError, ok := err.(etcd.Error); ok { - if etcdError.Code != etcd.ErrorCodeTestFailed { - return nil, err - } - } + // Acquired the lock! + l.lastIndex = resp.Node.ModifiedIndex + lockedCtx, cancel := context.WithCancel(context.Background()) + l.cancel = cancel + l.doneHolding = make(chan struct{}) - // Seeker section - errorCh := make(chan error) - chWStop := make(chan bool) - free := make(chan bool) + go l.holdLock(lockedCtx) - go l.waitLock(l.key, errorCh, chWStop, free) + return lockedCtx.Done(), nil + } - // Wait for the key to be available or for - // a signal to stop trying to lock the key - select { - case <-free: - break - case err := <-errorCh: - return nil, err - case <-stopChan: - return nil, ErrAbortTryLock - } + etcdErr, ok := err.(etcd.Error) + if !ok || etcdErr.Code != etcd.ErrorCodeNodeExist { + return nil, err // Unexpected error. + } - // Delete or Expire event occurred - // Retry + // Need to wait for the lock key to expire or be deleted. + if err := l.waitLock(stopChan, etcdErr.Index); err != nil { + return nil, err } - } - return lockHeld, nil + // Delete or Expire event occurred. + // Retry + } } -// Hold the lock as long as we can +// Hold the lock as long as we can. // Updates the key ttl periodically until we receive -// an explicit stop signal from the Unlock method -func (l *etcdLock) holdLock(key string, lockHeld chan struct{}, stopLocking <-chan struct{}) { - defer close(lockHeld) +// an explicit stop signal from the Unlock method OR +// the stopRenew channel is closed. +func (l *etcdLock) holdLock(ctx context.Context) { + defer close(l.doneHolding) + defer l.cancel() update := time.NewTicker(l.ttl / 3) defer update.Stop() - var err error setOpts := &etcd.SetOptions{TTL: l.ttl} for { select { case <-update.C: - setOpts.PrevIndex = l.last.Node.ModifiedIndex - l.last, err = l.client.Set(context.Background(), key, l.value, setOpts) + setOpts.PrevIndex = l.lastIndex + resp, err := l.client.Set(ctx, l.key, l.value, setOpts) if err != nil { return } - - case <-stopLocking: + l.lastIndex = resp.Node.ModifiedIndex + case <-l.stopRenew: + return + case <-ctx.Done(): return } } } -// WaitLock simply waits for the key to be available for creation -func (l *etcdLock) waitLock(key string, errorCh chan error, stopWatchCh chan bool, free chan<- bool) { - opts := &etcd.WatcherOptions{Recursive: false} - watcher := l.client.Watcher(key, opts) +// WaitLock simply waits for the key to be available for creation. +func (l *etcdLock) waitLock(stopWait <-chan struct{}, afterIndex uint64) error { + waitCtx, waitCancel := context.WithCancel(context.Background()) + defer waitCancel() + go func() { + select { + case <-stopWait: + // If the caller closes the stopWait, cancel the wait context. + waitCancel() + case <-waitCtx.Done(): + // No longer waiting. + } + }() + watcher := l.client.Watcher(l.key, &etcd.WatcherOptions{AfterIndex: afterIndex}) for { - event, err := watcher.Next(context.Background()) + event, err := watcher.Next(waitCtx) if err != nil { - errorCh <- err - return + if err == context.Canceled { + return ErrAbortTryLock + } + return err } - if event.Action == "delete" || event.Action == "expire" { - free <- true - return + switch event.Action { + case "delete", "compareAndDelete", "expire": + return nil // The key has been deleted or expired. } } } @@ -585,19 +585,17 @@ func (l *etcdLock) waitLock(key string, errorCh chan error, stopWatchCh chan boo // Unlock the "key". Calling unlock while // not holding the lock will throw an error func (l *etcdLock) Unlock() error { - if l.stopLock != nil { - l.stopLock <- struct{}{} - } - if l.last != nil { + l.cancel() // Will signal the holdLock goroutine to exit. + <-l.doneHolding // Wait for the holdLock goroutine to exit. + + var err error + if l.lastIndex != 0 { delOpts := &etcd.DeleteOptions{ - PrevIndex: l.last.Node.ModifiedIndex, - } - _, err := l.client.Delete(context.Background(), l.key, delOpts) - if err != nil { - return err + PrevIndex: l.lastIndex, } + _, err = l.client.Delete(context.Background(), l.key, delOpts) } - return nil + return err } // Close closes the client connection diff --git a/vendor/github.com/docker/swarmkit/agent/config.go b/vendor/github.com/docker/swarmkit/agent/config.go index b4293e9e03c7d..13024439dd7d9 100644 --- a/vendor/github.com/docker/swarmkit/agent/config.go +++ b/vendor/github.com/docker/swarmkit/agent/config.go @@ -1,12 +1,12 @@ package agent import ( - "github.com/boltdb/bolt" "github.com/docker/go-events" "github.com/docker/swarmkit/agent/exec" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/connectionbroker" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" "google.golang.org/grpc/credentials" ) diff --git a/vendor/github.com/docker/swarmkit/agent/session.go b/vendor/github.com/docker/swarmkit/agent/session.go index 8afca9587dc44..8c01d08fdd6d7 100644 --- a/vendor/github.com/docker/swarmkit/agent/session.go +++ b/vendor/github.com/docker/swarmkit/agent/session.go @@ -136,7 +136,7 @@ func (s *session) start(ctx context.Context, description *api.NodeDescription) e // then in `run` it's possible that we just terminate the function because // `ctx` is done and hence fail to propagate the timeout error to the agent. // If the error is not propogated to the agent, the agent will not close - // the session or rebuild a new sesssion. + // the session or rebuild a new session. sessionCtx, cancelSession := context.WithCancel(ctx) // Need to run Session in a goroutine since there's no way to set a diff --git a/vendor/github.com/docker/swarmkit/agent/storage.go b/vendor/github.com/docker/swarmkit/agent/storage.go index a49ad81fa42f0..519880197f2a6 100644 --- a/vendor/github.com/docker/swarmkit/agent/storage.go +++ b/vendor/github.com/docker/swarmkit/agent/storage.go @@ -1,9 +1,9 @@ package agent import ( - "github.com/boltdb/bolt" "github.com/docker/swarmkit/api" "github.com/gogo/protobuf/proto" + bolt "go.etcd.io/bbolt" ) // Layout: diff --git a/vendor/github.com/docker/swarmkit/agent/worker.go b/vendor/github.com/docker/swarmkit/agent/worker.go index 734a510715227..8125145d213c6 100644 --- a/vendor/github.com/docker/swarmkit/agent/worker.go +++ b/vendor/github.com/docker/swarmkit/agent/worker.go @@ -3,12 +3,12 @@ package agent import ( "sync" - "github.com/boltdb/bolt" "github.com/docker/swarmkit/agent/exec" "github.com/docker/swarmkit/api" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/watch" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" "golang.org/x/net/context" ) diff --git a/vendor/github.com/docker/swarmkit/api/specs.pb.go b/vendor/github.com/docker/swarmkit/api/specs.pb.go index 2930afc6cbbf6..14786d3fc1b7e 100644 --- a/vendor/github.com/docker/swarmkit/api/specs.pb.go +++ b/vendor/github.com/docker/swarmkit/api/specs.pb.go @@ -622,6 +622,20 @@ type ContainerSpec struct { // PidsLimit prevents from OS resource damage by applications inside the container // using fork bomb attack. PidsLimit int64 `protobuf:"varint,25,opt,name=pidsLimit,proto3" json:"pidsLimit,omitempty"` + // Sysctls sets namespaced kernel parameters (sysctls) in the container. This + // option is equivalent to passing --sysctl to docker run. + // + // Note that while options are subject to the same restrictions as arguments + // passed to the --sysctl flag on docker run, those options are not further + // validated to ensure that they are safe or sensible in a clustered + // environment. + // + // Additionally, sysctls are not validated for support in the underlying + // daemon. For information about supported options, refer to the + // documentation at: + // + // https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime + Sysctls map[string]string `protobuf:"bytes,26,rep,name=sysctls" json:"sysctls,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (m *ContainerSpec) Reset() { *m = ContainerSpec{} } @@ -1176,6 +1190,13 @@ func (m *ContainerSpec) CopyFrom(src interface{}) { m.Healthcheck = &HealthConfig{} deepcopy.Copy(m.Healthcheck, o.Healthcheck) } + if o.Sysctls != nil { + m.Sysctls = make(map[string]string, len(o.Sysctls)) + for k, v := range o.Sysctls { + m.Sysctls[k] = v + } + } + } func (m *ContainerSpec_PullOptions) Copy() *ContainerSpec_PullOptions { @@ -2064,6 +2085,25 @@ func (m *ContainerSpec) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintSpecs(dAtA, i, uint64(m.PidsLimit)) } + if len(m.Sysctls) > 0 { + for k, _ := range m.Sysctls { + dAtA[i] = 0xd2 + i++ + dAtA[i] = 0x1 + i++ + v := m.Sysctls[k] + mapSize := 1 + len(k) + sovSpecs(uint64(len(k))) + 1 + len(v) + sovSpecs(uint64(len(v))) + i = encodeVarintSpecs(dAtA, i, uint64(mapSize)) + dAtA[i] = 0xa + i++ + i = encodeVarintSpecs(dAtA, i, uint64(len(k))) + i += copy(dAtA[i:], k) + dAtA[i] = 0x12 + i++ + i = encodeVarintSpecs(dAtA, i, uint64(len(v))) + i += copy(dAtA[i:], v) + } + } return i, nil } @@ -2781,6 +2821,14 @@ func (m *ContainerSpec) Size() (n int) { if m.PidsLimit != 0 { n += 2 + sovSpecs(uint64(m.PidsLimit)) } + if len(m.Sysctls) > 0 { + for k, v := range m.Sysctls { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovSpecs(uint64(len(k))) + 1 + len(v) + sovSpecs(uint64(len(v))) + n += mapEntrySize + 2 + sovSpecs(uint64(mapEntrySize)) + } + } return n } @@ -3103,6 +3151,16 @@ func (this *ContainerSpec) String() string { mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) } mapStringForLabels += "}" + keysForSysctls := make([]string, 0, len(this.Sysctls)) + for k, _ := range this.Sysctls { + keysForSysctls = append(keysForSysctls, k) + } + sortkeys.Strings(keysForSysctls) + mapStringForSysctls := "map[string]string{" + for _, k := range keysForSysctls { + mapStringForSysctls += fmt.Sprintf("%v: %v,", k, this.Sysctls[k]) + } + mapStringForSysctls += "}" s := strings.Join([]string{`&ContainerSpec{`, `Image:` + fmt.Sprintf("%v", this.Image) + `,`, `Labels:` + mapStringForLabels + `,`, @@ -3129,6 +3187,7 @@ func (this *ContainerSpec) String() string { `Init:` + strings.Replace(fmt.Sprintf("%v", this.Init), "BoolValue", "google_protobuf4.BoolValue", 1) + `,`, `Isolation:` + fmt.Sprintf("%v", this.Isolation) + `,`, `PidsLimit:` + fmt.Sprintf("%v", this.PidsLimit) + `,`, + `Sysctls:` + mapStringForSysctls + `,`, `}`, }, "") return s @@ -5277,6 +5336,124 @@ func (m *ContainerSpec) Unmarshal(dAtA []byte) error { break } } + case 26: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sysctls", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthSpecs + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Sysctls == nil { + m.Sysctls = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthSpecs + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSpecs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthSpecs + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipSpecs(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthSpecs + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Sysctls[mapkey] = mapvalue + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipSpecs(dAtA[iNdEx:]) @@ -6588,139 +6765,141 @@ var ( func init() { proto.RegisterFile("github.com/docker/swarmkit/api/specs.proto", fileDescriptorSpecs) } var fileDescriptorSpecs = []byte{ - // 2131 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4f, 0x6f, 0x1b, 0xc7, - 0x15, 0x17, 0x25, 0x8a, 0x22, 0xdf, 0x52, 0x36, 0x35, 0x71, 0x9c, 0x15, 0x6d, 0x4b, 0x34, 0xe3, - 0xb8, 0x4a, 0x82, 0x52, 0xa8, 0x1a, 0xa4, 0x4e, 0xdc, 0xb4, 0x25, 0x45, 0x46, 0x66, 0x6d, 0x4b, - 0xc4, 0x50, 0x56, 0x6b, 0xa0, 0x00, 0x31, 0xda, 0x1d, 0x91, 0x03, 0x2d, 0x77, 0xb6, 0xb3, 0x43, - 0x19, 0xbc, 0xf5, 0x18, 0xa8, 0x9f, 0x41, 0xe8, 0xa1, 0xe8, 0xbd, 0xfd, 0x16, 0x3e, 0xf6, 0xd8, - 0x5e, 0x84, 0x44, 0x5f, 0xa1, 0xb7, 0x5e, 0x5a, 0xcc, 0xec, 0xec, 0x92, 0x94, 0x57, 0x96, 0x81, - 0xfa, 0xd0, 0xdb, 0xcc, 0xdb, 0xdf, 0xef, 0xcd, 0xbf, 0xdf, 0xbc, 0xf7, 0x66, 0xe1, 0xb3, 0x3e, - 0x93, 0x83, 0xd1, 0x61, 0xcd, 0xe1, 0xc3, 0x4d, 0x97, 0x3b, 0xc7, 0x54, 0x6c, 0x86, 0xaf, 0x88, - 0x18, 0x1e, 0x33, 0xb9, 0x49, 0x02, 0xb6, 0x19, 0x06, 0xd4, 0x09, 0x6b, 0x81, 0xe0, 0x92, 0x23, - 0x14, 0x01, 0x6a, 0x31, 0xa0, 0x76, 0xf2, 0x93, 0xf2, 0x75, 0x7c, 0x39, 0x0e, 0xa8, 0xe1, 0x97, - 0x6f, 0xf5, 0x79, 0x9f, 0xeb, 0xe6, 0xa6, 0x6a, 0x19, 0xeb, 0x5a, 0x9f, 0xf3, 0xbe, 0x47, 0x37, - 0x75, 0xef, 0x70, 0x74, 0xb4, 0xe9, 0x8e, 0x04, 0x91, 0x8c, 0xfb, 0xe6, 0xfb, 0xea, 0xe5, 0xef, - 0xc4, 0x1f, 0x5f, 0x45, 0x7d, 0x25, 0x48, 0x10, 0x50, 0x61, 0x06, 0xac, 0x9e, 0x65, 0x21, 0xbf, - 0xcb, 0x5d, 0xda, 0x0d, 0xa8, 0x83, 0x76, 0xc0, 0x22, 0xbe, 0xcf, 0xa5, 0xf6, 0x1d, 0xda, 0x99, - 0x4a, 0x66, 0xc3, 0xda, 0x5a, 0xaf, 0xbd, 0xb9, 0xa6, 0x5a, 0x7d, 0x02, 0x6b, 0x64, 0x5f, 0x9f, - 0xaf, 0xcf, 0xe1, 0x69, 0x26, 0xfa, 0x25, 0x14, 0x5d, 0x1a, 0x32, 0x41, 0xdd, 0x9e, 0xe0, 0x1e, - 0xb5, 0xe7, 0x2b, 0x99, 0x8d, 0x1b, 0x5b, 0x77, 0xd3, 0x3c, 0xa9, 0xc1, 0x31, 0xf7, 0x28, 0xb6, - 0x0c, 0x43, 0x75, 0xd0, 0x0e, 0xc0, 0x90, 0x0e, 0x0f, 0xa9, 0x08, 0x07, 0x2c, 0xb0, 0x17, 0x34, - 0xfd, 0x47, 0x57, 0xd1, 0xd5, 0xdc, 0x6b, 0xcf, 0x13, 0x38, 0x9e, 0xa2, 0xa2, 0xe7, 0x50, 0x24, - 0x27, 0x84, 0x79, 0xe4, 0x90, 0x79, 0x4c, 0x8e, 0xed, 0xac, 0x76, 0xf5, 0xe9, 0x5b, 0x5d, 0xd5, - 0xa7, 0x08, 0x78, 0x86, 0x5e, 0x75, 0x01, 0x26, 0x03, 0xa1, 0x87, 0xb0, 0xd4, 0x69, 0xed, 0x36, - 0xdb, 0xbb, 0x3b, 0xa5, 0xb9, 0xf2, 0xea, 0xe9, 0x59, 0xe5, 0x43, 0xe5, 0x63, 0x02, 0xe8, 0x50, - 0xdf, 0x65, 0x7e, 0x1f, 0x6d, 0x40, 0xbe, 0xbe, 0xbd, 0xdd, 0xea, 0xec, 0xb7, 0x9a, 0xa5, 0x4c, - 0xb9, 0x7c, 0x7a, 0x56, 0xb9, 0x3d, 0x0b, 0xac, 0x3b, 0x0e, 0x0d, 0x24, 0x75, 0xcb, 0xd9, 0xef, - 0xfe, 0xbc, 0x36, 0x57, 0xfd, 0x2e, 0x03, 0xc5, 0xe9, 0x49, 0xa0, 0x87, 0x90, 0xab, 0x6f, 0xef, - 0xb7, 0x0f, 0x5a, 0xa5, 0xb9, 0x09, 0x7d, 0x1a, 0x51, 0x77, 0x24, 0x3b, 0xa1, 0xe8, 0x01, 0x2c, - 0x76, 0xea, 0x2f, 0xba, 0xad, 0x52, 0x66, 0x32, 0x9d, 0x69, 0x58, 0x87, 0x8c, 0x42, 0x8d, 0x6a, - 0xe2, 0x7a, 0x7b, 0xb7, 0x34, 0x9f, 0x8e, 0x6a, 0x0a, 0xc2, 0x7c, 0x33, 0x95, 0x3f, 0x65, 0xc1, - 0xea, 0x52, 0x71, 0xc2, 0x9c, 0xf7, 0x2c, 0x91, 0x2f, 0x21, 0x2b, 0x49, 0x78, 0xac, 0xa5, 0x61, - 0xa5, 0x4b, 0x63, 0x9f, 0x84, 0xc7, 0x6a, 0x50, 0x43, 0xd7, 0x78, 0xa5, 0x0c, 0x41, 0x03, 0x8f, - 0x39, 0x44, 0x52, 0x57, 0x2b, 0xc3, 0xda, 0xfa, 0x24, 0x8d, 0x8d, 0x13, 0x94, 0x99, 0xff, 0x93, - 0x39, 0x3c, 0x45, 0x45, 0x8f, 0x21, 0xd7, 0xf7, 0xf8, 0x21, 0xf1, 0xb4, 0x26, 0xac, 0xad, 0xfb, - 0x69, 0x4e, 0x76, 0x34, 0x62, 0xe2, 0xc0, 0x50, 0xd0, 0x23, 0xc8, 0x8d, 0x02, 0x97, 0x48, 0x6a, - 0xe7, 0x34, 0xb9, 0x92, 0x46, 0x7e, 0xa1, 0x11, 0xdb, 0xdc, 0x3f, 0x62, 0x7d, 0x6c, 0xf0, 0xe8, - 0x29, 0xe4, 0x7d, 0x2a, 0x5f, 0x71, 0x71, 0x1c, 0xda, 0x4b, 0x95, 0x85, 0x0d, 0x6b, 0xeb, 0xf3, - 0x54, 0x31, 0x46, 0x98, 0xba, 0x94, 0xc4, 0x19, 0x0c, 0xa9, 0x2f, 0x23, 0x37, 0x8d, 0x79, 0x3b, - 0x83, 0x13, 0x07, 0xe8, 0xe7, 0x90, 0xa7, 0xbe, 0x1b, 0x70, 0xe6, 0x4b, 0x3b, 0x7f, 0xf5, 0x44, - 0x5a, 0x06, 0xa3, 0x36, 0x13, 0x27, 0x0c, 0xc5, 0x16, 0xdc, 0xf3, 0x0e, 0x89, 0x73, 0x6c, 0x17, - 0xde, 0x71, 0x19, 0x09, 0xa3, 0x91, 0x83, 0xec, 0x90, 0xbb, 0xb4, 0xba, 0x09, 0x2b, 0x6f, 0x6c, - 0x35, 0x2a, 0x43, 0xde, 0x6c, 0x75, 0xa4, 0x91, 0x2c, 0x4e, 0xfa, 0xd5, 0x9b, 0xb0, 0x3c, 0xb3, - 0xad, 0xd5, 0xbf, 0x2e, 0x42, 0x3e, 0x3e, 0x6b, 0x54, 0x87, 0x82, 0xc3, 0x7d, 0x49, 0x98, 0x4f, - 0x85, 0x91, 0x57, 0xea, 0xc9, 0x6c, 0xc7, 0x20, 0xc5, 0x7a, 0x32, 0x87, 0x27, 0x2c, 0xf4, 0x2d, - 0x14, 0x04, 0x0d, 0xf9, 0x48, 0x38, 0x34, 0x34, 0xfa, 0xda, 0x48, 0x57, 0x48, 0x04, 0xc2, 0xf4, - 0xf7, 0x23, 0x26, 0xa8, 0xda, 0xe5, 0x10, 0x4f, 0xa8, 0xe8, 0x31, 0x2c, 0x09, 0x1a, 0x4a, 0x22, - 0xe4, 0xdb, 0x24, 0x82, 0x23, 0x48, 0x87, 0x7b, 0xcc, 0x19, 0xe3, 0x98, 0x81, 0x1e, 0x43, 0x21, - 0xf0, 0x88, 0xa3, 0xbd, 0xda, 0x8b, 0x9a, 0x7e, 0x2f, 0x8d, 0xde, 0x89, 0x41, 0x78, 0x82, 0x47, - 0x5f, 0x01, 0x78, 0xbc, 0xdf, 0x73, 0x05, 0x3b, 0xa1, 0xc2, 0x48, 0xac, 0x9c, 0xc6, 0x6e, 0x6a, - 0x04, 0x2e, 0x78, 0xbc, 0x1f, 0x35, 0xd1, 0xce, 0xff, 0xa4, 0xaf, 0x29, 0x6d, 0x3d, 0x05, 0x20, - 0xc9, 0x57, 0xa3, 0xae, 0x4f, 0xdf, 0xc9, 0x95, 0x39, 0x91, 0x29, 0x3a, 0xba, 0x0f, 0xc5, 0x23, - 0x2e, 0x1c, 0xda, 0x33, 0xb7, 0xa6, 0xa0, 0x35, 0x61, 0x69, 0x5b, 0xa4, 0x2f, 0xd4, 0x80, 0xa5, - 0x3e, 0xf5, 0xa9, 0x60, 0x8e, 0x0d, 0x7a, 0xb0, 0x87, 0xa9, 0x17, 0x32, 0x82, 0xe0, 0x91, 0x2f, - 0xd9, 0x90, 0x9a, 0x91, 0x62, 0x22, 0xfa, 0x1d, 0x7c, 0x10, 0x1f, 0x5f, 0x4f, 0xd0, 0x23, 0x2a, - 0xa8, 0xaf, 0x34, 0x60, 0xe9, 0x7d, 0xf8, 0xe4, 0xed, 0x1a, 0x30, 0x68, 0x13, 0x6c, 0x90, 0xb8, - 0xfc, 0x21, 0x6c, 0x14, 0x60, 0x49, 0x44, 0xe3, 0x56, 0xff, 0x98, 0x51, 0xaa, 0xbf, 0x84, 0x40, - 0x9b, 0x60, 0x25, 0xc3, 0x33, 0x57, 0xab, 0xb7, 0xd0, 0xb8, 0x71, 0x71, 0xbe, 0x0e, 0x31, 0xb6, - 0xdd, 0x54, 0x31, 0xc8, 0xb4, 0x5d, 0xd4, 0x82, 0xe5, 0x84, 0xa0, 0xca, 0x00, 0x93, 0x28, 0x2b, - 0x6f, 0x9b, 0xe9, 0xfe, 0x38, 0xa0, 0xb8, 0x28, 0xa6, 0x7a, 0xd5, 0xdf, 0x02, 0x7a, 0x73, 0x5f, - 0x10, 0x82, 0xec, 0x31, 0xf3, 0xcd, 0x34, 0xb0, 0x6e, 0xa3, 0x1a, 0x2c, 0x05, 0x64, 0xec, 0x71, - 0xe2, 0x9a, 0x8b, 0x71, 0xab, 0x16, 0x15, 0x08, 0xb5, 0xb8, 0x40, 0xa8, 0xd5, 0xfd, 0x31, 0x8e, - 0x41, 0xd5, 0xa7, 0xf0, 0x61, 0xea, 0xf1, 0xa2, 0x2d, 0x28, 0x26, 0x17, 0x6e, 0xb2, 0xd6, 0x9b, - 0x17, 0xe7, 0xeb, 0x56, 0x72, 0x33, 0xdb, 0x4d, 0x6c, 0x25, 0xa0, 0xb6, 0x5b, 0xfd, 0xde, 0x82, - 0xe5, 0x99, 0x6b, 0x8b, 0x6e, 0xc1, 0x22, 0x1b, 0x92, 0x3e, 0x35, 0x73, 0x8c, 0x3a, 0xa8, 0x05, - 0x39, 0x8f, 0x1c, 0x52, 0x4f, 0x5d, 0x5e, 0x75, 0x70, 0x3f, 0xbe, 0xf6, 0xfe, 0xd7, 0x9e, 0x69, - 0x7c, 0xcb, 0x97, 0x62, 0x8c, 0x0d, 0x19, 0xd9, 0xb0, 0xe4, 0xf0, 0xe1, 0x90, 0xf8, 0x2a, 0x4d, - 0x2c, 0x6c, 0x14, 0x70, 0xdc, 0x55, 0x3b, 0x43, 0x44, 0x3f, 0xb4, 0xb3, 0xda, 0xac, 0xdb, 0xa8, - 0x04, 0x0b, 0xd4, 0x3f, 0xb1, 0x17, 0xb5, 0x49, 0x35, 0x95, 0xc5, 0x65, 0xd1, 0xed, 0x2b, 0x60, - 0xd5, 0x54, 0xbc, 0x51, 0x48, 0x85, 0xbd, 0x14, 0xed, 0xa8, 0x6a, 0xa3, 0x9f, 0x41, 0x6e, 0xc8, - 0x47, 0xbe, 0x0c, 0xed, 0xbc, 0x9e, 0xec, 0x6a, 0xda, 0x64, 0x9f, 0x2b, 0x84, 0x51, 0x96, 0x81, - 0xa3, 0x16, 0xac, 0x84, 0x92, 0x07, 0xbd, 0xbe, 0x20, 0x0e, 0xed, 0x05, 0x54, 0x30, 0xee, 0x9a, - 0x30, 0xbc, 0xfa, 0xc6, 0xa1, 0x34, 0x4d, 0xc1, 0x87, 0x6f, 0x2a, 0xce, 0x8e, 0xa2, 0x74, 0x34, - 0x03, 0x75, 0xa0, 0x18, 0x8c, 0x3c, 0xaf, 0xc7, 0x83, 0x28, 0x23, 0x47, 0x77, 0xe7, 0x1d, 0xb6, - 0xac, 0x33, 0xf2, 0xbc, 0xbd, 0x88, 0x84, 0xad, 0x60, 0xd2, 0x41, 0xb7, 0x21, 0xd7, 0x17, 0x7c, - 0x14, 0x44, 0xf7, 0xa6, 0x80, 0x4d, 0x0f, 0x7d, 0x03, 0x4b, 0x21, 0x75, 0x04, 0x95, 0xa1, 0x5d, - 0xd4, 0x4b, 0xfd, 0x38, 0x6d, 0x90, 0xae, 0x86, 0x24, 0x77, 0x02, 0xc7, 0x1c, 0xb4, 0x0a, 0x0b, - 0x52, 0x8e, 0xed, 0xe5, 0x4a, 0x66, 0x23, 0xdf, 0x58, 0xba, 0x38, 0x5f, 0x5f, 0xd8, 0xdf, 0x7f, - 0x89, 0x95, 0x4d, 0x65, 0x8b, 0x01, 0x0f, 0xa5, 0x4f, 0x86, 0xd4, 0xbe, 0xa1, 0xf7, 0x36, 0xe9, - 0xa3, 0x97, 0x00, 0xae, 0x1f, 0xf6, 0x1c, 0x1d, 0x9e, 0xec, 0x9b, 0x7a, 0x75, 0x9f, 0x5f, 0xbf, - 0xba, 0xe6, 0x6e, 0xd7, 0x64, 0xcc, 0xe5, 0x8b, 0xf3, 0xf5, 0x42, 0xd2, 0xc5, 0x05, 0xd7, 0x0f, - 0xa3, 0x26, 0x6a, 0x80, 0x35, 0xa0, 0xc4, 0x93, 0x03, 0x67, 0x40, 0x9d, 0x63, 0xbb, 0x74, 0x75, - 0x0a, 0x7c, 0xa2, 0x61, 0xc6, 0xc3, 0x34, 0x49, 0x29, 0x58, 0x4d, 0x35, 0xb4, 0x57, 0xf4, 0x5e, - 0x45, 0x1d, 0x74, 0x0f, 0x80, 0x07, 0xd4, 0xef, 0x85, 0xd2, 0x65, 0xbe, 0x8d, 0xd4, 0x92, 0x71, - 0x41, 0x59, 0xba, 0xca, 0x80, 0xee, 0xa8, 0x04, 0x45, 0xdc, 0x1e, 0xf7, 0xbd, 0xb1, 0xfd, 0x81, - 0xfe, 0x9a, 0x57, 0x86, 0x3d, 0xdf, 0x1b, 0xa3, 0x75, 0xb0, 0xb4, 0x2e, 0x42, 0xd6, 0xf7, 0x89, - 0x67, 0xdf, 0xd2, 0xfb, 0x01, 0xca, 0xd4, 0xd5, 0x16, 0x75, 0x0e, 0xd1, 0x6e, 0x84, 0xf6, 0x87, - 0x57, 0x9f, 0x83, 0x99, 0xec, 0xe4, 0x1c, 0x0c, 0x07, 0xfd, 0x02, 0x20, 0x10, 0xec, 0x84, 0x79, - 0xb4, 0x4f, 0x43, 0xfb, 0xb6, 0x5e, 0xf4, 0x5a, 0x6a, 0x66, 0x4a, 0x50, 0x78, 0x8a, 0x81, 0x6a, - 0x90, 0x65, 0x3e, 0x93, 0xf6, 0x47, 0x26, 0x2b, 0x5d, 0x96, 0x6a, 0x83, 0x73, 0xef, 0x80, 0x78, - 0x23, 0x8a, 0x35, 0x0e, 0xb5, 0xa1, 0xc0, 0x42, 0xee, 0x69, 0xf9, 0xda, 0xb6, 0x8e, 0x6f, 0xef, - 0x70, 0x7e, 0xed, 0x98, 0x82, 0x27, 0x6c, 0x74, 0x17, 0x0a, 0x01, 0x73, 0xc3, 0x67, 0x6c, 0xc8, - 0xa4, 0xbd, 0x5a, 0xc9, 0x6c, 0x2c, 0xe0, 0x89, 0xa1, 0xfc, 0x15, 0x58, 0x53, 0x61, 0x40, 0x5d, - 0xdf, 0x63, 0x3a, 0x36, 0x91, 0x45, 0x35, 0xd5, 0x59, 0x9d, 0xa8, 0x89, 0xe9, 0xd0, 0x57, 0xc0, - 0x51, 0xe7, 0xeb, 0xf9, 0x47, 0x99, 0xf2, 0x16, 0x58, 0x53, 0xd7, 0x01, 0x7d, 0xac, 0xc2, 0x72, - 0x9f, 0x85, 0x52, 0x8c, 0x7b, 0x64, 0x24, 0x07, 0xf6, 0xaf, 0x34, 0xa1, 0x18, 0x1b, 0xeb, 0x23, - 0x39, 0x28, 0xf7, 0x60, 0xa2, 0x2a, 0x54, 0x01, 0x4b, 0xa9, 0x35, 0xa4, 0xe2, 0x84, 0x0a, 0x55, - 0xf2, 0x28, 0x31, 0x4c, 0x9b, 0xd4, 0xad, 0x0a, 0x29, 0x11, 0xce, 0x40, 0x07, 0xb5, 0x02, 0x36, - 0x3d, 0x15, 0xa5, 0xe2, 0xab, 0x6b, 0xa2, 0x94, 0xe9, 0x56, 0xff, 0x96, 0x81, 0x42, 0xb2, 0x0d, - 0xe8, 0x0b, 0x58, 0x69, 0x77, 0xf7, 0x9e, 0xd5, 0xf7, 0xdb, 0x7b, 0xbb, 0xbd, 0x66, 0xeb, 0xdb, - 0xfa, 0x8b, 0x67, 0xfb, 0xa5, 0xb9, 0xf2, 0xbd, 0xd3, 0xb3, 0xca, 0xea, 0x24, 0xe2, 0xc6, 0xf0, - 0x26, 0x3d, 0x22, 0x23, 0x4f, 0xce, 0xb2, 0x3a, 0x78, 0x6f, 0xbb, 0xd5, 0xed, 0x96, 0x32, 0x57, - 0xb1, 0x3a, 0x82, 0x3b, 0x34, 0x0c, 0xd1, 0x16, 0x94, 0x26, 0xac, 0x27, 0x2f, 0x3b, 0x2d, 0x7c, - 0x50, 0x9a, 0x2f, 0xdf, 0x3d, 0x3d, 0xab, 0xd8, 0x6f, 0x92, 0x9e, 0x8c, 0x03, 0x2a, 0x0e, 0xcc, - 0x73, 0xe1, 0x5f, 0x19, 0x28, 0x4e, 0x57, 0x9b, 0x68, 0x3b, 0xaa, 0x12, 0xf5, 0x31, 0xdc, 0xd8, - 0xda, 0xbc, 0xae, 0x3a, 0xd5, 0x59, 0xce, 0x1b, 0x29, 0xbf, 0xcf, 0xd5, 0xc3, 0x50, 0x93, 0xd1, - 0x17, 0xb0, 0x18, 0x70, 0x21, 0xe3, 0x7c, 0x90, 0xae, 0x56, 0x2e, 0xe2, 0x1a, 0x26, 0x02, 0x57, - 0x07, 0x70, 0x63, 0xd6, 0x1b, 0x7a, 0x00, 0x0b, 0x07, 0xed, 0x4e, 0x69, 0xae, 0x7c, 0xe7, 0xf4, - 0xac, 0xf2, 0xd1, 0xec, 0xc7, 0x03, 0x26, 0xe4, 0x88, 0x78, 0xed, 0x0e, 0xfa, 0x0c, 0x16, 0x9b, - 0xbb, 0x5d, 0x8c, 0x4b, 0x99, 0xf2, 0xfa, 0xe9, 0x59, 0xe5, 0xce, 0x2c, 0x4e, 0x7d, 0xe2, 0x23, - 0xdf, 0xc5, 0xfc, 0x30, 0x79, 0x24, 0xfd, 0x7b, 0x1e, 0x2c, 0x93, 0x26, 0xdf, 0xf7, 0x3b, 0x7a, - 0x39, 0xaa, 0x01, 0xe3, 0xf8, 0x37, 0x7f, 0x6d, 0x29, 0x58, 0x8c, 0x08, 0x46, 0x97, 0xf7, 0xa1, - 0xc8, 0x82, 0x93, 0x2f, 0x7b, 0xd4, 0x27, 0x87, 0x9e, 0x79, 0x2f, 0xe5, 0xb1, 0xa5, 0x6c, 0xad, - 0xc8, 0xa4, 0x82, 0x2f, 0xf3, 0x25, 0x15, 0xbe, 0x79, 0x09, 0xe5, 0x71, 0xd2, 0x47, 0xdf, 0x40, - 0x96, 0x05, 0x64, 0x68, 0xea, 0xd7, 0xd4, 0x15, 0xb4, 0x3b, 0xf5, 0xe7, 0xe6, 0xde, 0x34, 0xf2, - 0x17, 0xe7, 0xeb, 0x59, 0x65, 0xc0, 0x9a, 0x86, 0xd6, 0xe2, 0x12, 0x52, 0x8d, 0xa4, 0x13, 0x69, - 0x1e, 0x4f, 0x59, 0x94, 0xf6, 0x99, 0xdf, 0x17, 0x34, 0x0c, 0x75, 0x4a, 0xcd, 0xe3, 0xb8, 0x8b, - 0xca, 0xb0, 0x64, 0x0a, 0x51, 0x5d, 0x79, 0x16, 0x54, 0x91, 0x67, 0x0c, 0x8d, 0x65, 0xb0, 0xa2, - 0xdd, 0xe8, 0x1d, 0x09, 0x3e, 0xac, 0xfe, 0x27, 0x0b, 0xd6, 0xb6, 0x37, 0x0a, 0xa5, 0xa9, 0x29, - 0xde, 0xdb, 0xe6, 0xbf, 0x84, 0x15, 0xa2, 0xdf, 0xe5, 0xc4, 0x57, 0x09, 0x5a, 0xd7, 0xf7, 0xe6, - 0x00, 0x1e, 0xa4, 0xba, 0x4b, 0xc0, 0xd1, 0x5b, 0xa0, 0x91, 0x53, 0x3e, 0xed, 0x0c, 0x2e, 0x91, - 0x4b, 0x5f, 0x50, 0x17, 0x96, 0xb9, 0x70, 0x06, 0x34, 0x94, 0x51, 0x5a, 0x37, 0xef, 0xd8, 0xd4, - 0x3f, 0x1c, 0x7b, 0xd3, 0x40, 0x93, 0xd3, 0xa2, 0xd9, 0xce, 0xfa, 0x40, 0x8f, 0x20, 0x2b, 0xc8, - 0x51, 0xfc, 0x56, 0x49, 0xbd, 0x24, 0x98, 0x1c, 0xc9, 0x19, 0x17, 0x9a, 0x81, 0x7e, 0x0d, 0xe0, - 0xb2, 0x30, 0x20, 0xd2, 0x19, 0x50, 0x61, 0x0e, 0x3b, 0x75, 0x89, 0xcd, 0x04, 0x35, 0xe3, 0x65, - 0x8a, 0x8d, 0x9e, 0x42, 0xc1, 0x21, 0xb1, 0x5c, 0x73, 0x57, 0x3f, 0xee, 0xb7, 0xeb, 0xc6, 0x45, - 0x49, 0xb9, 0xb8, 0x38, 0x5f, 0xcf, 0xc7, 0x16, 0x9c, 0x77, 0x88, 0x91, 0xef, 0x53, 0x58, 0x56, - 0x8f, 0xfe, 0x9e, 0x1b, 0x85, 0xb3, 0x48, 0x26, 0x57, 0xe4, 0x68, 0xf5, 0x82, 0x34, 0x61, 0x2f, - 0x3e, 0xce, 0xa2, 0x9c, 0xb2, 0xa1, 0xdf, 0xc0, 0x0a, 0xf5, 0x1d, 0x31, 0xd6, 0x62, 0x8d, 0x67, - 0x98, 0xbf, 0x7a, 0xb1, 0xad, 0x04, 0x3c, 0xb3, 0xd8, 0x12, 0xbd, 0x64, 0xaf, 0xfe, 0x33, 0x03, - 0x10, 0x95, 0x3d, 0xef, 0x57, 0x80, 0x08, 0xb2, 0x2e, 0x91, 0x44, 0x6b, 0xae, 0x88, 0x75, 0x1b, - 0x7d, 0x0d, 0x20, 0xe9, 0x30, 0x50, 0xa1, 0xd7, 0xef, 0x1b, 0xd9, 0xbc, 0x2d, 0x1c, 0x4c, 0xa1, - 0xd1, 0x16, 0xe4, 0xcc, 0x8b, 0x32, 0x7b, 0x2d, 0xcf, 0x20, 0xab, 0x7f, 0xc9, 0x00, 0x44, 0xcb, - 0xfc, 0xbf, 0x5e, 0x5b, 0xc3, 0x7e, 0xfd, 0xc3, 0xda, 0xdc, 0x3f, 0x7e, 0x58, 0x9b, 0xfb, 0xc3, - 0xc5, 0x5a, 0xe6, 0xf5, 0xc5, 0x5a, 0xe6, 0xef, 0x17, 0x6b, 0x99, 0xef, 0x2f, 0xd6, 0x32, 0x87, - 0x39, 0x5d, 0x99, 0xfc, 0xf4, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb8, 0xa3, 0x85, 0xdc, 0xc7, - 0x15, 0x00, 0x00, + // 2166 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x4d, 0x6f, 0x1b, 0xc9, + 0xd1, 0x16, 0x25, 0x8a, 0x1f, 0x35, 0x94, 0x4d, 0xf5, 0xda, 0xde, 0x11, 0x6d, 0x4b, 0x34, 0xd7, + 0xeb, 0x57, 0xbb, 0x8b, 0x97, 0x42, 0x94, 0xc5, 0xc6, 0x6b, 0x67, 0x93, 0x90, 0x22, 0x57, 0x62, + 0x6c, 0x4b, 0x44, 0x53, 0x56, 0x62, 0x20, 0x00, 0xd1, 0x9a, 0x69, 0x91, 0x03, 0x0d, 0xa7, 0x27, + 0xdd, 0x4d, 0x19, 0xbc, 0xe5, 0xb8, 0x50, 0x7e, 0x83, 0x90, 0x43, 0x90, 0x7b, 0xf2, 0x2f, 0x7c, + 0xcc, 0x31, 0xb9, 0x08, 0x59, 0x1d, 0xf2, 0x07, 0x72, 0xcb, 0x25, 0x41, 0xf7, 0xf4, 0xf0, 0x43, + 0x1e, 0x59, 0x0e, 0xe2, 0x43, 0x6e, 0xdd, 0x35, 0xcf, 0x53, 0xfd, 0xf5, 0x54, 0x75, 0xf5, 0xc0, + 0xe7, 0x3d, 0x4f, 0xf6, 0x87, 0x87, 0x55, 0x87, 0x0d, 0x36, 0x5c, 0xe6, 0x1c, 0x53, 0xbe, 0x21, + 0x5e, 0x13, 0x3e, 0x38, 0xf6, 0xe4, 0x06, 0x09, 0xbd, 0x0d, 0x11, 0x52, 0x47, 0x54, 0x43, 0xce, + 0x24, 0x43, 0x28, 0x02, 0x54, 0x63, 0x40, 0xf5, 0xe4, 0x07, 0xa5, 0xeb, 0xf8, 0x72, 0x14, 0x52, + 0xc3, 0x2f, 0xdd, 0xea, 0xb1, 0x1e, 0xd3, 0xcd, 0x0d, 0xd5, 0x32, 0xd6, 0xd5, 0x1e, 0x63, 0x3d, + 0x9f, 0x6e, 0xe8, 0xde, 0xe1, 0xf0, 0x68, 0xc3, 0x1d, 0x72, 0x22, 0x3d, 0x16, 0x98, 0xef, 0x2b, + 0x97, 0xbf, 0x93, 0x60, 0x74, 0x15, 0xf5, 0x35, 0x27, 0x61, 0x48, 0xb9, 0x19, 0xb0, 0x72, 0x96, + 0x86, 0xdc, 0x2e, 0x73, 0x69, 0x27, 0xa4, 0x0e, 0xda, 0x06, 0x8b, 0x04, 0x01, 0x93, 0xda, 0xb7, + 0xb0, 0x53, 0xe5, 0xd4, 0xba, 0xb5, 0xb9, 0x56, 0x7d, 0x7b, 0x4d, 0xd5, 0xda, 0x04, 0x56, 0x4f, + 0xbf, 0x39, 0x5f, 0x9b, 0xc3, 0xd3, 0x4c, 0xf4, 0x53, 0x28, 0xb8, 0x54, 0x78, 0x9c, 0xba, 0x5d, + 0xce, 0x7c, 0x6a, 0xcf, 0x97, 0x53, 0xeb, 0x37, 0x36, 0xef, 0x25, 0x79, 0x52, 0x83, 0x63, 0xe6, + 0x53, 0x6c, 0x19, 0x86, 0xea, 0xa0, 0x6d, 0x80, 0x01, 0x1d, 0x1c, 0x52, 0x2e, 0xfa, 0x5e, 0x68, + 0x2f, 0x68, 0xfa, 0xff, 0x5d, 0x45, 0x57, 0x73, 0xaf, 0xbe, 0x18, 0xc3, 0xf1, 0x14, 0x15, 0xbd, + 0x80, 0x02, 0x39, 0x21, 0x9e, 0x4f, 0x0e, 0x3d, 0xdf, 0x93, 0x23, 0x3b, 0xad, 0x5d, 0x7d, 0xf6, + 0x4e, 0x57, 0xb5, 0x29, 0x02, 0x9e, 0xa1, 0x57, 0x5c, 0x80, 0xc9, 0x40, 0xe8, 0x11, 0x64, 0xdb, + 0xcd, 0xdd, 0x46, 0x6b, 0x77, 0xbb, 0x38, 0x57, 0x5a, 0x39, 0x3d, 0x2b, 0xdf, 0x56, 0x3e, 0x26, + 0x80, 0x36, 0x0d, 0x5c, 0x2f, 0xe8, 0xa1, 0x75, 0xc8, 0xd5, 0xb6, 0xb6, 0x9a, 0xed, 0xfd, 0x66, + 0xa3, 0x98, 0x2a, 0x95, 0x4e, 0xcf, 0xca, 0x77, 0x66, 0x81, 0x35, 0xc7, 0xa1, 0xa1, 0xa4, 0x6e, + 0x29, 0xfd, 0xdd, 0xef, 0x57, 0xe7, 0x2a, 0xdf, 0xa5, 0xa0, 0x30, 0x3d, 0x09, 0xf4, 0x08, 0x32, + 0xb5, 0xad, 0xfd, 0xd6, 0x41, 0xb3, 0x38, 0x37, 0xa1, 0x4f, 0x23, 0x6a, 0x8e, 0xf4, 0x4e, 0x28, + 0x7a, 0x08, 0x8b, 0xed, 0xda, 0xcb, 0x4e, 0xb3, 0x98, 0x9a, 0x4c, 0x67, 0x1a, 0xd6, 0x26, 0x43, + 0xa1, 0x51, 0x0d, 0x5c, 0x6b, 0xed, 0x16, 0xe7, 0x93, 0x51, 0x0d, 0x4e, 0xbc, 0xc0, 0x4c, 0xe5, + 0x77, 0x69, 0xb0, 0x3a, 0x94, 0x9f, 0x78, 0xce, 0x07, 0x96, 0xc8, 0x57, 0x90, 0x96, 0x44, 0x1c, + 0x6b, 0x69, 0x58, 0xc9, 0xd2, 0xd8, 0x27, 0xe2, 0x58, 0x0d, 0x6a, 0xe8, 0x1a, 0xaf, 0x94, 0xc1, + 0x69, 0xe8, 0x7b, 0x0e, 0x91, 0xd4, 0xd5, 0xca, 0xb0, 0x36, 0x3f, 0x4d, 0x62, 0xe3, 0x31, 0xca, + 0xcc, 0x7f, 0x67, 0x0e, 0x4f, 0x51, 0xd1, 0x53, 0xc8, 0xf4, 0x7c, 0x76, 0x48, 0x7c, 0xad, 0x09, + 0x6b, 0xf3, 0x41, 0x92, 0x93, 0x6d, 0x8d, 0x98, 0x38, 0x30, 0x14, 0xf4, 0x18, 0x32, 0xc3, 0xd0, + 0x25, 0x92, 0xda, 0x19, 0x4d, 0x2e, 0x27, 0x91, 0x5f, 0x6a, 0xc4, 0x16, 0x0b, 0x8e, 0xbc, 0x1e, + 0x36, 0x78, 0xf4, 0x0c, 0x72, 0x01, 0x95, 0xaf, 0x19, 0x3f, 0x16, 0x76, 0xb6, 0xbc, 0xb0, 0x6e, + 0x6d, 0x7e, 0x91, 0x28, 0xc6, 0x08, 0x53, 0x93, 0x92, 0x38, 0xfd, 0x01, 0x0d, 0x64, 0xe4, 0xa6, + 0x3e, 0x6f, 0xa7, 0xf0, 0xd8, 0x01, 0xfa, 0x31, 0xe4, 0x68, 0xe0, 0x86, 0xcc, 0x0b, 0xa4, 0x9d, + 0xbb, 0x7a, 0x22, 0x4d, 0x83, 0x51, 0x9b, 0x89, 0xc7, 0x0c, 0xc5, 0xe6, 0xcc, 0xf7, 0x0f, 0x89, + 0x73, 0x6c, 0xe7, 0xdf, 0x73, 0x19, 0x63, 0x46, 0x3d, 0x03, 0xe9, 0x01, 0x73, 0x69, 0x65, 0x03, + 0x96, 0xdf, 0xda, 0x6a, 0x54, 0x82, 0x9c, 0xd9, 0xea, 0x48, 0x23, 0x69, 0x3c, 0xee, 0x57, 0x6e, + 0xc2, 0xd2, 0xcc, 0xb6, 0x56, 0xfe, 0xb8, 0x08, 0xb9, 0xf8, 0xac, 0x51, 0x0d, 0xf2, 0x0e, 0x0b, + 0x24, 0xf1, 0x02, 0xca, 0x8d, 0xbc, 0x12, 0x4f, 0x66, 0x2b, 0x06, 0x29, 0xd6, 0xce, 0x1c, 0x9e, + 0xb0, 0xd0, 0xb7, 0x90, 0xe7, 0x54, 0xb0, 0x21, 0x77, 0xa8, 0x30, 0xfa, 0x5a, 0x4f, 0x56, 0x48, + 0x04, 0xc2, 0xf4, 0xd7, 0x43, 0x8f, 0x53, 0xb5, 0xcb, 0x02, 0x4f, 0xa8, 0xe8, 0x29, 0x64, 0x39, + 0x15, 0x92, 0x70, 0xf9, 0x2e, 0x89, 0xe0, 0x08, 0xd2, 0x66, 0xbe, 0xe7, 0x8c, 0x70, 0xcc, 0x40, + 0x4f, 0x21, 0x1f, 0xfa, 0xc4, 0xd1, 0x5e, 0xed, 0x45, 0x4d, 0xbf, 0x9f, 0x44, 0x6f, 0xc7, 0x20, + 0x3c, 0xc1, 0xa3, 0xaf, 0x01, 0x7c, 0xd6, 0xeb, 0xba, 0xdc, 0x3b, 0xa1, 0xdc, 0x48, 0xac, 0x94, + 0xc4, 0x6e, 0x68, 0x04, 0xce, 0xfb, 0xac, 0x17, 0x35, 0xd1, 0xf6, 0x7f, 0xa5, 0xaf, 0x29, 0x6d, + 0x3d, 0x03, 0x20, 0xe3, 0xaf, 0x46, 0x5d, 0x9f, 0xbd, 0x97, 0x2b, 0x73, 0x22, 0x53, 0x74, 0xf4, + 0x00, 0x0a, 0x47, 0x8c, 0x3b, 0xb4, 0x6b, 0xa2, 0x26, 0xaf, 0x35, 0x61, 0x69, 0x5b, 0xa4, 0x2f, + 0x54, 0x87, 0x6c, 0x8f, 0x06, 0x94, 0x7b, 0x8e, 0x0d, 0x7a, 0xb0, 0x47, 0x89, 0x01, 0x19, 0x41, + 0xf0, 0x30, 0x90, 0xde, 0x80, 0x9a, 0x91, 0x62, 0x22, 0xfa, 0x15, 0x7c, 0x14, 0x1f, 0x5f, 0x97, + 0xd3, 0x23, 0xca, 0x69, 0xa0, 0x34, 0x60, 0xe9, 0x7d, 0xf8, 0xf4, 0xdd, 0x1a, 0x30, 0x68, 0x93, + 0x6c, 0x10, 0xbf, 0xfc, 0x41, 0xd4, 0xf3, 0x90, 0xe5, 0xd1, 0xb8, 0x95, 0xdf, 0xa6, 0x94, 0xea, + 0x2f, 0x21, 0xd0, 0x06, 0x58, 0xe3, 0xe1, 0x3d, 0x57, 0xab, 0x37, 0x5f, 0xbf, 0x71, 0x71, 0xbe, + 0x06, 0x31, 0xb6, 0xd5, 0x50, 0x39, 0xc8, 0xb4, 0x5d, 0xd4, 0x84, 0xa5, 0x31, 0x41, 0x95, 0x01, + 0xe6, 0xa2, 0x2c, 0xbf, 0x6b, 0xa6, 0xfb, 0xa3, 0x90, 0xe2, 0x02, 0x9f, 0xea, 0x55, 0x7e, 0x09, + 0xe8, 0xed, 0x7d, 0x41, 0x08, 0xd2, 0xc7, 0x5e, 0x60, 0xa6, 0x81, 0x75, 0x1b, 0x55, 0x21, 0x1b, + 0x92, 0x91, 0xcf, 0x88, 0x6b, 0x02, 0xe3, 0x56, 0x35, 0x2a, 0x10, 0xaa, 0x71, 0x81, 0x50, 0xad, + 0x05, 0x23, 0x1c, 0x83, 0x2a, 0xcf, 0xe0, 0x76, 0xe2, 0xf1, 0xa2, 0x4d, 0x28, 0x8c, 0x03, 0x6e, + 0xb2, 0xd6, 0x9b, 0x17, 0xe7, 0x6b, 0xd6, 0x38, 0x32, 0x5b, 0x0d, 0x6c, 0x8d, 0x41, 0x2d, 0xb7, + 0xf2, 0xf7, 0x02, 0x2c, 0xcd, 0x84, 0x2d, 0xba, 0x05, 0x8b, 0xde, 0x80, 0xf4, 0xa8, 0x99, 0x63, + 0xd4, 0x41, 0x4d, 0xc8, 0xf8, 0xe4, 0x90, 0xfa, 0x2a, 0x78, 0xd5, 0xc1, 0xfd, 0xff, 0xb5, 0xf1, + 0x5f, 0x7d, 0xae, 0xf1, 0xcd, 0x40, 0xf2, 0x11, 0x36, 0x64, 0x64, 0x43, 0xd6, 0x61, 0x83, 0x01, + 0x09, 0xd4, 0x35, 0xb1, 0xb0, 0x9e, 0xc7, 0x71, 0x57, 0xed, 0x0c, 0xe1, 0x3d, 0x61, 0xa7, 0xb5, + 0x59, 0xb7, 0x51, 0x11, 0x16, 0x68, 0x70, 0x62, 0x2f, 0x6a, 0x93, 0x6a, 0x2a, 0x8b, 0xeb, 0x45, + 0xd1, 0x97, 0xc7, 0xaa, 0xa9, 0x78, 0x43, 0x41, 0xb9, 0x9d, 0x8d, 0x76, 0x54, 0xb5, 0xd1, 0x8f, + 0x20, 0x33, 0x60, 0xc3, 0x40, 0x0a, 0x3b, 0xa7, 0x27, 0xbb, 0x92, 0x34, 0xd9, 0x17, 0x0a, 0x61, + 0x94, 0x65, 0xe0, 0xa8, 0x09, 0xcb, 0x42, 0xb2, 0xb0, 0xdb, 0xe3, 0xc4, 0xa1, 0xdd, 0x90, 0x72, + 0x8f, 0xb9, 0x26, 0x0d, 0xaf, 0xbc, 0x75, 0x28, 0x0d, 0x53, 0xf0, 0xe1, 0x9b, 0x8a, 0xb3, 0xad, + 0x28, 0x6d, 0xcd, 0x40, 0x6d, 0x28, 0x84, 0x43, 0xdf, 0xef, 0xb2, 0x30, 0xba, 0x91, 0xa3, 0xd8, + 0x79, 0x8f, 0x2d, 0x6b, 0x0f, 0x7d, 0x7f, 0x2f, 0x22, 0x61, 0x2b, 0x9c, 0x74, 0xd0, 0x1d, 0xc8, + 0xf4, 0x38, 0x1b, 0x86, 0x51, 0xdc, 0xe4, 0xb1, 0xe9, 0xa1, 0x6f, 0x20, 0x2b, 0xa8, 0xc3, 0xa9, + 0x14, 0x76, 0x41, 0x2f, 0xf5, 0x93, 0xa4, 0x41, 0x3a, 0x1a, 0x32, 0x8e, 0x09, 0x1c, 0x73, 0xd0, + 0x0a, 0x2c, 0x48, 0x39, 0xb2, 0x97, 0xca, 0xa9, 0xf5, 0x5c, 0x3d, 0x7b, 0x71, 0xbe, 0xb6, 0xb0, + 0xbf, 0xff, 0x0a, 0x2b, 0x9b, 0xba, 0x2d, 0xfa, 0x4c, 0xc8, 0x80, 0x0c, 0xa8, 0x7d, 0x43, 0xef, + 0xed, 0xb8, 0x8f, 0x5e, 0x01, 0xb8, 0x81, 0xe8, 0x3a, 0x3a, 0x3d, 0xd9, 0x37, 0xf5, 0xea, 0xbe, + 0xb8, 0x7e, 0x75, 0x8d, 0xdd, 0x8e, 0xb9, 0x31, 0x97, 0x2e, 0xce, 0xd7, 0xf2, 0xe3, 0x2e, 0xce, + 0xbb, 0x81, 0x88, 0x9a, 0xa8, 0x0e, 0x56, 0x9f, 0x12, 0x5f, 0xf6, 0x9d, 0x3e, 0x75, 0x8e, 0xed, + 0xe2, 0xd5, 0x57, 0xe0, 0x8e, 0x86, 0x19, 0x0f, 0xd3, 0x24, 0xa5, 0x60, 0x35, 0x55, 0x61, 0x2f, + 0xeb, 0xbd, 0x8a, 0x3a, 0xe8, 0x3e, 0x00, 0x0b, 0x69, 0xd0, 0x15, 0xd2, 0xf5, 0x02, 0x1b, 0xa9, + 0x25, 0xe3, 0xbc, 0xb2, 0x74, 0x94, 0x01, 0xdd, 0x55, 0x17, 0x14, 0x71, 0xbb, 0x2c, 0xf0, 0x47, + 0xf6, 0x47, 0xfa, 0x6b, 0x4e, 0x19, 0xf6, 0x02, 0x7f, 0x84, 0xd6, 0xc0, 0xd2, 0xba, 0x10, 0x5e, + 0x2f, 0x20, 0xbe, 0x7d, 0x4b, 0xef, 0x07, 0x28, 0x53, 0x47, 0x5b, 0xd4, 0x39, 0x44, 0xbb, 0x21, + 0xec, 0xdb, 0x57, 0x9f, 0x83, 0x99, 0xec, 0xe4, 0x1c, 0x0c, 0x07, 0xfd, 0x04, 0x20, 0xe4, 0xde, + 0x89, 0xe7, 0xd3, 0x1e, 0x15, 0xf6, 0x1d, 0xbd, 0xe8, 0xd5, 0xc4, 0x9b, 0x69, 0x8c, 0xc2, 0x53, + 0x0c, 0x54, 0x85, 0xb4, 0x17, 0x78, 0xd2, 0xfe, 0xd8, 0xdc, 0x4a, 0x97, 0xa5, 0x5a, 0x67, 0xcc, + 0x3f, 0x20, 0xfe, 0x90, 0x62, 0x8d, 0x43, 0x2d, 0xc8, 0x7b, 0x82, 0xf9, 0x5a, 0xbe, 0xb6, 0xad, + 0xf3, 0xdb, 0x7b, 0x9c, 0x5f, 0x2b, 0xa6, 0xe0, 0x09, 0x1b, 0xdd, 0x83, 0x7c, 0xe8, 0xb9, 0xe2, + 0xb9, 0x37, 0xf0, 0xa4, 0xbd, 0x52, 0x4e, 0xad, 0x2f, 0xe0, 0x89, 0x01, 0xed, 0x40, 0x56, 0x8c, + 0x84, 0x23, 0x7d, 0x61, 0x97, 0xf4, 0xbe, 0x54, 0xaf, 0x1f, 0xa6, 0x13, 0x11, 0xa2, 0xc4, 0x11, + 0xd3, 0x4b, 0x5f, 0x83, 0x35, 0x95, 0x50, 0x54, 0x22, 0x38, 0xa6, 0x23, 0x93, 0xa3, 0x54, 0x53, + 0x9d, 0xfa, 0x89, 0x5a, 0xa2, 0x4e, 0xa2, 0x79, 0x1c, 0x75, 0x9e, 0xcc, 0x3f, 0x4e, 0x95, 0x36, + 0xc1, 0x9a, 0x0a, 0x2c, 0xf4, 0x89, 0x4a, 0xf0, 0x3d, 0x4f, 0x48, 0x3e, 0xea, 0x92, 0xa1, 0xec, + 0xdb, 0x3f, 0xd3, 0x84, 0x42, 0x6c, 0xac, 0x0d, 0x65, 0xbf, 0xd4, 0x85, 0x89, 0x3e, 0x51, 0x19, + 0x2c, 0xa5, 0x7b, 0x41, 0xf9, 0x09, 0xe5, 0xaa, 0x78, 0x52, 0xb2, 0x9a, 0x36, 0xa9, 0xf8, 0x14, + 0x94, 0x70, 0xa7, 0xaf, 0xd3, 0x63, 0x1e, 0x9b, 0x9e, 0xca, 0x77, 0x71, 0x12, 0x30, 0xf9, 0xce, + 0x74, 0x4b, 0x4f, 0xa0, 0x30, 0xbd, 0xd0, 0xff, 0x64, 0x41, 0x95, 0x3f, 0xa5, 0x20, 0x3f, 0x3e, + 0x0c, 0xf4, 0x25, 0x2c, 0xb7, 0x3a, 0x7b, 0xcf, 0x6b, 0xfb, 0xad, 0xbd, 0xdd, 0x6e, 0xa3, 0xf9, + 0x6d, 0xed, 0xe5, 0xf3, 0xfd, 0xe2, 0x5c, 0xe9, 0xfe, 0xe9, 0x59, 0x79, 0x65, 0x92, 0xf7, 0x63, + 0x78, 0x83, 0x1e, 0x91, 0xa1, 0x2f, 0x67, 0x59, 0x6d, 0xbc, 0xb7, 0xd5, 0xec, 0x74, 0x8a, 0xa9, + 0xab, 0x58, 0x6d, 0xce, 0x1c, 0x2a, 0x04, 0xda, 0x84, 0xe2, 0x84, 0xb5, 0xf3, 0xaa, 0xdd, 0xc4, + 0x07, 0xc5, 0xf9, 0xd2, 0xbd, 0xd3, 0xb3, 0xb2, 0xfd, 0x36, 0x69, 0x67, 0x14, 0x52, 0x7e, 0x60, + 0x1e, 0x2d, 0xff, 0x48, 0x41, 0x61, 0xba, 0xe6, 0x45, 0x5b, 0x51, 0xad, 0xaa, 0x57, 0x7c, 0x63, + 0x73, 0xe3, 0xba, 0x1a, 0x59, 0xdf, 0xb5, 0xfe, 0x50, 0xf9, 0x7d, 0xa1, 0x9e, 0xa7, 0x9a, 0x8c, + 0xbe, 0x84, 0xc5, 0x90, 0x71, 0x19, 0xdf, 0x4a, 0xc9, 0x31, 0xc3, 0x78, 0x5c, 0x49, 0x45, 0xe0, + 0x4a, 0x1f, 0x6e, 0xcc, 0x7a, 0x43, 0x0f, 0x61, 0xe1, 0xa0, 0xd5, 0x2e, 0xce, 0x95, 0xee, 0x9e, + 0x9e, 0x95, 0x3f, 0x9e, 0xfd, 0x78, 0xe0, 0x71, 0x39, 0x24, 0x7e, 0xab, 0x8d, 0x3e, 0x87, 0xc5, + 0xc6, 0x6e, 0x07, 0xe3, 0x62, 0xaa, 0xb4, 0x76, 0x7a, 0x56, 0xbe, 0x3b, 0x8b, 0x53, 0x9f, 0xd8, + 0x30, 0x70, 0x31, 0x3b, 0x1c, 0x3f, 0xd5, 0xfe, 0x39, 0x0f, 0x96, 0xb9, 0xac, 0x3f, 0xf4, 0x6b, + 0x7e, 0x29, 0xaa, 0x44, 0xe3, 0x2c, 0x3c, 0x7f, 0x6d, 0x41, 0x5a, 0x88, 0x08, 0x46, 0xd3, 0x0f, + 0xa0, 0xe0, 0x85, 0x27, 0x5f, 0x75, 0x69, 0x40, 0x0e, 0x7d, 0xf3, 0x6a, 0xcb, 0x61, 0x4b, 0xd9, + 0x9a, 0x91, 0x49, 0x5d, 0x01, 0x5e, 0x20, 0x29, 0x0f, 0xcc, 0x7b, 0x2c, 0x87, 0xc7, 0x7d, 0xf4, + 0x0d, 0xa4, 0xbd, 0x90, 0x0c, 0x4c, 0x15, 0x9d, 0xb8, 0x82, 0x56, 0xbb, 0xf6, 0xc2, 0xc4, 0x5c, + 0x3d, 0x77, 0x71, 0xbe, 0x96, 0x56, 0x06, 0xac, 0x69, 0x68, 0x35, 0x2e, 0x64, 0xd5, 0x48, 0xfa, + 0x3a, 0xcf, 0xe1, 0x29, 0x8b, 0x8a, 0x1b, 0x2f, 0xe8, 0x71, 0x2a, 0x84, 0xbe, 0xd8, 0x73, 0x38, + 0xee, 0xa2, 0x12, 0x64, 0x4d, 0x39, 0xac, 0xeb, 0xdf, 0xbc, 0x2a, 0x35, 0x8d, 0xa1, 0xbe, 0x04, + 0x56, 0xb4, 0x1b, 0xdd, 0x23, 0xce, 0x06, 0x95, 0x7f, 0xa5, 0xc1, 0xda, 0xf2, 0x87, 0x42, 0x9a, + 0xca, 0xe6, 0x83, 0x6d, 0xfe, 0x2b, 0x58, 0x26, 0xfa, 0xef, 0x00, 0x09, 0x54, 0x99, 0xa0, 0x5f, + 0x19, 0xe6, 0x00, 0x1e, 0x26, 0xba, 0x1b, 0x83, 0xa3, 0x17, 0x49, 0x3d, 0xa3, 0x7c, 0xda, 0x29, + 0x5c, 0x24, 0x97, 0xbe, 0xa0, 0x0e, 0x2c, 0x31, 0xee, 0xf4, 0xa9, 0x90, 0x51, 0x71, 0x61, 0x5e, + 0xd3, 0x89, 0xff, 0x59, 0xf6, 0xa6, 0x81, 0xe6, 0x66, 0x8d, 0x66, 0x3b, 0xeb, 0x03, 0x3d, 0x86, + 0x34, 0x27, 0x47, 0xf1, 0x8b, 0x29, 0x31, 0x48, 0x30, 0x39, 0x92, 0x33, 0x2e, 0x34, 0x03, 0xfd, + 0x1c, 0xc0, 0xf5, 0x44, 0x48, 0xa4, 0xd3, 0xa7, 0xdc, 0x1c, 0x76, 0xe2, 0x12, 0x1b, 0x63, 0xd4, + 0x8c, 0x97, 0x29, 0x36, 0x7a, 0x06, 0x79, 0x87, 0xc4, 0x72, 0xcd, 0x5c, 0xfd, 0x8b, 0x61, 0xab, + 0x66, 0x5c, 0x14, 0x95, 0x8b, 0x8b, 0xf3, 0xb5, 0x5c, 0x6c, 0xc1, 0x39, 0x87, 0x18, 0xf9, 0x3e, + 0x83, 0x25, 0x49, 0xc4, 0x71, 0xd7, 0x8d, 0xd2, 0x59, 0x24, 0x93, 0x2b, 0x2a, 0x05, 0xf5, 0x8e, + 0x35, 0x69, 0x2f, 0x3e, 0xce, 0x82, 0x9c, 0xb2, 0xa1, 0x5f, 0xc0, 0x32, 0x0d, 0x1c, 0x3e, 0xd2, + 0x62, 0x8d, 0x67, 0x98, 0xbb, 0x7a, 0xb1, 0xcd, 0x31, 0x78, 0x66, 0xb1, 0x45, 0x7a, 0xc9, 0x5e, + 0xf9, 0x6b, 0x0a, 0x20, 0x2a, 0xbe, 0x3e, 0xac, 0x00, 0x11, 0xa4, 0x5d, 0x22, 0x89, 0xd6, 0x5c, + 0x01, 0xeb, 0x36, 0x7a, 0x02, 0x20, 0xe9, 0x20, 0x54, 0xa9, 0x37, 0xe8, 0x19, 0xd9, 0xbc, 0x2b, + 0x1d, 0x4c, 0xa1, 0xd1, 0x26, 0x64, 0xcc, 0xbb, 0x36, 0x7d, 0x2d, 0xcf, 0x20, 0x2b, 0x7f, 0x48, + 0x01, 0x44, 0xcb, 0xfc, 0x9f, 0x5e, 0x5b, 0xdd, 0x7e, 0xf3, 0xfd, 0xea, 0xdc, 0x5f, 0xbe, 0x5f, + 0x9d, 0xfb, 0xcd, 0xc5, 0x6a, 0xea, 0xcd, 0xc5, 0x6a, 0xea, 0xcf, 0x17, 0xab, 0xa9, 0xbf, 0x5d, + 0xac, 0xa6, 0x0e, 0x33, 0xba, 0x3e, 0xfa, 0xe1, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x32, 0x89, + 0x54, 0x8a, 0x4d, 0x16, 0x00, 0x00, } diff --git a/vendor/github.com/docker/swarmkit/api/specs.proto b/vendor/github.com/docker/swarmkit/api/specs.proto index 14448d0409c5f..f4645426099a4 100644 --- a/vendor/github.com/docker/swarmkit/api/specs.proto +++ b/vendor/github.com/docker/swarmkit/api/specs.proto @@ -315,9 +315,24 @@ message ContainerSpec { // Runtimes that don't support it ignore that field Isolation isolation = 24; - // PidsLimit prevents from OS resource damage by applications inside the container + // PidsLimit prevents from OS resource damage by applications inside the container // using fork bomb attack. int64 pidsLimit = 25; + + // Sysctls sets namespaced kernel parameters (sysctls) in the container. This + // option is equivalent to passing --sysctl to docker run. + // + // Note that while options are subject to the same restrictions as arguments + // passed to the --sysctl flag on docker run, those options are not further + // validated to ensure that they are safe or sensible in a clustered + // environment. + // + // Additionally, sysctls are not validated for support in the underlying + // daemon. For information about supported options, refer to the + // documentation at: + // + // https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime + map sysctls = 26; } // EndpointSpec defines the properties that can be configured to diff --git a/vendor/github.com/docker/swarmkit/api/types.pb.go b/vendor/github.com/docker/swarmkit/api/types.pb.go index 2ddc007569c4a..f41d5e2033735 100644 --- a/vendor/github.com/docker/swarmkit/api/types.pb.go +++ b/vendor/github.com/docker/swarmkit/api/types.pb.go @@ -213,20 +213,23 @@ func (NodeStatus_State) EnumDescriptor() ([]byte, []int) { return fileDescriptor type Mount_MountType int32 const ( - MountTypeBind Mount_MountType = 0 - MountTypeVolume Mount_MountType = 1 - MountTypeTmpfs Mount_MountType = 2 + MountTypeBind Mount_MountType = 0 + MountTypeVolume Mount_MountType = 1 + MountTypeTmpfs Mount_MountType = 2 + MountTypeNamedPipe Mount_MountType = 3 ) var Mount_MountType_name = map[int32]string{ 0: "BIND", 1: "VOLUME", 2: "TMPFS", + 3: "NPIPE", } var Mount_MountType_value = map[string]int32{ "BIND": 0, "VOLUME": 1, "TMPFS": 2, + "NPIPE": 3, } func (x Mount_MountType) String() string { @@ -17080,325 +17083,326 @@ var ( func init() { proto.RegisterFile("github.com/docker/swarmkit/api/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 5116 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x7a, 0x5d, 0x6c, 0x23, 0x59, - 0x56, 0x7f, 0xec, 0xd8, 0x8e, 0x7d, 0xec, 0x24, 0xd5, 0xb7, 0xb3, 0x3d, 0x69, 0x6f, 0x4f, 0xe2, - 0xa9, 0x99, 0xde, 0x99, 0xed, 0x9d, 0xbf, 0xfb, 0x6b, 0x77, 0xd5, 0x33, 0xf3, 0xdf, 0x9d, 0xb1, - 0xcb, 0x95, 0x8e, 0xb7, 0xd3, 0xb6, 0x75, 0xed, 0x74, 0xef, 0x22, 0x41, 0x51, 0xa9, 0xba, 0x71, - 0x6a, 0x52, 0xae, 0x6b, 0xaa, 0xca, 0xe9, 0x36, 0x0b, 0x62, 0xc4, 0x03, 0xa0, 0x3c, 0xc1, 0x0b, - 0x2c, 0x42, 0x41, 0x48, 0xf0, 0xc6, 0x03, 0x0f, 0x20, 0x21, 0x78, 0x1a, 0x24, 0x84, 0x56, 0xbc, - 0xc0, 0x82, 0x84, 0x56, 0x20, 0x05, 0x36, 0x0f, 0xbc, 0xad, 0xe0, 0x05, 0xf1, 0xc2, 0x03, 0xba, - 0x1f, 0x55, 0xae, 0xb8, 0x2b, 0xc9, 0x0c, 0xbb, 0x2f, 0x89, 0xef, 0x39, 0xbf, 0x73, 0xee, 0xbd, - 0xe7, 0xde, 0x7b, 0xee, 0x39, 0xe7, 0x16, 0xdc, 0x19, 0x3a, 0xe1, 0xc1, 0x64, 0xaf, 0x6e, 0xd1, - 0xd1, 0x5d, 0x9b, 0x5a, 0x87, 0xc4, 0xbf, 0x1b, 0xbc, 0x30, 0xfd, 0xd1, 0xa1, 0x13, 0xde, 0x35, - 0xc7, 0xce, 0xdd, 0x70, 0x3a, 0x26, 0x41, 0x7d, 0xec, 0xd3, 0x90, 0x22, 0x24, 0x00, 0xf5, 0x08, - 0x50, 0x3f, 0xba, 0x5f, 0xdd, 0x1c, 0x52, 0x3a, 0x74, 0xc9, 0x5d, 0x8e, 0xd8, 0x9b, 0xec, 0xdf, - 0x0d, 0x9d, 0x11, 0x09, 0x42, 0x73, 0x34, 0x16, 0x42, 0xd5, 0x8d, 0x79, 0x80, 0x3d, 0xf1, 0xcd, - 0xd0, 0xa1, 0x9e, 0xe4, 0xaf, 0x0d, 0xe9, 0x90, 0xf2, 0x9f, 0x77, 0xd9, 0x2f, 0x41, 0x55, 0x37, - 0x61, 0xe9, 0x19, 0xf1, 0x03, 0x87, 0x7a, 0x68, 0x0d, 0xf2, 0x8e, 0x67, 0x93, 0x97, 0xeb, 0x99, - 0x5a, 0xe6, 0x9d, 0x1c, 0x16, 0x0d, 0xf5, 0x1e, 0x40, 0x9b, 0xfd, 0xd0, 0xbd, 0xd0, 0x9f, 0x22, - 0x05, 0x16, 0x0f, 0xc9, 0x94, 0x23, 0x4a, 0x98, 0xfd, 0x64, 0x94, 0x23, 0xd3, 0x5d, 0xcf, 0x0a, - 0xca, 0x91, 0xe9, 0xaa, 0x3f, 0xca, 0x40, 0xb9, 0xe1, 0x79, 0x34, 0xe4, 0xbd, 0x07, 0x08, 0x41, - 0xce, 0x33, 0x47, 0x44, 0x0a, 0xf1, 0xdf, 0x48, 0x83, 0x82, 0x6b, 0xee, 0x11, 0x37, 0x58, 0xcf, - 0xd6, 0x16, 0xdf, 0x29, 0x3f, 0xf8, 0x4a, 0xfd, 0xd5, 0x29, 0xd7, 0x13, 0x4a, 0xea, 0x3b, 0x1c, - 0xcd, 0x07, 0x81, 0xa5, 0x28, 0xfa, 0x26, 0x2c, 0x39, 0x9e, 0xed, 0x58, 0x24, 0x58, 0xcf, 0x71, - 0x2d, 0x1b, 0x69, 0x5a, 0x66, 0xa3, 0x6f, 0xe6, 0xbe, 0x7f, 0xba, 0xb9, 0x80, 0x23, 0xa1, 0xea, - 0x7b, 0x50, 0x4e, 0xa8, 0x4d, 0x99, 0xdb, 0x1a, 0xe4, 0x8f, 0x4c, 0x77, 0x42, 0xe4, 0xec, 0x44, - 0xe3, 0xfd, 0xec, 0xa3, 0x8c, 0xfa, 0x11, 0xac, 0x75, 0xcc, 0x11, 0xb1, 0x1f, 0x13, 0x8f, 0xf8, - 0x8e, 0x85, 0x49, 0x40, 0x27, 0xbe, 0x45, 0xd8, 0x5c, 0x0f, 0x1d, 0xcf, 0x8e, 0xe6, 0xca, 0x7e, - 0xa7, 0x6b, 0x51, 0x35, 0x78, 0xad, 0xe5, 0x04, 0x96, 0x4f, 0x42, 0xf2, 0xb9, 0x95, 0x2c, 0x46, - 0x4a, 0x4e, 0x33, 0xb0, 0x3a, 0x2f, 0xfd, 0x33, 0x70, 0x9d, 0x99, 0xd8, 0x36, 0x7c, 0x49, 0x31, - 0x82, 0x31, 0xb1, 0xb8, 0xb2, 0xf2, 0x83, 0x77, 0xd2, 0x2c, 0x94, 0x36, 0x93, 0xed, 0x05, 0x7c, - 0x8d, 0xab, 0x89, 0x08, 0xfd, 0x31, 0xb1, 0x90, 0x05, 0x37, 0x6c, 0x39, 0xe8, 0x39, 0xf5, 0x59, - 0xae, 0x3e, 0x75, 0x19, 0x2f, 0x98, 0xe6, 0xf6, 0x02, 0x5e, 0x8b, 0x94, 0x25, 0x3b, 0x69, 0x02, - 0x14, 0x23, 0xdd, 0xea, 0xf7, 0x32, 0x50, 0x8a, 0x98, 0x01, 0xfa, 0x32, 0x94, 0x3c, 0xd3, 0xa3, - 0x86, 0x35, 0x9e, 0x04, 0x7c, 0x42, 0x8b, 0xcd, 0xca, 0xd9, 0xe9, 0x66, 0xb1, 0x63, 0x7a, 0x54, - 0xeb, 0xed, 0x06, 0xb8, 0xc8, 0xd8, 0xda, 0x78, 0x12, 0xa0, 0x37, 0xa0, 0x32, 0x22, 0x23, 0xea, - 0x4f, 0x8d, 0xbd, 0x69, 0x48, 0x02, 0x69, 0xb6, 0xb2, 0xa0, 0x35, 0x19, 0x09, 0x7d, 0x03, 0x96, - 0x86, 0x62, 0x48, 0xeb, 0x8b, 0x7c, 0xfb, 0xbc, 0x99, 0x36, 0xfa, 0xb9, 0x51, 0xe3, 0x48, 0x46, - 0xfd, 0xcd, 0x0c, 0xac, 0xc5, 0x54, 0xf2, 0x0b, 0x13, 0xc7, 0x27, 0x23, 0xe2, 0x85, 0x01, 0xfa, - 0x1a, 0x14, 0x5c, 0x67, 0xe4, 0x84, 0x81, 0xb4, 0xf9, 0xeb, 0x69, 0x6a, 0xe3, 0x49, 0x61, 0x09, - 0x46, 0x0d, 0xa8, 0xf8, 0x24, 0x20, 0xfe, 0x91, 0xd8, 0xf1, 0xd2, 0xa2, 0x57, 0x08, 0x9f, 0x13, - 0x51, 0xb7, 0xa0, 0xd8, 0x73, 0xcd, 0x70, 0x9f, 0xfa, 0x23, 0xa4, 0x42, 0xc5, 0xf4, 0xad, 0x03, - 0x27, 0x24, 0x56, 0x38, 0xf1, 0xa3, 0xd3, 0x77, 0x8e, 0x86, 0x6e, 0x40, 0x96, 0x8a, 0x8e, 0x4a, - 0xcd, 0xc2, 0xd9, 0xe9, 0x66, 0xb6, 0xdb, 0xc7, 0x59, 0x1a, 0xa8, 0x1f, 0xc0, 0xb5, 0x9e, 0x3b, - 0x19, 0x3a, 0x5e, 0x8b, 0x04, 0x96, 0xef, 0x8c, 0x99, 0x76, 0xb6, 0x2b, 0x99, 0x8f, 0x8a, 0x76, - 0x25, 0xfb, 0x1d, 0x1f, 0xed, 0xec, 0xec, 0x68, 0xab, 0xbf, 0x9e, 0x85, 0x6b, 0xba, 0x37, 0x74, - 0x3c, 0x92, 0x94, 0xbe, 0x0d, 0x2b, 0x84, 0x13, 0x8d, 0x23, 0xe1, 0x6e, 0xa4, 0x9e, 0x65, 0x41, - 0x8d, 0x7c, 0x50, 0x7b, 0xce, 0x2f, 0xdc, 0x4f, 0x9b, 0xfe, 0x2b, 0xda, 0x53, 0xbd, 0x83, 0x0e, - 0x4b, 0x63, 0x3e, 0x89, 0x40, 0x2e, 0xef, 0xed, 0x34, 0x5d, 0xaf, 0xcc, 0x33, 0x72, 0x12, 0x52, - 0xf6, 0x27, 0x71, 0x12, 0x7f, 0x9b, 0x85, 0xd5, 0x0e, 0xb5, 0xcf, 0xd9, 0xa1, 0x0a, 0xc5, 0x03, - 0x1a, 0x84, 0x09, 0x87, 0x18, 0xb7, 0xd1, 0x23, 0x28, 0x8e, 0xe5, 0xf2, 0xc9, 0xd5, 0xbf, 0x95, - 0x3e, 0x64, 0x81, 0xc1, 0x31, 0x1a, 0x7d, 0x00, 0xa5, 0xe8, 0xc8, 0xb0, 0xd9, 0x7e, 0x86, 0x8d, - 0x33, 0xc3, 0xa3, 0x6f, 0x40, 0x41, 0x2c, 0xc2, 0x7a, 0x8e, 0x4b, 0xde, 0xfe, 0x4c, 0x36, 0xc7, - 0x52, 0x08, 0x3d, 0x86, 0x62, 0xe8, 0x06, 0x86, 0xe3, 0xed, 0xd3, 0xf5, 0x3c, 0x57, 0xb0, 0x99, - 0xea, 0x64, 0xa8, 0x4d, 0x06, 0x3b, 0xfd, 0xb6, 0xb7, 0x4f, 0x9b, 0xe5, 0xb3, 0xd3, 0xcd, 0x25, - 0xd9, 0xc0, 0x4b, 0xa1, 0x1b, 0xb0, 0x1f, 0xe8, 0x16, 0xe4, 0xf6, 0x9d, 0x71, 0xb0, 0x5e, 0xa8, - 0x65, 0xde, 0x29, 0x36, 0x8b, 0x67, 0xa7, 0x9b, 0xb9, 0xad, 0x76, 0xaf, 0x8f, 0x39, 0x55, 0xfd, - 0xad, 0x0c, 0x94, 0x13, 0x3a, 0xd0, 0xeb, 0x00, 0xa1, 0x3f, 0x09, 0x42, 0xc3, 0xa7, 0x34, 0xe4, - 0xa6, 0xac, 0xe0, 0x12, 0xa7, 0x60, 0x4a, 0x43, 0x54, 0x87, 0xeb, 0x16, 0xf1, 0x43, 0xc3, 0x09, - 0x82, 0x09, 0xf1, 0x8d, 0x60, 0xb2, 0xf7, 0x31, 0xb1, 0x42, 0x6e, 0xd6, 0x0a, 0xbe, 0xc6, 0x58, - 0x6d, 0xce, 0xe9, 0x0b, 0x06, 0x7a, 0x08, 0x37, 0x92, 0xf8, 0xf1, 0x64, 0xcf, 0x75, 0x2c, 0x83, - 0x2d, 0xf5, 0x22, 0x17, 0xb9, 0x3e, 0x13, 0xe9, 0x71, 0xde, 0x13, 0x32, 0x55, 0x7f, 0x98, 0x01, - 0x05, 0x9b, 0xfb, 0xe1, 0x53, 0x32, 0xda, 0x23, 0x7e, 0x3f, 0x34, 0xc3, 0x49, 0x80, 0x6e, 0x40, - 0xc1, 0x25, 0xa6, 0x4d, 0x7c, 0x3e, 0xa8, 0x22, 0x96, 0x2d, 0xb4, 0xcb, 0xce, 0xb7, 0x69, 0x1d, - 0x98, 0x7b, 0x8e, 0xeb, 0x84, 0x53, 0x3e, 0x94, 0x95, 0xf4, 0x0d, 0x3e, 0xaf, 0xb3, 0x8e, 0x13, - 0x82, 0xf8, 0x9c, 0x1a, 0xb4, 0x0e, 0x4b, 0x23, 0x12, 0x04, 0xe6, 0x90, 0xf0, 0x91, 0x96, 0x70, - 0xd4, 0x54, 0x3f, 0x80, 0x4a, 0x52, 0x0e, 0x95, 0x61, 0x69, 0xb7, 0xf3, 0xa4, 0xd3, 0x7d, 0xde, - 0x51, 0x16, 0xd0, 0x2a, 0x94, 0x77, 0x3b, 0x58, 0x6f, 0x68, 0xdb, 0x8d, 0xe6, 0x8e, 0xae, 0x64, - 0xd0, 0x32, 0x94, 0x66, 0xcd, 0xac, 0xfa, 0xa7, 0x19, 0x00, 0x66, 0x6e, 0x39, 0xa9, 0xf7, 0x21, - 0x1f, 0x84, 0x66, 0x28, 0xf6, 0xec, 0xca, 0x83, 0xb7, 0x2e, 0x5a, 0x61, 0x39, 0x5e, 0xf6, 0x8f, - 0x60, 0x21, 0x92, 0x1c, 0x61, 0xf6, 0xdc, 0x08, 0x99, 0xfb, 0x30, 0x6d, 0xdb, 0x97, 0x03, 0xe7, - 0xbf, 0xd5, 0x0f, 0x20, 0xcf, 0xa5, 0xcf, 0x0f, 0xb7, 0x08, 0xb9, 0x16, 0xfb, 0x95, 0x41, 0x25, - 0xc8, 0x63, 0xbd, 0xd1, 0xfa, 0x8e, 0x92, 0x45, 0x0a, 0x54, 0x5a, 0xed, 0xbe, 0xd6, 0xed, 0x74, - 0x74, 0x6d, 0xa0, 0xb7, 0x94, 0x45, 0xf5, 0x36, 0xe4, 0xdb, 0x23, 0xa6, 0xf9, 0x16, 0x3b, 0x10, - 0xfb, 0xc4, 0x27, 0x9e, 0x15, 0x9d, 0xb3, 0x19, 0x41, 0xfd, 0x71, 0x19, 0xf2, 0x4f, 0xe9, 0xc4, - 0x0b, 0xd1, 0x83, 0x84, 0x53, 0x5b, 0x49, 0x8f, 0x1f, 0x38, 0xb0, 0x3e, 0x98, 0x8e, 0x89, 0x74, - 0x7a, 0x37, 0xa0, 0x20, 0x8e, 0x8e, 0x9c, 0x8e, 0x6c, 0x31, 0x7a, 0x68, 0xfa, 0x43, 0x12, 0xca, - 0xf9, 0xc8, 0x16, 0x7a, 0x87, 0xdd, 0x67, 0xa6, 0x4d, 0x3d, 0x77, 0xca, 0x4f, 0x58, 0x51, 0x5c, - 0x5a, 0x98, 0x98, 0x76, 0xd7, 0x73, 0xa7, 0x38, 0xe6, 0xa2, 0x6d, 0xa8, 0xec, 0x39, 0x9e, 0x6d, - 0xd0, 0xb1, 0xb8, 0x02, 0xf2, 0x17, 0x9f, 0x47, 0x31, 0xaa, 0xa6, 0xe3, 0xd9, 0x5d, 0x01, 0xc6, - 0xe5, 0xbd, 0x59, 0x03, 0x75, 0x60, 0xe5, 0x88, 0xba, 0x93, 0x11, 0x89, 0x75, 0x15, 0xb8, 0xae, - 0xb7, 0x2f, 0xd6, 0xf5, 0x8c, 0xe3, 0x23, 0x6d, 0xcb, 0x47, 0xc9, 0x26, 0x7a, 0x02, 0xcb, 0xe1, - 0x68, 0xbc, 0x1f, 0xc4, 0xea, 0x96, 0xb8, 0xba, 0x2f, 0x5d, 0x62, 0x30, 0x06, 0x8f, 0xb4, 0x55, - 0xc2, 0x44, 0x0b, 0x3d, 0x86, 0xb2, 0x45, 0xbd, 0xc0, 0x09, 0x42, 0xe2, 0x59, 0xd3, 0xf5, 0x22, - 0xb7, 0xfd, 0x25, 0xb3, 0xd4, 0x66, 0x60, 0x9c, 0x94, 0xac, 0xfe, 0xea, 0x22, 0x94, 0x13, 0x26, - 0x40, 0x7d, 0x28, 0x8f, 0x7d, 0x3a, 0x36, 0x87, 0xfc, 0x3e, 0x94, 0x8b, 0x7a, 0xff, 0x33, 0x99, - 0xaf, 0xde, 0x9b, 0x09, 0xe2, 0xa4, 0x16, 0xf5, 0x24, 0x0b, 0xe5, 0x04, 0x13, 0xdd, 0x81, 0x22, - 0xee, 0xe1, 0xf6, 0xb3, 0xc6, 0x40, 0x57, 0x16, 0xaa, 0xb7, 0x8e, 0x4f, 0x6a, 0xeb, 0x5c, 0x5b, - 0x52, 0x41, 0xcf, 0x77, 0x8e, 0xd8, 0x1e, 0x7e, 0x07, 0x96, 0x22, 0x68, 0xa6, 0xfa, 0xc5, 0xe3, - 0x93, 0xda, 0x6b, 0xf3, 0xd0, 0x04, 0x12, 0xf7, 0xb7, 0x1b, 0x58, 0x6f, 0x29, 0xd9, 0x74, 0x24, - 0xee, 0x1f, 0x98, 0x3e, 0xb1, 0xd1, 0x97, 0xa0, 0x20, 0x81, 0x8b, 0xd5, 0xea, 0xf1, 0x49, 0xed, - 0xc6, 0x3c, 0x70, 0x86, 0xc3, 0xfd, 0x9d, 0xc6, 0x33, 0x5d, 0xc9, 0xa5, 0xe3, 0x70, 0xdf, 0x35, - 0x8f, 0x08, 0x7a, 0x0b, 0xf2, 0x02, 0x96, 0xaf, 0xde, 0x3c, 0x3e, 0xa9, 0x7d, 0xe1, 0x15, 0x75, - 0x0c, 0x55, 0x5d, 0xff, 0x8d, 0x3f, 0xdc, 0x58, 0xf8, 0xcb, 0x3f, 0xda, 0x50, 0xe6, 0xd9, 0xd5, - 0xff, 0xc9, 0xc0, 0xf2, 0xb9, 0xbd, 0x83, 0x54, 0x28, 0x78, 0xd4, 0xa2, 0x63, 0x71, 0x4d, 0x16, - 0x9b, 0x70, 0x76, 0xba, 0x59, 0xe8, 0x50, 0x8d, 0x8e, 0xa7, 0x58, 0x72, 0xd0, 0x93, 0xb9, 0x8b, - 0xfe, 0xe1, 0x67, 0xdc, 0x98, 0xa9, 0x57, 0xfd, 0x87, 0xb0, 0x6c, 0xfb, 0xce, 0x11, 0xf1, 0x0d, - 0x8b, 0x7a, 0xfb, 0xce, 0x50, 0x5e, 0x81, 0xd5, 0xd4, 0x68, 0x94, 0x03, 0x71, 0x45, 0x08, 0x68, - 0x1c, 0xff, 0x13, 0x5c, 0xf2, 0xd5, 0x67, 0x50, 0x49, 0x6e, 0x75, 0x76, 0x2f, 0x05, 0xce, 0x2f, - 0x12, 0x19, 0x76, 0xf2, 0x20, 0x15, 0x97, 0x18, 0x45, 0x04, 0x9d, 0x6f, 0x43, 0x6e, 0x44, 0x6d, - 0xa1, 0x67, 0xb9, 0x79, 0x9d, 0xc5, 0x1a, 0xff, 0x7c, 0xba, 0x59, 0xa6, 0x41, 0x7d, 0xcb, 0x71, - 0xc9, 0x53, 0x6a, 0x13, 0xcc, 0x01, 0xea, 0x11, 0xe4, 0x98, 0xcf, 0x41, 0x5f, 0x84, 0x5c, 0xb3, - 0xdd, 0x69, 0x29, 0x0b, 0xd5, 0x6b, 0xc7, 0x27, 0xb5, 0x65, 0x6e, 0x12, 0xc6, 0x60, 0x7b, 0x17, - 0x6d, 0x42, 0xe1, 0x59, 0x77, 0x67, 0xf7, 0x29, 0xdb, 0x5e, 0xd7, 0x8f, 0x4f, 0x6a, 0xab, 0x31, - 0x5b, 0x18, 0x0d, 0xbd, 0x0e, 0xf9, 0xc1, 0xd3, 0xde, 0x56, 0x5f, 0xc9, 0x56, 0xd1, 0xf1, 0x49, - 0x6d, 0x25, 0xe6, 0xf3, 0x31, 0x57, 0xaf, 0xc9, 0x55, 0x2d, 0xc5, 0x74, 0xf5, 0x07, 0x19, 0x28, - 0x27, 0x0e, 0x1c, 0xdb, 0x98, 0x2d, 0x7d, 0xab, 0xb1, 0xbb, 0x33, 0x50, 0x16, 0x12, 0x1b, 0x33, - 0x01, 0x69, 0x91, 0x7d, 0x73, 0xe2, 0x32, 0x3f, 0x07, 0x5a, 0xb7, 0xd3, 0x6f, 0xf7, 0x07, 0x7a, - 0x67, 0xa0, 0x64, 0xaa, 0xeb, 0xc7, 0x27, 0xb5, 0xb5, 0x79, 0xf0, 0xd6, 0xc4, 0x75, 0xd9, 0xd6, - 0xd4, 0x1a, 0xda, 0x36, 0xdf, 0xeb, 0xb3, 0xad, 0x99, 0x40, 0x69, 0xa6, 0x75, 0x40, 0x6c, 0xf4, - 0x2e, 0x94, 0x5a, 0xfa, 0x8e, 0xfe, 0xb8, 0xc1, 0xbd, 0x7b, 0xf5, 0xf5, 0xe3, 0x93, 0xda, 0xcd, - 0x57, 0x7b, 0x77, 0xc9, 0xd0, 0x0c, 0x89, 0x3d, 0xb7, 0x45, 0x13, 0x10, 0xf5, 0xbf, 0xb2, 0xb0, - 0x8c, 0x59, 0xb2, 0xec, 0x87, 0x3d, 0xea, 0x3a, 0xd6, 0x14, 0xf5, 0xa0, 0x64, 0x51, 0xcf, 0x76, - 0x12, 0x7e, 0xe2, 0xc1, 0x05, 0x01, 0xd3, 0x4c, 0x2a, 0x6a, 0x69, 0x91, 0x24, 0x9e, 0x29, 0x41, - 0x77, 0x21, 0x6f, 0x13, 0xd7, 0x9c, 0xca, 0xc8, 0xed, 0x66, 0x5d, 0xa4, 0xe3, 0xf5, 0x28, 0x1d, - 0xaf, 0xb7, 0x64, 0x3a, 0x8e, 0x05, 0x8e, 0x67, 0x28, 0xe6, 0x4b, 0xc3, 0x0c, 0x43, 0x32, 0x1a, - 0x87, 0x22, 0x6c, 0xcb, 0xe1, 0xf2, 0xc8, 0x7c, 0xd9, 0x90, 0x24, 0x74, 0x1f, 0x0a, 0x2f, 0x1c, - 0xcf, 0xa6, 0x2f, 0x64, 0x64, 0x76, 0x89, 0x52, 0x09, 0x54, 0x8f, 0x59, 0x48, 0x32, 0x37, 0x4c, - 0xb6, 0x87, 0x3a, 0xdd, 0x8e, 0x1e, 0xed, 0x21, 0xc9, 0xef, 0x7a, 0x1d, 0xea, 0xb1, 0xf3, 0x0f, - 0xdd, 0x8e, 0xb1, 0xd5, 0x68, 0xef, 0xec, 0x62, 0xb6, 0x8f, 0xd6, 0x8e, 0x4f, 0x6a, 0x4a, 0x0c, - 0xd9, 0x32, 0x1d, 0x97, 0xa5, 0x0a, 0x37, 0x61, 0xb1, 0xd1, 0xf9, 0x8e, 0x92, 0xad, 0x2a, 0xc7, - 0x27, 0xb5, 0x4a, 0xcc, 0x6e, 0x78, 0xd3, 0x99, 0xdd, 0xe7, 0xfb, 0x55, 0xff, 0x6e, 0x11, 0x2a, - 0xbb, 0x63, 0xdb, 0x0c, 0x89, 0x38, 0x67, 0xa8, 0x06, 0xe5, 0xb1, 0xe9, 0x9b, 0xae, 0x4b, 0x5c, - 0x27, 0x18, 0xc9, 0x42, 0x43, 0x92, 0x84, 0xde, 0xfb, 0xac, 0x66, 0x6c, 0x16, 0xd9, 0xd9, 0xf9, - 0xde, 0xbf, 0x6e, 0x66, 0x22, 0x83, 0xee, 0xc2, 0xca, 0xbe, 0x18, 0xad, 0x61, 0x5a, 0x7c, 0x61, - 0x17, 0xf9, 0xc2, 0xd6, 0xd3, 0x16, 0x36, 0x39, 0xac, 0xba, 0x9c, 0x64, 0x83, 0x4b, 0xe1, 0xe5, - 0xfd, 0x64, 0x13, 0x3d, 0x84, 0xa5, 0x11, 0xf5, 0x9c, 0x90, 0xfa, 0x57, 0xaf, 0x42, 0x84, 0x44, - 0x77, 0xe0, 0x1a, 0x5b, 0xdc, 0x68, 0x3c, 0x9c, 0xcd, 0xaf, 0xf3, 0x2c, 0x5e, 0x1d, 0x99, 0x2f, - 0x65, 0x87, 0x98, 0x91, 0x51, 0x13, 0xf2, 0xd4, 0x67, 0xf1, 0x62, 0x81, 0x0f, 0xf7, 0xdd, 0x2b, - 0x87, 0x2b, 0x1a, 0x5d, 0x26, 0x83, 0x85, 0xa8, 0xfa, 0x75, 0x58, 0x3e, 0x37, 0x09, 0x16, 0x26, - 0xf5, 0x1a, 0xbb, 0x7d, 0x5d, 0x59, 0x40, 0x15, 0x28, 0x6a, 0xdd, 0xce, 0xa0, 0xdd, 0xd9, 0x65, - 0x71, 0x5e, 0x05, 0x8a, 0xb8, 0xbb, 0xb3, 0xd3, 0x6c, 0x68, 0x4f, 0x94, 0xac, 0x5a, 0x87, 0x72, - 0x42, 0x1b, 0x5a, 0x01, 0xe8, 0x0f, 0xba, 0x3d, 0x63, 0xab, 0x8d, 0xfb, 0x03, 0x11, 0x25, 0xf6, - 0x07, 0x0d, 0x3c, 0x90, 0x84, 0x8c, 0xfa, 0x1f, 0xd9, 0x68, 0x45, 0x65, 0x60, 0xd8, 0x3c, 0x1f, - 0x18, 0x5e, 0x32, 0x78, 0x19, 0x1a, 0xce, 0x1a, 0x71, 0x80, 0xf8, 0x1e, 0x00, 0xdf, 0x38, 0xc4, - 0x36, 0xcc, 0x50, 0x2e, 0x7c, 0xf5, 0x15, 0x23, 0x0f, 0xa2, 0x7a, 0x17, 0x2e, 0x49, 0x74, 0x23, - 0x44, 0xdf, 0x80, 0x8a, 0x45, 0x47, 0x63, 0x97, 0x48, 0xe1, 0xc5, 0x2b, 0x85, 0xcb, 0x31, 0xbe, - 0x11, 0x26, 0x43, 0xd3, 0xdc, 0xf9, 0xe0, 0xf9, 0xd7, 0x32, 0x91, 0x65, 0x52, 0xa2, 0xd1, 0x0a, - 0x14, 0x77, 0x7b, 0xad, 0xc6, 0xa0, 0xdd, 0x79, 0xac, 0x64, 0x10, 0x40, 0x81, 0x9b, 0xba, 0xa5, - 0x64, 0x59, 0x14, 0xad, 0x75, 0x9f, 0xf6, 0x76, 0x74, 0xee, 0xb1, 0xd0, 0x1a, 0x28, 0x91, 0xb1, - 0x0d, 0x6e, 0x48, 0xbd, 0xa5, 0xe4, 0xd0, 0x75, 0x58, 0x8d, 0xa9, 0x52, 0x32, 0x8f, 0x6e, 0x00, - 0x8a, 0x89, 0x33, 0x15, 0x05, 0xf5, 0x97, 0x61, 0x55, 0xa3, 0x5e, 0x68, 0x3a, 0x5e, 0x9c, 0x61, - 0x3c, 0x60, 0x93, 0x96, 0x24, 0xc3, 0x91, 0x75, 0xa2, 0xe6, 0xea, 0xd9, 0xe9, 0x66, 0x39, 0x86, - 0xb6, 0x5b, 0x3c, 0x54, 0x92, 0x0d, 0x9b, 0x9d, 0xdf, 0xb1, 0x63, 0x73, 0xe3, 0xe6, 0x9b, 0x4b, - 0x67, 0xa7, 0x9b, 0x8b, 0xbd, 0x76, 0x0b, 0x33, 0x1a, 0xfa, 0x22, 0x94, 0xc8, 0x4b, 0x27, 0x34, - 0x2c, 0x76, 0x2f, 0x31, 0x03, 0xe6, 0x71, 0x91, 0x11, 0x34, 0x76, 0x0d, 0x35, 0x01, 0x7a, 0xd4, - 0x0f, 0x65, 0xcf, 0x5f, 0x85, 0xfc, 0x98, 0xfa, 0xbc, 0xb2, 0x71, 0x61, 0xbd, 0x8d, 0xc1, 0xc5, - 0x46, 0xc5, 0x02, 0xac, 0xfe, 0xee, 0x22, 0xc0, 0xc0, 0x0c, 0x0e, 0xa5, 0x92, 0x47, 0x50, 0x8a, - 0x6b, 0x97, 0xb2, 0x44, 0x72, 0xe9, 0x6a, 0xc7, 0x60, 0xf4, 0x30, 0xda, 0x6c, 0x22, 0x77, 0x4a, - 0x4d, 0x71, 0xa3, 0x8e, 0xd2, 0xd2, 0x8f, 0xf3, 0x09, 0x12, 0xbb, 0xe6, 0x89, 0xef, 0xcb, 0x95, - 0x67, 0x3f, 0x91, 0xc6, 0xaf, 0x05, 0x61, 0x34, 0x19, 0x7d, 0xa7, 0x16, 0x85, 0xe6, 0x56, 0x64, - 0x7b, 0x01, 0xcf, 0xe4, 0xd0, 0x87, 0x50, 0x66, 0xf3, 0x36, 0x02, 0xce, 0x93, 0x81, 0xf7, 0x85, - 0xa6, 0x12, 0x1a, 0x30, 0x8c, 0x67, 0x56, 0x7e, 0x1d, 0xc0, 0x1c, 0x8f, 0x5d, 0x87, 0xd8, 0xc6, - 0xde, 0x94, 0x47, 0xda, 0x25, 0x5c, 0x92, 0x94, 0xe6, 0x94, 0x1d, 0x97, 0x88, 0x6d, 0x86, 0x3c, - 0x7a, 0xbe, 0xc2, 0x80, 0x12, 0xdd, 0x08, 0x9b, 0x0a, 0xac, 0xf8, 0x13, 0x8f, 0x19, 0x54, 0x8e, - 0x4e, 0xfd, 0x93, 0x2c, 0xbc, 0xd6, 0x21, 0xe1, 0x0b, 0xea, 0x1f, 0x36, 0xc2, 0xd0, 0xb4, 0x0e, - 0x46, 0xc4, 0x93, 0xcb, 0x97, 0x48, 0x68, 0x32, 0xe7, 0x12, 0x9a, 0x75, 0x58, 0x32, 0x5d, 0xc7, - 0x0c, 0x88, 0x08, 0xde, 0x4a, 0x38, 0x6a, 0xb2, 0xb4, 0x8b, 0x25, 0x71, 0x24, 0x08, 0x88, 0xa8, - 0xba, 0xb0, 0x81, 0x47, 0x04, 0xf4, 0x5d, 0xb8, 0x21, 0xc3, 0x34, 0x33, 0xee, 0x8a, 0x25, 0x14, - 0x51, 0xf9, 0x56, 0x4f, 0xcd, 0x2a, 0xd3, 0x07, 0x27, 0xe3, 0xb8, 0x19, 0xb9, 0x3b, 0x0e, 0x65, - 0x54, 0xb8, 0x66, 0xa7, 0xb0, 0xaa, 0x8f, 0xe1, 0xe6, 0x85, 0x22, 0x9f, 0xab, 0xaa, 0xf3, 0x8f, - 0x59, 0x80, 0x76, 0xaf, 0xf1, 0x54, 0x1a, 0xa9, 0x05, 0x85, 0x7d, 0x73, 0xe4, 0xb8, 0xd3, 0xcb, - 0x3c, 0xe0, 0x0c, 0x5f, 0x6f, 0x08, 0x73, 0x6c, 0x71, 0x19, 0x2c, 0x65, 0x79, 0x4e, 0x39, 0xd9, - 0xf3, 0x48, 0x18, 0xe7, 0x94, 0xbc, 0xc5, 0x86, 0xe1, 0x9b, 0x5e, 0xbc, 0x75, 0x45, 0x83, 0x2d, - 0x00, 0x0b, 0x79, 0x5e, 0x98, 0xd3, 0xc8, 0x6d, 0xc9, 0x26, 0xda, 0xe6, 0xb5, 0x53, 0xe2, 0x1f, - 0x11, 0x7b, 0x3d, 0xcf, 0x8d, 0x7a, 0xd5, 0x78, 0xb0, 0x84, 0x0b, 0xdb, 0xc5, 0xd2, 0xd5, 0x0f, - 0x78, 0xc8, 0x34, 0x63, 0x7d, 0x2e, 0x1b, 0xdd, 0x83, 0xe5, 0x73, 0xf3, 0x7c, 0x25, 0x99, 0x6f, - 0xf7, 0x9e, 0x7d, 0x55, 0xc9, 0xc9, 0x5f, 0x5f, 0x57, 0x0a, 0xea, 0xdf, 0x2c, 0x0a, 0x47, 0x23, - 0xad, 0x9a, 0xfe, 0x66, 0x50, 0xe4, 0xbb, 0xdb, 0xa2, 0xae, 0x74, 0x00, 0x6f, 0x5f, 0xee, 0x7f, - 0x58, 0x4e, 0xc7, 0xe1, 0x38, 0x16, 0x44, 0x9b, 0x50, 0x16, 0xbb, 0xd8, 0x60, 0x07, 0x8e, 0x9b, - 0x75, 0x19, 0x83, 0x20, 0x31, 0x49, 0x74, 0x1b, 0x56, 0x78, 0xf1, 0x27, 0x38, 0x20, 0xb6, 0xc0, - 0xe4, 0x38, 0x66, 0x39, 0xa6, 0x72, 0xd8, 0x53, 0xa8, 0x48, 0x82, 0xc1, 0xe3, 0xf9, 0x3c, 0x1f, - 0xd0, 0x9d, 0xab, 0x06, 0x24, 0x44, 0x78, 0x98, 0x5f, 0x1e, 0xcf, 0x1a, 0xea, 0xcf, 0x43, 0x31, - 0x1a, 0x2c, 0x5a, 0x87, 0xc5, 0x81, 0xd6, 0x53, 0x16, 0xaa, 0xab, 0xc7, 0x27, 0xb5, 0x72, 0x44, - 0x1e, 0x68, 0x3d, 0xc6, 0xd9, 0x6d, 0xf5, 0x94, 0xcc, 0x79, 0xce, 0x6e, 0xab, 0x87, 0xaa, 0x90, - 0xeb, 0x6b, 0x83, 0x5e, 0x14, 0x9f, 0x45, 0x2c, 0x46, 0xab, 0xe6, 0x58, 0x7c, 0xa6, 0xee, 0x43, - 0x39, 0xd1, 0x3b, 0x7a, 0x13, 0x96, 0xda, 0x9d, 0xc7, 0x58, 0xef, 0xf7, 0x95, 0x85, 0xea, 0x8d, - 0xe3, 0x93, 0x1a, 0x4a, 0x70, 0xdb, 0xde, 0x90, 0xad, 0x1d, 0x7a, 0x1d, 0x72, 0xdb, 0x5d, 0x76, - 0xef, 0x8b, 0xe4, 0x22, 0x81, 0xd8, 0xa6, 0x41, 0x58, 0xbd, 0x2e, 0x03, 0xbf, 0xa4, 0x62, 0xf5, - 0xf7, 0x32, 0x50, 0x10, 0x07, 0x2d, 0x75, 0x11, 0x1b, 0xb0, 0x14, 0x95, 0x10, 0x44, 0xe2, 0xf7, - 0xf6, 0xc5, 0x49, 0x5a, 0x5d, 0xe6, 0x54, 0x62, 0x6b, 0x46, 0x72, 0xd5, 0xf7, 0xa1, 0x92, 0x64, - 0x7c, 0xae, 0x8d, 0xf9, 0x5d, 0x28, 0xb3, 0xbd, 0x1f, 0x25, 0x6b, 0x0f, 0xa0, 0x20, 0x9c, 0x45, - 0x7c, 0x0f, 0x5d, 0x9c, 0x31, 0x4a, 0x24, 0x7a, 0x04, 0x4b, 0x22, 0xcb, 0x8c, 0xea, 0xca, 0x1b, - 0x97, 0x9f, 0x30, 0x1c, 0xc1, 0xd5, 0x0f, 0x21, 0xd7, 0x23, 0xc4, 0x67, 0xb6, 0xf7, 0xa8, 0x4d, - 0x66, 0x57, 0xb7, 0x4c, 0x90, 0x6d, 0xd2, 0x6e, 0xb1, 0x04, 0xd9, 0x26, 0x6d, 0x3b, 0xae, 0x8d, - 0x65, 0x13, 0xb5, 0xb1, 0x01, 0x54, 0x9e, 0x13, 0x67, 0x78, 0x10, 0x12, 0x9b, 0x2b, 0x7a, 0x17, - 0x72, 0x63, 0x12, 0x0f, 0x7e, 0x3d, 0x75, 0xf3, 0x11, 0xe2, 0x63, 0x8e, 0x62, 0x3e, 0xe6, 0x05, - 0x97, 0x96, 0x8f, 0x21, 0xb2, 0xa5, 0xfe, 0x43, 0x16, 0x56, 0xda, 0x41, 0x30, 0x31, 0x3d, 0x2b, - 0x8a, 0xea, 0xbe, 0x79, 0x3e, 0xaa, 0x4b, 0x7d, 0x35, 0x3a, 0x2f, 0x72, 0xbe, 0xe4, 0x27, 0x6f, - 0xd6, 0x6c, 0x7c, 0xb3, 0xaa, 0x3f, 0xce, 0x44, 0x75, 0xbd, 0xdb, 0x09, 0x57, 0x20, 0x72, 0xc4, - 0xa4, 0x26, 0xb2, 0xeb, 0x1d, 0x7a, 0xf4, 0x85, 0x87, 0xde, 0x80, 0x3c, 0xd6, 0x3b, 0xfa, 0x73, - 0x25, 0x23, 0xb6, 0xe7, 0x39, 0x10, 0x26, 0x1e, 0x79, 0xc1, 0x34, 0xf5, 0xf4, 0x4e, 0x8b, 0x45, - 0x61, 0xd9, 0x14, 0x4d, 0x3d, 0xe2, 0xd9, 0x8e, 0x37, 0x44, 0x6f, 0x42, 0xa1, 0xdd, 0xef, 0xef, - 0xf2, 0x14, 0xf2, 0xb5, 0xe3, 0x93, 0xda, 0xf5, 0x73, 0x28, 0x5e, 0xd3, 0xb5, 0x19, 0x88, 0xa5, - 0x40, 0x2c, 0x3e, 0x4b, 0x01, 0xb1, 0xd8, 0x5a, 0x80, 0x70, 0x77, 0xd0, 0x18, 0xe8, 0x4a, 0x3e, - 0x05, 0x84, 0x29, 0xfb, 0x2b, 0x8f, 0xdb, 0xbf, 0x64, 0x41, 0x69, 0x58, 0x16, 0x19, 0x87, 0x8c, - 0x2f, 0xb3, 0xce, 0x01, 0x14, 0xc7, 0xec, 0x97, 0x43, 0xa2, 0x08, 0xea, 0x51, 0xea, 0xbb, 0xe7, - 0x9c, 0x5c, 0x1d, 0x53, 0x97, 0x34, 0xec, 0x91, 0x13, 0x04, 0x0e, 0xf5, 0x04, 0x0d, 0xc7, 0x9a, - 0xaa, 0xff, 0x99, 0x81, 0xeb, 0x29, 0x08, 0x74, 0x0f, 0x72, 0x3e, 0x75, 0xa3, 0x35, 0xbc, 0x75, - 0x51, 0xc9, 0x96, 0x89, 0x62, 0x8e, 0x44, 0x1b, 0x00, 0xe6, 0x24, 0xa4, 0x26, 0xef, 0x9f, 0xaf, - 0x5e, 0x11, 0x27, 0x28, 0xe8, 0x39, 0x14, 0x02, 0x62, 0xf9, 0x24, 0x8a, 0xb3, 0x3f, 0xfc, 0xbf, - 0x8e, 0xbe, 0xde, 0xe7, 0x6a, 0xb0, 0x54, 0x57, 0xad, 0x43, 0x41, 0x50, 0xd8, 0xb6, 0xb7, 0xcd, - 0xd0, 0x94, 0x05, 0x7d, 0xfe, 0x9b, 0xed, 0x26, 0xd3, 0x1d, 0x46, 0xbb, 0xc9, 0x74, 0x87, 0xea, - 0x5f, 0x67, 0x01, 0xf4, 0x97, 0x21, 0xf1, 0x3d, 0xd3, 0xd5, 0x1a, 0x48, 0x4f, 0xdc, 0x0c, 0x62, - 0xb6, 0x5f, 0x4e, 0x7d, 0xc3, 0x88, 0x25, 0xea, 0x5a, 0x23, 0xe5, 0x6e, 0xb8, 0x09, 0x8b, 0x13, - 0x5f, 0x3e, 0x65, 0x8b, 0x18, 0x79, 0x17, 0xef, 0x60, 0x46, 0x43, 0xfa, 0xcc, 0x6d, 0x2d, 0x5e, - 0xfc, 0x60, 0x9d, 0xe8, 0x20, 0xd5, 0x75, 0xb1, 0x93, 0x6f, 0x99, 0x86, 0x45, 0xe4, 0xad, 0x52, - 0x11, 0x27, 0x5f, 0x6b, 0x68, 0xc4, 0x0f, 0x71, 0xc1, 0x32, 0xd9, 0xff, 0x9f, 0xc8, 0xbf, 0xbd, - 0x0b, 0x30, 0x9b, 0x1a, 0xda, 0x80, 0xbc, 0xb6, 0xd5, 0xef, 0xef, 0x28, 0x0b, 0xc2, 0x81, 0xcf, - 0x58, 0x9c, 0xac, 0xfe, 0x45, 0x16, 0x8a, 0x5a, 0x43, 0x5e, 0xb9, 0x1a, 0x28, 0xdc, 0x2b, 0xf1, - 0x67, 0x10, 0xf2, 0x72, 0xec, 0xf8, 0x53, 0xe9, 0x58, 0x2e, 0x49, 0x78, 0x57, 0x98, 0x08, 0x1b, - 0xb5, 0xce, 0x05, 0x10, 0x86, 0x0a, 0x91, 0x46, 0x30, 0x2c, 0x33, 0xf2, 0xf1, 0x1b, 0x97, 0x1b, - 0x4b, 0xa4, 0x2e, 0xb3, 0x76, 0x80, 0xcb, 0x91, 0x12, 0xcd, 0x0c, 0xd0, 0x7b, 0xb0, 0x1a, 0x38, - 0x43, 0xcf, 0xf1, 0x86, 0x46, 0x64, 0x3c, 0xfe, 0x26, 0xd3, 0xbc, 0x76, 0x76, 0xba, 0xb9, 0xdc, - 0x17, 0x2c, 0x69, 0xc3, 0x65, 0x89, 0xd4, 0xb8, 0x29, 0xd1, 0xd7, 0x61, 0x25, 0x21, 0xca, 0xac, - 0x28, 0xcc, 0xae, 0x9c, 0x9d, 0x6e, 0x56, 0x62, 0xc9, 0x27, 0x64, 0x8a, 0x2b, 0xb1, 0xe0, 0x13, - 0xc2, 0x6b, 0x33, 0xfb, 0xd4, 0xb7, 0x88, 0xe1, 0xf3, 0x33, 0xcd, 0x6f, 0xf7, 0x1c, 0x2e, 0x73, - 0x9a, 0x38, 0xe6, 0xea, 0x33, 0xb8, 0xde, 0xf5, 0xad, 0x03, 0x12, 0x84, 0xc2, 0x14, 0xd2, 0x8a, - 0x1f, 0xc2, 0xad, 0xd0, 0x0c, 0x0e, 0x8d, 0x03, 0x27, 0x08, 0xa9, 0x3f, 0x35, 0x7c, 0x12, 0x12, - 0x8f, 0xf1, 0x0d, 0xfe, 0xcc, 0x2b, 0x0b, 0x82, 0x37, 0x19, 0x66, 0x5b, 0x40, 0x70, 0x84, 0xd8, - 0x61, 0x00, 0xb5, 0x0d, 0x15, 0x96, 0xc2, 0xc8, 0xa2, 0x1a, 0x9b, 0x3d, 0xb8, 0x74, 0x68, 0x7c, - 0xe6, 0x6b, 0xaa, 0xe4, 0xd2, 0xa1, 0xf8, 0xa9, 0x7e, 0x1b, 0x94, 0x96, 0x13, 0x8c, 0xcd, 0xd0, - 0x3a, 0x88, 0x2a, 0x9d, 0xa8, 0x05, 0xca, 0x01, 0x31, 0xfd, 0x70, 0x8f, 0x98, 0xa1, 0x31, 0x26, - 0xbe, 0x43, 0xed, 0xab, 0x57, 0x79, 0x35, 0x16, 0xe9, 0x71, 0x09, 0xf5, 0xbf, 0x33, 0x00, 0xd8, - 0xdc, 0x8f, 0xa2, 0xb5, 0xaf, 0xc0, 0xb5, 0xc0, 0x33, 0xc7, 0xc1, 0x01, 0x0d, 0x0d, 0xc7, 0x0b, - 0x89, 0x7f, 0x64, 0xba, 0xb2, 0xb8, 0xa3, 0x44, 0x8c, 0xb6, 0xa4, 0xa3, 0x77, 0x01, 0x1d, 0x12, - 0x32, 0x36, 0xa8, 0x6b, 0x1b, 0x11, 0x53, 0x3c, 0x42, 0xe7, 0xb0, 0xc2, 0x38, 0x5d, 0xd7, 0xee, - 0x47, 0x74, 0xd4, 0x84, 0x0d, 0x36, 0x7d, 0xe2, 0x85, 0xbe, 0x43, 0x02, 0x63, 0x9f, 0xfa, 0x46, - 0xe0, 0xd2, 0x17, 0xc6, 0x3e, 0x75, 0x5d, 0xfa, 0x82, 0xf8, 0x51, 0xdd, 0xac, 0xea, 0xd2, 0xa1, - 0x2e, 0x40, 0x5b, 0xd4, 0xef, 0xbb, 0xf4, 0xc5, 0x56, 0x84, 0x60, 0x21, 0xdd, 0x6c, 0xce, 0xa1, - 0x63, 0x1d, 0x46, 0x21, 0x5d, 0x4c, 0x1d, 0x38, 0xd6, 0x21, 0x7a, 0x13, 0x96, 0x89, 0x4b, 0x78, - 0xf9, 0x44, 0xa0, 0xf2, 0x1c, 0x55, 0x89, 0x88, 0x0c, 0xa4, 0x7e, 0x04, 0x8a, 0xee, 0x59, 0xfe, - 0x74, 0x9c, 0x58, 0xf3, 0x77, 0x01, 0x31, 0x27, 0x69, 0xb8, 0xd4, 0x3a, 0x34, 0x46, 0xa6, 0x67, - 0x0e, 0xd9, 0xb8, 0xc4, 0xeb, 0x9f, 0xc2, 0x38, 0x3b, 0xd4, 0x3a, 0x7c, 0x2a, 0xe9, 0xea, 0x7b, - 0x00, 0xfd, 0xb1, 0x4f, 0x4c, 0xbb, 0xcb, 0xa2, 0x09, 0x66, 0x3a, 0xde, 0x32, 0x6c, 0xf9, 0xb6, - 0x4a, 0x7d, 0x79, 0xd4, 0x15, 0xc1, 0x68, 0xc5, 0x74, 0xf5, 0x67, 0xe1, 0x7a, 0xcf, 0x35, 0x2d, - 0xfe, 0x9d, 0x41, 0x2f, 0x7e, 0xce, 0x42, 0x8f, 0xa0, 0x20, 0xa0, 0x72, 0x25, 0x53, 0x8f, 0xdb, - 0xac, 0xcf, 0xed, 0x05, 0x2c, 0xf1, 0xcd, 0x0a, 0xc0, 0x4c, 0x8f, 0xfa, 0x67, 0x19, 0x28, 0xc5, - 0xfa, 0x51, 0x4d, 0xbc, 0xd2, 0x84, 0xbe, 0xe9, 0x78, 0x32, 0xe3, 0x2f, 0xe1, 0x24, 0x09, 0xb5, - 0xa1, 0x3c, 0x8e, 0xa5, 0x2f, 0x8d, 0xe7, 0x52, 0x46, 0x8d, 0x93, 0xb2, 0xe8, 0x7d, 0x28, 0x45, - 0x8f, 0xd9, 0x91, 0x87, 0xbd, 0xfc, 0xed, 0x7b, 0x06, 0x57, 0xbf, 0x09, 0xf0, 0x2d, 0xea, 0x78, - 0x03, 0x7a, 0x48, 0x3c, 0xfe, 0xfc, 0xca, 0xf2, 0x45, 0x12, 0x59, 0x51, 0xb6, 0x78, 0x19, 0x40, - 0x2c, 0x41, 0xfc, 0x0a, 0x29, 0x9a, 0xea, 0x5f, 0x65, 0xa1, 0x80, 0x29, 0x0d, 0xb5, 0x06, 0xaa, - 0x41, 0x41, 0xfa, 0x09, 0x7e, 0xff, 0x34, 0x4b, 0x67, 0xa7, 0x9b, 0x79, 0xe1, 0x20, 0xf2, 0x16, - 0xf7, 0x0c, 0x09, 0x0f, 0x9e, 0xbd, 0xc8, 0x83, 0xa3, 0x7b, 0x50, 0x91, 0x20, 0xe3, 0xc0, 0x0c, - 0x0e, 0x44, 0xf2, 0xd6, 0x5c, 0x39, 0x3b, 0xdd, 0x04, 0x81, 0xdc, 0x36, 0x83, 0x03, 0x0c, 0x02, - 0xcd, 0x7e, 0x23, 0x1d, 0xca, 0x1f, 0x53, 0xc7, 0x33, 0x42, 0x3e, 0x09, 0x59, 0x68, 0x4c, 0x5d, - 0xc7, 0xd9, 0x54, 0xe5, 0x97, 0x0a, 0xf0, 0xf1, 0x6c, 0xf2, 0x3a, 0x2c, 0xfb, 0x94, 0x86, 0xc2, - 0x6d, 0x39, 0xd4, 0x93, 0x35, 0x8c, 0x5a, 0x6a, 0x69, 0x9b, 0xd2, 0x10, 0x4b, 0x1c, 0xae, 0xf8, - 0x89, 0x16, 0xba, 0x07, 0x6b, 0xae, 0x19, 0x84, 0x06, 0xf7, 0x77, 0xf6, 0x4c, 0x5b, 0x81, 0x1f, - 0x35, 0xc4, 0x78, 0x5b, 0x9c, 0x15, 0x49, 0xa8, 0xff, 0x94, 0x81, 0x32, 0x9b, 0x8c, 0xb3, 0xef, - 0x58, 0x2c, 0xc8, 0xfb, 0xfc, 0xb1, 0xc7, 0x4d, 0x58, 0xb4, 0x02, 0x5f, 0x1a, 0x95, 0x5f, 0xbe, - 0x5a, 0x1f, 0x63, 0x46, 0x43, 0x1f, 0x41, 0x41, 0xd6, 0x52, 0x44, 0xd8, 0xa1, 0x5e, 0x1d, 0x8e, - 0x4a, 0xdb, 0x48, 0x39, 0xbe, 0x97, 0x67, 0xa3, 0x13, 0x97, 0x00, 0x4e, 0x92, 0xd0, 0x0d, 0xc8, - 0x5a, 0xc2, 0x5c, 0xf2, 0x53, 0x18, 0xad, 0x83, 0xb3, 0x96, 0xa7, 0xfe, 0x20, 0x03, 0xcb, 0xb3, - 0x03, 0xcf, 0x76, 0xc0, 0x2d, 0x28, 0x05, 0x93, 0xbd, 0x60, 0x1a, 0x84, 0x64, 0x14, 0x3d, 0x2d, - 0xc7, 0x04, 0xd4, 0x86, 0x92, 0xe9, 0x0e, 0xa9, 0xef, 0x84, 0x07, 0x23, 0x99, 0xa5, 0xa6, 0x87, - 0x0a, 0x49, 0x9d, 0xf5, 0x46, 0x24, 0x82, 0x67, 0xd2, 0xd1, 0xbd, 0x2f, 0xbe, 0x3f, 0xe0, 0xf7, - 0xfe, 0x1b, 0x50, 0x71, 0xcd, 0x11, 0x2f, 0x2e, 0x85, 0xce, 0x48, 0xcc, 0x23, 0x87, 0xcb, 0x92, - 0x36, 0x70, 0x46, 0x44, 0x55, 0xa1, 0x14, 0x2b, 0x43, 0xab, 0x50, 0x6e, 0xe8, 0x7d, 0xe3, 0xfe, - 0x83, 0x47, 0xc6, 0x63, 0xed, 0xa9, 0xb2, 0x20, 0x63, 0xd3, 0x3f, 0xcf, 0xc0, 0xb2, 0x74, 0x47, - 0x32, 0xde, 0x7f, 0x13, 0x96, 0x7c, 0x73, 0x3f, 0x8c, 0x32, 0x92, 0x9c, 0xd8, 0xd5, 0xcc, 0xc3, - 0xb3, 0x8c, 0x84, 0xb1, 0xd2, 0x33, 0x92, 0xc4, 0xc7, 0x0e, 0x8b, 0x97, 0x7e, 0xec, 0x90, 0xfb, - 0xa9, 0x7c, 0xec, 0xa0, 0xfe, 0x0a, 0xc0, 0x96, 0xe3, 0x92, 0x81, 0xa8, 0x43, 0xa5, 0xe5, 0x97, - 0x2c, 0x86, 0x93, 0x75, 0xce, 0x28, 0x86, 0x6b, 0xb7, 0x30, 0xa3, 0x31, 0xd6, 0xd0, 0xb1, 0xe5, - 0x61, 0xe4, 0xac, 0xc7, 0x8c, 0x35, 0x74, 0xec, 0xf8, 0x55, 0x2e, 0x77, 0xd5, 0xab, 0xdc, 0x49, - 0x06, 0x56, 0x65, 0xec, 0x1a, 0xbb, 0xdf, 0x2f, 0x43, 0x49, 0x84, 0xb1, 0xb3, 0x84, 0x8e, 0x3f, - 0xf0, 0x0b, 0x5c, 0xbb, 0x85, 0x8b, 0x82, 0xdd, 0xb6, 0xd1, 0x26, 0x94, 0x25, 0x34, 0xf1, 0xd9, - 0x14, 0x08, 0x52, 0x87, 0x0d, 0xff, 0xab, 0x90, 0xdb, 0x77, 0x5c, 0x22, 0x37, 0x7a, 0xaa, 0x03, - 0x98, 0x19, 0x60, 0x7b, 0x01, 0x73, 0x74, 0xb3, 0x18, 0x15, 0xea, 0xf8, 0xf8, 0x64, 0xda, 0x99, - 0x1c, 0x9f, 0xc8, 0x40, 0xe7, 0xc6, 0x27, 0x70, 0x6c, 0x7c, 0x82, 0x2d, 0xc6, 0x27, 0xa1, 0xc9, - 0xf1, 0x09, 0xd2, 0x4f, 0x65, 0x7c, 0x3b, 0x70, 0xa3, 0xe9, 0x9a, 0xd6, 0xa1, 0xeb, 0x04, 0x21, - 0xb1, 0x93, 0x1e, 0xe3, 0x01, 0x14, 0xce, 0x05, 0x9d, 0x97, 0x55, 0x34, 0x25, 0x52, 0xfd, 0xf7, - 0x0c, 0x54, 0xb6, 0x89, 0xe9, 0x86, 0x07, 0xb3, 0xb2, 0x51, 0x48, 0x82, 0x50, 0x5e, 0x56, 0xfc, - 0x37, 0xfa, 0x1a, 0x14, 0xe3, 0x98, 0xe4, 0xca, 0xb7, 0xb9, 0x18, 0x8a, 0x1e, 0xc2, 0x12, 0x3b, - 0x63, 0x74, 0x12, 0x25, 0x3b, 0x97, 0x3d, 0xfb, 0x48, 0x24, 0xbb, 0x64, 0x7c, 0xc2, 0x83, 0x10, - 0xbe, 0x95, 0xf2, 0x38, 0x6a, 0xa2, 0xff, 0x0f, 0x15, 0xfe, 0x6a, 0x11, 0xc5, 0x5c, 0xf9, 0xab, - 0x74, 0x96, 0xc5, 0xc3, 0xa3, 0x88, 0xb7, 0xfe, 0x38, 0x0b, 0x6b, 0x4f, 0xcd, 0xe9, 0x1e, 0x91, - 0x6e, 0x83, 0xd8, 0x98, 0x58, 0xd4, 0xb7, 0x51, 0x2f, 0xe9, 0x6e, 0x2e, 0x79, 0xc7, 0x4c, 0x13, - 0x4e, 0xf7, 0x3a, 0x51, 0x02, 0x96, 0x4d, 0x24, 0x60, 0x6b, 0x90, 0xf7, 0xa8, 0x67, 0x11, 0xe9, - 0x8b, 0x44, 0x43, 0xfd, 0xed, 0x4c, 0xd2, 0xd7, 0x54, 0xe3, 0x37, 0x46, 0x5e, 0x81, 0xea, 0xd0, - 0x30, 0xee, 0x0e, 0x7d, 0x04, 0xd5, 0xbe, 0xae, 0x61, 0x7d, 0xd0, 0xec, 0x7e, 0xdb, 0xe8, 0x37, - 0x76, 0xfa, 0x8d, 0x07, 0xf7, 0x8c, 0x5e, 0x77, 0xe7, 0x3b, 0xf7, 0x1f, 0xde, 0xfb, 0x9a, 0x92, - 0xa9, 0xd6, 0x8e, 0x4f, 0x6a, 0xb7, 0x3a, 0x0d, 0x6d, 0x47, 0x1c, 0x99, 0x3d, 0xfa, 0xb2, 0x6f, - 0xba, 0x81, 0xf9, 0xe0, 0x5e, 0x8f, 0xba, 0x53, 0x86, 0x41, 0x5f, 0x01, 0xb4, 0xa5, 0xe3, 0x8e, - 0x3e, 0x30, 0x22, 0x87, 0xa6, 0x35, 0x35, 0x25, 0x2b, 0xd2, 0x9a, 0x2d, 0xe2, 0x7b, 0x24, 0x6c, - 0xe8, 0xfd, 0xfb, 0x0f, 0x1e, 0x69, 0x4d, 0x8d, 0x1d, 0x82, 0x4a, 0xf2, 0x76, 0x4b, 0x5e, 0xda, - 0x99, 0x0b, 0x2f, 0xed, 0xd9, 0xdd, 0x9f, 0xbd, 0xe0, 0xee, 0xdf, 0x82, 0x35, 0xcb, 0xa7, 0x41, - 0x60, 0xb0, 0x5c, 0x81, 0xd8, 0x73, 0xd9, 0xc8, 0x17, 0xce, 0x4e, 0x37, 0xaf, 0x69, 0x8c, 0xdf, - 0xe7, 0x6c, 0xa9, 0xfe, 0x9a, 0x95, 0x20, 0xf1, 0x9e, 0xd4, 0xdf, 0x5f, 0x64, 0x61, 0x97, 0x73, - 0xe4, 0xb8, 0x64, 0x48, 0x02, 0xf4, 0x0c, 0x56, 0x2d, 0x9f, 0xd8, 0x2c, 0x09, 0x30, 0xdd, 0xe4, - 0xc7, 0xba, 0xff, 0x2f, 0x35, 0x02, 0x8a, 0x05, 0xeb, 0x5a, 0x2c, 0xd5, 0x1f, 0x13, 0x0b, 0xaf, - 0x58, 0xe7, 0xda, 0xe8, 0x63, 0x58, 0x0d, 0x88, 0xeb, 0x78, 0x93, 0x97, 0x86, 0x45, 0xbd, 0x90, - 0xbc, 0x8c, 0xde, 0xd6, 0xae, 0xd2, 0xdb, 0xd7, 0x77, 0x98, 0x94, 0x26, 0x84, 0x9a, 0xe8, 0xec, - 0x74, 0x73, 0xe5, 0x3c, 0x0d, 0xaf, 0x48, 0xcd, 0xb2, 0x5d, 0xed, 0xc0, 0xca, 0xf9, 0xd1, 0xa0, - 0x35, 0xe9, 0x29, 0xb8, 0xc3, 0x89, 0x3c, 0x01, 0xba, 0x05, 0x45, 0x9f, 0x0c, 0x9d, 0x20, 0xf4, - 0x85, 0x99, 0x19, 0x27, 0xa6, 0x30, 0x3f, 0x21, 0xbe, 0xa5, 0xaa, 0xfe, 0x12, 0xcc, 0xf5, 0xc8, - 0x8e, 0x96, 0xed, 0x04, 0xe6, 0x9e, 0x54, 0x59, 0xc4, 0x51, 0x93, 0xed, 0xd8, 0x49, 0x10, 0x87, - 0x75, 0xfc, 0x37, 0xa3, 0xf1, 0xf8, 0x43, 0x7e, 0x59, 0xc6, 0x23, 0x8c, 0xe8, 0x03, 0xd6, 0x5c, - 0xe2, 0x03, 0xd6, 0x35, 0xc8, 0xbb, 0xe4, 0x88, 0xb8, 0xe2, 0xe6, 0xc7, 0xa2, 0x71, 0xe7, 0x1e, - 0x54, 0xa2, 0x2f, 0x25, 0xf9, 0x37, 0x18, 0x45, 0xc8, 0x0d, 0x1a, 0xfd, 0x27, 0xca, 0x02, 0x02, - 0x28, 0x88, 0x9d, 0x2c, 0xde, 0xfd, 0xb4, 0x6e, 0x67, 0xab, 0xfd, 0x58, 0xc9, 0xde, 0xf9, 0x9d, - 0x1c, 0x94, 0xe2, 0x97, 0x27, 0x76, 0xd3, 0x74, 0xf4, 0xe7, 0xd1, 0x51, 0x88, 0xe9, 0x1d, 0xf2, - 0x02, 0xbd, 0x31, 0xab, 0x59, 0x7d, 0x24, 0x9e, 0xda, 0x63, 0x76, 0x54, 0xaf, 0x7a, 0x0b, 0x8a, - 0x8d, 0x7e, 0xbf, 0xfd, 0xb8, 0xa3, 0xb7, 0x94, 0x4f, 0x33, 0xd5, 0x2f, 0x1c, 0x9f, 0xd4, 0xae, - 0xc5, 0xa0, 0x46, 0x20, 0x36, 0x1f, 0x47, 0x69, 0x9a, 0xde, 0x1b, 0xe8, 0x2d, 0xe5, 0x93, 0xec, - 0x3c, 0x8a, 0xd7, 0x60, 0xf8, 0x47, 0x40, 0xa5, 0x1e, 0xd6, 0x7b, 0x0d, 0xcc, 0x3a, 0xfc, 0x34, - 0x2b, 0x4a, 0x69, 0xb3, 0x1e, 0x7d, 0x32, 0x36, 0x7d, 0xd6, 0xe7, 0x46, 0xf4, 0x55, 0xdd, 0x27, - 0x8b, 0xe2, 0x43, 0x91, 0xd9, 0x33, 0x1a, 0x31, 0xed, 0x29, 0xeb, 0x8d, 0xbf, 0x5f, 0x72, 0x35, - 0x8b, 0x73, 0xbd, 0xf5, 0x99, 0xa7, 0x62, 0x5a, 0x54, 0x58, 0xc2, 0xbb, 0x9d, 0x0e, 0x03, 0x7d, - 0x92, 0x9b, 0x9b, 0x1d, 0x9e, 0x78, 0x2c, 0xbf, 0x46, 0xb7, 0xa1, 0x18, 0x3d, 0x6f, 0x2a, 0x9f, - 0xe6, 0xe6, 0x06, 0xa4, 0x45, 0x6f, 0xb3, 0xbc, 0xc3, 0xed, 0xdd, 0x01, 0xff, 0xe8, 0xef, 0x93, - 0xfc, 0x7c, 0x87, 0x07, 0x93, 0xd0, 0xa6, 0x2f, 0x3c, 0x76, 0x66, 0x65, 0xd5, 0xee, 0xd3, 0xbc, - 0xf0, 0x05, 0x31, 0x46, 0x96, 0xec, 0xde, 0x82, 0x22, 0xd6, 0xbf, 0x25, 0xbe, 0x0f, 0xfc, 0xa4, - 0x30, 0xa7, 0x07, 0x93, 0x8f, 0x89, 0xc5, 0x7a, 0xab, 0x41, 0x01, 0xeb, 0x4f, 0xbb, 0xcf, 0x74, - 0xe5, 0x0f, 0x0a, 0x73, 0x7a, 0x30, 0x19, 0x51, 0xfe, 0x95, 0x54, 0xb1, 0x8b, 0x7b, 0xdb, 0x0d, - 0xbe, 0x28, 0xf3, 0x7a, 0xba, 0xfe, 0xf8, 0xc0, 0xf4, 0x88, 0x3d, 0xfb, 0x9e, 0x26, 0x66, 0xdd, - 0xf9, 0x39, 0x28, 0x46, 0x91, 0x2e, 0xda, 0x80, 0xc2, 0xf3, 0x2e, 0x7e, 0xa2, 0x63, 0x65, 0x41, - 0x58, 0x39, 0xe2, 0x3c, 0x17, 0x39, 0x4a, 0x0d, 0x96, 0x9e, 0x36, 0x3a, 0x8d, 0xc7, 0x3a, 0x8e, - 0x4a, 0xee, 0x11, 0x40, 0x86, 0x6b, 0x55, 0x45, 0x76, 0x10, 0xeb, 0x6c, 0xae, 0x7f, 0xff, 0x47, - 0x1b, 0x0b, 0x3f, 0xfc, 0xd1, 0xc6, 0xc2, 0x27, 0x67, 0x1b, 0x99, 0xef, 0x9f, 0x6d, 0x64, 0xfe, - 0xfe, 0x6c, 0x23, 0xf3, 0x6f, 0x67, 0x1b, 0x99, 0xbd, 0x02, 0xbf, 0x54, 0x1e, 0xfe, 0x6f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x80, 0x94, 0x1b, 0x9c, 0x7a, 0x32, 0x00, 0x00, + // 5135 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x7a, 0x4d, 0x6c, 0x24, 0x49, + 0x56, 0xbf, 0xeb, 0xd3, 0x55, 0xaf, 0xca, 0x76, 0x76, 0xb4, 0xb7, 0xc7, 0x5d, 0xdb, 0x63, 0xd7, + 0xe4, 0x4c, 0xef, 0xcc, 0xf6, 0xce, 0xbf, 0xfa, 0x6b, 0x77, 0xd5, 0x33, 0xf3, 0xdf, 0x9d, 0xa9, + 0x8f, 0x74, 0xbb, 0xb6, 0xed, 0xaa, 0x52, 0x54, 0xb9, 0x7b, 0xf7, 0x2f, 0xfd, 0x49, 0xd2, 0x99, + 0xe1, 0x72, 0x8e, 0xb3, 0x32, 0x8a, 0xcc, 0x2c, 0xbb, 0x8b, 0x05, 0x31, 0xe2, 0x00, 0xc8, 0x27, + 0xf6, 0x02, 0xbb, 0x42, 0x46, 0x48, 0x70, 0xe3, 0xc0, 0x01, 0x24, 0x04, 0xa7, 0x41, 0x42, 0x68, + 0xc5, 0x05, 0x16, 0x24, 0xb4, 0x02, 0xc9, 0xb0, 0x3e, 0x70, 0x43, 0x70, 0x41, 0x5c, 0x38, 0xa0, + 0xf8, 0xc8, 0xac, 0x74, 0x75, 0xda, 0x9e, 0x61, 0xf7, 0x62, 0x57, 0xbc, 0xf7, 0x7b, 0x2f, 0x22, + 0x5e, 0x44, 0xbc, 0x78, 0xef, 0x45, 0xc2, 0xbd, 0xa1, 0x1d, 0x1c, 0x4c, 0xf6, 0x6a, 0x26, 0x1d, + 0xdd, 0xb7, 0xa8, 0x79, 0x48, 0xbc, 0xfb, 0xfe, 0xb1, 0xe1, 0x8d, 0x0e, 0xed, 0xe0, 0xbe, 0x31, + 0xb6, 0xef, 0x07, 0xd3, 0x31, 0xf1, 0x6b, 0x63, 0x8f, 0x06, 0x14, 0x21, 0x01, 0xa8, 0x85, 0x80, + 0xda, 0xd1, 0xc3, 0xca, 0xc6, 0x90, 0xd2, 0xa1, 0x43, 0xee, 0x73, 0xc4, 0xde, 0x64, 0xff, 0x7e, + 0x60, 0x8f, 0x88, 0x1f, 0x18, 0xa3, 0xb1, 0x10, 0xaa, 0xac, 0xcf, 0x03, 0xac, 0x89, 0x67, 0x04, + 0x36, 0x75, 0x25, 0x7f, 0x75, 0x48, 0x87, 0x94, 0xff, 0xbc, 0xcf, 0x7e, 0x09, 0xaa, 0xba, 0x01, + 0x8b, 0xcf, 0x89, 0xe7, 0xdb, 0xd4, 0x45, 0xab, 0x90, 0xb3, 0x5d, 0x8b, 0xbc, 0x5c, 0x4b, 0x55, + 0x53, 0xef, 0x64, 0xb1, 0x68, 0xa8, 0x0f, 0x00, 0xda, 0xec, 0x87, 0xe6, 0x06, 0xde, 0x14, 0x29, + 0x90, 0x39, 0x24, 0x53, 0x8e, 0x28, 0x62, 0xf6, 0x93, 0x51, 0x8e, 0x0c, 0x67, 0x2d, 0x2d, 0x28, + 0x47, 0x86, 0xa3, 0xfe, 0x24, 0x05, 0xa5, 0xba, 0xeb, 0xd2, 0x80, 0xf7, 0xee, 0x23, 0x04, 0x59, + 0xd7, 0x18, 0x11, 0x29, 0xc4, 0x7f, 0xa3, 0x26, 0xe4, 0x1d, 0x63, 0x8f, 0x38, 0xfe, 0x5a, 0xba, + 0x9a, 0x79, 0xa7, 0xf4, 0xe8, 0x2b, 0xb5, 0x57, 0xa7, 0x5c, 0x8b, 0x29, 0xa9, 0x6d, 0x73, 0x34, + 0x1f, 0x04, 0x96, 0xa2, 0xe8, 0x9b, 0xb0, 0x68, 0xbb, 0x96, 0x6d, 0x12, 0x7f, 0x2d, 0xcb, 0xb5, + 0xac, 0x27, 0x69, 0x99, 0x8d, 0xbe, 0x91, 0xfd, 0xe1, 0xd9, 0xc6, 0x02, 0x0e, 0x85, 0x2a, 0xef, + 0x41, 0x29, 0xa6, 0x36, 0x61, 0x6e, 0xab, 0x90, 0x3b, 0x32, 0x9c, 0x09, 0x91, 0xb3, 0x13, 0x8d, + 0xf7, 0xd3, 0x4f, 0x52, 0xea, 0x47, 0xb0, 0xda, 0x31, 0x46, 0xc4, 0x7a, 0x4a, 0x5c, 0xe2, 0xd9, + 0x26, 0x26, 0x3e, 0x9d, 0x78, 0x26, 0x61, 0x73, 0x3d, 0xb4, 0x5d, 0x2b, 0x9c, 0x2b, 0xfb, 0x9d, + 0xac, 0x45, 0x6d, 0xc2, 0x6b, 0x2d, 0xdb, 0x37, 0x3d, 0x12, 0x90, 0xcf, 0xad, 0x24, 0x13, 0x2a, + 0x39, 0x4b, 0xc1, 0xca, 0xbc, 0xf4, 0xff, 0x83, 0x9b, 0xcc, 0xc4, 0x96, 0xee, 0x49, 0x8a, 0xee, + 0x8f, 0x89, 0xc9, 0x95, 0x95, 0x1e, 0xbd, 0x93, 0x64, 0xa1, 0xa4, 0x99, 0x6c, 0x2d, 0xe0, 0x1b, + 0x5c, 0x4d, 0x48, 0xe8, 0x8f, 0x89, 0x89, 0x4c, 0xb8, 0x65, 0xc9, 0x41, 0xcf, 0xa9, 0x4f, 0x73, + 0xf5, 0x89, 0xcb, 0x78, 0xc9, 0x34, 0xb7, 0x16, 0xf0, 0x6a, 0xa8, 0x2c, 0xde, 0x49, 0x03, 0xa0, + 0x10, 0xea, 0x56, 0xbf, 0x9f, 0x82, 0x62, 0xc8, 0xf4, 0xd1, 0x97, 0xa1, 0xe8, 0x1a, 0x2e, 0xd5, + 0xcd, 0xf1, 0xc4, 0xe7, 0x13, 0xca, 0x34, 0xca, 0xe7, 0x67, 0x1b, 0x85, 0x8e, 0xe1, 0xd2, 0x66, + 0x6f, 0xd7, 0xc7, 0x05, 0xc6, 0x6e, 0x8e, 0x27, 0x3e, 0x7a, 0x03, 0xca, 0x23, 0x32, 0xa2, 0xde, + 0x54, 0xdf, 0x9b, 0x06, 0xc4, 0x97, 0x66, 0x2b, 0x09, 0x5a, 0x83, 0x91, 0xd0, 0x37, 0x60, 0x71, + 0x28, 0x86, 0xb4, 0x96, 0xe1, 0xdb, 0xe7, 0xcd, 0xa4, 0xd1, 0xcf, 0x8d, 0x1a, 0x87, 0x32, 0xea, + 0x6f, 0xa6, 0x60, 0x35, 0xa2, 0x92, 0x5f, 0x98, 0xd8, 0x1e, 0x19, 0x11, 0x37, 0xf0, 0xd1, 0xd7, + 0x20, 0xef, 0xd8, 0x23, 0x3b, 0xf0, 0xa5, 0xcd, 0x5f, 0x4f, 0x52, 0x1b, 0x4d, 0x0a, 0x4b, 0x30, + 0xaa, 0x43, 0xd9, 0x23, 0x3e, 0xf1, 0x8e, 0xc4, 0x8e, 0x97, 0x16, 0xbd, 0x46, 0xf8, 0x82, 0x88, + 0xba, 0x09, 0x85, 0x9e, 0x63, 0x04, 0xfb, 0xd4, 0x1b, 0x21, 0x15, 0xca, 0x86, 0x67, 0x1e, 0xd8, + 0x01, 0x31, 0x83, 0x89, 0x17, 0x9e, 0xbe, 0x0b, 0x34, 0x74, 0x0b, 0xd2, 0x54, 0x74, 0x54, 0x6c, + 0xe4, 0xcf, 0xcf, 0x36, 0xd2, 0xdd, 0x3e, 0x4e, 0x53, 0x5f, 0xfd, 0x00, 0x6e, 0xf4, 0x9c, 0xc9, + 0xd0, 0x76, 0x5b, 0xc4, 0x37, 0x3d, 0x7b, 0xcc, 0xb4, 0xb3, 0x5d, 0xc9, 0x7c, 0x54, 0xb8, 0x2b, + 0xd9, 0xef, 0xe8, 0x68, 0xa7, 0x67, 0x47, 0x5b, 0xfd, 0xf5, 0x34, 0xdc, 0xd0, 0xdc, 0xa1, 0xed, + 0x92, 0xb8, 0xf4, 0x5d, 0x58, 0x26, 0x9c, 0xa8, 0x1f, 0x09, 0x77, 0x23, 0xf5, 0x2c, 0x09, 0x6a, + 0xe8, 0x83, 0xda, 0x73, 0x7e, 0xe1, 0x61, 0xd2, 0xf4, 0x5f, 0xd1, 0x9e, 0xe8, 0x1d, 0x34, 0x58, + 0x1c, 0xf3, 0x49, 0xf8, 0x72, 0x79, 0xef, 0x26, 0xe9, 0x7a, 0x65, 0x9e, 0xa1, 0x93, 0x90, 0xb2, + 0x3f, 0x8d, 0x93, 0xf8, 0xeb, 0x34, 0xac, 0x74, 0xa8, 0x75, 0xc1, 0x0e, 0x15, 0x28, 0x1c, 0x50, + 0x3f, 0x88, 0x39, 0xc4, 0xa8, 0x8d, 0x9e, 0x40, 0x61, 0x2c, 0x97, 0x4f, 0xae, 0xfe, 0x9d, 0xe4, + 0x21, 0x0b, 0x0c, 0x8e, 0xd0, 0xe8, 0x03, 0x28, 0x86, 0x47, 0x86, 0xcd, 0xf6, 0x33, 0x6c, 0x9c, + 0x19, 0x1e, 0x7d, 0x03, 0xf2, 0x62, 0x11, 0xd6, 0xb2, 0x5c, 0xf2, 0xee, 0x67, 0xb2, 0x39, 0x96, + 0x42, 0xe8, 0x29, 0x14, 0x02, 0xc7, 0xd7, 0x6d, 0x77, 0x9f, 0xae, 0xe5, 0xb8, 0x82, 0x8d, 0x44, + 0x27, 0x43, 0x2d, 0x32, 0xd8, 0xee, 0xb7, 0xdd, 0x7d, 0xda, 0x28, 0x9d, 0x9f, 0x6d, 0x2c, 0xca, + 0x06, 0x5e, 0x0c, 0x1c, 0x9f, 0xfd, 0x40, 0x77, 0x20, 0xbb, 0x6f, 0x8f, 0xfd, 0xb5, 0x7c, 0x35, + 0xf5, 0x4e, 0xa1, 0x51, 0x38, 0x3f, 0xdb, 0xc8, 0x6e, 0xb6, 0x7b, 0x7d, 0xcc, 0xa9, 0xea, 0xf7, + 0x52, 0x50, 0x8a, 0xe9, 0x40, 0xaf, 0x03, 0x04, 0xde, 0xc4, 0x0f, 0x74, 0x8f, 0xd2, 0x80, 0x9b, + 0xb2, 0x8c, 0x8b, 0x9c, 0x82, 0x29, 0x0d, 0x50, 0x0d, 0x6e, 0x9a, 0xc4, 0x0b, 0x74, 0xdb, 0xf7, + 0x27, 0xc4, 0xd3, 0xfd, 0xc9, 0xde, 0xc7, 0xc4, 0x0c, 0xb8, 0x59, 0xcb, 0xf8, 0x06, 0x63, 0xb5, + 0x39, 0xa7, 0x2f, 0x18, 0xe8, 0x31, 0xdc, 0x8a, 0xe3, 0xc7, 0x93, 0x3d, 0xc7, 0x36, 0x75, 0xb6, + 0xd4, 0x19, 0x2e, 0x72, 0x73, 0x26, 0xd2, 0xe3, 0xbc, 0x67, 0x64, 0xaa, 0xfe, 0x38, 0x05, 0x0a, + 0x36, 0xf6, 0x83, 0x1d, 0x32, 0xda, 0x23, 0x5e, 0x3f, 0x30, 0x82, 0x89, 0x8f, 0x6e, 0x41, 0xde, + 0x21, 0x86, 0x45, 0x3c, 0x3e, 0xa8, 0x02, 0x96, 0x2d, 0xb4, 0xcb, 0xce, 0xb7, 0x61, 0x1e, 0x18, + 0x7b, 0xb6, 0x63, 0x07, 0x53, 0x3e, 0x94, 0xe5, 0xe4, 0x0d, 0x3e, 0xaf, 0xb3, 0x86, 0x63, 0x82, + 0xf8, 0x82, 0x1a, 0xb4, 0x06, 0x8b, 0x23, 0xe2, 0xfb, 0xc6, 0x90, 0xf0, 0x91, 0x16, 0x71, 0xd8, + 0x54, 0x3f, 0x80, 0x72, 0x5c, 0x0e, 0x95, 0x60, 0x71, 0xb7, 0xf3, 0xac, 0xd3, 0x7d, 0xd1, 0x51, + 0x16, 0xd0, 0x0a, 0x94, 0x76, 0x3b, 0x58, 0xab, 0x37, 0xb7, 0xea, 0x8d, 0x6d, 0x4d, 0x49, 0xa1, + 0x25, 0x28, 0xce, 0x9a, 0x69, 0xf5, 0x8f, 0x53, 0x00, 0xcc, 0xdc, 0x72, 0x52, 0xef, 0x43, 0xce, + 0x0f, 0x8c, 0x40, 0xec, 0xd9, 0xe5, 0x47, 0x6f, 0x5d, 0xb6, 0xc2, 0x72, 0xbc, 0xec, 0x1f, 0xc1, + 0x42, 0x24, 0x3e, 0xc2, 0xf4, 0x85, 0x11, 0x32, 0xf7, 0x61, 0x58, 0x96, 0x27, 0x07, 0xce, 0x7f, + 0xab, 0x1f, 0x40, 0x8e, 0x4b, 0x5f, 0x1c, 0x6e, 0x01, 0xb2, 0x2d, 0xf6, 0x2b, 0x85, 0x8a, 0x90, + 0xc3, 0x5a, 0xbd, 0xf5, 0x1d, 0x25, 0x8d, 0x14, 0x28, 0xb7, 0xda, 0xfd, 0x66, 0xb7, 0xd3, 0xd1, + 0x9a, 0x03, 0xad, 0xa5, 0x64, 0xd4, 0xbb, 0x90, 0x6b, 0x8f, 0x98, 0xe6, 0x3b, 0xec, 0x40, 0xec, + 0x13, 0x8f, 0xb8, 0x66, 0x78, 0xce, 0x66, 0x04, 0xf5, 0x7b, 0x65, 0xc8, 0xed, 0xd0, 0x89, 0x1b, + 0xa0, 0x47, 0x31, 0xa7, 0xb6, 0x9c, 0x1c, 0x3f, 0x70, 0x60, 0x6d, 0x30, 0x1d, 0x13, 0xe9, 0xf4, + 0x6e, 0x41, 0x5e, 0x1c, 0x1d, 0x39, 0x1d, 0xd9, 0x62, 0xf4, 0xc0, 0xf0, 0x86, 0x24, 0x90, 0xf3, + 0x91, 0x2d, 0xf4, 0x0e, 0xbb, 0xcf, 0x0c, 0x8b, 0xba, 0xce, 0x94, 0x9f, 0xb0, 0x82, 0xb8, 0xb4, + 0x30, 0x31, 0xac, 0xae, 0xeb, 0x4c, 0x71, 0xc4, 0x45, 0x5b, 0x50, 0xde, 0xb3, 0x5d, 0x4b, 0xa7, + 0x63, 0x71, 0x05, 0xe4, 0x2e, 0x3f, 0x8f, 0x62, 0x54, 0x0d, 0xdb, 0xb5, 0xba, 0x02, 0x8c, 0x4b, + 0x7b, 0xb3, 0x06, 0xea, 0xc0, 0xf2, 0x11, 0x75, 0x26, 0x23, 0x12, 0xe9, 0xca, 0x73, 0x5d, 0x6f, + 0x5f, 0xae, 0xeb, 0x39, 0xc7, 0x87, 0xda, 0x96, 0x8e, 0xe2, 0x4d, 0xf4, 0x0c, 0x96, 0x82, 0xd1, + 0x78, 0xdf, 0x8f, 0xd4, 0x2d, 0x72, 0x75, 0x5f, 0xba, 0xc2, 0x60, 0x0c, 0x1e, 0x6a, 0x2b, 0x07, + 0xb1, 0x16, 0x7a, 0x0a, 0x25, 0x93, 0xba, 0xbe, 0xed, 0x07, 0xc4, 0x35, 0xa7, 0x6b, 0x05, 0x6e, + 0xfb, 0x2b, 0x66, 0xd9, 0x9c, 0x81, 0x71, 0x5c, 0xb2, 0xf2, 0xab, 0x19, 0x28, 0xc5, 0x4c, 0x80, + 0xfa, 0x50, 0x1a, 0x7b, 0x74, 0x6c, 0x0c, 0xf9, 0x7d, 0x28, 0x17, 0xf5, 0xe1, 0x67, 0x32, 0x5f, + 0xad, 0x37, 0x13, 0xc4, 0x71, 0x2d, 0xea, 0x69, 0x1a, 0x4a, 0x31, 0x26, 0xba, 0x07, 0x05, 0xdc, + 0xc3, 0xed, 0xe7, 0xf5, 0x81, 0xa6, 0x2c, 0x54, 0xee, 0x9c, 0x9c, 0x56, 0xd7, 0xb8, 0xb6, 0xb8, + 0x82, 0x9e, 0x67, 0x1f, 0xb1, 0x3d, 0xfc, 0x0e, 0x2c, 0x86, 0xd0, 0x54, 0xe5, 0x8b, 0x27, 0xa7, + 0xd5, 0xd7, 0xe6, 0xa1, 0x31, 0x24, 0xee, 0x6f, 0xd5, 0xb1, 0xd6, 0x52, 0xd2, 0xc9, 0x48, 0xdc, + 0x3f, 0x30, 0x3c, 0x62, 0xa1, 0x2f, 0x41, 0x5e, 0x02, 0x33, 0x95, 0xca, 0xc9, 0x69, 0xf5, 0xd6, + 0x3c, 0x70, 0x86, 0xc3, 0xfd, 0xed, 0xfa, 0x73, 0x4d, 0xc9, 0x26, 0xe3, 0x70, 0xdf, 0x31, 0x8e, + 0x08, 0x7a, 0x0b, 0x72, 0x02, 0x96, 0xab, 0xdc, 0x3e, 0x39, 0xad, 0x7e, 0xe1, 0x15, 0x75, 0x0c, + 0x55, 0x59, 0xfb, 0x8d, 0xdf, 0x5f, 0x5f, 0xf8, 0xf3, 0x3f, 0x58, 0x57, 0xe6, 0xd9, 0x95, 0xff, + 0x4e, 0xc1, 0xd2, 0x85, 0xbd, 0x83, 0x54, 0xc8, 0xbb, 0xd4, 0xa4, 0x63, 0x71, 0x4d, 0x16, 0x1a, + 0x70, 0x7e, 0xb6, 0x91, 0xef, 0xd0, 0x26, 0x1d, 0x4f, 0xb1, 0xe4, 0xa0, 0x67, 0x73, 0x17, 0xfd, + 0xe3, 0xcf, 0xb8, 0x31, 0x13, 0xaf, 0xfa, 0x0f, 0x61, 0xc9, 0xf2, 0xec, 0x23, 0xe2, 0xe9, 0x26, + 0x75, 0xf7, 0xed, 0xa1, 0xbc, 0x02, 0x2b, 0x89, 0xd1, 0x28, 0x07, 0xe2, 0xb2, 0x10, 0x68, 0x72, + 0xfc, 0x4f, 0x71, 0xc9, 0x57, 0x9e, 0x43, 0x39, 0xbe, 0xd5, 0xd9, 0xbd, 0xe4, 0xdb, 0xbf, 0x48, + 0x64, 0xd8, 0xc9, 0x83, 0x54, 0x5c, 0x64, 0x14, 0x11, 0x74, 0xbe, 0x0d, 0xd9, 0x11, 0xb5, 0x84, + 0x9e, 0xa5, 0xc6, 0x4d, 0x16, 0x6b, 0xfc, 0xe3, 0xd9, 0x46, 0x89, 0xfa, 0xb5, 0x4d, 0xdb, 0x21, + 0x3b, 0xd4, 0x22, 0x98, 0x03, 0xd4, 0x1f, 0xa4, 0x20, 0xcb, 0x9c, 0x0e, 0xfa, 0x22, 0x64, 0x1b, + 0xed, 0x4e, 0x4b, 0x59, 0xa8, 0xdc, 0x38, 0x39, 0xad, 0x2e, 0x71, 0x9b, 0x30, 0x06, 0xdb, 0xbc, + 0x68, 0x03, 0xf2, 0xcf, 0xbb, 0xdb, 0xbb, 0x3b, 0x6c, 0x7f, 0xdd, 0x3c, 0x39, 0xad, 0xae, 0x44, + 0x6c, 0x61, 0x35, 0xf4, 0x3a, 0xe4, 0x06, 0x3b, 0xbd, 0xcd, 0xbe, 0x92, 0xae, 0xa0, 0x93, 0xd3, + 0xea, 0x72, 0xc4, 0xe7, 0x83, 0x46, 0x6f, 0x40, 0xae, 0xd3, 0x6b, 0xf7, 0x34, 0x25, 0x53, 0xb9, + 0x75, 0x72, 0x5a, 0x45, 0x11, 0x9b, 0xe7, 0x04, 0x3d, 0x7b, 0x4c, 0x2a, 0x37, 0xe4, 0xca, 0x17, + 0x23, 0x9e, 0xfa, 0xa3, 0x14, 0x94, 0x62, 0x87, 0x92, 0x6d, 0xde, 0x96, 0xb6, 0x59, 0xdf, 0xdd, + 0x1e, 0x28, 0x0b, 0xb1, 0xcd, 0x1b, 0x83, 0xb4, 0xc8, 0xbe, 0x31, 0x71, 0x98, 0x2f, 0x84, 0x66, + 0xb7, 0xd3, 0x6f, 0xf7, 0x07, 0x5a, 0x67, 0xa0, 0xa4, 0x2a, 0x6b, 0x27, 0xa7, 0xd5, 0xd5, 0x79, + 0xf0, 0xe6, 0xc4, 0x71, 0xd8, 0xf6, 0x6d, 0xd6, 0x9b, 0x5b, 0xfc, 0x3c, 0xcc, 0xb6, 0x6f, 0x0c, + 0xd5, 0x34, 0xcc, 0x03, 0x62, 0xa1, 0x77, 0xa1, 0xd8, 0xd2, 0xb6, 0xb5, 0xa7, 0x75, 0x7e, 0x03, + 0x54, 0x5e, 0x3f, 0x39, 0xad, 0xde, 0x7e, 0xb5, 0x77, 0x87, 0x0c, 0x8d, 0x80, 0x58, 0x73, 0xdb, + 0x38, 0x06, 0x51, 0xff, 0x33, 0x0d, 0x4b, 0x98, 0x25, 0xd4, 0x5e, 0xd0, 0xa3, 0x8e, 0x6d, 0x4e, + 0x51, 0x0f, 0x8a, 0x26, 0x75, 0x2d, 0x3b, 0xe6, 0x4b, 0x1e, 0x5d, 0x12, 0x54, 0xcd, 0xa4, 0xc2, + 0x56, 0x33, 0x94, 0xc4, 0x33, 0x25, 0xe8, 0x3e, 0xe4, 0x2c, 0xe2, 0x18, 0x53, 0x19, 0xdd, 0xdd, + 0xae, 0x89, 0x94, 0xbd, 0x16, 0xa6, 0xec, 0xb5, 0x96, 0x4c, 0xd9, 0xb1, 0xc0, 0xf1, 0x2c, 0xc6, + 0x78, 0xa9, 0x1b, 0x41, 0x40, 0x46, 0xe3, 0x40, 0x84, 0x76, 0x59, 0x5c, 0x1a, 0x19, 0x2f, 0xeb, + 0x92, 0x84, 0x1e, 0x42, 0xfe, 0xd8, 0x76, 0x2d, 0x7a, 0x2c, 0xa3, 0xb7, 0x2b, 0x94, 0x4a, 0xa0, + 0x7a, 0xc2, 0xc2, 0x96, 0xb9, 0x61, 0xb2, 0x6d, 0xd6, 0xe9, 0x76, 0xb4, 0x70, 0x9b, 0x49, 0x7e, + 0xd7, 0xed, 0x50, 0x97, 0xf9, 0x08, 0xe8, 0x76, 0xf4, 0xcd, 0x7a, 0x7b, 0x7b, 0x17, 0xb3, 0xad, + 0xb6, 0x7a, 0x72, 0x5a, 0x55, 0x22, 0xc8, 0xa6, 0x61, 0x3b, 0x2c, 0x9d, 0xb8, 0x0d, 0x99, 0x7a, + 0xe7, 0x3b, 0x4a, 0xba, 0xa2, 0x9c, 0x9c, 0x56, 0xcb, 0x11, 0xbb, 0xee, 0x4e, 0x67, 0x76, 0x9f, + 0xef, 0x57, 0xfd, 0x9b, 0x0c, 0x94, 0x77, 0xc7, 0x96, 0x11, 0x10, 0x71, 0x16, 0x51, 0x15, 0x4a, + 0x63, 0xc3, 0x33, 0x1c, 0x87, 0x38, 0xb6, 0x3f, 0x92, 0xc5, 0x88, 0x38, 0x09, 0xbd, 0xf7, 0x59, + 0xcd, 0xd8, 0x28, 0xb0, 0xf3, 0xf5, 0xfd, 0x7f, 0xde, 0x48, 0x85, 0x06, 0xdd, 0x85, 0xe5, 0x7d, + 0x31, 0x5a, 0xdd, 0x30, 0xf9, 0xc2, 0x66, 0xf8, 0xc2, 0xd6, 0x92, 0x16, 0x36, 0x3e, 0xac, 0x9a, + 0x9c, 0x64, 0x9d, 0x4b, 0xe1, 0xa5, 0xfd, 0x78, 0x13, 0x3d, 0x86, 0xc5, 0x11, 0x75, 0xed, 0x80, + 0x7a, 0xd7, 0xaf, 0x42, 0x88, 0x44, 0xf7, 0xe0, 0x06, 0x5b, 0xdc, 0x70, 0x3c, 0x9c, 0xcd, 0xaf, + 0xfc, 0x34, 0x5e, 0x19, 0x19, 0x2f, 0x65, 0x87, 0x98, 0x91, 0x51, 0x03, 0x72, 0xd4, 0x63, 0x31, + 0x65, 0x9e, 0x0f, 0xf7, 0xdd, 0x6b, 0x87, 0x2b, 0x1a, 0x5d, 0x26, 0x83, 0x85, 0xa8, 0xfa, 0x75, + 0x58, 0xba, 0x30, 0x09, 0x16, 0x4a, 0xf5, 0xea, 0xbb, 0x7d, 0x4d, 0x59, 0x40, 0x65, 0x28, 0x34, + 0xbb, 0x9d, 0x41, 0xbb, 0xb3, 0xcb, 0x62, 0xc1, 0x32, 0x14, 0x70, 0x77, 0x7b, 0xbb, 0x51, 0x6f, + 0x3e, 0x53, 0xd2, 0x6a, 0x0d, 0x4a, 0x31, 0x6d, 0x68, 0x19, 0xa0, 0x3f, 0xe8, 0xf6, 0xf4, 0xcd, + 0x36, 0xee, 0x0f, 0x44, 0x24, 0xd9, 0x1f, 0xd4, 0xf1, 0x40, 0x12, 0x52, 0xea, 0xbf, 0xa7, 0xc3, + 0x15, 0x95, 0xc1, 0x63, 0xe3, 0x62, 0xf0, 0x78, 0xc5, 0xe0, 0x65, 0xf8, 0x38, 0x6b, 0x44, 0x41, + 0xe4, 0x7b, 0x00, 0x7c, 0xe3, 0x10, 0x4b, 0x37, 0x02, 0xb9, 0xf0, 0x95, 0x57, 0x8c, 0x3c, 0x08, + 0x6b, 0x62, 0xb8, 0x28, 0xd1, 0xf5, 0x00, 0x7d, 0x03, 0xca, 0x26, 0x1d, 0x8d, 0x1d, 0x22, 0x85, + 0x33, 0xd7, 0x0a, 0x97, 0x22, 0x7c, 0x3d, 0x88, 0x87, 0xaf, 0xd9, 0x8b, 0x01, 0xf6, 0xaf, 0xa5, + 0x42, 0xcb, 0x24, 0x44, 0xac, 0x65, 0x28, 0xec, 0xf6, 0x5a, 0xf5, 0x41, 0xbb, 0xf3, 0x54, 0x49, + 0x21, 0x80, 0x3c, 0x37, 0x75, 0x4b, 0x49, 0xb3, 0x48, 0xbb, 0xd9, 0xdd, 0xe9, 0x6d, 0x6b, 0xdc, + 0x63, 0xa1, 0x55, 0x50, 0x42, 0x63, 0xeb, 0xdc, 0x90, 0x5a, 0x4b, 0xc9, 0xa2, 0x9b, 0xb0, 0x12, + 0x51, 0xa5, 0x64, 0x0e, 0xdd, 0x02, 0x14, 0x11, 0x67, 0x2a, 0xf2, 0xea, 0x2f, 0xc3, 0x4a, 0x93, + 0xba, 0x81, 0x61, 0xbb, 0x51, 0x16, 0xf2, 0x88, 0x4d, 0x5a, 0x92, 0x74, 0x5b, 0xd6, 0x92, 0x1a, + 0x2b, 0xe7, 0x67, 0x1b, 0xa5, 0x08, 0xda, 0x6e, 0xf1, 0x70, 0x4a, 0x36, 0x2c, 0x76, 0x7e, 0xc7, + 0xb6, 0xc5, 0x8d, 0x9b, 0x6b, 0x2c, 0x9e, 0x9f, 0x6d, 0x64, 0x7a, 0xed, 0x16, 0x66, 0x34, 0xf4, + 0x45, 0x28, 0x92, 0x97, 0x76, 0xa0, 0x9b, 0xec, 0xee, 0x62, 0x06, 0xcc, 0xe1, 0x02, 0x23, 0x34, + 0xd9, 0x55, 0xd5, 0x00, 0xe8, 0x51, 0x2f, 0x90, 0x3d, 0x7f, 0x15, 0x72, 0x63, 0xea, 0xf1, 0xea, + 0xc7, 0xa5, 0x35, 0x39, 0x06, 0x17, 0x1b, 0x15, 0x0b, 0xb0, 0xfa, 0x83, 0x0c, 0xc0, 0xc0, 0xf0, + 0x0f, 0xa5, 0x92, 0x27, 0x50, 0x8c, 0xea, 0x9b, 0xb2, 0x8c, 0x72, 0xe5, 0x6a, 0x47, 0x60, 0xf4, + 0x38, 0xdc, 0x6c, 0x22, 0xbf, 0x4a, 0x4c, 0x83, 0xc3, 0x8e, 0x92, 0x52, 0x94, 0x8b, 0x49, 0x14, + 0x0b, 0x05, 0x88, 0xe7, 0xc9, 0x95, 0x67, 0x3f, 0x51, 0x93, 0x5f, 0x0b, 0xc2, 0x68, 0x32, 0x42, + 0x4f, 0x2c, 0x1c, 0xcd, 0xad, 0xc8, 0xd6, 0x02, 0x9e, 0xc9, 0xa1, 0x0f, 0xa1, 0xc4, 0xe6, 0xad, + 0xfb, 0x9c, 0x27, 0x83, 0xf3, 0x4b, 0x4d, 0x25, 0x34, 0x60, 0x18, 0xcf, 0xac, 0xfc, 0x3a, 0x80, + 0x31, 0x1e, 0x3b, 0x36, 0xb1, 0xf4, 0xbd, 0x29, 0x8f, 0xc6, 0x8b, 0xb8, 0x28, 0x29, 0x8d, 0x29, + 0x3b, 0x2e, 0x21, 0xdb, 0x08, 0x78, 0x84, 0x7d, 0x8d, 0x01, 0x25, 0xba, 0x1e, 0x34, 0x14, 0x58, + 0xf6, 0x26, 0x2e, 0x33, 0xa8, 0x1c, 0x9d, 0xfa, 0x47, 0x69, 0x78, 0xad, 0x43, 0x82, 0x63, 0xea, + 0x1d, 0xd6, 0x83, 0xc0, 0x30, 0x0f, 0x46, 0xc4, 0x95, 0xcb, 0x17, 0x4b, 0x7a, 0x52, 0x17, 0x92, + 0x9e, 0x35, 0x58, 0x34, 0x1c, 0xdb, 0xf0, 0x89, 0x08, 0xf0, 0x8a, 0x38, 0x6c, 0xb2, 0xd4, 0x8c, + 0x25, 0x7a, 0xc4, 0xf7, 0x89, 0xa8, 0xcc, 0xb0, 0x81, 0x87, 0x04, 0xf4, 0x5d, 0xb8, 0x25, 0x43, + 0x39, 0x23, 0xea, 0x8a, 0x25, 0x1d, 0x61, 0x89, 0x57, 0x4b, 0xcc, 0x3c, 0x93, 0x07, 0x27, 0x63, + 0xbd, 0x19, 0xb9, 0x3b, 0x0e, 0x64, 0xe4, 0xb8, 0x6a, 0x25, 0xb0, 0x2a, 0x4f, 0xe1, 0xf6, 0xa5, + 0x22, 0x9f, 0xab, 0xf2, 0xf3, 0xf7, 0x69, 0x80, 0x76, 0xaf, 0xbe, 0x23, 0x8d, 0xd4, 0x82, 0xfc, + 0xbe, 0x31, 0xb2, 0x9d, 0xe9, 0x55, 0x1e, 0x70, 0x86, 0xaf, 0xd5, 0x85, 0x39, 0x36, 0xb9, 0x0c, + 0x96, 0xb2, 0x3c, 0xef, 0x9c, 0xec, 0xb9, 0x24, 0x88, 0xf2, 0x4e, 0xde, 0x62, 0xc3, 0xf0, 0x0c, + 0x37, 0xda, 0xba, 0xa2, 0xc1, 0x16, 0x80, 0x85, 0x3c, 0xc7, 0xc6, 0x34, 0x74, 0x5b, 0xb2, 0x89, + 0xb6, 0x78, 0x7d, 0x95, 0x78, 0x47, 0xc4, 0x5a, 0xcb, 0x71, 0xa3, 0x5e, 0x37, 0x1e, 0x2c, 0xe1, + 0xc2, 0x76, 0x91, 0x74, 0xe5, 0x03, 0x1e, 0x32, 0xcd, 0x58, 0x9f, 0xcb, 0x46, 0x0f, 0x60, 0xe9, + 0xc2, 0x3c, 0x5f, 0x49, 0xf8, 0xdb, 0xbd, 0xe7, 0x5f, 0x55, 0xb2, 0xf2, 0xd7, 0xd7, 0x95, 0xbc, + 0xfa, 0x57, 0x19, 0xe1, 0x68, 0xa4, 0x55, 0x93, 0xdf, 0x15, 0x0a, 0x7c, 0x77, 0x9b, 0xd4, 0x91, + 0x0e, 0xe0, 0xed, 0xab, 0xfd, 0x0f, 0xcb, 0xfb, 0x38, 0x1c, 0x47, 0x82, 0x68, 0x03, 0x4a, 0x62, + 0x17, 0xeb, 0xec, 0xc0, 0x71, 0xb3, 0x2e, 0x61, 0x10, 0x24, 0x26, 0x89, 0xee, 0xc2, 0x32, 0x2f, + 0x10, 0xf9, 0x07, 0xc4, 0x12, 0x98, 0x2c, 0xc7, 0x2c, 0x45, 0x54, 0x0e, 0xdb, 0x81, 0xb2, 0x24, + 0xe8, 0x3c, 0xe6, 0xcf, 0xf1, 0x01, 0xdd, 0xbb, 0x6e, 0x40, 0x42, 0x84, 0xa7, 0x02, 0xa5, 0xf1, + 0xac, 0xa1, 0xfe, 0x3c, 0x14, 0xc2, 0xc1, 0xa2, 0x35, 0xc8, 0x0c, 0x9a, 0x3d, 0x65, 0xa1, 0xb2, + 0x72, 0x72, 0x5a, 0x2d, 0x85, 0xe4, 0x41, 0xb3, 0xc7, 0x38, 0xbb, 0xad, 0x9e, 0x92, 0xba, 0xc8, + 0xd9, 0x6d, 0xf5, 0x50, 0x05, 0xb2, 0xfd, 0xe6, 0xa0, 0x17, 0xc6, 0x67, 0x21, 0x8b, 0xd1, 0x2a, + 0x59, 0x16, 0x9f, 0xa9, 0xfb, 0x50, 0x8a, 0xf5, 0x8e, 0xde, 0x84, 0xc5, 0x76, 0xe7, 0x29, 0xd6, + 0xfa, 0x7d, 0x65, 0x41, 0xa4, 0x07, 0x31, 0x6e, 0xdb, 0x1d, 0xb2, 0xb5, 0x43, 0xaf, 0x43, 0x76, + 0xab, 0xcb, 0xee, 0x7d, 0x91, 0x7f, 0xc4, 0x10, 0x5b, 0xd4, 0x0f, 0x2a, 0x37, 0x65, 0xe0, 0x17, + 0x57, 0xac, 0xfe, 0x4e, 0x0a, 0xf2, 0xe2, 0xa0, 0x25, 0x2e, 0x62, 0x1d, 0x16, 0xc3, 0x32, 0x83, + 0x48, 0x0e, 0xdf, 0xbe, 0x3c, 0x91, 0xab, 0xc9, 0xbc, 0x4b, 0x6c, 0xcd, 0x50, 0xae, 0xf2, 0x3e, + 0x94, 0xe3, 0x8c, 0xcf, 0xb5, 0x31, 0xbf, 0x0b, 0x25, 0xb6, 0xf7, 0xc3, 0x84, 0xee, 0x11, 0xe4, + 0x85, 0xb3, 0x88, 0xee, 0xa1, 0xcb, 0xb3, 0x4a, 0x89, 0x44, 0x4f, 0x60, 0x51, 0x64, 0xa2, 0x61, + 0xed, 0x79, 0xfd, 0xea, 0x13, 0x86, 0x43, 0xb8, 0xfa, 0x21, 0x64, 0x7b, 0x84, 0x78, 0xcc, 0xf6, + 0x2e, 0xb5, 0xc8, 0xec, 0xea, 0x96, 0x49, 0xb4, 0x45, 0xda, 0x2d, 0x96, 0x44, 0x5b, 0xa4, 0x6d, + 0x45, 0xf5, 0xb3, 0x74, 0xac, 0x7e, 0x36, 0x80, 0xf2, 0x0b, 0x62, 0x0f, 0x0f, 0x02, 0x62, 0x71, + 0x45, 0xef, 0x42, 0x76, 0x4c, 0xa2, 0xc1, 0xaf, 0x25, 0x6e, 0x3e, 0x42, 0x3c, 0xcc, 0x51, 0xcc, + 0xc7, 0x1c, 0x73, 0x69, 0xf9, 0x60, 0x22, 0x5b, 0xea, 0xdf, 0xa5, 0x61, 0xb9, 0xed, 0xfb, 0x13, + 0xc3, 0x35, 0xc3, 0xa8, 0xee, 0x9b, 0x17, 0xa3, 0xba, 0xc4, 0x97, 0xa5, 0x8b, 0x22, 0x17, 0xcb, + 0x82, 0xf2, 0x66, 0x4d, 0x47, 0x37, 0xab, 0xfa, 0x6f, 0xa9, 0xb0, 0xf6, 0x77, 0x37, 0xe6, 0x0a, + 0x44, 0x8e, 0x18, 0xd7, 0x44, 0x76, 0xdd, 0x43, 0x97, 0x1e, 0xbb, 0x2c, 0x7b, 0xc5, 0x5a, 0x47, + 0x7b, 0xa1, 0xa4, 0xc4, 0xf6, 0xbc, 0x00, 0xc2, 0xc4, 0x25, 0xc7, 0x4c, 0x53, 0x4f, 0xeb, 0xb4, + 0x58, 0x14, 0x96, 0x4e, 0xd0, 0xd4, 0x23, 0xae, 0x65, 0xbb, 0x43, 0xf4, 0x26, 0xe4, 0xdb, 0xfd, + 0xfe, 0x2e, 0x4f, 0x21, 0x5f, 0x3b, 0x39, 0xad, 0xde, 0xbc, 0x80, 0xe2, 0x75, 0x5f, 0x8b, 0x81, + 0x58, 0x0a, 0xc4, 0xe2, 0xb3, 0x04, 0x10, 0x8b, 0xad, 0x05, 0x08, 0x77, 0x07, 0xf5, 0x81, 0xa6, + 0xe4, 0x12, 0x40, 0x98, 0xb2, 0xbf, 0xf2, 0xb8, 0xfd, 0x53, 0x1a, 0x94, 0xba, 0x69, 0x92, 0x71, + 0xc0, 0xf8, 0x32, 0xeb, 0x1c, 0x40, 0x61, 0xcc, 0x7e, 0xd9, 0x24, 0x8c, 0xa0, 0x9e, 0x24, 0xbe, + 0x8d, 0xce, 0xc9, 0xd5, 0x30, 0x75, 0x48, 0xdd, 0x1a, 0xd9, 0xbe, 0x6f, 0x53, 0x57, 0xd0, 0x70, + 0xa4, 0xa9, 0xf2, 0x1f, 0x29, 0xb8, 0x99, 0x80, 0x40, 0x0f, 0x20, 0xeb, 0x51, 0x27, 0x5c, 0xc3, + 0x3b, 0x97, 0x95, 0x75, 0x99, 0x28, 0xe6, 0x48, 0xb4, 0x0e, 0x60, 0x4c, 0x02, 0x6a, 0xf0, 0xfe, + 0xf9, 0xea, 0x15, 0x70, 0x8c, 0x82, 0x5e, 0x40, 0xde, 0x27, 0xa6, 0x47, 0xc2, 0x38, 0xfb, 0xc3, + 0xff, 0xed, 0xe8, 0x6b, 0x7d, 0xae, 0x06, 0x4b, 0x75, 0x95, 0x1a, 0xe4, 0x05, 0x85, 0x6d, 0x7b, + 0xcb, 0x08, 0x0c, 0x59, 0xf4, 0xe7, 0xbf, 0xd9, 0x6e, 0x32, 0x9c, 0x61, 0xb8, 0x9b, 0x0c, 0x67, + 0xa8, 0xfe, 0x65, 0x1a, 0x40, 0x7b, 0x19, 0x10, 0xcf, 0x35, 0x9c, 0x66, 0x1d, 0x69, 0xb1, 0x9b, + 0x41, 0xcc, 0xf6, 0xcb, 0x89, 0xef, 0x1c, 0x91, 0x44, 0xad, 0x59, 0x4f, 0xb8, 0x1b, 0x6e, 0x43, + 0x66, 0xe2, 0xc9, 0xe7, 0x6e, 0x11, 0x23, 0xef, 0xe2, 0x6d, 0xcc, 0x68, 0x48, 0x9b, 0xb9, 0xad, + 0xcc, 0xe5, 0x8f, 0xda, 0xb1, 0x0e, 0x12, 0x5d, 0x17, 0x3b, 0xf9, 0xa6, 0xa1, 0x9b, 0x44, 0xde, + 0x2a, 0x65, 0x71, 0xf2, 0x9b, 0xf5, 0x26, 0xf1, 0x02, 0x9c, 0x37, 0x0d, 0xf6, 0xff, 0xa7, 0xf2, + 0x6f, 0xef, 0x02, 0xcc, 0xa6, 0x86, 0xd6, 0x21, 0xd7, 0xdc, 0xec, 0xf7, 0xb7, 0x95, 0x05, 0xe1, + 0xc0, 0x67, 0x2c, 0x4e, 0x56, 0xff, 0x2c, 0x0d, 0x85, 0x66, 0x5d, 0x5e, 0xb9, 0x4d, 0x50, 0xb8, + 0x57, 0xe2, 0x4f, 0x25, 0xe4, 0xe5, 0xd8, 0xf6, 0xa6, 0xd2, 0xb1, 0x5c, 0x91, 0xf0, 0x2e, 0x33, + 0x11, 0x36, 0x6a, 0x8d, 0x0b, 0x20, 0x0c, 0x65, 0x22, 0x8d, 0xa0, 0x9b, 0x46, 0xe8, 0xe3, 0xd7, + 0xaf, 0x36, 0x96, 0x48, 0x5d, 0x66, 0x6d, 0x1f, 0x97, 0x42, 0x25, 0x4d, 0xc3, 0x47, 0xef, 0xc1, + 0x8a, 0x6f, 0x0f, 0x5d, 0xdb, 0x1d, 0xea, 0xa1, 0xf1, 0xf8, 0xbb, 0x4d, 0xe3, 0xc6, 0xf9, 0xd9, + 0xc6, 0x52, 0x5f, 0xb0, 0xa4, 0x0d, 0x97, 0x24, 0xb2, 0xc9, 0x4d, 0x89, 0xbe, 0x0e, 0xcb, 0x31, + 0x51, 0x66, 0x45, 0x61, 0x76, 0xe5, 0xfc, 0x6c, 0xa3, 0x1c, 0x49, 0x3e, 0x23, 0x53, 0x5c, 0x8e, + 0x04, 0x9f, 0x11, 0x5e, 0x9b, 0xd9, 0xa7, 0x9e, 0x49, 0x74, 0x8f, 0x9f, 0x69, 0x7e, 0xbb, 0x67, + 0x71, 0x89, 0xd3, 0xc4, 0x31, 0x57, 0x9f, 0xc3, 0xcd, 0xae, 0x67, 0x1e, 0x10, 0x3f, 0x10, 0xa6, + 0x90, 0x56, 0xfc, 0x10, 0xee, 0x04, 0x86, 0x7f, 0xa8, 0x1f, 0xd8, 0x7e, 0x40, 0xbd, 0xa9, 0xee, + 0x91, 0x80, 0xb8, 0x8c, 0xaf, 0xf3, 0xa7, 0x60, 0x59, 0x34, 0xbc, 0xcd, 0x30, 0x5b, 0x02, 0x82, + 0x43, 0xc4, 0x36, 0x03, 0xa8, 0x6d, 0x28, 0xb3, 0x14, 0x46, 0x16, 0xd5, 0xd8, 0xec, 0xc1, 0xa1, + 0x43, 0xfd, 0x33, 0x5f, 0x53, 0x45, 0x87, 0x0e, 0xc5, 0x4f, 0xf5, 0xdb, 0xa0, 0xb4, 0x6c, 0x7f, + 0x6c, 0x04, 0xe6, 0x41, 0x58, 0x0d, 0x45, 0x2d, 0x50, 0x0e, 0x88, 0xe1, 0x05, 0x7b, 0xc4, 0x08, + 0xf4, 0x31, 0xf1, 0x6c, 0x6a, 0x5d, 0xbf, 0xca, 0x2b, 0x91, 0x48, 0x8f, 0x4b, 0xa8, 0xff, 0x95, + 0x02, 0xc0, 0xc6, 0x7e, 0x18, 0xad, 0x7d, 0x05, 0x6e, 0xf8, 0xae, 0x31, 0xf6, 0x0f, 0x68, 0xa0, + 0xdb, 0x6e, 0x40, 0xbc, 0x23, 0xc3, 0x91, 0xc5, 0x1d, 0x25, 0x64, 0xb4, 0x25, 0x1d, 0xbd, 0x0b, + 0xe8, 0x90, 0x90, 0xb1, 0x4e, 0x1d, 0x4b, 0x0f, 0x99, 0xe2, 0xa1, 0x3a, 0x8b, 0x15, 0xc6, 0xe9, + 0x3a, 0x56, 0x3f, 0xa4, 0xa3, 0x06, 0xac, 0xb3, 0xe9, 0x13, 0x37, 0xf0, 0x6c, 0xe2, 0xeb, 0xfb, + 0xd4, 0xd3, 0x7d, 0x87, 0x1e, 0xeb, 0xfb, 0xd4, 0x71, 0xe8, 0x31, 0xf1, 0xc2, 0xba, 0x59, 0xc5, + 0xa1, 0x43, 0x4d, 0x80, 0x36, 0xa9, 0xd7, 0x77, 0xe8, 0xf1, 0x66, 0x88, 0x60, 0x21, 0xdd, 0x6c, + 0xce, 0x81, 0x6d, 0x1e, 0x86, 0x21, 0x5d, 0x44, 0x1d, 0xd8, 0xe6, 0x21, 0x7a, 0x13, 0x96, 0x88, + 0x43, 0x78, 0xf9, 0x44, 0xa0, 0x72, 0x1c, 0x55, 0x0e, 0x89, 0x0c, 0xa4, 0x7e, 0x04, 0x8a, 0xe6, + 0x9a, 0xde, 0x74, 0x1c, 0x5b, 0xf3, 0x77, 0x01, 0x31, 0x27, 0xa9, 0x3b, 0xd4, 0x3c, 0xd4, 0x47, + 0x86, 0x6b, 0x0c, 0xd9, 0xb8, 0xc4, 0x0b, 0xa1, 0xc2, 0x38, 0xdb, 0xd4, 0x3c, 0xdc, 0x91, 0x74, + 0xf5, 0x3d, 0x80, 0xfe, 0xd8, 0x23, 0x86, 0xd5, 0x65, 0xd1, 0x04, 0x33, 0x1d, 0x6f, 0xe9, 0x96, + 0x7c, 0x7f, 0xa5, 0x9e, 0x3c, 0xea, 0x8a, 0x60, 0xb4, 0x22, 0xba, 0xfa, 0xff, 0xe1, 0x66, 0xcf, + 0x31, 0x4c, 0xfe, 0x2d, 0x42, 0x2f, 0x7a, 0xf2, 0x42, 0x4f, 0x20, 0x2f, 0xa0, 0x72, 0x25, 0x13, + 0x8f, 0xdb, 0xac, 0xcf, 0xad, 0x05, 0x2c, 0xf1, 0x8d, 0x32, 0xc0, 0x4c, 0x8f, 0xfa, 0x27, 0x29, + 0x28, 0x46, 0xfa, 0x51, 0x55, 0xbc, 0xe4, 0x04, 0x9e, 0x61, 0xbb, 0x32, 0xe3, 0x2f, 0xe2, 0x38, + 0x09, 0xb5, 0xa1, 0x34, 0x8e, 0xa4, 0xaf, 0x8c, 0xe7, 0x12, 0x46, 0x8d, 0xe3, 0xb2, 0xe8, 0x7d, + 0x28, 0x86, 0x0f, 0xde, 0xa1, 0x87, 0xbd, 0xfa, 0x7d, 0x7c, 0x06, 0x57, 0xbf, 0x09, 0xf0, 0x2d, + 0x6a, 0xbb, 0x03, 0x7a, 0x48, 0x5c, 0xfe, 0x44, 0xcb, 0xf2, 0x45, 0x12, 0x5a, 0x51, 0xb6, 0x78, + 0x19, 0x40, 0x2c, 0x41, 0xf4, 0x52, 0x29, 0x9a, 0xea, 0x5f, 0xa4, 0x21, 0x8f, 0x29, 0x0d, 0x9a, + 0x75, 0x54, 0x85, 0xbc, 0xf4, 0x13, 0xfc, 0xfe, 0x69, 0x14, 0xcf, 0xcf, 0x36, 0x72, 0xc2, 0x41, + 0xe4, 0x4c, 0xee, 0x19, 0x62, 0x1e, 0x3c, 0x7d, 0x99, 0x07, 0x47, 0x0f, 0xa0, 0x2c, 0x41, 0xfa, + 0x81, 0xe1, 0x1f, 0x88, 0xe4, 0xad, 0xb1, 0x7c, 0x7e, 0xb6, 0x01, 0x02, 0xb9, 0x65, 0xf8, 0x07, + 0x18, 0x04, 0x9a, 0xfd, 0x46, 0x1a, 0x94, 0x3e, 0xa6, 0xb6, 0xab, 0x07, 0x7c, 0x12, 0xb2, 0xd0, + 0x98, 0xb8, 0x8e, 0xb3, 0xa9, 0xca, 0xaf, 0x19, 0xe0, 0xe3, 0xd9, 0xe4, 0x35, 0x58, 0xf2, 0x28, + 0x0d, 0x84, 0xdb, 0xb2, 0xa9, 0x2b, 0x6b, 0x18, 0xd5, 0xc4, 0xd2, 0x36, 0xa5, 0x01, 0x96, 0x38, + 0x5c, 0xf6, 0x62, 0x2d, 0xf4, 0x00, 0x56, 0x1d, 0xc3, 0x0f, 0x74, 0xee, 0xef, 0xac, 0x99, 0xb6, + 0x3c, 0x3f, 0x6a, 0x88, 0xf1, 0x36, 0x39, 0x2b, 0x94, 0x50, 0xff, 0x21, 0x05, 0x25, 0x36, 0x19, + 0x7b, 0xdf, 0x36, 0x59, 0x90, 0xf7, 0xf9, 0x63, 0x8f, 0xdb, 0x90, 0x31, 0x7d, 0x4f, 0x1a, 0x95, + 0x5f, 0xbe, 0xcd, 0x3e, 0xc6, 0x8c, 0x86, 0x3e, 0x82, 0xbc, 0xac, 0xa5, 0x88, 0xb0, 0x43, 0xbd, + 0x3e, 0x1c, 0x95, 0xb6, 0x91, 0x72, 0x7c, 0x2f, 0xcf, 0x46, 0x27, 0x2e, 0x01, 0x1c, 0x27, 0xa1, + 0x5b, 0x90, 0x36, 0x85, 0xb9, 0xe4, 0xe7, 0x32, 0xcd, 0x0e, 0x4e, 0x9b, 0xae, 0xfa, 0xa3, 0x14, + 0x2c, 0xcd, 0x0e, 0x3c, 0xdb, 0x01, 0x77, 0xa0, 0xe8, 0x4f, 0xf6, 0xfc, 0xa9, 0x1f, 0x90, 0x51, + 0xf8, 0xfc, 0x1c, 0x11, 0x50, 0x1b, 0x8a, 0x86, 0x33, 0xa4, 0x9e, 0x1d, 0x1c, 0x8c, 0x64, 0x96, + 0x9a, 0x1c, 0x2a, 0xc4, 0x75, 0xd6, 0xea, 0xa1, 0x08, 0x9e, 0x49, 0x87, 0xf7, 0xbe, 0xf8, 0x46, + 0x81, 0xdf, 0xfb, 0x6f, 0x40, 0xd9, 0x31, 0x46, 0xbc, 0xb8, 0x14, 0xd8, 0x23, 0x31, 0x8f, 0x2c, + 0x2e, 0x49, 0xda, 0xc0, 0x1e, 0x11, 0x55, 0x85, 0x62, 0xa4, 0x0c, 0xad, 0x40, 0xa9, 0xae, 0xf5, + 0xf5, 0x87, 0x8f, 0x9e, 0xe8, 0x4f, 0x9b, 0x3b, 0xca, 0x82, 0x8c, 0x4d, 0xff, 0x34, 0x05, 0x4b, + 0xd2, 0x1d, 0xc9, 0x78, 0xff, 0x4d, 0x58, 0xf4, 0x8c, 0xfd, 0x20, 0xcc, 0x48, 0xb2, 0x62, 0x57, + 0x33, 0x0f, 0xcf, 0x32, 0x12, 0xc6, 0x4a, 0xce, 0x48, 0x62, 0x1f, 0x44, 0x64, 0xae, 0xfc, 0x20, + 0x22, 0xfb, 0x33, 0xf9, 0x20, 0x42, 0xfd, 0x15, 0x80, 0x4d, 0xdb, 0x21, 0x03, 0x51, 0x87, 0x4a, + 0xca, 0x2f, 0x59, 0x0c, 0x27, 0xeb, 0x9c, 0x61, 0x0c, 0xd7, 0x6e, 0x61, 0x46, 0x63, 0xac, 0xa1, + 0x6d, 0xc9, 0xc3, 0xc8, 0x59, 0x4f, 0x19, 0x6b, 0x68, 0x5b, 0xd1, 0xcb, 0x5d, 0xf6, 0xba, 0x97, + 0xbb, 0xd3, 0x14, 0xac, 0xc8, 0xd8, 0x35, 0x72, 0xbf, 0x5f, 0x86, 0xa2, 0x08, 0x63, 0x67, 0x09, + 0x1d, 0xff, 0x08, 0x40, 0xe0, 0xda, 0x2d, 0x5c, 0x10, 0xec, 0xb6, 0x85, 0x36, 0xa0, 0x24, 0xa1, + 0xb1, 0x4f, 0xab, 0x40, 0x90, 0x3a, 0x6c, 0xf8, 0x5f, 0x85, 0xec, 0xbe, 0xed, 0x10, 0xb9, 0xd1, + 0x13, 0x1d, 0xc0, 0xcc, 0x00, 0x5b, 0x0b, 0x98, 0xa3, 0x1b, 0x85, 0xb0, 0x50, 0xc7, 0xc7, 0x27, + 0xd3, 0xce, 0xf8, 0xf8, 0x44, 0x06, 0x3a, 0x37, 0x3e, 0x81, 0x63, 0xe3, 0x13, 0x6c, 0x31, 0x3e, + 0x09, 0x8d, 0x8f, 0x4f, 0x90, 0x7e, 0x26, 0xe3, 0xdb, 0x86, 0x5b, 0x0d, 0xc7, 0x30, 0x0f, 0x1d, + 0xdb, 0x0f, 0x88, 0x15, 0xf7, 0x18, 0x8f, 0x20, 0x7f, 0x21, 0xe8, 0xbc, 0xaa, 0xa2, 0x29, 0x91, + 0xea, 0xbf, 0xa6, 0xa0, 0xbc, 0x45, 0x0c, 0x27, 0x38, 0x98, 0x95, 0x8d, 0x02, 0xe2, 0x07, 0xf2, + 0xb2, 0xe2, 0xbf, 0xd1, 0xd7, 0xa0, 0x10, 0xc5, 0x24, 0xd7, 0xbe, 0xcd, 0x45, 0x50, 0xf4, 0x18, + 0x16, 0xd9, 0x19, 0xa3, 0x93, 0x30, 0xd9, 0xb9, 0xea, 0xd9, 0x47, 0x22, 0xd9, 0x25, 0xe3, 0x11, + 0x1e, 0x84, 0xf0, 0xad, 0x94, 0xc3, 0x61, 0x13, 0xfd, 0x5f, 0x28, 0xf3, 0x57, 0x8b, 0x30, 0xe6, + 0xca, 0x5d, 0xa7, 0xb3, 0x24, 0x1e, 0x1e, 0x45, 0xbc, 0xf5, 0x87, 0x69, 0x58, 0xdd, 0x31, 0xa6, + 0x7b, 0x44, 0xba, 0x0d, 0x62, 0x61, 0x62, 0x52, 0xcf, 0x42, 0xbd, 0xb8, 0xbb, 0xb9, 0xe2, 0x1d, + 0x33, 0x49, 0x38, 0xd9, 0xeb, 0x84, 0x09, 0x58, 0x3a, 0x96, 0x80, 0xad, 0x42, 0xce, 0xa5, 0xae, + 0x49, 0xa4, 0x2f, 0x12, 0x0d, 0xf5, 0xb7, 0x52, 0x71, 0x5f, 0x53, 0x89, 0xde, 0x18, 0x79, 0x05, + 0xaa, 0x43, 0x83, 0xa8, 0x3b, 0xf4, 0x11, 0x54, 0xfa, 0x5a, 0x13, 0x6b, 0x83, 0x46, 0xf7, 0xdb, + 0x7a, 0xbf, 0xbe, 0xdd, 0xaf, 0x3f, 0x7a, 0xa0, 0xf7, 0xba, 0xdb, 0xdf, 0x79, 0xf8, 0xf8, 0xc1, + 0xd7, 0x94, 0x54, 0xa5, 0x7a, 0x72, 0x5a, 0xbd, 0xd3, 0xa9, 0x37, 0xb7, 0xc5, 0x91, 0xd9, 0xa3, + 0x2f, 0xfb, 0x86, 0xe3, 0x1b, 0x8f, 0x1e, 0xf4, 0xa8, 0x33, 0x65, 0x18, 0xf4, 0x15, 0x40, 0x9b, + 0x1a, 0xee, 0x68, 0x03, 0x3d, 0x74, 0x68, 0xcd, 0x46, 0x53, 0x49, 0x8b, 0xb4, 0x66, 0x93, 0x78, + 0x2e, 0x09, 0xea, 0x5a, 0xff, 0xe1, 0xa3, 0x27, 0xcd, 0x46, 0x93, 0x1d, 0x82, 0x72, 0xfc, 0x76, + 0x8b, 0x5f, 0xda, 0xa9, 0x4b, 0x2f, 0xed, 0xd9, 0xdd, 0x9f, 0xbe, 0xe4, 0xee, 0xdf, 0x84, 0x55, + 0xd3, 0xa3, 0xbe, 0xaf, 0xb3, 0x5c, 0x81, 0x58, 0x73, 0xd9, 0xc8, 0x17, 0xce, 0xcf, 0x36, 0x6e, + 0x34, 0x19, 0xbf, 0xcf, 0xd9, 0x52, 0xfd, 0x0d, 0x33, 0x46, 0xe2, 0x3d, 0xa9, 0xbf, 0x9b, 0x61, + 0x61, 0x97, 0x7d, 0x64, 0x3b, 0x64, 0x48, 0x7c, 0xf4, 0x1c, 0x56, 0x4c, 0x8f, 0x58, 0x2c, 0x09, + 0x30, 0x9c, 0xf8, 0x07, 0xbd, 0xff, 0x27, 0x31, 0x02, 0x8a, 0x04, 0x6b, 0xcd, 0x48, 0xaa, 0x3f, + 0x26, 0x26, 0x5e, 0x36, 0x2f, 0xb4, 0xd1, 0xc7, 0xb0, 0xe2, 0x13, 0xc7, 0x76, 0x27, 0x2f, 0x75, + 0x93, 0xba, 0x01, 0x79, 0x19, 0xbe, 0xad, 0x5d, 0xa7, 0xb7, 0xaf, 0x6d, 0x33, 0xa9, 0xa6, 0x10, + 0x6a, 0xa0, 0xf3, 0xb3, 0x8d, 0xe5, 0x8b, 0x34, 0xbc, 0x2c, 0x35, 0xcb, 0x76, 0xa5, 0x03, 0xcb, + 0x17, 0x47, 0x83, 0x56, 0xa5, 0xa7, 0xe0, 0x0e, 0x27, 0xf4, 0x04, 0xe8, 0x0e, 0x14, 0x3c, 0x32, + 0xb4, 0xfd, 0xc0, 0x13, 0x66, 0x66, 0x9c, 0x88, 0xc2, 0xfc, 0x84, 0xf8, 0xde, 0xaa, 0xf2, 0x4b, + 0x30, 0xd7, 0x23, 0x3b, 0x5a, 0x96, 0xed, 0x1b, 0x7b, 0x52, 0x65, 0x01, 0x87, 0x4d, 0xb6, 0x63, + 0x27, 0x7e, 0x14, 0xd6, 0xf1, 0xdf, 0x8c, 0xc6, 0xe3, 0x0f, 0xf9, 0xf5, 0x19, 0x8f, 0x30, 0xc2, + 0x8f, 0x5c, 0xb3, 0xb1, 0x8f, 0x5c, 0x57, 0x21, 0xe7, 0x90, 0x23, 0xe2, 0x88, 0x9b, 0x1f, 0x8b, + 0xc6, 0xbd, 0x07, 0x50, 0x0e, 0xbf, 0xa6, 0xe4, 0x9f, 0x69, 0x14, 0x20, 0x3b, 0xa8, 0xf7, 0x9f, + 0x29, 0x0b, 0x08, 0x20, 0x2f, 0x76, 0xb2, 0x78, 0xf7, 0x6b, 0x76, 0x3b, 0x9b, 0xed, 0xa7, 0x4a, + 0xfa, 0xde, 0x6f, 0x67, 0xa1, 0x18, 0xbd, 0x3c, 0xb1, 0x9b, 0xa6, 0xa3, 0xbd, 0x08, 0x8f, 0x42, + 0x44, 0xef, 0x90, 0x63, 0xf4, 0xc6, 0xac, 0x66, 0xf5, 0x91, 0x78, 0x6a, 0x8f, 0xd8, 0x61, 0xbd, + 0xea, 0x2d, 0x28, 0xd4, 0xfb, 0xfd, 0xf6, 0xd3, 0x8e, 0xd6, 0x52, 0x3e, 0x4d, 0x55, 0xbe, 0x70, + 0x72, 0x5a, 0xbd, 0x11, 0x81, 0xea, 0xbe, 0xd8, 0x7c, 0x1c, 0xd5, 0x6c, 0x6a, 0xbd, 0x81, 0xd6, + 0x52, 0x3e, 0x49, 0xcf, 0xa3, 0x78, 0x0d, 0x86, 0x7f, 0x28, 0x54, 0xec, 0x61, 0xad, 0x57, 0xc7, + 0xac, 0xc3, 0x4f, 0xd3, 0xa2, 0x94, 0x36, 0xeb, 0xd1, 0x23, 0x63, 0xc3, 0x63, 0x7d, 0xae, 0x87, + 0x5f, 0xde, 0x7d, 0x92, 0x11, 0xdf, 0x92, 0xcc, 0x9e, 0xd1, 0x88, 0x61, 0x4d, 0x59, 0x6f, 0xfc, + 0xfd, 0x92, 0xab, 0xc9, 0xcc, 0xf5, 0xd6, 0x67, 0x9e, 0x8a, 0x69, 0x51, 0x61, 0x11, 0xef, 0x76, + 0x3a, 0x0c, 0xf4, 0x49, 0x76, 0x6e, 0x76, 0x78, 0xe2, 0xb2, 0xfc, 0x1a, 0xdd, 0x85, 0x42, 0xf8, + 0xbc, 0xa9, 0x7c, 0x9a, 0x9d, 0x1b, 0x50, 0x33, 0x7c, 0x9b, 0xe5, 0x1d, 0x6e, 0xed, 0x0e, 0xf8, + 0x87, 0x81, 0x9f, 0xe4, 0xe6, 0x3b, 0x3c, 0x98, 0x04, 0x16, 0x3d, 0x76, 0xd9, 0x99, 0x95, 0x55, + 0xbb, 0x4f, 0x73, 0xc2, 0x17, 0x44, 0x18, 0x59, 0xb2, 0x7b, 0x0b, 0x0a, 0x58, 0xfb, 0x96, 0xf8, + 0x86, 0xf0, 0x93, 0xfc, 0x9c, 0x1e, 0x4c, 0x3e, 0x26, 0x26, 0xeb, 0xad, 0x0a, 0x79, 0xac, 0xed, + 0x74, 0x9f, 0x6b, 0xca, 0xef, 0xe5, 0xe7, 0xf4, 0x60, 0x32, 0xa2, 0xfc, 0x4b, 0xaa, 0x42, 0x17, + 0xf7, 0xb6, 0xea, 0x7c, 0x51, 0xe6, 0xf5, 0x74, 0xbd, 0xf1, 0x81, 0xe1, 0x12, 0x6b, 0xf6, 0x3d, + 0x4d, 0xc4, 0xba, 0xf7, 0x73, 0x50, 0x08, 0x23, 0x5d, 0xb4, 0x0e, 0xf9, 0x17, 0x5d, 0xfc, 0x4c, + 0xc3, 0xca, 0x82, 0xb0, 0x72, 0xc8, 0x79, 0x21, 0x72, 0x94, 0x2a, 0x2c, 0xee, 0xd4, 0x3b, 0xf5, + 0xa7, 0x1a, 0x0e, 0x4b, 0xee, 0x21, 0x40, 0x86, 0x6b, 0x15, 0x45, 0x76, 0x10, 0xe9, 0x6c, 0xac, + 0xfd, 0xf0, 0x27, 0xeb, 0x0b, 0x3f, 0xfe, 0xc9, 0xfa, 0xc2, 0x27, 0xe7, 0xeb, 0xa9, 0x1f, 0x9e, + 0xaf, 0xa7, 0xfe, 0xf6, 0x7c, 0x3d, 0xf5, 0x2f, 0xe7, 0xeb, 0xa9, 0xbd, 0x3c, 0xbf, 0x54, 0x1e, + 0xff, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xac, 0xef, 0xe8, 0x11, 0x9e, 0x32, 0x00, 0x00, } diff --git a/vendor/github.com/docker/swarmkit/api/types.proto b/vendor/github.com/docker/swarmkit/api/types.proto index d25d6625e9cc6..26c3197667924 100644 --- a/vendor/github.com/docker/swarmkit/api/types.proto +++ b/vendor/github.com/docker/swarmkit/api/types.proto @@ -202,6 +202,7 @@ message Mount { BIND = 0 [(gogoproto.enumvalue_customname) = "MountTypeBind"]; // Bind mount host dir VOLUME = 1 [(gogoproto.enumvalue_customname) = "MountTypeVolume"]; // Remote storage volumes TMPFS = 2 [(gogoproto.enumvalue_customname) = "MountTypeTmpfs"]; // Mount a tmpfs + NPIPE = 3 [(gogoproto.enumvalue_customname) = "MountTypeNamedPipe"]; // Windows named pipes } // Type defines the nature of the mount. diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go b/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go index a6f0289a02132..e8b7e88c47368 100644 --- a/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go +++ b/vendor/github.com/docker/swarmkit/manager/allocator/allocator.go @@ -1,12 +1,12 @@ package allocator import ( - "net" "sync" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/go-events" "github.com/docker/swarmkit/api" + "github.com/docker/swarmkit/manager/allocator/cnmallocator" "github.com/docker/swarmkit/manager/state" "github.com/docker/swarmkit/manager/state/store" "golang.org/x/net/context" @@ -34,12 +34,8 @@ type Allocator struct { // pluginGetter provides access to docker's plugin inventory. pluginGetter plugingetter.PluginGetter - // DefaultAddrPool specifies default subnet pool for global scope networks - defaultAddrPool []*net.IPNet - - // SubnetSize specifies the subnet size of the networks created from - // the default subnet pool - subnetSize int + // networkConfig stores network related config for the cluster + networkConfig *cnmallocator.NetworkConfig } // taskBallot controls how the voting for task allocation is @@ -73,17 +69,16 @@ type allocActor struct { // New returns a new instance of Allocator for use during allocation // stage of the manager. -func New(store *store.MemoryStore, pg plugingetter.PluginGetter, defaultAddrPool []*net.IPNet, subnetSize int) (*Allocator, error) { +func New(store *store.MemoryStore, pg plugingetter.PluginGetter, netConfig *cnmallocator.NetworkConfig) (*Allocator, error) { a := &Allocator{ store: store, taskBallot: &taskBallot{ votes: make(map[string][]string), }, - stopChan: make(chan struct{}), - doneChan: make(chan struct{}), - pluginGetter: pg, - defaultAddrPool: defaultAddrPool, - subnetSize: subnetSize, + stopChan: make(chan struct{}), + doneChan: make(chan struct{}), + pluginGetter: pg, + networkConfig: netConfig, } return a, nil diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/drivers_ipam.go b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/drivers_ipam.go index d0daccc75ac21..39bce0615c70e 100644 --- a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/drivers_ipam.go +++ b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/drivers_ipam.go @@ -1,7 +1,6 @@ package cnmallocator import ( - "net" "strconv" "strings" @@ -14,7 +13,7 @@ import ( "github.com/sirupsen/logrus" ) -func initIPAMDrivers(r *drvregistry.DrvRegistry, defaultAddrPool []*net.IPNet, subnetSize int) error { +func initIPAMDrivers(r *drvregistry.DrvRegistry, netConfig *NetworkConfig) error { var addressPool []*ipamutils.NetworkToSplit var str strings.Builder str.WriteString("Subnetlist - ") @@ -22,16 +21,16 @@ func initIPAMDrivers(r *drvregistry.DrvRegistry, defaultAddrPool []*net.IPNet, s // from the info. We will be using it to call Libnetwork API // We also need to log new address pool info whenever swarm init // happens with default address pool option - if defaultAddrPool != nil { - for _, p := range defaultAddrPool { + if netConfig != nil { + for _, p := range netConfig.DefaultAddrPool { addressPool = append(addressPool, &ipamutils.NetworkToSplit{ - Base: p.String(), - Size: subnetSize, + Base: p, + Size: int(netConfig.SubnetSize), }) - str.WriteString(p.String() + ",") + str.WriteString(p + ",") } str.WriteString(": Size ") - str.WriteString(strconv.Itoa(subnetSize)) + str.WriteString(strconv.Itoa(int(netConfig.SubnetSize))) } if err := ipamutils.ConfigGlobalScopeDefaultNetworks(addressPool); err != nil { return err diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go index 22229d509562e..7a786406e1494 100644 --- a/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go +++ b/vendor/github.com/docker/swarmkit/manager/allocator/cnmallocator/networkallocator.go @@ -86,8 +86,18 @@ type initializer struct { ntype string } +// NetworkConfig is used to store network related cluster config in the Manager. +type NetworkConfig struct { + // DefaultAddrPool specifies default subnet pool for global scope networks + DefaultAddrPool []string + + // SubnetSize specifies the subnet size of the networks created from + // the default subnet pool + SubnetSize uint32 +} + // New returns a new NetworkAllocator handle -func New(pg plugingetter.PluginGetter, defaultAddrPool []*net.IPNet, subnetSize int) (networkallocator.NetworkAllocator, error) { +func New(pg plugingetter.PluginGetter, netConfig *NetworkConfig) (networkallocator.NetworkAllocator, error) { na := &cnmNetworkAllocator{ networks: make(map[string]*network), services: make(map[string]struct{}), @@ -106,7 +116,7 @@ func New(pg plugingetter.PluginGetter, defaultAddrPool []*net.IPNet, subnetSize return nil, err } - if err = initIPAMDrivers(reg, defaultAddrPool, subnetSize); err != nil { + if err = initIPAMDrivers(reg, netConfig); err != nil { return nil, err } diff --git a/vendor/github.com/docker/swarmkit/manager/allocator/network.go b/vendor/github.com/docker/swarmkit/manager/allocator/network.go index 88f665c2fe503..e4d5b61827adb 100644 --- a/vendor/github.com/docker/swarmkit/manager/allocator/network.go +++ b/vendor/github.com/docker/swarmkit/manager/allocator/network.go @@ -68,7 +68,15 @@ type networkContext struct { } func (a *Allocator) doNetworkInit(ctx context.Context) (err error) { - na, err := cnmallocator.New(a.pluginGetter, a.defaultAddrPool, a.subnetSize) + var netConfig *cnmallocator.NetworkConfig + if a.networkConfig != nil && a.networkConfig.DefaultAddrPool != nil { + netConfig = &cnmallocator.NetworkConfig{ + DefaultAddrPool: a.networkConfig.DefaultAddrPool, + SubnetSize: a.networkConfig.SubnetSize, + } + } + + na, err := cnmallocator.New(a.pluginGetter, netConfig) if err != nil { return err } diff --git a/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go b/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go index 7b34807294846..ad248044844a0 100644 --- a/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go +++ b/vendor/github.com/docker/swarmkit/manager/controlapi/cluster.go @@ -19,6 +19,13 @@ const ( // expiredCertGrace is the amount of time to keep a node in the // blacklist beyond its certificate expiration timestamp. expiredCertGrace = 24 * time.Hour * 7 + // inbuilt default subnet size + inbuiltSubnetSize = 24 +) + +var ( + // inbuilt default address pool + inbuiltDefaultAddressPool = []string{"10.0.0.0/8"} ) func validateClusterSpec(spec *api.ClusterSpec) error { @@ -268,6 +275,12 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster { DefaultAddressPool: cluster.DefaultAddressPool, SubnetSize: cluster.SubnetSize, } + if newCluster.DefaultAddressPool == nil { + // This is just for CLI display. Set the inbuilt default pool for + // user reference. + newCluster.DefaultAddressPool = inbuiltDefaultAddressPool + newCluster.SubnetSize = inbuiltSubnetSize + } redactedClusters = append(redactedClusters, newCluster) } diff --git a/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go b/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go index d783fd4c35e01..569ab26375865 100644 --- a/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go +++ b/vendor/github.com/docker/swarmkit/manager/dispatcher/dispatcher.go @@ -342,6 +342,39 @@ func (d *Dispatcher) Stop() error { d.cancel() d.mu.Unlock() + d.processUpdatesLock.Lock() + // when we called d.cancel(), there may be routines, servicing RPC calls to + // the (*Dispatcher).Session endpoint, currently waiting at + // d.processUpdatesCond.Wait() inside of (*Dispatcher).markNodeReady(). + // + // these routines are typically woken by a call to + // d.processUpdatesCond.Broadcast() at the end of + // (*Dispatcher).processUpdates() as part of the main Run loop. However, + // when d.cancel() is called, the main Run loop is stopped, and there are + // no more opportunties for processUpdates to be called. Any calls to + // Session would be stuck waiting on a call to Broadcast that will never + // come. + // + // Further, because the rpcRW write lock cannot be obtained until every RPC + // has exited and released its read lock, then Stop would be stuck forever. + // + // To avoid this case, we acquire the processUpdatesLock (so that no new + // waits can start) and then do a Broadcast to wake all of the waiting + // routines. Further, if any routines are waiting in markNodeReady to + // acquire this lock, but not yet waiting, those routines will check the + // context cancelation, see the context is canceled, and exit before doing + // the Wait. + // + // This call to Broadcast must occur here. If we called Broadcast before + // context cancelation, then some new routines could enter the wait. If we + // call Broadcast after attempting to acquire the rpcRW lock, we will be + // deadlocked. If we do this Broadcast without obtaining this lock (as is + // done in the processUpdates method), then it would be possible for that + // broadcast to come after the context cancelation check in markNodeReady, + // but before the call to Wait. + d.processUpdatesCond.Broadcast() + d.processUpdatesLock.Unlock() + // The active nodes list can be cleaned out only when all // existing RPCs have finished. // RPCs that start after rpcRW.Unlock() should find the context @@ -351,13 +384,6 @@ func (d *Dispatcher) Stop() error { d.downNodes.Clean() d.rpcRW.Unlock() - d.processUpdatesLock.Lock() - // In case there are any waiters. There is no chance of any starting - // after this point, because they check if the context is canceled - // before waiting. - d.processUpdatesCond.Broadcast() - d.processUpdatesLock.Unlock() - d.clusterUpdateQueue.Close() // TODO(anshul): This use of Wait() could be unsafe. diff --git a/vendor/github.com/docker/swarmkit/manager/manager.go b/vendor/github.com/docker/swarmkit/manager/manager.go index c8bafb77aaa38..106c8e2b585c2 100644 --- a/vendor/github.com/docker/swarmkit/manager/manager.go +++ b/vendor/github.com/docker/swarmkit/manager/manager.go @@ -20,6 +20,7 @@ import ( "github.com/docker/swarmkit/identity" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager/allocator" + "github.com/docker/swarmkit/manager/allocator/cnmallocator" "github.com/docker/swarmkit/manager/allocator/networkallocator" "github.com/docker/swarmkit/manager/controlapi" "github.com/docker/swarmkit/manager/dispatcher" @@ -127,12 +128,8 @@ type Config struct { // FIPS setting. FIPS bool - // DefaultAddrPool specifies default subnet pool for global scope networks - DefaultAddrPool []*net.IPNet - - // SubnetSize specifies the subnet size of the networks created from - // the default subnet pool - SubnetSize int + // NetworkConfig stores network related config for the cluster + NetworkConfig *cnmallocator.NetworkConfig } // Manager is the cluster manager for Swarm. @@ -947,14 +944,10 @@ func (m *Manager) becomeLeader(ctx context.Context) { nil, 0) - var defaultAddrPool []string - for _, p := range m.config.DefaultAddrPool { - defaultAddrPool = append(defaultAddrPool, p.String()) - } // If defaultAddrPool is valid we update cluster object with new value - if defaultAddrPool != nil { - clusterObj.DefaultAddressPool = defaultAddrPool - clusterObj.SubnetSize = uint32(m.config.SubnetSize) + if m.config.NetworkConfig != nil && m.config.NetworkConfig.DefaultAddrPool != nil { + clusterObj.DefaultAddressPool = m.config.NetworkConfig.DefaultAddrPool + clusterObj.SubnetSize = m.config.NetworkConfig.SubnetSize } err := store.CreateCluster(tx, clusterObj) @@ -1003,24 +996,20 @@ func (m *Manager) becomeLeader(ctx context.Context) { // If DefaultAddrPool is null, Read from store and check if // DefaultAddrPool info is stored in cluster object - if m.config.DefaultAddrPool == nil { + if m.config.NetworkConfig == nil || m.config.NetworkConfig.DefaultAddrPool == nil { var cluster *api.Cluster s.View(func(tx store.ReadTx) { cluster = store.GetCluster(tx, clusterID) }) if cluster.DefaultAddressPool != nil { for _, address := range cluster.DefaultAddressPool { - _, b, err := net.ParseCIDR(address) - if err != nil { - log.G(ctx).WithError(err).Error("Default Address Pool reading failed for cluster object %s", address) - } - m.config.DefaultAddrPool = append(m.config.DefaultAddrPool, b) + m.config.NetworkConfig.DefaultAddrPool = append(m.config.NetworkConfig.DefaultAddrPool, address) } + m.config.NetworkConfig.SubnetSize = cluster.SubnetSize } - m.config.SubnetSize = int(cluster.SubnetSize) } - m.allocator, err = allocator.New(s, m.config.PluginGetter, m.config.DefaultAddrPool, m.config.SubnetSize) + m.allocator, err = allocator.New(s, m.config.PluginGetter, m.config.NetworkConfig) if err != nil { log.G(ctx).WithError(err).Error("failed to create allocator") // TODO(stevvooe): It doesn't seem correct here to fail @@ -1144,7 +1133,7 @@ func defaultClusterObject( rootCA *ca.RootCA, fips bool, defaultAddressPool []string, - subnetSize int) *api.Cluster { + subnetSize uint32) *api.Cluster { var caKey []byte if rcaSigner, err := rootCA.Signer(); err == nil { caKey = rcaSigner.Key @@ -1178,7 +1167,7 @@ func defaultClusterObject( UnlockKeys: initialUnlockKeys, FIPS: fips, DefaultAddressPool: defaultAddressPool, - SubnetSize: uint32(subnetSize), + SubnetSize: subnetSize, } } diff --git a/vendor/github.com/docker/swarmkit/node/node.go b/vendor/github.com/docker/swarmkit/node/node.go index 843c738995631..6cbf265c5d3ea 100644 --- a/vendor/github.com/docker/swarmkit/node/node.go +++ b/vendor/github.com/docker/swarmkit/node/node.go @@ -17,7 +17,6 @@ import ( "github.com/docker/swarmkit/ca/keyutils" "github.com/docker/swarmkit/identity" - "github.com/boltdb/bolt" "github.com/docker/docker/pkg/plugingetter" metrics "github.com/docker/go-metrics" "github.com/docker/swarmkit/agent" @@ -28,12 +27,14 @@ import ( "github.com/docker/swarmkit/ioutils" "github.com/docker/swarmkit/log" "github.com/docker/swarmkit/manager" + "github.com/docker/swarmkit/manager/allocator/cnmallocator" "github.com/docker/swarmkit/manager/encryption" "github.com/docker/swarmkit/remotes" "github.com/docker/swarmkit/xnet" grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "github.com/pkg/errors" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -105,12 +106,8 @@ type Config struct { // for connections to the remote API (including the raft service). AdvertiseRemoteAPI string - // DefaultAddrPool specifies default subnet pool for global scope networks - DefaultAddrPool []*net.IPNet - - // SubnetSize specifies the subnet size of the networks created from - // the default subnet pool - SubnetSize int + // NetworkConfig stores network related config for the cluster + NetworkConfig *cnmallocator.NetworkConfig // Executor specifies the executor to use for the agent. Executor exec.Executor @@ -1002,8 +999,7 @@ func (n *Node) runManager(ctx context.Context, securityConfig *ca.SecurityConfig PluginGetter: n.config.PluginGetter, RootCAPaths: rootPaths, FIPS: n.config.FIPS, - DefaultAddrPool: n.config.DefaultAddrPool, - SubnetSize: n.config.SubnetSize, + NetworkConfig: n.config.NetworkConfig, }) if err != nil { return false, err diff --git a/vendor/github.com/docker/swarmkit/vendor.conf b/vendor/github.com/docker/swarmkit/vendor.conf index c86ff34a002c6..f91ea497e0af1 100644 --- a/vendor/github.com/docker/swarmkit/vendor.conf +++ b/vendor/github.com/docker/swarmkit/vendor.conf @@ -43,7 +43,6 @@ github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 # v1.1.0 github.com/Microsoft/go-winio v0.4.8 github.com/sirupsen/logrus v1.0.3 github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 -github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904 github.com/cloudflare/cfssl 1.3.2 github.com/dustin/go-humanize 8929fe90cee4b2cb9deb468b51fb34eba64d1bf0 github.com/fernet/fernet-go 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2 @@ -60,6 +59,7 @@ github.com/rcrowley/go-metrics 51425a2415d21afadfd55cd93432c0bc69e9598d github.com/spf13/cobra 8e91712f174ced10270cf66615e0a9127e7c4de5 github.com/spf13/pflag 7f60f83a2c81bc3c3c0d5297f61ddfa68da9d3b7 github.com/stretchr/testify v1.1.4 +go.etcd.io/bbolt v1.3.1-etcd.8 golang.org/x/crypto 1a580b3eff7814fc9b40602fd35256c63b50f491 golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd golang.org/x/sys 37707fdb30a5b38865cfb95e5aab41707daec7fd diff --git a/vendor/github.com/moby/buildkit/cache/gc.go b/vendor/github.com/moby/buildkit/cache/gc.go deleted file mode 100644 index 31a98b93c8fa8..0000000000000 --- a/vendor/github.com/moby/buildkit/cache/gc.go +++ /dev/null @@ -1,27 +0,0 @@ -package cache - -import ( - "context" - "errors" - "time" -) - -// GCPolicy defines policy for garbage collection -type GCPolicy struct { - MaxSize uint64 - MaxKeepDuration time.Duration -} - -// // CachePolicy defines policy for keeping a resource in cache -// type CachePolicy struct { -// Priority int -// LastUsed time.Time -// } -// -// func defaultCachePolicy() CachePolicy { -// return CachePolicy{Priority: 10, LastUsed: time.Now()} -// } - -func (cm *cacheManager) GC(ctx context.Context) error { - return errors.New("GC not implemented") -} diff --git a/vendor/github.com/moby/buildkit/cache/manager.go b/vendor/github.com/moby/buildkit/cache/manager.go index e73de71f3a8a2..948eb8df8b3a2 100644 --- a/vendor/github.com/moby/buildkit/cache/manager.go +++ b/vendor/github.com/moby/buildkit/cache/manager.go @@ -25,7 +25,6 @@ var ( type ManagerOpt struct { Snapshotter snapshot.SnapshotterBase - GCPolicy GCPolicy MetadataStore *metadata.Store PruneRefChecker ExternalRefCheckerFunc } @@ -40,7 +39,6 @@ type Accessor interface { type Controller interface { DiskUsage(ctx context.Context, info client.DiskUsageInfo) ([]*client.UsageInfo, error) Prune(ctx context.Context, ch chan client.UsageInfo, info ...client.PruneInfo) error - GC(ctx context.Context) error } type Manager interface { @@ -128,17 +126,24 @@ func (cm *cacheManager) get(ctx context.Context, id string, fromSnapshotter bool rec.mu.Lock() defer rec.mu.Unlock() + triggerUpdate := true + for _, o := range opts { + if o == NoUpdateLastUsed { + triggerUpdate = false + } + } + if rec.mutable { if len(rec.refs) != 0 { return nil, errors.Wrapf(ErrLocked, "%s is locked", id) } if rec.equalImmutable != nil { - return rec.equalImmutable.ref(), nil + return rec.equalImmutable.ref(triggerUpdate), nil } - return rec.mref().commit(ctx) + return rec.mref(triggerUpdate).commit(ctx) } - return rec.ref(), nil + return rec.ref(triggerUpdate), nil } // getRecord returns record for id. Requires manager lock. @@ -166,8 +171,8 @@ func (cm *cacheManager) getRecord(ctx context.Context, id string, fromSnapshotte rec := &cacheRecord{ mu: &sync.Mutex{}, cm: cm, - refs: make(map[Mountable]struct{}), - parent: mutable.Parent(), + refs: make(map[ref]struct{}), + parent: mutable.parentRef(false), md: md, equalMutable: &mutableRef{cacheRecord: mutable}, } @@ -183,7 +188,7 @@ func (cm *cacheManager) getRecord(ctx context.Context, id string, fromSnapshotte var parent ImmutableRef if info.Parent != "" { - parent, err = cm.get(ctx, info.Parent, fromSnapshotter, opts...) + parent, err = cm.get(ctx, info.Parent, fromSnapshotter, append(opts, NoUpdateLastUsed)...) if err != nil { return nil, err } @@ -198,7 +203,7 @@ func (cm *cacheManager) getRecord(ctx context.Context, id string, fromSnapshotte mu: &sync.Mutex{}, mutable: info.Kind != snapshots.KindCommitted, cm: cm, - refs: make(map[Mountable]struct{}), + refs: make(map[ref]struct{}), parent: parent, md: md, } @@ -229,7 +234,7 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti var parentID string if s != nil { var err error - parent, err = cm.Get(ctx, s.ID()) + parent, err = cm.Get(ctx, s.ID(), NoUpdateLastUsed) if err != nil { return nil, err } @@ -252,7 +257,7 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti mu: &sync.Mutex{}, mutable: true, cm: cm, - refs: make(map[Mountable]struct{}), + refs: make(map[ref]struct{}), parent: parent, md: md, } @@ -269,7 +274,7 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti cm.records[id] = rec // TODO: save to db - return rec.mref(), nil + return rec.mref(true), nil } func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef, error) { cm.mu.Lock() @@ -301,7 +306,7 @@ func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef, rec.equalImmutable = nil } - return rec.mref(), nil + return rec.mref(true), nil } func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo, opts ...client.PruneInfo) error { @@ -669,7 +674,7 @@ func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) if d.Size == sizeUnknown { func(d *client.UsageInfo) { eg.Go(func() error { - ref, err := cm.Get(ctx, d.ID) + ref, err := cm.Get(ctx, d.ID, NoUpdateLastUsed) if err != nil { d.Size = 0 return nil @@ -700,7 +705,7 @@ func IsNotFound(err error) bool { return errors.Cause(err) == errNotFound } -type RefOption func(withMetadata) error +type RefOption interface{} type cachePolicy int @@ -713,6 +718,10 @@ type withMetadata interface { Metadata() *metadata.StorageItem } +type noUpdateLastUsed struct{} + +var NoUpdateLastUsed noUpdateLastUsed + func HasCachePolicyRetain(m withMetadata) bool { return getCachePolicy(m.Metadata()) == cachePolicyRetain } @@ -750,8 +759,10 @@ func initializeMetadata(m withMetadata, opts ...RefOption) error { } for _, opt := range opts { - if err := opt(m); err != nil { - return err + if fn, ok := opt.(func(withMetadata) error); ok { + if err := fn(m); err != nil { + return err + } } } diff --git a/vendor/github.com/moby/buildkit/cache/metadata.go b/vendor/github.com/moby/buildkit/cache/metadata.go index ae26699dcd268..9929868844c9f 100644 --- a/vendor/github.com/moby/buildkit/cache/metadata.go +++ b/vendor/github.com/moby/buildkit/cache/metadata.go @@ -3,10 +3,10 @@ package cache import ( "time" - "github.com/boltdb/bolt" "github.com/moby/buildkit/cache/metadata" "github.com/moby/buildkit/client" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) const sizeUnknown int64 = -1 diff --git a/vendor/github.com/moby/buildkit/cache/metadata/metadata.go b/vendor/github.com/moby/buildkit/cache/metadata/metadata.go index 461ff6cfd7fe2..9da270b4e6190 100644 --- a/vendor/github.com/moby/buildkit/cache/metadata/metadata.go +++ b/vendor/github.com/moby/buildkit/cache/metadata/metadata.go @@ -6,9 +6,9 @@ import ( "strings" "sync" - "github.com/boltdb/bolt" "github.com/pkg/errors" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" ) const ( diff --git a/vendor/github.com/moby/buildkit/cache/refs.go b/vendor/github.com/moby/buildkit/cache/refs.go index af92b80977329..7521e0aa9af40 100644 --- a/vendor/github.com/moby/buildkit/cache/refs.go +++ b/vendor/github.com/moby/buildkit/cache/refs.go @@ -38,12 +38,16 @@ type Mountable interface { Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) } +type ref interface { + updateLastUsed() bool +} + type cacheRecord struct { cm *cacheManager mu *sync.Mutex // the mutex is shared by records sharing data mutable bool - refs map[Mountable]struct{} + refs map[ref]struct{} parent ImmutableRef md *metadata.StorageItem @@ -61,15 +65,15 @@ type cacheRecord struct { } // hold ref lock before calling -func (cr *cacheRecord) ref() *immutableRef { - ref := &immutableRef{cacheRecord: cr} +func (cr *cacheRecord) ref(triggerLastUsed bool) *immutableRef { + ref := &immutableRef{cacheRecord: cr, triggerLastUsed: triggerLastUsed} cr.refs[ref] = struct{}{} return ref } // hold ref lock before calling -func (cr *cacheRecord) mref() *mutableRef { - ref := &mutableRef{cacheRecord: cr} +func (cr *cacheRecord) mref(triggerLastUsed bool) *mutableRef { + ref := &mutableRef{cacheRecord: cr, triggerLastUsed: triggerLastUsed} cr.refs[ref] = struct{}{} return ref } @@ -116,13 +120,17 @@ func (cr *cacheRecord) Size(ctx context.Context) (int64, error) { } func (cr *cacheRecord) Parent() ImmutableRef { + return cr.parentRef(true) +} + +func (cr *cacheRecord) parentRef(hidden bool) ImmutableRef { if cr.parent == nil { return nil } p := cr.parent.(*immutableRef) p.mu.Lock() defer p.mu.Unlock() - return p.ref() + return p.ref(hidden) } func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) { @@ -188,15 +196,17 @@ func (cr *cacheRecord) ID() string { type immutableRef struct { *cacheRecord + triggerLastUsed bool } type mutableRef struct { *cacheRecord + triggerLastUsed bool } func (sr *immutableRef) Clone() ImmutableRef { sr.mu.Lock() - ref := sr.ref() + ref := sr.ref(false) sr.mu.Unlock() return ref } @@ -211,11 +221,33 @@ func (sr *immutableRef) Release(ctx context.Context) error { return sr.release(ctx) } +func (sr *immutableRef) updateLastUsed() bool { + return sr.triggerLastUsed +} + +func (sr *immutableRef) updateLastUsedNow() bool { + if !sr.triggerLastUsed { + return false + } + for r := range sr.refs { + if r.updateLastUsed() { + return false + } + } + return true +} + func (sr *immutableRef) release(ctx context.Context) error { delete(sr.refs, sr) - if len(sr.refs) == 0 { + if sr.updateLastUsedNow() { updateLastUsed(sr.md) + if sr.equalMutable != nil { + sr.equalMutable.triggerLastUsed = true + } + } + + if len(sr.refs) == 0 { if sr.viewMount != nil { // TODO: release viewMount earlier if possible if err := sr.cm.Snapshotter.Remove(ctx, sr.view); err != nil { return err @@ -273,6 +305,10 @@ func (cr *cacheRecord) finalize(ctx context.Context, commit bool) error { return cr.md.Commit() } +func (sr *mutableRef) updateLastUsed() bool { + return sr.triggerLastUsed +} + func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) { if !sr.mutable || len(sr.refs) == 0 { return nil, errors.Wrapf(errInvalid, "invalid mutable ref") @@ -280,13 +316,12 @@ func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) { id := identity.NewID() md, _ := sr.cm.md.Get(id) - rec := &cacheRecord{ mu: sr.mu, cm: sr.cm, - parent: sr.Parent(), + parent: sr.parentRef(false), equalMutable: sr, - refs: make(map[Mountable]struct{}), + refs: make(map[ref]struct{}), md: md, } @@ -312,11 +347,15 @@ func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) { return nil, err } - ref := rec.ref() + ref := rec.ref(true) sr.equalImmutable = ref return ref, nil } +func (sr *mutableRef) updatesLastUsed() bool { + return sr.triggerLastUsed +} + func (sr *mutableRef) Commit(ctx context.Context) (ImmutableRef, error) { sr.cm.mu.Lock() defer sr.cm.mu.Unlock() @@ -342,6 +381,10 @@ func (sr *mutableRef) release(ctx context.Context) error { if getCachePolicy(sr.md) != cachePolicyRetain { if sr.equalImmutable != nil { if getCachePolicy(sr.equalImmutable.md) == cachePolicyRetain { + if sr.updateLastUsed() { + updateLastUsed(sr.md) + sr.triggerLastUsed = false + } return nil } if err := sr.equalImmutable.remove(ctx, false); err != nil { @@ -355,7 +398,10 @@ func (sr *mutableRef) release(ctx context.Context) error { } return sr.remove(ctx, true) } else { - updateLastUsed(sr.md) + if sr.updateLastUsed() { + updateLastUsed(sr.md) + sr.triggerLastUsed = false + } } return nil } diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go b/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go index fa9dc1a7f2cb0..fa23aa5522038 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go @@ -10,17 +10,17 @@ import ( "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/auth" "github.com/moby/buildkit/util/contentutil" - "github.com/moby/buildkit/util/tracing" + "github.com/moby/buildkit/util/resolver" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) -func ResolveCacheExporterFunc(sm *session.Manager) remotecache.ResolveCacheExporterFunc { +func ResolveCacheExporterFunc(sm *session.Manager, resolverOpt resolver.ResolveOptionsFunc) remotecache.ResolveCacheExporterFunc { return func(ctx context.Context, typ, ref string) (remotecache.Exporter, error) { if typ != "" { return nil, errors.Errorf("unsupported cache exporter type: %s", typ) } - remote := newRemoteResolver(ctx, sm) + remote := newRemoteResolver(ctx, resolverOpt, sm, ref) pusher, err := remote.Pusher(ctx, ref) if err != nil { return nil, err @@ -29,12 +29,12 @@ func ResolveCacheExporterFunc(sm *session.Manager) remotecache.ResolveCacheExpor } } -func ResolveCacheImporterFunc(sm *session.Manager) remotecache.ResolveCacheImporterFunc { +func ResolveCacheImporterFunc(sm *session.Manager, resolverOpt resolver.ResolveOptionsFunc) remotecache.ResolveCacheImporterFunc { return func(ctx context.Context, typ, ref string) (remotecache.Importer, specs.Descriptor, error) { if typ != "" { return nil, specs.Descriptor{}, errors.Errorf("unsupported cache importer type: %s", typ) } - remote := newRemoteResolver(ctx, sm) + remote := newRemoteResolver(ctx, resolverOpt, sm, ref) xref, desc, err := remote.Resolve(ctx, ref) if err != nil { return nil, specs.Descriptor{}, err @@ -47,11 +47,10 @@ func ResolveCacheImporterFunc(sm *session.Manager) remotecache.ResolveCacheImpor } } -func newRemoteResolver(ctx context.Context, sm *session.Manager) remotes.Resolver { - return docker.NewResolver(docker.ResolverOptions{ - Client: tracing.DefaultClient, - Credentials: getCredentialsFunc(ctx, sm), - }) +func newRemoteResolver(ctx context.Context, resolverOpt resolver.ResolveOptionsFunc, sm *session.Manager, ref string) remotes.Resolver { + opt := resolverOpt(ref) + opt.Credentials = getCredentialsFunc(ctx, sm) + return docker.NewResolver(opt) } func getCredentialsFunc(ctx context.Context, sm *session.Manager) func(string) (string, string, error) { diff --git a/vendor/github.com/moby/buildkit/client/client.go b/vendor/github.com/moby/buildkit/client/client.go index 403ed52a8ce3c..6126acdc1b36e 100644 --- a/vendor/github.com/moby/buildkit/client/client.go +++ b/vendor/github.com/moby/buildkit/client/client.go @@ -25,12 +25,11 @@ type ClientOpt interface{} func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error) { gopts := []grpc.DialOption{ grpc.WithDialer(dialer), - grpc.FailOnNonTempDialError(true), } needWithInsecure := true for _, o := range opts { - if _, ok := o.(*withBlockOpt); ok { - gopts = append(gopts, grpc.WithBlock(), grpc.FailOnNonTempDialError(true)) + if _, ok := o.(*withFailFast); ok { + gopts = append(gopts, grpc.FailOnNonTempDialError(true)) } if credInfo, ok := o.(*withCredentials); ok { opt, err := loadCredentials(credInfo) @@ -52,7 +51,6 @@ func New(ctx context.Context, address string, opts ...ClientOpt) (*Client, error if address == "" { address = appdefaults.Address } - conn, err := grpc.DialContext(ctx, address, gopts...) if err != nil { return nil, errors.Wrapf(err, "failed to dial %q . make sure buildkitd is running", address) @@ -71,10 +69,10 @@ func (c *Client) Close() error { return c.conn.Close() } -type withBlockOpt struct{} +type withFailFast struct{} -func WithBlock() ClientOpt { - return &withBlockOpt{} +func WithFailFast() ClientOpt { + return &withFailFast{} } type withCredentials struct { diff --git a/vendor/github.com/moby/buildkit/client/llb/exec.go b/vendor/github.com/moby/buildkit/client/llb/exec.go index ebb5b7123f95c..a34e75ea1a20e 100644 --- a/vendor/github.com/moby/buildkit/client/llb/exec.go +++ b/vendor/github.com/moby/buildkit/client/llb/exec.go @@ -2,6 +2,7 @@ package llb import ( _ "crypto/sha256" + "fmt" "net" "sort" @@ -61,6 +62,7 @@ type ExecOp struct { constraints Constraints isValidated bool secrets []SecretInfo + ssh []SSHInfo } func (e *ExecOp) AddMount(target string, source Output, opt ...MountOption) Output { @@ -130,6 +132,17 @@ func (e *ExecOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, return e.mounts[i].target < e.mounts[j].target }) + if len(e.ssh) > 0 { + for i, s := range e.ssh { + if s.Target == "" { + e.ssh[i].Target = fmt.Sprintf("/run/buildkit/ssh_agent.%d", i) + } + } + if _, ok := e.meta.Env.Get("SSH_AUTH_SOCK"); !ok { + e.meta.Env = e.meta.Env.AddOrReplace("SSH_AUTH_SOCK", e.ssh[0].Target) + } + } + meta := &pb.Meta{ Args: e.meta.Args, Env: e.meta.Env.ToArray(), @@ -264,6 +277,21 @@ func (e *ExecOp) Marshal(c *Constraints) (digest.Digest, []byte, *pb.OpMetadata, peo.Mounts = append(peo.Mounts, pm) } + for _, s := range e.ssh { + pm := &pb.Mount{ + Dest: s.Target, + MountType: pb.MountType_SSH, + SSHOpt: &pb.SSHOpt{ + ID: s.ID, + Uid: uint32(s.UID), + Gid: uint32(s.GID), + Mode: uint32(s.Mode), + Optional: s.Optional, + }, + } + peo.Mounts = append(peo.Mounts, pm) + } + dt, err := pop.Marshal() if err != nil { return "", nil, nil, err @@ -432,6 +460,56 @@ func AddMount(dest string, mountState State, opts ...MountOption) RunOption { }) } +func AddSSHSocket(opts ...SSHOption) RunOption { + return runOptionFunc(func(ei *ExecInfo) { + s := &SSHInfo{ + Mode: 0600, + } + for _, opt := range opts { + opt.SetSSHOption(s) + } + ei.SSH = append(ei.SSH, *s) + }) +} + +type SSHOption interface { + SetSSHOption(*SSHInfo) +} + +type sshOptionFunc func(*SSHInfo) + +func (fn sshOptionFunc) SetSSHOption(si *SSHInfo) { + fn(si) +} + +func SSHID(id string) SSHOption { + return sshOptionFunc(func(si *SSHInfo) { + si.ID = id + }) +} + +func SSHSocketOpt(target string, uid, gid, mode int) SSHOption { + return sshOptionFunc(func(si *SSHInfo) { + si.Target = target + si.UID = uid + si.GID = gid + si.Mode = mode + }) +} + +var SSHOptional = sshOptionFunc(func(si *SSHInfo) { + si.Optional = true +}) + +type SSHInfo struct { + ID string + Target string + Mode int + UID int + GID int + Optional bool +} + func AddSecret(dest string, opts ...SecretOption) RunOption { return runOptionFunc(func(ei *ExecInfo) { s := &SecretInfo{ID: dest, Target: dest, Mode: 0400} @@ -498,6 +576,7 @@ type ExecInfo struct { ReadonlyRootFS bool ProxyEnv *ProxyEnv Secrets []SecretInfo + SSH []SSHInfo } type MountInfo struct { diff --git a/vendor/github.com/moby/buildkit/client/llb/resolver.go b/vendor/github.com/moby/buildkit/client/llb/resolver.go index 45240f0224966..d670a991888f3 100644 --- a/vendor/github.com/moby/buildkit/client/llb/resolver.go +++ b/vendor/github.com/moby/buildkit/client/llb/resolver.go @@ -7,12 +7,14 @@ import ( digest "github.com/opencontainers/go-digest" ) +// WithMetaResolver adds a metadata resolver to an image func WithMetaResolver(mr ImageMetaResolver) ImageOption { return imageOptionFunc(func(ii *ImageInfo) { ii.metaResolver = mr }) } +// ImageMetaResolver can resolve image config metadata from a reference type ImageMetaResolver interface { ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error) } diff --git a/vendor/github.com/moby/buildkit/client/llb/state.go b/vendor/github.com/moby/buildkit/client/llb/state.go index e8972dfdbaecc..b5b8f1e1119ce 100644 --- a/vendor/github.com/moby/buildkit/client/llb/state.go +++ b/vendor/github.com/moby/buildkit/client/llb/state.go @@ -196,6 +196,7 @@ func (s State) Run(ro ...RunOption) ExecState { exec.AddMount(m.Target, m.Source, m.Opts...) } exec.secrets = ei.Secrets + exec.ssh = ei.SSH return ExecState{ State: s.WithOutput(exec.Output()), diff --git a/vendor/github.com/moby/buildkit/client/workers.go b/vendor/github.com/moby/buildkit/client/workers.go index 50654897ed09d..b011ee2efdbf2 100644 --- a/vendor/github.com/moby/buildkit/client/workers.go +++ b/vendor/github.com/moby/buildkit/client/workers.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" ) +// WorkerInfo contains information about a worker type WorkerInfo struct { ID string Labels map[string]string @@ -18,6 +19,7 @@ type WorkerInfo struct { GCPolicy []PruneInfo } +// ListWorkers lists all active workers func (c *Client) ListWorkers(ctx context.Context, opts ...ListWorkersOption) ([]*WorkerInfo, error) { info := &ListWorkersInfo{} for _, o := range opts { @@ -44,10 +46,12 @@ func (c *Client) ListWorkers(ctx context.Context, opts ...ListWorkersOption) ([] return wi, nil } +// ListWorkersOption is an option for a worker list query type ListWorkersOption interface { SetListWorkersOption(*ListWorkersInfo) } +// ListWorkersInfo is a payload for worker list query type ListWorkersInfo struct { Filter []string } diff --git a/vendor/github.com/moby/buildkit/control/control.go b/vendor/github.com/moby/buildkit/control/control.go index 8b3b7bd8ac03a..96862ed680c12 100644 --- a/vendor/github.com/moby/buildkit/control/control.go +++ b/vendor/github.com/moby/buildkit/control/control.go @@ -127,7 +127,7 @@ func (c *Controller) Prune(req *controlapi.PruneRequest, stream controlapi.Contr ReleaseUnreferenced() error }); ok { if err := c.ReleaseUnreferenced(); err != nil { - logrus.Errorf("failed to release cache metadata: %+v") + logrus.Errorf("failed to release cache metadata: %+v", err) } } } diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go index cdb0d28ab3d9a..fbf827182124d 100644 --- a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go +++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" "syscall" + "time" "github.com/containerd/containerd/contrib/seccomp" "github.com/containerd/containerd/mount" @@ -88,7 +89,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex Command: cmd, Log: filepath.Join(root, "runc-log.json"), LogFormat: runc.JSON, - PdeathSignal: syscall.SIGKILL, + PdeathSignal: syscall.SIGKILL, // this can still leak the process Setpgid: true, // we don't execute runc with --rootless=(true|false) explicitly, // so as to support non-runc runtimes @@ -220,16 +221,43 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache. return err } - forwardIO, err := newForwardIO(stdin, stdout, stderr) - if err != nil { - return errors.Wrap(err, "creating new forwarding IO") - } - defer forwardIO.Close() + // runCtx/killCtx is used for extra check in case the kill command blocks + runCtx, cancelRun := context.WithCancel(context.Background()) + defer cancelRun() + + done := make(chan struct{}) + go func() { + for { + select { + case <-ctx.Done(): + killCtx, timeout := context.WithTimeout(context.Background(), 7*time.Second) + if err := w.runc.Kill(killCtx, id, int(syscall.SIGKILL), nil); err != nil { + logrus.Errorf("failed to kill runc %s: %+v", id, err) + select { + case <-killCtx.Done(): + timeout() + cancelRun() + return + default: + } + } + timeout() + select { + case <-time.After(50 * time.Millisecond): + case <-done: + return + } + case <-done: + return + } + } + }() logrus.Debugf("> creating %s %v", id, meta.Args) - status, err := w.runc.Run(ctx, id, bundle, &runc.CreateOpts{ - IO: forwardIO, + status, err := w.runc.Run(runCtx, id, bundle, &runc.CreateOpts{ + IO: &forwardIO{stdin: stdin, stdout: stdout, stderr: stderr}, }) + close(done) if err != nil { return err } @@ -242,57 +270,11 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache. } type forwardIO struct { - stdin, stdout, stderr *os.File - toRelease []io.Closer - toClose []io.Closer -} - -func newForwardIO(stdin io.ReadCloser, stdout, stderr io.WriteCloser) (f *forwardIO, err error) { - fio := &forwardIO{} - defer func() { - if err != nil { - fio.Close() - } - }() - if stdin != nil { - fio.stdin, err = fio.readCloserToFile(stdin) - if err != nil { - return nil, err - } - } - if stdout != nil { - fio.stdout, err = fio.writeCloserToFile(stdout) - if err != nil { - return nil, err - } - } - if stderr != nil { - fio.stderr, err = fio.writeCloserToFile(stderr) - if err != nil { - return nil, err - } - } - return fio, nil + stdin io.ReadCloser + stdout, stderr io.WriteCloser } func (s *forwardIO) Close() error { - s.CloseAfterStart() - var err error - for _, cl := range s.toClose { - if err1 := cl.Close(); err == nil { - err = err1 - } - } - s.toClose = nil - return err -} - -// release releases active FDs if the process doesn't need them any more -func (s *forwardIO) CloseAfterStart() error { - for _, cl := range s.toRelease { - cl.Close() - } - s.toRelease = nil return nil } @@ -302,46 +284,6 @@ func (s *forwardIO) Set(cmd *exec.Cmd) { cmd.Stderr = s.stderr } -func (s *forwardIO) readCloserToFile(rc io.ReadCloser) (*os.File, error) { - if f, ok := rc.(*os.File); ok { - return f, nil - } - pr, pw, err := os.Pipe() - if err != nil { - return nil, err - } - s.toClose = append(s.toClose, pw) - s.toRelease = append(s.toRelease, pr) - go func() { - _, err := io.Copy(pw, rc) - if err1 := pw.Close(); err == nil { - err = err1 - } - _ = err - }() - return pr, nil -} - -func (s *forwardIO) writeCloserToFile(wc io.WriteCloser) (*os.File, error) { - if f, ok := wc.(*os.File); ok { - return f, nil - } - pr, pw, err := os.Pipe() - if err != nil { - return nil, err - } - s.toClose = append(s.toClose, pr) - s.toRelease = append(s.toRelease, pw) - go func() { - _, err := io.Copy(wc, pr) - if err1 := pw.Close(); err == nil { - err = err1 - } - _ = err - }() - return pw, nil -} - func (s *forwardIO) Stdin() io.WriteCloser { return nil } diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go index 19d017dabcc3a..b2fe8b29370dd 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go @@ -23,6 +23,7 @@ import ( "github.com/moby/buildkit/frontend/dockerfile/shell" gw "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/solver/pb" + "github.com/moby/buildkit/util/system" specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -133,8 +134,12 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } ds.platform = &p } + allDispatchStates.addState(ds) - total := 1 + total := 0 + if ds.stage.BaseName != emptyImageName && ds.base == nil { + total = 1 + } for _, cmd := range ds.stage.Commands { switch cmd.(type) { case *instructions.AddCommand, *instructions.CopyCommand, *instructions.RunCommand: @@ -143,7 +148,6 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, } ds.cmdTotal = total - allDispatchStates.addState(ds) if opt.IgnoreCache != nil { if len(opt.IgnoreCache) == 0 { ds.ignoreCache = true @@ -215,10 +219,15 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, d.stage.BaseName = reference.TagNameOnly(ref).String() var isScratch bool if metaResolver != nil && reachable && !d.unregistered { + prefix := "[" + if opt.PrefixPlatform && platform != nil { + prefix += platforms.Format(*platform) + " " + } + prefix += "internal]" dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, gw.ResolveImageConfigOpt{ Platform: platform, ResolveMode: opt.ImageResolveMode.String(), - LogName: fmt.Sprintf("[internal] load metadata for %s", d.stage.BaseName), + LogName: fmt.Sprintf("%s load metadata for %s", prefix, d.stage.BaseName), }) if err == nil { // handle the error while builder is actually running var img Image @@ -242,6 +251,13 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, _ = ref if len(img.RootFS.DiffIDs) == 0 { isScratch = true + // schema1 images can't return diffIDs so double check :( + for _, h := range img.History { + if !h.EmptyLayer { + isScratch = false + break + } + } } } } @@ -274,6 +290,11 @@ func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, d.image = clone(d.base.image) } + // make sure that PATH is always set + if _, ok := shell.BuildEnvs(d.image.Config.Env)["PATH"]; !ok { + d.image.Config.Env = append(d.image.Config.Env, "PATH="+system.DefaultPathEnv) + } + // initialize base metadata from image conf for _, env := range d.image.Config.Env { k, v := parseKeyValue(env) @@ -689,16 +710,17 @@ func dispatchCopy(d *dispatchState, c instructions.SourcesAndDest, sourceState l args = append(args[:1], append([]string{"--unpack"}, args[1:]...)...) } - runOpt := []llb.RunOption{llb.Args(args), llb.Dir("/dest"), llb.ReadonlyRootFS(), dfCmd(cmdToPrint), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), d.state.Env())), d.prefixPlatform, d.state.GetPlatform()))} + platform := opt.targetPlatform + if d.platform != nil { + platform = *d.platform + } + + runOpt := []llb.RunOption{llb.Args(args), llb.Dir("/dest"), llb.ReadonlyRootFS(), dfCmd(cmdToPrint), llb.WithCustomName(prefixCommand(d, uppercaseCmd(processCmdEnv(opt.shlex, cmdToPrint.String(), d.state.Env())), d.prefixPlatform, &platform))} if d.ignoreCache { runOpt = append(runOpt, llb.IgnoreCache) } run := img.Run(append(runOpt, mounts...)...) - d.state = run.AddMount("/dest", d.state).Platform(opt.targetPlatform) - - if d.platform != nil { - d.state = d.state.Platform(*d.platform) - } + d.state = run.AddMount("/dest", d.state).Platform(platform) return commitToHistory(&d.image, commitMessage.String(), true, &d.state) } diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go index c726b15c03134..e42c8614e279d 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert_runmount.go @@ -78,9 +78,12 @@ func dispatchRunMounts(d *dispatchState, c *instructions.RunCommand, sources []* } mountOpts = append(mountOpts, llb.AsPersistentCacheDir(opt.cacheIDNamespace+"/"+mount.CacheID, sharing)) } - target := path.Join("/", mount.Target) + target := mount.Target + if !filepath.IsAbs(filepath.Clean(mount.Target)) { + target = filepath.Join("/", d.state.GetDir(), mount.Target) + } if target == "/" { - return nil, errors.Errorf("invalid mount target %q", mount.Target) + return nil, errors.Errorf("invalid mount target %q", target) } if src := path.Join("/", mount.Source); src != "/" { mountOpts = append(mountOpts, llb.SourcePath(src)) diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go index 6085d1e4d20af..e83e58b657a51 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/image.go @@ -29,6 +29,7 @@ type HealthConfig struct { Retries int `json:",omitempty"` } +// ImageConfig is a docker compatible config for an image type ImageConfig struct { specs.ImageConfig diff --git a/vendor/github.com/moby/buildkit/session/grpchijack/hijack.go b/vendor/github.com/moby/buildkit/session/grpchijack/hijack.go index 6e34b2164e9f3..096a9e806f2f2 100644 --- a/vendor/github.com/moby/buildkit/session/grpchijack/hijack.go +++ b/vendor/github.com/moby/buildkit/session/grpchijack/hijack.go @@ -7,6 +7,7 @@ import ( "google.golang.org/grpc/metadata" ) +// Hijack hijacks session to a connection. func Hijack(stream controlapi.Control_SessionServer) (net.Conn, <-chan struct{}, map[string][]string) { md, _ := metadata.FromIncomingContext(stream.Context()) c, closeCh := streamToConn(stream) diff --git a/vendor/github.com/moby/buildkit/session/sshforward/copy.go b/vendor/github.com/moby/buildkit/session/sshforward/copy.go new file mode 100644 index 0000000000000..c101f3b4558fb --- /dev/null +++ b/vendor/github.com/moby/buildkit/session/sshforward/copy.go @@ -0,0 +1,61 @@ +package sshforward + +import ( + io "io" + + context "golang.org/x/net/context" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" +) + +func Copy(ctx context.Context, conn io.ReadWriteCloser, stream grpc.Stream) error { + g, ctx := errgroup.WithContext(ctx) + + g.Go(func() (retErr error) { + p := &BytesMessage{} + for { + if err := stream.RecvMsg(p); err != nil { + if err == io.EOF { + return nil + } + conn.Close() + return err + } + select { + case <-ctx.Done(): + conn.Close() + return ctx.Err() + default: + } + if _, err := conn.Write(p.Data); err != nil { + conn.Close() + return err + } + p.Data = p.Data[:0] + } + }) + + g.Go(func() (retErr error) { + for { + buf := make([]byte, 32*1024) + n, err := conn.Read(buf) + switch { + case err == io.EOF: + return nil + case err != nil: + return err + } + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + p := &BytesMessage{Data: buf[:n]} + if err := stream.SendMsg(p); err != nil { + return err + } + } + }) + + return g.Wait() +} diff --git a/vendor/github.com/moby/buildkit/session/sshforward/generate.go b/vendor/github.com/moby/buildkit/session/sshforward/generate.go new file mode 100644 index 0000000000000..feecc7743c25a --- /dev/null +++ b/vendor/github.com/moby/buildkit/session/sshforward/generate.go @@ -0,0 +1,3 @@ +package sshforward + +//go:generate protoc --gogoslick_out=plugins=grpc:. ssh.proto diff --git a/vendor/github.com/moby/buildkit/session/sshforward/ssh.go b/vendor/github.com/moby/buildkit/session/sshforward/ssh.go new file mode 100644 index 0000000000000..a4effef604a2e --- /dev/null +++ b/vendor/github.com/moby/buildkit/session/sshforward/ssh.go @@ -0,0 +1,113 @@ +package sshforward + +import ( + "io/ioutil" + "net" + "os" + "path/filepath" + + "github.com/moby/buildkit/session" + context "golang.org/x/net/context" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc/metadata" +) + +// DefaultID is the default ssh ID +const DefaultID = "default" + +const KeySSHID = "buildkit.ssh.id" + +type server struct { + caller session.Caller +} + +func (s *server) run(ctx context.Context, l net.Listener, id string) error { + eg, ctx := errgroup.WithContext(ctx) + + eg.Go(func() error { + <-ctx.Done() + return ctx.Err() + }) + + eg.Go(func() error { + for { + conn, err := l.Accept() + if err != nil { + return err + } + + client := NewSSHClient(s.caller.Conn()) + + opts := make(map[string][]string) + opts[KeySSHID] = []string{id} + ctx = metadata.NewOutgoingContext(ctx, opts) + + stream, err := client.ForwardAgent(ctx) + if err != nil { + conn.Close() + return err + } + + go Copy(ctx, conn, stream) + } + }) + + return eg.Wait() +} + +type SocketOpt struct { + ID string + UID int + GID int + Mode int +} + +func MountSSHSocket(ctx context.Context, c session.Caller, opt SocketOpt) (sockPath string, closer func() error, err error) { + dir, err := ioutil.TempDir("", ".buildkit-ssh-sock") + if err != nil { + return "", nil, err + } + + defer func() { + if err != nil { + os.RemoveAll(dir) + } + }() + + sockPath = filepath.Join(dir, "ssh_auth_sock") + + l, err := net.Listen("unix", sockPath) + if err != nil { + return "", nil, err + } + + if err := os.Chown(sockPath, opt.UID, opt.GID); err != nil { + l.Close() + return "", nil, err + } + if err := os.Chmod(sockPath, os.FileMode(opt.Mode)); err != nil { + l.Close() + return "", nil, err + } + + s := &server{caller: c} + + id := opt.ID + if id == "" { + id = DefaultID + } + + go s.run(ctx, l, id) // erroring per connection allowed + + return sockPath, func() error { + err := l.Close() + os.RemoveAll(sockPath) + return err + }, nil +} + +func CheckSSHID(ctx context.Context, c session.Caller, id string) error { + client := NewSSHClient(c.Conn()) + _, err := client.CheckAgent(ctx, &CheckAgentRequest{ID: id}) + return err +} diff --git a/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go b/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go new file mode 100644 index 0000000000000..3fb36c9d34ac6 --- /dev/null +++ b/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go @@ -0,0 +1,816 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ssh.proto + +/* +Package sshforward is a generated protocol buffer package. + +It is generated from these files: + ssh.proto + +It has these top-level messages: + BytesMessage + CheckAgentRequest + CheckAgentResponse +*/ +package sshforward + +import proto "github.com/gogo/protobuf/proto" +import fmt "fmt" +import math "math" + +import bytes "bytes" + +import strings "strings" +import reflect "reflect" + +import context "golang.org/x/net/context" +import grpc "google.golang.org/grpc" + +import io "io" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package + +// BytesMessage contains a chunk of byte data +type BytesMessage struct { + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (m *BytesMessage) Reset() { *m = BytesMessage{} } +func (*BytesMessage) ProtoMessage() {} +func (*BytesMessage) Descriptor() ([]byte, []int) { return fileDescriptorSsh, []int{0} } + +func (m *BytesMessage) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +type CheckAgentRequest struct { + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` +} + +func (m *CheckAgentRequest) Reset() { *m = CheckAgentRequest{} } +func (*CheckAgentRequest) ProtoMessage() {} +func (*CheckAgentRequest) Descriptor() ([]byte, []int) { return fileDescriptorSsh, []int{1} } + +func (m *CheckAgentRequest) GetID() string { + if m != nil { + return m.ID + } + return "" +} + +type CheckAgentResponse struct { +} + +func (m *CheckAgentResponse) Reset() { *m = CheckAgentResponse{} } +func (*CheckAgentResponse) ProtoMessage() {} +func (*CheckAgentResponse) Descriptor() ([]byte, []int) { return fileDescriptorSsh, []int{2} } + +func init() { + proto.RegisterType((*BytesMessage)(nil), "moby.sshforward.v1.BytesMessage") + proto.RegisterType((*CheckAgentRequest)(nil), "moby.sshforward.v1.CheckAgentRequest") + proto.RegisterType((*CheckAgentResponse)(nil), "moby.sshforward.v1.CheckAgentResponse") +} +func (this *BytesMessage) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BytesMessage) + if !ok { + that2, ok := that.(BytesMessage) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + return true +} +func (this *CheckAgentRequest) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*CheckAgentRequest) + if !ok { + that2, ok := that.(CheckAgentRequest) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.ID != that1.ID { + return false + } + return true +} +func (this *CheckAgentResponse) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*CheckAgentResponse) + if !ok { + that2, ok := that.(CheckAgentResponse) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *BytesMessage) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&sshforward.BytesMessage{") + s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *CheckAgentRequest) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 5) + s = append(s, "&sshforward.CheckAgentRequest{") + s = append(s, "ID: "+fmt.Sprintf("%#v", this.ID)+",\n") + s = append(s, "}") + return strings.Join(s, "") +} +func (this *CheckAgentResponse) GoString() string { + if this == nil { + return "nil" + } + s := make([]string, 0, 4) + s = append(s, "&sshforward.CheckAgentResponse{") + s = append(s, "}") + return strings.Join(s, "") +} +func valueToGoStringSsh(v interface{}, typ string) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for SSH service + +type SSHClient interface { + CheckAgent(ctx context.Context, in *CheckAgentRequest, opts ...grpc.CallOption) (*CheckAgentResponse, error) + ForwardAgent(ctx context.Context, opts ...grpc.CallOption) (SSH_ForwardAgentClient, error) +} + +type sSHClient struct { + cc *grpc.ClientConn +} + +func NewSSHClient(cc *grpc.ClientConn) SSHClient { + return &sSHClient{cc} +} + +func (c *sSHClient) CheckAgent(ctx context.Context, in *CheckAgentRequest, opts ...grpc.CallOption) (*CheckAgentResponse, error) { + out := new(CheckAgentResponse) + err := grpc.Invoke(ctx, "/moby.sshforward.v1.SSH/CheckAgent", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *sSHClient) ForwardAgent(ctx context.Context, opts ...grpc.CallOption) (SSH_ForwardAgentClient, error) { + stream, err := grpc.NewClientStream(ctx, &_SSH_serviceDesc.Streams[0], c.cc, "/moby.sshforward.v1.SSH/ForwardAgent", opts...) + if err != nil { + return nil, err + } + x := &sSHForwardAgentClient{stream} + return x, nil +} + +type SSH_ForwardAgentClient interface { + Send(*BytesMessage) error + Recv() (*BytesMessage, error) + grpc.ClientStream +} + +type sSHForwardAgentClient struct { + grpc.ClientStream +} + +func (x *sSHForwardAgentClient) Send(m *BytesMessage) error { + return x.ClientStream.SendMsg(m) +} + +func (x *sSHForwardAgentClient) Recv() (*BytesMessage, error) { + m := new(BytesMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// Server API for SSH service + +type SSHServer interface { + CheckAgent(context.Context, *CheckAgentRequest) (*CheckAgentResponse, error) + ForwardAgent(SSH_ForwardAgentServer) error +} + +func RegisterSSHServer(s *grpc.Server, srv SSHServer) { + s.RegisterService(&_SSH_serviceDesc, srv) +} + +func _SSH_CheckAgent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckAgentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SSHServer).CheckAgent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/moby.sshforward.v1.SSH/CheckAgent", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SSHServer).CheckAgent(ctx, req.(*CheckAgentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _SSH_ForwardAgent_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SSHServer).ForwardAgent(&sSHForwardAgentServer{stream}) +} + +type SSH_ForwardAgentServer interface { + Send(*BytesMessage) error + Recv() (*BytesMessage, error) + grpc.ServerStream +} + +type sSHForwardAgentServer struct { + grpc.ServerStream +} + +func (x *sSHForwardAgentServer) Send(m *BytesMessage) error { + return x.ServerStream.SendMsg(m) +} + +func (x *sSHForwardAgentServer) Recv() (*BytesMessage, error) { + m := new(BytesMessage) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _SSH_serviceDesc = grpc.ServiceDesc{ + ServiceName: "moby.sshforward.v1.SSH", + HandlerType: (*SSHServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CheckAgent", + Handler: _SSH_CheckAgent_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "ForwardAgent", + Handler: _SSH_ForwardAgent_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "ssh.proto", +} + +func (m *BytesMessage) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BytesMessage) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Data) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintSsh(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + return i, nil +} + +func (m *CheckAgentRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CheckAgentRequest) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.ID) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintSsh(dAtA, i, uint64(len(m.ID))) + i += copy(dAtA[i:], m.ID) + } + return i, nil +} + +func (m *CheckAgentResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *CheckAgentResponse) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func encodeVarintSsh(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func (m *BytesMessage) Size() (n int) { + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovSsh(uint64(l)) + } + return n +} + +func (m *CheckAgentRequest) Size() (n int) { + var l int + _ = l + l = len(m.ID) + if l > 0 { + n += 1 + l + sovSsh(uint64(l)) + } + return n +} + +func (m *CheckAgentResponse) Size() (n int) { + var l int + _ = l + return n +} + +func sovSsh(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozSsh(x uint64) (n int) { + return sovSsh(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (this *BytesMessage) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&BytesMessage{`, + `Data:` + fmt.Sprintf("%v", this.Data) + `,`, + `}`, + }, "") + return s +} +func (this *CheckAgentRequest) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CheckAgentRequest{`, + `ID:` + fmt.Sprintf("%v", this.ID) + `,`, + `}`, + }, "") + return s +} +func (this *CheckAgentResponse) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&CheckAgentResponse{`, + `}`, + }, "") + return s +} +func valueToStringSsh(v interface{}) string { + rv := reflect.ValueOf(v) + if rv.IsNil() { + return "nil" + } + pv := reflect.Indirect(rv).Interface() + return fmt.Sprintf("*%v", pv) +} +func (m *BytesMessage) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSsh + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BytesMessage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BytesMessage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSsh + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthSsh + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipSsh(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthSsh + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CheckAgentRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSsh + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CheckAgentRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CheckAgentRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSsh + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthSsh + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipSsh(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthSsh + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *CheckAgentResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowSsh + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: CheckAgentResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: CheckAgentResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipSsh(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthSsh + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipSsh(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSsh + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSsh + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSsh + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthSsh + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowSsh + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipSsh(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthSsh = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowSsh = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("ssh.proto", fileDescriptorSsh) } + +var fileDescriptorSsh = []byte{ + // 243 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2c, 0x2e, 0xce, 0xd0, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xca, 0xcd, 0x4f, 0xaa, 0xd4, 0x2b, 0x2e, 0xce, 0x48, + 0xcb, 0x2f, 0x2a, 0x4f, 0x2c, 0x4a, 0xd1, 0x2b, 0x33, 0x54, 0x52, 0xe2, 0xe2, 0x71, 0xaa, 0x2c, + 0x49, 0x2d, 0xf6, 0x4d, 0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x15, 0x12, 0xe2, 0x62, 0x49, 0x49, 0x2c, + 0x49, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x09, 0x02, 0xb3, 0x95, 0x94, 0xb9, 0x04, 0x9d, 0x33, + 0x52, 0x93, 0xb3, 0x1d, 0xd3, 0x53, 0xf3, 0x4a, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x84, + 0xf8, 0xb8, 0x98, 0x3c, 0x5d, 0xc0, 0xca, 0x38, 0x83, 0x98, 0x3c, 0x5d, 0x94, 0x44, 0xb8, 0x84, + 0x90, 0x15, 0x15, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x1a, 0xed, 0x62, 0xe4, 0x62, 0x0e, 0x0e, 0xf6, + 0x10, 0x8a, 0xe6, 0xe2, 0x42, 0xc8, 0x0a, 0xa9, 0xea, 0x61, 0xba, 0x44, 0x0f, 0xc3, 0x0a, 0x29, + 0x35, 0x42, 0xca, 0x20, 0x96, 0x08, 0x85, 0x71, 0xf1, 0xb8, 0x41, 0x14, 0x40, 0x8c, 0x57, 0xc0, + 0xa6, 0x0f, 0xd9, 0x97, 0x52, 0x04, 0x55, 0x68, 0x30, 0x1a, 0x30, 0x3a, 0x59, 0x5c, 0x78, 0x28, + 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f, 0xe4, 0x18, 0x57, 0x3c, + 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x5f, + 0x3c, 0x92, 0x63, 0xf8, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x28, 0x2e, 0x84, 0x69, + 0x49, 0x6c, 0xe0, 0x00, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x31, 0x3e, 0x40, 0xab, 0x7d, + 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/moby/buildkit/session/sshforward/ssh.proto b/vendor/github.com/moby/buildkit/session/sshforward/ssh.proto new file mode 100644 index 0000000000000..99f63436a610d --- /dev/null +++ b/vendor/github.com/moby/buildkit/session/sshforward/ssh.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package moby.sshforward.v1; + +option go_package = "sshforward"; + +service SSH { + rpc CheckAgent(CheckAgentRequest) returns (CheckAgentResponse); + rpc ForwardAgent(stream BytesMessage) returns (stream BytesMessage); +} + +// BytesMessage contains a chunk of byte data +message BytesMessage{ + bytes data = 1; +} + +message CheckAgentRequest { + string ID = 1; +} + +message CheckAgentResponse { +} \ No newline at end of file diff --git a/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go b/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go index e91241b7b648e..d6861ae5d6051 100644 --- a/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go +++ b/vendor/github.com/moby/buildkit/snapshot/blobmapping/snapshotter.go @@ -3,13 +3,13 @@ package blobmapping import ( "context" - "github.com/boltdb/bolt" "github.com/containerd/containerd/content" "github.com/containerd/containerd/snapshots" "github.com/moby/buildkit/cache/metadata" "github.com/moby/buildkit/snapshot" digest "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" ) const blobKey = "blobmapping.blob" diff --git a/vendor/github.com/moby/buildkit/solver/boltdbcachestorage/storage.go b/vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go similarity index 99% rename from vendor/github.com/moby/buildkit/solver/boltdbcachestorage/storage.go rename to vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go index 0b38fe8610c72..19755816cd5ae 100644 --- a/vendor/github.com/moby/buildkit/solver/boltdbcachestorage/storage.go +++ b/vendor/github.com/moby/buildkit/solver/bboltcachestorage/storage.go @@ -1,14 +1,14 @@ -package boltdbcachestorage +package bboltcachestorage import ( "bytes" "encoding/json" "fmt" - "github.com/boltdb/bolt" "github.com/moby/buildkit/solver" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) const ( diff --git a/vendor/github.com/moby/buildkit/solver/cachemanager.go b/vendor/github.com/moby/buildkit/solver/cachemanager.go index 1c7a1ada679a2..ce41aa791b303 100644 --- a/vendor/github.com/moby/buildkit/solver/cachemanager.go +++ b/vendor/github.com/moby/buildkit/solver/cachemanager.go @@ -10,12 +10,12 @@ import ( "github.com/sirupsen/logrus" ) -type CacheID string - +// NewInMemoryCacheManager creates a new in-memory cache manager func NewInMemoryCacheManager() CacheManager { return NewCacheManager(identity.NewID(), NewInMemoryCacheStorage(), NewInMemoryResultStorage()) } +// NewCacheManager creates a new cache manager with specific storage backend func NewCacheManager(id string, storage CacheKeyStorage, results CacheResultStorage) CacheManager { cm := &cacheManager{ id: id, diff --git a/vendor/github.com/moby/buildkit/solver/jobs.go b/vendor/github.com/moby/buildkit/solver/jobs.go index 15dcde8847f43..66a9a51621ff0 100644 --- a/vendor/github.com/moby/buildkit/solver/jobs.go +++ b/vendor/github.com/moby/buildkit/solver/jobs.go @@ -26,7 +26,7 @@ type Builder interface { // Solver provides a shared graph of all the vertexes currently being // processed. Every vertex that is being solved needs to be loaded into job -// first. Vertex operations are invoked and progress tracking happends through +// first. Vertex operations are invoked and progress tracking happens through // jobs. type Solver struct { mu sync.RWMutex @@ -444,6 +444,7 @@ func (j *Job) Discard() error { j.pw.Close() for k, st := range j.list.actives { + st.mu.Lock() if _, ok := st.jobs[j]; ok { delete(st.jobs, j) j.list.deleteIfUnreferenced(k, st) @@ -451,6 +452,7 @@ func (j *Job) Discard() error { if _, ok := st.allPw[j.pw]; ok { delete(st.allPw, j.pw) } + st.mu.Unlock() } return nil } diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go index b5725706124d3..5894417deb004 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go @@ -7,6 +7,7 @@ import ( "strings" "sync" + "github.com/containerd/containerd/platforms" "github.com/docker/distribution/reference" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/remotecache" @@ -49,7 +50,7 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (res * func(ref string) { cm = newLazyCacheManager(ref, func() (solver.CacheManager, error) { var cmNew solver.CacheManager - if err := inVertexContext(b.builder.Context(ctx), "importing cache manifest from "+ref, func(ctx context.Context) error { + if err := inVertexContext(b.builder.Context(ctx), "importing cache manifest from "+ref, "", func(ctx context.Context) error { if b.resolveCacheImporter == nil { return errors.New("no cache importer is available") } @@ -143,7 +144,13 @@ func (s *llbBridge) ResolveImageConfig(ctx context.Context, ref string, opt gw.R if opt.LogName == "" { opt.LogName = fmt.Sprintf("resolve image config for %s", ref) } - err = inVertexContext(s.builder.Context(ctx), opt.LogName, func(ctx context.Context) error { + id := ref // make a deterministic ID for avoiding duplicates + if platform := opt.Platform; platform == nil { + id += platforms.Format(platforms.DefaultSpec()) + } else { + id += platforms.Format(*platform) + } + err = inVertexContext(s.builder.Context(ctx), opt.LogName, id, func(ctx context.Context) error { dgst, config, err = w.ResolveImageConfig(ctx, ref, opt) return err }) diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go index 3abb82c7ac61b..ee9c3af7bfb3f 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec.go @@ -16,7 +16,6 @@ import ( "sync" "time" - "github.com/boltdb/bolt" "github.com/containerd/containerd/mount" "github.com/docker/docker/pkg/locker" "github.com/moby/buildkit/cache" @@ -26,6 +25,7 @@ import ( "github.com/moby/buildkit/identity" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/secrets" + "github.com/moby/buildkit/session/sshforward" "github.com/moby/buildkit/snapshot" "github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver/llbsolver" @@ -36,6 +36,9 @@ import ( "github.com/opencontainers/runc/libcontainer/system" "github.com/pkg/errors" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) const execCacheType = "buildkit.exec.v0" @@ -279,6 +282,85 @@ func (e *execOp) getRefCacheDirNoCache(ctx context.Context, key string, ref cach return mRef, nil } +func (e *execOp) getSSHMountable(ctx context.Context, m *pb.Mount) (cache.Mountable, error) { + sessionID := session.FromContext(ctx) + if sessionID == "" { + return nil, errors.New("could not access local files without session") + } + + timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + caller, err := e.sm.Get(timeoutCtx, sessionID) + if err != nil { + return nil, err + } + + if err := sshforward.CheckSSHID(ctx, caller, m.SSHOpt.ID); err != nil { + if m.SSHOpt.Optional { + return nil, nil + } + if st, ok := status.FromError(err); ok && st.Code() == codes.Unimplemented { + return nil, errors.Errorf("no ssh forwarded from the client") + } + return nil, err + } + + return &sshMount{mount: m, caller: caller}, nil +} + +type sshMount struct { + mount *pb.Mount + caller session.Caller +} + +func (sm *sshMount) Mount(ctx context.Context, readonly bool) (snapshot.Mountable, error) { + return &sshMountInstance{sm: sm}, nil +} + +type sshMountInstance struct { + sm *sshMount + cleanup func() error +} + +func (sm *sshMountInstance) Mount() ([]mount.Mount, error) { + ctx, cancel := context.WithCancel(context.TODO()) + + sock, cleanup, err := sshforward.MountSSHSocket(ctx, sm.sm.caller, sshforward.SocketOpt{ + ID: sm.sm.mount.SSHOpt.ID, + UID: int(sm.sm.mount.SSHOpt.Uid), + GID: int(sm.sm.mount.SSHOpt.Gid), + Mode: int(sm.sm.mount.SSHOpt.Mode), + }) + if err != nil { + cancel() + return nil, err + } + sm.cleanup = func() error { + var err error + if cleanup != nil { + err = cleanup() + } + cancel() + return err + } + + return []mount.Mount{{ + Type: "bind", + Source: sock, + Options: []string{"rbind"}, + }}, nil +} + +func (sm *sshMountInstance) Release() error { + if sm.cleanup != nil { + if err := sm.cleanup(); err != nil { + return err + } + } + return nil +} + func (e *execOp) getSecretMountable(ctx context.Context, m *pb.Mount) (cache.Mountable, error) { if m.SecretOpt == nil { return nil, errors.Errorf("invalid sercet mount options") @@ -482,6 +564,17 @@ func (e *execOp) Exec(ctx context.Context, inputs []solver.Result) ([]solver.Res continue } mountable = secretMount + + case pb.MountType_SSH: + sshMount, err := e.getSSHMountable(ctx, m) + if err != nil { + return nil, err + } + if sshMount == nil { + continue + } + mountable = sshMount + default: return nil, errors.Errorf("mount type %s not implemented", m.MountType) } diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go b/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go index bedbac09d3c75..6b258d92d48d3 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/solver.go @@ -168,7 +168,7 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest inp.Refs = m } - if err := inVertexContext(j.Context(ctx), exp.Name(), func(ctx context.Context) error { + if err := inVertexContext(j.Context(ctx), exp.Name(), "", func(ctx context.Context) error { exporterResponse, err = exp.Export(ctx, inp) return err }); err != nil { @@ -177,7 +177,7 @@ func (s *Solver) Solve(ctx context.Context, id string, req frontend.SolveRequest } if e := exp.CacheExporter; e != nil { - if err := inVertexContext(j.Context(ctx), "exporting cache", func(ctx context.Context) error { + if err := inVertexContext(j.Context(ctx), "exporting cache", "", func(ctx context.Context) error { prepareDone := oneOffProgress(ctx, "preparing build cache for export") if err := res.EachRef(func(res solver.CachedResult) error { // all keys have same export chain so exporting others is not needed @@ -243,9 +243,12 @@ func oneOffProgress(ctx context.Context, id string) func(err error) error { } } -func inVertexContext(ctx context.Context, name string, f func(ctx context.Context) error) error { +func inVertexContext(ctx context.Context, name, id string, f func(ctx context.Context) error) error { + if id == "" { + id = identity.NewID() + } v := client.Vertex{ - Digest: digest.FromBytes([]byte(identity.NewID())), + Digest: digest.FromBytes([]byte(id)), Name: name, } pw, _, ctx := progress.FromContext(ctx, progress.WithMetadata("vertex", v.Digest)) diff --git a/vendor/github.com/moby/buildkit/solver/pb/const.go b/vendor/github.com/moby/buildkit/solver/pb/const.go index 2cb9951082e83..c2d20b29f2044 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/const.go +++ b/vendor/github.com/moby/buildkit/solver/pb/const.go @@ -1,12 +1,25 @@ package pb +// InputIndex is incrementing index to the input vertex type InputIndex int64 + +// OutputIndex is incrementing index that another vertex can depend on type OutputIndex int64 +// RootMount is a base mountpoint const RootMount = "/" + +// SkipOutput marks a disabled output index const SkipOutput OutputIndex = -1 + +// Empty marks an input with no content const Empty InputIndex = -1 + +// LLBBuilder is a special builder for BuildOp that directly builds LLB const LLBBuilder InputIndex = -1 +// LLBDefinitionInput marks an input that contains LLB definition for BuildOp const LLBDefinitionInput = "buildkit.llb.definition" + +// LLBDefaultDefinitionFile is a filename containing the definition in LLBBuilder const LLBDefaultDefinitionFile = LLBDefinitionInput diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go b/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go index 7a78618b72de3..fd97675db7178 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go +++ b/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go @@ -19,6 +19,7 @@ Mount CacheOpt SecretOpt + SSHOpt CopyOp CopySource SourceOp @@ -41,6 +42,8 @@ import _ "github.com/gogo/protobuf/gogoproto" import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest" import github_com_moby_buildkit_util_apicaps "github.com/moby/buildkit/util/apicaps" +import sortkeys "github.com/gogo/protobuf/sortkeys" + import io "io" // Reference imports to suppress errors if they are not otherwise used. @@ -512,6 +515,7 @@ type Mount struct { MountType MountType `protobuf:"varint,6,opt,name=mountType,proto3,enum=pb.MountType" json:"mountType,omitempty"` CacheOpt *CacheOpt `protobuf:"bytes,20,opt,name=cacheOpt" json:"cacheOpt,omitempty"` SecretOpt *SecretOpt `protobuf:"bytes,21,opt,name=secretOpt" json:"secretOpt,omitempty"` + SSHOpt *SSHOpt `protobuf:"bytes,22,opt,name=SSHOpt" json:"SSHOpt,omitempty"` } func (m *Mount) Reset() { *m = Mount{} } @@ -561,6 +565,13 @@ func (m *Mount) GetSecretOpt() *SecretOpt { return nil } +func (m *Mount) GetSSHOpt() *SSHOpt { + if m != nil { + return m.SSHOpt + } + return nil +} + // CacheOpt defines options specific to cache mounts type CacheOpt struct { // ID is an optional namespace for the mount @@ -643,6 +654,61 @@ func (m *SecretOpt) GetOptional() bool { return false } +// SSHOpt defines options describing secret mounts +type SSHOpt struct { + // ID of exposed ssh rule. Used for quering the value. + ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"` + // UID of agent socket + Uid uint32 `protobuf:"varint,2,opt,name=uid,proto3" json:"uid,omitempty"` + // GID of agent socket + Gid uint32 `protobuf:"varint,3,opt,name=gid,proto3" json:"gid,omitempty"` + // Mode is the filesystem mode of agent socket + Mode uint32 `protobuf:"varint,4,opt,name=mode,proto3" json:"mode,omitempty"` + // Optional defines if ssh socket is required. Error is produced + // if client does not expose ssh. + Optional bool `protobuf:"varint,5,opt,name=optional,proto3" json:"optional,omitempty"` +} + +func (m *SSHOpt) Reset() { *m = SSHOpt{} } +func (m *SSHOpt) String() string { return proto.CompactTextString(m) } +func (*SSHOpt) ProtoMessage() {} +func (*SSHOpt) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{8} } + +func (m *SSHOpt) GetID() string { + if m != nil { + return m.ID + } + return "" +} + +func (m *SSHOpt) GetUid() uint32 { + if m != nil { + return m.Uid + } + return 0 +} + +func (m *SSHOpt) GetGid() uint32 { + if m != nil { + return m.Gid + } + return 0 +} + +func (m *SSHOpt) GetMode() uint32 { + if m != nil { + return m.Mode + } + return 0 +} + +func (m *SSHOpt) GetOptional() bool { + if m != nil { + return m.Optional + } + return false +} + // CopyOp copies files across Ops. type CopyOp struct { Src []*CopySource `protobuf:"bytes,1,rep,name=src" json:"src,omitempty"` @@ -652,7 +718,7 @@ type CopyOp struct { func (m *CopyOp) Reset() { *m = CopyOp{} } func (m *CopyOp) String() string { return proto.CompactTextString(m) } func (*CopyOp) ProtoMessage() {} -func (*CopyOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{8} } +func (*CopyOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{9} } func (m *CopyOp) GetSrc() []*CopySource { if m != nil { @@ -677,7 +743,7 @@ type CopySource struct { func (m *CopySource) Reset() { *m = CopySource{} } func (m *CopySource) String() string { return proto.CompactTextString(m) } func (*CopySource) ProtoMessage() {} -func (*CopySource) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{9} } +func (*CopySource) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{10} } func (m *CopySource) GetSelector() string { if m != nil { @@ -698,7 +764,7 @@ type SourceOp struct { func (m *SourceOp) Reset() { *m = SourceOp{} } func (m *SourceOp) String() string { return proto.CompactTextString(m) } func (*SourceOp) ProtoMessage() {} -func (*SourceOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{10} } +func (*SourceOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{11} } func (m *SourceOp) GetIdentifier() string { if m != nil { @@ -726,7 +792,7 @@ type BuildOp struct { func (m *BuildOp) Reset() { *m = BuildOp{} } func (m *BuildOp) String() string { return proto.CompactTextString(m) } func (*BuildOp) ProtoMessage() {} -func (*BuildOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{11} } +func (*BuildOp) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{12} } func (m *BuildOp) GetInputs() map[string]*BuildInput { if m != nil { @@ -757,7 +823,7 @@ type BuildInput struct { func (m *BuildInput) Reset() { *m = BuildInput{} } func (m *BuildInput) String() string { return proto.CompactTextString(m) } func (*BuildInput) ProtoMessage() {} -func (*BuildInput) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{12} } +func (*BuildInput) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{13} } // OpMetadata is a per-vertex metadata entry, which can be defined for arbitrary Op vertex and overridable on the run time. type OpMetadata struct { @@ -774,7 +840,7 @@ type OpMetadata struct { func (m *OpMetadata) Reset() { *m = OpMetadata{} } func (m *OpMetadata) String() string { return proto.CompactTextString(m) } func (*OpMetadata) ProtoMessage() {} -func (*OpMetadata) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{13} } +func (*OpMetadata) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{14} } func (m *OpMetadata) GetIgnoreCache() bool { if m != nil { @@ -811,7 +877,7 @@ type ExportCache struct { func (m *ExportCache) Reset() { *m = ExportCache{} } func (m *ExportCache) String() string { return proto.CompactTextString(m) } func (*ExportCache) ProtoMessage() {} -func (*ExportCache) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{14} } +func (*ExportCache) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{15} } func (m *ExportCache) GetValue() bool { if m != nil { @@ -830,7 +896,7 @@ type ProxyEnv struct { func (m *ProxyEnv) Reset() { *m = ProxyEnv{} } func (m *ProxyEnv) String() string { return proto.CompactTextString(m) } func (*ProxyEnv) ProtoMessage() {} -func (*ProxyEnv) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{15} } +func (*ProxyEnv) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{16} } func (m *ProxyEnv) GetHttpProxy() string { if m != nil { @@ -868,7 +934,7 @@ type WorkerConstraints struct { func (m *WorkerConstraints) Reset() { *m = WorkerConstraints{} } func (m *WorkerConstraints) String() string { return proto.CompactTextString(m) } func (*WorkerConstraints) ProtoMessage() {} -func (*WorkerConstraints) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{16} } +func (*WorkerConstraints) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{17} } func (m *WorkerConstraints) GetFilter() []string { if m != nil { @@ -889,7 +955,7 @@ type Definition struct { func (m *Definition) Reset() { *m = Definition{} } func (m *Definition) String() string { return proto.CompactTextString(m) } func (*Definition) ProtoMessage() {} -func (*Definition) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{17} } +func (*Definition) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{18} } func (m *Definition) GetDef() [][]byte { if m != nil { @@ -913,7 +979,7 @@ type HostIP struct { func (m *HostIP) Reset() { *m = HostIP{} } func (m *HostIP) String() string { return proto.CompactTextString(m) } func (*HostIP) ProtoMessage() {} -func (*HostIP) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{18} } +func (*HostIP) Descriptor() ([]byte, []int) { return fileDescriptorOps, []int{19} } func (m *HostIP) GetHost() string { if m != nil { @@ -938,6 +1004,7 @@ func init() { proto.RegisterType((*Mount)(nil), "pb.Mount") proto.RegisterType((*CacheOpt)(nil), "pb.CacheOpt") proto.RegisterType((*SecretOpt)(nil), "pb.SecretOpt") + proto.RegisterType((*SSHOpt)(nil), "pb.SSHOpt") proto.RegisterType((*CopyOp)(nil), "pb.CopyOp") proto.RegisterType((*CopySource)(nil), "pb.CopySource") proto.RegisterType((*SourceOp)(nil), "pb.SourceOp") @@ -1355,6 +1422,18 @@ func (m *Mount) MarshalTo(dAtA []byte) (int, error) { } i += n11 } + if m.SSHOpt != nil { + dAtA[i] = 0xb2 + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintOps(dAtA, i, uint64(m.SSHOpt.Size())) + n12, err := m.SSHOpt.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n12 + } return i, nil } @@ -1436,6 +1515,55 @@ func (m *SecretOpt) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func (m *SSHOpt) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SSHOpt) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.ID) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintOps(dAtA, i, uint64(len(m.ID))) + i += copy(dAtA[i:], m.ID) + } + if m.Uid != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintOps(dAtA, i, uint64(m.Uid)) + } + if m.Gid != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintOps(dAtA, i, uint64(m.Gid)) + } + if m.Mode != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintOps(dAtA, i, uint64(m.Mode)) + } + if m.Optional { + dAtA[i] = 0x28 + i++ + if m.Optional { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + return i, nil +} + func (m *CopyOp) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1523,10 +1651,15 @@ func (m *SourceOp) MarshalTo(dAtA []byte) (int, error) { i += copy(dAtA[i:], m.Identifier) } if len(m.Attrs) > 0 { + keysForAttrs := make([]string, 0, len(m.Attrs)) for k, _ := range m.Attrs { + keysForAttrs = append(keysForAttrs, string(k)) + } + sortkeys.Strings(keysForAttrs) + for _, k := range keysForAttrs { dAtA[i] = 0x12 i++ - v := m.Attrs[k] + v := m.Attrs[string(k)] mapSize := 1 + len(k) + sovOps(uint64(len(k))) + 1 + len(v) + sovOps(uint64(len(v))) i = encodeVarintOps(dAtA, i, uint64(mapSize)) dAtA[i] = 0xa @@ -1563,10 +1696,15 @@ func (m *BuildOp) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintOps(dAtA, i, uint64(m.Builder)) } if len(m.Inputs) > 0 { + keysForInputs := make([]string, 0, len(m.Inputs)) for k, _ := range m.Inputs { + keysForInputs = append(keysForInputs, string(k)) + } + sortkeys.Strings(keysForInputs) + for _, k := range keysForInputs { dAtA[i] = 0x12 i++ - v := m.Inputs[k] + v := m.Inputs[string(k)] msgSize := 0 if v != nil { msgSize = v.Size() @@ -1582,11 +1720,11 @@ func (m *BuildOp) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintOps(dAtA, i, uint64(v.Size())) - n12, err := v.MarshalTo(dAtA[i:]) + n13, err := v.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n12 + i += n13 } } } @@ -1594,17 +1732,22 @@ func (m *BuildOp) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x1a i++ i = encodeVarintOps(dAtA, i, uint64(m.Def.Size())) - n13, err := m.Def.MarshalTo(dAtA[i:]) + n14, err := m.Def.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n13 + i += n14 } if len(m.Attrs) > 0 { + keysForAttrs := make([]string, 0, len(m.Attrs)) for k, _ := range m.Attrs { + keysForAttrs = append(keysForAttrs, string(k)) + } + sortkeys.Strings(keysForAttrs) + for _, k := range keysForAttrs { dAtA[i] = 0x22 i++ - v := m.Attrs[k] + v := m.Attrs[string(k)] mapSize := 1 + len(k) + sovOps(uint64(len(k))) + 1 + len(v) + sovOps(uint64(len(v))) i = encodeVarintOps(dAtA, i, uint64(mapSize)) dAtA[i] = 0xa @@ -1669,10 +1812,15 @@ func (m *OpMetadata) MarshalTo(dAtA []byte) (int, error) { i++ } if len(m.Description) > 0 { + keysForDescription := make([]string, 0, len(m.Description)) for k, _ := range m.Description { + keysForDescription = append(keysForDescription, string(k)) + } + sortkeys.Strings(keysForDescription) + for _, k := range keysForDescription { dAtA[i] = 0x12 i++ - v := m.Description[k] + v := m.Description[string(k)] mapSize := 1 + len(k) + sovOps(uint64(len(k))) + 1 + len(v) + sovOps(uint64(len(v))) i = encodeVarintOps(dAtA, i, uint64(mapSize)) dAtA[i] = 0xa @@ -1689,17 +1837,22 @@ func (m *OpMetadata) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x22 i++ i = encodeVarintOps(dAtA, i, uint64(m.ExportCache.Size())) - n14, err := m.ExportCache.MarshalTo(dAtA[i:]) + n15, err := m.ExportCache.MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n14 + i += n15 } if len(m.Caps) > 0 { + keysForCaps := make([]string, 0, len(m.Caps)) for k, _ := range m.Caps { + keysForCaps = append(keysForCaps, string(k)) + } + sortkeys.Strings(keysForCaps) + for _, k := range keysForCaps { dAtA[i] = 0x2a i++ - v := m.Caps[k] + v := m.Caps[github_com_moby_buildkit_util_apicaps.CapID(k)] mapSize := 1 + len(k) + sovOps(uint64(len(k))) + 1 + 1 i = encodeVarintOps(dAtA, i, uint64(mapSize)) dAtA[i] = 0xa @@ -1846,10 +1999,15 @@ func (m *Definition) MarshalTo(dAtA []byte) (int, error) { } } if len(m.Metadata) > 0 { + keysForMetadata := make([]string, 0, len(m.Metadata)) for k, _ := range m.Metadata { + keysForMetadata = append(keysForMetadata, string(k)) + } + sortkeys.Strings(keysForMetadata) + for _, k := range keysForMetadata { dAtA[i] = 0x12 i++ - v := m.Metadata[k] + v := m.Metadata[github_com_opencontainers_go_digest.Digest(k)] msgSize := 0 if (&v) != nil { msgSize = (&v).Size() @@ -1864,11 +2022,11 @@ func (m *Definition) MarshalTo(dAtA []byte) (int, error) { dAtA[i] = 0x12 i++ i = encodeVarintOps(dAtA, i, uint64((&v).Size())) - n15, err := (&v).MarshalTo(dAtA[i:]) + n16, err := (&v).MarshalTo(dAtA[i:]) if err != nil { return 0, err } - i += n15 + i += n16 } } return i, nil @@ -2099,6 +2257,10 @@ func (m *Mount) Size() (n int) { l = m.SecretOpt.Size() n += 2 + l + sovOps(uint64(l)) } + if m.SSHOpt != nil { + l = m.SSHOpt.Size() + n += 2 + l + sovOps(uint64(l)) + } return n } @@ -2137,6 +2299,28 @@ func (m *SecretOpt) Size() (n int) { return n } +func (m *SSHOpt) Size() (n int) { + var l int + _ = l + l = len(m.ID) + if l > 0 { + n += 1 + l + sovOps(uint64(l)) + } + if m.Uid != 0 { + n += 1 + sovOps(uint64(m.Uid)) + } + if m.Gid != 0 { + n += 1 + sovOps(uint64(m.Gid)) + } + if m.Mode != 0 { + n += 1 + sovOps(uint64(m.Mode)) + } + if m.Optional { + n += 2 + } + return n +} + func (m *CopyOp) Size() (n int) { var l int _ = l @@ -3508,6 +3692,39 @@ func (m *Mount) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 22: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SSHOpt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOps + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SSHOpt == nil { + m.SSHOpt = &SSHOpt{} + } + if err := m.SSHOpt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipOps(dAtA[iNdEx:]) @@ -3783,6 +4000,162 @@ func (m *SecretOpt) Unmarshal(dAtA []byte) error { } return nil } +func (m *SSHOpt) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SSHOpt: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SSHOpt: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOps + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Uid", wireType) + } + m.Uid = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Uid |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Gid", wireType) + } + m.Gid = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Gid |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Mode", wireType) + } + m.Mode = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Mode |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Optional", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Optional = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipOps(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthOps + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *CopyOp) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -5663,94 +6036,96 @@ var ( func init() { proto.RegisterFile("ops.proto", fileDescriptorOps) } var fileDescriptorOps = []byte{ - // 1415 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6f, 0x1b, 0x45, - 0x14, 0x8f, 0xd7, 0x9f, 0xfb, 0x9c, 0xa4, 0x66, 0xfa, 0x81, 0x09, 0x25, 0x09, 0x5b, 0x40, 0x69, - 0xd2, 0x38, 0x92, 0x2b, 0xb5, 0x15, 0x87, 0x8a, 0xf8, 0xa3, 0x8a, 0x29, 0x89, 0xa3, 0x71, 0x08, - 0xc7, 0x6a, 0xb3, 0x1e, 0x3b, 0xab, 0x38, 0x3b, 0xab, 0xdd, 0x71, 0x1b, 0x5f, 0x38, 0xf4, 0x2f, - 0x40, 0x42, 0xe2, 0xce, 0x91, 0x0b, 0xff, 0x01, 0xf7, 0x1e, 0xb9, 0xc2, 0xa1, 0xa0, 0xf2, 0x8f, - 0xa0, 0xf7, 0x66, 0xd6, 0xbb, 0xfd, 0x40, 0xb4, 0x82, 0x93, 0xdf, 0xbc, 0xf7, 0x9b, 0xdf, 0xcc, - 0xfc, 0xde, 0x9b, 0x79, 0x6b, 0xb0, 0x65, 0x18, 0x37, 0xc2, 0x48, 0x2a, 0xc9, 0xac, 0xf0, 0x64, - 0x65, 0x7b, 0xec, 0xab, 0xd3, 0xe9, 0x49, 0xc3, 0x93, 0xe7, 0x3b, 0x63, 0x39, 0x96, 0x3b, 0x14, - 0x3a, 0x99, 0x8e, 0x68, 0x44, 0x03, 0xb2, 0xf4, 0x14, 0xe7, 0x47, 0x0b, 0xac, 0x7e, 0xc8, 0x3e, - 0x86, 0x92, 0x1f, 0x84, 0x53, 0x15, 0xd7, 0x73, 0xeb, 0xf9, 0x8d, 0x6a, 0xd3, 0x6e, 0x84, 0x27, - 0x8d, 0x1e, 0x7a, 0xb8, 0x09, 0xb0, 0x75, 0x28, 0x88, 0x0b, 0xe1, 0xd5, 0xad, 0xf5, 0xdc, 0x46, - 0xb5, 0x09, 0x08, 0xe8, 0x5e, 0x08, 0xaf, 0x1f, 0xee, 0x2d, 0x70, 0x8a, 0xb0, 0xcf, 0xa0, 0x14, - 0xcb, 0x69, 0xe4, 0x89, 0x7a, 0x9e, 0x30, 0x8b, 0x88, 0x19, 0x90, 0x87, 0x50, 0x26, 0x8a, 0x4c, - 0x9e, 0x0c, 0x67, 0xf5, 0x42, 0xca, 0xd4, 0x96, 0xe1, 0x4c, 0x33, 0x61, 0x84, 0xdd, 0x80, 0xe2, - 0xc9, 0xd4, 0x9f, 0x0c, 0xeb, 0x45, 0x82, 0x54, 0x11, 0xd2, 0x42, 0x07, 0x61, 0x74, 0x8c, 0x6d, - 0x40, 0x25, 0x9c, 0xb8, 0x6a, 0x24, 0xa3, 0xf3, 0x3a, 0xa4, 0x0b, 0x1e, 0x1a, 0x1f, 0x9f, 0x47, - 0xd9, 0x5d, 0xa8, 0x7a, 0x32, 0x88, 0x55, 0xe4, 0xfa, 0x81, 0x8a, 0xeb, 0x55, 0x02, 0x5f, 0x45, - 0xf0, 0x37, 0x32, 0x3a, 0x13, 0x51, 0x3b, 0x0d, 0xf2, 0x2c, 0xb2, 0x55, 0x00, 0x4b, 0x86, 0xce, - 0x0f, 0x39, 0xa8, 0x24, 0xac, 0xcc, 0x81, 0xc5, 0xdd, 0xc8, 0x3b, 0xf5, 0x95, 0xf0, 0xd4, 0x34, - 0x12, 0xf5, 0xdc, 0x7a, 0x6e, 0xc3, 0xe6, 0x2f, 0xf9, 0xd8, 0x32, 0x58, 0xfd, 0x01, 0x09, 0x65, - 0x73, 0xab, 0x3f, 0x60, 0x75, 0x28, 0x1f, 0xbb, 0x91, 0xef, 0x06, 0x8a, 0x94, 0xb1, 0x79, 0x32, - 0x64, 0xd7, 0xc1, 0xee, 0x0f, 0x8e, 0x45, 0x14, 0xfb, 0x32, 0x20, 0x3d, 0x6c, 0x9e, 0x3a, 0xd8, - 0x2a, 0x40, 0x7f, 0xf0, 0x40, 0xb8, 0x48, 0x1a, 0xd7, 0x8b, 0xeb, 0xf9, 0x0d, 0x9b, 0x67, 0x3c, - 0xce, 0xb7, 0x50, 0xa4, 0x1c, 0xb1, 0x2f, 0xa1, 0x34, 0xf4, 0xc7, 0x22, 0x56, 0x7a, 0x3b, 0xad, - 0xe6, 0xb3, 0xe7, 0x6b, 0x0b, 0xbf, 0x3f, 0x5f, 0xdb, 0xcc, 0x14, 0x83, 0x0c, 0x45, 0xe0, 0xc9, - 0x40, 0xb9, 0x7e, 0x20, 0xa2, 0x78, 0x67, 0x2c, 0xb7, 0xf5, 0x94, 0x46, 0x87, 0x7e, 0xb8, 0x61, - 0x60, 0x37, 0xa1, 0xe8, 0x07, 0x43, 0x71, 0x41, 0xfb, 0xcf, 0xb7, 0x2e, 0x1b, 0xaa, 0x6a, 0x7f, - 0xaa, 0xc2, 0xa9, 0xea, 0x61, 0x88, 0x6b, 0x84, 0x13, 0x42, 0x49, 0x97, 0x00, 0xbb, 0x0e, 0x85, - 0x73, 0xa1, 0x5c, 0x5a, 0xbe, 0xda, 0xac, 0xa0, 0xb4, 0xfb, 0x42, 0xb9, 0x9c, 0xbc, 0x58, 0x5d, - 0xe7, 0x72, 0x8a, 0xd2, 0x5b, 0x69, 0x75, 0xed, 0xa3, 0x87, 0x9b, 0x00, 0xfb, 0x14, 0xca, 0x81, - 0x50, 0x4f, 0x64, 0x74, 0x46, 0x12, 0x2d, 0xeb, 0x9c, 0x1f, 0x08, 0xb5, 0x2f, 0x87, 0x82, 0x27, - 0x31, 0xe7, 0xa7, 0x1c, 0x14, 0x90, 0x98, 0x31, 0x28, 0xb8, 0xd1, 0x58, 0x97, 0xab, 0xcd, 0xc9, - 0x66, 0x35, 0xc8, 0x8b, 0xe0, 0x31, 0xad, 0x61, 0x73, 0x34, 0xd1, 0xe3, 0x3d, 0x19, 0x1a, 0xd1, - 0xd1, 0xc4, 0x79, 0xd3, 0x58, 0x44, 0x46, 0x6b, 0xb2, 0xd9, 0x4d, 0xb0, 0xc3, 0x48, 0x5e, 0xcc, - 0x1e, 0xe1, 0xec, 0x62, 0xa6, 0x92, 0xd0, 0xd9, 0x0d, 0x1e, 0xf3, 0x4a, 0x68, 0x2c, 0xb6, 0x09, - 0x20, 0x2e, 0x54, 0xe4, 0xee, 0xc9, 0x58, 0xc5, 0xf5, 0x12, 0x9d, 0x86, 0x0a, 0x18, 0x1d, 0xbd, - 0x43, 0x9e, 0x89, 0x3a, 0x3f, 0x5b, 0x50, 0xa4, 0x43, 0xb2, 0x0d, 0x94, 0x34, 0x9c, 0xea, 0xec, - 0xe4, 0x5b, 0xcc, 0x48, 0x0a, 0x94, 0xbc, 0xb9, 0xa2, 0x98, 0xc8, 0x15, 0xa8, 0xc4, 0x62, 0x22, - 0x3c, 0x25, 0x23, 0x53, 0x3f, 0xf3, 0x31, 0x6e, 0x7d, 0x88, 0x29, 0xd6, 0xa7, 0x21, 0x9b, 0x6d, - 0x41, 0x49, 0x52, 0x5e, 0xe8, 0x40, 0xff, 0x90, 0x2d, 0x03, 0x41, 0xf2, 0x48, 0xb8, 0x43, 0x19, - 0x4c, 0x66, 0x74, 0xcc, 0x0a, 0x9f, 0x8f, 0xd9, 0x16, 0xd8, 0x94, 0x89, 0xa3, 0x59, 0x28, 0xea, - 0x25, 0xca, 0xc0, 0xd2, 0x3c, 0x4b, 0xe8, 0xe4, 0x69, 0x1c, 0x6f, 0x9e, 0xe7, 0x7a, 0xa7, 0xa2, - 0x1f, 0xaa, 0xfa, 0x95, 0x54, 0xaf, 0xb6, 0xf1, 0xf1, 0x79, 0x14, 0x69, 0x63, 0xe1, 0x45, 0x42, - 0x21, 0xf4, 0x2a, 0x41, 0x89, 0x76, 0x90, 0x38, 0x79, 0x1a, 0x77, 0x7a, 0x50, 0x49, 0x28, 0xf0, - 0x0a, 0xf5, 0x3a, 0xe6, 0x72, 0x59, 0xbd, 0x0e, 0xdb, 0x86, 0x72, 0x7c, 0xea, 0x46, 0x7e, 0x30, - 0x26, 0x5d, 0x96, 0x9b, 0x97, 0xe7, 0x2b, 0x0e, 0xb4, 0x1f, 0xc9, 0x12, 0x8c, 0x23, 0xc1, 0x9e, - 0x2f, 0xf1, 0x1a, 0x57, 0x0d, 0xf2, 0x53, 0x7f, 0x48, 0x3c, 0x4b, 0x1c, 0x4d, 0xf4, 0x8c, 0x7d, - 0x5d, 0x27, 0x4b, 0x1c, 0x4d, 0x14, 0xfb, 0x5c, 0x0e, 0x05, 0xc9, 0xba, 0xc4, 0xc9, 0x46, 0xfd, - 0x64, 0xa8, 0x7c, 0x19, 0xb8, 0x93, 0x44, 0xbf, 0x64, 0xec, 0xdc, 0x87, 0x92, 0x7e, 0xc3, 0xd8, - 0x3a, 0xe4, 0xe3, 0xc8, 0x33, 0xef, 0xe8, 0x72, 0xf2, 0xb8, 0xe9, 0x67, 0x90, 0x63, 0x68, 0x9e, - 0x48, 0x2b, 0x4d, 0xa4, 0xc3, 0x01, 0x52, 0xd8, 0xff, 0x53, 0x30, 0xce, 0xf7, 0x39, 0xa8, 0x24, - 0xcf, 0x2f, 0xbe, 0x25, 0xfe, 0x50, 0x04, 0xca, 0x1f, 0xf9, 0x22, 0x32, 0x62, 0x64, 0x3c, 0x6c, - 0x1b, 0x8a, 0xae, 0x52, 0x51, 0x72, 0x45, 0xdf, 0xcf, 0xbe, 0xdd, 0x8d, 0x5d, 0x8c, 0x74, 0x03, - 0x15, 0xcd, 0xb8, 0x46, 0xad, 0xdc, 0x03, 0x48, 0x9d, 0xa8, 0xdf, 0x99, 0x98, 0x19, 0x56, 0x34, - 0xd9, 0x15, 0x28, 0x3e, 0x76, 0x27, 0x53, 0x61, 0x36, 0xa5, 0x07, 0x9f, 0x5b, 0xf7, 0x72, 0xce, - 0x2f, 0x16, 0x94, 0xcd, 0x5b, 0xce, 0x6e, 0x41, 0x99, 0xde, 0x72, 0xb3, 0xa3, 0x37, 0x9f, 0x34, - 0x81, 0xb0, 0x9d, 0x79, 0x93, 0xca, 0xec, 0xd1, 0x50, 0xe9, 0x66, 0x65, 0xf6, 0x98, 0xb6, 0xac, - 0xfc, 0x50, 0x8c, 0x4c, 0x37, 0xa2, 0x54, 0x74, 0xc4, 0xc8, 0x0f, 0x7c, 0xcc, 0x19, 0xc7, 0x10, - 0xbb, 0x95, 0x9c, 0xba, 0x40, 0x8c, 0xd7, 0xb2, 0x8c, 0xaf, 0x1f, 0xba, 0x07, 0xd5, 0xcc, 0x32, - 0x6f, 0x38, 0xf5, 0x27, 0xd9, 0x53, 0x9b, 0x25, 0x89, 0x4e, 0xb7, 0xd2, 0x54, 0x85, 0xff, 0xa0, - 0xdf, 0x1d, 0x80, 0x94, 0xf2, 0xed, 0x2b, 0xc5, 0x79, 0x9a, 0x07, 0xe8, 0x87, 0xf8, 0x78, 0x0e, - 0x5d, 0x7a, 0x93, 0x17, 0xfd, 0x71, 0x20, 0x23, 0xf1, 0x88, 0x2e, 0x2b, 0xcd, 0xaf, 0xf0, 0xaa, - 0xf6, 0xd1, 0xbd, 0x62, 0xbb, 0x50, 0x1d, 0x8a, 0xd8, 0x8b, 0x7c, 0x2a, 0x72, 0x23, 0xfa, 0x1a, - 0x9e, 0x29, 0xe5, 0x69, 0x74, 0x52, 0x84, 0xd6, 0x2a, 0x3b, 0x87, 0x35, 0x61, 0x51, 0x5c, 0x84, - 0x32, 0x52, 0x66, 0x15, 0xdd, 0xf2, 0x2f, 0xe9, 0x8f, 0x07, 0xf4, 0xd3, 0x4a, 0xbc, 0x2a, 0xd2, - 0x01, 0x73, 0xa1, 0xe0, 0xb9, 0xa1, 0xee, 0x77, 0xd5, 0x66, 0xfd, 0x95, 0xf5, 0xda, 0x6e, 0xa8, - 0x45, 0x6b, 0xdd, 0xc6, 0xb3, 0x3e, 0xfd, 0x63, 0x6d, 0x2b, 0xd3, 0xe4, 0xce, 0xe5, 0xc9, 0x6c, - 0x87, 0xea, 0xe5, 0xcc, 0x57, 0x3b, 0x53, 0xe5, 0x4f, 0x76, 0xdc, 0xd0, 0x47, 0x3a, 0x9c, 0xd8, - 0xeb, 0x70, 0xa2, 0x5e, 0xb9, 0x0f, 0xb5, 0x57, 0xf7, 0xfd, 0x2e, 0x39, 0x58, 0xb9, 0x0b, 0xf6, - 0x7c, 0x1f, 0xff, 0x36, 0xb1, 0x92, 0x4d, 0xde, 0x0d, 0xa8, 0x66, 0xce, 0x8d, 0xc0, 0x63, 0x02, - 0x6a, 0xf5, 0xf5, 0xc0, 0x79, 0x8a, 0xdf, 0x1b, 0x49, 0xc7, 0xf9, 0x08, 0xe0, 0x54, 0xa9, 0xf0, - 0x11, 0xb5, 0x20, 0xb3, 0x88, 0x8d, 0x1e, 0x42, 0xb0, 0x35, 0xa8, 0xe2, 0x20, 0x36, 0x71, 0xbd, - 0x53, 0x9a, 0x11, 0x6b, 0xc0, 0x87, 0x60, 0x8f, 0xe6, 0xd3, 0x75, 0xeb, 0xa8, 0x8c, 0x92, 0xd9, - 0x1f, 0x40, 0x25, 0x90, 0x26, 0xa6, 0x3b, 0x62, 0x39, 0x90, 0x14, 0x72, 0xb6, 0xe0, 0xbd, 0xd7, - 0x3e, 0x8e, 0xd8, 0x35, 0x28, 0x8d, 0xfc, 0x89, 0xa2, 0xeb, 0x8a, 0x4d, 0xd6, 0x8c, 0x9c, 0xdf, - 0x72, 0x00, 0xe9, 0xd5, 0x42, 0x45, 0xf0, 0xde, 0x21, 0x66, 0x51, 0xdf, 0xb3, 0x09, 0x54, 0xce, - 0x4d, 0x06, 0x4d, 0x1d, 0x5d, 0x7f, 0xf9, 0x3a, 0x36, 0x92, 0x04, 0xeb, 0xdc, 0x36, 0x4d, 0x6e, - 0xdf, 0xe5, 0x03, 0x66, 0xbe, 0xc2, 0xca, 0x43, 0x58, 0x7a, 0x89, 0xee, 0x2d, 0x6f, 0x6a, 0x5a, - 0x65, 0xd9, 0x94, 0xdd, 0x82, 0x92, 0x6e, 0xee, 0xf8, 0x6e, 0xa3, 0x65, 0x68, 0xc8, 0xa6, 0xde, - 0x72, 0x98, 0x7c, 0xea, 0xf5, 0x0e, 0x37, 0x37, 0xa0, 0x6c, 0x3e, 0x5a, 0x98, 0x0d, 0xc5, 0xaf, - 0x0f, 0x06, 0xdd, 0xa3, 0xda, 0x02, 0xab, 0x40, 0x61, 0xaf, 0x3f, 0x38, 0xaa, 0xe5, 0xd0, 0x3a, - 0xe8, 0x1f, 0x74, 0x6b, 0xd6, 0xe6, 0x17, 0x60, 0xcf, 0x9b, 0x2b, 0xba, 0x5b, 0xbd, 0x83, 0x4e, - 0x6d, 0x81, 0x01, 0x94, 0x06, 0xdd, 0x36, 0xef, 0x22, 0xb8, 0x0c, 0xf9, 0xc1, 0x60, 0xaf, 0x66, - 0x21, 0x55, 0x7b, 0xb7, 0xbd, 0xd7, 0xad, 0xe5, 0xd1, 0x3c, 0xda, 0x3f, 0x7c, 0x30, 0xa8, 0x15, - 0x36, 0xef, 0xc0, 0xa5, 0x57, 0x1a, 0x20, 0xcd, 0xde, 0xdb, 0xe5, 0x5d, 0x64, 0xaa, 0x42, 0xf9, - 0x90, 0xf7, 0x8e, 0x77, 0x8f, 0xba, 0xb5, 0x1c, 0x06, 0xbe, 0xea, 0xb7, 0x1f, 0x76, 0x3b, 0x35, - 0xab, 0x55, 0x7b, 0xf6, 0x62, 0x35, 0xf7, 0xeb, 0x8b, 0xd5, 0xdc, 0x9f, 0x2f, 0x56, 0x73, 0xdf, - 0xfd, 0xb5, 0xba, 0x70, 0x52, 0xa2, 0x3f, 0x03, 0xb7, 0xff, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x8c, - 0x1e, 0x1e, 0x98, 0x4c, 0x0c, 0x00, 0x00, + // 1444 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4b, 0x6f, 0x1b, 0x47, + 0x12, 0x16, 0x87, 0xcf, 0x29, 0x4a, 0x32, 0xb7, 0xfd, 0x58, 0xae, 0xd6, 0x2b, 0x69, 0xc7, 0xbb, + 0x81, 0x2c, 0x59, 0x14, 0x40, 0x03, 0xb6, 0x91, 0x83, 0x11, 0xf1, 0x61, 0x88, 0x71, 0x24, 0x0a, + 0x4d, 0x45, 0x39, 0x1a, 0xa3, 0x61, 0x93, 0x1a, 0x88, 0x9a, 0x1e, 0xcc, 0x34, 0x6d, 0xf1, 0x92, + 0x83, 0x7f, 0x41, 0x80, 0x00, 0xb9, 0xe7, 0x98, 0x1f, 0x91, 0xbb, 0x8f, 0x41, 0x4e, 0x49, 0x0e, + 0x4e, 0xa0, 0xfc, 0x91, 0xa0, 0xaa, 0x7b, 0x38, 0xe3, 0x47, 0x10, 0x1b, 0x09, 0x72, 0x62, 0x75, + 0xd5, 0xd7, 0x5f, 0xd7, 0xab, 0xbb, 0x86, 0x60, 0xcb, 0x30, 0x6e, 0x84, 0x91, 0x54, 0x92, 0x59, + 0xe1, 0xc9, 0xca, 0xf6, 0xd8, 0x57, 0xa7, 0xd3, 0x93, 0x86, 0x27, 0xcf, 0x77, 0xc6, 0x72, 0x2c, + 0x77, 0xc8, 0x74, 0x32, 0x1d, 0xd1, 0x8a, 0x16, 0x24, 0xe9, 0x2d, 0xce, 0xd7, 0x16, 0x58, 0xfd, + 0x90, 0xfd, 0x17, 0x4a, 0x7e, 0x10, 0x4e, 0x55, 0x5c, 0xcf, 0xad, 0xe7, 0x37, 0xaa, 0x4d, 0xbb, + 0x11, 0x9e, 0x34, 0x7a, 0xa8, 0xe1, 0xc6, 0xc0, 0xd6, 0xa1, 0x20, 0x2e, 0x84, 0x57, 0xb7, 0xd6, + 0x73, 0x1b, 0xd5, 0x26, 0x20, 0xa0, 0x7b, 0x21, 0xbc, 0x7e, 0xb8, 0xb7, 0xc0, 0xc9, 0xc2, 0x3e, + 0x80, 0x52, 0x2c, 0xa7, 0x91, 0x27, 0xea, 0x79, 0xc2, 0x2c, 0x22, 0x66, 0x40, 0x1a, 0x42, 0x19, + 0x2b, 0x32, 0x79, 0x32, 0x9c, 0xd5, 0x0b, 0x29, 0x53, 0x5b, 0x86, 0x33, 0xcd, 0x84, 0x16, 0x76, + 0x0b, 0x8a, 0x27, 0x53, 0x7f, 0x32, 0xac, 0x17, 0x09, 0x52, 0x45, 0x48, 0x0b, 0x15, 0x84, 0xd1, + 0x36, 0xb6, 0x01, 0x95, 0x70, 0xe2, 0xaa, 0x91, 0x8c, 0xce, 0xeb, 0x90, 0x1e, 0x78, 0x68, 0x74, + 0x7c, 0x6e, 0x65, 0xf7, 0xa1, 0xea, 0xc9, 0x20, 0x56, 0x91, 0xeb, 0x07, 0x2a, 0xae, 0x57, 0x09, + 0x7c, 0x1d, 0xc1, 0x9f, 0xc9, 0xe8, 0x4c, 0x44, 0xed, 0xd4, 0xc8, 0xb3, 0xc8, 0x56, 0x01, 0x2c, + 0x19, 0x3a, 0x5f, 0xe5, 0xa0, 0x92, 0xb0, 0x32, 0x07, 0x16, 0x77, 0x23, 0xef, 0xd4, 0x57, 0xc2, + 0x53, 0xd3, 0x48, 0xd4, 0x73, 0xeb, 0xb9, 0x0d, 0x9b, 0xbf, 0xa2, 0x63, 0xcb, 0x60, 0xf5, 0x07, + 0x94, 0x28, 0x9b, 0x5b, 0xfd, 0x01, 0xab, 0x43, 0xf9, 0xd8, 0x8d, 0x7c, 0x37, 0x50, 0x94, 0x19, + 0x9b, 0x27, 0x4b, 0x76, 0x13, 0xec, 0xfe, 0xe0, 0x58, 0x44, 0xb1, 0x2f, 0x03, 0xca, 0x87, 0xcd, + 0x53, 0x05, 0x5b, 0x05, 0xe8, 0x0f, 0x1e, 0x09, 0x17, 0x49, 0xe3, 0x7a, 0x71, 0x3d, 0xbf, 0x61, + 0xf3, 0x8c, 0xc6, 0xf9, 0x1c, 0x8a, 0x54, 0x23, 0xf6, 0x31, 0x94, 0x86, 0xfe, 0x58, 0xc4, 0x4a, + 0xbb, 0xd3, 0x6a, 0xbe, 0x78, 0xb9, 0xb6, 0xf0, 0xd3, 0xcb, 0xb5, 0xcd, 0x4c, 0x33, 0xc8, 0x50, + 0x04, 0x9e, 0x0c, 0x94, 0xeb, 0x07, 0x22, 0x8a, 0x77, 0xc6, 0x72, 0x5b, 0x6f, 0x69, 0x74, 0xe8, + 0x87, 0x1b, 0x06, 0x76, 0x1b, 0x8a, 0x7e, 0x30, 0x14, 0x17, 0xe4, 0x7f, 0xbe, 0x75, 0xd5, 0x50, + 0x55, 0xfb, 0x53, 0x15, 0x4e, 0x55, 0x0f, 0x4d, 0x5c, 0x23, 0x9c, 0x10, 0x4a, 0xba, 0x05, 0xd8, + 0x4d, 0x28, 0x9c, 0x0b, 0xe5, 0xd2, 0xf1, 0xd5, 0x66, 0x05, 0x53, 0xbb, 0x2f, 0x94, 0xcb, 0x49, + 0x8b, 0xdd, 0x75, 0x2e, 0xa7, 0x98, 0x7a, 0x2b, 0xed, 0xae, 0x7d, 0xd4, 0x70, 0x63, 0x60, 0xff, + 0x87, 0x72, 0x20, 0xd4, 0x33, 0x19, 0x9d, 0x51, 0x8a, 0x96, 0x75, 0xcd, 0x0f, 0x84, 0xda, 0x97, + 0x43, 0xc1, 0x13, 0x9b, 0xf3, 0x4d, 0x0e, 0x0a, 0x48, 0xcc, 0x18, 0x14, 0xdc, 0x68, 0xac, 0xdb, + 0xd5, 0xe6, 0x24, 0xb3, 0x1a, 0xe4, 0x45, 0xf0, 0x94, 0xce, 0xb0, 0x39, 0x8a, 0xa8, 0xf1, 0x9e, + 0x0d, 0x4d, 0xd2, 0x51, 0xc4, 0x7d, 0xd3, 0x58, 0x44, 0x26, 0xd7, 0x24, 0xb3, 0xdb, 0x60, 0x87, + 0x91, 0xbc, 0x98, 0x3d, 0xc1, 0xdd, 0xc5, 0x4c, 0x27, 0xa1, 0xb2, 0x1b, 0x3c, 0xe5, 0x95, 0xd0, + 0x48, 0x6c, 0x13, 0x40, 0x5c, 0xa8, 0xc8, 0xdd, 0x93, 0xb1, 0x8a, 0xeb, 0x25, 0x8a, 0x86, 0x1a, + 0x18, 0x15, 0xbd, 0x43, 0x9e, 0xb1, 0x3a, 0xdf, 0x5b, 0x50, 0xa4, 0x20, 0xd9, 0x06, 0xa6, 0x34, + 0x9c, 0xea, 0xea, 0xe4, 0x5b, 0xcc, 0xa4, 0x14, 0xa8, 0x78, 0xf3, 0x8c, 0x62, 0x21, 0x57, 0xa0, + 0x12, 0x8b, 0x89, 0xf0, 0x94, 0x8c, 0x4c, 0xff, 0xcc, 0xd7, 0xe8, 0xfa, 0x10, 0x4b, 0xac, 0xa3, + 0x21, 0x99, 0x6d, 0x41, 0x49, 0x52, 0x5d, 0x28, 0xa0, 0xdf, 0xa9, 0x96, 0x81, 0x20, 0x79, 0x24, + 0xdc, 0xa1, 0x0c, 0x26, 0x33, 0x0a, 0xb3, 0xc2, 0xe7, 0x6b, 0xb6, 0x05, 0x36, 0x55, 0xe2, 0x68, + 0x16, 0x8a, 0x7a, 0x89, 0x2a, 0xb0, 0x34, 0xaf, 0x12, 0x2a, 0x79, 0x6a, 0xc7, 0x9b, 0xe7, 0xb9, + 0xde, 0xa9, 0xe8, 0x87, 0xaa, 0x7e, 0x2d, 0xcd, 0x57, 0xdb, 0xe8, 0xf8, 0xdc, 0x8a, 0xb4, 0xb1, + 0xf0, 0x22, 0xa1, 0x10, 0x7a, 0x9d, 0xa0, 0x44, 0x3b, 0x48, 0x94, 0x3c, 0xb5, 0x33, 0x07, 0x4a, + 0x83, 0xc1, 0x1e, 0x22, 0x6f, 0xa4, 0x2f, 0x83, 0xd6, 0x70, 0x63, 0x71, 0x7a, 0x50, 0x49, 0x8e, + 0xc1, 0x6b, 0xd6, 0xeb, 0x98, 0x0b, 0x68, 0xf5, 0x3a, 0x6c, 0x1b, 0xca, 0xf1, 0xa9, 0x1b, 0xf9, + 0xc1, 0x98, 0x72, 0xb7, 0xdc, 0xbc, 0x3a, 0xf7, 0x6a, 0xa0, 0xf5, 0xc8, 0x94, 0x60, 0x1c, 0x09, + 0xf6, 0xdc, 0x8d, 0x37, 0xb8, 0x6a, 0x90, 0x9f, 0xfa, 0x43, 0xe2, 0x59, 0xe2, 0x28, 0xa2, 0x66, + 0xec, 0xeb, 0x5e, 0x5a, 0xe2, 0x28, 0x62, 0x41, 0xce, 0xe5, 0x50, 0x50, 0xea, 0x97, 0x38, 0xc9, + 0x98, 0x63, 0x19, 0x2a, 0x5f, 0x06, 0xee, 0x24, 0xc9, 0x71, 0xb2, 0x76, 0x26, 0x49, 0x7c, 0x7f, + 0xcb, 0x69, 0x0f, 0xa1, 0xa4, 0x5f, 0x55, 0xb6, 0x0e, 0xf9, 0x38, 0xf2, 0xcc, 0xcb, 0xbe, 0x9c, + 0x3c, 0xb7, 0xfa, 0x61, 0xe6, 0x68, 0x9a, 0xb7, 0x96, 0x95, 0xb6, 0x96, 0xc3, 0x01, 0x52, 0xd8, + 0x5f, 0xd3, 0xc2, 0xce, 0x97, 0x39, 0xa8, 0x24, 0x03, 0x01, 0x5f, 0x37, 0x7f, 0x28, 0x02, 0xe5, + 0x8f, 0x7c, 0x11, 0x99, 0x64, 0x64, 0x34, 0x6c, 0x1b, 0x8a, 0xae, 0x52, 0x51, 0xf2, 0x68, 0xfc, + 0x33, 0x3b, 0x4d, 0x1a, 0xbb, 0x68, 0xe9, 0x06, 0x2a, 0x9a, 0x71, 0x8d, 0x5a, 0x79, 0x00, 0x90, + 0x2a, 0x31, 0x7f, 0x67, 0x62, 0x66, 0x58, 0x51, 0x64, 0xd7, 0xa0, 0xf8, 0xd4, 0x9d, 0x4c, 0x85, + 0x71, 0x4a, 0x2f, 0x3e, 0xb4, 0x1e, 0xe4, 0x9c, 0x6f, 0x2d, 0x28, 0x9b, 0xe9, 0xc2, 0xee, 0x40, + 0x99, 0xa6, 0x8b, 0xf1, 0xe8, 0xed, 0x91, 0x26, 0x10, 0xb6, 0x33, 0x1f, 0x9b, 0x19, 0x1f, 0x0d, + 0x95, 0x1e, 0x9f, 0xc6, 0xc7, 0x74, 0x88, 0xe6, 0x87, 0x62, 0x64, 0xe6, 0x23, 0x95, 0xa2, 0x23, + 0x46, 0x7e, 0xe0, 0x63, 0xcd, 0x38, 0x9a, 0xd8, 0x9d, 0x24, 0xea, 0x02, 0x31, 0xde, 0xc8, 0x32, + 0xbe, 0x19, 0x74, 0x0f, 0xaa, 0x99, 0x63, 0xde, 0x12, 0xf5, 0xff, 0xb2, 0x51, 0x9b, 0x23, 0x89, + 0x4e, 0x0f, 0xf7, 0x34, 0x0b, 0x7f, 0x22, 0x7f, 0xf7, 0x00, 0x52, 0xca, 0x77, 0xef, 0x14, 0xe7, + 0x79, 0x1e, 0xa0, 0x1f, 0xe2, 0x73, 0x3e, 0x74, 0x69, 0x4a, 0x2c, 0xfa, 0xe3, 0x40, 0x46, 0xe2, + 0x09, 0x3d, 0x1f, 0xb4, 0xbf, 0xc2, 0xab, 0x5a, 0x47, 0xb7, 0x98, 0xed, 0x42, 0x75, 0x28, 0x62, + 0x2f, 0xf2, 0xa9, 0xc9, 0x4d, 0xd2, 0xd7, 0x30, 0xa6, 0x94, 0xa7, 0xd1, 0x49, 0x11, 0x3a, 0x57, + 0xd9, 0x3d, 0xac, 0x09, 0x8b, 0xe2, 0x22, 0x94, 0x91, 0x32, 0xa7, 0xe8, 0x8f, 0x90, 0x2b, 0xfa, + 0x73, 0x06, 0xf5, 0x74, 0x12, 0xaf, 0x8a, 0x74, 0xc1, 0x5c, 0x28, 0x78, 0x6e, 0xa8, 0x27, 0x70, + 0xb5, 0x59, 0x7f, 0xed, 0xbc, 0xb6, 0x1b, 0xea, 0xa4, 0xb5, 0xee, 0x62, 0xac, 0xcf, 0x7f, 0x5e, + 0xdb, 0xca, 0x8c, 0xdd, 0x73, 0x79, 0x32, 0xdb, 0xa1, 0x7e, 0x39, 0xf3, 0xd5, 0xce, 0x54, 0xf9, + 0x93, 0x1d, 0x37, 0xf4, 0x91, 0x0e, 0x37, 0xf6, 0x3a, 0x9c, 0xa8, 0x57, 0x1e, 0x42, 0xed, 0x75, + 0xbf, 0xdf, 0xa7, 0x06, 0x2b, 0xf7, 0xc1, 0x9e, 0xfb, 0xf1, 0x47, 0x1b, 0x2b, 0xd9, 0xe2, 0xdd, + 0x82, 0x6a, 0x26, 0x6e, 0x04, 0x1e, 0x13, 0x50, 0x67, 0x5f, 0x2f, 0x9c, 0xe7, 0xf8, 0x05, 0x94, + 0xcc, 0xc0, 0xff, 0x00, 0x9c, 0x2a, 0x15, 0x3e, 0xa1, 0xa1, 0x68, 0x0e, 0xb1, 0x51, 0x43, 0x08, + 0xb6, 0x06, 0x55, 0x5c, 0xc4, 0xc6, 0xae, 0x3d, 0xa5, 0x1d, 0xb1, 0x06, 0xfc, 0x1b, 0xec, 0xd1, + 0x7c, 0xbb, 0x1e, 0x66, 0x95, 0x51, 0xb2, 0xfb, 0x5f, 0x50, 0x09, 0xa4, 0xb1, 0xe9, 0x19, 0x5d, + 0x0e, 0x24, 0x99, 0x9c, 0x2d, 0xf8, 0xc7, 0x1b, 0x9f, 0x6b, 0xec, 0x06, 0x94, 0x46, 0xfe, 0x44, + 0xd1, 0x75, 0xc5, 0xb1, 0x6f, 0x56, 0xce, 0x8f, 0x39, 0x80, 0xf4, 0x6a, 0x61, 0x46, 0xf0, 0xde, + 0x21, 0x66, 0x51, 0xdf, 0xb3, 0x09, 0x54, 0xce, 0x4d, 0x05, 0x4d, 0x1f, 0xdd, 0x7c, 0xf5, 0x3a, + 0x36, 0x92, 0x02, 0xeb, 0xda, 0x36, 0x4d, 0x6d, 0xdf, 0xe7, 0x93, 0x6a, 0x7e, 0xc2, 0xca, 0x63, + 0x58, 0x7a, 0x85, 0xee, 0x1d, 0x6f, 0x6a, 0xda, 0x65, 0xd9, 0x92, 0xdd, 0x81, 0x92, 0xfe, 0xdc, + 0xc0, 0x77, 0x1b, 0x25, 0x43, 0x43, 0x32, 0xcd, 0x96, 0xc3, 0xe4, 0xe3, 0xb3, 0x77, 0xb8, 0xb9, + 0x01, 0x65, 0xf3, 0x19, 0xc5, 0x6c, 0x28, 0x7e, 0x7a, 0x30, 0xe8, 0x1e, 0xd5, 0x16, 0x58, 0x05, + 0x0a, 0x7b, 0xfd, 0xc1, 0x51, 0x2d, 0x87, 0xd2, 0x41, 0xff, 0xa0, 0x5b, 0xb3, 0x36, 0x3f, 0x02, + 0x7b, 0x3e, 0xee, 0x51, 0xdd, 0xea, 0x1d, 0x74, 0x6a, 0x0b, 0x0c, 0xa0, 0x34, 0xe8, 0xb6, 0x79, + 0x17, 0xc1, 0x65, 0xc8, 0x0f, 0x06, 0x7b, 0x35, 0x0b, 0xa9, 0xda, 0xbb, 0xed, 0xbd, 0x6e, 0x2d, + 0x8f, 0xe2, 0xd1, 0xfe, 0xe1, 0xa3, 0x41, 0xad, 0xb0, 0x79, 0x0f, 0xae, 0xbc, 0x36, 0x6e, 0x69, + 0xf7, 0xde, 0x2e, 0xef, 0x22, 0x53, 0x15, 0xca, 0x87, 0xbc, 0x77, 0xbc, 0x7b, 0xd4, 0xad, 0xe5, + 0xd0, 0xf0, 0x49, 0xbf, 0xfd, 0xb8, 0xdb, 0xa9, 0x59, 0xad, 0x6b, 0x2f, 0x2e, 0x57, 0x73, 0xdf, + 0x5d, 0xae, 0xe6, 0x7e, 0xb8, 0x5c, 0xcd, 0xfd, 0x72, 0xb9, 0x9a, 0xfb, 0xe2, 0xd7, 0xd5, 0x85, + 0x93, 0x12, 0xfd, 0x45, 0xb9, 0xfb, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0xfe, 0x08, 0x0c, + 0xe2, 0x0c, 0x00, 0x00, } diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops.proto b/vendor/github.com/moby/buildkit/solver/pb/ops.proto index 17b5506addff4..09442f60c4cb6 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/ops.proto +++ b/vendor/github.com/moby/buildkit/solver/pb/ops.proto @@ -6,6 +6,8 @@ package pb; import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +option (gogoproto.stable_marshaler_all) = true; + // Op represents a vertex of the LLB DAG. message Op { // inputs is a set of input edges. @@ -72,6 +74,7 @@ message Mount { MountType mountType = 6; CacheOpt cacheOpt = 20; SecretOpt secretOpt = 21; + SSHOpt SSHOpt = 22; } // MountType defines a type of a mount from a supported set @@ -116,6 +119,21 @@ message SecretOpt { bool optional = 5; } +// SSHOpt defines options describing secret mounts +message SSHOpt { + // ID of exposed ssh rule. Used for quering the value. + string ID = 1; + // UID of agent socket + uint32 uid = 2; + // GID of agent socket + uint32 gid = 3; + // Mode is the filesystem mode of agent socket + uint32 mode = 4; + // Optional defines if ssh socket is required. Error is produced + // if client does not expose ssh. + bool optional = 5; +} + // CopyOp copies files across Ops. message CopyOp { repeated CopySource src = 1; diff --git a/vendor/github.com/moby/buildkit/solver/scheduler.go b/vendor/github.com/moby/buildkit/solver/scheduler.go index d9ed9c587311f..7fe981eff4547 100644 --- a/vendor/github.com/moby/buildkit/solver/scheduler.go +++ b/vendor/github.com/moby/buildkit/solver/scheduler.go @@ -371,7 +371,7 @@ func debugSchedulerPreUnpark(e *edge, inc []pipe.Sender, updates, allPipes []pip if dep.req != nil { des = dep.req.Request().(*edgeRequest).desiredState } - logrus.Debugf(":: dep%d %s state=%s des=%s keys=%s hasslowcache=%v", i, e.edge.Vertex.Inputs()[i].Vertex.Name(), dep.state, des, len(dep.keys), e.slowCacheFunc(dep) != nil) + logrus.Debugf(":: dep%d %s state=%s des=%s keys=%d hasslowcache=%v", i, e.edge.Vertex.Inputs()[i].Vertex.Name(), dep.state, des, len(dep.keys), e.slowCacheFunc(dep) != nil) } for i, in := range inc { diff --git a/vendor/github.com/moby/buildkit/source/git/gitsource.go b/vendor/github.com/moby/buildkit/source/git/gitsource.go index c0afc3b8048f5..47d304b792350 100644 --- a/vendor/github.com/moby/buildkit/source/git/gitsource.go +++ b/vendor/github.com/moby/buildkit/source/git/gitsource.go @@ -11,7 +11,6 @@ import ( "regexp" "strings" - "github.com/boltdb/bolt" "github.com/docker/docker/pkg/locker" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/metadata" @@ -22,6 +21,7 @@ import ( "github.com/moby/buildkit/util/progress/logs" "github.com/pkg/errors" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" ) var validHex = regexp.MustCompile(`^[a-f0-9]{40}$`) diff --git a/vendor/github.com/moby/buildkit/source/http/httpsource.go b/vendor/github.com/moby/buildkit/source/http/httpsource.go index 58c70400989ca..39939128cd9e6 100644 --- a/vendor/github.com/moby/buildkit/source/http/httpsource.go +++ b/vendor/github.com/moby/buildkit/source/http/httpsource.go @@ -15,7 +15,6 @@ import ( "strings" "time" - "github.com/boltdb/bolt" "github.com/docker/docker/pkg/locker" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/metadata" @@ -24,6 +23,7 @@ import ( "github.com/moby/buildkit/util/tracing" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" + bolt "go.etcd.io/bbolt" ) type Opt struct { diff --git a/vendor/github.com/moby/buildkit/source/local/local.go b/vendor/github.com/moby/buildkit/source/local/local.go index b2deb5c15b63c..8ffe0c09ed361 100644 --- a/vendor/github.com/moby/buildkit/source/local/local.go +++ b/vendor/github.com/moby/buildkit/source/local/local.go @@ -6,7 +6,6 @@ import ( "fmt" "time" - "github.com/boltdb/bolt" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/contenthash" "github.com/moby/buildkit/cache/metadata" @@ -20,6 +19,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/tonistiigi/fsutil" + bolt "go.etcd.io/bbolt" "golang.org/x/time/rate" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" diff --git a/vendor/github.com/moby/buildkit/util/contentutil/copy.go b/vendor/github.com/moby/buildkit/util/contentutil/copy.go index a03f16e65e26f..04d46c4f36dc6 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/copy.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/copy.go @@ -3,10 +3,13 @@ package contentutil import ( "context" "io" + "sync" "github.com/containerd/containerd/content" + "github.com/containerd/containerd/images" "github.com/containerd/containerd/remotes" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" ) func Copy(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispec.Descriptor) error { @@ -41,3 +44,38 @@ func (r *rc) Read(b []byte) (int, error) { } return n, err } + +func CopyChain(ctx context.Context, ingester content.Ingester, provider content.Provider, desc ocispec.Descriptor) error { + var m sync.Mutex + manifestStack := []ocispec.Descriptor{} + + filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + switch desc.MediaType { + case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest, + images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: + m.Lock() + manifestStack = append(manifestStack, desc) + m.Unlock() + return nil, images.ErrStopHandler + default: + return nil, nil + } + }) + handlers := []images.Handler{ + images.ChildrenHandler(provider), + filterHandler, + remotes.FetchHandler(ingester, &localFetcher{provider}), + } + + if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil { + return errors.WithStack(err) + } + + for i := len(manifestStack) - 1; i >= 0; i-- { + if err := Copy(ctx, ingester, provider, manifestStack[i]); err != nil { + return errors.WithStack(err) + } + } + + return nil +} diff --git a/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go b/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go index 0c87e6476027a..d55c101219845 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go @@ -55,6 +55,9 @@ func (r *readerAt) ReadAt(b []byte, off int64) (int, error) { var totalN int for len(b) > 0 { n, err := r.Reader.Read(b) + if err == io.EOF && n == len(b) { + err = nil + } r.offset += int64(n) totalN += n b = b[n:] diff --git a/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go b/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go index fd635ad456967..3dafed7dc2adb 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" ) +// NewMultiProvider creates a new mutable provider with a base provider func NewMultiProvider(base content.Provider) *MultiProvider { return &MultiProvider{ base: base, @@ -18,12 +19,14 @@ func NewMultiProvider(base content.Provider) *MultiProvider { } } +// MultiProvider is a provider backed by a mutable map of providers type MultiProvider struct { mu sync.RWMutex base content.Provider sub map[digest.Digest]content.Provider } +// ReaderAt returns a content.ReaderAt func (mp *MultiProvider) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) { mp.mu.RLock() if p, ok := mp.sub[desc.Digest]; ok { @@ -37,6 +40,7 @@ func (mp *MultiProvider) ReaderAt(ctx context.Context, desc ocispec.Descriptor) return mp.base.ReaderAt(ctx, desc) } +// Add adds a new child provider for a specific digest func (mp *MultiProvider) Add(dgst digest.Digest, p content.Provider) { mp.mu.Lock() defer mp.mu.Unlock() diff --git a/vendor/github.com/moby/buildkit/util/contentutil/refs.go b/vendor/github.com/moby/buildkit/util/contentutil/refs.go new file mode 100644 index 0000000000000..b3a10d1505ac1 --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/contentutil/refs.go @@ -0,0 +1,57 @@ +package contentutil + +import ( + "context" + "net/http" + + "github.com/containerd/containerd/content" + "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/remotes/docker" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +func ProviderFromRef(ref string) (ocispec.Descriptor, content.Provider, error) { + remote := docker.NewResolver(docker.ResolverOptions{ + Client: http.DefaultClient, + }) + + name, desc, err := remote.Resolve(context.TODO(), ref) + if err != nil { + return ocispec.Descriptor{}, nil, err + } + + fetcher, err := remote.Fetcher(context.TODO(), name) + if err != nil { + return ocispec.Descriptor{}, nil, err + } + return desc, FromFetcher(fetcher), nil +} + +func IngesterFromRef(ref string) (content.Ingester, error) { + remote := docker.NewResolver(docker.ResolverOptions{ + Client: http.DefaultClient, + }) + + pusher, err := remote.Pusher(context.TODO(), ref) + if err != nil { + return nil, err + } + + return &ingester{ + pusher: pusher, + }, nil +} + +type ingester struct { + pusher remotes.Pusher +} + +func (w *ingester) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) { + var wo content.WriterOpts + for _, o := range opts { + if err := o(&wo); err != nil { + return nil, err + } + } + return w.pusher.Push(ctx, wo.Desc) +} diff --git a/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go b/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go index e51824a4f3606..d79231173f4e2 100644 --- a/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go +++ b/vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go @@ -21,11 +21,13 @@ type contextKeyT string var contextKey = contextKeyT("buildkit/util/flightcontrol.progress") +// Group is a flightcontrol syncronization group type Group struct { mu sync.Mutex // protects m m map[string]*call // lazily initialized } +// Do executes a context function syncronized by the key func (g *Group) Do(ctx context.Context, key string, fn func(ctx context.Context) (interface{}, error)) (v interface{}, err error) { defer func() { if errors.Cause(err) == errRetry { @@ -312,13 +314,3 @@ func (ps *progressState) close(pw progress.Writer) { } ps.mu.Unlock() } - -func WriteProgress(ctx context.Context, pw progress.Writer) error { - v := ctx.Value(contextKey) - p, ok := v.(*progressState) - if !ok { - return errors.Errorf("invalid context not from flightcontrol") - } - p.add(pw) - return nil -} diff --git a/vendor/github.com/moby/buildkit/util/imageutil/config.go b/vendor/github.com/moby/buildkit/util/imageutil/config.go index 27ff4f4244c7a..a9890e730eb43 100644 --- a/vendor/github.com/moby/buildkit/util/imageutil/config.go +++ b/vendor/github.com/moby/buildkit/util/imageutil/config.go @@ -14,12 +14,12 @@ import ( "github.com/pkg/errors" ) -type IngesterProvider interface { +type ContentCache interface { content.Ingester content.Provider } -func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester IngesterProvider, p *specs.Platform) (digest.Digest, []byte, error) { +func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, p *specs.Platform) (digest.Digest, []byte, error) { // TODO: fix buildkit to take interface instead of struct var platform platforms.MatchComparer if p != nil { @@ -36,7 +36,7 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester Digest: ref.Digest(), } if desc.Digest != "" { - ra, err := ingester.ReaderAt(ctx, desc) + ra, err := cache.ReaderAt(ctx, desc) if err == nil { desc.Size = ra.Size() mt, err := DetectManifestMediaType(ra) @@ -58,19 +58,23 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester return "", nil, err } + if desc.MediaType == images.MediaTypeDockerSchema1Manifest { + return readSchema1Config(ctx, ref.String(), desc, fetcher, cache) + } + handlers := []images.Handler{ - remotes.FetchHandler(ingester, fetcher), - childrenConfigHandler(ingester, platform), + remotes.FetchHandler(cache, fetcher), + childrenConfigHandler(cache, platform), } if err := images.Dispatch(ctx, images.Handlers(handlers...), desc); err != nil { return "", nil, err } - config, err := images.Config(ctx, ingester, desc, platform) + config, err := images.Config(ctx, cache, desc, platform) if err != nil { return "", nil, err } - dt, err := content.ReadBlob(ctx, ingester, config) + dt, err := content.ReadBlob(ctx, cache, config) if err != nil { return "", nil, err } diff --git a/vendor/github.com/moby/buildkit/util/imageutil/schema1.go b/vendor/github.com/moby/buildkit/util/imageutil/schema1.go new file mode 100644 index 0000000000000..591676fffdbad --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/imageutil/schema1.go @@ -0,0 +1,87 @@ +package imageutil + +import ( + "context" + "encoding/json" + "io/ioutil" + "strings" + "time" + + "github.com/containerd/containerd/remotes" + digest "github.com/opencontainers/go-digest" + specs "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" +) + +func readSchema1Config(ctx context.Context, ref string, desc specs.Descriptor, fetcher remotes.Fetcher, cache ContentCache) (digest.Digest, []byte, error) { + rc, err := fetcher.Fetch(ctx, desc) + if err != nil { + return "", nil, err + } + defer rc.Close() + dt, err := ioutil.ReadAll(rc) + if err != nil { + return "", nil, errors.Wrap(err, "failed to fetch schema1 manifest") + } + dt, err = convertSchema1ConfigMeta(dt) + if err != nil { + return "", nil, err + } + return desc.Digest, dt, nil +} + +func convertSchema1ConfigMeta(in []byte) ([]byte, error) { + type history struct { + V1Compatibility string `json:"v1Compatibility"` + } + var m struct { + History []history `json:"history"` + } + if err := json.Unmarshal(in, &m); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal schema1 manifest") + } + if len(m.History) == 0 { + return nil, errors.Errorf("invalid schema1 manifest") + } + + var img specs.Image + if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), &img); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal image from schema 1 history") + } + + img.RootFS = specs.RootFS{ + Type: "layers", // filled in by exporter + } + img.History = make([]specs.History, len(m.History)) + + for i := range m.History { + var h v1History + if err := json.Unmarshal([]byte(m.History[i].V1Compatibility), &h); err != nil { + return nil, errors.Wrap(err, "failed to unmarshal history") + } + img.History[len(m.History)-i-1] = specs.History{ + Author: h.Author, + Comment: h.Comment, + Created: &h.Created, + CreatedBy: strings.Join(h.ContainerConfig.Cmd, " "), + EmptyLayer: (h.ThrowAway != nil && *h.ThrowAway) || (h.Size != nil && *h.Size == 0), + } + } + + dt, err := json.MarshalIndent(img, "", " ") + if err != nil { + return nil, errors.Wrap(err, "failed to marshal schema1 config") + } + return dt, nil +} + +type v1History struct { + Author string `json:"author,omitempty"` + Created time.Time `json:"created"` + Comment string `json:"comment,omitempty"` + ThrowAway *bool `json:"throwaway,omitempty"` + Size *int `json:"Size,omitempty"` // used before ThrowAway field + ContainerConfig struct { + Cmd []string `json:"Cmd,omitempty"` + } `json:"container_config,omitempty"` +} diff --git a/vendor/github.com/moby/buildkit/util/resolver/resolver.go b/vendor/github.com/moby/buildkit/util/resolver/resolver.go new file mode 100644 index 0000000000000..da28923564cd3 --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/resolver/resolver.go @@ -0,0 +1,45 @@ +package resolver + +import ( + "math/rand" + + "github.com/containerd/containerd/remotes/docker" + "github.com/docker/distribution/reference" + "github.com/moby/buildkit/util/tracing" +) + +type RegistryConf struct { + Mirrors []string + PlainHTTP bool +} + +type ResolveOptionsFunc func(string) docker.ResolverOptions + +func NewResolveOptionsFunc(m map[string]RegistryConf) ResolveOptionsFunc { + return func(ref string) docker.ResolverOptions { + def := docker.ResolverOptions{ + Client: tracing.DefaultClient, + } + + parsed, err := reference.ParseNormalizedNamed(ref) + if err != nil { + return def + } + host := reference.Domain(parsed) + + c, ok := m[host] + if !ok { + return def + } + + if len(c.Mirrors) > 0 { + def.Host = func(string) (string, error) { + return c.Mirrors[rand.Intn(len(c.Mirrors))], nil + } + } + + def.PlainHTTP = c.PlainHTTP + + return def + } +} diff --git a/vendor/github.com/moby/buildkit/vendor.conf b/vendor/github.com/moby/buildkit/vendor.conf index ad490d2a9a611..00f8c83244d61 100644 --- a/vendor/github.com/moby/buildkit/vendor.conf +++ b/vendor/github.com/moby/buildkit/vendor.conf @@ -1,12 +1,12 @@ -github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd github.com/pkg/errors v0.8.0 +go.etcd.io/bbolt v1.3.1-etcd.8 github.com/stretchr/testify v1.1.4 github.com/davecgh/go-spew v1.1.0 github.com/pmezard/go-difflib v1.0.0 golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 -github.com/containerd/containerd v1.2.0-beta.2 +github.com/containerd/containerd d97a907f7f781c0ab8340877d8e6b53cc7f1c2f6 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c github.com/sirupsen/logrus v1.0.0 @@ -16,19 +16,20 @@ golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd github.com/gogo/protobuf v1.0.0 github.com/gogo/googleapis b23578765ee54ff6bceff57f397d833bf4ca6869 github.com/golang/protobuf v1.1.0 -github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b +github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537 github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd -github.com/Microsoft/go-winio v0.4.10 +github.com/Microsoft/go-winio v0.4.11 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c -github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce # v1.0.1-43-gd810dbc -github.com/containerd/go-runc acb7c88cac264acca9b5eae187a117f4d77a1292 +github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d +github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 -github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55 +github.com/Microsoft/hcsshim v0.7.3 +golang.org/x/crypto 0709b304e793a5edb4a2c0145f281ecdc20838a4 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b @@ -39,7 +40,7 @@ golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631 github.com/docker/docker 71cd53e4a197b303c6ba086bd584ffd67a884281 github.com/pkg/profile 5b67d428864e92711fcbd2f8629456121a56d91f -github.com/tonistiigi/fsutil b19464cd1b6a00773b4f2eb7acf9c30426f9df42 +github.com/tonistiigi/fsutil 7e391b0e788f9b925f22bd3cf88e0210d1643673 github.com/hashicorp/go-immutable-radix 826af9ccf0feeee615d546d69b11f8e98da8c8f1 git://github.com/tonistiigi/go-immutable-radix.git github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b @@ -49,8 +50,9 @@ github.com/docker/distribution 30578ca32960a4d368bf6db67b0a33c2a1f3dc6f github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2 github.com/docker/cli 99576756eb3303b7af8102c502f21a912e3c1af6 https://github.com/tonistiigi/docker-cli.git github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1 -github.com/docker/libnetwork 822e5b59d346b7ad0735df2c8e445e9787320e67 +github.com/docker/libnetwork 36d3bed0e9f4b3c8c66df9bd45278bb90b33e911 github.com/BurntSushi/toml 3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005 +github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746 github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7 diff --git a/vendor/github.com/moby/buildkit/worker/cacheresult.go b/vendor/github.com/moby/buildkit/worker/cacheresult.go index f70be6f476707..fb11525d7724a 100644 --- a/vendor/github.com/moby/buildkit/worker/cacheresult.go +++ b/vendor/github.com/moby/buildkit/worker/cacheresult.go @@ -36,7 +36,7 @@ func (s *cacheResultStorage) Save(res solver.Result) (solver.CacheResult, error) return solver.CacheResult{ID: ref.ID(), CreatedAt: time.Now()}, nil } func (s *cacheResultStorage) Load(ctx context.Context, res solver.CacheResult) (solver.Result, error) { - return s.load(res.ID) + return s.load(res.ID, false) } func (s *cacheResultStorage) getWorkerRef(id string) (Worker, string, error) { @@ -51,7 +51,7 @@ func (s *cacheResultStorage) getWorkerRef(id string) (Worker, string, error) { return w, refID, nil } -func (s *cacheResultStorage) load(id string) (solver.Result, error) { +func (s *cacheResultStorage) load(id string, hidden bool) (solver.Result, error) { w, refID, err := s.getWorkerRef(id) if err != nil { return nil, err @@ -59,7 +59,7 @@ func (s *cacheResultStorage) load(id string) (solver.Result, error) { if refID == "" { return NewWorkerRefResult(nil, w), nil } - ref, err := w.LoadRef(refID) + ref, err := w.LoadRef(refID, hidden) if err != nil { return nil, err } @@ -71,7 +71,7 @@ func (s *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheRes if err != nil { return nil, err } - ref, err := w.LoadRef(refID) + ref, err := w.LoadRef(refID, true) if err != nil { return nil, err } @@ -83,7 +83,7 @@ func (s *cacheResultStorage) LoadRemote(ctx context.Context, res solver.CacheRes return remote, nil } func (s *cacheResultStorage) Exists(id string) bool { - ref, err := s.load(id) + ref, err := s.load(id, true) if err != nil { return false } diff --git a/vendor/github.com/moby/buildkit/worker/worker.go b/vendor/github.com/moby/buildkit/worker/worker.go index 97abfbfbb2a55..47a5d4bf74eb4 100644 --- a/vendor/github.com/moby/buildkit/worker/worker.go +++ b/vendor/github.com/moby/buildkit/worker/worker.go @@ -21,7 +21,7 @@ type Worker interface { Labels() map[string]string Platforms() []specs.Platform GCPolicy() []client.PruneInfo - LoadRef(id string) (cache.ImmutableRef, error) + LoadRef(id string, hidden bool) (cache.ImmutableRef, error) // ResolveOp resolves Vertex.Sys() to Op implementation. ResolveOp(v solver.Vertex, s frontend.FrontendLLBBridge) (solver.Op, error) ResolveImageConfig(ctx context.Context, ref string, opt gw.ResolveImageConfigOpt) (digest.Digest, []byte, error) diff --git a/vendor/github.com/boltdb/bolt/LICENSE b/vendor/go.etcd.io/bbolt/LICENSE similarity index 100% rename from vendor/github.com/boltdb/bolt/LICENSE rename to vendor/go.etcd.io/bbolt/LICENSE diff --git a/vendor/github.com/boltdb/bolt/README.md b/vendor/go.etcd.io/bbolt/README.md similarity index 84% rename from vendor/github.com/boltdb/bolt/README.md rename to vendor/go.etcd.io/bbolt/README.md index 2a69d95e78af4..6546fc01ac5ad 100644 --- a/vendor/github.com/boltdb/bolt/README.md +++ b/vendor/go.etcd.io/bbolt/README.md @@ -1,5 +1,18 @@ -Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.2.1-green.svg) -==== +bbolt +===== + +[![Go Report Card](https://goreportcard.com/badge/github.com/etcd-io/bbolt?style=flat-square)](https://goreportcard.com/report/github.com/etcd-io/bbolt) +[![Coverage](https://codecov.io/gh/etcd-io/bbolt/branch/master/graph/badge.svg)](https://codecov.io/gh/etcd-io/bbolt) +[![Build Status Travis](https://img.shields.io/travis/etcd-io/bboltlabs.svg?style=flat-square&&branch=master)](https://travis-ci.com/etcd-io/bbolt) +[![Godoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/etcd-io/bbolt) +[![Releases](https://img.shields.io/github/release/etcd-io/bbolt/all.svg?style=flat-square)](https://github.com/etcd-io/bbolt/releases) +[![LICENSE](https://img.shields.io/github/license/etcd-io/bbolt.svg?style=flat-square)](https://github.com/etcd-io/bbolt/blob/master/LICENSE) + +bbolt is a fork of [Ben Johnson's][gh_ben] [Bolt][bolt] key/value +store. The purpose of this fork is to provide the Go community with an active +maintenance and development target for Bolt; the goal is improved reliability +and stability. bbolt includes bug fixes, performance enhancements, and features +not found in Bolt while preserving backwards compatibility with the Bolt API. Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas] [LMDB project][lmdb]. The goal of the project is to provide a simple, @@ -10,6 +23,8 @@ Since Bolt is meant to be used as such a low-level piece of functionality, simplicity is key. The API will be small and only focus on getting values and setting values. That's it. +[gh_ben]: https://github.com/benbjohnson +[bolt]: https://github.com/boltdb/bolt [hyc_symas]: https://twitter.com/hyc_symas [lmdb]: http://symas.com/mdb/ @@ -17,40 +32,46 @@ and setting values. That's it. Bolt is stable, the API is fixed, and the file format is fixed. Full unit test coverage and randomized black box testing are used to ensure database -consistency and thread safety. Bolt is currently in high-load production +consistency and thread safety. Bolt is currently used in high-load production environments serving databases as large as 1TB. Many companies such as Shopify and Heroku use Bolt-backed services every day. +## Project versioning + +bbolt uses [semantic versioning](http://semver.org). +API should not change between patch and minor releases. +New minor versions may add additional features to the API. + ## Table of Contents -- [Getting Started](#getting-started) - - [Installing](#installing) - - [Opening a database](#opening-a-database) - - [Transactions](#transactions) - - [Read-write transactions](#read-write-transactions) - - [Read-only transactions](#read-only-transactions) - - [Batch read-write transactions](#batch-read-write-transactions) - - [Managing transactions manually](#managing-transactions-manually) - - [Using buckets](#using-buckets) - - [Using key/value pairs](#using-keyvalue-pairs) - - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket) - - [Iterating over keys](#iterating-over-keys) - - [Prefix scans](#prefix-scans) - - [Range scans](#range-scans) - - [ForEach()](#foreach) - - [Nested buckets](#nested-buckets) - - [Database backups](#database-backups) - - [Statistics](#statistics) - - [Read-Only Mode](#read-only-mode) - - [Mobile Use (iOS/Android)](#mobile-use-iosandroid) -- [Resources](#resources) -- [Comparison with other databases](#comparison-with-other-databases) - - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases) - - [LevelDB, RocksDB](#leveldb-rocksdb) - - [LMDB](#lmdb) -- [Caveats & Limitations](#caveats--limitations) -- [Reading the Source](#reading-the-source) -- [Other Projects Using Bolt](#other-projects-using-bolt) + - [Getting Started](#getting-started) + - [Installing](#installing) + - [Opening a database](#opening-a-database) + - [Transactions](#transactions) + - [Read-write transactions](#read-write-transactions) + - [Read-only transactions](#read-only-transactions) + - [Batch read-write transactions](#batch-read-write-transactions) + - [Managing transactions manually](#managing-transactions-manually) + - [Using buckets](#using-buckets) + - [Using key/value pairs](#using-keyvalue-pairs) + - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket) + - [Iterating over keys](#iterating-over-keys) + - [Prefix scans](#prefix-scans) + - [Range scans](#range-scans) + - [ForEach()](#foreach) + - [Nested buckets](#nested-buckets) + - [Database backups](#database-backups) + - [Statistics](#statistics) + - [Read-Only Mode](#read-only-mode) + - [Mobile Use (iOS/Android)](#mobile-use-iosandroid) + - [Resources](#resources) + - [Comparison with other databases](#comparison-with-other-databases) + - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases) + - [LevelDB, RocksDB](#leveldb-rocksdb) + - [LMDB](#lmdb) + - [Caveats & Limitations](#caveats--limitations) + - [Reading the Source](#reading-the-source) + - [Other Projects Using Bolt](#other-projects-using-bolt) ## Getting Started @@ -59,13 +80,28 @@ Shopify and Heroku use Bolt-backed services every day. To start using Bolt, install Go and run `go get`: ```sh -$ go get github.com/boltdb/bolt/... +$ go get go.etcd.io/bbolt/... ``` This will retrieve the library and install the `bolt` command line utility into your `$GOBIN` path. +### Importing bbolt + +To use bbolt as an embedded key-value store, import as: + +```go +import bolt "go.etcd.io/bbolt" + +db, err := bolt.Open(path, 0666, nil) +if err != nil { + return err +} +defer db.Close() +``` + + ### Opening a database The top-level object in Bolt is a `DB`. It is represented as a single file on @@ -79,7 +115,7 @@ package main import ( "log" - "github.com/boltdb/bolt" + bolt "go.etcd.io/bbolt" ) func main() { @@ -395,7 +431,7 @@ db.View(func(tx *bolt.Tx) error { c := tx.Bucket([]byte("MyBucket")).Cursor() prefix := []byte("1234") - for k, v := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, v = c.Next() { + for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { fmt.Printf("key=%s, value=%s\n", k, v) } @@ -464,6 +500,55 @@ func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) func (*Bucket) DeleteBucket(key []byte) error ``` +Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings. + +```go + +// createUser creates a new user in the given account. +func createUser(accountID int, u *User) error { + // Start the transaction. + tx, err := db.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + // Retrieve the root bucket for the account. + // Assume this has already been created when the account was set up. + root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10))) + + // Setup the users bucket. + bkt, err := root.CreateBucketIfNotExists([]byte("USERS")) + if err != nil { + return err + } + + // Generate an ID for the new user. + userID, err := bkt.NextSequence() + if err != nil { + return err + } + u.ID = userID + + // Marshal and save the encoded user. + if buf, err := json.Marshal(u); err != nil { + return err + } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil { + return err + } + + // Commit the transaction. + if err := tx.Commit(); err != nil { + return err + } + + return nil +} + +``` + + + ### Database backups @@ -473,7 +558,7 @@ this from a read-only transaction, it will perform a hot backup and not block your other database reads and writes. By default, it will use a regular file handle which will utilize the operating -system's page cache. See the [`Tx`](https://godoc.org/github.com/boltdb/bolt#Tx) +system's page cache. See the [`Tx`](https://godoc.org/go.etcd.io/bbolt#Tx) documentation for information about optimizing for larger-than-RAM datasets. One common use case is to backup over HTTP so you can use tools like `cURL` to @@ -719,6 +804,9 @@ Here are a few things to note when evaluating and using Bolt: can be reused by a new page or can be unmapped from virtual memory and you'll see an `unexpected fault address` panic when accessing it. +* Bolt uses an exclusive write lock on the database file so it cannot be + shared by multiple processes. + * Be careful when using `Bucket.FillPercent`. Setting a high fill percent for buckets that have random inserts will cause your database to have very poor page utilization. @@ -759,7 +847,7 @@ Here are a few things to note when evaluating and using Bolt: ## Reading the Source -Bolt is a relatively small code base (<3KLOC) for an embedded, serializable, +Bolt is a relatively small code base (<5KLOC) for an embedded, serializable, transactional key/value database so it can be a good starting point for people interested in how databases work. @@ -811,47 +899,55 @@ them via pull request. Below is a list of public, open source projects that use Bolt: -* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. -* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. +* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. * [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside. -* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. -* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics. -* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects. -* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday. +* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal. +* [boltcli](https://github.com/spacewander/boltcli) - the redis-cli for boltdb with Lua script support. +* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB +* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt. +* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. +* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. +* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. +* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. +* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining + simple tx and key scans. +* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. * [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations. -* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite. -* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin". +* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. +* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. +* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. +* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems. * [event-shuttle](https://github.com/sclasen/event-shuttle) - A Unix system service to collect and reliably deliver messages to Kafka. +* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. +* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. +* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. +* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains +* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin". +* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. +* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters. * [ipxed](https://github.com/kelseyhightower/ipxed) - Web interface and api for ipxed. -* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt. -* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site. +* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies +* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs. * [LedisDB](https://github.com/siddontang/ledisdb) - A high performance NoSQL, using Bolt as optional storage. -* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters. -* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. -* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. -* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. -* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. -* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. -* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. +* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. +* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets. +* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite. +* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. +* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. +* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site. * [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system. -* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. -* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs. -* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems. +* [reef-pi](https://github.com/reef-pi/reef-pi) - reef-pi is an award winning, modular, DIY reef tank controller using easy to learn electronics based on a Raspberry Pi. +* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service +* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. * [stow](https://github.com/djherbis/stow) - a persistence manager for objects backed by boltdb. -* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining - simple tx and key scans. -* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets. -* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service -* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. -* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. -* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. * [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB. -* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. * [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings. -* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. -* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. -* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics. +* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects. +* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. * [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development. +* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday. If you are using Bolt in a project please send a pull request to add it to the list. diff --git a/vendor/github.com/boltdb/bolt/bolt_386.go b/vendor/go.etcd.io/bbolt/bolt_386.go similarity index 95% rename from vendor/github.com/boltdb/bolt/bolt_386.go rename to vendor/go.etcd.io/bbolt/bolt_386.go index 820d533c15faa..4d35ee7cf3d25 100644 --- a/vendor/github.com/boltdb/bolt/bolt_386.go +++ b/vendor/go.etcd.io/bbolt/bolt_386.go @@ -1,4 +1,4 @@ -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0x7FFFFFFF // 2GB diff --git a/vendor/github.com/boltdb/bolt/bolt_amd64.go b/vendor/go.etcd.io/bbolt/bolt_amd64.go similarity index 95% rename from vendor/github.com/boltdb/bolt/bolt_amd64.go rename to vendor/go.etcd.io/bbolt/bolt_amd64.go index 98fafdb47d86b..60a52dad56b2d 100644 --- a/vendor/github.com/boltdb/bolt/bolt_amd64.go +++ b/vendor/go.etcd.io/bbolt/bolt_amd64.go @@ -1,4 +1,4 @@ -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0xFFFFFFFFFFFF // 256TB diff --git a/vendor/github.com/boltdb/bolt/bolt_arm.go b/vendor/go.etcd.io/bbolt/bolt_arm.go similarity index 98% rename from vendor/github.com/boltdb/bolt/bolt_arm.go rename to vendor/go.etcd.io/bbolt/bolt_arm.go index 7e5cb4b941286..105d27ddb7ddb 100644 --- a/vendor/github.com/boltdb/bolt/bolt_arm.go +++ b/vendor/go.etcd.io/bbolt/bolt_arm.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import "unsafe" diff --git a/vendor/github.com/boltdb/bolt/bolt_arm64.go b/vendor/go.etcd.io/bbolt/bolt_arm64.go similarity index 95% rename from vendor/github.com/boltdb/bolt/bolt_arm64.go rename to vendor/go.etcd.io/bbolt/bolt_arm64.go index b26d84f91ba77..f5aa2a5ee248e 100644 --- a/vendor/github.com/boltdb/bolt/bolt_arm64.go +++ b/vendor/go.etcd.io/bbolt/bolt_arm64.go @@ -1,6 +1,6 @@ // +build arm64 -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0xFFFFFFFFFFFF // 256TB diff --git a/vendor/github.com/boltdb/bolt/bolt_linux.go b/vendor/go.etcd.io/bbolt/bolt_linux.go similarity index 91% rename from vendor/github.com/boltdb/bolt/bolt_linux.go rename to vendor/go.etcd.io/bbolt/bolt_linux.go index 2b67666140906..7707bcacf03a1 100644 --- a/vendor/github.com/boltdb/bolt/bolt_linux.go +++ b/vendor/go.etcd.io/bbolt/bolt_linux.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "syscall" diff --git a/vendor/go.etcd.io/bbolt/bolt_mips64x.go b/vendor/go.etcd.io/bbolt/bolt_mips64x.go new file mode 100644 index 0000000000000..baeb289fd94b8 --- /dev/null +++ b/vendor/go.etcd.io/bbolt/bolt_mips64x.go @@ -0,0 +1,12 @@ +// +build mips64 mips64le + +package bbolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x8000000000 // 512GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/go.etcd.io/bbolt/bolt_mipsx.go b/vendor/go.etcd.io/bbolt/bolt_mipsx.go new file mode 100644 index 0000000000000..2d9b1a91f3642 --- /dev/null +++ b/vendor/go.etcd.io/bbolt/bolt_mipsx.go @@ -0,0 +1,12 @@ +// +build mips mipsle + +package bbolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x40000000 // 1GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_openbsd.go b/vendor/go.etcd.io/bbolt/bolt_openbsd.go similarity index 97% rename from vendor/github.com/boltdb/bolt/bolt_openbsd.go rename to vendor/go.etcd.io/bbolt/bolt_openbsd.go index 7058c3d734ef7..d7f50358ef141 100644 --- a/vendor/github.com/boltdb/bolt/bolt_openbsd.go +++ b/vendor/go.etcd.io/bbolt/bolt_openbsd.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "syscall" diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc.go b/vendor/go.etcd.io/bbolt/bolt_ppc.go similarity index 69% rename from vendor/github.com/boltdb/bolt/bolt_ppc.go rename to vendor/go.etcd.io/bbolt/bolt_ppc.go index 645ddc3edc2d6..69804714aaef3 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc.go +++ b/vendor/go.etcd.io/bbolt/bolt_ppc.go @@ -1,9 +1,12 @@ // +build ppc -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0x7FFFFFFF // 2GB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64.go b/vendor/go.etcd.io/bbolt/bolt_ppc64.go similarity index 70% rename from vendor/github.com/boltdb/bolt/bolt_ppc64.go rename to vendor/go.etcd.io/bbolt/bolt_ppc64.go index 2dc6be02e3e3e..356590857607a 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc64.go +++ b/vendor/go.etcd.io/bbolt/bolt_ppc64.go @@ -1,9 +1,12 @@ // +build ppc64 -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go b/vendor/go.etcd.io/bbolt/bolt_ppc64le.go similarity index 95% rename from vendor/github.com/boltdb/bolt/bolt_ppc64le.go rename to vendor/go.etcd.io/bbolt/bolt_ppc64le.go index 8c143bc5d194d..422c7c69d667a 100644 --- a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go +++ b/vendor/go.etcd.io/bbolt/bolt_ppc64le.go @@ -1,6 +1,6 @@ // +build ppc64le -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0xFFFFFFFFFFFF // 256TB diff --git a/vendor/github.com/boltdb/bolt/bolt_s390x.go b/vendor/go.etcd.io/bbolt/bolt_s390x.go similarity index 95% rename from vendor/github.com/boltdb/bolt/bolt_s390x.go rename to vendor/go.etcd.io/bbolt/bolt_s390x.go index d7c39af925390..6d3fcb825d344 100644 --- a/vendor/github.com/boltdb/bolt/bolt_s390x.go +++ b/vendor/go.etcd.io/bbolt/bolt_s390x.go @@ -1,6 +1,6 @@ // +build s390x -package bolt +package bbolt // maxMapSize represents the largest mmap size supported by Bolt. const maxMapSize = 0xFFFFFFFFFFFF // 256TB diff --git a/vendor/github.com/boltdb/bolt/bolt_unix.go b/vendor/go.etcd.io/bbolt/bolt_unix.go similarity index 71% rename from vendor/github.com/boltdb/bolt/bolt_unix.go rename to vendor/go.etcd.io/bbolt/bolt_unix.go index cad62dda1e387..5f2bb51451990 100644 --- a/vendor/github.com/boltdb/bolt/bolt_unix.go +++ b/vendor/go.etcd.io/bbolt/bolt_unix.go @@ -1,41 +1,43 @@ // +build !windows,!plan9,!solaris -package bolt +package bbolt import ( "fmt" - "os" "syscall" "time" "unsafe" ) // flock acquires an advisory lock on a file descriptor. -func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { +func flock(db *DB, exclusive bool, timeout time.Duration) error { var t time.Time + if timeout != 0 { + t = time.Now() + } + fd := db.file.Fd() + flag := syscall.LOCK_NB + if exclusive { + flag |= syscall.LOCK_EX + } else { + flag |= syscall.LOCK_SH + } for { - // If we're beyond our timeout then return an error. - // This can only occur after we've attempted a flock once. - if t.IsZero() { - t = time.Now() - } else if timeout > 0 && time.Since(t) > timeout { - return ErrTimeout - } - flag := syscall.LOCK_SH - if exclusive { - flag = syscall.LOCK_EX - } - - // Otherwise attempt to obtain an exclusive lock. - err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB) + // Attempt to obtain an exclusive lock. + err := syscall.Flock(int(fd), flag) if err == nil { return nil } else if err != syscall.EWOULDBLOCK { return err } + // If we timed out then return an error. + if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout { + return ErrTimeout + } + // Wait for a bit and try again. - time.Sleep(50 * time.Millisecond) + time.Sleep(flockRetryTimeout) } } @@ -53,7 +55,9 @@ func mmap(db *DB, sz int) error { } // Advise the kernel that the mmap is accessed randomly. - if err := madvise(b, syscall.MADV_RANDOM); err != nil { + err = madvise(b, syscall.MADV_RANDOM) + if err != nil && err != syscall.ENOSYS { + // Ignore not implemented error in kernel because it still works. return fmt.Errorf("madvise: %s", err) } diff --git a/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go b/vendor/go.etcd.io/bbolt/bolt_unix_solaris.go similarity index 70% rename from vendor/github.com/boltdb/bolt/bolt_unix_solaris.go rename to vendor/go.etcd.io/bbolt/bolt_unix_solaris.go index 307bf2b3ee976..babad657862bb 100644 --- a/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go +++ b/vendor/go.etcd.io/bbolt/bolt_unix_solaris.go @@ -1,8 +1,7 @@ -package bolt +package bbolt import ( "fmt" - "os" "syscall" "time" "unsafe" @@ -11,36 +10,35 @@ import ( ) // flock acquires an advisory lock on a file descriptor. -func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { +func flock(db *DB, exclusive bool, timeout time.Duration) error { var t time.Time + if timeout != 0 { + t = time.Now() + } + fd := db.file.Fd() + var lockType int16 + if exclusive { + lockType = syscall.F_WRLCK + } else { + lockType = syscall.F_RDLCK + } for { - // If we're beyond our timeout then return an error. - // This can only occur after we've attempted a flock once. - if t.IsZero() { - t = time.Now() - } else if timeout > 0 && time.Since(t) > timeout { - return ErrTimeout - } - var lock syscall.Flock_t - lock.Start = 0 - lock.Len = 0 - lock.Pid = 0 - lock.Whence = 0 - lock.Pid = 0 - if exclusive { - lock.Type = syscall.F_WRLCK - } else { - lock.Type = syscall.F_RDLCK - } - err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock) + // Attempt to obtain an exclusive lock. + lock := syscall.Flock_t{Type: lockType} + err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock) if err == nil { return nil } else if err != syscall.EAGAIN { return err } + // If we timed out then return an error. + if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout { + return ErrTimeout + } + // Wait for a bit and try again. - time.Sleep(50 * time.Millisecond) + time.Sleep(flockRetryTimeout) } } diff --git a/vendor/github.com/boltdb/bolt/bolt_windows.go b/vendor/go.etcd.io/bbolt/bolt_windows.go similarity index 76% rename from vendor/github.com/boltdb/bolt/bolt_windows.go rename to vendor/go.etcd.io/bbolt/bolt_windows.go index d538e6afd77ac..fca178bd29082 100644 --- a/vendor/github.com/boltdb/bolt/bolt_windows.go +++ b/vendor/go.etcd.io/bbolt/bolt_windows.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "fmt" @@ -16,8 +16,6 @@ var ( ) const ( - lockExt = ".lock" - // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx flagLockExclusive = 2 flagLockFailImmediately = 1 @@ -48,48 +46,47 @@ func fdatasync(db *DB) error { } // flock acquires an advisory lock on a file descriptor. -func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { - // Create a separate lock file on windows because a process - // cannot share an exclusive lock on the same file. This is - // needed during Tx.WriteTo(). - f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode) - if err != nil { - return err - } - db.lockfile = f - +func flock(db *DB, exclusive bool, timeout time.Duration) error { var t time.Time + if timeout != 0 { + t = time.Now() + } + var flag uint32 = flagLockFailImmediately + if exclusive { + flag |= flagLockExclusive + } for { - // If we're beyond our timeout then return an error. - // This can only occur after we've attempted a flock once. - if t.IsZero() { - t = time.Now() - } else if timeout > 0 && time.Since(t) > timeout { - return ErrTimeout - } - - var flag uint32 = flagLockFailImmediately - if exclusive { - flag |= flagLockExclusive - } + // Fix for https://github.com/etcd-io/bbolt/issues/121. Use byte-range + // -1..0 as the lock on the database file. + var m1 uint32 = (1 << 32) - 1 // -1 in a uint32 + err := lockFileEx(syscall.Handle(db.file.Fd()), flag, 0, 1, 0, &syscall.Overlapped{ + Offset: m1, + OffsetHigh: m1, + }) - err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}) if err == nil { return nil } else if err != errLockViolation { return err } + // If we timed oumercit then return an error. + if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout { + return ErrTimeout + } + // Wait for a bit and try again. - time.Sleep(50 * time.Millisecond) + time.Sleep(flockRetryTimeout) } } // funlock releases an advisory lock on a file descriptor. func funlock(db *DB) error { - err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{}) - db.lockfile.Close() - os.Remove(db.path+lockExt) + var m1 uint32 = (1 << 32) - 1 // -1 in a uint32 + err := unlockFileEx(syscall.Handle(db.file.Fd()), 0, 1, 0, &syscall.Overlapped{ + Offset: m1, + OffsetHigh: m1, + }) return err } diff --git a/vendor/github.com/boltdb/bolt/boltsync_unix.go b/vendor/go.etcd.io/bbolt/boltsync_unix.go similarity index 91% rename from vendor/github.com/boltdb/bolt/boltsync_unix.go rename to vendor/go.etcd.io/bbolt/boltsync_unix.go index f50442523c384..9587afefee404 100644 --- a/vendor/github.com/boltdb/bolt/boltsync_unix.go +++ b/vendor/go.etcd.io/bbolt/boltsync_unix.go @@ -1,6 +1,6 @@ // +build !windows,!plan9,!linux,!openbsd -package bolt +package bbolt // fdatasync flushes written data to a file descriptor. func fdatasync(db *DB) error { diff --git a/vendor/github.com/boltdb/bolt/bucket.go b/vendor/go.etcd.io/bbolt/bucket.go similarity index 99% rename from vendor/github.com/boltdb/bolt/bucket.go rename to vendor/go.etcd.io/bbolt/bucket.go index 511ce72d337f8..84bfd4d6a283e 100644 --- a/vendor/github.com/boltdb/bolt/bucket.go +++ b/vendor/go.etcd.io/bbolt/bucket.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "bytes" @@ -14,13 +14,6 @@ const ( MaxValueSize = (1 << 31) - 2 ) -const ( - maxUint = ^uint(0) - minUint = 0 - maxInt = int(^uint(0) >> 1) - minInt = -maxInt - 1 -) - const bucketHeaderSize = int(unsafe.Sizeof(bucket{})) const ( @@ -175,9 +168,8 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { if bytes.Equal(key, k) { if (flags & bucketLeafFlag) != 0 { return nil, ErrBucketExists - } else { - return nil, ErrIncompatibleValue } + return nil, ErrIncompatibleValue } // Create empty, inline bucket. @@ -324,7 +316,12 @@ func (b *Bucket) Delete(key []byte) error { // Move cursor to correct position. c := b.Cursor() - _, _, flags := c.seek(key) + k, _, flags := c.seek(key) + + // Return nil if the key doesn't exist. + if !bytes.Equal(key, k) { + return nil + } // Return an error if there is already existing bucket value. if (flags & bucketLeafFlag) != 0 { diff --git a/vendor/github.com/boltdb/bolt/cursor.go b/vendor/go.etcd.io/bbolt/cursor.go similarity index 99% rename from vendor/github.com/boltdb/bolt/cursor.go rename to vendor/go.etcd.io/bbolt/cursor.go index 1be9f35e3ef85..3000aced6c4c1 100644 --- a/vendor/github.com/boltdb/bolt/cursor.go +++ b/vendor/go.etcd.io/bbolt/cursor.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "bytes" @@ -157,12 +157,6 @@ func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) { // Start from root page/node and traverse to correct page. c.stack = c.stack[:0] c.search(seek, c.bucket.root) - ref := &c.stack[len(c.stack)-1] - - // If the cursor is pointing to the end of page/node then return nil. - if ref.index >= ref.count() { - return nil, nil, 0 - } // If this is a bucket then return a nil value. return c.keyValue() @@ -339,6 +333,8 @@ func (c *Cursor) nsearch(key []byte) { // keyValue returns the key and value of the current leaf element. func (c *Cursor) keyValue() ([]byte, []byte, uint32) { ref := &c.stack[len(c.stack)-1] + + // If the cursor is pointing to the end of page/node then return nil. if ref.count() == 0 || ref.index >= ref.count() { return nil, nil, 0 } diff --git a/vendor/github.com/boltdb/bolt/db.go b/vendor/go.etcd.io/bbolt/db.go similarity index 84% rename from vendor/github.com/boltdb/bolt/db.go rename to vendor/go.etcd.io/bbolt/db.go index 1223493ca7be8..d91dcf813a14f 100644 --- a/vendor/github.com/boltdb/bolt/db.go +++ b/vendor/go.etcd.io/bbolt/db.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "errors" @@ -7,8 +7,7 @@ import ( "log" "os" "runtime" - "runtime/debug" - "strings" + "sort" "sync" "time" "unsafe" @@ -23,6 +22,8 @@ const version = 2 // Represents a marker value to indicate that a file is a Bolt DB. const magic uint32 = 0xED0CDAED +const pgidNoFreelist pgid = 0xffffffffffffffff + // IgnoreNoSync specifies whether the NoSync field of a DB is ignored when // syncing changes to a file. This is required as some operating systems, // such as OpenBSD, do not have a unified buffer cache (UBC) and writes @@ -39,6 +40,9 @@ const ( // default page size for db is set to the OS page size. var defaultPageSize = os.Getpagesize() +// The time elapsed between consecutive file locking attempts. +const flockRetryTimeout = 50 * time.Millisecond + // DB represents a collection of buckets persisted to a file on disk. // All data access is performed through transactions which can be obtained through the DB. // All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called. @@ -61,6 +65,11 @@ type DB struct { // THIS IS UNSAFE. PLEASE USE WITH CAUTION. NoSync bool + // When true, skips syncing freelist to disk. This improves the database + // write performance under normal operation, but requires a full database + // re-sync during recovery. + NoFreelistSync bool + // When true, skips the truncate call when growing the database. // Setting this to true is only safe on non-ext3/ext4 systems. // Skipping truncation avoids preallocation of hard drive space and @@ -96,8 +105,7 @@ type DB struct { path string file *os.File - lockfile *os.File // windows only - dataref []byte // mmap'ed readonly, write throws SEGV + dataref []byte // mmap'ed readonly, write throws SEGV data *[maxMapSize]byte datasz int filesz int // current on disk file size @@ -107,9 +115,11 @@ type DB struct { opened bool rwtx *Tx txs []*Tx - freelist *freelist stats Stats + freelist *freelist + freelistLoad sync.Once + pagePool sync.Pool batchMu sync.Mutex @@ -148,14 +158,17 @@ func (db *DB) String() string { // If the file does not exist then it will be created automatically. // Passing in nil options will cause Bolt to open the database with the default options. func Open(path string, mode os.FileMode, options *Options) (*DB, error) { - var db = &DB{opened: true} - + db := &DB{ + opened: true, + } // Set default options if no options are provided. if options == nil { options = DefaultOptions } + db.NoSync = options.NoSync db.NoGrowSync = options.NoGrowSync db.MmapFlags = options.MmapFlags + db.NoFreelistSync = options.NoFreelistSync // Set default values for later DB operations. db.MaxBatchSize = DefaultMaxBatchSize @@ -183,7 +196,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) { // if !options.ReadOnly. // The database file is locked using the shared lock (more than one process may // hold a lock at the same time) otherwise (options.ReadOnly is set). - if err := flock(db, mode, !db.readOnly, options.Timeout); err != nil { + if err := flock(db, !db.readOnly, options.Timeout); err != nil { _ = db.close() return nil, err } @@ -191,31 +204,41 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) { // Default values for test hooks db.ops.writeAt = db.file.WriteAt + if db.pageSize = options.PageSize; db.pageSize == 0 { + // Set the default page size to the OS page size. + db.pageSize = defaultPageSize + } + // Initialize the database if it doesn't exist. if info, err := db.file.Stat(); err != nil { + _ = db.close() return nil, err } else if info.Size() == 0 { // Initialize new files with meta pages. if err := db.init(); err != nil { + // clean up file descriptor on initialization fail + _ = db.close() return nil, err } } else { // Read the first meta page to determine the page size. var buf [0x1000]byte - if _, err := db.file.ReadAt(buf[:], 0); err == nil { - m := db.pageInBuffer(buf[:], 0).meta() - if err := m.validate(); err != nil { - // If we can't read the page size, we can assume it's the same - // as the OS -- since that's how the page size was chosen in the - // first place. - // - // If the first page is invalid and this OS uses a different - // page size than what the database was created with then we - // are out of luck and cannot access the database. - db.pageSize = os.Getpagesize() - } else { + // If we can't read the page size, but can read a page, assume + // it's the same as the OS or one given -- since that's how the + // page size was chosen in the first place. + // + // If the first page is invalid and this OS uses a different + // page size than what the database was created with then we + // are out of luck and cannot access the database. + // + // TODO: scan for next page + if bw, err := db.file.ReadAt(buf[:], 0); err == nil && bw == len(buf) { + if m := db.pageInBuffer(buf[:], 0).meta(); m.validate() == nil { db.pageSize = int(m.pageSize) } + } else { + _ = db.close() + return nil, ErrInvalid } } @@ -232,14 +255,50 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) { return nil, err } - // Read in the freelist. - db.freelist = newFreelist() - db.freelist.read(db.page(db.meta().freelist)) + if db.readOnly { + return db, nil + } + + db.loadFreelist() + + // Flush freelist when transitioning from no sync to sync so + // NoFreelistSync unaware boltdb can open the db later. + if !db.NoFreelistSync && !db.hasSyncedFreelist() { + tx, err := db.Begin(true) + if tx != nil { + err = tx.Commit() + } + if err != nil { + _ = db.close() + return nil, err + } + } // Mark the database as opened and return. return db, nil } +// loadFreelist reads the freelist if it is synced, or reconstructs it +// by scanning the DB if it is not synced. It assumes there are no +// concurrent accesses being made to the freelist. +func (db *DB) loadFreelist() { + db.freelistLoad.Do(func() { + db.freelist = newFreelist() + if !db.hasSyncedFreelist() { + // Reconstruct free list by scanning the DB. + db.freelist.readIDs(db.freepages()) + } else { + // Read free list from freelist page. + db.freelist.read(db.page(db.meta().freelist)) + } + db.stats.FreePageN = len(db.freelist.ids) + }) +} + +func (db *DB) hasSyncedFreelist() bool { + return db.meta().freelist != pgidNoFreelist +} + // mmap opens the underlying memory-mapped file and initializes the meta references. // minsz is the minimum size that the new mmap can be. func (db *DB) mmap(minsz int) error { @@ -341,9 +400,6 @@ func (db *DB) mmapSize(size int) (int, error) { // init creates a new database file and initializes its meta pages. func (db *DB) init() error { - // Set the page size to the OS page size. - db.pageSize = os.Getpagesize() - // Create two meta pages on a buffer. buf := make([]byte, db.pageSize*4) for i := 0; i < 2; i++ { @@ -387,7 +443,8 @@ func (db *DB) init() error { } // Close releases all database resources. -// All transactions must be closed before closing the database. +// It will block waiting for any open transactions to finish +// before closing the database and returning. func (db *DB) Close() error { db.rwlock.Lock() defer db.rwlock.Unlock() @@ -395,8 +452,8 @@ func (db *DB) Close() error { db.metalock.Lock() defer db.metalock.Unlock() - db.mmaplock.RLock() - defer db.mmaplock.RUnlock() + db.mmaplock.Lock() + defer db.mmaplock.Unlock() return db.close() } @@ -526,21 +583,36 @@ func (db *DB) beginRWTx() (*Tx, error) { t := &Tx{writable: true} t.init(db) db.rwtx = t + db.freePages() + return t, nil +} - // Free any pages associated with closed read-only transactions. - var minid txid = 0xFFFFFFFFFFFFFFFF - for _, t := range db.txs { - if t.meta.txid < minid { - minid = t.meta.txid - } +// freePages releases any pages associated with closed read-only transactions. +func (db *DB) freePages() { + // Free all pending pages prior to earliest open transaction. + sort.Sort(txsById(db.txs)) + minid := txid(0xFFFFFFFFFFFFFFFF) + if len(db.txs) > 0 { + minid = db.txs[0].meta.txid } if minid > 0 { db.freelist.release(minid - 1) } - - return t, nil + // Release unused txid extents. + for _, t := range db.txs { + db.freelist.releaseRange(minid, t.meta.txid-1) + minid = t.meta.txid + 1 + } + db.freelist.releaseRange(minid, txid(0xFFFFFFFFFFFFFFFF)) + // Any page both allocated and freed in an extent is safe to release. } +type txsById []*Tx + +func (t txsById) Len() int { return len(t) } +func (t txsById) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t txsById) Less(i, j int) bool { return t[i].meta.txid < t[j].meta.txid } + // removeTx removes a transaction from the database. func (db *DB) removeTx(tx *Tx) { // Release the read lock on the mmap. @@ -552,7 +624,10 @@ func (db *DB) removeTx(tx *Tx) { // Remove the transaction. for i, t := range db.txs { if t == tx { - db.txs = append(db.txs[:i], db.txs[i+1:]...) + last := len(db.txs) - 1 + db.txs[i] = db.txs[last] + db.txs[last] = nil + db.txs = db.txs[:last] break } } @@ -630,11 +705,7 @@ func (db *DB) View(fn func(*Tx) error) error { return err } - if err := t.Rollback(); err != nil { - return err - } - - return nil + return t.Rollback() } // Batch calls fn as part of a batch. It behaves similar to Update, @@ -734,9 +805,7 @@ retry: // pass success, or bolt internal errors, to all callers for _, c := range b.calls { - if c.err != nil { - c.err <- err - } + c.err <- err } break retry } @@ -823,7 +892,7 @@ func (db *DB) meta() *meta { } // allocate returns a contiguous block of memory starting at a given page. -func (db *DB) allocate(count int) (*page, error) { +func (db *DB) allocate(txid txid, count int) (*page, error) { // Allocate a temporary buffer for the page. var buf []byte if count == 1 { @@ -835,7 +904,7 @@ func (db *DB) allocate(count int) (*page, error) { p.overflow = uint32(count - 1) // Use pages from the freelist if they are available. - if p.id = db.freelist.allocate(count); p.id != 0 { + if p.id = db.freelist.allocate(txid, count); p.id != 0 { return p, nil } @@ -890,6 +959,38 @@ func (db *DB) IsReadOnly() bool { return db.readOnly } +func (db *DB) freepages() []pgid { + tx, err := db.beginTx() + defer func() { + err = tx.Rollback() + if err != nil { + panic("freepages: failed to rollback tx") + } + }() + if err != nil { + panic("freepages: failed to open read only tx") + } + + reachable := make(map[pgid]*page) + nofreed := make(map[pgid]bool) + ech := make(chan error) + go func() { + for e := range ech { + panic(fmt.Sprintf("freepages: failed to get all reachable pages (%v)", e)) + } + }() + tx.checkBucket(&tx.root, reachable, nofreed, ech) + close(ech) + + var fids []pgid + for i := pgid(2); i < db.meta().pgid; i++ { + if _, ok := reachable[i]; !ok { + fids = append(fids, i) + } + } + return fids +} + // Options represents the options that can be set when opening a database. type Options struct { // Timeout is the amount of time to wait to obtain a file lock. @@ -900,6 +1001,10 @@ type Options struct { // Sets the DB.NoGrowSync flag before memory mapping the file. NoGrowSync bool + // Do not sync freelist to disk. This improves the database write performance + // under normal operation, but requires a full database re-sync during recovery. + NoFreelistSync bool + // Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to // grab a shared lock (UNIX). ReadOnly bool @@ -916,6 +1021,14 @@ type Options struct { // If initialMmapSize is smaller than the previous database size, // it takes no effect. InitialMmapSize int + + // PageSize overrides the default OS page size. + PageSize int + + // NoSync sets the initial value of DB.NoSync. Normally this can just be + // set directly on the DB itself when returned from Open(), but this option + // is useful in APIs which expose Options but not the underlying DB. + NoSync bool } // DefaultOptions represent the options used if nil options are passed into Open(). @@ -952,15 +1065,11 @@ func (s *Stats) Sub(other *Stats) Stats { diff.PendingPageN = s.PendingPageN diff.FreeAlloc = s.FreeAlloc diff.FreelistInuse = s.FreelistInuse - diff.TxN = other.TxN - s.TxN + diff.TxN = s.TxN - other.TxN diff.TxStats = s.TxStats.Sub(&other.TxStats) return diff } -func (s *Stats) add(other *Stats) { - s.TxStats.add(&other.TxStats) -} - type Info struct { Data uintptr PageSize int @@ -999,7 +1108,8 @@ func (m *meta) copy(dest *meta) { func (m *meta) write(p *page) { if m.root.root >= m.pgid { panic(fmt.Sprintf("root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid)) - } else if m.freelist >= m.pgid { + } else if m.freelist >= m.pgid && m.freelist != pgidNoFreelist { + // TODO: reject pgidNoFreeList if !NoFreelistSync panic(fmt.Sprintf("freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid)) } @@ -1026,11 +1136,3 @@ func _assert(condition bool, msg string, v ...interface{}) { panic(fmt.Sprintf("assertion failed: "+msg, v...)) } } - -func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) } -func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) } - -func printstack() { - stack := strings.Join(strings.Split(string(debug.Stack()), "\n")[2:], "\n") - fmt.Fprintln(os.Stderr, stack) -} diff --git a/vendor/github.com/boltdb/bolt/doc.go b/vendor/go.etcd.io/bbolt/doc.go similarity index 94% rename from vendor/github.com/boltdb/bolt/doc.go rename to vendor/go.etcd.io/bbolt/doc.go index cc937845dba0d..95f25f01c6a48 100644 --- a/vendor/github.com/boltdb/bolt/doc.go +++ b/vendor/go.etcd.io/bbolt/doc.go @@ -1,5 +1,5 @@ /* -Package bolt implements a low-level key/value store in pure Go. It supports +package bbolt implements a low-level key/value store in pure Go. It supports fully serializable transactions, ACID semantics, and lock-free MVCC with multiple readers and a single writer. Bolt can be used for projects that want a simple data store without the need to add large dependencies such as @@ -41,4 +41,4 @@ point to different data or can point to invalid memory which will cause a panic. */ -package bolt +package bbolt diff --git a/vendor/github.com/boltdb/bolt/errors.go b/vendor/go.etcd.io/bbolt/errors.go similarity index 99% rename from vendor/github.com/boltdb/bolt/errors.go rename to vendor/go.etcd.io/bbolt/errors.go index a3620a3ebb296..48758ca5770b7 100644 --- a/vendor/github.com/boltdb/bolt/errors.go +++ b/vendor/go.etcd.io/bbolt/errors.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import "errors" diff --git a/vendor/github.com/boltdb/bolt/freelist.go b/vendor/go.etcd.io/bbolt/freelist.go similarity index 57% rename from vendor/github.com/boltdb/bolt/freelist.go rename to vendor/go.etcd.io/bbolt/freelist.go index d32f6cd937386..e4bcb2dcf9590 100644 --- a/vendor/github.com/boltdb/bolt/freelist.go +++ b/vendor/go.etcd.io/bbolt/freelist.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "fmt" @@ -6,25 +6,40 @@ import ( "unsafe" ) +// txPending holds a list of pgids and corresponding allocation txns +// that are pending to be freed. +type txPending struct { + ids []pgid + alloctx []txid // txids allocating the ids + lastReleaseBegin txid // beginning txid of last matching releaseRange +} + // freelist represents a list of all pages that are available for allocation. // It also tracks pages that have been freed but are still in use by open transactions. type freelist struct { - ids []pgid // all free and available free page ids. - pending map[txid][]pgid // mapping of soon-to-be free page ids by tx. - cache map[pgid]bool // fast lookup of all free and pending page ids. + ids []pgid // all free and available free page ids. + allocs map[pgid]txid // mapping of txid that allocated a pgid. + pending map[txid]*txPending // mapping of soon-to-be free page ids by tx. + cache map[pgid]bool // fast lookup of all free and pending page ids. } // newFreelist returns an empty, initialized freelist. func newFreelist() *freelist { return &freelist{ - pending: make(map[txid][]pgid), + allocs: make(map[pgid]txid), + pending: make(map[txid]*txPending), cache: make(map[pgid]bool), } } // size returns the size of the page after serialization. func (f *freelist) size() int { - return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * f.count()) + n := f.count() + if n >= 0xFFFF { + // The first element will be used to store the count. See freelist.write. + n++ + } + return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n) } // count returns count of pages on the freelist @@ -40,27 +55,26 @@ func (f *freelist) free_count() int { // pending_count returns count of pending pages func (f *freelist) pending_count() int { var count int - for _, list := range f.pending { - count += len(list) + for _, txp := range f.pending { + count += len(txp.ids) } return count } -// all returns a list of all free ids and all pending ids in one sorted list. -func (f *freelist) all() []pgid { - m := make(pgids, 0) - - for _, list := range f.pending { - m = append(m, list...) +// copyall copies into dst a list of all free ids and all pending ids in one sorted list. +// f.count returns the minimum length required for dst. +func (f *freelist) copyall(dst []pgid) { + m := make(pgids, 0, f.pending_count()) + for _, txp := range f.pending { + m = append(m, txp.ids...) } - sort.Sort(m) - return pgids(f.ids).merge(m) + mergepgids(dst, f.ids, m) } // allocate returns the starting page id of a contiguous list of pages of a given size. // If a contiguous block cannot be found then 0 is returned. -func (f *freelist) allocate(n int) pgid { +func (f *freelist) allocate(txid txid, n int) pgid { if len(f.ids) == 0 { return 0 } @@ -93,7 +107,7 @@ func (f *freelist) allocate(n int) pgid { for i := pgid(0); i < pgid(n); i++ { delete(f.cache, initial+i) } - + f.allocs[initial] = txid return initial } @@ -110,28 +124,73 @@ func (f *freelist) free(txid txid, p *page) { } // Free page and all its overflow pages. - var ids = f.pending[txid] + txp := f.pending[txid] + if txp == nil { + txp = &txPending{} + f.pending[txid] = txp + } + allocTxid, ok := f.allocs[p.id] + if ok { + delete(f.allocs, p.id) + } else if (p.flags & freelistPageFlag) != 0 { + // Freelist is always allocated by prior tx. + allocTxid = txid - 1 + } + for id := p.id; id <= p.id+pgid(p.overflow); id++ { // Verify that page is not already free. if f.cache[id] { panic(fmt.Sprintf("page %d already freed", id)) } - // Add to the freelist and cache. - ids = append(ids, id) + txp.ids = append(txp.ids, id) + txp.alloctx = append(txp.alloctx, allocTxid) f.cache[id] = true } - f.pending[txid] = ids } // release moves all page ids for a transaction id (or older) to the freelist. func (f *freelist) release(txid txid) { m := make(pgids, 0) - for tid, ids := range f.pending { + for tid, txp := range f.pending { if tid <= txid { // Move transaction's pending pages to the available freelist. // Don't remove from the cache since the page is still free. - m = append(m, ids...) + m = append(m, txp.ids...) + delete(f.pending, tid) + } + } + sort.Sort(m) + f.ids = pgids(f.ids).merge(m) +} + +// releaseRange moves pending pages allocated within an extent [begin,end] to the free list. +func (f *freelist) releaseRange(begin, end txid) { + if begin > end { + return + } + var m pgids + for tid, txp := range f.pending { + if tid < begin || tid > end { + continue + } + // Don't recompute freed pages if ranges haven't updated. + if txp.lastReleaseBegin == begin { + continue + } + for i := 0; i < len(txp.ids); i++ { + if atx := txp.alloctx[i]; atx < begin || atx > end { + continue + } + m = append(m, txp.ids[i]) + txp.ids[i] = txp.ids[len(txp.ids)-1] + txp.ids = txp.ids[:len(txp.ids)-1] + txp.alloctx[i] = txp.alloctx[len(txp.alloctx)-1] + txp.alloctx = txp.alloctx[:len(txp.alloctx)-1] + i-- + } + txp.lastReleaseBegin = begin + if len(txp.ids) == 0 { delete(f.pending, tid) } } @@ -142,12 +201,29 @@ func (f *freelist) release(txid txid) { // rollback removes the pages from a given pending tx. func (f *freelist) rollback(txid txid) { // Remove page ids from cache. - for _, id := range f.pending[txid] { - delete(f.cache, id) + txp := f.pending[txid] + if txp == nil { + return } - - // Remove pages from pending list. + var m pgids + for i, pgid := range txp.ids { + delete(f.cache, pgid) + tx := txp.alloctx[i] + if tx == 0 { + continue + } + if tx != txid { + // Pending free aborted; restore page back to alloc list. + f.allocs[pgid] = tx + } else { + // Freed page was allocated by this txn; OK to throw away. + m = append(m, pgid) + } + } + // Remove pages from pending list and mark as free if allocated by txid. delete(f.pending, txid) + sort.Sort(m) + f.ids = pgids(f.ids).merge(m) } // freed returns whether a given page is in the free list. @@ -157,6 +233,9 @@ func (f *freelist) freed(pgid pgid) bool { // read initializes the freelist from a freelist page. func (f *freelist) read(p *page) { + if (p.flags & freelistPageFlag) == 0 { + panic(fmt.Sprintf("invalid freelist page: %d, page type is %s", p.id, p.typ())) + } // If the page.count is at the max uint16 value (64k) then it's considered // an overflow and the size of the freelist is stored as the first element. idx, count := 0, int(p.count) @@ -169,7 +248,7 @@ func (f *freelist) read(p *page) { if count == 0 { f.ids = nil } else { - ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] + ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx : idx+count] f.ids = make([]pgid, len(ids)) copy(f.ids, ids) @@ -181,27 +260,33 @@ func (f *freelist) read(p *page) { f.reindex() } +// read initializes the freelist from a given list of ids. +func (f *freelist) readIDs(ids []pgid) { + f.ids = ids + f.reindex() +} + // write writes the page ids onto a freelist page. All free and pending ids are // saved to disk since in the event of a program crash, all pending ids will // become free. func (f *freelist) write(p *page) error { // Combine the old free pgids and pgids waiting on an open transaction. - ids := f.all() // Update the header flag. p.flags |= freelistPageFlag // The page.count can only hold up to 64k elements so if we overflow that // number then we handle it by putting the size in the first element. - if len(ids) == 0 { - p.count = uint16(len(ids)) - } else if len(ids) < 0xFFFF { - p.count = uint16(len(ids)) - copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids) + lenids := f.count() + if lenids == 0 { + p.count = uint16(lenids) + } else if lenids < 0xFFFF { + p.count = uint16(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:]) } else { p.count = 0xFFFF - ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(len(ids)) - copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:], ids) + ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:]) } return nil @@ -213,8 +298,8 @@ func (f *freelist) reload(p *page) { // Build a cache of only pending pages. pcache := make(map[pgid]bool) - for _, pendingIDs := range f.pending { - for _, pendingID := range pendingIDs { + for _, txp := range f.pending { + for _, pendingID := range txp.ids { pcache[pendingID] = true } } @@ -240,8 +325,8 @@ func (f *freelist) reindex() { for _, id := range f.ids { f.cache[id] = true } - for _, pendingIDs := range f.pending { - for _, pendingID := range pendingIDs { + for _, txp := range f.pending { + for _, pendingID := range txp.ids { f.cache[pendingID] = true } } diff --git a/vendor/github.com/boltdb/bolt/node.go b/vendor/go.etcd.io/bbolt/node.go similarity index 99% rename from vendor/github.com/boltdb/bolt/node.go rename to vendor/go.etcd.io/bbolt/node.go index 159318b229cbd..6c3fa553ea68d 100644 --- a/vendor/github.com/boltdb/bolt/node.go +++ b/vendor/go.etcd.io/bbolt/node.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "bytes" @@ -365,7 +365,7 @@ func (n *node) spill() error { } // Allocate contiguous space for the node. - p, err := tx.allocate((node.size() / tx.db.pageSize) + 1) + p, err := tx.allocate((node.size() + tx.db.pageSize - 1) / tx.db.pageSize) if err != nil { return err } diff --git a/vendor/github.com/boltdb/bolt/page.go b/vendor/go.etcd.io/bbolt/page.go similarity index 88% rename from vendor/github.com/boltdb/bolt/page.go rename to vendor/go.etcd.io/bbolt/page.go index 7651a6bf7d996..bca9615f0fd64 100644 --- a/vendor/github.com/boltdb/bolt/page.go +++ b/vendor/go.etcd.io/bbolt/page.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "fmt" @@ -145,12 +145,33 @@ func (a pgids) merge(b pgids) pgids { // Return the opposite slice if one is nil. if len(a) == 0 { return b - } else if len(b) == 0 { + } + if len(b) == 0 { return a } + merged := make(pgids, len(a)+len(b)) + mergepgids(merged, a, b) + return merged +} + +// mergepgids copies the sorted union of a and b into dst. +// If dst is too small, it panics. +func mergepgids(dst, a, b pgids) { + if len(dst) < len(a)+len(b) { + panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b))) + } + // Copy in the opposite slice if one is nil. + if len(a) == 0 { + copy(dst, b) + return + } + if len(b) == 0 { + copy(dst, a) + return + } - // Create a list to hold all elements from both lists. - merged := make(pgids, 0, len(a)+len(b)) + // Merged will hold all elements from both lists. + merged := dst[:0] // Assign lead to the slice with a lower starting value, follow to the higher value. lead, follow := a, b @@ -172,7 +193,5 @@ func (a pgids) merge(b pgids) pgids { } // Append what's left in follow. - merged = append(merged, follow...) - - return merged + _ = append(merged, follow...) } diff --git a/vendor/github.com/boltdb/bolt/tx.go b/vendor/go.etcd.io/bbolt/tx.go similarity index 93% rename from vendor/github.com/boltdb/bolt/tx.go rename to vendor/go.etcd.io/bbolt/tx.go index 1cfb4cde85559..f50864142762c 100644 --- a/vendor/github.com/boltdb/bolt/tx.go +++ b/vendor/go.etcd.io/bbolt/tx.go @@ -1,4 +1,4 @@ -package bolt +package bbolt import ( "fmt" @@ -126,10 +126,7 @@ func (tx *Tx) DeleteBucket(name []byte) error { // the error is returned to the caller. func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error { return tx.root.ForEach(func(k, v []byte) error { - if err := fn(k, tx.root.Bucket(k)); err != nil { - return err - } - return nil + return fn(k, tx.root.Bucket(k)) }) } @@ -169,28 +166,18 @@ func (tx *Tx) Commit() error { // Free the old root bucket. tx.meta.root.root = tx.root.root - opgid := tx.meta.pgid - - // Free the freelist and allocate new pages for it. This will overestimate - // the size of the freelist but not underestimate the size (which would be bad). - tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist)) - p, err := tx.allocate((tx.db.freelist.size() / tx.db.pageSize) + 1) - if err != nil { - tx.rollback() - return err - } - if err := tx.db.freelist.write(p); err != nil { - tx.rollback() - return err + // Free the old freelist because commit writes out a fresh freelist. + if tx.meta.freelist != pgidNoFreelist { + tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist)) } - tx.meta.freelist = p.id - // If the high water mark has moved up then attempt to grow the database. - if tx.meta.pgid > opgid { - if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil { - tx.rollback() + if !tx.db.NoFreelistSync { + err := tx.commitFreelist() + if err != nil { return err } + } else { + tx.meta.freelist = pgidNoFreelist } // Write dirty pages to disk. @@ -235,6 +222,31 @@ func (tx *Tx) Commit() error { return nil } +func (tx *Tx) commitFreelist() error { + // Allocate new pages for the new free list. This will overestimate + // the size of the freelist but not underestimate the size (which would be bad). + opgid := tx.meta.pgid + p, err := tx.allocate((tx.db.freelist.size() / tx.db.pageSize) + 1) + if err != nil { + tx.rollback() + return err + } + if err := tx.db.freelist.write(p); err != nil { + tx.rollback() + return err + } + tx.meta.freelist = p.id + // If the high water mark has moved up then attempt to grow the database. + if tx.meta.pgid > opgid { + if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil { + tx.rollback() + return err + } + } + + return nil +} + // Rollback closes the transaction and ignores all previous updates. Read-only // transactions must be rolled back and not committed. func (tx *Tx) Rollback() error { @@ -291,7 +303,9 @@ func (tx *Tx) close() { } // Copy writes the entire database to a writer. -// This function exists for backwards compatibility. Use WriteTo() instead. +// This function exists for backwards compatibility. +// +// Deprecated; Use WriteTo() instead. func (tx *Tx) Copy(w io.Writer) error { _, err := tx.WriteTo(w) return err @@ -305,7 +319,11 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { if err != nil { return 0, err } - defer func() { _ = f.Close() }() + defer func() { + if cerr := f.Close(); err == nil { + err = cerr + } + }() // Generate a meta page. We use the same page data for both meta pages. buf := make([]byte, tx.db.pageSize) @@ -333,7 +351,7 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { } // Move past the meta pages in the file. - if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil { + if _, err := f.Seek(int64(tx.db.pageSize*2), io.SeekStart); err != nil { return n, fmt.Errorf("seek: %s", err) } @@ -344,7 +362,7 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { return n, err } - return n, f.Close() + return n, nil } // CopyFile copies the entire database to file at the given path. @@ -379,9 +397,14 @@ func (tx *Tx) Check() <-chan error { } func (tx *Tx) check(ch chan error) { + // Force loading free list if opened in ReadOnly mode. + tx.db.loadFreelist() + // Check if any pages are double freed. freed := make(map[pgid]bool) - for _, id := range tx.db.freelist.all() { + all := make([]pgid, tx.db.freelist.count()) + tx.db.freelist.copyall(all) + for _, id := range all { if freed[id] { ch <- fmt.Errorf("page %d: already freed", id) } @@ -392,8 +415,10 @@ func (tx *Tx) check(ch chan error) { reachable := make(map[pgid]*page) reachable[0] = tx.page(0) // meta0 reachable[1] = tx.page(1) // meta1 - for i := uint32(0); i <= tx.page(tx.meta.freelist).overflow; i++ { - reachable[tx.meta.freelist+pgid(i)] = tx.page(tx.meta.freelist) + if tx.meta.freelist != pgidNoFreelist { + for i := uint32(0); i <= tx.page(tx.meta.freelist).overflow; i++ { + reachable[tx.meta.freelist+pgid(i)] = tx.page(tx.meta.freelist) + } } // Recursively check buckets. @@ -451,7 +476,7 @@ func (tx *Tx) checkBucket(b *Bucket, reachable map[pgid]*page, freed map[pgid]bo // allocate returns a contiguous block of memory starting at a given page. func (tx *Tx) allocate(count int) (*page, error) { - p, err := tx.db.allocate(count) + p, err := tx.db.allocate(tx.meta.txid, count) if err != nil { return nil, err } @@ -460,7 +485,7 @@ func (tx *Tx) allocate(count int) (*page, error) { tx.pages[p.id] = p // Update statistics. - tx.stats.PageCount++ + tx.stats.PageCount += count tx.stats.PageAlloc += count * tx.db.pageSize return p, nil diff --git a/volume/service/db.go b/volume/service/db.go index 3b31f7bf14871..d48ae544a4ebf 100644 --- a/volume/service/db.go +++ b/volume/service/db.go @@ -3,10 +3,10 @@ package service // import "github.com/docker/docker/volume/service" import ( "encoding/json" - "github.com/boltdb/bolt" "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" ) var volumeBucketName = []byte("volumes") diff --git a/volume/service/db_test.go b/volume/service/db_test.go index 4cac9176b75d0..8b6295adfd5c5 100644 --- a/volume/service/db_test.go +++ b/volume/service/db_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/boltdb/bolt" + bolt "go.etcd.io/bbolt" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/volume/service/restore.go b/volume/service/restore.go index 55c66c4f4287c..6741f9ec5fcb5 100644 --- a/volume/service/restore.go +++ b/volume/service/restore.go @@ -4,9 +4,9 @@ import ( "context" "sync" - "github.com/boltdb/bolt" "github.com/docker/docker/volume" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" ) // restore is called when a new volume store is created. diff --git a/volume/service/store.go b/volume/service/store.go index e7e9d8a3201dc..69a6c7bec98df 100644 --- a/volume/service/store.go +++ b/volume/service/store.go @@ -12,7 +12,6 @@ import ( "github.com/pkg/errors" - "github.com/boltdb/bolt" "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/locker" "github.com/docker/docker/volume" @@ -20,6 +19,7 @@ import ( volumemounts "github.com/docker/docker/volume/mounts" "github.com/docker/docker/volume/service/opts" "github.com/sirupsen/logrus" + bolt "go.etcd.io/bbolt" ) const (