bump up containerd (v1.0.0-beta.3)

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
docker-18.09
Akihiro Suda 2017-11-06 09:44:23 +00:00
parent 2898b24cab
commit c71a1ca768
178 changed files with 12675 additions and 1749 deletions

View File

@ -123,7 +123,7 @@ The `tonistiigi/buildkit:standalone` image can be built locally using the Docker
#### Supported runc version #### Supported runc version
During development buildkit is tested with the version of runc that is being used by the containerd repository. Please refer to [runc.md](https://github.com/containerd/containerd/blob/d1e11f17ec7b325f89608dd46c128300b8727d50/RUNC.md) for more information. During development buildkit is tested with the version of runc that is being used by the containerd repository. Please refer to [runc.md](https://github.com/containerd/containerd/blob/v1.0.0-beta.3/RUNC.md) for more information.
#### Contributing #### Contributing

View File

@ -3,8 +3,8 @@ package blobs
import ( import (
gocontext "context" gocontext "context"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/rootfs"
"github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache"
"github.com/moby/buildkit/snapshot" "github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/util/flightcontrol" "github.com/moby/buildkit/util/flightcontrol"
@ -27,7 +27,7 @@ type blobmapper interface {
SetBlob(ctx gocontext.Context, key string, diffID, blob digest.Digest) error SetBlob(ctx gocontext.Context, key string, diffID, blob digest.Digest) error
} }
func GetDiffPairs(ctx context.Context, snapshotter snapshot.Snapshotter, differ rootfs.MountDiffer, ref cache.ImmutableRef) ([]DiffPair, error) { func GetDiffPairs(ctx context.Context, snapshotter snapshot.Snapshotter, differ diff.Differ, ref cache.ImmutableRef) ([]DiffPair, error) {
blobmap, ok := snapshotter.(blobmapper) blobmap, ok := snapshotter.(blobmapper)
if !ok { if !ok {
return nil, errors.Errorf("image exporter requires snapshotter with blobs mapping support") return nil, errors.Errorf("image exporter requires snapshotter with blobs mapping support")
@ -71,7 +71,9 @@ func GetDiffPairs(ctx context.Context, snapshotter snapshot.Snapshotter, differ
if err != nil { if err != nil {
return nil, err return nil, err
} }
descr, err := differ.DiffMounts(ctx, lower, upper, ocispec.MediaTypeImageLayer, ref.ID()) descr, err := differ.DiffMounts(ctx, lower, upper,
diff.WithMediaType(ocispec.MediaTypeImageLayer),
diff.WithReference(ref.ID()))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -6,8 +6,8 @@ import (
"encoding/json" "encoding/json"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/rootfs"
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
"github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/manifest/schema2"
"github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache"
@ -38,7 +38,7 @@ type CacheRecord struct {
type ExporterOpt struct { type ExporterOpt struct {
Snapshotter snapshot.Snapshotter Snapshotter snapshot.Snapshotter
ContentStore content.Store ContentStore content.Store
Differ rootfs.MountDiffer Differ diff.Differ
SessionManager *session.Manager SessionManager *session.Manager
} }

View File

@ -7,9 +7,11 @@ import (
"time" "time"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker" "github.com/containerd/containerd/remotes/docker"
"github.com/containerd/containerd/rootfs" "github.com/containerd/containerd/rootfs"
cdsnapshot "github.com/containerd/containerd/snapshot"
"github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/blobs" "github.com/moby/buildkit/cache/blobs"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
@ -30,7 +32,7 @@ type ImportOpt struct {
SessionManager *session.Manager SessionManager *session.Manager
ContentStore content.Store ContentStore content.Store
Snapshotter snapshot.Snapshotter Snapshotter snapshot.Snapshotter
Applier rootfs.Applier Applier diff.Differ
CacheAccessor cache.Accessor CacheAccessor cache.Accessor
} }
@ -263,10 +265,18 @@ func (ii *importInfo) unpack(ctx context.Context, dpairs []blobs.DiffPair) (stri
return "", err return "", err
} }
chainID, err := rootfs.ApplyLayers(ctx, layers, ii.opt.Snapshotter, ii.opt.Applier) var chain []digest.Digest
if err != nil { for _, layer := range layers {
return "", err labels := map[string]string{
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
"containerd.io/uncompressed": layer.Diff.Digest.String(),
}
if _, err := rootfs.ApplyLayer(ctx, layer, chain, ii.opt.Snapshotter, ii.opt.Applier, cdsnapshot.WithLabels(labels)); err != nil {
return "", err
}
chain = append(chain, layer.Diff.Digest)
} }
chainID := identity.ChainID(chain)
if err := ii.fillBlobMapping(ctx, layers); err != nil { if err := ii.fillBlobMapping(ctx, layers); err != nil {
return "", err return "", err

View File

@ -33,7 +33,9 @@ func TestChecksumBasicFile(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
cm := setupCacheManager(t, tmpdir) snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
cm := setupCacheManager(t, tmpdir, snapshotter)
defer cm.Close() defer cm.Close()
ch := []string{ ch := []string{
@ -180,7 +182,9 @@ func TestHandleChange(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
cm := setupCacheManager(t, tmpdir) snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
cm := setupCacheManager(t, tmpdir, snapshotter)
defer cm.Close() defer cm.Close()
ch := []string{ ch := []string{
@ -255,7 +259,9 @@ func TestPersistence(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
cm := setupCacheManager(t, tmpdir) snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
cm := setupCacheManager(t, tmpdir, snapshotter)
defer cm.Close() defer cm.Close()
ch := []string{ ch := []string{
@ -289,9 +295,10 @@ func TestPersistence(t *testing.T) {
time.Sleep(100 * time.Millisecond) // saving happens on the background time.Sleep(100 * time.Millisecond) // saving happens on the background
// we can't close snapshotter and open it twice (especially, its internal boltdb store)
cm.Close() cm.Close()
getDefaultManager().lru.Purge() getDefaultManager().lru.Purge()
cm = setupCacheManager(t, tmpdir) cm = setupCacheManager(t, tmpdir, snapshotter)
defer cm.Close() defer cm.Close()
ref, err = cm.Get(context.TODO(), id) ref, err = cm.Get(context.TODO(), id)
@ -324,10 +331,7 @@ func createRef(t *testing.T, cm cache.Manager, files []string) cache.ImmutableRe
return ref return ref
} }
func setupCacheManager(t *testing.T, tmpdir string) cache.Manager { func setupCacheManager(t *testing.T, tmpdir string, snapshotter snapshot.Snapshotter) cache.Manager {
snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db")) md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
require.NoError(t, err) require.NoError(t, err)

5
cache/manager.go vendored
View File

@ -188,7 +188,10 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti
parentID = parent.ID() parentID = parent.ID()
} }
if _, err := cm.Snapshotter.Prepare(ctx, id, parentID); err != nil { labels := map[string]string{
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
}
if _, err := cm.Snapshotter.Prepare(ctx, id, parentID, cdsnapshot.WithLabels(labels)); err != nil {
if parent != nil { if parent != nil {
parent.Release(context.TODO()) parent.Release(context.TODO())
} }

18
cache/manager_test.go vendored
View File

@ -24,7 +24,9 @@ func TestManager(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
cm := getCacheManager(t, tmpdir) snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
cm := getCacheManager(t, tmpdir, snapshotter)
_, err = cm.Get(ctx, "foobar") _, err = cm.Get(ctx, "foobar")
require.Error(t, err) require.Error(t, err)
@ -132,7 +134,9 @@ func TestLazyCommit(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
cm := getCacheManager(t, tmpdir) snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
cm := getCacheManager(t, tmpdir, snapshotter)
active, err := cm.New(ctx, nil, CachePolicyRetain) active, err := cm.New(ctx, nil, CachePolicyRetain)
require.NoError(t, err) require.NoError(t, err)
@ -213,7 +217,8 @@ func TestLazyCommit(t *testing.T) {
err = cm.Close() err = cm.Close()
require.NoError(t, err) require.NoError(t, err)
cm = getCacheManager(t, tmpdir) // we can't close snapshotter and open it twice (especially, its internal boltdb store)
cm = getCacheManager(t, tmpdir, snapshotter)
snap2, err = cm.Get(ctx, snap.ID()) snap2, err = cm.Get(ctx, snap.ID())
require.NoError(t, err) require.NoError(t, err)
@ -234,7 +239,7 @@ func TestLazyCommit(t *testing.T) {
err = cm.Close() err = cm.Close()
require.NoError(t, err) require.NoError(t, err)
cm = getCacheManager(t, tmpdir) cm = getCacheManager(t, tmpdir, snapshotter)
snap2, err = cm.Get(ctx, snap.ID()) snap2, err = cm.Get(ctx, snap.ID())
require.NoError(t, err) require.NoError(t, err)
@ -250,10 +255,7 @@ func TestLazyCommit(t *testing.T) {
require.Equal(t, errNotFound, errors.Cause(err)) require.Equal(t, errNotFound, errors.Cause(err))
} }
func getCacheManager(t *testing.T, tmpdir string) Manager { func getCacheManager(t *testing.T, tmpdir string, snapshotter snapshot.Snapshotter) Manager {
snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
require.NoError(t, err)
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db")) md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
require.NoError(t, err) require.NoError(t, err)

7
cache/refs.go vendored
View File

@ -2,8 +2,10 @@ package cache
import ( import (
"sync" "sync"
"time"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
cdsnapshot "github.com/containerd/containerd/snapshot"
"github.com/moby/buildkit/cache/metadata" "github.com/moby/buildkit/cache/metadata"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/flightcontrol" "github.com/moby/buildkit/util/flightcontrol"
@ -134,7 +136,10 @@ func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount,
} }
if cr.viewMount == nil { // TODO: handle this better if cr.viewMount == nil { // TODO: handle this better
cr.view = identity.NewID() cr.view = identity.NewID()
m, err := cr.cm.Snapshotter.View(ctx, cr.view, cr.ID()) labels := map[string]string{
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
}
m, err := cr.cm.Snapshotter.View(ctx, cr.view, cr.ID(), cdsnapshot.WithLabels(labels))
if err != nil { if err != nil {
cr.view = "" cr.view = ""
return nil, errors.Wrapf(err, "failed to mount %s", cr.ID()) return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())

View File

@ -6,8 +6,8 @@ import (
"path/filepath" "path/filepath"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/rootfs"
ctdsnapshot "github.com/containerd/containerd/snapshot" ctdsnapshot "github.com/containerd/containerd/snapshot"
"github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache"
"github.com/moby/buildkit/cache/cacheimport" "github.com/moby/buildkit/cache/cacheimport"
@ -31,8 +31,8 @@ import (
type pullDeps struct { type pullDeps struct {
Snapshotter ctdsnapshot.Snapshotter Snapshotter ctdsnapshot.Snapshotter
ContentStore content.Store ContentStore content.Store
Applier rootfs.Applier Applier diff.Differ
Differ rootfs.MountDiffer Differ diff.Differ
Images images.Store Images images.Store
} }

View File

@ -8,7 +8,7 @@ import (
"path/filepath" "path/filepath"
"github.com/containerd/containerd/content/local" "github.com/containerd/containerd/content/local"
"github.com/containerd/containerd/differ" "github.com/containerd/containerd/diff/walking"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
ctdsnapshot "github.com/containerd/containerd/snapshot" ctdsnapshot "github.com/containerd/containerd/snapshot"
@ -55,7 +55,7 @@ func newStandalonePullDeps(root string) (*pullDeps, error) {
return nil, err return nil, err
} }
df, err := differ.NewWalkingDiff(c) df, err := walking.NewWalkingDiff(c)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -17,8 +17,8 @@ type buildOpt struct {
func main() { func main() {
var opt buildOpt var opt buildOpt
flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)") flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)")
flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.1", "containerd version") flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.3", "containerd version")
flag.StringVar(&opt.runc, "runc", "v1.0.0-rc4", "runc version") flag.StringVar(&opt.runc, "runc", "74a17296470088de3805e138d3d87c62e613dfc4", "runc version")
flag.Parse() flag.Parse()
bk := buildkit(opt) bk := buildkit(opt)

View File

@ -17,8 +17,8 @@ type buildOpt struct {
func main() { func main() {
var opt buildOpt var opt buildOpt
flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)") flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)")
flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.1", "containerd version") flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.3", "containerd version")
flag.StringVar(&opt.runc, "runc", "v1.0.0-rc4", "runc version") flag.StringVar(&opt.runc, "runc", "74a17296470088de3805e138d3d87c62e613dfc4", "runc version")
flag.Parse() flag.Parse()
bk := buildkit(opt) bk := buildkit(opt)

View File

@ -17,8 +17,8 @@ type buildOpt struct {
func main() { func main() {
var opt buildOpt var opt buildOpt
flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)") flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)")
flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.1", "containerd version") flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.3", "containerd version")
flag.StringVar(&opt.runc, "runc", "v1.0.0-rc4", "runc version") flag.StringVar(&opt.runc, "runc", "74a17296470088de3805e138d3d87c62e613dfc4", "runc version")
flag.Parse() flag.Parse()
bk := buildkit(opt) bk := buildkit(opt)

View File

@ -18,8 +18,8 @@ type buildOpt struct {
func main() { func main() {
var opt buildOpt var opt buildOpt
flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)") flag.StringVar(&opt.target, "target", "containerd", "target (standalone, containerd)")
flag.StringVar(&opt.containerd, "containerd", "v1.0.0-beta.1", "containerd version") flag.StringVar(&opt.containerd, "containerd", "ab67fd50dcb4c5b7ddb0c482c1ee542b0ed87e33", "containerd version")
flag.StringVar(&opt.runc, "runc", "v1.0.0-rc4", "runc version") flag.StringVar(&opt.runc, "runc", "74a17296470088de3805e138d3d87c62e613dfc4", "runc version")
flag.StringVar(&opt.buildkit, "buildkit", "master", "buildkit version") flag.StringVar(&opt.buildkit, "buildkit", "master", "buildkit version")
flag.Parse() flag.Parse()

View File

@ -7,9 +7,9 @@ import (
"time" "time"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/rootfs"
"github.com/docker/distribution" "github.com/docker/distribution"
"github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/manifest/schema2"
"github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache"
@ -38,7 +38,7 @@ type Opt struct {
SessionManager *session.Manager SessionManager *session.Manager
Snapshotter snapshot.Snapshotter Snapshotter snapshot.Snapshotter
ContentStore content.Store ContentStore content.Store
Differ rootfs.MountDiffer Differ diff.Differ
Images images.Store Images images.Store
} }

View File

@ -1,5 +1,5 @@
ARG RUNC_VERSION=e775f0fba3ea329b8b766451c892c41a3d49594d ARG RUNC_VERSION=74a17296470088de3805e138d3d87c62e613dfc4
ARG CONTAINERD_VERSION=d1e11f17ec7b325f89608dd46c128300b8727d50 ARG CONTAINERD_VERSION=v1.0.0-beta.3
ARG BUILDKIT_TARGET=standalone ARG BUILDKIT_TARGET=standalone
FROM golang:1.9-alpine AS gobuild-base FROM golang:1.9-alpine AS gobuild-base

View File

@ -48,7 +48,7 @@ func (lm *localMounter) Mount() (string, error) {
return "", errors.Wrap(err, "failed to create temp dir") return "", errors.Wrap(err, "failed to create temp dir")
} }
if err := mount.MountAll(lm.m, dir); err != nil { if err := mount.All(lm.m, dir); err != nil {
os.RemoveAll(dir) os.RemoveAll(dir)
return "", err return "", err
} }

View File

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
@ -35,7 +36,7 @@ type SourceOpt struct {
SessionManager *session.Manager SessionManager *session.Manager
Snapshotter snapshot.Snapshotter Snapshotter snapshot.Snapshotter
ContentStore content.Store ContentStore content.Store
Applier rootfs.Applier Applier diff.Differ
CacheAccessor cache.Accessor CacheAccessor cache.Accessor
} }
@ -195,7 +196,7 @@ func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
return nil, nil return nil, nil
}), }),
remotes.FetchHandler(p.is.ContentStore, fetcher), remotes.FetchHandler(p.is.ContentStore, fetcher),
images.ChildrenHandler(p.is.ContentStore), images.ChildrenHandler(p.is.ContentStore, platforms.Default()),
} }
if err := images.Dispatch(ctx, images.Handlers(handlers...), p.desc); err != nil { if err := images.Dispatch(ctx, images.Handlers(handlers...), p.desc); err != nil {
stopProgress() stopProgress()
@ -219,7 +220,18 @@ func (is *imageSource) unpack(ctx context.Context, desc ocispec.Descriptor) (str
return "", err return "", err
} }
chainID, err := rootfs.ApplyLayers(ctx, layers, is.Snapshotter, is.Applier) var chain []digest.Digest
for _, layer := range layers {
labels := map[string]string{
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
"containerd.io/uncompressed": layer.Diff.Digest.String(),
}
if _, err := rootfs.ApplyLayer(ctx, layer, chain, is.Snapshotter, is.Applier, snapshot.WithLabels(labels)); err != nil {
return "", err
}
chain = append(chain, layer.Diff.Digest)
}
chainID := identity.ChainID(chain)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -244,12 +256,12 @@ func (is *imageSource) fillBlobMapping(ctx context.Context, layers []rootfs.Laye
} }
func getLayers(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]rootfs.Layer, error) { func getLayers(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]rootfs.Layer, error) {
manifest, err := images.Manifest(ctx, provider, desc, platforms.Format(platforms.Default())) manifest, err := images.Manifest(ctx, provider, desc, platforms.Default())
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStack(err)
} }
image := images.Image{Target: desc} image := images.Image{Target: desc}
diffIDs, err := image.RootFS(ctx, provider, platforms.Format(platforms.Default())) diffIDs, err := image.RootFS(ctx, provider, platforms.Default())
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to resolve rootfs") return nil, errors.Wrap(err, "failed to resolve rootfs")
} }

View File

@ -61,7 +61,7 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, ingester
if err := images.Dispatch(ctx, images.Handlers(handlers...), *desc); err != nil { if err := images.Dispatch(ctx, images.Handlers(handlers...), *desc); err != nil {
return "", nil, err return "", nil, err
} }
config, err := images.Config(ctx, ingester, *desc, platforms.Format(platforms.Default())) config, err := images.Config(ctx, ingester, *desc, platforms.Default())
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }

View File

@ -69,7 +69,7 @@ func Push(ctx context.Context, sm *session.Manager, cs content.Store, dgst diges
m.Lock() m.Lock()
manifestStack = append(manifestStack, desc) manifestStack = append(manifestStack, desc)
m.Unlock() m.Unlock()
return nil, images.StopHandler return nil, images.ErrStopHandler
default: default:
return nil, nil return nil, nil
} }

View File

@ -6,7 +6,8 @@ github.com/davecgh/go-spew v1.1.0
github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib v1.0.0
golang.org/x/sys 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce golang.org/x/sys 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce
github.com/containerd/containerd d1e11f17ec7b325f89608dd46c128300b8727d50 github.com/containerd/containerd v1.0.0-beta.3
github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
github.com/sirupsen/logrus v1.0.0 github.com/sirupsen/logrus v1.0.0
google.golang.org/grpc v1.3.0 google.golang.org/grpc v1.3.0
@ -46,4 +47,4 @@ github.com/docker/distribution 30578ca32960a4d368bf6db67b0a33c2a1f3dc6f
github.com/tonistiigi/units 29de085e9400559bd68aea2e7bc21566e7b8281d github.com/tonistiigi/units 29de085e9400559bd68aea2e7bc21566e7b8281d
github.com/docker/cli 99576756eb3303b7af8102c502f21a912e3c1af6 https://github.com/tonistiigi/docker-cli.git github.com/docker/cli 99576756eb3303b7af8102c502f21a912e3c1af6 https://github.com/tonistiigi/docker-cli.git
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1 github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1

View File

@ -1,4 +1,4 @@
Attribution-ShareAlike 4.0 International Attribution 4.0 International
======================================================================= =======================================================================
@ -54,18 +54,16 @@ exhaustive, and do not form part of our licenses.
======================================================================= =======================================================================
Creative Commons Attribution-ShareAlike 4.0 International Public Creative Commons Attribution 4.0 International Public License
License
By exercising the Licensed Rights (defined below), You accept and agree By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public Attribution 4.0 International Public License ("Public License"). To the
License"). To the extent this Public License may be interpreted as a extent this Public License may be interpreted as a contract, You are
contract, You are granted the Licensed Rights in consideration of Your granted the Licensed Rights in consideration of Your acceptance of
acceptance of these terms and conditions, and the Licensor grants You these terms and conditions, and the Licensor grants You such rights in
such rights in consideration of benefits the Licensor receives from consideration of benefits the Licensor receives from making the
making the Licensed Material available under these terms and Licensed Material available under these terms and conditions.
conditions.
Section 1 -- Definitions. Section 1 -- Definitions.
@ -84,11 +82,7 @@ Section 1 -- Definitions.
and Similar Rights in Your contributions to Adapted Material in and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License. accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at c. Copyright and Similar Rights means copyright and/or similar rights
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation, closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or Rights, without regard to how the rights are labeled or
@ -96,33 +90,29 @@ Section 1 -- Definitions.
specified in Section 2(b)(1)-(2) are not Copyright and Similar specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights. Rights.
e. Effective Technological Measures means those measures that, in the d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international Treaty adopted on December 20, 1996, and/or similar international
agreements. agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material. that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name f. Licensed Material means the artistic or literary work, database,
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public or other material to which the Licensor applied this Public
License. License.
i. Licensed Rights means the rights granted to You subject to the g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license. Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License. under this Public License.
k. Share means to provide material to the public by any means or i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution, as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material dissemination, communication, or importation, and to make material
@ -130,13 +120,13 @@ Section 1 -- Definitions.
public may access the material from a place and at a time public may access the material from a place and at a time
individually chosen by them. individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases, the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world. equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning. under this Public License. Your has a corresponding meaning.
@ -182,13 +172,7 @@ Section 2 -- Scope.
Licensed Rights under the terms and conditions of this Licensed Rights under the terms and conditions of this
Public License. Public License.
b. Additional offer from the Licensor -- Adapted Material. b. No downstream restrictions. You may not offer or impose
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the Licensed Material if doing so restricts exercise of the
@ -270,24 +254,9 @@ following conditions.
information required by Section 3(a)(1)(A) to the extent information required by Section 3(a)(1)(A) to the extent
reasonably practicable. reasonably practicable.
b. ShareAlike. 4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
In addition to the conditions in Section 3(a), if You Share Material from complying with this Public License.
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights. Section 4 -- Sui Generis Database Rights.
@ -302,9 +271,8 @@ apply to Your use of the Licensed Material:
b. if You include all or a substantial portion of the database b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material, Rights (but not its individual contents) is Adapted Material; and
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database. all or a substantial portion of the contents of the database.
@ -407,11 +375,13 @@ Section 8 -- Interpretation.
======================================================================= =======================================================================
Creative Commons is not a party to its public licenses. Creative Commons is not a party to its public
Notwithstanding, Creative Commons may elect to apply one of its public licenses. Notwithstanding, Creative Commons may elect to apply one of
licenses to material it publishes and in those instances will be its public licenses to material it publishes and in those instances
considered the "Licensor." Except for the limited purpose of indicating will be considered the “Licensor.” The text of the Creative Commons
that material is shared under a Creative Commons public license or as public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo use of the trademark "Creative Commons" or any other trademark or logo
@ -419,7 +389,7 @@ of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements, to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the public the avoidance of doubt, this paragraph does not form part of the
licenses. public licenses.
Creative Commons may be contacted at creativecommons.org. Creative Commons may be contacted at creativecommons.org.

View File

@ -9,6 +9,8 @@ containerd is an industry-standard container runtime with an emphasis on simplic
containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users. containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users.
![architecture](design/architecture.png)
## Getting Started ## Getting Started
If you are interested in trying out containerd please see our [Getting Started Guide](docs/getting-started.md). If you are interested in trying out containerd please see our [Getting Started Guide](docs/getting-started.md).
@ -79,7 +81,7 @@ You can specify options when creating a container about how to modify the specif
redis, err := client.NewContainer(context, "redis-master", containerd.WithNewSpec(containerd.WithImageConfig(image))) redis, err := client.NewContainer(context, "redis-master", containerd.WithNewSpec(containerd.WithImageConfig(image)))
``` ```
## Root Filesystems ### Root Filesystems
containerd allows you to use overlay or snapshot filesystems with your containers. It comes with builtin support for overlayfs and btrfs. containerd allows you to use overlay or snapshot filesystems with your containers. It comes with builtin support for overlayfs and btrfs.
@ -148,11 +150,11 @@ defer task.Delete(context)
err := task.Start(context) err := task.Start(context)
``` ```
### Developer Quick-Start ## Developer Quick-Start
To build the daemon and `ctr` simple test client, the following build system dependencies are required: To build the daemon and `ctr` simple test client, the following build system dependencies are required:
* Go 1.8.x or above (requires 1.8 due to use of golang plugin(s)) * Go 1.9.x or above
* Protoc 3.x compiler and headers (download at the [Google protobuf releases page](https://github.com/google/protobuf/releases)) * Protoc 3.x compiler and headers (download at the [Google protobuf releases page](https://github.com/google/protobuf/releases))
* Btrfs headers and libraries for your distribution. Note that building the btrfs driver can be disabled via build tag removing this dependency. * Btrfs headers and libraries for your distribution. Note that building the btrfs driver can be disabled via build tag removing this dependency.
@ -194,14 +196,12 @@ For sync communication we have a community slack with a #containerd channel that
### Reporting security issues ### Reporting security issues
__If you are reporting a security issue, please follow the responsible __If you are reporting a security issue, please reach out discreetly at security@containerd.io__.
disclosure guidelines and reach out discreetly at containerd-security@googlegroups.com__.
## Copyright and license ## Licenses
Copyright ©2016-2017 Docker, Inc. All rights reserved, except as follows. Code The containerd codebase is released under the [Apache 2.0 license](LICENSE.code).
is released under the Apache 2.0 license. The README.md file, and files in the The README.md file, and files in the "docs" folder are licensed under the
"docs" folder are licensed under the Creative Commons Attribution 4.0 Creative Commons Attribution 4.0 International License under the terms and
International License under the terms and conditions set forth in the file conditions set forth in the file "[LICENSE.docs](LICENSE.docs)". You may obtain a duplicate
"LICENSE.docs". You may obtain a duplicate copy of the same license, titled copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.
CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.

View File

@ -65,6 +65,8 @@ type Container struct {
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// Labels provides an area to include arbitrary data on containers. // Labels provides an area to include arbitrary data on containers.
// //
// The combined size of a key/value pair cannot exceed 4096 bytes.
//
// Note that to add a new value to this field, read the existing set and // Note that to add a new value to this field, read the existing set and
// include the entire result in the update call. // include the entire result in the update call.
Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
@ -94,6 +96,16 @@ type Container struct {
CreatedAt time.Time `protobuf:"bytes,8,opt,name=created_at,json=createdAt,stdtime" json:"created_at"` CreatedAt time.Time `protobuf:"bytes,8,opt,name=created_at,json=createdAt,stdtime" json:"created_at"`
// UpdatedAt is the last time the container was mutated. // UpdatedAt is the last time the container was mutated.
UpdatedAt time.Time `protobuf:"bytes,9,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"` UpdatedAt time.Time `protobuf:"bytes,9,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"`
// Extensions allow clients to provide zero or more blobs that are directly
// associated with the container. One may provide protobuf, json, or other
// encoding formats. The primary use of this is to further decorate the
// container object with fields that may be specific to a client integration.
//
// The key portion of this map should identify a "name" for the extension
// that should be unique against other extensions. When updating extension
// data, one should only update the specified extension using field paths
// to select a specific map key.
Extensions map[string]google_protobuf1.Any `protobuf:"bytes,10,rep,name=extensions" json:"extensions" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
} }
func (m *Container) Reset() { *m = Container{} } func (m *Container) Reset() { *m = Container{} }
@ -518,6 +530,32 @@ func (m *Container) MarshalTo(dAtA []byte) (int, error) {
return 0, err return 0, err
} }
i += n4 i += n4
if len(m.Extensions) > 0 {
for k, _ := range m.Extensions {
dAtA[i] = 0x52
i++
v := m.Extensions[k]
msgSize := 0
if (&v) != nil {
msgSize = (&v).Size()
msgSize += 1 + sovContainers(uint64(msgSize))
}
mapSize := 1 + len(k) + sovContainers(uint64(len(k))) + msgSize
i = encodeVarintContainers(dAtA, i, uint64(mapSize))
dAtA[i] = 0xa
i++
i = encodeVarintContainers(dAtA, i, uint64(len(k)))
i += copy(dAtA[i:], k)
dAtA[i] = 0x12
i++
i = encodeVarintContainers(dAtA, i, uint64((&v).Size()))
n5, err := (&v).MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n5
}
}
return i, nil return i, nil
} }
@ -546,11 +584,11 @@ func (m *Container_Runtime) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.Options.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.Options.Size()))
n5, err := m.Options.MarshalTo(dAtA[i:]) n6, err := m.Options.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n5 i += n6
} }
return i, nil return i, nil
} }
@ -597,11 +635,11 @@ func (m *GetContainerResponse) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size()))
n6, err := m.Container.MarshalTo(dAtA[i:]) n7, err := m.Container.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n6 i += n7
return i, nil return i, nil
} }
@ -686,11 +724,11 @@ func (m *CreateContainerRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size()))
n7, err := m.Container.MarshalTo(dAtA[i:]) n8, err := m.Container.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n7 i += n8
return i, nil return i, nil
} }
@ -712,11 +750,11 @@ func (m *CreateContainerResponse) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size()))
n8, err := m.Container.MarshalTo(dAtA[i:]) n9, err := m.Container.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n8 i += n9
return i, nil return i, nil
} }
@ -738,20 +776,20 @@ func (m *UpdateContainerRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size()))
n9, err := m.Container.MarshalTo(dAtA[i:]) n10, err := m.Container.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n9 i += n10
if m.UpdateMask != nil { if m.UpdateMask != nil {
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.UpdateMask.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.UpdateMask.Size()))
n10, err := m.UpdateMask.MarshalTo(dAtA[i:]) n11, err := m.UpdateMask.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n10 i += n11
} }
return i, nil return i, nil
} }
@ -774,11 +812,11 @@ func (m *UpdateContainerResponse) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size())) i = encodeVarintContainers(dAtA, i, uint64(m.Container.Size()))
n11, err := m.Container.MarshalTo(dAtA[i:]) n12, err := m.Container.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n11 i += n12
return i, nil return i, nil
} }
@ -872,6 +910,15 @@ func (m *Container) Size() (n int) {
n += 1 + l + sovContainers(uint64(l)) n += 1 + l + sovContainers(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt) l = github_com_gogo_protobuf_types.SizeOfStdTime(m.UpdatedAt)
n += 1 + l + sovContainers(uint64(l)) n += 1 + l + sovContainers(uint64(l))
if len(m.Extensions) > 0 {
for k, v := range m.Extensions {
_ = k
_ = v
l = v.Size()
mapEntrySize := 1 + len(k) + sovContainers(uint64(len(k))) + 1 + l + sovContainers(uint64(l))
n += mapEntrySize + 1 + sovContainers(uint64(mapEntrySize))
}
}
return n return n
} }
@ -1004,6 +1051,16 @@ func (this *Container) String() string {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
} }
mapStringForLabels += "}" mapStringForLabels += "}"
keysForExtensions := make([]string, 0, len(this.Extensions))
for k, _ := range this.Extensions {
keysForExtensions = append(keysForExtensions, k)
}
github_com_gogo_protobuf_sortkeys.Strings(keysForExtensions)
mapStringForExtensions := "map[string]google_protobuf1.Any{"
for _, k := range keysForExtensions {
mapStringForExtensions += fmt.Sprintf("%v: %v,", k, this.Extensions[k])
}
mapStringForExtensions += "}"
s := strings.Join([]string{`&Container{`, s := strings.Join([]string{`&Container{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`, `ID:` + fmt.Sprintf("%v", this.ID) + `,`,
`Labels:` + mapStringForLabels + `,`, `Labels:` + mapStringForLabels + `,`,
@ -1014,6 +1071,7 @@ func (this *Container) String() string {
`SnapshotKey:` + fmt.Sprintf("%v", this.SnapshotKey) + `,`, `SnapshotKey:` + fmt.Sprintf("%v", this.SnapshotKey) + `,`,
`CreatedAt:` + strings.Replace(strings.Replace(this.CreatedAt.String(), "Timestamp", "google_protobuf4.Timestamp", 1), `&`, ``, 1) + `,`, `CreatedAt:` + strings.Replace(strings.Replace(this.CreatedAt.String(), "Timestamp", "google_protobuf4.Timestamp", 1), `&`, ``, 1) + `,`,
`UpdatedAt:` + strings.Replace(strings.Replace(this.UpdatedAt.String(), "Timestamp", "google_protobuf4.Timestamp", 1), `&`, ``, 1) + `,`, `UpdatedAt:` + strings.Replace(strings.Replace(this.UpdatedAt.String(), "Timestamp", "google_protobuf4.Timestamp", 1), `&`, ``, 1) + `,`,
`Extensions:` + mapStringForExtensions + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -1515,6 +1573,127 @@ func (m *Container) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 10:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Extensions", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowContainers
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthContainers
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
var keykey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowContainers
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
keykey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowContainers
}
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 ErrInvalidLengthContainers
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
if m.Extensions == nil {
m.Extensions = make(map[string]google_protobuf1.Any)
}
if iNdEx < postIndex {
var valuekey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowContainers
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
valuekey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var mapmsglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowContainers
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapmsglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if mapmsglen < 0 {
return ErrInvalidLengthContainers
}
postmsgIndex := iNdEx + mapmsglen
if mapmsglen < 0 {
return ErrInvalidLengthContainers
}
if postmsgIndex > l {
return io.ErrUnexpectedEOF
}
mapvalue := &google_protobuf1.Any{}
if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
return err
}
iNdEx = postmsgIndex
m.Extensions[mapkey] = *mapvalue
} else {
var mapvalue google_protobuf1.Any
m.Extensions[mapkey] = mapvalue
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipContainers(dAtA[iNdEx:]) skippy, err := skipContainers(dAtA[iNdEx:])
@ -2509,51 +2688,54 @@ func init() {
} }
var fileDescriptorContainers = []byte{ var fileDescriptorContainers = []byte{
// 730 bytes of a gzipped FileDescriptorProto // 776 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcb, 0x72, 0x12, 0x41, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0xcd, 0x72, 0x12, 0x5b,
0x14, 0xcd, 0xc0, 0x04, 0xc2, 0xc5, 0x85, 0xd5, 0x22, 0x8e, 0x63, 0x15, 0x10, 0x56, 0x2c, 0x74, 0x10, 0xce, 0x00, 0x81, 0xd0, 0xdc, 0xaa, 0x7b, 0xeb, 0x5c, 0x2e, 0x77, 0x1c, 0xab, 0x80, 0xb0,
0x30, 0x68, 0x69, 0x1e, 0xab, 0x90, 0x57, 0x59, 0x26, 0x56, 0xaa, 0x4b, 0x37, 0xba, 0x88, 0x0d, 0xa2, 0x2c, 0x1d, 0x0c, 0x5a, 0x9a, 0x1f, 0x37, 0x21, 0x7f, 0x65, 0x99, 0x58, 0xa9, 0x51, 0x37,
0x74, 0xc8, 0xc8, 0xbc, 0x9c, 0x6e, 0xa8, 0xa2, 0x5c, 0xe8, 0x27, 0xf8, 0x17, 0xfe, 0x4a, 0x96, 0xba, 0x88, 0x03, 0x74, 0xc8, 0xc8, 0xfc, 0x39, 0xe7, 0x40, 0x49, 0xb9, 0xd0, 0x47, 0x70, 0xe7,
0x2e, 0x5d, 0xc5, 0x84, 0x2f, 0xb1, 0xba, 0x67, 0x26, 0x43, 0x78, 0x94, 0x10, 0x65, 0x77, 0x2f, 0x23, 0xf8, 0x2a, 0x59, 0xba, 0x74, 0x15, 0x13, 0x9e, 0xc4, 0x9a, 0x33, 0x33, 0xcc, 0x04, 0x06,
0x7d, 0xcf, 0xbd, 0x67, 0x4e, 0x9f, 0x3b, 0x0c, 0x1c, 0xb6, 0x4d, 0x7e, 0xd6, 0x6d, 0x18, 0x4d, 0x85, 0x68, 0x76, 0xa7, 0x39, 0xfd, 0x7d, 0xfd, 0xf1, 0x75, 0xf7, 0x01, 0xd8, 0xef, 0x68, 0xec,
0xd7, 0xae, 0x36, 0x5d, 0x87, 0x13, 0xd3, 0xa1, 0x7e, 0x6b, 0x38, 0x24, 0x9e, 0x59, 0x65, 0xd4, 0xa4, 0xd7, 0x94, 0x5b, 0x96, 0x51, 0x6b, 0x59, 0x26, 0x53, 0x35, 0x13, 0x9d, 0x76, 0xf4, 0xa8,
0xef, 0x99, 0x4d, 0xca, 0xe2, 0xdf, 0x59, 0xb5, 0xb7, 0x36, 0x94, 0x19, 0x9e, 0xef, 0x72, 0x17, 0xda, 0x5a, 0x8d, 0xa2, 0xd3, 0xd7, 0x5a, 0x48, 0xc3, 0xcf, 0x69, 0xad, 0xbf, 0x12, 0x89, 0x64,
0xad, 0xc6, 0x38, 0x23, 0xc2, 0x18, 0x43, 0x55, 0xbd, 0x35, 0x3d, 0xd7, 0x76, 0xdb, 0xae, 0xac, 0xdb, 0xb1, 0x98, 0x45, 0x96, 0x43, 0x9c, 0x1c, 0x60, 0xe4, 0x48, 0x56, 0x7f, 0x45, 0xca, 0x77,
0xae, 0x8a, 0x28, 0x00, 0xea, 0x0f, 0xdb, 0xae, 0xdb, 0xb6, 0x68, 0x55, 0x66, 0x8d, 0xee, 0x69, 0xac, 0x8e, 0xc5, 0xb3, 0x6b, 0xee, 0xc9, 0x03, 0x4a, 0x37, 0x3a, 0x96, 0xd5, 0xd1, 0xb1, 0xc6,
0x95, 0x38, 0xfd, 0xf0, 0xe8, 0xd1, 0xe8, 0x11, 0xb5, 0x3d, 0x1e, 0x1d, 0x96, 0x46, 0x0f, 0x4f, 0xa3, 0x66, 0xef, 0xb8, 0xa6, 0x9a, 0x03, 0xff, 0xea, 0xe6, 0xf8, 0x15, 0x1a, 0x36, 0x0b, 0x2e,
0x4d, 0x6a, 0xb5, 0x4e, 0x6c, 0xc2, 0x3a, 0x61, 0x45, 0x71, 0xb4, 0x82, 0x9b, 0x36, 0x65, 0x9c, 0xcb, 0xe3, 0x97, 0xc7, 0x1a, 0xea, 0xed, 0x23, 0x43, 0xa5, 0x5d, 0x3f, 0xa3, 0x34, 0x9e, 0xc1,
0xd8, 0x5e, 0x50, 0x50, 0xbe, 0x50, 0x21, 0xb3, 0x13, 0x51, 0x44, 0x79, 0x48, 0x98, 0x2d, 0x4d, 0x34, 0x03, 0x29, 0x53, 0x0d, 0xdb, 0x4b, 0xa8, 0x7c, 0x4e, 0x43, 0x76, 0x2b, 0x90, 0x48, 0x0a,
0x29, 0x29, 0x95, 0x4c, 0x3d, 0x35, 0xb8, 0x28, 0x26, 0x5e, 0xed, 0xe2, 0x84, 0xd9, 0x42, 0xc7, 0x90, 0xd0, 0xda, 0xa2, 0x50, 0x16, 0xaa, 0xd9, 0x46, 0x7a, 0x78, 0x56, 0x4a, 0x3c, 0xde, 0x56,
0x90, 0xb2, 0x48, 0x83, 0x5a, 0x4c, 0x4b, 0x94, 0x92, 0x95, 0x6c, 0x6d, 0xdd, 0xf8, 0xeb, 0xa3, 0x12, 0x5a, 0x9b, 0x1c, 0x42, 0x5a, 0x57, 0x9b, 0xa8, 0x53, 0x31, 0x51, 0x4e, 0x56, 0x73, 0xf5,
0x1a, 0xd7, 0x5d, 0x8d, 0x43, 0x09, 0xdd, 0x73, 0xb8, 0xdf, 0xc7, 0x61, 0x1f, 0x94, 0x83, 0x65, 0x55, 0xf9, 0x97, 0x5f, 0x55, 0x1e, 0xb1, 0xca, 0xfb, 0x1c, 0xba, 0x63, 0x32, 0x67, 0xa0, 0xf8,
0xd3, 0x26, 0x6d, 0xaa, 0x25, 0xc5, 0x30, 0x1c, 0x24, 0xe8, 0x0d, 0xa4, 0xfd, 0xae, 0x23, 0x38, 0x3c, 0x24, 0x0f, 0x8b, 0x9a, 0xa1, 0x76, 0x50, 0x4c, 0xba, 0xc5, 0x14, 0x2f, 0x20, 0x4f, 0x21,
0x6a, 0x6a, 0x49, 0xa9, 0x64, 0x6b, 0xcf, 0xe7, 0x1a, 0x84, 0x03, 0x2c, 0x8e, 0x9a, 0xa0, 0x0a, 0xe3, 0xf4, 0x4c, 0x57, 0xa3, 0x98, 0x2a, 0x0b, 0xd5, 0x5c, 0xfd, 0xfe, 0x5c, 0x85, 0x14, 0x0f,
0xa8, 0xcc, 0xa3, 0x4d, 0x6d, 0x59, 0x36, 0xcb, 0x19, 0x81, 0x1a, 0x46, 0xa4, 0x86, 0xb1, 0xed, 0xab, 0x04, 0x24, 0xa4, 0x0a, 0x29, 0x6a, 0x63, 0x4b, 0x5c, 0xe4, 0x64, 0x79, 0xd9, 0x73, 0x43,
0xf4, 0xb1, 0xac, 0x40, 0x25, 0xc8, 0x32, 0x87, 0x78, 0xec, 0xcc, 0xe5, 0x9c, 0xfa, 0x5a, 0x4a, 0x0e, 0xdc, 0x90, 0x37, 0xcd, 0x81, 0xc2, 0x33, 0x48, 0x19, 0x72, 0xd4, 0x54, 0x6d, 0x7a, 0x62,
0xb2, 0x1a, 0xfe, 0x09, 0xad, 0xc2, 0x9d, 0x28, 0x3d, 0xe9, 0xd0, 0xbe, 0x96, 0xbe, 0x59, 0xf2, 0x31, 0x86, 0x8e, 0x98, 0xe6, 0xaa, 0xa2, 0x1f, 0x91, 0x65, 0xf8, 0x2b, 0x08, 0x8f, 0xba, 0x38,
0x9a, 0xf6, 0xd1, 0x0e, 0x40, 0xd3, 0xa7, 0x84, 0xd3, 0xd6, 0x09, 0xe1, 0xda, 0x8a, 0x1c, 0xaa, 0x10, 0x33, 0x97, 0x53, 0x9e, 0xe0, 0x80, 0x6c, 0x01, 0xb4, 0x1c, 0x54, 0x19, 0xb6, 0x8f, 0x54,
0x8f, 0x0d, 0x7d, 0x1b, 0x5d, 0x41, 0x7d, 0xe5, 0xfc, 0xa2, 0xb8, 0xf4, 0xfd, 0x77, 0x51, 0xc1, 0x26, 0x2e, 0xf1, 0xa2, 0xd2, 0x44, 0xd1, 0xe7, 0x41, 0x0b, 0x1a, 0x4b, 0xa7, 0x67, 0xa5, 0x85,
0x99, 0x10, 0xb7, 0xcd, 0x45, 0x93, 0xae, 0xd7, 0x8a, 0x9a, 0x64, 0xe6, 0x69, 0x12, 0xe2, 0xb6, 0x4f, 0xdf, 0x4b, 0x82, 0x92, 0xf5, 0x71, 0x9b, 0xcc, 0x25, 0xe9, 0xd9, 0xed, 0x80, 0x24, 0x3b,
0xb9, 0xbe, 0x01, 0xd9, 0x21, 0xd5, 0xd1, 0x5d, 0x48, 0x0a, 0xca, 0xf2, 0x62, 0xb1, 0x08, 0x85, 0x0f, 0x89, 0x8f, 0xdb, 0x64, 0xa4, 0x09, 0x80, 0xef, 0x18, 0x9a, 0x54, 0xb3, 0x4c, 0x2a, 0x02,
0xfe, 0x3d, 0x62, 0x75, 0xa9, 0x96, 0x08, 0xf4, 0x97, 0xc9, 0x66, 0x62, 0x5d, 0xd1, 0x8f, 0x20, 0x6f, 0xda, 0xa3, 0xb9, 0xbc, 0xdc, 0x19, 0xc1, 0x79, 0xe3, 0x1a, 0x29, 0xb7, 0x8c, 0x12, 0x61,
0x1d, 0xea, 0x88, 0x10, 0xa8, 0x0e, 0xb1, 0x69, 0x88, 0x93, 0x31, 0x32, 0x20, 0xed, 0x7a, 0xdc, 0x95, 0xd6, 0x20, 0x17, 0xe9, 0x2c, 0xf9, 0x07, 0x92, 0xae, 0x2d, 0x7c, 0x78, 0x14, 0xf7, 0xe8,
0x74, 0x1d, 0x26, 0xa1, 0xd3, 0x54, 0x8d, 0x8a, 0xca, 0x4f, 0xe0, 0xde, 0x01, 0xe5, 0xd7, 0x77, 0xf6, 0xb8, 0xaf, 0xea, 0x3d, 0x14, 0x13, 0x5e, 0x8f, 0x79, 0xb0, 0x9e, 0x58, 0x15, 0xa4, 0x03,
0x84, 0xe9, 0xe7, 0x2e, 0x65, 0x7c, 0x9a, 0xd3, 0xca, 0x67, 0x90, 0xbb, 0x59, 0xce, 0x3c, 0xd7, 0xc8, 0xf8, 0xbd, 0x22, 0x04, 0x52, 0xa6, 0x6a, 0xa0, 0x8f, 0xe3, 0x67, 0x22, 0x43, 0xc6, 0xb2,
0x61, 0x14, 0x1d, 0x43, 0xe6, 0xfa, 0xd6, 0x25, 0x2c, 0x5b, 0x7b, 0x3c, 0x8f, 0x37, 0xea, 0xaa, 0x19, 0x97, 0x9e, 0xf8, 0x49, 0xe7, 0x82, 0x24, 0xe9, 0x19, 0xfc, 0x3d, 0x26, 0x37, 0x46, 0xcd,
0x90, 0x09, 0xc7, 0x4d, 0xca, 0x6b, 0x70, 0xff, 0xd0, 0x64, 0xf1, 0x28, 0x16, 0x51, 0xd3, 0x20, 0xad, 0xa8, 0x9a, 0x69, 0x94, 0xa1, 0xc6, 0xca, 0x1d, 0xf8, 0x77, 0x0f, 0xd9, 0xc8, 0x10, 0x05,
0x7d, 0x6a, 0x5a, 0x9c, 0xfa, 0x4c, 0x53, 0x4a, 0xc9, 0x4a, 0x06, 0x47, 0x69, 0xd9, 0x82, 0xfc, 0xdf, 0xf6, 0x90, 0xb2, 0x69, 0x2b, 0x52, 0x39, 0x81, 0xfc, 0xe5, 0x74, 0x6a, 0x5b, 0x26, 0x45,
0x28, 0x24, 0xa4, 0x87, 0x01, 0xe2, 0xc1, 0x12, 0x76, 0x3b, 0x7e, 0x43, 0x5d, 0xca, 0x9f, 0x20, 0x72, 0x08, 0xd9, 0x91, 0xc5, 0x1c, 0x96, 0xab, 0xdf, 0x9e, 0xa7, 0x11, 0xbe, 0xf1, 0x21, 0x49,
0xbf, 0x23, 0x5d, 0x31, 0x26, 0xde, 0xff, 0x17, 0xa3, 0x03, 0x0f, 0xc6, 0x66, 0x2d, 0x4c, 0xf9, 0x65, 0x05, 0xfe, 0xdb, 0xd7, 0x68, 0x58, 0x8a, 0x06, 0xd2, 0x44, 0xc8, 0x1c, 0x6b, 0x3a, 0x43,
0x1f, 0x0a, 0xe4, 0xdf, 0x49, 0xab, 0x2e, 0xfe, 0xc9, 0xd0, 0x16, 0x64, 0x83, 0xb5, 0x90, 0xaf, 0x87, 0x8a, 0x42, 0x39, 0x59, 0xcd, 0x2a, 0x41, 0x58, 0xd1, 0xa1, 0x30, 0x0e, 0xf1, 0xe5, 0x29,
0xc5, 0xd0, 0xb3, 0xe3, 0xfb, 0xb4, 0x2f, 0xde, 0x9c, 0x47, 0x84, 0x75, 0x70, 0xb8, 0x7d, 0x22, 0x00, 0x61, 0x61, 0x0e, 0xbb, 0x9a, 0xbe, 0x08, 0x4b, 0xe5, 0x0d, 0x14, 0xb6, 0xf8, 0x38, 0x4f,
0x16, 0xb2, 0x8c, 0x11, 0x5d, 0x98, 0x2c, 0x4f, 0x21, 0xbf, 0x4b, 0x2d, 0x3a, 0x41, 0x95, 0x29, 0x98, 0xf7, 0xe7, 0xcd, 0xe8, 0xc2, 0xff, 0x13, 0xb5, 0xae, 0xcd, 0xf9, 0x2f, 0x02, 0x14, 0x5e,
0xcb, 0x52, 0xbb, 0x54, 0x01, 0x62, 0x33, 0xa2, 0x1e, 0x24, 0x0f, 0x28, 0x47, 0x2f, 0x66, 0xa0, 0xf0, 0x1d, 0xbb, 0xfe, 0x6f, 0x46, 0x36, 0x20, 0xe7, 0xed, 0x33, 0x7f, 0xcf, 0xfd, 0xa9, 0x9d,
0x31, 0x61, 0x25, 0xf5, 0x97, 0x73, 0xe3, 0x42, 0x29, 0xbe, 0x80, 0x2a, 0xd6, 0x02, 0xcd, 0xf2, 0x7c, 0x08, 0x76, 0xdd, 0x27, 0xff, 0x40, 0xa5, 0x5d, 0xc5, 0x7f, 0x36, 0xdc, 0xb3, 0x6b, 0xcb,
0xaf, 0x30, 0x71, 0xe5, 0xf4, 0x8d, 0x5b, 0x20, 0xc3, 0xe1, 0x5f, 0x21, 0x15, 0x38, 0x17, 0xcd, 0x84, 0xd0, 0x6b, 0xb3, 0xe5, 0x2e, 0x14, 0xb6, 0x51, 0xc7, 0x18, 0x57, 0xa6, 0x2c, 0x4b, 0xfd,
0xd2, 0x64, 0xf2, 0x42, 0xe9, 0x9b, 0xb7, 0x81, 0xc6, 0x04, 0x02, 0x8f, 0xcc, 0x44, 0x60, 0xb2, 0x3c, 0x05, 0x10, 0x0e, 0x23, 0xe9, 0x43, 0x72, 0x0f, 0x19, 0x79, 0x30, 0x83, 0x8c, 0x98, 0x95,
0xef, 0x67, 0x22, 0x30, 0xcd, 0x89, 0x1f, 0x20, 0x15, 0xf8, 0x66, 0x26, 0x02, 0x93, 0x2d, 0xa6, 0x94, 0x1e, 0xce, 0x8d, 0xf3, 0xad, 0x78, 0x0f, 0x29, 0x77, 0x2d, 0xc8, 0x2c, 0x3f, 0x67, 0xb1,
0xe7, 0xc7, 0x36, 0x62, 0x4f, 0x7c, 0x68, 0xd4, 0x3f, 0x9e, 0x5f, 0x15, 0x96, 0x7e, 0x5d, 0x15, 0x2b, 0x27, 0xad, 0x5d, 0x01, 0xe9, 0x17, 0xff, 0x00, 0x69, 0x6f, 0x72, 0xc9, 0x2c, 0x24, 0xf1,
0x96, 0xbe, 0x0d, 0x0a, 0xca, 0xf9, 0xa0, 0xa0, 0xfc, 0x1c, 0x14, 0x94, 0xcb, 0x41, 0x41, 0x79, 0x0b, 0x25, 0xad, 0x5f, 0x05, 0x1a, 0x0a, 0xf0, 0x66, 0x64, 0x26, 0x01, 0xf1, 0x73, 0x3f, 0x93,
0xbf, 0xff, 0x0f, 0xdf, 0x4e, 0x5b, 0x71, 0xd6, 0x48, 0xc9, 0x89, 0xcf, 0xfe, 0x04, 0x00, 0x00, 0x80, 0x69, 0x93, 0xf8, 0x0a, 0xd2, 0xde, 0xdc, 0xcc, 0x24, 0x20, 0x7e, 0xc4, 0xa4, 0xc2, 0xc4,
0xff, 0xff, 0x7e, 0x6d, 0xca, 0xbd, 0x8c, 0x09, 0x00, 0x00, 0x46, 0xec, 0xb8, 0xff, 0x90, 0x1a, 0xaf, 0x4f, 0x2f, 0x8a, 0x0b, 0xdf, 0x2e, 0x8a, 0x0b, 0x1f,
0x87, 0x45, 0xe1, 0x74, 0x58, 0x14, 0xbe, 0x0e, 0x8b, 0xc2, 0xf9, 0xb0, 0x28, 0xbc, 0xdc, 0xfd,
0x8d, 0x3f, 0x7d, 0x1b, 0x61, 0xd4, 0x4c, 0xf3, 0x8a, 0xf7, 0x7e, 0x04, 0x00, 0x00, 0xff, 0xff,
0x17, 0x73, 0xba, 0x43, 0x45, 0x0a, 0x00, 0x00,
} }

View File

@ -42,6 +42,8 @@ message Container {
// Labels provides an area to include arbitrary data on containers. // Labels provides an area to include arbitrary data on containers.
// //
// The combined size of a key/value pair cannot exceed 4096 bytes.
//
// Note that to add a new value to this field, read the existing set and // Note that to add a new value to this field, read the existing set and
// include the entire result in the update call. // include the entire result in the update call.
map<string, string> labels = 2; map<string, string> labels = 2;
@ -84,6 +86,17 @@ message Container {
// UpdatedAt is the last time the container was mutated. // UpdatedAt is the last time the container was mutated.
google.protobuf.Timestamp updated_at = 9 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; google.protobuf.Timestamp updated_at = 9 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
// Extensions allow clients to provide zero or more blobs that are directly
// associated with the container. One may provide protobuf, json, or other
// encoding formats. The primary use of this is to further decorate the
// container object with fields that may be specific to a client integration.
//
// The key portion of this map should identify a "name" for the extension
// that should be unique against other extensions. When updating extension
// data, one should only update the specified extension using field paths
// to select a specific map key.
map<string, google.protobuf.Any> extensions = 10 [(gogoproto.nullable) = false];
} }
message GetContainerRequest { message GetContainerRequest {

View File

@ -115,7 +115,9 @@ type Info struct {
CreatedAt time.Time `protobuf:"bytes,3,opt,name=created_at,json=createdAt,stdtime" json:"created_at"` CreatedAt time.Time `protobuf:"bytes,3,opt,name=created_at,json=createdAt,stdtime" json:"created_at"`
// UpdatedAt provides the time the info was last updated. // UpdatedAt provides the time the info was last updated.
UpdatedAt time.Time `protobuf:"bytes,4,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"` UpdatedAt time.Time `protobuf:"bytes,4,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"`
// Labels are arbitrary data on content. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,5,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,5,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
@ -321,7 +323,9 @@ type WriteContentRequest struct {
// If this is empty and the message is not a commit, a response will be // If this is empty and the message is not a commit, a response will be
// returned with the current write state. // returned with the current write state.
Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"` Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"`
// Labels are arbitrary data to set on commit. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,7,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,7,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }

View File

@ -87,7 +87,9 @@ message Info {
// UpdatedAt provides the time the info was last updated. // UpdatedAt provides the time the info was last updated.
google.protobuf.Timestamp updated_at = 4 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; google.protobuf.Timestamp updated_at = 4 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
// Labels are arbitrary data on content. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 5; map<string, string> labels = 5;
} }
@ -270,7 +272,9 @@ message WriteContentRequest {
// returned with the current write state. // returned with the current write state.
bytes data = 6; bytes data = 6;
// Labels are arbitrary data to set on commit. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 7; map<string, string> labels = 7;
} }

View File

@ -30,6 +30,7 @@ import (
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -78,6 +79,9 @@ type DiffRequest struct {
// Ref identifies the pre-commit content store object. This // Ref identifies the pre-commit content store object. This
// reference can be used to get the status from the content store. // reference can be used to get the status from the content store.
Ref string `protobuf:"bytes,4,opt,name=ref,proto3" json:"ref,omitempty"` Ref string `protobuf:"bytes,4,opt,name=ref,proto3" json:"ref,omitempty"`
// Labels are the labels to apply to the generated content
// on content store commit.
Labels map[string]string `protobuf:"bytes,5,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
func (m *DiffRequest) Reset() { *m = DiffRequest{} } func (m *DiffRequest) Reset() { *m = DiffRequest{} }
@ -334,6 +338,23 @@ func (m *DiffRequest) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintDiff(dAtA, i, uint64(len(m.Ref))) i = encodeVarintDiff(dAtA, i, uint64(len(m.Ref)))
i += copy(dAtA[i:], m.Ref) i += copy(dAtA[i:], m.Ref)
} }
if len(m.Labels) > 0 {
for k, _ := range m.Labels {
dAtA[i] = 0x2a
i++
v := m.Labels[k]
mapSize := 1 + len(k) + sovDiff(uint64(len(k))) + 1 + len(v) + sovDiff(uint64(len(v)))
i = encodeVarintDiff(dAtA, i, uint64(mapSize))
dAtA[i] = 0xa
i++
i = encodeVarintDiff(dAtA, i, uint64(len(k)))
i += copy(dAtA[i:], k)
dAtA[i] = 0x12
i++
i = encodeVarintDiff(dAtA, i, uint64(len(v)))
i += copy(dAtA[i:], v)
}
}
return i, nil return i, nil
} }
@ -441,6 +462,14 @@ func (m *DiffRequest) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovDiff(uint64(l)) n += 1 + l + sovDiff(uint64(l))
} }
if len(m.Labels) > 0 {
for k, v := range m.Labels {
_ = k
_ = v
mapEntrySize := 1 + len(k) + sovDiff(uint64(len(k))) + 1 + len(v) + sovDiff(uint64(len(v)))
n += mapEntrySize + 1 + sovDiff(uint64(mapEntrySize))
}
}
return n return n
} }
@ -492,11 +521,22 @@ func (this *DiffRequest) String() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
keysForLabels := make([]string, 0, len(this.Labels))
for k, _ := range this.Labels {
keysForLabels = append(keysForLabels, k)
}
github_com_gogo_protobuf_sortkeys.Strings(keysForLabels)
mapStringForLabels := "map[string]string{"
for _, k := range keysForLabels {
mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k])
}
mapStringForLabels += "}"
s := strings.Join([]string{`&DiffRequest{`, s := strings.Join([]string{`&DiffRequest{`,
`Left:` + strings.Replace(fmt.Sprintf("%v", this.Left), "Mount", "containerd_types.Mount", 1) + `,`, `Left:` + strings.Replace(fmt.Sprintf("%v", this.Left), "Mount", "containerd_types.Mount", 1) + `,`,
`Right:` + strings.Replace(fmt.Sprintf("%v", this.Right), "Mount", "containerd_types.Mount", 1) + `,`, `Right:` + strings.Replace(fmt.Sprintf("%v", this.Right), "Mount", "containerd_types.Mount", 1) + `,`,
`MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`, `MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`,
`Ref:` + fmt.Sprintf("%v", this.Ref) + `,`, `Ref:` + fmt.Sprintf("%v", this.Ref) + `,`,
`Labels:` + mapStringForLabels + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -865,6 +905,122 @@ func (m *DiffRequest) Unmarshal(dAtA []byte) error {
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.Ref = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDiff
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthDiff
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
var keykey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDiff
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
keykey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDiff
}
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 ErrInvalidLengthDiff
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey := string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
if m.Labels == nil {
m.Labels = make(map[string]string)
}
if iNdEx < postIndex {
var valuekey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDiff
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
valuekey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDiff
}
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 ErrInvalidLengthDiff
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
return io.ErrUnexpectedEOF
}
mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
m.Labels[mapkey] = mapvalue
} else {
var mapvalue string
m.Labels[mapkey] = mapvalue
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipDiff(dAtA[iNdEx:]) skippy, err := skipDiff(dAtA[iNdEx:])
@ -1079,31 +1235,34 @@ func init() {
} }
var fileDescriptorDiff = []byte{ var fileDescriptorDiff = []byte{
// 401 bytes of a gzipped FileDescriptorProto // 454 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0x41, 0x8b, 0xda, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x4f, 0x6f, 0xd3, 0x30,
0x14, 0xc7, 0x9d, 0x26, 0x5a, 0x1c, 0x2d, 0x94, 0xa1, 0xd0, 0x90, 0xb6, 0x41, 0x72, 0x8a, 0x2d, 0x14, 0x9f, 0xfb, 0x0f, 0xf5, 0x75, 0x48, 0xc8, 0x9a, 0x44, 0x14, 0x20, 0xaa, 0x7a, 0xea, 0x40,
0x9d, 0x54, 0x0b, 0x1e, 0xea, 0xc5, 0x16, 0xa1, 0xa7, 0x5e, 0x82, 0xa7, 0x16, 0x5a, 0x62, 0x32, 0x38, 0xac, 0xa0, 0x09, 0xb6, 0xcb, 0x40, 0x43, 0x5c, 0xc6, 0x25, 0xda, 0x09, 0x24, 0x50, 0xda,
0x89, 0x03, 0x9a, 0x19, 0x33, 0xa3, 0xe0, 0xad, 0x9f, 0x63, 0xbf, 0xce, 0x5e, 0x3c, 0xee, 0x71, 0xbc, 0x74, 0x16, 0x69, 0xec, 0xd9, 0x6e, 0xa5, 0xdc, 0xf8, 0x2e, 0x7c, 0x14, 0x2e, 0x3b, 0x72,
0x8f, 0x6b, 0x3e, 0xc9, 0x92, 0x49, 0xb2, 0x1b, 0x58, 0x70, 0xb3, 0x7b, 0x9a, 0xc7, 0xbc, 0xdf, 0xe4, 0x48, 0xfb, 0x49, 0x90, 0x9d, 0x14, 0x22, 0x21, 0x95, 0xc0, 0x29, 0x2f, 0xcf, 0xbf, 0x7f,
0xff, 0xbd, 0xff, 0xbc, 0xbc, 0xc0, 0x59, 0x4c, 0xe5, 0x6a, 0xb7, 0xc4, 0x01, 0xdb, 0xb8, 0x01, 0xf6, 0xb3, 0xe1, 0x6c, 0xce, 0xcd, 0xd5, 0x72, 0xca, 0x66, 0x62, 0x11, 0xce, 0x44, 0x6e, 0x62,
0x4b, 0xa4, 0x4f, 0x13, 0x92, 0x86, 0xf5, 0xd0, 0xe7, 0xd4, 0x15, 0x24, 0xdd, 0xd3, 0x80, 0x08, 0x9e, 0xa3, 0x4a, 0xea, 0x65, 0x2c, 0x79, 0xa8, 0x51, 0xad, 0xf8, 0x0c, 0x75, 0x98, 0xf0, 0x34,
0x37, 0xa4, 0x51, 0xe4, 0xee, 0x47, 0xea, 0xc4, 0x3c, 0x65, 0x92, 0xa1, 0x77, 0xf7, 0x2c, 0xae, 0x0d, 0x57, 0x47, 0xee, 0xcb, 0xa4, 0x12, 0x46, 0xd0, 0x7b, 0xbf, 0xb1, 0x6c, 0x8b, 0x63, 0x6e,
0x38, 0xac, 0xf2, 0xfb, 0x91, 0xf9, 0x26, 0x66, 0x31, 0x53, 0x9c, 0x9b, 0x47, 0x85, 0xc4, 0x9c, 0x7d, 0x75, 0xe4, 0x1f, 0xcc, 0xc5, 0x5c, 0x38, 0x5c, 0x68, 0xab, 0x92, 0xe2, 0x1f, 0x37, 0x32,
0x34, 0x6a, 0x2a, 0x0f, 0x9c, 0x08, 0x77, 0xc3, 0x76, 0x89, 0x2c, 0x75, 0xd3, 0x27, 0xe8, 0x42, 0x35, 0x85, 0x44, 0x1d, 0x2e, 0xc4, 0x32, 0x37, 0x15, 0xef, 0xf4, 0x1f, 0x78, 0x09, 0xea, 0x99,
0x22, 0x82, 0x94, 0x72, 0xc9, 0xd2, 0x42, 0x6c, 0x6f, 0x61, 0xff, 0x3b, 0xe7, 0xeb, 0x83, 0x47, 0xe2, 0xd2, 0x08, 0x55, 0x92, 0x47, 0xd7, 0xb0, 0xff, 0x52, 0xca, 0xac, 0x88, 0xf0, 0x7a, 0x89,
0xb6, 0x3b, 0x22, 0x24, 0xfa, 0x02, 0xf5, 0xdc, 0xa5, 0x01, 0x06, 0xc0, 0xe9, 0x8d, 0xdf, 0xe3, 0xda, 0xd0, 0x27, 0xd0, 0xb1, 0x29, 0x3d, 0x32, 0x24, 0xe3, 0xc1, 0xe4, 0x3e, 0xab, 0x6d, 0xc3,
0xda, 0x33, 0x54, 0x05, 0x3c, 0xbf, 0xab, 0xe0, 0x29, 0x12, 0xb9, 0xb0, 0xa3, 0xdc, 0x08, 0xe3, 0x29, 0xb0, 0xf3, 0x5f, 0x0a, 0x91, 0x43, 0xd2, 0x10, 0x7a, 0x2e, 0x8d, 0xf6, 0x5a, 0xc3, 0xf6,
0xc5, 0x40, 0x73, 0x7a, 0xe3, 0xb7, 0x0f, 0x35, 0xbf, 0xf2, 0xbc, 0x57, 0x62, 0xf6, 0x4f, 0xf8, 0x78, 0x30, 0xb9, 0xfb, 0x27, 0xe7, 0xad, 0x5d, 0x8f, 0x2a, 0xd8, 0xe8, 0x0d, 0xdc, 0xae, 0x2c,
0xaa, 0x6c, 0x29, 0x38, 0x4b, 0x04, 0x41, 0x13, 0xf8, 0xd2, 0xe7, 0x7c, 0x4d, 0x49, 0xd8, 0xa8, 0xb5, 0x14, 0xb9, 0x46, 0x7a, 0x0c, 0xb7, 0x62, 0x29, 0x33, 0x8e, 0x49, 0x23, 0xdb, 0x2d, 0x78,
0x6d, 0x05, 0xdb, 0x17, 0x00, 0xf6, 0xe6, 0x34, 0x8a, 0x2a, 0xef, 0x9f, 0xa0, 0xbe, 0x26, 0x91, 0xf4, 0xa5, 0x05, 0x83, 0x73, 0x9e, 0xa6, 0xdb, 0xec, 0x8f, 0xa0, 0x93, 0x61, 0x6a, 0x3c, 0xb2,
0x34, 0xc0, 0x79, 0x1f, 0x0a, 0x42, 0x9f, 0x61, 0x3b, 0xa5, 0xf1, 0x4a, 0x3e, 0xe6, 0xba, 0xa0, 0x3b, 0x87, 0x03, 0xd1, 0xc7, 0xd0, 0x55, 0x7c, 0x7e, 0x65, 0xfe, 0x96, 0xba, 0x44, 0xd1, 0x07,
0xd0, 0x07, 0x08, 0x37, 0x24, 0xa4, 0xfe, 0xbf, 0x3c, 0x67, 0x68, 0x03, 0xe0, 0x74, 0xbd, 0xae, 0x00, 0x0b, 0x4c, 0x78, 0xfc, 0xd1, 0xae, 0x79, 0xed, 0x21, 0x19, 0xf7, 0xa3, 0xbe, 0xeb, 0x5c,
0xba, 0x59, 0x1c, 0x38, 0x41, 0xaf, 0xa1, 0x96, 0x92, 0xc8, 0xd0, 0xd5, 0x7d, 0x1e, 0xda, 0x33, 0x16, 0x12, 0xe9, 0x1d, 0x68, 0x2b, 0x4c, 0xbd, 0x8e, 0xeb, 0xdb, 0x92, 0x5e, 0x40, 0x2f, 0x8b,
0xd8, 0x2f, 0xbc, 0x95, 0x8f, 0xac, 0x06, 0xab, 0x35, 0x1d, 0xec, 0xf8, 0x12, 0x40, 0x3d, 0x2f, 0xa7, 0x98, 0x69, 0xaf, 0xeb, 0x0c, 0x9e, 0xb1, 0x1d, 0x37, 0x82, 0xd5, 0xb6, 0xc1, 0x2e, 0x1c,
0x81, 0xfe, 0xc2, 0xb6, 0x1a, 0x18, 0x1a, 0xe2, 0x33, 0x5b, 0x85, 0xeb, 0xdf, 0xd1, 0xfc, 0xd8, 0xed, 0x75, 0x6e, 0x54, 0x11, 0x55, 0x1a, 0xfe, 0x0b, 0x18, 0xd4, 0xda, 0xd6, 0xee, 0x13, 0x16,
0x04, 0x2d, 0xad, 0xfd, 0x29, 0xfb, 0x38, 0x67, 0x35, 0xb5, 0x49, 0x9b, 0xc3, 0x06, 0x64, 0x51, 0xee, 0xb4, 0xfa, 0x91, 0x2d, 0xe9, 0x01, 0x74, 0x57, 0x71, 0xb6, 0x44, 0xaf, 0xe5, 0x7a, 0xe5,
0xfc, 0xc7, 0xe2, 0x78, 0xb2, 0x5a, 0xd7, 0x27, 0xab, 0xf5, 0x3f, 0xb3, 0xc0, 0x31, 0xb3, 0xc0, 0xcf, 0x49, 0xeb, 0x39, 0x19, 0x9d, 0xc1, 0x7e, 0xa9, 0x5e, 0x9d, 0xf6, 0x76, 0xc2, 0xed, 0xa6,
0x55, 0x66, 0x81, 0x9b, 0xcc, 0x02, 0xbf, 0xbf, 0x3d, 0xeb, 0x27, 0x9b, 0xe6, 0xe7, 0xb2, 0xa3, 0x13, 0x9e, 0x7c, 0x25, 0xd0, 0xb1, 0x12, 0xf4, 0x03, 0x74, 0xdd, 0xe4, 0xe8, 0xe1, 0xce, 0xcd,
0xb6, 0xf7, 0xeb, 0x6d, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6e, 0x16, 0x1d, 0x04, 0xa9, 0x03, 0x00, 0xd4, 0x2f, 0x94, 0xff, 0xb0, 0x09, 0xb4, 0x8a, 0xf6, 0xbe, 0xf2, 0x19, 0x37, 0x3d, 0x2b, 0xff,
0x00, 0xb0, 0x01, 0xb2, 0x14, 0x7f, 0x75, 0x79, 0xb3, 0x0e, 0xf6, 0xbe, 0xaf, 0x83, 0xbd, 0xcf, 0x9b,
0x80, 0xdc, 0x6c, 0x02, 0xf2, 0x6d, 0x13, 0x90, 0x1f, 0x9b, 0x80, 0xbc, 0x3b, 0xf9, 0xaf, 0xd7,
0x7e, 0x6a, 0xbf, 0xd3, 0x9e, 0x7b, 0x46, 0x4f, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x01,
0x51, 0xf0, 0x32, 0x04, 0x00, 0x00,
} }

View File

@ -50,6 +50,10 @@ message DiffRequest {
// Ref identifies the pre-commit content store object. This // Ref identifies the pre-commit content store object. This
// reference can be used to get the status from the content store. // reference can be used to get the status from the content store.
string ref = 4; string ref = 4;
// Labels are the labels to apply to the generated content
// on content store commit.
map<string, string> labels = 5;
} }
message DiffResponse { message DiffResponse {

View File

@ -53,7 +53,7 @@ import _ "github.com/gogo/protobuf/gogoproto"
import google_protobuf1 "github.com/gogo/protobuf/types" import google_protobuf1 "github.com/gogo/protobuf/types"
import _ "github.com/containerd/containerd/protobuf/plugin" import _ "github.com/containerd/containerd/protobuf/plugin"
import github_com_containerd_containerd_typeurl "github.com/containerd/containerd/typeurl" import github_com_containerd_typeurl "github.com/containerd/typeurl"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
@ -158,7 +158,7 @@ func (m *ContainerCreate_Runtime) Field(fieldpath []string) (string, bool) {
case "name": case "name":
return string(m.Name), len(m.Name) > 0 return string(m.Name), len(m.Name) > 0
case "options": case "options":
decoded, err := github_com_containerd_containerd_typeurl.UnmarshalAny(m.Options) decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Options)
if err != nil { if err != nil {
return "", false return "", false
} }

View File

@ -15,7 +15,7 @@ import _ "github.com/gogo/protobuf/types"
import time "time" import time "time"
import github_com_containerd_containerd_typeurl "github.com/containerd/containerd/typeurl" import github_com_containerd_typeurl "github.com/containerd/typeurl"
import ( import (
context "golang.org/x/net/context" context "golang.org/x/net/context"
@ -92,7 +92,7 @@ func (m *Envelope) Field(fieldpath []string) (string, bool) {
case "topic": case "topic":
return string(m.Topic), len(m.Topic) > 0 return string(m.Topic), len(m.Topic) > 0
case "event": case "event":
decoded, err := github_com_containerd_containerd_typeurl.UnmarshalAny(m.Event) decoded, err := github_com_containerd_typeurl.UnmarshalAny(m.Event)
if err != nil { if err != nil {
return "", false return "", false
} }

View File

@ -67,6 +67,7 @@ type Image struct {
// and do not get inherited into the package image in any way. // and do not get inherited into the package image in any way.
// //
// Labels may be updated using the field mask. // Labels may be updated using the field mask.
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Target describes the content entry point of the image. // Target describes the content entry point of the image.
Target containerd_types.Descriptor `protobuf:"bytes,3,opt,name=target" json:"target"` Target containerd_types.Descriptor `protobuf:"bytes,3,opt,name=target" json:"target"`

View File

@ -51,6 +51,7 @@ message Image {
// and do not get inherited into the package image in any way. // and do not get inherited into the package image in any way.
// //
// Labels may be updated using the field mask. // Labels may be updated using the field mask.
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 2; map<string, string> labels = 2;
// Target describes the content entry point of the image. // Target describes the content entry point of the image.

View File

@ -0,0 +1 @@
package introspection

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
syntax = "proto3";
package containerd.services.introspection.v1;
import "github.com/containerd/containerd/api/types/platform.proto";
import "google/rpc/status.proto";
import "gogoproto/gogo.proto";
option go_package = "github.com/containerd/containerd/api/services/introspection/v1;introspection";
service Introspection {
// Plugins returns a list of plugins in containerd.
//
// Clients can use this to detect features and capabilities when using
// containerd.
rpc Plugins(PluginsRequest) returns (PluginsResponse);
}
message Plugin {
// Type defines the type of plugin.
//
// See package plugin for a list of possible values. Non core plugins may
// define their own values during registration.
string type = 1;
// ID identifies the plugin uniquely in the system.
string id = 2;
// Requires lists the plugin types required by this plugin.
repeated string requires = 3;
// Platforms enumerates the platforms this plugin will support.
//
// If values are provided here, the plugin will only be operable under the
// provided platforms.
//
// If this is empty, the plugin will work across all platforms.
//
// If the plugin prefers certain platforms over others, they should be
// listed from most to least preferred.
repeated types.Platform platforms = 4 [(gogoproto.nullable) = false];
// Exports allows plugins to provide values about state or configuration to
// interested parties.
//
// One example is exposing the configured path of a snapshotter plugin.
map<string, string> exports = 5;
// Capabilities allows plugins to communicate feature switches to allow
// clients to detect features that may not be on be default or may be
// different from version to version.
//
// Use this sparingly.
repeated string capabilities = 6;
// InitErr will be set if the plugin fails initialization.
//
// This means the plugin may have been registered but a non-terminal error
// was encountered during initialization.
//
// Plugins that have this value set cannot be used.
google.rpc.Status init_err = 7;
}
message PluginsRequest {
// Filters contains one or more filters using the syntax defined in the
// containerd filter package.
//
// The returned result will be those that match any of the provided
// filters. Expanded, plugins that match the following will be
// returned:
//
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
//
// If filters is zero-length or nil, all items will be returned.
repeated string filters = 1;
}
message PluginsResponse {
repeated Plugin plugins = 1 [(gogoproto.nullable) = false];
}

View File

@ -0,0 +1 @@
package leases

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
syntax = "proto3";
package containerd.services.leases.v1;
import "gogoproto/gogo.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
option go_package = "github.com/containerd/containerd/api/services/leases/v1;leases";
// Leases service manages resources leases within the metadata store.
service Leases {
// Create creates a new lease for managing changes to metadata. A lease
// can be used to protect objects from being removed.
rpc Create(CreateRequest) returns (CreateResponse);
// Delete deletes the lease and makes any unreferenced objects created
// during the lease eligible for garbage collection if not referenced
// or retained by other resources during the lease.
rpc Delete(DeleteRequest) returns (google.protobuf.Empty);
// ListTransactions lists all active leases, returning the full list of
// leases and optionally including the referenced resources.
rpc List(ListRequest) returns (ListResponse);
}
// Lease is an object which retains resources while it exists.
message Lease {
string id = 1;
google.protobuf.Timestamp created_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
map<string, string> labels = 3;
}
message CreateRequest {
// ID is used to identity the lease, when the id is not set the service
// generates a random identifier for the lease.
string id = 1;
map<string, string> labels = 3;
}
message CreateResponse {
Lease lease = 1;
}
message DeleteRequest {
string id = 1;
}
message ListRequest {
repeated string filters = 1;
}
message ListResponse {
repeated Lease leases = 1;
}

View File

@ -55,6 +55,8 @@ type Namespace struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// Labels provides an area to include arbitrary data on namespaces. // Labels provides an area to include arbitrary data on namespaces.
// //
// The combined size of a key/value pair cannot exceed 4096 bytes.
//
// Note that to add a new value to this field, read the existing set and // Note that to add a new value to this field, read the existing set and
// include the entire result in the update call. // include the entire result in the update call.
Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`

View File

@ -32,6 +32,8 @@ message Namespace {
// Labels provides an area to include arbitrary data on namespaces. // Labels provides an area to include arbitrary data on namespaces.
// //
// The combined size of a key/value pair cannot exceed 4096 bytes.
//
// Note that to add a new value to this field, read the existing set and // Note that to add a new value to this field, read the existing set and
// include the entire result in the update call. // include the entire result in the update call.
map<string, string> labels = 2; map<string, string> labels = 2;

View File

@ -97,6 +97,8 @@ type PrepareSnapshotRequest struct {
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Parent string `protobuf:"bytes,3,opt,name=parent,proto3" json:"parent,omitempty"` Parent string `protobuf:"bytes,3,opt,name=parent,proto3" json:"parent,omitempty"`
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
@ -117,6 +119,8 @@ type ViewSnapshotRequest struct {
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Parent string `protobuf:"bytes,3,opt,name=parent,proto3" json:"parent,omitempty"` Parent string `protobuf:"bytes,3,opt,name=parent,proto3" json:"parent,omitempty"`
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
@ -163,6 +167,8 @@ type CommitSnapshotRequest struct {
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"` Key string `protobuf:"bytes,3,opt,name=key,proto3" json:"key,omitempty"`
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,4,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
@ -188,6 +194,8 @@ type Info struct {
// UpdatedAt provides the time the info was last updated. // UpdatedAt provides the time the info was last updated.
UpdatedAt time.Time `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"` UpdatedAt time.Time `protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,stdtime" json:"updated_at"`
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
Labels map[string]string `protobuf:"bytes,6,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,6,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }

View File

@ -29,6 +29,8 @@ message PrepareSnapshotRequest {
string parent = 3; string parent = 3;
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 4; map<string, string> labels = 4;
} }
@ -42,6 +44,8 @@ message ViewSnapshotRequest {
string parent = 3; string parent = 3;
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 4; map<string, string> labels = 4;
} }
@ -69,6 +73,8 @@ message CommitSnapshotRequest {
string key = 3; string key = 3;
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 4; map<string, string> labels = 4;
} }
@ -99,6 +105,8 @@ message Info {
google.protobuf.Timestamp updated_at = 5 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; google.protobuf.Timestamp updated_at = 5 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
// Labels are arbitrary data on snapshots. // Labels are arbitrary data on snapshots.
//
// The combined size of a key/value pair cannot exceed 4096 bytes.
map<string, string> labels = 6; map<string, string> labels = 6;
} }

View File

@ -34,6 +34,8 @@
UpdateTaskRequest UpdateTaskRequest
MetricsRequest MetricsRequest
MetricsResponse MetricsResponse
WaitRequest
WaitResponse
*/ */
package tasks package tasks
@ -266,7 +268,8 @@ func (*ListPidsRequest) ProtoMessage() {}
func (*ListPidsRequest) Descriptor() ([]byte, []int) { return fileDescriptorTasks, []int{18} } func (*ListPidsRequest) Descriptor() ([]byte, []int) { return fileDescriptorTasks, []int{18} }
type ListPidsResponse struct { type ListPidsResponse struct {
Pids []uint32 `protobuf:"varint,1,rep,packed,name=pids" json:"pids,omitempty"` // Processes includes the process ID and additional process information
Processes []*containerd_v1_types.ProcessInfo `protobuf:"bytes,1,rep,name=processes" json:"processes,omitempty"`
} }
func (m *ListPidsResponse) Reset() { *m = ListPidsResponse{} } func (m *ListPidsResponse) Reset() { *m = ListPidsResponse{} }
@ -316,6 +319,24 @@ func (m *MetricsResponse) Reset() { *m = MetricsResponse{} }
func (*MetricsResponse) ProtoMessage() {} func (*MetricsResponse) ProtoMessage() {}
func (*MetricsResponse) Descriptor() ([]byte, []int) { return fileDescriptorTasks, []int{24} } func (*MetricsResponse) Descriptor() ([]byte, []int) { return fileDescriptorTasks, []int{24} }
type WaitRequest struct {
ContainerID string `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"`
ExecID string `protobuf:"bytes,2,opt,name=exec_id,json=execId,proto3" json:"exec_id,omitempty"`
}
func (m *WaitRequest) Reset() { *m = WaitRequest{} }
func (*WaitRequest) ProtoMessage() {}
func (*WaitRequest) Descriptor() ([]byte, []int) { return fileDescriptorTasks, []int{25} }
type WaitResponse struct {
ExitStatus uint32 `protobuf:"varint,1,opt,name=exit_status,json=exitStatus,proto3" json:"exit_status,omitempty"`
ExitedAt time.Time `protobuf:"bytes,2,opt,name=exited_at,json=exitedAt,stdtime" json:"exited_at"`
}
func (m *WaitResponse) Reset() { *m = WaitResponse{} }
func (*WaitResponse) ProtoMessage() {}
func (*WaitResponse) Descriptor() ([]byte, []int) { return fileDescriptorTasks, []int{26} }
func init() { func init() {
proto.RegisterType((*CreateTaskRequest)(nil), "containerd.services.tasks.v1.CreateTaskRequest") proto.RegisterType((*CreateTaskRequest)(nil), "containerd.services.tasks.v1.CreateTaskRequest")
proto.RegisterType((*CreateTaskResponse)(nil), "containerd.services.tasks.v1.CreateTaskResponse") proto.RegisterType((*CreateTaskResponse)(nil), "containerd.services.tasks.v1.CreateTaskResponse")
@ -342,6 +363,8 @@ func init() {
proto.RegisterType((*UpdateTaskRequest)(nil), "containerd.services.tasks.v1.UpdateTaskRequest") proto.RegisterType((*UpdateTaskRequest)(nil), "containerd.services.tasks.v1.UpdateTaskRequest")
proto.RegisterType((*MetricsRequest)(nil), "containerd.services.tasks.v1.MetricsRequest") proto.RegisterType((*MetricsRequest)(nil), "containerd.services.tasks.v1.MetricsRequest")
proto.RegisterType((*MetricsResponse)(nil), "containerd.services.tasks.v1.MetricsResponse") proto.RegisterType((*MetricsResponse)(nil), "containerd.services.tasks.v1.MetricsResponse")
proto.RegisterType((*WaitRequest)(nil), "containerd.services.tasks.v1.WaitRequest")
proto.RegisterType((*WaitResponse)(nil), "containerd.services.tasks.v1.WaitResponse")
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -375,6 +398,7 @@ type TasksClient interface {
Checkpoint(ctx context.Context, in *CheckpointTaskRequest, opts ...grpc.CallOption) (*CheckpointTaskResponse, error) Checkpoint(ctx context.Context, in *CheckpointTaskRequest, opts ...grpc.CallOption) (*CheckpointTaskResponse, error)
Update(ctx context.Context, in *UpdateTaskRequest, opts ...grpc.CallOption) (*google_protobuf.Empty, error) Update(ctx context.Context, in *UpdateTaskRequest, opts ...grpc.CallOption) (*google_protobuf.Empty, error)
Metrics(ctx context.Context, in *MetricsRequest, opts ...grpc.CallOption) (*MetricsResponse, error) Metrics(ctx context.Context, in *MetricsRequest, opts ...grpc.CallOption) (*MetricsResponse, error)
Wait(ctx context.Context, in *WaitRequest, opts ...grpc.CallOption) (*WaitResponse, error)
} }
type tasksClient struct { type tasksClient struct {
@ -529,6 +553,15 @@ func (c *tasksClient) Metrics(ctx context.Context, in *MetricsRequest, opts ...g
return out, nil return out, nil
} }
func (c *tasksClient) Wait(ctx context.Context, in *WaitRequest, opts ...grpc.CallOption) (*WaitResponse, error) {
out := new(WaitResponse)
err := grpc.Invoke(ctx, "/containerd.services.tasks.v1.Tasks/Wait", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Tasks service // Server API for Tasks service
type TasksServer interface { type TasksServer interface {
@ -552,6 +585,7 @@ type TasksServer interface {
Checkpoint(context.Context, *CheckpointTaskRequest) (*CheckpointTaskResponse, error) Checkpoint(context.Context, *CheckpointTaskRequest) (*CheckpointTaskResponse, error)
Update(context.Context, *UpdateTaskRequest) (*google_protobuf.Empty, error) Update(context.Context, *UpdateTaskRequest) (*google_protobuf.Empty, error)
Metrics(context.Context, *MetricsRequest) (*MetricsResponse, error) Metrics(context.Context, *MetricsRequest) (*MetricsResponse, error)
Wait(context.Context, *WaitRequest) (*WaitResponse, error)
} }
func RegisterTasksServer(s *grpc.Server, srv TasksServer) { func RegisterTasksServer(s *grpc.Server, srv TasksServer) {
@ -846,6 +880,24 @@ func _Tasks_Metrics_Handler(srv interface{}, ctx context.Context, dec func(inter
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _Tasks_Wait_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(WaitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TasksServer).Wait(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/containerd.services.tasks.v1.Tasks/Wait",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TasksServer).Wait(ctx, req.(*WaitRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Tasks_serviceDesc = grpc.ServiceDesc{ var _Tasks_serviceDesc = grpc.ServiceDesc{
ServiceName: "containerd.services.tasks.v1.Tasks", ServiceName: "containerd.services.tasks.v1.Tasks",
HandlerType: (*TasksServer)(nil), HandlerType: (*TasksServer)(nil),
@ -914,6 +966,10 @@ var _Tasks_serviceDesc = grpc.ServiceDesc{
MethodName: "Metrics", MethodName: "Metrics",
Handler: _Tasks_Metrics_Handler, Handler: _Tasks_Metrics_Handler,
}, },
{
MethodName: "Wait",
Handler: _Tasks_Wait_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "github.com/containerd/containerd/api/services/tasks/v1/tasks.proto", Metadata: "github.com/containerd/containerd/api/services/tasks/v1/tasks.proto",
@ -1591,22 +1647,17 @@ func (m *ListPidsResponse) MarshalTo(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.Pids) > 0 { if len(m.Processes) > 0 {
dAtA7 := make([]byte, len(m.Pids)*10) for _, msg := range m.Processes {
var j6 int dAtA[i] = 0xa
for _, num := range m.Pids { i++
for num >= 1<<7 { i = encodeVarintTasks(dAtA, i, uint64(msg.Size()))
dAtA7[j6] = uint8(uint64(num)&0x7f | 0x80) n, err := msg.MarshalTo(dAtA[i:])
num >>= 7 if err != nil {
j6++ return 0, err
} }
dAtA7[j6] = uint8(num) i += n
j6++
} }
dAtA[i] = 0xa
i++
i = encodeVarintTasks(dAtA, i, uint64(j6))
i += copy(dAtA[i:], dAtA7[:j6])
} }
return i, nil return i, nil
} }
@ -1642,11 +1693,11 @@ func (m *CheckpointTaskRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x1a dAtA[i] = 0x1a
i++ i++
i = encodeVarintTasks(dAtA, i, uint64(m.Options.Size())) i = encodeVarintTasks(dAtA, i, uint64(m.Options.Size()))
n8, err := m.Options.MarshalTo(dAtA[i:]) n6, err := m.Options.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n8 i += n6
} }
return i, nil return i, nil
} }
@ -1706,11 +1757,11 @@ func (m *UpdateTaskRequest) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintTasks(dAtA, i, uint64(m.Resources.Size())) i = encodeVarintTasks(dAtA, i, uint64(m.Resources.Size()))
n9, err := m.Resources.MarshalTo(dAtA[i:]) n7, err := m.Resources.MarshalTo(dAtA[i:])
if err != nil { if err != nil {
return 0, err return 0, err
} }
i += n9 i += n7
} }
return i, nil return i, nil
} }
@ -1778,6 +1829,67 @@ func (m *MetricsResponse) MarshalTo(dAtA []byte) (int, error) {
return i, nil return i, nil
} }
func (m *WaitRequest) 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 *WaitRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.ContainerID) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintTasks(dAtA, i, uint64(len(m.ContainerID)))
i += copy(dAtA[i:], m.ContainerID)
}
if len(m.ExecID) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintTasks(dAtA, i, uint64(len(m.ExecID)))
i += copy(dAtA[i:], m.ExecID)
}
return i, nil
}
func (m *WaitResponse) 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 *WaitResponse) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.ExitStatus != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintTasks(dAtA, i, uint64(m.ExitStatus))
}
dAtA[i] = 0x12
i++
i = encodeVarintTasks(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)))
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.ExitedAt, dAtA[i:])
if err != nil {
return 0, err
}
i += n8
return i, nil
}
func encodeFixed64Tasks(dAtA []byte, offset int, v uint64) int { func encodeFixed64Tasks(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v) dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8) dAtA[offset+1] = uint8(v >> 8)
@ -2097,12 +2209,11 @@ func (m *ListPidsRequest) Size() (n int) {
func (m *ListPidsResponse) Size() (n int) { func (m *ListPidsResponse) Size() (n int) {
var l int var l int
_ = l _ = l
if len(m.Pids) > 0 { if len(m.Processes) > 0 {
l = 0 for _, e := range m.Processes {
for _, e := range m.Pids { l = e.Size()
l += sovTasks(uint64(e)) n += 1 + l + sovTasks(uint64(l))
} }
n += 1 + sovTasks(uint64(l)) + l
} }
return n return n
} }
@ -2175,6 +2286,31 @@ func (m *MetricsResponse) Size() (n int) {
return n return n
} }
func (m *WaitRequest) Size() (n int) {
var l int
_ = l
l = len(m.ContainerID)
if l > 0 {
n += 1 + l + sovTasks(uint64(l))
}
l = len(m.ExecID)
if l > 0 {
n += 1 + l + sovTasks(uint64(l))
}
return n
}
func (m *WaitResponse) Size() (n int) {
var l int
_ = l
if m.ExitStatus != 0 {
n += 1 + sovTasks(uint64(m.ExitStatus))
}
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.ExitedAt)
n += 1 + l + sovTasks(uint64(l))
return n
}
func sovTasks(x uint64) (n int) { func sovTasks(x uint64) (n int) {
for { for {
n++ n++
@ -2410,7 +2546,7 @@ func (this *ListPidsResponse) String() string {
return "nil" return "nil"
} }
s := strings.Join([]string{`&ListPidsResponse{`, s := strings.Join([]string{`&ListPidsResponse{`,
`Pids:` + fmt.Sprintf("%v", this.Pids) + `,`, `Processes:` + strings.Replace(fmt.Sprintf("%v", this.Processes), "ProcessInfo", "containerd_v1_types.ProcessInfo", 1) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -2468,6 +2604,28 @@ func (this *MetricsResponse) String() string {
}, "") }, "")
return s return s
} }
func (this *WaitRequest) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&WaitRequest{`,
`ContainerID:` + fmt.Sprintf("%v", this.ContainerID) + `,`,
`ExecID:` + fmt.Sprintf("%v", this.ExecID) + `,`,
`}`,
}, "")
return s
}
func (this *WaitResponse) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&WaitResponse{`,
`ExitStatus:` + fmt.Sprintf("%v", this.ExitStatus) + `,`,
`ExitedAt:` + strings.Replace(strings.Replace(this.ExitedAt.String(), "Timestamp", "google_protobuf3.Timestamp", 1), `&`, ``, 1) + `,`,
`}`,
}, "")
return s
}
func valueToStringTasks(v interface{}) string { func valueToStringTasks(v interface{}) string {
rv := reflect.ValueOf(v) rv := reflect.ValueOf(v)
if rv.IsNil() { if rv.IsNil() {
@ -4705,67 +4863,36 @@ func (m *ListPidsResponse) Unmarshal(dAtA []byte) error {
} }
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType == 0 { if wireType != 2 {
var v uint32 return fmt.Errorf("proto: wrong wireType = %d for field Processes", wireType)
for shift := uint(0); ; shift += 7 { }
if shift >= 64 { var msglen int
return ErrIntOverflowTasks for shift := uint(0); ; shift += 7 {
} if shift >= 64 {
if iNdEx >= l { return ErrIntOverflowTasks
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
} }
m.Pids = append(m.Pids, v) if iNdEx >= l {
} else if wireType == 2 {
var packedLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTasks
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
packedLen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if packedLen < 0 {
return ErrInvalidLengthTasks
}
postIndex := iNdEx + packedLen
if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
for iNdEx < postIndex { b := dAtA[iNdEx]
var v uint32 iNdEx++
for shift := uint(0); ; shift += 7 { msglen |= (int(b) & 0x7F) << shift
if shift >= 64 { if b < 0x80 {
return ErrIntOverflowTasks break
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Pids = append(m.Pids, v)
} }
} else {
return fmt.Errorf("proto: wrong wireType = %d for field Pids", wireType)
} }
if msglen < 0 {
return ErrInvalidLengthTasks
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Processes = append(m.Processes, &containerd_v1_types.ProcessInfo{})
if err := m.Processes[len(m.Processes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipTasks(dAtA[iNdEx:]) skippy, err := skipTasks(dAtA[iNdEx:])
@ -5281,6 +5408,213 @@ func (m *MetricsResponse) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *WaitRequest) 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 ErrIntOverflowTasks
}
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: WaitRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: WaitRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ContainerID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTasks
}
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 ErrInvalidLengthTasks
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ContainerID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ExecID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTasks
}
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 ErrInvalidLengthTasks
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ExecID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTasks(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTasks
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *WaitResponse) 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 ErrIntOverflowTasks
}
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: WaitResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: WaitResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ExitStatus", wireType)
}
m.ExitStatus = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTasks
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ExitStatus |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ExitedAt", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTasks
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTasks
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.ExitedAt, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTasks(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTasks
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTasks(dAtA []byte) (n int, err error) { func skipTasks(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -5391,85 +5725,88 @@ func init() {
} }
var fileDescriptorTasks = []byte{ var fileDescriptorTasks = []byte{
// 1274 bytes of a gzipped FileDescriptorProto // 1317 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4f, 0x6f, 0x1b, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x5b, 0x6f, 0x1b, 0x45,
0x14, 0xef, 0xc6, 0xf6, 0xda, 0x7e, 0x6e, 0xda, 0x64, 0x48, 0xc3, 0xb2, 0x54, 0x71, 0x58, 0x24, 0x1b, 0xee, 0xfa, 0xec, 0xd7, 0x49, 0x9b, 0xec, 0x97, 0xe6, 0x33, 0x4b, 0x15, 0x87, 0xe5, 0xc6,
0x64, 0x02, 0xdd, 0xa5, 0x2e, 0xaa, 0x10, 0xad, 0x90, 0x9a, 0x3f, 0x44, 0x16, 0x54, 0x4d, 0xb7, 0x04, 0xba, 0x4b, 0x5d, 0x54, 0x21, 0x5a, 0x21, 0x35, 0x07, 0x22, 0x0b, 0xaa, 0xa6, 0xdb, 0x72,
0x05, 0xa1, 0x5e, 0xc2, 0x76, 0x77, 0xe2, 0x8c, 0x62, 0xef, 0x6e, 0x77, 0xc6, 0x69, 0x03, 0x07, 0x50, 0x25, 0x14, 0xb6, 0xbb, 0x13, 0x67, 0x14, 0x7b, 0x67, 0xbb, 0x33, 0x4e, 0x1b, 0xb8, 0x80,
0xf8, 0x08, 0xbd, 0x72, 0xe1, 0xf3, 0xe4, 0xc8, 0x11, 0x21, 0x14, 0xa8, 0xbf, 0x05, 0x07, 0x24, 0x9f, 0xd0, 0x5b, 0x6e, 0xf8, 0x3d, 0xb9, 0xe4, 0x12, 0xa1, 0x2a, 0x50, 0xff, 0x0b, 0xee, 0xd0,
0x34, 0x7f, 0x76, 0xb3, 0xb1, 0xe3, 0xd8, 0xa9, 0x1b, 0x2e, 0xed, 0xcc, 0xec, 0xef, 0xbd, 0x79, 0x1c, 0x76, 0xb3, 0xb1, 0x63, 0xaf, 0x93, 0x34, 0xdc, 0xb4, 0x33, 0xb3, 0xef, 0x69, 0x9e, 0x79,
0xf3, 0x9b, 0x37, 0xef, 0xfd, 0x1c, 0x58, 0x6d, 0x13, 0xb6, 0xdb, 0x7b, 0x6a, 0xfb, 0x51, 0xd7, 0x0f, 0x8f, 0x03, 0xab, 0x1d, 0xcc, 0x76, 0xfb, 0xcf, 0x2c, 0x8f, 0xf4, 0x6c, 0x8f, 0x04, 0xcc,
0xf1, 0xa3, 0x90, 0x79, 0x24, 0xc4, 0x49, 0x90, 0x1f, 0x7a, 0x31, 0x71, 0x28, 0x4e, 0xf6, 0x89, 0xc5, 0x01, 0x8a, 0xfc, 0xf4, 0xd2, 0x0d, 0xb1, 0x4d, 0x51, 0xb4, 0x8f, 0x3d, 0x44, 0x6d, 0xe6,
0x8f, 0xa9, 0xc3, 0x3c, 0xba, 0x47, 0x9d, 0xfd, 0x9b, 0x72, 0x60, 0xc7, 0x49, 0xc4, 0x22, 0x74, 0xd2, 0x3d, 0x6a, 0xef, 0xdf, 0x92, 0x0b, 0x2b, 0x8c, 0x08, 0x23, 0xfa, 0x8d, 0x63, 0x69, 0x2b,
0xfd, 0x18, 0x6d, 0xa7, 0x48, 0x5b, 0x02, 0xf6, 0x6f, 0x9a, 0xef, 0xb6, 0xa3, 0xa8, 0xdd, 0xc1, 0x96, 0xb4, 0xa4, 0xc0, 0xfe, 0x2d, 0xe3, 0xdd, 0x0e, 0x21, 0x9d, 0x2e, 0xb2, 0x85, 0xec, 0xb3,
0x8e, 0xc0, 0x3e, 0xed, 0xed, 0x38, 0xb8, 0x1b, 0xb3, 0x03, 0x69, 0x6a, 0xbe, 0x33, 0xf8, 0xd1, 0xfe, 0x8e, 0x8d, 0x7a, 0x21, 0x3b, 0x90, 0xaa, 0xc6, 0x3b, 0xc3, 0x1f, 0xdd, 0x20, 0xfe, 0xb4,
0x0b, 0xd3, 0x4f, 0x0b, 0xed, 0xa8, 0x1d, 0x89, 0xa1, 0xc3, 0x47, 0x6a, 0xf5, 0xf6, 0x44, 0xf1, 0xd0, 0x21, 0x1d, 0x22, 0x96, 0x36, 0x5f, 0xa9, 0xd3, 0x3b, 0x53, 0xc5, 0xcb, 0x0e, 0x42, 0x44,
0xb2, 0x83, 0x18, 0x53, 0xa7, 0x1b, 0xf5, 0x42, 0xa6, 0xec, 0x3e, 0x3b, 0x8f, 0x1d, 0x66, 0x09, 0xed, 0x1e, 0xe9, 0x07, 0x4c, 0xe9, 0x7d, 0x7a, 0x16, 0x3d, 0xc4, 0x22, 0xec, 0xa9, 0xdb, 0x19,
0xf1, 0xd5, 0xe9, 0xcc, 0x3b, 0xe7, 0xb0, 0x0c, 0x30, 0xf5, 0x13, 0x12, 0xb3, 0x28, 0x51, 0xc6, 0x77, 0xcf, 0xa0, 0xe9, 0x23, 0xea, 0x45, 0x38, 0x64, 0x24, 0x52, 0xca, 0x9f, 0x9d, 0x41, 0x99,
0x9f, 0x9f, 0xc3, 0x98, 0x33, 0x26, 0xfe, 0x51, 0xb6, 0xf5, 0x41, 0x6e, 0x18, 0xe9, 0x62, 0xca, 0x23, 0x26, 0xfe, 0x51, 0xba, 0x8d, 0x61, 0x6c, 0x18, 0xee, 0x21, 0xca, 0xdc, 0x5e, 0x28, 0x05,
0xbc, 0x6e, 0x2c, 0x01, 0xd6, 0xe1, 0x0c, 0xcc, 0xaf, 0x25, 0xd8, 0x63, 0xf8, 0xb1, 0x47, 0xf7, 0xcc, 0xc3, 0x1c, 0xcc, 0xaf, 0x45, 0xc8, 0x65, 0xe8, 0x89, 0x4b, 0xf7, 0x1c, 0xf4, 0xbc, 0x8f,
0x5c, 0xfc, 0xac, 0x87, 0x29, 0x43, 0x4d, 0xb8, 0x9c, 0xb9, 0xdf, 0x26, 0x81, 0xa1, 0x2d, 0x6b, 0x28, 0xd3, 0x5b, 0x30, 0x93, 0x98, 0xdf, 0xc6, 0x7e, 0x5d, 0x5b, 0xd6, 0x9a, 0xd5, 0xd5, 0x6b,
0x8d, 0xea, 0xea, 0xd5, 0xfe, 0x51, 0xbd, 0xb6, 0x96, 0xae, 0xb7, 0xd6, 0xdd, 0x5a, 0x06, 0x6a, 0x83, 0xa3, 0x46, 0x6d, 0x2d, 0x3e, 0x6f, 0xaf, 0x3b, 0xb5, 0x44, 0xa8, 0xed, 0xeb, 0x36, 0x94,
0x05, 0xc8, 0x01, 0x3d, 0x89, 0x22, 0xb6, 0x43, 0x8d, 0xc2, 0x72, 0xa1, 0x51, 0x6b, 0xbe, 0x6d, 0x22, 0x42, 0xd8, 0x0e, 0xad, 0xe7, 0x97, 0xf3, 0xcd, 0x5a, 0xeb, 0xff, 0x56, 0xea, 0x49, 0x45,
0xe7, 0xae, 0x54, 0x44, 0x67, 0xdf, 0xe7, 0x64, 0xba, 0x0a, 0x86, 0x16, 0xa0, 0x44, 0x59, 0x40, 0x74, 0xd6, 0x03, 0x0e, 0xa6, 0xa3, 0xc4, 0xf4, 0x05, 0x28, 0x52, 0xe6, 0xe3, 0xa0, 0x5e, 0xe0,
0x42, 0xa3, 0xc8, 0xbd, 0xbb, 0x72, 0x82, 0x16, 0x41, 0xa7, 0x2c, 0x88, 0x7a, 0xcc, 0x28, 0x89, 0xd6, 0x1d, 0xb9, 0xd1, 0x17, 0xa1, 0x44, 0x99, 0x4f, 0xfa, 0xac, 0x5e, 0x14, 0xc7, 0x6a, 0xa7,
0x65, 0x35, 0x53, 0xeb, 0x38, 0x49, 0x0c, 0x3d, 0x5b, 0xc7, 0x49, 0x82, 0x4c, 0xa8, 0x30, 0x9c, 0xce, 0x51, 0x14, 0xd5, 0x4b, 0xc9, 0x39, 0x8a, 0x22, 0xdd, 0x80, 0x0a, 0x43, 0x51, 0x0f, 0x07,
0x74, 0x49, 0xe8, 0x75, 0x8c, 0xf2, 0xb2, 0xd6, 0xa8, 0xb8, 0xd9, 0x1c, 0xdd, 0x05, 0xf0, 0x77, 0x6e, 0xb7, 0x5e, 0x5e, 0xd6, 0x9a, 0x15, 0x27, 0xd9, 0xeb, 0xf7, 0x00, 0xbc, 0x5d, 0xe4, 0xed,
0xb1, 0xbf, 0x17, 0x47, 0x24, 0x64, 0x46, 0x65, 0x59, 0x6b, 0xd4, 0x9a, 0xd7, 0x87, 0xc3, 0x5a, 0x85, 0x04, 0x07, 0xac, 0x5e, 0x59, 0xd6, 0x9a, 0xb5, 0xd6, 0x8d, 0xd1, 0xb0, 0xd6, 0x13, 0xc4,
0xcf, 0x18, 0x77, 0x73, 0x78, 0x64, 0x43, 0x39, 0x8a, 0x19, 0x89, 0x42, 0x6a, 0x54, 0x85, 0xe9, 0x9d, 0x94, 0xbc, 0x6e, 0x41, 0x99, 0x84, 0x0c, 0x93, 0x80, 0xd6, 0xab, 0x42, 0x75, 0xc1, 0x92,
0x82, 0x2d, 0xd9, 0xb4, 0x53, 0x36, 0xed, 0x7b, 0xe1, 0x81, 0x9b, 0x82, 0xac, 0x27, 0x80, 0xf2, 0x68, 0x5a, 0x31, 0x9a, 0xd6, 0xfd, 0xe0, 0xc0, 0x89, 0x85, 0xcc, 0xa7, 0xa0, 0xa7, 0x91, 0xa4,
0x4c, 0xd2, 0x38, 0x0a, 0x29, 0x7e, 0x2d, 0x2a, 0xe7, 0xa0, 0x10, 0x93, 0xc0, 0x98, 0x59, 0xd6, 0x21, 0x09, 0x28, 0x3a, 0x17, 0x94, 0x73, 0x90, 0x0f, 0xb1, 0x5f, 0xcf, 0x2d, 0x6b, 0xcd, 0x59,
0x1a, 0xb3, 0x2e, 0x1f, 0x5a, 0x6d, 0xb8, 0xfc, 0x88, 0x79, 0x09, 0x9b, 0xe6, 0x82, 0xde, 0x87, 0x87, 0x2f, 0xcd, 0x0e, 0xcc, 0x3c, 0x66, 0x6e, 0xc4, 0x2e, 0xf2, 0x40, 0xef, 0x43, 0x19, 0xbd,
0x32, 0x7e, 0x81, 0xfd, 0x6d, 0xe5, 0xb9, 0xba, 0x0a, 0xfd, 0xa3, 0xba, 0xbe, 0xf1, 0x02, 0xfb, 0x44, 0xde, 0xb6, 0xb2, 0x5c, 0x5d, 0x85, 0xc1, 0x51, 0xa3, 0xb4, 0xf1, 0x12, 0x79, 0xed, 0x75,
0xad, 0x75, 0x57, 0xe7, 0x9f, 0x5a, 0x81, 0xf5, 0x1e, 0xcc, 0xaa, 0x8d, 0x54, 0xfc, 0x2a, 0x16, 0xa7, 0xc4, 0x3f, 0xb5, 0x7d, 0xf3, 0x3d, 0x98, 0x55, 0x8e, 0x54, 0xfc, 0x2a, 0x16, 0xed, 0x38,
0xed, 0x38, 0x96, 0x4d, 0x98, 0x5f, 0xc7, 0x1d, 0x3c, 0x75, 0xc6, 0x58, 0xbf, 0x6a, 0x70, 0x45, 0x96, 0x4d, 0x98, 0x5f, 0x47, 0x5d, 0x74, 0xe1, 0x8c, 0x31, 0x7f, 0xd3, 0xe0, 0xaa, 0xb4, 0x94,
0x7a, 0xca, 0x76, 0x5b, 0x84, 0x99, 0xcc, 0x58, 0xef, 0x1f, 0xd5, 0x67, 0x5a, 0xeb, 0xee, 0x0c, 0x78, 0x5b, 0x84, 0x5c, 0xa2, 0x5c, 0x1a, 0x1c, 0x35, 0x72, 0xed, 0x75, 0x27, 0x87, 0x4f, 0x41,
0x39, 0x85, 0x11, 0x54, 0x87, 0x1a, 0x7e, 0x41, 0xd8, 0x36, 0x65, 0x1e, 0xeb, 0xf1, 0x9c, 0xe3, 0x44, 0x6f, 0x40, 0x0d, 0xbd, 0xc4, 0x6c, 0x9b, 0x32, 0x97, 0xf5, 0x79, 0xce, 0xf1, 0x2f, 0xc0,
0x5f, 0x80, 0x2f, 0x3d, 0x12, 0x2b, 0xe8, 0x1e, 0x54, 0xf9, 0x0c, 0x07, 0xdb, 0x1e, 0x13, 0x29, 0x8f, 0x1e, 0x8b, 0x13, 0xfd, 0x3e, 0x54, 0xf9, 0x0e, 0xf9, 0xdb, 0x2e, 0x13, 0x29, 0x56, 0x6b,
0x56, 0x6b, 0x9a, 0x43, 0x17, 0xf8, 0x38, 0x7d, 0x0e, 0xab, 0x95, 0xc3, 0xa3, 0xfa, 0xa5, 0x97, 0x19, 0x23, 0x0f, 0xf8, 0x24, 0x2e, 0x87, 0xd5, 0xca, 0xe1, 0x51, 0xe3, 0xca, 0xab, 0xbf, 0x1a,
0x7f, 0xd5, 0x35, 0xb7, 0x22, 0xcd, 0xee, 0x31, 0x2b, 0x82, 0x05, 0x19, 0xdf, 0x56, 0x12, 0xf9, 0x9a, 0x53, 0x91, 0x6a, 0xf7, 0x99, 0x49, 0x60, 0x41, 0xc6, 0xb7, 0x15, 0x11, 0x0f, 0x51, 0x7a,
0x98, 0xd2, 0x0b, 0x67, 0x1f, 0x03, 0x6c, 0xe2, 0x8b, 0xbf, 0xe4, 0x0d, 0xa8, 0x89, 0x6d, 0x14, 0xe9, 0xe8, 0x23, 0x80, 0x4d, 0x74, 0xf9, 0x8f, 0xbc, 0x01, 0x35, 0xe1, 0x46, 0x81, 0x7e, 0x07,
0xe9, 0xb7, 0xa1, 0x1c, 0xcb, 0x03, 0x8a, 0x2d, 0x06, 0xde, 0xc8, 0xfe, 0x4d, 0xf5, 0x4c, 0x52, 0xca, 0xa1, 0xbc, 0xa0, 0x70, 0x31, 0x54, 0x23, 0xfb, 0xb7, 0x54, 0x99, 0xc4, 0x20, 0xc4, 0xc2,
0x12, 0x52, 0xb0, 0xb5, 0x02, 0x73, 0x5f, 0x13, 0xca, 0x78, 0x1a, 0x64, 0xd4, 0x2c, 0x82, 0xbe, 0xe6, 0x0a, 0xcc, 0x7d, 0x85, 0x29, 0xe3, 0x69, 0x90, 0x40, 0xb3, 0x08, 0xa5, 0x1d, 0xdc, 0x65,
0x43, 0x3a, 0x0c, 0x27, 0x32, 0x5a, 0x57, 0xcd, 0x78, 0xd2, 0xe4, 0xb0, 0xd9, 0xdb, 0x28, 0x89, 0x28, 0x92, 0xd1, 0x3a, 0x6a, 0xc7, 0x93, 0x26, 0x25, 0x9b, 0xd4, 0x46, 0x51, 0xb4, 0xf8, 0xba,
0x12, 0x6f, 0x68, 0xa2, 0x62, 0x9c, 0xbd, 0xad, 0x84, 0x5a, 0x2f, 0x35, 0xa8, 0x7d, 0x45, 0x3a, 0x26, 0x3a, 0xc6, 0x64, 0xb7, 0x52, 0xd4, 0x7c, 0xa5, 0x41, 0xed, 0x4b, 0xdc, 0xed, 0x5e, 0x36,
0x9d, 0x8b, 0x26, 0x49, 0x14, 0x1c, 0xd2, 0xe6, 0x65, 0x45, 0xe6, 0x96, 0x9a, 0xf1, 0x54, 0xf4, 0x48, 0xa2, 0xe1, 0xe0, 0x0e, 0x6f, 0x2b, 0x32, 0xb7, 0xd4, 0x8e, 0xa7, 0xa2, 0xdb, 0xed, 0x8a,
0x3a, 0x1d, 0x91, 0x51, 0x15, 0x97, 0x0f, 0xad, 0x7f, 0x34, 0x40, 0xdc, 0xf8, 0x0d, 0x64, 0x49, 0x8c, 0xaa, 0x38, 0x7c, 0x69, 0xfe, 0xa3, 0x81, 0xce, 0x95, 0xdf, 0x42, 0x96, 0x24, 0x3d, 0x31,
0x56, 0x13, 0x67, 0x4e, 0xaf, 0x89, 0x85, 0x11, 0x35, 0xb1, 0x38, 0xb2, 0x26, 0x96, 0x06, 0x6a, 0x77, 0x7a, 0x4f, 0xcc, 0x8f, 0xe9, 0x89, 0x85, 0xb1, 0x3d, 0xb1, 0x38, 0xd4, 0x13, 0x9b, 0x50,
0x62, 0x03, 0x8a, 0x34, 0xc6, 0xbe, 0xa8, 0xa2, 0xa3, 0x4a, 0x9a, 0x40, 0xe4, 0x59, 0x2a, 0x8f, 0xa0, 0x21, 0xf2, 0x44, 0x17, 0x1d, 0xd7, 0xd2, 0x84, 0x44, 0x1a, 0xa5, 0xf2, 0xd8, 0x54, 0xba,
0x4c, 0xa5, 0x6b, 0xf0, 0xd6, 0x89, 0xa3, 0xcb, 0x9b, 0xb5, 0x7e, 0xd1, 0x60, 0xce, 0xc5, 0x94, 0x0e, 0xff, 0x3b, 0x71, 0x75, 0xf9, 0xb2, 0xe6, 0xaf, 0x1a, 0xcc, 0x39, 0x88, 0xe2, 0x1f, 0xd1,
0xfc, 0x80, 0xb7, 0xd8, 0xc1, 0x85, 0x5f, 0xd5, 0x02, 0x94, 0x9e, 0x93, 0x80, 0xed, 0xaa, 0x9b, 0x16, 0x3b, 0xb8, 0xf4, 0xa7, 0x5a, 0x80, 0xe2, 0x0b, 0xec, 0xb3, 0x5d, 0xf5, 0x52, 0x72, 0xc3,
0x92, 0x13, 0xce, 0xce, 0x2e, 0x26, 0xed, 0x5d, 0xf9, 0xfa, 0x67, 0x5d, 0x35, 0xb3, 0x7e, 0x82, 0xd1, 0xd9, 0x45, 0xb8, 0xb3, 0x2b, 0xab, 0x7f, 0xd6, 0x51, 0x3b, 0xf3, 0x67, 0xb8, 0xba, 0xd6,
0x2b, 0x6b, 0x9d, 0x88, 0xe2, 0xd6, 0x83, 0xff, 0x23, 0x30, 0x79, 0x9d, 0x05, 0x71, 0x0b, 0x72, 0x25, 0x14, 0xb5, 0x1f, 0xfe, 0x17, 0x81, 0xc9, 0xe7, 0xcc, 0x8b, 0x57, 0x90, 0x1b, 0xf3, 0x0b,
0x62, 0x7d, 0x09, 0x73, 0x5b, 0x5e, 0x8f, 0x4e, 0x5d, 0x3f, 0x37, 0x61, 0xde, 0xc5, 0xb4, 0xd7, 0x98, 0xdb, 0x72, 0xfb, 0xf4, 0xc2, 0xfd, 0x73, 0x13, 0xe6, 0x1d, 0x44, 0xfb, 0xbd, 0x0b, 0x1b,
0x9d, 0xda, 0xd1, 0x06, 0x5c, 0xe5, 0x8f, 0x73, 0x8b, 0x04, 0xd3, 0x24, 0xaf, 0xf5, 0x81, 0xac, 0xda, 0x80, 0x6b, 0xbc, 0x38, 0xb7, 0xb0, 0x7f, 0x91, 0xe4, 0x35, 0x1d, 0xd9, 0x0f, 0xa4, 0x19,
0x07, 0xd2, 0x8d, 0x7a, 0xe2, 0x08, 0x8a, 0x31, 0x09, 0xe4, 0x0b, 0x9f, 0x75, 0xc5, 0xd8, 0xfa, 0x55, 0xe2, 0x9f, 0x43, 0x55, 0xb5, 0x0b, 0x14, 0x97, 0xf9, 0xf2, 0xa4, 0x32, 0x6f, 0x07, 0x3b,
0x53, 0x83, 0x6b, 0x6b, 0x59, 0x9f, 0x9d, 0x56, 0x77, 0x6c, 0xc3, 0x7c, 0xec, 0x25, 0x38, 0x64, 0xc4, 0x39, 0x56, 0x31, 0x5f, 0x6b, 0x70, 0x7d, 0x2d, 0x99, 0xc9, 0x17, 0xe5, 0x28, 0xdb, 0x30,
0xdb, 0xb9, 0x5e, 0x2f, 0xaf, 0xa4, 0xc9, 0x6b, 0xfa, 0x1f, 0x47, 0xf5, 0x95, 0x9c, 0x82, 0x8a, 0x1f, 0xba, 0x11, 0x0a, 0xd8, 0x76, 0x8a, 0x17, 0xc8, 0xe7, 0x6b, 0xf1, 0xfe, 0xff, 0xe7, 0x51,
0x62, 0x1c, 0x66, 0xe6, 0xd4, 0x69, 0x47, 0x37, 0x02, 0xd2, 0xc6, 0x94, 0xd9, 0xeb, 0xe2, 0x3f, 0x63, 0x25, 0xc5, 0xb6, 0x48, 0x88, 0x82, 0x44, 0x9d, 0xda, 0x1d, 0x72, 0xd3, 0xc7, 0x1d, 0x44,
0x77, 0x4e, 0x3a, 0x5b, 0x3b, 0x55, 0x07, 0x14, 0x26, 0xd1, 0x01, 0xdf, 0xc1, 0xe2, 0xe0, 0xe9, 0x99, 0xb5, 0x2e, 0xfe, 0x73, 0xe6, 0xa4, 0xb1, 0xb5, 0x53, 0x39, 0x43, 0x7e, 0x1a, 0xce, 0xf0,
0x14, 0x19, 0x5f, 0x40, 0xed, 0x58, 0xdd, 0x9d, 0x5a, 0xf5, 0x86, 0x04, 0x49, 0xde, 0xc0, 0xfa, 0x1d, 0x2c, 0x0e, 0xdf, 0x2e, 0x01, 0xae, 0x76, 0xcc, 0x04, 0x4f, 0xed, 0x90, 0x23, 0xe4, 0x25,
0x11, 0xe6, 0xbf, 0x89, 0x83, 0x37, 0xa0, 0xd5, 0x9a, 0x50, 0x4d, 0x30, 0x8d, 0x7a, 0x89, 0x8f, 0xad, 0x60, 0xfe, 0x04, 0xf3, 0x5f, 0x87, 0xfe, 0x5b, 0xe0, 0x75, 0x2d, 0xa8, 0x46, 0x88, 0x92,
0xa9, 0xe0, 0x6a, 0xd4, 0xa1, 0x8e, 0x61, 0xd6, 0x0a, 0x5c, 0xb9, 0x2f, 0x45, 0x6d, 0xba, 0xb3, 0x7e, 0xe4, 0x21, 0x2a, 0xb0, 0x1a, 0x77, 0xa9, 0x63, 0x31, 0x73, 0x05, 0xae, 0x3e, 0x90, 0x04,
0x01, 0x65, 0x59, 0xdd, 0xe5, 0x51, 0xaa, 0x6e, 0x3a, 0xe5, 0x09, 0x95, 0x61, 0xb3, 0x5a, 0x5f, 0x38, 0xf6, 0x5c, 0x87, 0xb2, 0x9c, 0x04, 0xf2, 0x2a, 0x55, 0x27, 0xde, 0xf2, 0xe4, 0x4b, 0x64,
0x56, 0x9a, 0x58, 0x9d, 0xdb, 0x38, 0x45, 0x1f, 0x0a, 0x80, 0x9b, 0x02, 0x9b, 0xff, 0xd6, 0xa0, 0x93, 0xb9, 0x50, 0x56, 0xfc, 0x59, 0xdd, 0xbb, 0x7e, 0x0a, 0x97, 0x14, 0x02, 0x4e, 0x2c, 0x68,
0x24, 0x3a, 0x06, 0xda, 0x03, 0x5d, 0x6a, 0x2b, 0xe4, 0xd8, 0x67, 0xfd, 0x52, 0xb0, 0x87, 0xb4, 0xee, 0x40, 0xed, 0x5b, 0x17, 0x5f, 0xfe, 0xec, 0x8c, 0x60, 0x46, 0xfa, 0x51, 0xb1, 0x0e, 0xf1,
0xac, 0xf9, 0xc9, 0xe4, 0x06, 0x2a, 0xd4, 0xef, 0xa1, 0x24, 0x34, 0x10, 0x5a, 0x39, 0xdb, 0x34, 0x10, 0x6d, 0x32, 0x0f, 0xc9, 0x9d, 0x87, 0x87, 0xb4, 0x5e, 0xcf, 0x40, 0x51, 0x4c, 0x4e, 0x7d,
0xaf, 0xc8, 0xcc, 0x8f, 0x26, 0xc2, 0xaa, 0x1d, 0xda, 0xa0, 0x4b, 0x61, 0x31, 0xee, 0x38, 0x43, 0x0f, 0x4a, 0x92, 0x63, 0xea, 0xb6, 0x35, 0xe9, 0x17, 0x93, 0x35, 0xc2, 0xe9, 0x8d, 0x8f, 0xa7,
0x42, 0xcb, 0xfc, 0x78, 0x12, 0x83, 0x6c, 0xa3, 0x67, 0x30, 0x7b, 0x42, 0xc1, 0xa0, 0xe6, 0x24, 0x57, 0x50, 0x57, 0xfb, 0x01, 0x8a, 0x82, 0x0b, 0xea, 0x2b, 0x93, 0x55, 0xd3, 0xcc, 0xd4, 0xf8,
0xe6, 0x27, 0x1b, 0xd9, 0x39, 0xb7, 0x7c, 0x02, 0x85, 0x4d, 0xcc, 0x50, 0xe3, 0x6c, 0xa3, 0x63, 0x70, 0x2a, 0x59, 0xe5, 0xa1, 0x03, 0x25, 0x49, 0xb0, 0xb2, 0xae, 0x33, 0x42, 0x38, 0x8d, 0x8f,
0x99, 0x63, 0x7e, 0x38, 0x01, 0x32, 0xe3, 0xad, 0xc8, 0x2b, 0x0c, 0xb2, 0xcf, 0x36, 0x19, 0x54, 0xa6, 0x51, 0x48, 0x1c, 0x3d, 0x87, 0xd9, 0x13, 0x4c, 0x4e, 0x6f, 0x4d, 0xa3, 0x7e, 0x72, 0xa0,
0x25, 0xa6, 0x33, 0x31, 0x5e, 0x6d, 0xd4, 0x82, 0x22, 0x17, 0x19, 0x68, 0x4c, 0x6c, 0x39, 0x21, 0x9f, 0xd1, 0xe5, 0x53, 0xc8, 0x6f, 0x22, 0xa6, 0x37, 0x27, 0x2b, 0x1d, 0xd3, 0x3d, 0xe3, 0x83,
0x62, 0x2e, 0x0e, 0x3d, 0xa0, 0x0d, 0xfe, 0x23, 0x15, 0x6d, 0x41, 0x91, 0x77, 0x05, 0x34, 0x26, 0x29, 0x24, 0x13, 0xdc, 0x0a, 0xbc, 0xd3, 0xea, 0xd6, 0x64, 0x95, 0x61, 0x76, 0x66, 0xd8, 0x53,
0x0f, 0x87, 0x05, 0xc4, 0x48, 0x8f, 0x8f, 0xa0, 0x9a, 0xf5, 0xd6, 0x71, 0x54, 0x0c, 0x36, 0xe1, 0xcb, 0x2b, 0x47, 0x6d, 0x28, 0x70, 0xb2, 0xa5, 0x67, 0xc4, 0x96, 0x22, 0x64, 0xc6, 0xe2, 0x48,
0x91, 0x4e, 0x1f, 0x40, 0x59, 0x75, 0x45, 0x34, 0xe6, 0xbe, 0x4f, 0x36, 0xcf, 0x33, 0x1c, 0x96, 0x72, 0x6f, 0xf0, 0x1f, 0xeb, 0xfa, 0x16, 0x14, 0x78, 0x29, 0xe9, 0x19, 0x79, 0x38, 0x4a, 0xa4,
0x44, 0x97, 0x1b, 0x17, 0xe1, 0x60, 0x2b, 0x1c, 0xe9, 0xf0, 0x21, 0xe8, 0xb2, 0xdd, 0x8d, 0x7b, 0xc6, 0x5a, 0x7c, 0x0c, 0xd5, 0x84, 0x63, 0x64, 0x41, 0x31, 0x4c, 0x46, 0xc6, 0x1a, 0x7d, 0x08,
0x34, 0x43, 0x4d, 0x71, 0xa4, 0x4b, 0x02, 0x95, 0xb4, 0x63, 0xa1, 0x1b, 0xe3, 0x73, 0x24, 0xd7, 0x65, 0xc5, 0x0e, 0xf4, 0x8c, 0xf7, 0x3e, 0x49, 0x22, 0x26, 0x18, 0x2c, 0x8a, 0x69, 0x9f, 0x15,
0x20, 0x4d, 0x7b, 0x52, 0xb8, 0xca, 0xa8, 0xe7, 0x00, 0xb9, 0x9e, 0x72, 0x6b, 0x0c, 0xc5, 0xa7, 0xe1, 0x30, 0x25, 0x18, 0x6b, 0xf0, 0x11, 0x94, 0xe4, 0xd8, 0xcf, 0x2a, 0x9a, 0x11, 0x72, 0x30,
0x75, 0x47, 0xf3, 0xd3, 0xf3, 0x19, 0xa9, 0x8d, 0x1f, 0x82, 0x2e, 0x9b, 0xc6, 0x38, 0xda, 0x86, 0xd6, 0x24, 0x86, 0x4a, 0x3c, 0xb9, 0xf5, 0x9b, 0xd9, 0x39, 0x92, 0x22, 0x0a, 0x86, 0x35, 0xad,
0x5a, 0xcb, 0x48, 0xda, 0x76, 0xa0, 0xac, 0xca, 0xfb, 0xb8, 0x5c, 0x39, 0xd9, 0x31, 0xcc, 0x1b, 0xb8, 0xca, 0xa8, 0x17, 0x00, 0xa9, 0x79, 0x79, 0x3b, 0x03, 0xe2, 0xd3, 0x26, 0xbf, 0xf1, 0xc9,
0x13, 0xa2, 0x65, 0xe8, 0xab, 0xdf, 0x1e, 0xbe, 0x5a, 0xba, 0xf4, 0xfb, 0xab, 0xa5, 0x4b, 0x3f, 0xd9, 0x94, 0x94, 0xe3, 0x47, 0x50, 0x92, 0x03, 0x31, 0x0b, 0xb6, 0x91, 0xb1, 0x39, 0x16, 0xb6,
0xf7, 0x97, 0xb4, 0xc3, 0xfe, 0x92, 0xf6, 0x5b, 0x7f, 0x49, 0xfb, 0xbb, 0xbf, 0xa4, 0x3d, 0xb9, 0x1d, 0x28, 0xab, 0xd1, 0x95, 0x95, 0x2b, 0x27, 0xa7, 0xa1, 0x71, 0x73, 0x4a, 0x69, 0x15, 0xfa,
0xfb, 0x7a, 0x7f, 0x72, 0xba, 0x23, 0x06, 0x4f, 0x75, 0x71, 0x9e, 0x5b, 0xff, 0x05, 0x00, 0x00, 0xf7, 0x50, 0xe0, 0x33, 0x27, 0xab, 0x0a, 0x53, 0xf3, 0xcf, 0x58, 0x99, 0x46, 0x54, 0x9a, 0x5f,
0xff, 0xff, 0x5e, 0xf6, 0xae, 0x85, 0xb9, 0x12, 0x00, 0x00, 0xfd, 0xe6, 0xf0, 0xcd, 0xd2, 0x95, 0x3f, 0xde, 0x2c, 0x5d, 0xf9, 0x65, 0xb0, 0xa4, 0x1d, 0x0e,
0x96, 0xb4, 0xdf, 0x07, 0x4b, 0xda, 0xdf, 0x83, 0x25, 0xed, 0xe9, 0xbd, 0xf3, 0xfd, 0x65, 0xef,
0xae, 0x58, 0x3c, 0x2b, 0x09, 0xb8, 0x6e, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x67, 0xc5, 0x63,
0x32, 0x20, 0x14, 0x00, 0x00,
} }

View File

@ -49,6 +49,8 @@ service Tasks {
rpc Update(UpdateTaskRequest) returns (google.protobuf.Empty); rpc Update(UpdateTaskRequest) returns (google.protobuf.Empty);
rpc Metrics(MetricsRequest) returns (MetricsResponse); rpc Metrics(MetricsRequest) returns (MetricsResponse);
rpc Wait(WaitRequest) returns (WaitResponse);
} }
message CreateTaskRequest { message CreateTaskRequest {
@ -168,8 +170,9 @@ message ListPidsRequest {
string container_id = 1; string container_id = 1;
} }
message ListPidsResponse{ message ListPidsResponse {
repeated uint32 pids = 1; // Processes includes the process ID and additional process information
repeated containerd.v1.types.ProcessInfo processes = 1;
} }
message CheckpointTaskRequest { message CheckpointTaskRequest {
@ -194,3 +197,13 @@ message MetricsRequest {
message MetricsResponse { message MetricsResponse {
repeated types.Metric metrics = 1; repeated types.Metric metrics = 1;
} }
message WaitRequest {
string container_id = 1;
string exec_id = 2;
}
message WaitResponse {
uint32 exit_status = 1;
google.protobuf.Timestamp exited_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
}

View File

@ -9,11 +9,13 @@
github.com/containerd/containerd/api/types/descriptor.proto github.com/containerd/containerd/api/types/descriptor.proto
github.com/containerd/containerd/api/types/metrics.proto github.com/containerd/containerd/api/types/metrics.proto
github.com/containerd/containerd/api/types/mount.proto github.com/containerd/containerd/api/types/mount.proto
github.com/containerd/containerd/api/types/platform.proto
It has these top-level messages: It has these top-level messages:
Descriptor Descriptor
Metric Metric
Mount Mount
Platform
*/ */
package types package types

View File

@ -0,0 +1,412 @@
// Code generated by protoc-gen-gogo.
// source: github.com/containerd/containerd/api/types/platform.proto
// DO NOT EDIT!
package types
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import strings "strings"
import reflect "reflect"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// Platform follows the structure of the OCI platform specification, from
// descriptors.
type Platform struct {
OS string `protobuf:"bytes,1,opt,name=os,proto3" json:"os,omitempty"`
Architecture string `protobuf:"bytes,2,opt,name=architecture,proto3" json:"architecture,omitempty"`
Variant string `protobuf:"bytes,3,opt,name=variant,proto3" json:"variant,omitempty"`
}
func (m *Platform) Reset() { *m = Platform{} }
func (*Platform) ProtoMessage() {}
func (*Platform) Descriptor() ([]byte, []int) { return fileDescriptorPlatform, []int{0} }
func init() {
proto.RegisterType((*Platform)(nil), "containerd.types.Platform")
}
func (m *Platform) 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 *Platform) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.OS) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintPlatform(dAtA, i, uint64(len(m.OS)))
i += copy(dAtA[i:], m.OS)
}
if len(m.Architecture) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintPlatform(dAtA, i, uint64(len(m.Architecture)))
i += copy(dAtA[i:], m.Architecture)
}
if len(m.Variant) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintPlatform(dAtA, i, uint64(len(m.Variant)))
i += copy(dAtA[i:], m.Variant)
}
return i, nil
}
func encodeFixed64Platform(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Platform(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintPlatform(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 *Platform) Size() (n int) {
var l int
_ = l
l = len(m.OS)
if l > 0 {
n += 1 + l + sovPlatform(uint64(l))
}
l = len(m.Architecture)
if l > 0 {
n += 1 + l + sovPlatform(uint64(l))
}
l = len(m.Variant)
if l > 0 {
n += 1 + l + sovPlatform(uint64(l))
}
return n
}
func sovPlatform(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozPlatform(x uint64) (n int) {
return sovPlatform(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *Platform) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&Platform{`,
`OS:` + fmt.Sprintf("%v", this.OS) + `,`,
`Architecture:` + fmt.Sprintf("%v", this.Architecture) + `,`,
`Variant:` + fmt.Sprintf("%v", this.Variant) + `,`,
`}`,
}, "")
return s
}
func valueToStringPlatform(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *Platform) 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 ErrIntOverflowPlatform
}
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: Platform: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Platform: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field OS", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPlatform
}
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 ErrInvalidLengthPlatform
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.OS = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Architecture", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPlatform
}
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 ErrInvalidLengthPlatform
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Architecture = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Variant", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPlatform
}
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 ErrInvalidLengthPlatform
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Variant = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipPlatform(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPlatform
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipPlatform(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, ErrIntOverflowPlatform
}
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, ErrIntOverflowPlatform
}
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, ErrIntOverflowPlatform
}
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, ErrInvalidLengthPlatform
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowPlatform
}
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 := skipPlatform(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 (
ErrInvalidLengthPlatform = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowPlatform = fmt.Errorf("proto: integer overflow")
)
func init() {
proto.RegisterFile("github.com/containerd/containerd/api/types/platform.proto", fileDescriptorPlatform)
}
var fileDescriptorPlatform = []byte{
// 203 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4c, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d,
0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0x17, 0xe4, 0x24,
0x96, 0xa4, 0xe5, 0x17, 0xe5, 0xea, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0x09, 0x20, 0x14, 0xe9,
0x81, 0x15, 0x48, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf5, 0x41, 0x2c, 0x88, 0x3a, 0xa5,
0x04, 0x2e, 0x8e, 0x00, 0xa8, 0x4e, 0x21, 0x31, 0x2e, 0xa6, 0xfc, 0x62, 0x09, 0x46, 0x05, 0x46,
0x0d, 0x4e, 0x27, 0xb6, 0x47, 0xf7, 0xe4, 0x99, 0xfc, 0x83, 0x83, 0x98, 0xf2, 0x8b, 0x85, 0x94,
0xb8, 0x78, 0x12, 0x8b, 0x92, 0x33, 0x32, 0x4b, 0x52, 0x93, 0x4b, 0x4a, 0x8b, 0x52, 0x25, 0x98,
0x40, 0x2a, 0x82, 0x50, 0xc4, 0x84, 0x24, 0xb8, 0xd8, 0xcb, 0x12, 0x8b, 0x32, 0x13, 0xf3, 0x4a,
0x24, 0x98, 0xc1, 0xd2, 0x30, 0xae, 0x93, 0xd7, 0x89, 0x87, 0x72, 0x0c, 0x37, 0x1e, 0xca, 0x31,
0x34, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4,
0x18, 0xa3, 0x0c, 0x88, 0xf7, 0x9e, 0x35, 0x98, 0x4c, 0x62, 0x03, 0x3b, 0xda, 0x18, 0x10, 0x00,
0x00, 0xff, 0xff, 0x97, 0xa1, 0x99, 0x56, 0x19, 0x01, 0x00, 0x00,
}

View File

@ -0,0 +1,15 @@
syntax = "proto3";
package containerd.types;
import "gogoproto/gogo.proto";
option go_package = "github.com/containerd/containerd/api/types;types";
// Platform follows the structure of the OCI platform specification, from
// descriptors.
message Platform {
string os = 1 [(gogoproto.customname) = "OS"];
string architecture = 2;
string variant = 3;
}

View File

@ -10,6 +10,7 @@
It has these top-level messages: It has these top-level messages:
Process Process
ProcessInfo
*/ */
package task package task
@ -18,6 +19,7 @@ import fmt "fmt"
import math "math" import math "math"
import _ "github.com/gogo/protobuf/gogoproto" import _ "github.com/gogo/protobuf/gogoproto"
import _ "github.com/gogo/protobuf/types" import _ "github.com/gogo/protobuf/types"
import google_protobuf2 "github.com/gogo/protobuf/types"
import time "time" import time "time"
@ -90,8 +92,22 @@ func (m *Process) Reset() { *m = Process{} }
func (*Process) ProtoMessage() {} func (*Process) ProtoMessage() {}
func (*Process) Descriptor() ([]byte, []int) { return fileDescriptorTask, []int{0} } func (*Process) Descriptor() ([]byte, []int) { return fileDescriptorTask, []int{0} }
type ProcessInfo struct {
// PID is the process ID.
Pid uint32 `protobuf:"varint,1,opt,name=pid,proto3" json:"pid,omitempty"`
// Info contains additional process information.
//
// Info varies by platform.
Info *google_protobuf2.Any `protobuf:"bytes,2,opt,name=info" json:"info,omitempty"`
}
func (m *ProcessInfo) Reset() { *m = ProcessInfo{} }
func (*ProcessInfo) ProtoMessage() {}
func (*ProcessInfo) Descriptor() ([]byte, []int) { return fileDescriptorTask, []int{1} }
func init() { func init() {
proto.RegisterType((*Process)(nil), "containerd.v1.types.Process") proto.RegisterType((*Process)(nil), "containerd.v1.types.Process")
proto.RegisterType((*ProcessInfo)(nil), "containerd.v1.types.ProcessInfo")
proto.RegisterEnum("containerd.v1.types.Status", Status_name, Status_value) proto.RegisterEnum("containerd.v1.types.Status", Status_name, Status_value)
} }
func (m *Process) Marshal() (dAtA []byte, err error) { func (m *Process) Marshal() (dAtA []byte, err error) {
@ -175,6 +191,39 @@ func (m *Process) MarshalTo(dAtA []byte) (int, error) {
return i, nil return i, nil
} }
func (m *ProcessInfo) 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 *ProcessInfo) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Pid != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintTask(dAtA, i, uint64(m.Pid))
}
if m.Info != nil {
dAtA[i] = 0x12
i++
i = encodeVarintTask(dAtA, i, uint64(m.Info.Size()))
n2, err := m.Info.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n2
}
return i, nil
}
func encodeFixed64Task(dAtA []byte, offset int, v uint64) int { func encodeFixed64Task(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v) dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8) dAtA[offset+1] = uint8(v >> 8)
@ -242,6 +291,19 @@ func (m *Process) Size() (n int) {
return n return n
} }
func (m *ProcessInfo) Size() (n int) {
var l int
_ = l
if m.Pid != 0 {
n += 1 + sovTask(uint64(m.Pid))
}
if m.Info != nil {
l = m.Info.Size()
n += 1 + l + sovTask(uint64(l))
}
return n
}
func sovTask(x uint64) (n int) { func sovTask(x uint64) (n int) {
for { for {
n++ n++
@ -274,6 +336,17 @@ func (this *Process) String() string {
}, "") }, "")
return s return s
} }
func (this *ProcessInfo) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&ProcessInfo{`,
`Pid:` + fmt.Sprintf("%v", this.Pid) + `,`,
`Info:` + strings.Replace(fmt.Sprintf("%v", this.Info), "Any", "google_protobuf2.Any", 1) + `,`,
`}`,
}, "")
return s
}
func valueToStringTask(v interface{}) string { func valueToStringTask(v interface{}) string {
rv := reflect.ValueOf(v) rv := reflect.ValueOf(v)
if rv.IsNil() { if rv.IsNil() {
@ -584,6 +657,108 @@ func (m *Process) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *ProcessInfo) 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 ErrIntOverflowTask
}
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: ProcessInfo: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ProcessInfo: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Pid", wireType)
}
m.Pid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTask
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Pid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTask
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthTask
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Info == nil {
m.Info = &google_protobuf2.Any{}
}
if err := m.Info.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTask(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTask
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTask(dAtA []byte) (n int, err error) { func skipTask(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -694,37 +869,39 @@ func init() {
} }
var fileDescriptorTask = []byte{ var fileDescriptorTask = []byte{
// 503 bytes of a gzipped FileDescriptorProto // 543 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x3d, 0x6f, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xcf, 0x6e, 0xd3, 0x4c,
0x1c, 0xc6, 0x73, 0x6e, 0xe3, 0x24, 0x97, 0xb6, 0x98, 0xa3, 0xaa, 0x2c, 0x83, 0x6c, 0x8b, 0x29, 0x14, 0xc5, 0x33, 0x6e, 0xe3, 0x24, 0xe3, 0xb6, 0x9f, 0x3f, 0x13, 0x55, 0xc6, 0x20, 0xdb, 0xea,
0x62, 0xb0, 0x45, 0xba, 0xb1, 0xe5, 0x4d, 0x28, 0x42, 0x72, 0xa3, 0x4b, 0x22, 0xc6, 0xc8, 0xc9, 0xca, 0x62, 0x61, 0x8b, 0x74, 0xc7, 0x2e, 0xff, 0x84, 0x2c, 0x24, 0x37, 0x72, 0x12, 0xb1, 0x8c,
0x1d, 0xe6, 0xd4, 0xe6, 0xce, 0xb2, 0xcf, 0xbc, 0x6c, 0x8c, 0xa8, 0x13, 0x5f, 0xa0, 0x13, 0x7c, 0x9c, 0x78, 0x62, 0x46, 0x6d, 0x66, 0x2c, 0x7b, 0x0c, 0x64, 0xc7, 0x12, 0x75, 0xc5, 0x0b, 0x74,
0x0a, 0x3e, 0x41, 0x46, 0x26, 0xc4, 0x14, 0xa8, 0x3f, 0x09, 0x3a, 0xdb, 0x09, 0x19, 0x58, 0xac, 0x05, 0x4f, 0xc1, 0x13, 0x64, 0xc9, 0x0a, 0xb1, 0x0a, 0xd4, 0x4f, 0x82, 0xc6, 0x76, 0xd2, 0x08,
0x7b, 0x9e, 0xdf, 0x73, 0x8f, 0xff, 0xf7, 0x87, 0x2f, 0x22, 0x26, 0xdf, 0x66, 0x4b, 0x6f, 0x25, 0xd8, 0x8c, 0xee, 0x3d, 0xbf, 0x33, 0x77, 0xee, 0x1c, 0xf8, 0x22, 0xc2, 0xec, 0x4d, 0x36, 0xb7,
0xd6, 0xfe, 0x4a, 0x70, 0x19, 0x32, 0x4e, 0x13, 0x72, 0x78, 0x0c, 0x63, 0xe6, 0xcb, 0x8f, 0x31, 0x17, 0x74, 0xe5, 0x2c, 0x28, 0x61, 0x01, 0x26, 0x28, 0x09, 0x0f, 0xcb, 0x20, 0xc6, 0x0e, 0x5b,
0x4d, 0x7d, 0x19, 0xa6, 0xd7, 0xc5, 0xc7, 0x8b, 0x13, 0x21, 0x05, 0x7a, 0xf4, 0x2f, 0xe5, 0xbd, 0xc7, 0x28, 0x75, 0x58, 0x90, 0x5e, 0x17, 0x87, 0x1d, 0x27, 0x94, 0x51, 0xe5, 0xd1, 0x83, 0xcb,
0x7b, 0xee, 0x15, 0x21, 0xeb, 0x3c, 0x12, 0x91, 0x28, 0xb8, 0xaf, 0x4e, 0x65, 0xd4, 0x72, 0x22, 0x7e, 0xfb, 0xdc, 0x2e, 0x4c, 0x5a, 0x3b, 0xa2, 0x11, 0x2d, 0xb8, 0xc3, 0xab, 0xd2, 0xaa, 0x19,
0x21, 0xa2, 0x1b, 0xea, 0x17, 0x6a, 0x99, 0xbd, 0xf1, 0x25, 0x5b, 0xd3, 0x54, 0x86, 0xeb, 0xb8, 0x11, 0xa5, 0xd1, 0x0d, 0x72, 0x8a, 0x6e, 0x9e, 0x2d, 0x1d, 0x86, 0x57, 0x28, 0x65, 0xc1, 0x2a,
0x0c, 0x3c, 0xcd, 0x35, 0xd8, 0x98, 0x24, 0x62, 0x45, 0xd3, 0x14, 0x75, 0xe1, 0xc9, 0xbe, 0x79, 0xae, 0x0c, 0x8f, 0xff, 0x34, 0x04, 0x64, 0x5d, 0xa2, 0x8b, 0x5c, 0x80, 0x8d, 0x51, 0x42, 0x17,
0xc1, 0x88, 0x09, 0x5c, 0xd0, 0x69, 0xf5, 0x1f, 0xe4, 0x5b, 0xa7, 0x3d, 0xd8, 0xf9, 0xe3, 0x21, 0x28, 0x4d, 0x95, 0x0e, 0x3c, 0xd9, 0x3f, 0x3a, 0xc3, 0xa1, 0x0a, 0x4c, 0x60, 0xb5, 0x7a, 0xff,
0x6e, 0xef, 0x43, 0x63, 0x82, 0x2e, 0xa0, 0xc6, 0x88, 0xa9, 0x15, 0x49, 0x3d, 0xdf, 0x3a, 0xda, 0xe5, 0x5b, 0x43, 0xea, 0xef, 0x74, 0x77, 0xe0, 0x4b, 0x7b, 0x93, 0x1b, 0x2a, 0xe7, 0x50, 0xc0,
0x78, 0x88, 0x35, 0x46, 0x90, 0x01, 0x8f, 0x62, 0x46, 0xcc, 0x23, 0x17, 0x74, 0x4e, 0xb1, 0x3a, 0xa1, 0x2a, 0x14, 0x4e, 0x31, 0xdf, 0x1a, 0x82, 0x3b, 0xf0, 0x05, 0x1c, 0x2a, 0x32, 0x3c, 0x8a,
0xa2, 0x4b, 0xa8, 0xa7, 0x32, 0x94, 0x59, 0x6a, 0x1e, 0xbb, 0xa0, 0x73, 0xd6, 0x7d, 0xec, 0xfd, 0x71, 0xa8, 0x1e, 0x99, 0xc0, 0x3a, 0xf5, 0x79, 0xa9, 0x5c, 0x42, 0x31, 0x65, 0x01, 0xcb, 0x52,
0xe7, 0x19, 0xde, 0xb4, 0x88, 0xe0, 0x2a, 0x8a, 0xce, 0x61, 0x3d, 0x95, 0x84, 0x71, 0xb3, 0xae, 0xf5, 0xd8, 0x04, 0xd6, 0x59, 0xe7, 0x89, 0xfd, 0x8f, 0x1f, 0xda, 0xe3, 0xc2, 0xe2, 0x57, 0x56,
0xfe, 0x80, 0x4b, 0x81, 0x2e, 0x54, 0x15, 0x11, 0x99, 0x34, 0xf5, 0xc2, 0xae, 0x54, 0xe5, 0xd3, 0xa5, 0x0d, 0xeb, 0x29, 0x0b, 0x31, 0x51, 0xeb, 0xfc, 0x05, 0xbf, 0x6c, 0x94, 0x73, 0x3e, 0x2a,
0x24, 0x31, 0x1b, 0x7b, 0x9f, 0x26, 0x09, 0xb2, 0x60, 0x53, 0xd2, 0x64, 0xcd, 0x78, 0x78, 0x63, 0xa4, 0x19, 0x53, 0xc5, 0x42, 0xae, 0xba, 0x4a, 0x47, 0x49, 0xa2, 0x36, 0xf6, 0x3a, 0x4a, 0x12,
0x36, 0x5d, 0xd0, 0x69, 0xe2, 0xbd, 0x46, 0x0e, 0x6c, 0xd3, 0x0f, 0x4c, 0x2e, 0xaa, 0xd9, 0x5a, 0x45, 0x83, 0x4d, 0x86, 0x92, 0x15, 0x26, 0xc1, 0x8d, 0xda, 0x34, 0x81, 0xd5, 0xf4, 0xf7, 0xbd,
0xc5, 0xc0, 0x50, 0x59, 0xe5, 0x28, 0xa8, 0x07, 0x5b, 0x4a, 0x51, 0xb2, 0x08, 0xa5, 0x09, 0x5d, 0x62, 0x40, 0x09, 0xbd, 0xc7, 0x6c, 0x56, 0xed, 0xd6, 0x2a, 0x16, 0x86, 0x5c, 0x2a, 0x57, 0x51,
0xd0, 0x69, 0x77, 0x2d, 0xaf, 0x5c, 0xab, 0xb7, 0x5b, 0xab, 0x37, 0xdb, 0xad, 0xb5, 0xdf, 0xdc, 0xba, 0xb0, 0xc5, 0x3b, 0x14, 0xce, 0x02, 0xa6, 0x42, 0x13, 0x58, 0x52, 0x47, 0xb3, 0xcb, 0x40,
0x6c, 0x9d, 0xda, 0x97, 0xdf, 0x0e, 0xc0, 0xcd, 0xf2, 0x5a, 0x4f, 0x3e, 0xfb, 0x09, 0xa0, 0x5e, 0xed, 0x5d, 0xa0, 0xf6, 0x64, 0x97, 0x78, 0xaf, 0xb9, 0xd9, 0x1a, 0xb5, 0x4f, 0x3f, 0x0d, 0xe0,
0xb5, 0xd9, 0xb0, 0x31, 0x0f, 0x5e, 0x05, 0x57, 0xaf, 0x03, 0xa3, 0x66, 0x3d, 0xbc, 0xbd, 0x73, 0x37, 0xcb, 0x6b, 0x5d, 0x76, 0xe1, 0x42, 0xa9, 0xca, 0xd8, 0x25, 0x4b, 0xba, 0xcb, 0x06, 0x3c,
0x4f, 0x4b, 0x30, 0xe7, 0xd7, 0x5c, 0xbc, 0xe7, 0x8a, 0x0f, 0xf0, 0xa8, 0x37, 0x1b, 0x0d, 0x0d, 0x64, 0x63, 0xc1, 0x63, 0x4c, 0x96, 0xb4, 0xc8, 0x51, 0xea, 0xb4, 0xff, 0x1a, 0xdf, 0x25, 0x6b,
0x70, 0xc8, 0x07, 0x09, 0x0d, 0x25, 0x25, 0x8a, 0xe3, 0x79, 0x10, 0x8c, 0x83, 0x97, 0x86, 0x76, 0xbf, 0x70, 0x3c, 0xfb, 0x0e, 0xa0, 0x58, 0x2d, 0xa6, 0xc3, 0xc6, 0xd4, 0x7b, 0xe5, 0x5d, 0xbd,
0xc8, 0x71, 0xc6, 0x39, 0xe3, 0x91, 0xe2, 0xd3, 0xd9, 0xd5, 0x64, 0x32, 0x1a, 0x1a, 0x47, 0x87, 0xf6, 0xe4, 0x9a, 0xf6, 0xff, 0xed, 0x9d, 0x79, 0x5a, 0x82, 0x29, 0xb9, 0x26, 0xf4, 0x1d, 0xe1,
0x7c, 0x2a, 0x45, 0x1c, 0x53, 0x82, 0x9e, 0x40, 0x7d, 0xd2, 0x9b, 0x4f, 0x47, 0x43, 0xe3, 0xd8, 0xbc, 0xef, 0x0f, 0xbb, 0x93, 0xe1, 0x40, 0x06, 0x87, 0xbc, 0x9f, 0xa0, 0x80, 0xa1, 0x90, 0x73,
0x32, 0x6e, 0xef, 0xdc, 0x93, 0x12, 0x4f, 0xc2, 0x2c, 0x2d, 0xdb, 0x15, 0x55, 0xed, 0xf5, 0xc3, 0x7f, 0xea, 0x79, 0xae, 0xf7, 0x52, 0x16, 0x0e, 0xb9, 0x9f, 0x11, 0x82, 0x49, 0xc4, 0xf9, 0x78,
0xdb, 0x0a, 0x33, 0x1e, 0x59, 0x67, 0x9f, 0xbf, 0xda, 0xb5, 0xef, 0xdf, 0xec, 0xea, 0x35, 0x7d, 0x72, 0x35, 0x1a, 0x0d, 0x07, 0xf2, 0xd1, 0x21, 0x1f, 0x33, 0x1a, 0xc7, 0x28, 0x54, 0x9e, 0x42,
0x73, 0x73, 0x6f, 0xd7, 0x7e, 0xdd, 0xdb, 0xb5, 0x4f, 0xb9, 0x0d, 0x36, 0xb9, 0x0d, 0x7e, 0xe4, 0x71, 0xd4, 0x9d, 0x8e, 0x87, 0x03, 0xf9, 0x58, 0x93, 0x6f, 0xef, 0xcc, 0x93, 0x12, 0x8f, 0x82,
0x36, 0xf8, 0x93, 0xdb, 0x60, 0xa9, 0x17, 0xab, 0xb9, 0xfc, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x14, 0x2c, 0x2d, 0xa7, 0x73, 0xca, 0xa7, 0xd7, 0x0f, 0x6f, 0x73, 0x8c, 0x49, 0xa4, 0x9d, 0x7d, 0xfc,
0xf3, 0xee, 0x85, 0xe8, 0x02, 0x00, 0x00, 0xac, 0xd7, 0xbe, 0x7e, 0xd1, 0xab, 0xdf, 0xf4, 0xd4, 0xcd, 0xbd, 0x5e, 0xfb, 0x71, 0xaf, 0xd7,
0x3e, 0xe4, 0x3a, 0xd8, 0xe4, 0x3a, 0xf8, 0x96, 0xeb, 0xe0, 0x57, 0xae, 0x83, 0xb9, 0x58, 0xc4,
0x70, 0xf9, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x19, 0xf7, 0x5b, 0x8f, 0x4e, 0x03, 0x00, 0x00,
} }

View File

@ -4,6 +4,7 @@ package containerd.v1.types;
import "gogoproto/gogo.proto"; import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto"; import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";
enum Status { enum Status {
option (gogoproto.goproto_enum_prefix) = false; option (gogoproto.goproto_enum_prefix) = false;
@ -29,3 +30,12 @@ message Process {
uint32 exit_status = 9; uint32 exit_status = 9;
google.protobuf.Timestamp exited_at = 10 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; google.protobuf.Timestamp exited_at = 10 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
} }
message ProcessInfo {
// PID is the process ID.
uint32 pid = 1;
// Info contains additional process information.
//
// Info varies by platform.
google.protobuf.Any info = 2;
}

View File

@ -88,8 +88,6 @@ const (
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets // See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
func Apply(ctx context.Context, root string, r io.Reader) (int64, error) { func Apply(ctx context.Context, root string, r io.Reader) (int64, error) {
root = filepath.Clean(root) root = filepath.Clean(root)
fn := prepareApply()
defer fn()
var ( var (
tr = tar.NewReader(r) tr = tar.NewReader(r)
@ -107,6 +105,12 @@ func Apply(ctx context.Context, root string, r io.Reader) (int64, error) {
// Iterate through the files in the archive. // Iterate through the files in the archive.
for { for {
select {
case <-ctx.Done():
return 0, ctx.Err()
default:
}
hdr, err := tr.Next() hdr, err := tr.Next()
if err == io.EOF { if err == io.EOF {
// end of tar archive // end of tar archive
@ -445,19 +449,18 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header
// Create directory unless it exists as a directory already. // Create directory unless it exists as a directory already.
// In that case we just want to merge the two // In that case we just want to merge the two
if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) { if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
if err := os.Mkdir(path, hdrInfo.Mode()); err != nil { if err := mkdir(path, hdrInfo.Mode()); err != nil {
return err return err
} }
} }
case tar.TypeReg, tar.TypeRegA: case tar.TypeReg, tar.TypeRegA:
file, err := openFile(path, os.O_CREATE|os.O_WRONLY, hdrInfo.Mode()) file, err := openFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, hdrInfo.Mode())
if err != nil { if err != nil {
return err return err
} }
buf := bufferPool.Get().([]byte)
_, err = io.CopyBuffer(file, reader, buf) _, err = copyBuffered(ctx, file, reader)
bufferPool.Put(buf)
if err1 := file.Close(); err == nil { if err1 := file.Close(); err == nil {
err = err1 err = err1
} }
@ -522,9 +525,43 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header
return err return err
} }
if err := chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime)); err != nil { return chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime))
return err }
}
func copyBuffered(ctx context.Context, dst io.Writer, src io.Reader) (written int64, err error) {
return nil buf := bufferPool.Get().([]byte)
defer bufferPool.Put(buf)
for {
select {
case <-ctx.Done():
err = ctx.Err()
return
default:
}
nr, er := src.Read(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = io.ErrShortWrite
break
}
}
if er != nil {
if er != io.EOF {
err = er
}
break
}
}
return written, err
} }

View File

@ -31,44 +31,40 @@ func setHeaderForSpecialDevice(hdr *tar.Header, name string, fi os.FileInfo) err
// Currently go does not fill in the major/minors // Currently go does not fill in the major/minors
if s.Mode&syscall.S_IFBLK != 0 || if s.Mode&syscall.S_IFBLK != 0 ||
s.Mode&syscall.S_IFCHR != 0 { s.Mode&syscall.S_IFCHR != 0 {
hdr.Devmajor = int64(major(uint64(s.Rdev))) hdr.Devmajor = int64(unix.Major(uint64(s.Rdev)))
hdr.Devminor = int64(minor(uint64(s.Rdev))) hdr.Devminor = int64(unix.Minor(uint64(s.Rdev)))
} }
return nil return nil
} }
func major(device uint64) uint64 {
return (device >> 8) & 0xfff
}
func minor(device uint64) uint64 {
return (device & 0xff) | ((device >> 12) & 0xfff00)
}
func mkdev(major int64, minor int64) uint32 {
return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff))
}
func open(p string) (*os.File, error) { func open(p string) (*os.File, error) {
return os.Open(p) return os.Open(p)
} }
func openFile(name string, flag int, perm os.FileMode) (*os.File, error) { func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
return os.OpenFile(name, flag, perm) f, err := os.OpenFile(name, flag, perm)
if err != nil {
return nil, err
}
// Call chmod to avoid permission mask
if err := os.Chmod(name, perm); err != nil {
return nil, err
}
return f, err
} }
func mkdirAll(path string, perm os.FileMode) error { func mkdirAll(path string, perm os.FileMode) error {
return os.MkdirAll(path, perm) return os.MkdirAll(path, perm)
} }
func prepareApply() func() { func mkdir(path string, perm os.FileMode) error {
// Unset unmask before doing an apply operation, if err := os.Mkdir(path, perm); err != nil {
// restore unmask when complete return err
oldmask := unix.Umask(0)
return func() {
unix.Umask(oldmask)
} }
// Only final created directory gets explicit permission
// call to avoid permission mask
return os.Chmod(path, perm)
} }
func skipFile(*tar.Header) bool { func skipFile(*tar.Header) bool {
@ -103,7 +99,7 @@ func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
mode |= unix.S_IFIFO mode |= unix.S_IFIFO
} }
return unix.Mknod(path, mode, int(mkdev(hdr.Devmajor, hdr.Devminor))) return unix.Mknod(path, mode, int(unix.Mkdev(uint32(hdr.Devmajor), uint32(hdr.Devminor))))
} }
func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {

View File

@ -56,9 +56,8 @@ func mkdirAll(path string, perm os.FileMode) error {
return sys.MkdirAll(path, perm) return sys.MkdirAll(path, perm)
} }
func prepareApply() func() { func mkdir(path string, perm os.FileMode) error {
// No umask or filesystem changes needed before apply return os.Mkdir(path, perm)
return func() {}
} }
func skipFile(hdr *tar.Header) bool { func skipFile(hdr *tar.Header) bool {

View File

@ -15,26 +15,31 @@ import (
diffapi "github.com/containerd/containerd/api/services/diff/v1" diffapi "github.com/containerd/containerd/api/services/diff/v1"
eventsapi "github.com/containerd/containerd/api/services/events/v1" eventsapi "github.com/containerd/containerd/api/services/events/v1"
imagesapi "github.com/containerd/containerd/api/services/images/v1" imagesapi "github.com/containerd/containerd/api/services/images/v1"
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1" namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1"
snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1" snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1"
"github.com/containerd/containerd/api/services/tasks/v1" "github.com/containerd/containerd/api/services/tasks/v1"
versionservice "github.com/containerd/containerd/api/services/version/v1" versionservice "github.com/containerd/containerd/api/services/version/v1"
"github.com/containerd/containerd/containers" "github.com/containerd/containerd/containers"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/dialer"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/reference" "github.com/containerd/containerd/reference"
"github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker" "github.com/containerd/containerd/remotes/docker"
"github.com/containerd/containerd/remotes/docker/schema1" "github.com/containerd/containerd/remotes/docker/schema1"
contentservice "github.com/containerd/containerd/services/content" contentservice "github.com/containerd/containerd/services/content"
"github.com/containerd/containerd/services/diff"
diffservice "github.com/containerd/containerd/services/diff" diffservice "github.com/containerd/containerd/services/diff"
imagesservice "github.com/containerd/containerd/services/images" imagesservice "github.com/containerd/containerd/services/images"
namespacesservice "github.com/containerd/containerd/services/namespaces"
snapshotservice "github.com/containerd/containerd/services/snapshot" snapshotservice "github.com/containerd/containerd/services/snapshot"
"github.com/containerd/containerd/snapshot" "github.com/containerd/containerd/snapshot"
"github.com/containerd/containerd/typeurl" "github.com/containerd/typeurl"
pempty "github.com/golang/protobuf/ptypes/empty" pempty "github.com/golang/protobuf/ptypes/empty"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
@ -44,12 +49,13 @@ import (
) )
func init() { func init() {
const prefix = "types.containerd.io"
// register TypeUrls for commonly marshaled external types // register TypeUrls for commonly marshaled external types
major := strconv.Itoa(specs.VersionMajor) major := strconv.Itoa(specs.VersionMajor)
typeurl.Register(&specs.Spec{}, "opencontainers/runtime-spec", major, "Spec") typeurl.Register(&specs.Spec{}, prefix, "opencontainers/runtime-spec", major, "Spec")
typeurl.Register(&specs.Process{}, "opencontainers/runtime-spec", major, "Process") typeurl.Register(&specs.Process{}, prefix, "opencontainers/runtime-spec", major, "Process")
typeurl.Register(&specs.LinuxResources{}, "opencontainers/runtime-spec", major, "LinuxResources") typeurl.Register(&specs.LinuxResources{}, prefix, "opencontainers/runtime-spec", major, "LinuxResources")
typeurl.Register(&specs.WindowsResources{}, "opencontainers/runtime-spec", major, "WindowsResources") typeurl.Register(&specs.WindowsResources{}, prefix, "opencontainers/runtime-spec", major, "WindowsResources")
} }
// New returns a new containerd client that is connected to the containerd // New returns a new containerd client that is connected to the containerd
@ -67,7 +73,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
grpc.WithTimeout(60 * time.Second), grpc.WithTimeout(60 * time.Second),
grpc.FailOnNonTempDialError(true), grpc.FailOnNonTempDialError(true),
grpc.WithBackoffMaxDelay(3 * time.Second), grpc.WithBackoffMaxDelay(3 * time.Second),
grpc.WithDialer(Dialer), grpc.WithDialer(dialer.Dialer),
} }
if len(copts.dialOptions) > 0 { if len(copts.dialOptions) > 0 {
gopts = copts.dialOptions gopts = copts.dialOptions
@ -79,7 +85,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
grpc.WithStreamInterceptor(stream), grpc.WithStreamInterceptor(stream),
) )
} }
conn, err := grpc.Dial(DialAddress(address), gopts...) conn, err := grpc.Dial(dialer.DialAddress(address), gopts...)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to dial %q", address) return nil, errors.Wrapf(err, "failed to dial %q", address)
} }
@ -98,10 +104,8 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
// Client is the client to interact with containerd and its various services // Client is the client to interact with containerd and its various services
// using a uniform interface // using a uniform interface
type Client struct { type Client struct {
conn *grpc.ClientConn conn *grpc.ClientConn
runtime string
defaultns string
runtime string
} }
// IsServing returns true if the client can successfully connect to the // IsServing returns true if the client can successfully connect to the
@ -134,6 +138,12 @@ func (c *Client) Containers(ctx context.Context, filters ...string) ([]Container
// NewContainer will create a new container in container with the provided id // NewContainer will create a new container in container with the provided id
// the id must be unique within the namespace // the id must be unique within the namespace
func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) { func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) {
ctx, done, err := c.withLease(ctx)
if err != nil {
return nil, err
}
defer done()
container := containers.Container{ container := containers.Container{
ID: id, ID: id,
Runtime: containers.RuntimeInfo{ Runtime: containers.RuntimeInfo{
@ -176,6 +186,9 @@ type RemoteContext struct {
// Snapshotter used for unpacking // Snapshotter used for unpacking
Snapshotter string Snapshotter string
// Labels to be applied to the created image
Labels map[string]string
// BaseHandlers are a set of handlers which get are called on dispatch. // BaseHandlers are a set of handlers which get are called on dispatch.
// These handlers always get called before any operation specific // These handlers always get called before any operation specific
// handlers. // handlers.
@ -197,7 +210,7 @@ func defaultRemoteContext() *RemoteContext {
} }
// Pull downloads the provided content into containerd's content store // Pull downloads the provided content into containerd's content store
func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Image, error) { func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
pullCtx := defaultRemoteContext() pullCtx := defaultRemoteContext()
for _, o := range opts { for _, o := range opts {
if err := o(c, pullCtx); err != nil { if err := o(c, pullCtx); err != nil {
@ -206,6 +219,12 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
} }
store := c.ContentStore() store := c.ContentStore()
ctx, done, err := c.withLease(ctx)
if err != nil {
return nil, err
}
defer done()
name, desc, err := pullCtx.Resolver.Resolve(ctx, ref) name, desc, err := pullCtx.Resolver.Resolve(ctx, ref)
if err != nil { if err != nil {
return nil, err return nil, err
@ -225,7 +244,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
} else { } else {
handler = images.Handlers(append(pullCtx.BaseHandlers, handler = images.Handlers(append(pullCtx.BaseHandlers,
remotes.FetchHandler(store, fetcher), remotes.FetchHandler(store, fetcher),
images.ChildrenHandler(store))..., images.ChildrenHandler(store, platforms.Default()))...,
) )
} }
@ -242,22 +261,23 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
imgrec := images.Image{ imgrec := images.Image{
Name: name, Name: name,
Target: desc, Target: desc,
Labels: pullCtx.Labels,
} }
is := c.ImageService() is := c.ImageService()
if updated, err := is.Update(ctx, imgrec, "target"); err != nil { if created, err := is.Create(ctx, imgrec); err != nil {
if !errdefs.IsNotFound(err) { if !errdefs.IsAlreadyExists(err) {
return nil, err return nil, err
} }
created, err := is.Create(ctx, imgrec) updated, err := is.Update(ctx, imgrec)
if err != nil { if err != nil {
return nil, err return nil, err
} }
imgrec = created
} else {
imgrec = updated imgrec = updated
} else {
imgrec = created
} }
img := &image{ img := &image{
@ -273,7 +293,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpts) (Imag
} }
// Push uploads the provided content to a remote resource // Push uploads the provided content to a remote resource
func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor, opts ...RemoteOpts) error { func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor, opts ...RemoteOpt) error {
pushCtx := defaultRemoteContext() pushCtx := defaultRemoteContext()
for _, o := range opts { for _, o := range opts {
if err := o(c, pushCtx); err != nil { if err := o(c, pushCtx); err != nil {
@ -296,7 +316,7 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
m.Lock() m.Lock()
manifestStack = append(manifestStack, desc) manifestStack = append(manifestStack, desc)
m.Unlock() m.Unlock()
return nil, images.StopHandler return nil, images.ErrStopHandler
default: default:
return nil, nil return nil, nil
} }
@ -306,7 +326,7 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
pushHandler := remotes.PushHandler(cs, pusher) pushHandler := remotes.PushHandler(cs, pusher)
handlers := append(pushCtx.BaseHandlers, handlers := append(pushCtx.BaseHandlers,
images.ChildrenHandler(cs), images.ChildrenHandler(cs, platforms.Default()),
filterHandler, filterHandler,
pushHandler, pushHandler,
) )
@ -338,8 +358,8 @@ func (c *Client) GetImage(ctx context.Context, ref string) (Image, error) {
} }
// ListImages returns all existing images // ListImages returns all existing images
func (c *Client) ListImages(ctx context.Context) ([]Image, error) { func (c *Client) ListImages(ctx context.Context, filters ...string) ([]Image, error) {
imgs, err := c.ImageService().List(ctx) imgs, err := c.ImageService().List(ctx, filters...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -404,42 +424,57 @@ func (c *Client) Close() error {
return c.conn.Close() return c.conn.Close()
} }
func (c *Client) NamespaceService() namespacesapi.NamespacesClient { // NamespaceService returns the underlying Namespaces Store
return namespacesapi.NewNamespacesClient(c.conn) func (c *Client) NamespaceService() namespaces.Store {
return namespacesservice.NewStoreFromClient(namespacesapi.NewNamespacesClient(c.conn))
} }
// ContainerService returns the underlying container Store
func (c *Client) ContainerService() containers.Store { func (c *Client) ContainerService() containers.Store {
return NewRemoteContainerStore(containersapi.NewContainersClient(c.conn)) return NewRemoteContainerStore(containersapi.NewContainersClient(c.conn))
} }
// ContentStore returns the underlying content Store
func (c *Client) ContentStore() content.Store { func (c *Client) ContentStore() content.Store {
return contentservice.NewStoreFromClient(contentapi.NewContentClient(c.conn)) return contentservice.NewStoreFromClient(contentapi.NewContentClient(c.conn))
} }
// SnapshotService returns the underlying snapshotter for the provided snapshotter name
func (c *Client) SnapshotService(snapshotterName string) snapshot.Snapshotter { func (c *Client) SnapshotService(snapshotterName string) snapshot.Snapshotter {
return snapshotservice.NewSnapshotterFromClient(snapshotapi.NewSnapshotsClient(c.conn), snapshotterName) return snapshotservice.NewSnapshotterFromClient(snapshotapi.NewSnapshotsClient(c.conn), snapshotterName)
} }
// TaskService returns the underlying TasksClient
func (c *Client) TaskService() tasks.TasksClient { func (c *Client) TaskService() tasks.TasksClient {
return tasks.NewTasksClient(c.conn) return tasks.NewTasksClient(c.conn)
} }
// ImageService returns the underlying image Store
func (c *Client) ImageService() images.Store { func (c *Client) ImageService() images.Store {
return imagesservice.NewStoreFromClient(imagesapi.NewImagesClient(c.conn)) return imagesservice.NewStoreFromClient(imagesapi.NewImagesClient(c.conn))
} }
func (c *Client) DiffService() diff.DiffService { // DiffService returns the underlying Differ
func (c *Client) DiffService() diff.Differ {
return diffservice.NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn)) return diffservice.NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn))
} }
// IntrospectionService returns the underlying Introspection Client
func (c *Client) IntrospectionService() introspectionapi.IntrospectionClient {
return introspectionapi.NewIntrospectionClient(c.conn)
}
// HealthService returns the underlying GRPC HealthClient
func (c *Client) HealthService() grpc_health_v1.HealthClient { func (c *Client) HealthService() grpc_health_v1.HealthClient {
return grpc_health_v1.NewHealthClient(c.conn) return grpc_health_v1.NewHealthClient(c.conn)
} }
// EventService returns the underlying EventsClient
func (c *Client) EventService() eventsapi.EventsClient { func (c *Client) EventService() eventsapi.EventsClient {
return eventsapi.NewEventsClient(c.conn) return eventsapi.NewEventsClient(c.conn)
} }
// VersionService returns the underlying VersionClient
func (c *Client) VersionService() versionservice.VersionClient { func (c *Client) VersionService() versionservice.VersionClient {
return versionservice.NewVersionClient(c.conn) return versionservice.NewVersionClient(c.conn)
} }
@ -473,11 +508,38 @@ const (
type importOpts struct { type importOpts struct {
format imageFormat format imageFormat
refObject string refObject string
labels map[string]string
} }
// ImportOpt allows the caller to specify import specific options // ImportOpt allows the caller to specify import specific options
type ImportOpt func(c *importOpts) error type ImportOpt func(c *importOpts) error
// WithImportLabel sets a label to be associated with an imported image
func WithImportLabel(key, value string) ImportOpt {
return func(opts *importOpts) error {
if opts.labels == nil {
opts.labels = make(map[string]string)
}
opts.labels[key] = value
return nil
}
}
// WithImportLabels associates a set of labels to an imported image
func WithImportLabels(labels map[string]string) ImportOpt {
return func(opts *importOpts) error {
if opts.labels == nil {
opts.labels = make(map[string]string)
}
for k, v := range labels {
opts.labels[k] = v
}
return nil
}
}
// WithOCIImportFormat sets the import format for an OCI image format // WithOCIImportFormat sets the import format for an OCI image format
func WithOCIImportFormat() ImportOpt { func WithOCIImportFormat() ImportOpt {
return func(c *importOpts) error { return func(c *importOpts) error {
@ -529,6 +591,13 @@ func (c *Client) Import(ctx context.Context, ref string, reader io.Reader, opts
if err != nil { if err != nil {
return nil, err return nil, err
} }
ctx, done, err := c.withLease(ctx)
if err != nil {
return nil, err
}
defer done()
switch iopts.format { switch iopts.format {
case ociImageFormat: case ociImageFormat:
return c.importFromOCITar(ctx, ref, reader, iopts) return c.importFromOCITar(ctx, ref, reader, iopts)

View File

@ -33,25 +33,51 @@ func WithDialOpts(opts []grpc.DialOption) ClientOpt {
} }
} }
// RemoteOpts allows the caller to set distribution options for a remote // RemoteOpt allows the caller to set distribution options for a remote
type RemoteOpts func(*Client, *RemoteContext) error type RemoteOpt func(*Client, *RemoteContext) error
// WithPullUnpack is used to unpack an image after pull. This // WithPullUnpack is used to unpack an image after pull. This
// uses the snapshotter, content store, and diff service // uses the snapshotter, content store, and diff service
// configured for the client. // configured for the client.
func WithPullUnpack(client *Client, c *RemoteContext) error { func WithPullUnpack(_ *Client, c *RemoteContext) error {
c.Unpack = true c.Unpack = true
return nil return nil
} }
// WithPullSnapshotter specifies snapshotter name used for unpacking // WithPullSnapshotter specifies snapshotter name used for unpacking
func WithPullSnapshotter(snapshotterName string) RemoteOpts { func WithPullSnapshotter(snapshotterName string) RemoteOpt {
return func(client *Client, c *RemoteContext) error { return func(_ *Client, c *RemoteContext) error {
c.Snapshotter = snapshotterName c.Snapshotter = snapshotterName
return nil return nil
} }
} }
// WithPullLabel sets a label to be associated with a pulled reference
func WithPullLabel(key, value string) RemoteOpt {
return func(_ *Client, rc *RemoteContext) error {
if rc.Labels == nil {
rc.Labels = make(map[string]string)
}
rc.Labels[key] = value
return nil
}
}
// WithPullLabels associates a set of labels to a pulled reference
func WithPullLabels(labels map[string]string) RemoteOpt {
return func(_ *Client, rc *RemoteContext) error {
if rc.Labels == nil {
rc.Labels = make(map[string]string)
}
for k, v := range labels {
rc.Labels[k] = v
}
return nil
}
}
// WithSchema1Conversion is used to convert Docker registry schema 1 // WithSchema1Conversion is used to convert Docker registry schema 1
// manifests to oci manifests on pull. Without this option schema 1 // manifests to oci manifests on pull. Without this option schema 1
// manifests will return a not supported error. // manifests will return a not supported error.
@ -61,7 +87,7 @@ func WithSchema1Conversion(client *Client, c *RemoteContext) error {
} }
// WithResolver specifies the resolver to use. // WithResolver specifies the resolver to use.
func WithResolver(resolver remotes.Resolver) RemoteOpts { func WithResolver(resolver remotes.Resolver) RemoteOpt {
return func(client *Client, c *RemoteContext) error { return func(client *Client, c *RemoteContext) error {
c.Resolver = resolver c.Resolver = resolver
return nil return nil
@ -69,7 +95,7 @@ func WithResolver(resolver remotes.Resolver) RemoteOpts {
} }
// WithImageHandler adds a base handler to be called on dispatch. // WithImageHandler adds a base handler to be called on dispatch.
func WithImageHandler(h images.Handler) RemoteOpts { func WithImageHandler(h images.Handler) RemoteOpt {
return func(client *Client, c *RemoteContext) error { return func(client *Client, c *RemoteContext) error {
c.BaseHandlers = append(c.BaseHandlers, h) c.BaseHandlers = append(c.BaseHandlers, h)
return nil return nil

View File

@ -5,36 +5,36 @@ import (
"encoding/json" "encoding/json"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"github.com/containerd/containerd/api/services/tasks/v1" "github.com/containerd/containerd/api/services/tasks/v1"
"github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types"
"github.com/containerd/containerd/containers" "github.com/containerd/containerd/containers"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/typeurl" "github.com/containerd/typeurl"
prototypes "github.com/gogo/protobuf/types"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// DeleteOpts allows the caller to set options for the deletion of a container
type DeleteOpts func(context.Context, *Client, containers.Container) error
// Container is a metadata object for container resources and task creation // Container is a metadata object for container resources and task creation
type Container interface { type Container interface {
// ID identifies the container // ID identifies the container
ID() string ID() string
// Info returns the underlying container record type // Info returns the underlying container record type
Info() containers.Container Info(context.Context) (containers.Container, error)
// Delete removes the container // Delete removes the container
Delete(context.Context, ...DeleteOpts) error Delete(context.Context, ...DeleteOpts) error
// NewTask creates a new task based on the container metadata // NewTask creates a new task based on the container metadata
NewTask(context.Context, IOCreation, ...NewTaskOpts) (Task, error) NewTask(context.Context, IOCreation, ...NewTaskOpts) (Task, error)
// Spec returns the OCI runtime specification // Spec returns the OCI runtime specification
Spec() (*specs.Spec, error) Spec(context.Context) (*specs.Spec, error)
// Task returns the current task for the container // Task returns the current task for the container
// //
// If IOAttach options are passed the client will reattach to the IO for the running // If IOAttach options are passed the client will reattach to the IO for the running
// task. If no task exists for the container a NotFound error is returned // task. If no task exists for the container a NotFound error is returned
//
// Clients must make sure that only one reader is attached to the task and consuming
// the output from the task's fifos
Task(context.Context, IOAttach) (Task, error) Task(context.Context, IOAttach) (Task, error)
// Image returns the image that the container is based on // Image returns the image that the container is based on
Image(context.Context) (Image, error) Image(context.Context) (Image, error)
@ -42,52 +42,54 @@ type Container interface {
Labels(context.Context) (map[string]string, error) Labels(context.Context) (map[string]string, error)
// SetLabels sets the provided labels for the container and returns the final label set // SetLabels sets the provided labels for the container and returns the final label set
SetLabels(context.Context, map[string]string) (map[string]string, error) SetLabels(context.Context, map[string]string) (map[string]string, error)
// Extensions returns the extensions set on the container
Extensions(context.Context) (map[string]prototypes.Any, error)
// Update a container
Update(context.Context, ...UpdateContainerOpts) error
} }
func containerFromRecord(client *Client, c containers.Container) *container { func containerFromRecord(client *Client, c containers.Container) *container {
return &container{ return &container{
client: client, client: client,
c: c, id: c.ID,
} }
} }
var _ = (Container)(&container{}) var _ = (Container)(&container{})
type container struct { type container struct {
mu sync.Mutex
client *Client client *Client
c containers.Container id string
} }
// ID returns the container's unique id // ID returns the container's unique id
func (c *container) ID() string { func (c *container) ID() string {
return c.c.ID return c.id
} }
func (c *container) Info() containers.Container { func (c *container) Info(ctx context.Context) (containers.Container, error) {
return c.c return c.get(ctx)
} }
func (c *container) Labels(ctx context.Context) (map[string]string, error) { func (c *container) Extensions(ctx context.Context) (map[string]prototypes.Any, error) {
r, err := c.client.ContainerService().Get(ctx, c.ID()) r, err := c.get(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return r.Extensions, nil
}
c.c = r func (c *container) Labels(ctx context.Context) (map[string]string, error) {
r, err := c.get(ctx)
m := make(map[string]string, len(r.Labels)) if err != nil {
for k, v := range c.c.Labels { return nil, err
m[k] = v
} }
return r.Labels, nil
return m, nil
} }
func (c *container) SetLabels(ctx context.Context, labels map[string]string) (map[string]string, error) { func (c *container) SetLabels(ctx context.Context, labels map[string]string) (map[string]string, error) {
container := containers.Container{ container := containers.Container{
ID: c.ID(), ID: c.id,
Labels: labels, Labels: labels,
} }
@ -102,20 +104,17 @@ func (c *container) SetLabels(ctx context.Context, labels map[string]string) (ma
if err != nil { if err != nil {
return nil, err return nil, err
} }
return r.Labels, nil
c.c = r // update our local container
m := make(map[string]string, len(r.Labels))
for k, v := range c.c.Labels {
m[k] = v
}
return m, nil
} }
// Spec returns the current OCI specification for the container // Spec returns the current OCI specification for the container
func (c *container) Spec() (*specs.Spec, error) { func (c *container) Spec(ctx context.Context) (*specs.Spec, error) {
r, err := c.get(ctx)
if err != nil {
return nil, err
}
var s specs.Spec var s specs.Spec
if err := json.Unmarshal(c.c.Spec.Value, &s); err != nil { if err := json.Unmarshal(r.Spec.Value, &s); err != nil {
return nil, err return nil, err
} }
return &s, nil return &s, nil
@ -123,20 +122,20 @@ func (c *container) Spec() (*specs.Spec, error) {
// Delete deletes an existing container // Delete deletes an existing container
// an error is returned if the container has running tasks // an error is returned if the container has running tasks
func (c *container) Delete(ctx context.Context, opts ...DeleteOpts) (err error) { func (c *container) Delete(ctx context.Context, opts ...DeleteOpts) error {
if _, err := c.Task(ctx, nil); err == nil { if _, err := c.loadTask(ctx, nil); err == nil {
return errors.Wrapf(errdefs.ErrFailedPrecondition, "cannot delete running task %v", c.ID()) return errors.Wrapf(errdefs.ErrFailedPrecondition, "cannot delete running task %v", c.id)
}
r, err := c.get(ctx)
if err != nil {
return err
} }
for _, o := range opts { for _, o := range opts {
if err := o(ctx, c.client, c.c); err != nil { if err := o(ctx, c.client, r); err != nil {
return err return err
} }
} }
return c.client.ContainerService().Delete(ctx, c.id)
if cerr := c.client.ContainerService().Delete(ctx, c.ID()); err == nil {
err = cerr
}
return err
} }
func (c *container) Task(ctx context.Context, attach IOAttach) (Task, error) { func (c *container) Task(ctx context.Context, attach IOAttach) (Task, error) {
@ -145,12 +144,16 @@ func (c *container) Task(ctx context.Context, attach IOAttach) (Task, error) {
// Image returns the image that the container is based on // Image returns the image that the container is based on
func (c *container) Image(ctx context.Context) (Image, error) { func (c *container) Image(ctx context.Context) (Image, error) {
if c.c.Image == "" { r, err := c.get(ctx)
return nil, errors.Wrapf(errdefs.ErrNotFound, "container not created from an image")
}
i, err := c.client.ImageService().Get(ctx, c.c.Image)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "failed to get image for container") return nil, err
}
if r.Image == "" {
return nil, errors.Wrap(errdefs.ErrNotFound, "container not created from an image")
}
i, err := c.client.ImageService().Get(ctx, r.Image)
if err != nil {
return nil, errors.Wrapf(err, "failed to get image %s for container", r.Image)
} }
return &image{ return &image{
client: c.client, client: c.client,
@ -159,27 +162,29 @@ func (c *container) Image(ctx context.Context) (Image, error) {
} }
func (c *container) NewTask(ctx context.Context, ioCreate IOCreation, opts ...NewTaskOpts) (Task, error) { func (c *container) NewTask(ctx context.Context, ioCreate IOCreation, opts ...NewTaskOpts) (Task, error) {
c.mu.Lock() i, err := ioCreate(c.id)
defer c.mu.Unlock()
i, err := ioCreate(c.c.ID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
cfg := i.Config() cfg := i.Config()
request := &tasks.CreateTaskRequest{ request := &tasks.CreateTaskRequest{
ContainerID: c.c.ID, ContainerID: c.id,
Terminal: cfg.Terminal, Terminal: cfg.Terminal,
Stdin: cfg.Stdin, Stdin: cfg.Stdin,
Stdout: cfg.Stdout, Stdout: cfg.Stdout,
Stderr: cfg.Stderr, Stderr: cfg.Stderr,
} }
if c.c.SnapshotKey != "" { r, err := c.get(ctx)
if c.c.Snapshotter == "" { if err != nil {
return nil, err
}
if r.SnapshotKey != "" {
if r.Snapshotter == "" {
return nil, errors.Wrapf(errdefs.ErrInvalidArgument, "unable to resolve rootfs mounts without snapshotter on container") return nil, errors.Wrapf(errdefs.ErrInvalidArgument, "unable to resolve rootfs mounts without snapshotter on container")
} }
// get the rootfs from the snapshotter and add it to the request // get the rootfs from the snapshotter and add it to the request
mounts, err := c.client.SnapshotService(c.c.Snapshotter).Mounts(ctx, c.c.SnapshotKey) mounts, err := c.client.SnapshotService(r.Snapshotter).Mounts(ctx, r.SnapshotKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -216,25 +221,39 @@ func (c *container) NewTask(ctx context.Context, ioCreate IOCreation, opts ...Ne
t := &task{ t := &task{
client: c.client, client: c.client,
io: i, io: i,
id: c.ID(), id: c.id,
} }
if info.Checkpoint != nil { if info.Checkpoint != nil {
request.Checkpoint = info.Checkpoint request.Checkpoint = info.Checkpoint
// we need to defer the create call to start
t.deferred = request
} else {
response, err := c.client.TaskService().Create(ctx, request)
if err != nil {
return nil, errdefs.FromGRPC(err)
}
t.pid = response.Pid
} }
response, err := c.client.TaskService().Create(ctx, request)
if err != nil {
return nil, errdefs.FromGRPC(err)
}
t.pid = response.Pid
return t, nil return t, nil
} }
func (c *container) Update(ctx context.Context, opts ...UpdateContainerOpts) error {
// fetch the current container config before updating it
r, err := c.get(ctx)
if err != nil {
return err
}
for _, o := range opts {
if err := o(ctx, c.client, &r); err != nil {
return err
}
}
if _, err := c.client.ContainerService().Update(ctx, r); err != nil {
return errdefs.FromGRPC(err)
}
return nil
}
func (c *container) loadTask(ctx context.Context, ioAttach IOAttach) (Task, error) { func (c *container) loadTask(ctx context.Context, ioAttach IOAttach) (Task, error) {
response, err := c.client.TaskService().Get(ctx, &tasks.GetRequest{ response, err := c.client.TaskService().Get(ctx, &tasks.GetRequest{
ContainerID: c.c.ID, ContainerID: c.id,
}) })
if err != nil { if err != nil {
err = errdefs.FromGRPC(err) err = errdefs.FromGRPC(err)
@ -258,6 +277,10 @@ func (c *container) loadTask(ctx context.Context, ioAttach IOAttach) (Task, erro
return t, nil return t, nil
} }
func (c *container) get(ctx context.Context) (containers.Container, error) {
return c.client.ContainerService().Get(ctx, c.id)
}
func attachExistingIO(response *tasks.GetResponse, ioAttach IOAttach) (IO, error) { func attachExistingIO(response *tasks.GetResponse, ioAttach IOAttach) (IO, error) {
// get the existing fifo paths from the task information stored by the daemon // get the existing fifo paths from the task information stored by the daemon
paths := &FIFOSet{ paths := &FIFOSet{

View File

@ -6,15 +6,21 @@ import (
"github.com/containerd/containerd/containers" "github.com/containerd/containerd/containers"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/typeurl" "github.com/containerd/typeurl"
"github.com/gogo/protobuf/types" "github.com/gogo/protobuf/types"
"github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/identity"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// DeleteOpts allows the caller to set options for the deletion of a container
type DeleteOpts func(ctx context.Context, client *Client, c containers.Container) error
// NewContainerOpts allows the caller to set additional options when creating a container // NewContainerOpts allows the caller to set additional options when creating a container
type NewContainerOpts func(ctx context.Context, client *Client, c *containers.Container) error type NewContainerOpts func(ctx context.Context, client *Client, c *containers.Container) error
// UpdateContainerOpts allows the caller to set additional options when updating a container
type UpdateContainerOpts func(ctx context.Context, client *Client, c *containers.Container) error
// WithRuntime allows a user to specify the runtime name and additional options that should // WithRuntime allows a user to specify the runtime name and additional options that should
// be used to create tasks for the container // be used to create tasks for the container
func WithRuntime(name string, options interface{}) NewContainerOpts { func WithRuntime(name string, options interface{}) NewContainerOpts {
@ -80,12 +86,13 @@ func WithSnapshot(id string) NewContainerOpts {
// root filesystem in read-write mode // root filesystem in read-write mode
func WithNewSnapshot(id string, i Image) NewContainerOpts { func WithNewSnapshot(id string, i Image) NewContainerOpts {
return func(ctx context.Context, client *Client, c *containers.Container) error { return func(ctx context.Context, client *Client, c *containers.Container) error {
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Format(platforms.Default())) diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
if err != nil { if err != nil {
return err return err
} }
setSnapshotterIfEmpty(c) setSnapshotterIfEmpty(c)
if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, identity.ChainID(diffIDs).String()); err != nil { parent := identity.ChainID(diffIDs).String()
if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent); err != nil {
return err return err
} }
c.SnapshotKey = id c.SnapshotKey = id
@ -109,12 +116,13 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta
// root filesystem in read-only mode // root filesystem in read-only mode
func WithNewSnapshotView(id string, i Image) NewContainerOpts { func WithNewSnapshotView(id string, i Image) NewContainerOpts {
return func(ctx context.Context, client *Client, c *containers.Container) error { return func(ctx context.Context, client *Client, c *containers.Container) error {
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Format(platforms.Default())) diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
if err != nil { if err != nil {
return err return err
} }
setSnapshotterIfEmpty(c) setSnapshotterIfEmpty(c)
if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, identity.ChainID(diffIDs).String()); err != nil { parent := identity.ChainID(diffIDs).String()
if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent); err != nil {
return err return err
} }
c.SnapshotKey = id c.SnapshotKey = id
@ -128,3 +136,31 @@ func setSnapshotterIfEmpty(c *containers.Container) {
c.Snapshotter = DefaultSnapshotter c.Snapshotter = DefaultSnapshotter
} }
} }
// WithContainerExtension appends extension data to the container object.
// Use this to decorate the container object with additional data for the client
// integration.
//
// Make sure to register the type of `extension` in the typeurl package via
// `typeurl.Register` or container creation may fail.
func WithContainerExtension(name string, extension interface{}) NewContainerOpts {
return func(ctx context.Context, client *Client, c *containers.Container) error {
if name == "" {
return errors.Wrapf(errdefs.ErrInvalidArgument, "extension key must not be zero-length")
}
any, err := typeurl.MarshalAny(extension)
if err != nil {
if errors.Cause(err) == typeurl.ErrNotFound {
return errors.Wrapf(err, "extension %q is not registered with the typeurl package, see `typeurl.Register`", name)
}
return errors.Wrap(err, "error marshalling extension")
}
if c.Extensions == nil {
c.Extensions = make(map[string]types.Any)
}
c.Extensions[name] = *any
return nil
}
}

View File

@ -18,16 +18,20 @@ import (
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/identity"
"github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
) )
// WithCheckpoint allows a container to be created from the checkpointed information // WithCheckpoint allows a container to be created from the checkpointed information
// provided by the descriptor. The image, snapshot, and runtime specifications are // provided by the descriptor. The image, snapshot, and runtime specifications are
// restored on the container // restored on the container
func WithCheckpoint(desc v1.Descriptor, snapshotKey string) NewContainerOpts { func WithCheckpoint(im Image, snapshotKey string) NewContainerOpts {
// set image and rw, and spec // set image and rw, and spec
return func(ctx context.Context, client *Client, c *containers.Container) error { return func(ctx context.Context, client *Client, c *containers.Container) error {
id := desc.Digest var (
store := client.ContentStore() desc = im.Target()
id = desc.Digest
store = client.ContentStore()
)
index, err := decodeIndex(ctx, store, id) index, err := decodeIndex(ctx, store, id)
if err != nil { if err != nil {
return err return err
@ -38,14 +42,14 @@ func WithCheckpoint(desc v1.Descriptor, snapshotKey string) NewContainerOpts {
case v1.MediaTypeImageLayer: case v1.MediaTypeImageLayer:
fk := m fk := m
rw = &fk rw = &fk
case images.MediaTypeDockerSchema2Manifest: case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList:
config, err := images.Config(ctx, store, m, platforms.Format(platforms.Default())) config, err := images.Config(ctx, store, m, platforms.Default())
if err != nil { if err != nil {
return err return errors.Wrap(err, "unable to resolve image config")
} }
diffIDs, err := images.RootFS(ctx, store, config) diffIDs, err := images.RootFS(ctx, store, config)
if err != nil { if err != nil {
return err return errors.Wrap(err, "unable to get rootfs")
} }
setSnapshotterIfEmpty(c) setSnapshotterIfEmpty(c)
if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, snapshotKey, identity.ChainID(diffIDs).String()); err != nil { if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, snapshotKey, identity.ChainID(diffIDs).String()); err != nil {
@ -57,7 +61,7 @@ func WithCheckpoint(desc v1.Descriptor, snapshotKey string) NewContainerOpts {
case images.MediaTypeContainerd1CheckpointConfig: case images.MediaTypeContainerd1CheckpointConfig:
data, err := content.ReadBlob(ctx, store, m.Digest) data, err := content.ReadBlob(ctx, store, m.Digest)
if err != nil { if err != nil {
return err return errors.Wrap(err, "unable to read checkpoint config")
} }
var any protobuf.Any var any protobuf.Any
if err := proto.Unmarshal(data, &any); err != nil { if err := proto.Unmarshal(data, &any); err != nil {
@ -70,10 +74,10 @@ func WithCheckpoint(desc v1.Descriptor, snapshotKey string) NewContainerOpts {
// apply the rw snapshot to the new rw layer // apply the rw snapshot to the new rw layer
mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, snapshotKey) mounts, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, snapshotKey)
if err != nil { if err != nil {
return err return errors.Wrapf(err, "unable to get mounts for %s", snapshotKey)
} }
if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil { if _, err := client.DiffService().Apply(ctx, *rw, mounts); err != nil {
return err return errors.Wrap(err, "unable to apply rw diff")
} }
} }
c.SnapshotKey = snapshotKey c.SnapshotKey = snapshotKey
@ -84,8 +88,9 @@ func WithCheckpoint(desc v1.Descriptor, snapshotKey string) NewContainerOpts {
// WithTaskCheckpoint allows a task to be created with live runtime and memory data from a // 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 // previous checkpoint. Additional software such as CRIU may be required to
// restore a task from a checkpoint // restore a task from a checkpoint
func WithTaskCheckpoint(desc v1.Descriptor) NewTaskOpts { func WithTaskCheckpoint(im Image) NewTaskOpts {
return func(ctx context.Context, c *Client, info *TaskInfo) error { return func(ctx context.Context, c *Client, info *TaskInfo) error {
desc := im.Target()
id := desc.Digest id := desc.Digest
index, err := decodeIndex(ctx, c.ContentStore(), id) index, err := decodeIndex(ctx, c.ContentStore(), id)
if err != nil { if err != nil {

View File

@ -57,13 +57,18 @@ type Container struct {
// UpdatedAt is the time at which the container was updated. // UpdatedAt is the time at which the container was updated.
UpdatedAt time.Time UpdatedAt time.Time
// Extensions stores client-specified metadata
Extensions map[string]types.Any
} }
// RuntimeInfo holds runtime specific information
type RuntimeInfo struct { type RuntimeInfo struct {
Name string Name string
Options *types.Any Options *types.Any
} }
// Store interacts with the underlying container storage
type Store interface { type Store interface {
Get(ctx context.Context, id string) (Container, error) Get(ctx context.Context, id string) (Container, error)

View File

@ -15,6 +15,7 @@ type remoteContainers struct {
var _ containers.Store = &remoteContainers{} var _ containers.Store = &remoteContainers{}
// NewRemoteContainerStore returns the container Store connected with the provided client
func NewRemoteContainerStore(client containersapi.ContainersClient) containers.Store { func NewRemoteContainerStore(client containersapi.ContainersClient) containers.Store {
return &remoteContainers{ return &remoteContainers{
client: client, client: client,
@ -97,6 +98,7 @@ func containerToProto(container *containers.Container) containersapi.Container {
Spec: container.Spec, Spec: container.Spec,
Snapshotter: container.Snapshotter, Snapshotter: container.Snapshotter,
SnapshotKey: container.SnapshotKey, SnapshotKey: container.SnapshotKey,
Extensions: container.Extensions,
} }
} }
@ -116,6 +118,9 @@ func containerFromProto(containerpb *containersapi.Container) containers.Contain
Spec: containerpb.Spec, Spec: containerpb.Spec,
Snapshotter: containerpb.Snapshotter, Snapshotter: containerpb.Snapshotter,
SnapshotKey: containerpb.SnapshotKey, SnapshotKey: containerpb.SnapshotKey,
CreatedAt: containerpb.CreatedAt,
UpdatedAt: containerpb.UpdatedAt,
Extensions: containerpb.Extensions,
} }
} }

View File

@ -8,20 +8,25 @@ import (
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
// ReaderAt extends the standard io.ReaderAt interface with reporting of Size and io.Closer
type ReaderAt interface { type ReaderAt interface {
io.ReaderAt io.ReaderAt
io.Closer io.Closer
Size() int64 Size() int64
} }
// Provider provides a reader interface for specific content
type Provider interface { type Provider interface {
ReaderAt(ctx context.Context, dgst digest.Digest) (ReaderAt, error) ReaderAt(ctx context.Context, dgst digest.Digest) (ReaderAt, error)
} }
// Ingester writes content
type Ingester interface { type Ingester interface {
Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (Writer, error) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (Writer, error)
} }
// Info holds content specific information
//
// TODO(stevvooe): Consider a very different name for this struct. Info is way // TODO(stevvooe): Consider a very different name for this struct. Info is way
// to general. It also reads very weird in certain context, like pluralization. // to general. It also reads very weird in certain context, like pluralization.
type Info struct { type Info struct {
@ -32,6 +37,7 @@ type Info struct {
Labels map[string]string Labels map[string]string
} }
// Status of a content operation
type Status struct { type Status struct {
Ref string Ref string
Offset int64 Offset int64
@ -81,8 +87,10 @@ type IngestManager interface {
Abort(ctx context.Context, ref string) error Abort(ctx context.Context, ref string) error
} }
// Writer handles the write of content into a content store
type Writer interface { type Writer interface {
// Close is expected to be called after Commit() when commission is needed. // Close is expected to be called after Commit() when commission is needed.
// Closing a writer without commit allows resuming or aborting.
io.WriteCloser io.WriteCloser
// Digest may return empty digest or panics until committed. // Digest may return empty digest or panics until committed.
@ -111,6 +119,7 @@ type Store interface {
// Opt is used to alter the mutable properties of content // Opt is used to alter the mutable properties of content
type Opt func(*Info) error type Opt func(*Info) error
// WithLabels allows labels to be set on content
func WithLabels(labels map[string]string) Opt { func WithLabels(labels map[string]string) Opt {
return func(info *Info) error { return func(info *Info) error {
info.Labels = labels info.Labels = labels

View File

@ -19,6 +19,7 @@ var (
} }
) )
// NewReader returns a io.Reader from a ReaderAt
func NewReader(ra ReaderAt) io.Reader { func NewReader(ra ReaderAt) io.Reader {
rd := io.NewSectionReader(ra, 0, ra.Size()) rd := io.NewSectionReader(ra, 0, ra.Size())
return rd return rd
@ -47,7 +48,7 @@ func ReadBlob(ctx context.Context, provider Provider, dgst digest.Digest) ([]byt
// This is useful when the digest and size are known beforehand. // This is useful when the digest and size are known beforehand.
// //
// Copy is buffered, so no need to wrap reader in buffered io. // Copy is buffered, so no need to wrap reader in buffered io.
func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size int64, expected digest.Digest) error { func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error {
cw, err := cs.Writer(ctx, ref, size, expected) cw, err := cs.Writer(ctx, ref, size, expected)
if err != nil { if err != nil {
if !errdefs.IsAlreadyExists(err) { if !errdefs.IsAlreadyExists(err) {
@ -58,7 +59,7 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size i
} }
defer cw.Close() defer cw.Close()
return Copy(ctx, cw, r, size, expected) return Copy(ctx, cw, r, size, expected, opts...)
} }
// Copy copies data with the expected digest from the reader into the // Copy copies data with the expected digest from the reader into the
@ -68,7 +69,7 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size i
// the size or digest is unknown, these values may be empty. // the size or digest is unknown, these values may be empty.
// //
// Copy is buffered, so no need to wrap reader in buffered io. // Copy is buffered, so no need to wrap reader in buffered io.
func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected digest.Digest) error { func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error {
ws, err := cw.Status() ws, err := cw.Status()
if err != nil { if err != nil {
return err return err
@ -95,7 +96,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
return err return err
} }
if err := cw.Commit(ctx, size, expected); err != nil { if err := cw.Commit(ctx, size, expected, opts...); err != nil {
if !errdefs.IsAlreadyExists(err) { if !errdefs.IsAlreadyExists(err) {
return errors.Wrapf(err, "failed commit on ref %q", ws.Ref) return errors.Wrapf(err, "failed commit on ref %q", ws.Ref)
} }

View File

@ -8,6 +8,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings"
"sync" "sync"
"time" "time"
@ -27,6 +28,19 @@ var (
} }
) )
// LabelStore is used to store mutable labels for digests
type LabelStore interface {
// Get returns all the labels for the given digest
Get(digest.Digest) (map[string]string, error)
// Set sets all the labels for a given digest
Set(digest.Digest, map[string]string) error
// Update replaces the given labels for a digest,
// a key with an empty value removes a label.
Update(digest.Digest, map[string]string) (map[string]string, error)
}
// Store is digest-keyed store for content. All data written into the store is // Store is digest-keyed store for content. All data written into the store is
// stored under a verifiable digest. // stored under a verifiable digest.
// //
@ -34,15 +48,27 @@ var (
// including resumable ingest. // including resumable ingest.
type store struct { type store struct {
root string root string
ls LabelStore
} }
// NewStore returns a local content store
func NewStore(root string) (content.Store, error) { func NewStore(root string) (content.Store, error) {
return NewLabeledStore(root, nil)
}
// NewLabeledStore returns a new content store using the provided label store
//
// Note: content stores which are used underneath a metadata store may not
// require labels and should use `NewStore`. `NewLabeledStore` is primarily
// useful for tests or standalone implementations.
func NewLabeledStore(root string, ls LabelStore) (content.Store, error) {
if err := os.MkdirAll(filepath.Join(root, "ingest"), 0777); err != nil && !os.IsExist(err) { if err := os.MkdirAll(filepath.Join(root, "ingest"), 0777); err != nil && !os.IsExist(err) {
return nil, err return nil, err
} }
return &store{ return &store{
root: root, root: root,
ls: ls,
}, nil }, nil
} }
@ -56,16 +82,23 @@ func (s *store) Info(ctx context.Context, dgst digest.Digest) (content.Info, err
return content.Info{}, err return content.Info{}, err
} }
var labels map[string]string
return s.info(dgst, fi), nil if s.ls != nil {
labels, err = s.ls.Get(dgst)
if err != nil {
return content.Info{}, err
}
}
return s.info(dgst, fi, labels), nil
} }
func (s *store) info(dgst digest.Digest, fi os.FileInfo) content.Info { func (s *store) info(dgst digest.Digest, fi os.FileInfo, labels map[string]string) content.Info {
return content.Info{ return content.Info{
Digest: dgst, Digest: dgst,
Size: fi.Size(), Size: fi.Size(),
CreatedAt: fi.ModTime(), CreatedAt: fi.ModTime(),
UpdatedAt: fi.ModTime(), UpdatedAt: getATime(fi),
Labels: labels,
} }
} }
@ -97,8 +130,8 @@ func (s *store) ReaderAt(ctx context.Context, dgst digest.Digest) (content.Reade
// //
// While this is safe to do concurrently, safe exist-removal logic must hold // While this is safe to do concurrently, safe exist-removal logic must hold
// some global lock on the store. // some global lock on the store.
func (cs *store) Delete(ctx context.Context, dgst digest.Digest) error { func (s *store) Delete(ctx context.Context, dgst digest.Digest) error {
if err := os.RemoveAll(cs.blobPath(dgst)); err != nil { if err := os.RemoveAll(s.blobPath(dgst)); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return err
} }
@ -109,14 +142,72 @@ func (cs *store) Delete(ctx context.Context, dgst digest.Digest) error {
return nil return nil
} }
func (cs *store) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) { func (s *store) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
// TODO: Support persisting and updating mutable content data if s.ls == nil {
return content.Info{}, errors.Wrapf(errdefs.ErrFailedPrecondition, "update not supported on immutable content store") return content.Info{}, errors.Wrapf(errdefs.ErrFailedPrecondition, "update not supported on immutable content store")
}
p := s.blobPath(info.Digest)
fi, err := os.Stat(p)
if err != nil {
if os.IsNotExist(err) {
err = errors.Wrapf(errdefs.ErrNotFound, "content %v", info.Digest)
}
return content.Info{}, err
}
var (
all bool
labels map[string]string
)
if len(fieldpaths) > 0 {
for _, path := range fieldpaths {
if strings.HasPrefix(path, "labels.") {
if labels == nil {
labels = map[string]string{}
}
key := strings.TrimPrefix(path, "labels.")
labels[key] = info.Labels[key]
continue
}
switch path {
case "labels":
all = true
labels = info.Labels
default:
return content.Info{}, errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on content info %q", path, info.Digest)
}
}
} else {
all = true
labels = info.Labels
}
if all {
err = s.ls.Set(info.Digest, labels)
} else {
labels, err = s.ls.Update(info.Digest, labels)
}
if err != nil {
return content.Info{}, err
}
info = s.info(info.Digest, fi, labels)
info.UpdatedAt = time.Now()
if err := os.Chtimes(p, info.UpdatedAt, info.CreatedAt); err != nil {
log.G(ctx).WithError(err).Warnf("could not change access time for %s", info.Digest)
}
return info, nil
} }
func (cs *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error { func (s *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error {
// TODO: Support filters // TODO: Support filters
root := filepath.Join(cs.root, "blobs") root := filepath.Join(s.root, "blobs")
var alg digest.Algorithm var alg digest.Algorithm
return filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { return filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if err != nil { if err != nil {
@ -153,7 +244,14 @@ func (cs *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...strin
// store or extra paths not expected previously. // store or extra paths not expected previously.
} }
return fn(cs.info(dgst, fi)) var labels map[string]string
if s.ls != nil {
labels, err = s.ls.Get(dgst)
if err != nil {
return err
}
}
return fn(s.info(dgst, fi, labels))
}) })
} }
@ -382,8 +480,8 @@ func (s *store) Abort(ctx context.Context, ref string) error {
return nil return nil
} }
func (cs *store) blobPath(dgst digest.Digest) string { func (s *store) blobPath(dgst digest.Digest) string {
return filepath.Join(cs.root, "blobs", dgst.Algorithm().String(), dgst.Hex()) return filepath.Join(s.root, "blobs", dgst.Algorithm().String(), dgst.Hex())
} }
func (s *store) ingestRoot(ref string) string { func (s *store) ingestRoot(ref string) string {

View File

@ -18,3 +18,12 @@ func getStartTime(fi os.FileInfo) time.Time {
return fi.ModTime() return fi.ModTime()
} }
func getATime(fi os.FileInfo) time.Time {
if st, ok := fi.Sys().(*syscall.Stat_t); ok {
return time.Unix(int64(sys.StatAtime(st).Sec),
int64(sys.StatAtime(st).Nsec))
}
return fi.ModTime()
}

View File

@ -8,3 +8,7 @@ import (
func getStartTime(fi os.FileInfo) time.Time { func getStartTime(fi os.FileInfo) time.Time {
return fi.ModTime() return fi.ModTime()
} }
func getATime(fi os.FileInfo) time.Time {
return fi.ModTime()
}

View File

@ -56,6 +56,13 @@ func (w *writer) Write(p []byte) (n int, err error) {
} }
func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error { func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
var base content.Info
for _, opt := range opts {
if err := opt(&base); err != nil {
return err
}
}
if w.fp == nil { if w.fp == nil {
return errors.Wrap(errdefs.ErrFailedPrecondition, "cannot commit on closed writer") return errors.Wrap(errdefs.ErrFailedPrecondition, "cannot commit on closed writer")
} }
@ -123,6 +130,12 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest,
w.fp = nil w.fp = nil
unlock(w.ref) unlock(w.ref)
if w.s.ls != nil && base.Labels != nil {
if err := w.s.ls.Set(dgst, base.Labels); err != nil {
return err
}
}
return nil return nil
} }
@ -130,10 +143,10 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest,
// tact. // tact.
// //
// If one needs to resume the transaction, a new writer can be obtained from // If one needs to resume the transaction, a new writer can be obtained from
// `ContentStore.Resume` using the same key. The write can then be continued // `Ingester.Writer` using the same key. The write can then be continued
// from it was left off. // from it was left off.
// //
// To abandon a transaction completely, first call close then `Store.Remove` to // To abandon a transaction completely, first call close then `IngestManager.Abort` to
// clean up the associated resources. // clean up the associated resources.
func (w *writer) Close() (err error) { func (w *writer) Close() (err error) {
if w.fp != nil { if w.fp != nil {

View File

@ -1,8 +1,7 @@
package containerd package dialer
import ( import (
"net" "net"
"strings"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -13,12 +12,12 @@ type dialResult struct {
err error err error
} }
// Dialer returns a GRPC net.Conn connected to the provided address
func Dialer(address string, timeout time.Duration) (net.Conn, error) { func Dialer(address string, timeout time.Duration) (net.Conn, error) {
var ( var (
stopC = make(chan struct{}) stopC = make(chan struct{})
synC = make(chan *dialResult) synC = make(chan *dialResult)
) )
address = strings.TrimPrefix(address, "unix://")
go func() { go func() {
defer close(synC) defer close(synC)
for { for {
@ -47,6 +46,6 @@ func Dialer(address string, timeout time.Duration) (net.Conn, error) {
dr.c.Close() dr.c.Close()
} }
}() }()
return nil, errors.Errorf("dial %s: no such file or directory", address) return nil, errors.Errorf("dial %s: timeout", address)
} }
} }

View File

@ -1,15 +1,22 @@
// +build !windows // +build !windows
package containerd package dialer
import ( import (
"fmt" "fmt"
"net" "net"
"os" "os"
"strings"
"syscall" "syscall"
"time" "time"
) )
// DialAddress returns the address with unix:// prepended to the
// provided address
func DialAddress(address string) string {
return fmt.Sprintf("unix://%s", address)
}
func isNoent(err error) bool { func isNoent(err error) bool {
if err != nil { if err != nil {
if nerr, ok := err.(*net.OpError); ok { if nerr, ok := err.(*net.OpError); ok {
@ -24,9 +31,6 @@ func isNoent(err error) bool {
} }
func dialer(address string, timeout time.Duration) (net.Conn, error) { func dialer(address string, timeout time.Duration) (net.Conn, error) {
address = strings.TrimPrefix(address, "unix://")
return net.DialTimeout("unix", address, timeout) return net.DialTimeout("unix", address, timeout)
} }
func DialAddress(address string) string {
return fmt.Sprintf("unix://%s", address)
}

View File

@ -1,4 +1,4 @@
package containerd package dialer
import ( import (
"net" "net"
@ -24,6 +24,7 @@ func dialer(address string, timeout time.Duration) (net.Conn, error) {
return winio.DialPipe(address, &timeout) return winio.DialPipe(address, &timeout)
} }
// DialAddress returns the dial address
func DialAddress(address string) string { func DialAddress(address string) string {
return address return address
} }

69
vendor/github.com/containerd/containerd/diff/diff.go generated vendored Normal file
View File

@ -0,0 +1,69 @@
package diff
import (
"github.com/containerd/containerd/mount"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/net/context"
)
// Config is used to hold parameters needed for a diff operation
type Config struct {
// MediaType is the type of diff to generate
// Default depends on the differ,
// i.e. application/vnd.oci.image.layer.v1.tar+gzip
MediaType string
// Reference is the content upload reference
// Default will use a random reference string
Reference string
// Labels are the labels to apply to the generated content
Labels map[string]string
}
// Opt is used to configure a diff operation
type Opt func(*Config) error
// Differ allows the apply and creation of filesystem diffs between mounts
type Differ interface {
// Apply applies the content referred to by the given descriptor to
// the provided mount. The method of applying is based on the
// implementation and content descriptor. For example, in the common
// case the descriptor is a file system difference in tar format,
// that tar would be applied on top of the mounts.
Apply(ctx context.Context, desc ocispec.Descriptor, mount []mount.Mount) (ocispec.Descriptor, error)
// DiffMounts computes the difference between two mounts and returns a
// descriptor for the computed diff. The options can provide
// a ref which can be used to track the content creation of the diff.
// The media type which is used to determine the format of the created
// content can also be provided as an option.
DiffMounts(ctx context.Context, lower, upper []mount.Mount, opts ...Opt) (ocispec.Descriptor, error)
}
// WithMediaType sets the media type to use for creating the diff, without
// specifying the differ will choose a default.
func WithMediaType(m string) Opt {
return func(c *Config) error {
c.MediaType = m
return nil
}
}
// WithReference is used to set the content upload reference used by
// the diff operation. This allows the caller to track the upload through
// the content store.
func WithReference(ref string) Opt {
return func(c *Config) error {
c.Reference = ref
return nil
}
}
// WithLabels is used to set content labels on the created diff content.
func WithLabels(labels map[string]string) Opt {
return func(c *Config) error {
c.Labels = labels
return nil
}
}

View File

@ -1,23 +1,30 @@
package differ package walking
import ( import (
"crypto/rand"
"encoding/base64"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"strings" "strings"
"time"
"github.com/boltdb/bolt"
"github.com/containerd/containerd/archive" "github.com/containerd/containerd/archive"
"github.com/containerd/containerd/archive/compression" "github.com/containerd/containerd/archive/compression"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/diff"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -25,20 +32,17 @@ func init() {
plugin.Register(&plugin.Registration{ plugin.Register(&plugin.Registration{
Type: plugin.DiffPlugin, Type: plugin.DiffPlugin,
ID: "walking", ID: "walking",
Requires: []plugin.PluginType{ Requires: []plugin.Type{
plugin.ContentPlugin,
plugin.MetadataPlugin, plugin.MetadataPlugin,
}, },
Init: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
c, err := ic.Get(plugin.ContentPlugin)
if err != nil {
return nil, err
}
md, err := ic.Get(plugin.MetadataPlugin) md, err := ic.Get(plugin.MetadataPlugin)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewWalkingDiff(metadata.NewContentStore(md.(*bolt.DB), c.(content.Store)))
ic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec())
return NewWalkingDiff(md.(*metadata.DB).ContentStore())
}, },
}) })
} }
@ -49,9 +53,9 @@ type walkingDiff struct {
var emptyDesc = ocispec.Descriptor{} var emptyDesc = ocispec.Descriptor{}
// NewWalkingDiff is a generic implementation of plugin.Differ. // NewWalkingDiff is a generic implementation of diff.Differ.
// NewWalkingDiff is expected to work with any filesystem. // NewWalkingDiff is expected to work with any filesystem.
func NewWalkingDiff(store content.Store) (plugin.Differ, error) { func NewWalkingDiff(store content.Store) (diff.Differ, error) {
return &walkingDiff{ return &walkingDiff{
store: store, store: store,
}, nil }, nil
@ -60,7 +64,18 @@ func NewWalkingDiff(store content.Store) (plugin.Differ, error) {
// Apply applies the content associated with the provided digests onto the // Apply applies the content associated with the provided digests onto the
// provided mounts. Archive content will be extracted and decompressed if // provided mounts. Archive content will be extracted and decompressed if
// necessary. // necessary.
func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount) (ocispec.Descriptor, error) { func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount) (d ocispec.Descriptor, err error) {
t1 := time.Now()
defer func() {
if err == nil {
log.G(ctx).WithFields(logrus.Fields{
"d": time.Now().Sub(t1),
"dgst": desc.Digest,
"size": desc.Size,
"media": desc.MediaType,
}).Debugf("diff applied")
}
}()
var isCompressed bool var isCompressed bool
switch desc.MediaType { switch desc.MediaType {
case ocispec.MediaTypeImageLayer, images.MediaTypeDockerSchema2Layer: case ocispec.MediaTypeImageLayer, images.MediaTypeDockerSchema2Layer:
@ -81,7 +96,7 @@ func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts
} }
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
if err := mount.MountAll(mounts, dir); err != nil { if err := mount.All(mounts, dir); err != nil {
return emptyDesc, errors.Wrap(err, "failed to mount") return emptyDesc, errors.Wrap(err, "failed to mount")
} }
defer mount.Unmount(dir, 0) defer mount.Unmount(dir, 0)
@ -125,17 +140,25 @@ func (s *walkingDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts
// DiffMounts creates a diff between the given mounts and uploads the result // DiffMounts creates a diff between the given mounts and uploads the result
// to the content store. // to the content store.
func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, media, ref string) (ocispec.Descriptor, error) { func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, opts ...diff.Opt) (d ocispec.Descriptor, err error) {
var config diff.Config
for _, opt := range opts {
if err := opt(&config); err != nil {
return emptyDesc, err
}
}
if config.MediaType == "" {
config.MediaType = ocispec.MediaTypeImageLayerGzip
}
var isCompressed bool var isCompressed bool
switch media { switch config.MediaType {
case ocispec.MediaTypeImageLayer: case ocispec.MediaTypeImageLayer:
case ocispec.MediaTypeImageLayerGzip: case ocispec.MediaTypeImageLayerGzip:
isCompressed = true isCompressed = true
case "":
media = ocispec.MediaTypeImageLayerGzip
isCompressed = true
default: default:
return emptyDesc, errors.Wrapf(errdefs.ErrNotImplemented, "unsupported diff media type: %v", media) return emptyDesc, errors.Wrapf(errdefs.ErrNotImplemented, "unsupported diff media type: %v", config.MediaType)
} }
aDir, err := ioutil.TempDir("", "left-") aDir, err := ioutil.TempDir("", "left-")
if err != nil { if err != nil {
@ -149,22 +172,42 @@ func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount
} }
defer os.RemoveAll(bDir) defer os.RemoveAll(bDir)
if err := mount.MountAll(lower, aDir); err != nil { if err := mount.All(lower, aDir); err != nil {
return emptyDesc, errors.Wrap(err, "failed to mount") return emptyDesc, errors.Wrap(err, "failed to mount")
} }
defer mount.Unmount(aDir, 0) defer mount.Unmount(aDir, 0)
if err := mount.MountAll(upper, bDir); err != nil { if err := mount.All(upper, bDir); err != nil {
return emptyDesc, errors.Wrap(err, "failed to mount") return emptyDesc, errors.Wrap(err, "failed to mount")
} }
defer mount.Unmount(bDir, 0) defer mount.Unmount(bDir, 0)
cw, err := s.store.Writer(ctx, ref, 0, "") var newReference bool
if config.Reference == "" {
newReference = true
config.Reference = uniqueRef()
}
cw, err := s.store.Writer(ctx, config.Reference, 0, "")
if err != nil { if err != nil {
return emptyDesc, errors.Wrap(err, "failed to open writer") return emptyDesc, errors.Wrap(err, "failed to open writer")
} }
defer func() {
if err != nil {
cw.Close()
if newReference {
if err := s.store.Abort(ctx, config.Reference); err != nil {
log.G(ctx).WithField("ref", config.Reference).Warnf("failed to delete diff upload")
}
}
}
}()
if !newReference {
if err := cw.Truncate(0); err != nil {
return emptyDesc, err
}
}
var opts []content.Opt
if isCompressed { if isCompressed {
dgstr := digest.SHA256.Digester() dgstr := digest.SHA256.Digester()
compressed, err := compression.CompressStream(cw, compression.Gzip) compressed, err := compression.CompressStream(cw, compression.Gzip)
@ -176,17 +219,24 @@ func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount
if err != nil { if err != nil {
return emptyDesc, errors.Wrap(err, "failed to write compressed diff") return emptyDesc, errors.Wrap(err, "failed to write compressed diff")
} }
opts = append(opts, content.WithLabels(map[string]string{
"containerd.io/uncompressed": dgstr.Digest().String(), if config.Labels == nil {
})) config.Labels = map[string]string{}
}
config.Labels["containerd.io/uncompressed"] = dgstr.Digest().String()
} else { } else {
if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil { if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil {
return emptyDesc, errors.Wrap(err, "failed to write diff") return emptyDesc, errors.Wrap(err, "failed to write diff")
} }
} }
var commitopts []content.Opt
if config.Labels != nil {
commitopts = append(commitopts, content.WithLabels(config.Labels))
}
dgst := cw.Digest() dgst := cw.Digest()
if err := cw.Commit(ctx, 0, dgst, opts...); err != nil { if err := cw.Commit(ctx, 0, dgst, commitopts...); err != nil {
return emptyDesc, errors.Wrap(err, "failed to commit") return emptyDesc, errors.Wrap(err, "failed to commit")
} }
@ -196,7 +246,7 @@ func (s *walkingDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount
} }
return ocispec.Descriptor{ return ocispec.Descriptor{
MediaType: media, MediaType: config.MediaType,
Size: info.Size, Size: info.Size,
Digest: info.Digest, Digest: info.Digest,
}, nil }, nil
@ -212,3 +262,11 @@ func (rc *readCounter) Read(p []byte) (n int, err error) {
rc.c += int64(n) rc.c += int64(n)
return return
} }
func uniqueRef() string {
t := time.Now()
var b [3]byte
// Ignore read failures, just decreases uniqueness
rand.Read(b[:])
return fmt.Sprintf("%d-%s", t.UnixNano(), base64.URLEncoding.EncodeToString(b[:]))
}

View File

@ -29,6 +29,7 @@ var (
ErrNotImplemented = errors.New("not implemented") // represents not supported and unimplemented ErrNotImplemented = errors.New("not implemented") // represents not supported and unimplemented
) )
// IsInvalidArgument returns true if the error is due to an invalid argument
func IsInvalidArgument(err error) bool { func IsInvalidArgument(err error) bool {
return errors.Cause(err) == ErrInvalidArgument return errors.Cause(err) == ErrInvalidArgument
} }
@ -45,15 +46,17 @@ func IsAlreadyExists(err error) bool {
} }
// IsFailedPrecondition returns true if an operation could not proceed to the // IsFailedPrecondition returns true if an operation could not proceed to the
// lack of a particular condition. // lack of a particular condition
func IsFailedPrecondition(err error) bool { func IsFailedPrecondition(err error) bool {
return errors.Cause(err) == ErrFailedPrecondition return errors.Cause(err) == ErrFailedPrecondition
} }
// IsUnavailable returns true if the error is due to a resource being unavailable
func IsUnavailable(err error) bool { func IsUnavailable(err error) bool {
return errors.Cause(err) == ErrUnavailable return errors.Cause(err) == ErrUnavailable
} }
// IsNotImplemented returns true if the error is due to not being implemented
func IsNotImplemented(err error) bool { func IsNotImplemented(err error) bool {
return errors.Cause(err) == ErrNotImplemented return errors.Cause(err) == ErrNotImplemented
} }

View File

@ -29,17 +29,17 @@ func ToGRPC(err error) error {
switch { switch {
case IsInvalidArgument(err): case IsInvalidArgument(err):
return grpc.Errorf(codes.InvalidArgument, err.Error()) return status.Errorf(codes.InvalidArgument, err.Error())
case IsNotFound(err): case IsNotFound(err):
return grpc.Errorf(codes.NotFound, err.Error()) return status.Errorf(codes.NotFound, err.Error())
case IsAlreadyExists(err): case IsAlreadyExists(err):
return grpc.Errorf(codes.AlreadyExists, err.Error()) return status.Errorf(codes.AlreadyExists, err.Error())
case IsFailedPrecondition(err): case IsFailedPrecondition(err):
return grpc.Errorf(codes.FailedPrecondition, err.Error()) return status.Errorf(codes.FailedPrecondition, err.Error())
case IsUnavailable(err): case IsUnavailable(err):
return grpc.Errorf(codes.Unavailable, err.Error()) return status.Errorf(codes.Unavailable, err.Error())
case IsNotImplemented(err): case IsNotImplemented(err):
return grpc.Errorf(codes.Unimplemented, err.Error()) return status.Errorf(codes.Unimplemented, err.Error())
} }
return err return err
@ -53,6 +53,7 @@ func ToGRPCf(err error, format string, args ...interface{}) error {
return ToGRPC(errors.Wrapf(err, format, args...)) return ToGRPC(errors.Wrapf(err, format, args...))
} }
// FromGRPC returns the underlying error from a grpc service based on the grpc error code
func FromGRPC(err error) error { func FromGRPC(err error) error {
if err == nil { if err == nil {
return nil return nil

View File

@ -6,6 +6,7 @@ import (
events "github.com/containerd/containerd/api/services/events/v1" events "github.com/containerd/containerd/api/services/events/v1"
) )
// Event is a generic interface for any type of event
type Event interface{} type Event interface{}
// Publisher posts the event. // Publisher posts the event.
@ -13,6 +14,7 @@ type Publisher interface {
Publish(ctx context.Context, topic string, event Event) error Publish(ctx context.Context, topic string, event Event) error
} }
// Forwarder forwards an event to the underlying event bus
type Forwarder interface { type Forwarder interface {
Forward(ctx context.Context, envelope *events.Envelope) error Forward(ctx context.Context, envelope *events.Envelope) error
} }
@ -23,6 +25,7 @@ func (fn publisherFunc) Publish(ctx context.Context, topic string, event Event)
return fn(ctx, topic, event) return fn(ctx, topic, event)
} }
// Subscriber allows callers to subscribe to events
type Subscriber interface { type Subscriber interface {
Subscribe(ctx context.Context, filters ...string) (ch <-chan *events.Envelope, errs <-chan error) Subscribe(ctx context.Context, filters ...string) (ch <-chan *events.Envelope, errs <-chan error)
} }

View File

@ -1,27 +1,30 @@
package events package exchange
import ( import (
"context" "context"
"strings" "strings"
"time" "time"
events "github.com/containerd/containerd/api/services/events/v1" v1 "github.com/containerd/containerd/api/services/events/v1"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/filters" "github.com/containerd/containerd/filters"
"github.com/containerd/containerd/identifiers" "github.com/containerd/containerd/identifiers"
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/typeurl" "github.com/containerd/typeurl"
goevents "github.com/docker/go-events" goevents "github.com/docker/go-events"
"github.com/gogo/protobuf/types" "github.com/gogo/protobuf/types"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// Exchange broadcasts events
type Exchange struct { type Exchange struct {
broadcaster *goevents.Broadcaster broadcaster *goevents.Broadcaster
} }
// NewExchange returns a new event Exchange
func NewExchange() *Exchange { func NewExchange() *Exchange {
return &Exchange{ return &Exchange{
broadcaster: goevents.NewBroadcaster(), broadcaster: goevents.NewBroadcaster(),
@ -32,7 +35,7 @@ func NewExchange() *Exchange {
// //
// This is useful when an event is forwaded on behalf of another namespace or // This is useful when an event is forwaded on behalf of another namespace or
// when the event is propagated on behalf of another publisher. // when the event is propagated on behalf of another publisher.
func (e *Exchange) Forward(ctx context.Context, envelope *events.Envelope) (err error) { func (e *Exchange) Forward(ctx context.Context, envelope *v1.Envelope) (err error) {
if err := validateEnvelope(envelope); err != nil { if err := validateEnvelope(envelope); err != nil {
return err return err
} }
@ -57,11 +60,11 @@ func (e *Exchange) Forward(ctx context.Context, envelope *events.Envelope) (err
// Publish packages and sends an event. The caller will be considered the // Publish packages and sends an event. The caller will be considered the
// initial publisher of the event. This means the timestamp will be calculated // initial publisher of the event. This means the timestamp will be calculated
// at this point and this method may read from the calling context. // at this point and this method may read from the calling context.
func (e *Exchange) Publish(ctx context.Context, topic string, event Event) (err error) { func (e *Exchange) Publish(ctx context.Context, topic string, event events.Event) (err error) {
var ( var (
namespace string namespace string
encoded *types.Any encoded *types.Any
envelope events.Envelope envelope v1.Envelope
) )
namespace, err = namespaces.NamespaceRequired(ctx) namespace, err = namespaces.NamespaceRequired(ctx)
@ -106,9 +109,9 @@ func (e *Exchange) Publish(ctx context.Context, topic string, event Event) (err
// Zero or more filters may be provided as strings. Only events that match // Zero or more filters may be provided as strings. Only events that match
// *any* of the provided filters will be sent on the channel. The filters use // *any* of the provided filters will be sent on the channel. The filters use
// the standard containerd filters package syntax. // the standard containerd filters package syntax.
func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *events.Envelope, errs <-chan error) { func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *v1.Envelope, errs <-chan error) {
var ( var (
evch = make(chan *events.Envelope) evch = make(chan *v1.Envelope)
errq = make(chan error, 1) errq = make(chan error, 1)
channel = goevents.NewChannel(0) channel = goevents.NewChannel(0)
queue = goevents.NewQueue(channel) queue = goevents.NewQueue(channel)
@ -148,7 +151,7 @@ func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *even
for { for {
select { select {
case ev := <-channel.C: case ev := <-channel.C:
env, ok := ev.(*events.Envelope) env, ok := ev.(*v1.Envelope)
if !ok { if !ok {
// TODO(stevvooe): For the most part, we are well protected // TODO(stevvooe): For the most part, we are well protected
// from this condition. Both Forward and Publish protect // from this condition. Both Forward and Publish protect
@ -202,7 +205,7 @@ func validateTopic(topic string) error {
return nil return nil
} }
func validateEnvelope(envelope *events.Envelope) error { func validateEnvelope(envelope *v1.Envelope) error {
if err := namespaces.Validate(envelope.Namespace); err != nil { if err := namespaces.Validate(envelope.Namespace); err != nil {
return errors.Wrapf(err, "event envelope has invalid namespace") return errors.Wrapf(err, "event envelope has invalid namespace")
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
ocispecs "github.com/opencontainers/image-spec/specs-go" ocispecs "github.com/opencontainers/image-spec/specs-go"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -32,7 +33,7 @@ func (c *Client) exportToOCITar(ctx context.Context, desc ocispec.Descriptor, wr
} }
handlers := images.Handlers( handlers := images.Handlers(
images.ChildrenHandler(cs), images.ChildrenHandler(cs, platforms.Default()),
images.HandlerFunc(exportHandler), images.HandlerFunc(exportHandler),
) )

View File

@ -8,8 +8,10 @@ type Adaptor interface {
Field(fieldpath []string) (value string, present bool) Field(fieldpath []string) (value string, present bool)
} }
// AdapterFunc allows implementation specific matching of fieldpaths
type AdapterFunc func(fieldpath []string) (string, bool) type AdapterFunc func(fieldpath []string) (string, bool)
// Field returns the field name and true if it exists
func (fn AdapterFunc) Field(fieldpath []string) (string, bool) { func (fn AdapterFunc) Field(fieldpath []string) (string, bool) {
return fn(fieldpath) return fn(fieldpath)
} }

View File

@ -58,22 +58,28 @@ import (
"github.com/containerd/containerd/log" "github.com/containerd/containerd/log"
) )
// Filter matches specific resources based the provided filter
type Filter interface { type Filter interface {
Match(adaptor Adaptor) bool Match(adaptor Adaptor) bool
} }
// FilterFunc is a function that handles matching with an adaptor
type FilterFunc func(Adaptor) bool type FilterFunc func(Adaptor) bool
// Match matches the FilterFunc returning true if the object matches the filter
func (fn FilterFunc) Match(adaptor Adaptor) bool { func (fn FilterFunc) Match(adaptor Adaptor) bool {
return fn(adaptor) return fn(adaptor)
} }
// Always is a filter that always returns true for any type of object
var Always FilterFunc = func(adaptor Adaptor) bool { var Always FilterFunc = func(adaptor Adaptor) bool {
return true return true
} }
// Any allows multiple filters to be matched aginst the object
type Any []Filter type Any []Filter
// Match returns true if any of the provided filters are true
func (m Any) Match(adaptor Adaptor) bool { func (m Any) Match(adaptor Adaptor) bool {
for _, m := range m { for _, m := range m {
if m.Match(adaptor) { if m.Match(adaptor) {
@ -84,8 +90,10 @@ func (m Any) Match(adaptor Adaptor) bool {
return false return false
} }
// All allows multiple filters to be matched aginst the object
type All []Filter type All []Filter
// Match only returns true if all filters match the object
func (m All) Match(adaptor Adaptor) bool { func (m All) Match(adaptor Adaptor) bool {
for _, m := range m { for _, m := range m {
if !m.Match(adaptor) { if !m.Match(adaptor) {

View File

@ -67,9 +67,8 @@ func (s *scanner) next() rune {
if r == utf8.RuneError { if r == utf8.RuneError {
if w > 0 { if w > 0 {
return tokenIllegal return tokenIllegal
} else {
return tokenEOF
} }
return tokenEOF
} }
if r == 0 { if r == 0 {

View File

@ -1,5 +1,6 @@
package fs package fs
// Usage of disk information
type Usage struct { type Usage struct {
Inodes int64 Inodes int64
Size int64 Size int64

View File

@ -2,7 +2,7 @@ package fs
import "os" import "os"
// GetLinkID returns an identifier representing the node a hardlink is pointing // GetLinkInfo returns an identifier representing the node a hardlink is pointing
// to. If the file is not hard linked then 0 will be returned. // to. If the file is not hard linked then 0 will be returned.
func GetLinkInfo(fi os.FileInfo) (uint64, bool) { func GetLinkInfo(fi os.FileInfo) (uint64, bool) {
return getLinkInfo(fi) return getLinkInfo(fi)

160
vendor/github.com/containerd/containerd/gc/gc.go generated vendored Normal file
View File

@ -0,0 +1,160 @@
// Package gc experiments with providing central gc tooling to ensure
// deterministic resource removal within containerd.
//
// For now, we just have a single exported implementation that can be used
// under certain use cases.
package gc
import (
"context"
"sync"
)
// ResourceType represents type of resource at a node
type ResourceType uint8
// Node presents a resource which has a type and key,
// this node can be used to lookup other nodes.
type Node struct {
Type ResourceType
Namespace string
Key string
}
// Tricolor implements basic, single-thread tri-color GC. Given the roots, the
// complete set and a refs function, this function returns a map of all
// reachable objects.
//
// Correct usage requires that the caller not allow the arguments to change
// until the result is used to delete objects in the system.
//
// It will allocate memory proportional to the size of the reachable set.
//
// We can probably use this to inform a design for incremental GC by injecting
// callbacks to the set modification algorithms.
func Tricolor(roots []Node, refs func(ref Node) ([]Node, error)) (map[Node]struct{}, error) {
var (
grays []Node // maintain a gray "stack"
seen = map[Node]struct{}{} // or not "white", basically "seen"
reachable = map[Node]struct{}{} // or "block", in tri-color parlance
)
grays = append(grays, roots...)
for len(grays) > 0 {
// Pick any gray object
id := grays[len(grays)-1] // effectively "depth first" because first element
grays = grays[:len(grays)-1]
seen[id] = struct{}{} // post-mark this as not-white
rs, err := refs(id)
if err != nil {
return nil, err
}
// mark all the referenced objects as gray
for _, target := range rs {
if _, ok := seen[target]; !ok {
grays = append(grays, target)
}
}
// mark as black when done
reachable[id] = struct{}{}
}
return reachable, nil
}
// ConcurrentMark implements simple, concurrent GC. All the roots are scanned
// and the complete set of references is formed by calling the refs function
// for each seen object. This function returns a map of all object reachable
// from a root.
//
// Correct usage requires that the caller not allow the arguments to change
// until the result is used to delete objects in the system.
//
// It will allocate memory proportional to the size of the reachable set.
func ConcurrentMark(ctx context.Context, root <-chan Node, refs func(context.Context, Node, func(Node)) error) (map[Node]struct{}, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
var (
grays = make(chan Node)
seen = map[Node]struct{}{} // or not "white", basically "seen"
wg sync.WaitGroup
errOnce sync.Once
refErr error
)
go func() {
for gray := range grays {
if _, ok := seen[gray]; ok {
wg.Done()
continue
}
seen[gray] = struct{}{} // post-mark this as non-white
go func(gray Node) {
defer wg.Done()
send := func(n Node) {
wg.Add(1)
select {
case grays <- n:
case <-ctx.Done():
wg.Done()
}
}
if err := refs(ctx, gray, send); err != nil {
errOnce.Do(func() {
refErr = err
cancel()
})
}
}(gray)
}
}()
for r := range root {
wg.Add(1)
select {
case grays <- r:
case <-ctx.Done():
wg.Done()
}
}
// Wait for outstanding grays to be processed
wg.Wait()
close(grays)
if refErr != nil {
return nil, refErr
}
if cErr := ctx.Err(); cErr != nil {
return nil, cErr
}
return seen, nil
}
// Sweep removes all nodes returned through the channel which are not in
// the reachable set by calling the provided remove function.
func Sweep(reachable map[Node]struct{}, all []Node, remove func(Node) error) error {
// All black objects are now reachable, and all white objects are
// unreachable. Free those that are white!
for _, node := range all {
if _, ok := reachable[node]; !ok {
if err := remove(node); err != nil {
return err
}
}
}
return nil
}

View File

@ -2,11 +2,16 @@ package containerd
import ( import (
"context" "context"
"fmt"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/rootfs" "github.com/containerd/containerd/rootfs"
"github.com/containerd/containerd/snapshot"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -25,6 +30,8 @@ type Image interface {
Size(ctx context.Context) (int64, error) Size(ctx context.Context) (int64, error)
// Config descriptor for the image. // Config descriptor for the image.
Config(ctx context.Context) (ocispec.Descriptor, error) Config(ctx context.Context) (ocispec.Descriptor, error)
// IsUnpacked returns whether or not an image is unpacked.
IsUnpacked(context.Context, string) (bool, error)
} }
var _ = (Image)(&image{}) var _ = (Image)(&image{})
@ -45,55 +52,85 @@ func (i *image) Target() ocispec.Descriptor {
func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) { func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
provider := i.client.ContentStore() provider := i.client.ContentStore()
return i.i.RootFS(ctx, provider, platforms.Format(platforms.Default())) return i.i.RootFS(ctx, provider, platforms.Default())
} }
func (i *image) Size(ctx context.Context) (int64, error) { func (i *image) Size(ctx context.Context) (int64, error) {
provider := i.client.ContentStore() provider := i.client.ContentStore()
return i.i.Size(ctx, provider) return i.i.Size(ctx, provider, platforms.Default())
} }
func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) { func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {
provider := i.client.ContentStore() provider := i.client.ContentStore()
return i.i.Config(ctx, provider, platforms.Format(platforms.Default())) return i.i.Config(ctx, provider, platforms.Default())
}
func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, error) {
sn := i.client.SnapshotService(snapshotterName)
cs := i.client.ContentStore()
diffs, err := i.i.RootFS(ctx, cs, platforms.Default())
if err != nil {
return false, err
}
chainID := identity.ChainID(diffs)
_, err = sn.Stat(ctx, chainID.String())
if err == nil {
return true, nil
} else if !errdefs.IsNotFound(err) {
return false, err
}
return false, nil
} }
func (i *image) Unpack(ctx context.Context, snapshotterName string) error { func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
layers, err := i.getLayers(ctx, platforms.Format(platforms.Default())) layers, err := i.getLayers(ctx, platforms.Default())
if err != nil { if err != nil {
return err return err
} }
sn := i.client.SnapshotService(snapshotterName) var (
a := i.client.DiffService() sn = i.client.SnapshotService(snapshotterName)
cs := i.client.ContentStore() a = i.client.DiffService()
cs = i.client.ContentStore()
var chain []digest.Digest chain []digest.Digest
unpacked bool
)
for _, layer := range layers { for _, layer := range layers {
unpacked, err := rootfs.ApplyLayer(ctx, layer, chain, sn, a) labels := map[string]string{
if err != nil { "containerd.io/uncompressed": layer.Diff.Digest.String(),
// TODO: possibly wait and retry if extraction of same chain id was in progress
return err
} }
if unpacked {
info, err := cs.Info(ctx, layer.Blob.Digest) unpacked, err = rootfs.ApplyLayer(ctx, layer, chain, sn, a, snapshot.WithLabels(labels))
if err != nil { if err != nil {
return err return err
}
if info.Labels["containerd.io/uncompressed"] != layer.Diff.Digest.String() {
if info.Labels == nil {
info.Labels = map[string]string{}
}
info.Labels["containerd.io/uncompressed"] = layer.Diff.Digest.String()
if _, err := cs.Update(ctx, info, "labels.containerd.io/uncompressed"); err != nil {
return err
}
}
} }
chain = append(chain, layer.Diff.Digest) chain = append(chain, layer.Diff.Digest)
} }
if unpacked {
desc, err := i.i.Config(ctx, cs, platforms.Default())
if err != nil {
return err
}
rootfs := identity.ChainID(chain).String()
cinfo := content.Info{
Digest: desc.Digest,
Labels: map[string]string{
fmt.Sprintf("containerd.io/gc.ref.snapshot.%s", snapshotterName): rootfs,
},
}
if _, err := cs.Update(ctx, cinfo, fmt.Sprintf("labels.containerd.io/gc.ref.snapshot.%s", snapshotterName)); err != nil {
return err
}
}
return nil return nil
} }

View File

@ -2,48 +2,49 @@ package images
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/log"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
var ( var (
// SkipDesc is used to skip processing of a descriptor and // ErrSkipDesc is used to skip processing of a descriptor and
// its descendants. // its descendants.
SkipDesc = fmt.Errorf("skip descriptor") ErrSkipDesc = fmt.Errorf("skip descriptor")
// StopHandler is used to signify that the descriptor // ErrStopHandler is used to signify that the descriptor
// has been handled and should not be handled further. // has been handled and should not be handled further.
// This applies only to a single descriptor in a handler // This applies only to a single descriptor in a handler
// chain and does not apply to descendant descriptors. // chain and does not apply to descendant descriptors.
StopHandler = fmt.Errorf("stop handler") ErrStopHandler = fmt.Errorf("stop handler")
) )
// Handler handles image manifests
type Handler interface { type Handler interface {
Handle(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) Handle(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error)
} }
// HandlerFunc function implementing the Handler interface
type HandlerFunc func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) type HandlerFunc func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error)
// Handle image manifests
func (fn HandlerFunc) Handle(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) { func (fn HandlerFunc) Handle(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) {
return fn(ctx, desc) return fn(ctx, desc)
} }
// Handlers returns a handler that will run the handlers in sequence. // Handlers returns a handler that will run the handlers in sequence.
// //
// A handler may return `StopHandler` to stop calling additional handlers // A handler may return `ErrStopHandler` to stop calling additional handlers
func Handlers(handlers ...Handler) HandlerFunc { func Handlers(handlers ...Handler) HandlerFunc {
return func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) { return func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) {
var children []ocispec.Descriptor var children []ocispec.Descriptor
for _, handler := range handlers { for _, handler := range handlers {
ch, err := handler.Handle(ctx, desc) ch, err := handler.Handle(ctx, desc)
if err != nil { if err != nil {
if errors.Cause(err) == StopHandler { if errors.Cause(err) == ErrStopHandler {
break break
} }
return nil, err return nil, err
@ -66,7 +67,7 @@ func Walk(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) err
children, err := handler.Handle(ctx, desc) children, err := handler.Handle(ctx, desc)
if err != nil { if err != nil {
if errors.Cause(err) == SkipDesc { if errors.Cause(err) == ErrSkipDesc {
continue // don't traverse the children. continue // don't traverse the children.
} }
return err return err
@ -86,7 +87,7 @@ func Walk(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) err
// If the handler decode subresources, they will be visited, as well. // If the handler decode subresources, they will be visited, as well.
// //
// Handlers for siblings are run in parallel on the provided descriptors. A // Handlers for siblings are run in parallel on the provided descriptors. A
// handler may return `SkipDesc` to signal to the dispatcher to not traverse // handler may return `ErrSkipDesc` to signal to the dispatcher to not traverse
// any children. // any children.
// //
// Typically, this function will be used with `FetchHandler`, often composed // Typically, this function will be used with `FetchHandler`, often composed
@ -103,7 +104,7 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor)
children, err := handler.Handle(ctx, desc) children, err := handler.Handle(ctx, desc)
if err != nil { if err != nil {
if errors.Cause(err) == SkipDesc { if errors.Cause(err) == ErrSkipDesc {
return nil // don't traverse the children. return nil // don't traverse the children.
} }
return err return err
@ -120,53 +121,15 @@ func Dispatch(ctx context.Context, handler Handler, descs ...ocispec.Descriptor)
return eg.Wait() return eg.Wait()
} }
// ChildrenHandler decodes well-known manifests types and returns their children. // ChildrenHandler decodes well-known manifest types and returns their children.
// //
// This is useful for supporting recursive fetch and other use cases where you // This is useful for supporting recursive fetch and other use cases where you
// want to do a full walk of resources. // want to do a full walk of resources.
// //
// One can also replace this with another implementation to allow descending of // One can also replace this with another implementation to allow descending of
// arbitrary types. // arbitrary types.
func ChildrenHandler(provider content.Provider) HandlerFunc { func ChildrenHandler(provider content.Provider, platform string) HandlerFunc {
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
var descs []ocispec.Descriptor return Children(ctx, provider, desc, platform)
switch desc.MediaType {
case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
p, err := content.ReadBlob(ctx, provider, desc.Digest)
if err != nil {
return nil, err
}
// TODO(stevvooe): We just assume oci manifest, for now. There may be
// subtle differences from the docker version.
var manifest ocispec.Manifest
if err := json.Unmarshal(p, &manifest); err != nil {
return nil, err
}
descs = append(descs, manifest.Config)
descs = append(descs, manifest.Layers...)
case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
p, err := content.ReadBlob(ctx, provider, desc.Digest)
if err != nil {
return nil, err
}
var index ocispec.Index
if err := json.Unmarshal(p, &index); err != nil {
return nil, err
}
descs = append(descs, index.Manifests...)
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip:
// childless data types.
return nil, nil
default:
log.G(ctx).Warnf("encountered unknown type %v; children may not be fetched", desc.MediaType)
}
return descs, nil
} }
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -15,12 +16,29 @@ import (
// Image provides the model for how containerd views container images. // Image provides the model for how containerd views container images.
type Image struct { type Image struct {
Name string // Name of the image.
Labels map[string]string //
Target ocispec.Descriptor // To be pulled, it must be a reference compatible with resolvers.
//
// This field is required.
Name string
// Labels provide runtime decoration for the image record.
//
// There is no default behavior for how these labels are propagated. They
// only decorate the static metadata object.
//
// This field is optional.
Labels map[string]string
// Target describes the root content for this image. Typically, this is
// a manifest, index or manifest list.
Target ocispec.Descriptor
CreatedAt, UpdatedAt time.Time CreatedAt, UpdatedAt time.Time
} }
// Store and interact with images
type Store interface { type Store interface {
Get(ctx context.Context, name string) (Image, error) Get(ctx context.Context, name string) (Image, error)
List(ctx context.Context, filters ...string) ([]Image, error) List(ctx context.Context, filters ...string) ([]Image, error)
@ -58,7 +76,7 @@ func (image *Image) RootFS(ctx context.Context, provider content.Provider, platf
} }
// Size returns the total size of an image's packed resources. // Size returns the total size of an image's packed resources.
func (image *Image) Size(ctx context.Context, provider content.Provider) (int64, error) { func (image *Image) Size(ctx context.Context, provider content.Provider, platform string) (int64, error) {
var size int64 var size int64
return size, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { return size, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if desc.Size < 0 { if desc.Size < 0 {
@ -66,9 +84,15 @@ func (image *Image) Size(ctx context.Context, provider content.Provider) (int64,
} }
size += desc.Size size += desc.Size
return nil, nil return nil, nil
}), ChildrenHandler(provider)), image.Target) }), ChildrenHandler(provider, platform)), image.Target)
} }
// Manifest resolves a manifest from the image for the given platform.
//
// TODO(stevvooe): This violates the current platform agnostic approach to this
// package by returning a specific manifest type. We'll need to refactor this
// to return a manifest descriptor or decide that we want to bring the API in
// this direction because this abstraction is not needed.`
func Manifest(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform string) (ocispec.Manifest, error) { func Manifest(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform string) (ocispec.Manifest, error) {
var ( var (
matcher platforms.Matcher matcher platforms.Matcher
@ -146,7 +170,7 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
return descs, nil return descs, nil
} }
return nil, errors.New("could not resolve manifest") return nil, errors.Wrap(errdefs.ErrNotFound, "could not resolve manifest")
}), image); err != nil { }), image); err != nil {
return ocispec.Manifest{}, err return ocispec.Manifest{}, err
} }
@ -177,7 +201,7 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des
return platformSpecs, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { return platformSpecs, Walk(ctx, Handlers(HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if desc.Platform != nil { if desc.Platform != nil {
platformSpecs = append(platformSpecs, *desc.Platform) platformSpecs = append(platformSpecs, *desc.Platform)
return nil, SkipDesc return nil, ErrSkipDesc
} }
switch desc.MediaType { switch desc.MediaType {
@ -196,7 +220,110 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des
platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture})) platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}))
} }
return nil, nil return nil, nil
}), ChildrenHandler(provider)), image) }), ChildrenHandler(provider, "")), image)
}
// Check returns nil if the all components of an image are available in the
// provider for the specified platform.
//
// If available is true, the caller can assume that required represents the
// complete set of content required for the image.
//
// missing will have the components that are part of required but not avaiiable
// in the provider.
//
// If there is a problem resolving content, an error will be returned.
func Check(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform string) (available bool, required, present, missing []ocispec.Descriptor, err error) {
mfst, err := Manifest(ctx, provider, image, platform)
if err != nil {
if errdefs.IsNotFound(err) {
return false, []ocispec.Descriptor{image}, nil, []ocispec.Descriptor{image}, nil
}
return false, nil, nil, nil, errors.Wrap(err, "image check failed")
}
// TODO(stevvooe): It is possible that referenced conponents could have
// children, but this is rare. For now, we ignore this and only verify
// that manfiest components are present.
required = append([]ocispec.Descriptor{mfst.Config}, mfst.Layers...)
for _, desc := range required {
ra, err := provider.ReaderAt(ctx, desc.Digest)
if err != nil {
if errdefs.IsNotFound(err) {
missing = append(missing, desc)
continue
} else {
return false, nil, nil, nil, err
}
}
ra.Close()
present = append(present, desc)
}
return true, required, present, missing, nil
}
// Children returns the immediate children of content described by the descriptor.
func Children(ctx context.Context, provider content.Provider, desc ocispec.Descriptor, platform string) ([]ocispec.Descriptor, error) {
var descs []ocispec.Descriptor
switch desc.MediaType {
case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
p, err := content.ReadBlob(ctx, provider, desc.Digest)
if err != nil {
return nil, err
}
// TODO(stevvooe): We just assume oci manifest, for now. There may be
// subtle differences from the docker version.
var manifest ocispec.Manifest
if err := json.Unmarshal(p, &manifest); err != nil {
return nil, err
}
descs = append(descs, manifest.Config)
descs = append(descs, manifest.Layers...)
case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
p, err := content.ReadBlob(ctx, provider, desc.Digest)
if err != nil {
return nil, err
}
var index ocispec.Index
if err := json.Unmarshal(p, &index); err != nil {
return nil, err
}
if platform != "" {
matcher, err := platforms.Parse(platform)
if err != nil {
return nil, err
}
for _, d := range index.Manifests {
if d.Platform == nil || matcher.Match(*d.Platform) {
descs = append(descs, d)
}
}
} else {
descs = append(descs, index.Manifests...)
}
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip,
MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip,
ocispec.MediaTypeImageLayerNonDistributable, ocispec.MediaTypeImageLayerNonDistributableGzip,
MediaTypeContainerd1Checkpoint, MediaTypeContainerd1CheckpointConfig:
// childless data types.
return nil, nil
default:
log.G(ctx).Warnf("encountered unknown type %v; children may not be fetched", desc.MediaType)
}
return descs, nil
} }
// RootFS returns the unpacked diffids that make up and images rootfs. // RootFS returns the unpacked diffids that make up and images rootfs.

View File

@ -5,11 +5,13 @@ package images
// oci components are generally referenced directly, although we may centralize // oci components are generally referenced directly, although we may centralize
// here for clarity. // here for clarity.
const ( const (
MediaTypeDockerSchema2Layer = "application/vnd.docker.image.rootfs.diff.tar" MediaTypeDockerSchema2Layer = "application/vnd.docker.image.rootfs.diff.tar"
MediaTypeDockerSchema2LayerGzip = "application/vnd.docker.image.rootfs.diff.tar.gzip" MediaTypeDockerSchema2LayerForeign = "application/vnd.docker.image.rootfs.foreign.diff.tar"
MediaTypeDockerSchema2Config = "application/vnd.docker.container.image.v1+json" MediaTypeDockerSchema2LayerGzip = "application/vnd.docker.image.rootfs.diff.tar.gzip"
MediaTypeDockerSchema2Manifest = "application/vnd.docker.distribution.manifest.v2+json" MediaTypeDockerSchema2LayerForeignGzip = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip"
MediaTypeDockerSchema2ManifestList = "application/vnd.docker.distribution.manifest.list.v2+json" MediaTypeDockerSchema2Config = "application/vnd.docker.container.image.v1+json"
MediaTypeDockerSchema2Manifest = "application/vnd.docker.distribution.manifest.v2+json"
MediaTypeDockerSchema2ManifestList = "application/vnd.docker.distribution.manifest.list.v2+json"
// Checkpoint/Restore Media Types // Checkpoint/Restore Media Types
MediaTypeContainerd1Checkpoint = "application/vnd.containerd.container.criu.checkpoint.criu.tar" MediaTypeContainerd1Checkpoint = "application/vnd.containerd.container.criu.checkpoint.criu.tar"
MediaTypeContainerd1CheckpointPreDump = "application/vnd.containerd.container.criu.checkpoint.predump.tar" MediaTypeContainerd1CheckpointPreDump = "application/vnd.containerd.container.criu.checkpoint.predump.tar"

View File

@ -68,6 +68,7 @@ func (c *Client) importFromOCITar(ctx context.Context, ref string, reader io.Rea
imgrec := images.Image{ imgrec := images.Image{
Name: ref, Name: ref,
Target: *desc, Target: *desc,
Labels: iopts.labels,
} }
is := c.ImageService() is := c.ImageService()
if updated, err := is.Update(ctx, imgrec, "target"); err != nil { if updated, err := is.Update(ctx, imgrec, "target"); err != nil {

View File

@ -68,6 +68,10 @@ func (c *cio) Close() error {
type IOCreation func(id string) (IO, error) type IOCreation func(id string) (IO, error)
// IOAttach allows callers to reattach to running tasks // IOAttach allows callers to reattach to running tasks
//
// There should only be one reader for a task's IO set
// because fifo's can only be read from one reader or the output
// will be sent only to the first reads
type IOAttach func(*FIFOSet) (IO, error) type IOAttach func(*FIFOSet) (IO, error)
// NewIO returns an IOCreation that will provide IO sets without a terminal // NewIO returns an IOCreation that will provide IO sets without a terminal

View File

@ -16,7 +16,7 @@ import (
// NewFifos returns a new set of fifos for the task // NewFifos returns a new set of fifos for the task
func NewFifos(id string) (*FIFOSet, error) { func NewFifos(id string) (*FIFOSet, error) {
root := filepath.Join(os.TempDir(), "containerd") root := "/run/containerd/fifo"
if err := os.MkdirAll(root, 0700); err != nil { if err := os.MkdirAll(root, 0700); err != nil {
return nil, err return nil, err
} }
@ -119,6 +119,7 @@ func NewDirectIO(ctx context.Context, terminal bool) (*DirectIO, error) {
return f, nil return f, nil
} }
// DirectIO allows task IO to be handled externally by the caller
type DirectIO struct { type DirectIO struct {
Stdin io.WriteCloser Stdin io.WriteCloser
Stdout io.ReadCloser Stdout io.ReadCloser
@ -128,14 +129,17 @@ type DirectIO struct {
terminal bool terminal bool
} }
// IOCreate returns IO avaliable for use with task creation
func (f *DirectIO) IOCreate(id string) (IO, error) { func (f *DirectIO) IOCreate(id string) (IO, error) {
return f, nil return f, nil
} }
// IOAttach returns IO avaliable for use with task attachment
func (f *DirectIO) IOAttach(set *FIFOSet) (IO, error) { func (f *DirectIO) IOAttach(set *FIFOSet) (IO, error) {
return f, nil return f, nil
} }
// Config returns the IOConfig
func (f *DirectIO) Config() IOConfig { func (f *DirectIO) Config() IOConfig {
return IOConfig{ return IOConfig{
Terminal: f.terminal, Terminal: f.terminal,
@ -145,14 +149,21 @@ func (f *DirectIO) Config() IOConfig {
} }
} }
// Cancel stops any IO copy operations
//
// Not applicable for DirectIO
func (f *DirectIO) Cancel() { func (f *DirectIO) Cancel() {
// nothing to cancel as all operations are handled externally // nothing to cancel as all operations are handled externally
} }
// Wait on any IO copy operations
//
// Not applicable for DirectIO
func (f *DirectIO) Wait() { func (f *DirectIO) Wait() {
// nothing to wait on as all operations are handled externally // nothing to wait on as all operations are handled externally
} }
// Close closes all open fds
func (f *DirectIO) Close() error { func (f *DirectIO) Close() error {
err := f.Stdin.Close() err := f.Stdin.Close()
if err2 := f.Stdout.Close(); err == nil { if err2 := f.Stdout.Close(); err == nil {
@ -164,6 +175,7 @@ func (f *DirectIO) Close() error {
return err return err
} }
// Delete removes the underlying directory containing fifos
func (f *DirectIO) Delete() error { func (f *DirectIO) Delete() error {
if f.set.Dir == "" { if f.set.Dir == "" {
return nil return nil

View File

@ -0,0 +1,21 @@
package labels
import (
"github.com/containerd/containerd/errdefs"
"github.com/pkg/errors"
)
const (
maxSize = 4096
)
// Validate a label's key and value are under 4096 bytes
func Validate(k, v string) error {
if (len(k) + len(v)) > maxSize {
if len(k) > 10 {
k = k[:10]
}
return errors.Wrapf(errdefs.ErrInvalidArgument, "label key and value greater than maximum size (%d bytes), key: %s", maxSize, k)
}
return nil
}

91
vendor/github.com/containerd/containerd/lease.go generated vendored Normal file
View File

@ -0,0 +1,91 @@
package containerd
import (
"context"
"time"
leasesapi "github.com/containerd/containerd/api/services/leases/v1"
"github.com/containerd/containerd/leases"
)
// Lease is used to hold a reference to active resources which have not been
// referenced by a root resource. This is useful for preventing garbage
// collection of resources while they are actively being updated.
type Lease struct {
id string
createdAt time.Time
client *Client
}
// CreateLease creates a new lease
func (c *Client) CreateLease(ctx context.Context) (Lease, error) {
lapi := leasesapi.NewLeasesClient(c.conn)
resp, err := lapi.Create(ctx, &leasesapi.CreateRequest{})
if err != nil {
return Lease{}, err
}
return Lease{
id: resp.Lease.ID,
client: c,
}, nil
}
// ListLeases lists active leases
func (c *Client) ListLeases(ctx context.Context) ([]Lease, error) {
lapi := leasesapi.NewLeasesClient(c.conn)
resp, err := lapi.List(ctx, &leasesapi.ListRequest{})
if err != nil {
return nil, err
}
leases := make([]Lease, len(resp.Leases))
for i := range resp.Leases {
leases[i] = Lease{
id: resp.Leases[i].ID,
createdAt: resp.Leases[i].CreatedAt,
client: c,
}
}
return leases, nil
}
func (c *Client) withLease(ctx context.Context) (context.Context, func() error, error) {
_, ok := leases.Lease(ctx)
if ok {
return ctx, func() error {
return nil
}, nil
}
l, err := c.CreateLease(ctx)
if err != nil {
return nil, nil, err
}
ctx = leases.WithLease(ctx, l.ID())
return ctx, func() error {
return l.Delete(ctx)
}, nil
}
// ID returns the lease ID
func (l Lease) ID() string {
return l.id
}
// CreatedAt returns the time at which the lease was created
func (l Lease) CreatedAt() time.Time {
return l.createdAt
}
// Delete deletes the lease, removing the reference to all resources created
// during the lease.
func (l Lease) Delete(ctx context.Context) error {
lapi := leasesapi.NewLeasesClient(l.client.conn)
_, err := lapi.Delete(ctx, &leasesapi.DeleteRequest{
ID: l.id,
})
return err
}

View File

@ -0,0 +1,24 @@
package leases
import "context"
type leaseKey struct{}
// WithLease sets a given lease on the context
func WithLease(ctx context.Context, lid string) context.Context {
ctx = context.WithValue(ctx, leaseKey{}, lid)
// also store on the grpc headers so it gets picked up by any clients that
// are using this.
return withGRPCLeaseHeader(ctx, lid)
}
// Lease returns the lease from the context.
func Lease(ctx context.Context) (string, bool) {
lid, ok := ctx.Value(leaseKey{}).(string)
if !ok {
return fromGRPCHeader(ctx)
}
return lid, ok
}

41
vendor/github.com/containerd/containerd/leases/grpc.go generated vendored Normal file
View File

@ -0,0 +1,41 @@
package leases
import (
"golang.org/x/net/context"
"google.golang.org/grpc/metadata"
)
const (
// GRPCHeader defines the header name for specifying a containerd lease.
GRPCHeader = "containerd-lease"
)
func withGRPCLeaseHeader(ctx context.Context, lid string) context.Context {
// also store on the grpc headers so it gets picked up by any clients
// that are using this.
txheader := metadata.Pairs(GRPCHeader, lid)
md, ok := metadata.FromOutgoingContext(ctx) // merge with outgoing context.
if !ok {
md = txheader
} else {
// order ensures the latest is first in this list.
md = metadata.Join(txheader, md)
}
return metadata.NewOutgoingContext(ctx, md)
}
func fromGRPCHeader(ctx context.Context) (string, bool) {
// try to extract for use in grpc servers.
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return "", false
}
values := md[GRPCHeader]
if len(values) == 0 {
return "", false
}
return values[0], true
}

View File

@ -57,6 +57,8 @@ type CreateOptions struct {
CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"` CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"`
NoNewKeyring bool `protobuf:"varint,8,opt,name=no_new_keyring,json=noNewKeyring,proto3" json:"no_new_keyring,omitempty"` NoNewKeyring bool `protobuf:"varint,8,opt,name=no_new_keyring,json=noNewKeyring,proto3" json:"no_new_keyring,omitempty"`
ShimCgroup string `protobuf:"bytes,9,opt,name=shim_cgroup,json=shimCgroup,proto3" json:"shim_cgroup,omitempty"` ShimCgroup string `protobuf:"bytes,9,opt,name=shim_cgroup,json=shimCgroup,proto3" json:"shim_cgroup,omitempty"`
IoUid uint32 `protobuf:"varint,10,opt,name=io_uid,json=ioUid,proto3" json:"io_uid,omitempty"`
IoGid uint32 `protobuf:"varint,11,opt,name=io_gid,json=ioGid,proto3" json:"io_gid,omitempty"`
} }
func (m *CreateOptions) Reset() { *m = CreateOptions{} } func (m *CreateOptions) Reset() { *m = CreateOptions{} }
@ -230,6 +232,16 @@ func (m *CreateOptions) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintRunc(dAtA, i, uint64(len(m.ShimCgroup))) i = encodeVarintRunc(dAtA, i, uint64(len(m.ShimCgroup)))
i += copy(dAtA[i:], m.ShimCgroup) i += copy(dAtA[i:], m.ShimCgroup)
} }
if m.IoUid != 0 {
dAtA[i] = 0x50
i++
i = encodeVarintRunc(dAtA, i, uint64(m.IoUid))
}
if m.IoGid != 0 {
dAtA[i] = 0x58
i++
i = encodeVarintRunc(dAtA, i, uint64(m.IoGid))
}
return i, nil return i, nil
} }
@ -405,6 +417,12 @@ func (m *CreateOptions) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovRunc(uint64(l)) n += 1 + l + sovRunc(uint64(l))
} }
if m.IoUid != 0 {
n += 1 + sovRunc(uint64(m.IoUid))
}
if m.IoGid != 0 {
n += 1 + sovRunc(uint64(m.IoGid))
}
return n return n
} }
@ -479,6 +497,8 @@ func (this *CreateOptions) String() string {
`CgroupsMode:` + fmt.Sprintf("%v", this.CgroupsMode) + `,`, `CgroupsMode:` + fmt.Sprintf("%v", this.CgroupsMode) + `,`,
`NoNewKeyring:` + fmt.Sprintf("%v", this.NoNewKeyring) + `,`, `NoNewKeyring:` + fmt.Sprintf("%v", this.NoNewKeyring) + `,`,
`ShimCgroup:` + fmt.Sprintf("%v", this.ShimCgroup) + `,`, `ShimCgroup:` + fmt.Sprintf("%v", this.ShimCgroup) + `,`,
`IoUid:` + fmt.Sprintf("%v", this.IoUid) + `,`,
`IoGid:` + fmt.Sprintf("%v", this.IoGid) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -900,6 +920,44 @@ func (m *CreateOptions) Unmarshal(dAtA []byte) error {
} }
m.ShimCgroup = string(dAtA[iNdEx:postIndex]) m.ShimCgroup = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 10:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field IoUid", wireType)
}
m.IoUid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.IoUid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 11:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field IoGid", wireType)
}
m.IoGid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunc
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.IoGid |= (uint32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRunc(dAtA[iNdEx:]) skippy, err := skipRunc(dAtA[iNdEx:])
@ -1239,35 +1297,36 @@ func init() {
} }
var fileDescriptorRunc = []byte{ var fileDescriptorRunc = []byte{
// 467 bytes of a gzipped FileDescriptorProto // 495 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x93, 0x41, 0x6f, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x93, 0x31, 0x6f, 0xd3, 0x40,
0x10, 0x85, 0xbb, 0x6d, 0x69, 0x9d, 0x4d, 0x53, 0x60, 0xa1, 0x92, 0x29, 0xc2, 0x84, 0x08, 0xa4, 0x14, 0xc7, 0x7b, 0xb4, 0x4d, 0x9c, 0x4b, 0x53, 0xe0, 0x20, 0xd2, 0x51, 0x84, 0x09, 0x11, 0x48,
0x70, 0x49, 0x24, 0xb8, 0x20, 0xb8, 0x91, 0x23, 0x50, 0x2a, 0x03, 0x17, 0x2e, 0x2b, 0x77, 0x33, 0x61, 0x49, 0x24, 0x58, 0x10, 0x6c, 0x64, 0x60, 0x00, 0x4a, 0x65, 0xe8, 0xc2, 0x72, 0x72, 0xcf,
0x24, 0xab, 0xd8, 0x33, 0xab, 0xdd, 0x35, 0x75, 0x6e, 0xfc, 0x02, 0x7e, 0x57, 0x8f, 0x88, 0x13, 0x87, 0xf3, 0x94, 0xf8, 0xde, 0xe9, 0xee, 0x4c, 0x93, 0xad, 0x9f, 0x80, 0xcf, 0xd5, 0x91, 0x91,
0x47, 0x9a, 0x3f, 0x02, 0xf2, 0xda, 0x2e, 0x5c, 0xb9, 0x72, 0x7b, 0xf3, 0xbd, 0xb1, 0xe7, 0xe9, 0x91, 0xe6, 0x8b, 0x80, 0x7c, 0xb6, 0x0b, 0x2b, 0x2b, 0xdb, 0xff, 0xfd, 0xfe, 0xcf, 0x7e, 0x4f,
0x49, 0xcb, 0x9f, 0x2f, 0xb4, 0x5f, 0x96, 0x67, 0x13, 0x45, 0xc5, 0x54, 0x11, 0xfa, 0x4c, 0x23, 0xff, 0xd3, 0xa3, 0x2f, 0x73, 0xf0, 0x8b, 0xf2, 0x6c, 0x2a, 0xb1, 0x98, 0x49, 0xd4, 0x3e, 0x05,
0xd8, 0xf9, 0xdf, 0x32, 0xd7, 0x58, 0x56, 0x53, 0x5b, 0xa2, 0x22, 0xe3, 0x5d, 0x10, 0x13, 0x63, 0xad, 0x6c, 0xf6, 0xb7, 0x5c, 0x81, 0x2e, 0xd7, 0x33, 0x5b, 0x6a, 0x89, 0xc6, 0xbb, 0x20, 0xa6,
0xc9, 0x93, 0x38, 0xfa, 0xb3, 0x35, 0x09, 0x5b, 0x93, 0xda, 0x3c, 0xbe, 0xbd, 0xa0, 0x05, 0x85, 0xc6, 0xa2, 0x47, 0x36, 0xfc, 0xd3, 0x35, 0x0d, 0x5d, 0xd3, 0xca, 0x3c, 0xba, 0x9b, 0x63, 0x8e,
0x8d, 0x69, 0xad, 0x9a, 0xe5, 0xd1, 0x57, 0xc6, 0xfb, 0x69, 0x89, 0xea, 0xad, 0xf1, 0x9a, 0xd0, 0xa1, 0x63, 0x56, 0xa9, 0xba, 0x79, 0xfc, 0x8d, 0xd0, 0x7e, 0x52, 0x6a, 0xf9, 0xc1, 0x78, 0x40,
0x89, 0x98, 0xef, 0xdb, 0x12, 0xbd, 0x2e, 0x20, 0x66, 0x43, 0x36, 0xee, 0xa5, 0xdd, 0x28, 0x1e, 0xed, 0x18, 0xa7, 0x5d, 0x5b, 0x6a, 0x0f, 0x85, 0xe2, 0x64, 0x44, 0x26, 0xbd, 0xa4, 0x2d, 0xd9,
0xf0, 0x83, 0x56, 0x4a, 0x4b, 0xe4, 0xe3, 0xed, 0x60, 0xf7, 0x5b, 0x96, 0x12, 0x79, 0x71, 0x97, 0x23, 0x7a, 0xd0, 0x48, 0x61, 0x11, 0x3d, 0xbf, 0x11, 0xec, 0x7e, 0xc3, 0x12, 0x44, 0xcf, 0xee,
0xf7, 0x94, 0xd5, 0xa5, 0x34, 0x99, 0x5f, 0xc6, 0x3b, 0xc1, 0x8f, 0x6a, 0x70, 0x9a, 0xf9, 0xa5, 0xd3, 0x9e, 0xb4, 0x50, 0x0a, 0x93, 0xfa, 0x05, 0xdf, 0x0d, 0x7e, 0x54, 0x81, 0x93, 0xd4, 0x2f,
0x78, 0xc4, 0x0f, 0xdd, 0xda, 0x79, 0x28, 0xe6, 0x52, 0x2d, 0x2c, 0x95, 0x26, 0xde, 0x1d, 0xb2, 0xd8, 0x13, 0x7a, 0xe8, 0x36, 0xce, 0xab, 0x22, 0x13, 0x32, 0xb7, 0x58, 0x1a, 0xbe, 0x37, 0x22,
0x71, 0x94, 0x0e, 0x5a, 0x3a, 0x0b, 0x70, 0xf4, 0x7d, 0x9b, 0x0f, 0x66, 0x16, 0x32, 0x0f, 0x5d, 0x93, 0x28, 0x19, 0x34, 0x74, 0x1e, 0xe0, 0xf8, 0x62, 0x97, 0x0e, 0xe6, 0x56, 0xa5, 0x5e, 0xb5,
0xa4, 0x11, 0x1f, 0x20, 0x49, 0xa3, 0x3f, 0x93, 0x6f, 0x2e, 0xb3, 0xf0, 0x5d, 0x1f, 0xe9, 0xb4, 0x2b, 0x8d, 0xe9, 0x40, 0xa3, 0x30, 0xf0, 0x15, 0x7d, 0x3d, 0x99, 0x84, 0xef, 0xfa, 0x1a, 0x4f,
0x66, 0xe1, 0xf2, 0x1d, 0x1e, 0x91, 0x01, 0x94, 0x5e, 0x99, 0x10, 0x2c, 0x4a, 0xf7, 0xeb, 0xf9, 0x2a, 0x16, 0x26, 0xdf, 0xa3, 0x11, 0x1a, 0xa5, 0x85, 0x97, 0x26, 0x2c, 0x16, 0x25, 0xdd, 0xaa,
0xbd, 0x32, 0xe2, 0x09, 0x3f, 0x82, 0xca, 0x83, 0xc5, 0x2c, 0x97, 0x25, 0xea, 0x4a, 0x3a, 0x52, 0xfe, 0x24, 0x0d, 0x7b, 0x46, 0x87, 0x6a, 0xed, 0x95, 0xd5, 0xe9, 0x4a, 0x94, 0x1a, 0xd6, 0xc2,
0x2b, 0xf0, 0x2e, 0x04, 0x8c, 0xd2, 0x5b, 0x9d, 0xf9, 0x01, 0x75, 0xf5, 0xae, 0xb1, 0xc4, 0x31, 0xa1, 0x5c, 0x2a, 0xef, 0xc2, 0x82, 0x51, 0x72, 0xa7, 0x35, 0x4f, 0x35, 0xac, 0x3f, 0xd6, 0x16,
0x8f, 0x3c, 0xd8, 0x42, 0x63, 0x96, 0xb7, 0x29, 0xaf, 0x66, 0x71, 0x8f, 0xf3, 0x4f, 0x3a, 0x07, 0x3b, 0xa2, 0x91, 0x57, 0xb6, 0x00, 0x9d, 0xae, 0x9a, 0x2d, 0xaf, 0x6b, 0xf6, 0x80, 0xd2, 0x2f,
0x99, 0x93, 0x5a, 0xb9, 0xf8, 0x5a, 0x70, 0x7b, 0x35, 0x79, 0x5d, 0x03, 0xf1, 0x98, 0xdf, 0x80, 0xb0, 0x52, 0x62, 0x85, 0x72, 0xe9, 0xf8, 0x7e, 0x70, 0x7b, 0x15, 0x79, 0x57, 0x01, 0xf6, 0x94,
0xc2, 0xf8, 0xb5, 0xc4, 0xac, 0x00, 0x67, 0x32, 0x05, 0x2e, 0xde, 0x1b, 0xee, 0x8c, 0x7b, 0xe9, 0xde, 0x52, 0x85, 0xf1, 0x1b, 0xa1, 0xd3, 0x42, 0x39, 0x93, 0x4a, 0xe5, 0x78, 0x67, 0xb4, 0x3b,
0xf5, 0xc0, 0x4f, 0xae, 0x70, 0xdd, 0x68, 0xd3, 0x84, 0x93, 0x05, 0xcd, 0x21, 0xde, 0x6f, 0x1a, 0xe9, 0x25, 0x37, 0x03, 0x3f, 0xbe, 0xc6, 0x55, 0xa2, 0x75, 0x12, 0x4e, 0x14, 0x98, 0x29, 0xde,
0x6d, 0xd9, 0x1b, 0x9a, 0x83, 0x78, 0xc8, 0x0f, 0x91, 0x24, 0xc2, 0xb9, 0x5c, 0xc1, 0xda, 0x6a, 0xad, 0x13, 0x6d, 0xd8, 0x7b, 0xcc, 0x14, 0x7b, 0x4c, 0x0f, 0x35, 0x0a, 0xad, 0xce, 0xc5, 0x52,
0x5c, 0xc4, 0x51, 0x38, 0x78, 0x80, 0x74, 0x02, 0xe7, 0xaf, 0x1a, 0x26, 0xee, 0xf3, 0xbe, 0x5b, 0x6d, 0x2c, 0xe8, 0x9c, 0x47, 0x61, 0xe0, 0x81, 0xc6, 0x63, 0x75, 0xfe, 0xb6, 0x66, 0xec, 0x21,
0xea, 0xa2, 0xeb, 0xb5, 0x17, 0xfe, 0xc3, 0x6b, 0xd4, 0x96, 0xfa, 0x8b, 0xf1, 0x9b, 0xb3, 0x25, 0xed, 0xbb, 0x05, 0x14, 0x6d, 0xae, 0xbd, 0xf0, 0x1f, 0x5a, 0xa1, 0x3a, 0x54, 0x36, 0xa4, 0x1d,
0xa8, 0x95, 0x21, 0x8d, 0xbe, 0x2b, 0x56, 0xf0, 0x5d, 0xa8, 0x74, 0xd7, 0x67, 0xd0, 0xff, 0x6b, 0x40, 0x51, 0x42, 0xc6, 0xe9, 0x88, 0x4c, 0x06, 0xc9, 0x3e, 0xe0, 0x29, 0x64, 0x0d, 0xce, 0x21,
0x91, 0x2f, 0xd3, 0x8b, 0xcb, 0x64, 0xeb, 0xc7, 0x65, 0xb2, 0xf5, 0x65, 0x93, 0xb0, 0x8b, 0x4d, 0xe3, 0xfd, 0x16, 0xbf, 0x81, 0x6c, 0xfc, 0x8b, 0xd0, 0xdb, 0xf3, 0x85, 0x92, 0x4b, 0x83, 0xa0,
0xc2, 0xbe, 0x6d, 0x12, 0xf6, 0x73, 0x93, 0xb0, 0x8f, 0xcf, 0xfe, 0xf1, 0xa9, 0xbd, 0xe8, 0xc4, 0x7d, 0xfb, 0x0c, 0x8c, 0xee, 0xa9, 0x35, 0xb4, 0xe9, 0x07, 0xfd, 0xbf, 0xc6, 0xfe, 0x3a, 0xb9,
0xd9, 0x5e, 0x78, 0x42, 0x4f, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xe6, 0x26, 0x29, 0x60, 0xad, 0xbc, 0x8a, 0x77, 0x7e, 0x5c, 0xc5, 0x3b, 0x17, 0xdb, 0x98, 0x5c, 0x6e, 0x63, 0xf2, 0x7d, 0x1b,
0x03, 0x00, 0x00, 0x93, 0x9f, 0xdb, 0x98, 0x7c, 0x7e, 0xf1, 0x8f, 0x87, 0xf9, 0xaa, 0x15, 0x67, 0x9d, 0x70, 0x70,
0xcf, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xbb, 0xf0, 0x6c, 0xdb, 0x03, 0x00, 0x00,
} }

View File

@ -23,6 +23,8 @@ message CreateOptions {
string cgroups_mode = 7; string cgroups_mode = 7;
bool no_new_keyring = 8; bool no_new_keyring = 8;
string shim_cgroup = 9; string shim_cgroup = 9;
uint32 io_uid = 10;
uint32 io_gid = 11;
} }
message CheckpointOptions { message CheckpointOptions {

View File

@ -17,9 +17,14 @@ func WithTransactionContext(ctx context.Context, tx *bolt.Tx) context.Context {
return context.WithValue(ctx, transactionKey{}, tx) return context.WithValue(ctx, transactionKey{}, tx)
} }
type transactor interface {
View(fn func(*bolt.Tx) error) error
Update(fn func(*bolt.Tx) error) error
}
// view gets a bolt db transaction either from the context // view gets a bolt db transaction either from the context
// or starts a new one with the provided bolt database. // or starts a new one with the provided bolt database.
func view(ctx context.Context, db *bolt.DB, fn func(*bolt.Tx) error) error { func view(ctx context.Context, db transactor, fn func(*bolt.Tx) error) error {
tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx) tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx)
if !ok { if !ok {
return db.View(fn) return db.View(fn)
@ -29,7 +34,7 @@ func view(ctx context.Context, db *bolt.DB, fn func(*bolt.Tx) error) error {
// update gets a writable bolt db transaction either from the context // update gets a writable bolt db transaction either from the context
// or starts a new one with the provided bolt database. // or starts a new one with the provided bolt database.
func update(ctx context.Context, db *bolt.DB, fn func(*bolt.Tx) error) error { func update(ctx context.Context, db transactor, fn func(*bolt.Tx) error) error {
tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx) tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx)
if !ok { if !ok {
return db.Update(fn) return db.Update(fn)

View File

@ -28,7 +28,8 @@ import (
// key: object-specific key identifying the storage bucket for the objects // key: object-specific key identifying the storage bucket for the objects
// contents. // contents.
var ( var (
bucketKeyVersion = []byte("v1") bucketKeyVersion = []byte(schemaVersion)
bucketKeyDBVersion = []byte("version") // stores the version of the schema
bucketKeyObjectLabels = []byte("labels") // stores the labels for a namespace. bucketKeyObjectLabels = []byte("labels") // stores the labels for a namespace.
bucketKeyObjectIndexes = []byte("indexes") // reserved bucketKeyObjectIndexes = []byte("indexes") // reserved
bucketKeyObjectImages = []byte("images") // stores image objects bucketKeyObjectImages = []byte("images") // stores image objects
@ -37,6 +38,7 @@ var (
bucketKeyObjectContent = []byte("content") // stores content references bucketKeyObjectContent = []byte("content") // stores content references
bucketKeyObjectBlob = []byte("blob") // stores content links bucketKeyObjectBlob = []byte("blob") // stores content links
bucketKeyObjectIngest = []byte("ingest") // stores ingest links bucketKeyObjectIngest = []byte("ingest") // stores ingest links
bucketKeyObjectLeases = []byte("leases") // stores leases
bucketKeyDigest = []byte("digest") bucketKeyDigest = []byte("digest")
bucketKeyMediaType = []byte("mediatype") bucketKeyMediaType = []byte("mediatype")
@ -45,11 +47,14 @@ var (
bucketKeyRuntime = []byte("runtime") bucketKeyRuntime = []byte("runtime")
bucketKeyName = []byte("name") bucketKeyName = []byte("name")
bucketKeyParent = []byte("parent") bucketKeyParent = []byte("parent")
bucketKeyChildren = []byte("children")
bucketKeyOptions = []byte("options") bucketKeyOptions = []byte("options")
bucketKeySpec = []byte("spec") bucketKeySpec = []byte("spec")
bucketKeySnapshotKey = []byte("snapshotKey") bucketKeySnapshotKey = []byte("snapshotKey")
bucketKeySnapshotter = []byte("snapshotter") bucketKeySnapshotter = []byte("snapshotter")
bucketKeyTarget = []byte("target") bucketKeyTarget = []byte("target")
bucketKeyExtensions = []byte("extensions")
bucketKeyCreatedAt = []byte("createdat")
) )
func getBucket(tx *bolt.Tx, keys ...[]byte) *bolt.Bucket { func getBucket(tx *bolt.Tx, keys ...[]byte) *bolt.Bucket {

View File

@ -10,6 +10,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/filters" "github.com/containerd/containerd/filters"
"github.com/containerd/containerd/identifiers" "github.com/containerd/containerd/identifiers"
"github.com/containerd/containerd/labels"
"github.com/containerd/containerd/metadata/boltutil" "github.com/containerd/containerd/metadata/boltutil"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
@ -21,6 +22,7 @@ type containerStore struct {
tx *bolt.Tx tx *bolt.Tx
} }
// NewContainerStore returns a Store backed by an underlying bolt DB
func NewContainerStore(tx *bolt.Tx) containers.Store { func NewContainerStore(tx *bolt.Tx) containers.Store {
return &containerStore{ return &containerStore{
tx: tx, tx: tx,
@ -146,7 +148,7 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai
if len(fieldpaths) == 0 { if len(fieldpaths) == 0 {
// only allow updates to these field on full replace. // only allow updates to these field on full replace.
fieldpaths = []string{"labels", "spec"} fieldpaths = []string{"labels", "spec", "extensions"}
// Fields that are immutable must cause an error when no field paths // Fields that are immutable must cause an error when no field paths
// are provided. This allows these fields to become mutable in the // are provided. This allows these fields to become mutable in the
@ -181,11 +183,22 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai
continue continue
} }
if strings.HasPrefix(path, "extensions.") {
if updated.Extensions == nil {
updated.Extensions = map[string]types.Any{}
}
key := strings.TrimPrefix(path, "extensions.")
updated.Extensions[key] = container.Extensions[key]
continue
}
switch path { switch path {
case "labels": case "labels":
updated.Labels = container.Labels updated.Labels = container.Labels
case "spec": case "spec":
updated.Spec = container.Spec updated.Spec = container.Spec
case "extensions":
updated.Extensions = container.Extensions
default: default:
return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on %q", path, container.ID) return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on %q", path, container.ID)
} }
@ -226,7 +239,19 @@ func validateContainer(container *containers.Container) error {
return errors.Wrapf(err, "container.ID validation error") return errors.Wrapf(err, "container.ID validation error")
} }
// labels and image have no validation for k := range container.Extensions {
if k == "" {
return errors.Wrapf(errdefs.ErrInvalidArgument, "container.Extension keys must not be zero-length")
}
}
// image has no validation
for k, v := range container.Labels {
if err := labels.Validate(k, v); err == nil {
return errors.Wrapf(err, "containers.Labels")
}
}
if container.Runtime.Name == "" { if container.Runtime.Name == "" {
return errors.Wrapf(errdefs.ErrInvalidArgument, "container.Runtime.Name must be set") return errors.Wrapf(errdefs.ErrInvalidArgument, "container.Runtime.Name must be set")
} }
@ -288,6 +313,27 @@ func readContainer(container *containers.Container, bkt *bolt.Bucket) error {
container.SnapshotKey = string(v) container.SnapshotKey = string(v)
case string(bucketKeySnapshotter): case string(bucketKeySnapshotter):
container.Snapshotter = string(v) container.Snapshotter = string(v)
case string(bucketKeyExtensions):
ebkt := bkt.Bucket(bucketKeyExtensions)
if ebkt == nil {
return nil
}
extensions := make(map[string]types.Any)
if err := ebkt.ForEach(func(k, v []byte) error {
var a types.Any
if err := proto.Unmarshal(v, &a); err != nil {
return err
}
extensions[string(k)] = a
return nil
}); err != nil {
return err
}
container.Extensions = extensions
} }
return nil return nil
@ -335,6 +381,24 @@ func writeContainer(bkt *bolt.Bucket, container *containers.Container) error {
return err return err
} }
if len(container.Extensions) > 0 {
ebkt, err := bkt.CreateBucketIfNotExists(bucketKeyExtensions)
if err != nil {
return err
}
for name, ext := range container.Extensions {
p, err := proto.Marshal(&ext)
if err != nil {
return err
}
if err := ebkt.Put([]byte(name), p); err != nil {
return err
}
}
}
if container.Runtime.Options != nil { if container.Runtime.Options != nil {
data, err := proto.Marshal(container.Runtime.Options) data, err := proto.Marshal(container.Runtime.Options)
if err != nil { if err != nil {

View File

@ -4,12 +4,15 @@ import (
"context" "context"
"encoding/binary" "encoding/binary"
"strings" "strings"
"sync"
"time" "time"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/filters" "github.com/containerd/containerd/filters"
"github.com/containerd/containerd/labels"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/metadata/boltutil" "github.com/containerd/containerd/metadata/boltutil"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
@ -18,12 +21,13 @@ import (
type contentStore struct { type contentStore struct {
content.Store content.Store
db *bolt.DB db *DB
l sync.RWMutex
} }
// NewContentStore returns a namespaced content store using an existing // newContentStore returns a namespaced content store using an existing
// content store interface. // content store interface.
func NewContentStore(db *bolt.DB, cs content.Store) content.Store { func newContentStore(db *DB, cs content.Store) *contentStore {
return &contentStore{ return &contentStore{
Store: cs, Store: cs,
db: db, db: db,
@ -58,6 +62,9 @@ func (cs *contentStore) Update(ctx context.Context, info content.Info, fieldpath
return content.Info{}, err return content.Info{}, err
} }
cs.l.RLock()
defer cs.l.RUnlock()
updated := content.Info{ updated := content.Info{
Digest: info.Digest, Digest: info.Digest,
} }
@ -94,6 +101,9 @@ func (cs *contentStore) Update(ctx context.Context, info content.Info, fieldpath
// Set mutable fields // Set mutable fields
updated.Labels = info.Labels updated.Labels = info.Labels
} }
if err := validateInfo(&updated); err != nil {
return err
}
updated.UpdatedAt = time.Now().UTC() updated.UpdatedAt = time.Now().UTC()
return writeInfo(&updated, bkt) return writeInfo(&updated, bkt)
@ -162,15 +172,25 @@ func (cs *contentStore) Delete(ctx context.Context, dgst digest.Digest) error {
return err return err
} }
cs.l.RLock()
defer cs.l.RUnlock()
return update(ctx, cs.db, func(tx *bolt.Tx) error { return update(ctx, cs.db, func(tx *bolt.Tx) error {
bkt := getBlobBucket(tx, ns, dgst) bkt := getBlobBucket(tx, ns, dgst)
if bkt == nil { if bkt == nil {
return errors.Wrapf(errdefs.ErrNotFound, "content digest %v", dgst) return errors.Wrapf(errdefs.ErrNotFound, "content digest %v", dgst)
} }
// Just remove local reference, garbage collector is responsible for if err := getBlobsBucket(tx, ns).DeleteBucket([]byte(dgst.String())); err != nil {
// cleaning up on disk content return err
return getBlobsBucket(tx, ns).DeleteBucket([]byte(dgst.String())) }
// Mark content store as dirty for triggering garbage collection
cs.db.dirtyL.Lock()
cs.db.dirtyCS = true
cs.db.dirtyL.Unlock()
return nil
}) })
} }
@ -265,6 +285,9 @@ func (cs *contentStore) Abort(ctx context.Context, ref string) error {
return err return err
} }
cs.l.RLock()
defer cs.l.RUnlock()
return update(ctx, cs.db, func(tx *bolt.Tx) error { return update(ctx, cs.db, func(tx *bolt.Tx) error {
bkt := getIngestBucket(tx, ns) bkt := getIngestBucket(tx, ns)
if bkt == nil { if bkt == nil {
@ -289,6 +312,9 @@ func (cs *contentStore) Writer(ctx context.Context, ref string, size int64, expe
return nil, err return nil, err
} }
cs.l.RLock()
defer cs.l.RUnlock()
var w content.Writer var w content.Writer
if err := update(ctx, cs.db, func(tx *bolt.Tx) error { if err := update(ctx, cs.db, func(tx *bolt.Tx) error {
if expected != "" { if expected != "" {
@ -342,6 +368,7 @@ func (cs *contentStore) Writer(ctx context.Context, ref string, size int64, expe
ref: ref, ref: ref,
namespace: ns, namespace: ns,
db: cs.db, db: cs.db,
l: &cs.l,
}, nil }, nil
} }
@ -349,10 +376,14 @@ type namespacedWriter struct {
content.Writer content.Writer
ref string ref string
namespace string namespace string
db *bolt.DB db transactor
l *sync.RWMutex
} }
func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error { func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
nw.l.RLock()
defer nw.l.RUnlock()
return update(ctx, nw.db, func(tx *bolt.Tx) error { return update(ctx, nw.db, func(tx *bolt.Tx) error {
bkt := getIngestBucket(tx, nw.namespace) bkt := getIngestBucket(tx, nw.namespace)
if bkt != nil { if bkt != nil {
@ -360,23 +391,31 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig
return err return err
} }
} }
return nw.commit(ctx, tx, size, expected, opts...) dgst, err := nw.commit(ctx, tx, size, expected, opts...)
if err != nil {
return err
}
return addContentLease(ctx, tx, dgst)
}) })
} }
func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) error { func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) (digest.Digest, error) {
var base content.Info var base content.Info
for _, opt := range opts { for _, opt := range opts {
if err := opt(&base); err != nil { if err := opt(&base); err != nil {
return err return "", err
} }
} }
if err := validateInfo(&base); err != nil {
return "", err
}
status, err := nw.Writer.Status() status, err := nw.Writer.Status()
if err != nil { if err != nil {
return err return "", err
} }
if size != 0 && size != status.Offset { if size != 0 && size != status.Offset {
return errors.Errorf("%q failed size validation: %v != %v", nw.ref, status.Offset, size) return "", errors.Errorf("%q failed size validation: %v != %v", nw.ref, status.Offset, size)
} }
size = status.Offset size = status.Offset
@ -384,36 +423,32 @@ func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64,
if err := nw.Writer.Commit(ctx, size, expected); err != nil { if err := nw.Writer.Commit(ctx, size, expected); err != nil {
if !errdefs.IsAlreadyExists(err) { if !errdefs.IsAlreadyExists(err) {
return err return "", err
} }
if getBlobBucket(tx, nw.namespace, actual) != nil { if getBlobBucket(tx, nw.namespace, actual) != nil {
return errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual) return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
} }
} }
bkt, err := createBlobBucket(tx, nw.namespace, actual) bkt, err := createBlobBucket(tx, nw.namespace, actual)
if err != nil { if err != nil {
return err return "", err
} }
commitTime := time.Now().UTC() commitTime := time.Now().UTC()
sizeEncoded, err := encodeSize(size) sizeEncoded, err := encodeInt(size)
if err != nil { if err != nil {
return err return "", err
} }
if err := boltutil.WriteTimestamps(bkt, commitTime, commitTime); err != nil { if err := boltutil.WriteTimestamps(bkt, commitTime, commitTime); err != nil {
return err return "", err
} }
if err := boltutil.WriteLabels(bkt, base.Labels); err != nil { if err := boltutil.WriteLabels(bkt, base.Labels); err != nil {
return err return "", err
} }
if err := bkt.Put(bucketKeySize, sizeEncoded); err != nil { return actual, bkt.Put(bucketKeySize, sizeEncoded)
return err
}
return nil
} }
func (nw *namespacedWriter) Status() (content.Status, error) { func (nw *namespacedWriter) Status() (content.Status, error) {
@ -446,6 +481,16 @@ func (cs *contentStore) checkAccess(ctx context.Context, dgst digest.Digest) err
}) })
} }
func validateInfo(info *content.Info) error {
for k, v := range info.Labels {
if err := labels.Validate(k, v); err == nil {
return errors.Wrapf(err, "info.Labels")
}
}
return nil
}
func readInfo(info *content.Info, bkt *bolt.Bucket) error { func readInfo(info *content.Info, bkt *bolt.Bucket) error {
if err := boltutil.ReadTimestamps(bkt, &info.CreatedAt, &info.UpdatedAt); err != nil { if err := boltutil.ReadTimestamps(bkt, &info.CreatedAt, &info.UpdatedAt); err != nil {
return err return err
@ -474,14 +519,64 @@ func writeInfo(info *content.Info, bkt *bolt.Bucket) error {
} }
// Write size // Write size
sizeEncoded, err := encodeSize(info.Size) sizeEncoded, err := encodeInt(info.Size)
if err != nil { if err != nil {
return err return err
} }
if err := bkt.Put(bucketKeySize, sizeEncoded); err != nil { return bkt.Put(bucketKeySize, sizeEncoded)
}
func (cs *contentStore) garbageCollect(ctx context.Context) error {
lt1 := time.Now()
cs.l.Lock()
defer func() {
cs.l.Unlock()
log.G(ctx).WithField("t", time.Now().Sub(lt1)).Debugf("content garbage collected")
}()
seen := map[string]struct{}{}
if err := cs.db.View(func(tx *bolt.Tx) error {
v1bkt := tx.Bucket(bucketKeyVersion)
if v1bkt == nil {
return nil
}
// iterate through each namespace
v1c := v1bkt.Cursor()
for k, v := v1c.First(); k != nil; k, v = v1c.Next() {
if v != nil {
continue
}
cbkt := v1bkt.Bucket(k).Bucket(bucketKeyObjectContent)
if cbkt == nil {
continue
}
bbkt := cbkt.Bucket(bucketKeyObjectBlob)
if err := bbkt.ForEach(func(ck, cv []byte) error {
if cv == nil {
seen[string(ck)] = struct{}{}
}
return nil
}); err != nil {
return err
}
}
return nil
}); err != nil {
return err return err
} }
return nil return cs.Store.Walk(ctx, func(info content.Info) error {
if _, ok := seen[info.Digest.String()]; !ok {
if err := cs.Store.Delete(ctx, info.Digest); err != nil {
return err
}
log.G(ctx).WithField("digest", info.Digest).Debug("removed content")
}
return nil
})
} }

328
vendor/github.com/containerd/containerd/metadata/db.go generated vendored Normal file
View File

@ -0,0 +1,328 @@
package metadata
import (
"context"
"encoding/binary"
"strings"
"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/snapshot"
"github.com/pkg/errors"
)
const (
// schemaVersion represents the schema version of
// the database. This schema version represents the
// structure of the data in the database. The schema
// can envolve at any time but any backwards
// incompatible changes or structural changes require
// bumping the schema version.
schemaVersion = "v1"
// dbVersion represents updates to the schema
// version which are additions and compatible with
// prior version of the same schema.
dbVersion = 1
)
// DB represents a metadata database backed by a bolt
// database. The database is fully namespaced and stores
// image, container, namespace, snapshot, and content data
// while proxying data shared across namespaces to backend
// datastores for content and snapshots.
type DB struct {
db *bolt.DB
ss map[string]*snapshotter
cs *contentStore
// wlock is used to protect access to the data structures during garbage
// collection. While the wlock is held no writable transactions can be
// opened, preventing changes from occurring between the mark and
// sweep phases without preventing read transactions.
wlock sync.RWMutex
// dirty flags and lock keeps track of datastores which have had deletions
// since the last garbage collection. These datastores will will be garbage
// collected during the next garbage collection.
dirtyL sync.Mutex
dirtySS map[string]struct{}
dirtyCS bool
// TODO: Keep track of stats such as pause time, number of collected objects, errors
lastCollection time.Time
}
// NewDB creates a new metadata database using the provided
// bolt database, content store, and snapshotters.
func NewDB(db *bolt.DB, cs content.Store, ss map[string]snapshot.Snapshotter) *DB {
m := &DB{
db: db,
ss: make(map[string]*snapshotter, len(ss)),
dirtySS: map[string]struct{}{},
}
// Initialize data stores
m.cs = newContentStore(m, cs)
for name, sn := range ss {
m.ss[name] = newSnapshotter(m, name, sn)
}
return m
}
// Init ensures the database is at the correct version
// and performs any needed migrations.
func (m *DB) Init(ctx context.Context) error {
// errSkip is used when no migration or version needs to be written
// to the database and the transaction can be immediately rolled
// back rather than performing a much slower and unnecessary commit.
var errSkip = errors.New("skip update")
err := m.db.Update(func(tx *bolt.Tx) error {
var (
// current schema and version
schema = "v0"
version = 0
)
// i represents the index of the first migration
// which must be run to get the database up to date.
// The migration's version will be checked in reverse
// order, decrementing i for each migration which
// represents a version newer than the current
// database version
i := len(migrations)
for ; i > 0; i-- {
migration := migrations[i-1]
bkt := tx.Bucket([]byte(migration.schema))
if bkt == nil {
// Hasn't encountered another schema, go to next migration
if schema == "v0" {
continue
}
break
}
if schema == "v0" {
schema = migration.schema
vb := bkt.Get(bucketKeyDBVersion)
if vb != nil {
v, _ := binary.Varint(vb)
version = int(v)
}
}
if version >= migration.version {
break
}
}
// Previous version fo database found
if schema != "v0" {
updates := migrations[i:]
// No migration updates, return immediately
if len(updates) == 0 {
return errSkip
}
for _, m := range updates {
t0 := time.Now()
if err := m.migrate(tx); err != nil {
return errors.Wrapf(err, "failed to migrate to %s.%d", m.schema, m.version)
}
log.G(ctx).WithField("d", time.Now().Sub(t0)).Debugf("database migration to %s.%d finished", m.schema, m.version)
}
}
bkt, err := tx.CreateBucketIfNotExists(bucketKeyVersion)
if err != nil {
return err
}
versionEncoded, err := encodeInt(dbVersion)
if err != nil {
return err
}
return bkt.Put(bucketKeyDBVersion, versionEncoded)
})
if err == errSkip {
err = nil
}
return err
}
// ContentStore returns a namespaced content store
// proxied to a content store.
func (m *DB) ContentStore() content.Store {
if m.cs == nil {
return nil
}
return m.cs
}
// Snapshotter returns a namespaced content store for
// the requested snapshotter name proxied to a snapshotter.
func (m *DB) Snapshotter(name string) snapshot.Snapshotter {
sn, ok := m.ss[name]
if !ok {
return nil
}
return sn
}
// View runs a readonly transaction on the metadata store.
func (m *DB) View(fn func(*bolt.Tx) error) error {
return m.db.View(fn)
}
// Update runs a writable transation on the metadata store.
func (m *DB) Update(fn func(*bolt.Tx) error) error {
m.wlock.RLock()
defer m.wlock.RUnlock()
return m.db.Update(fn)
}
// GarbageCollect starts garbage collection
func (m *DB) GarbageCollect(ctx context.Context) error {
lt1 := time.Now()
m.wlock.Lock()
defer func() {
m.wlock.Unlock()
log.G(ctx).WithField("d", time.Now().Sub(lt1)).Debug("metadata garbage collected")
}()
marked, err := m.getMarked(ctx)
if err != nil {
return err
}
m.dirtyL.Lock()
defer m.dirtyL.Unlock()
if err := m.db.Update(func(tx *bolt.Tx) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
rm := func(ctx context.Context, n gc.Node) error {
if _, ok := marked[n]; ok {
return nil
}
if n.Type == ResourceSnapshot {
if idx := strings.IndexRune(n.Key, '/'); idx > 0 {
m.dirtySS[n.Key[:idx]] = struct{}{}
}
} else if n.Type == ResourceContent {
m.dirtyCS = true
}
return remove(ctx, tx, n)
}
if err := scanAll(ctx, tx, rm); err != nil {
return errors.Wrap(err, "failed to scan and remove")
}
return nil
}); err != nil {
return err
}
m.lastCollection = time.Now()
if len(m.dirtySS) > 0 {
for snapshotterName := range m.dirtySS {
log.G(ctx).WithField("snapshotter", snapshotterName).Debug("scheduling snapshotter cleanup")
go m.cleanupSnapshotter(snapshotterName)
}
m.dirtySS = map[string]struct{}{}
}
if m.dirtyCS {
log.G(ctx).Debug("scheduling content cleanup")
go m.cleanupContent()
m.dirtyCS = false
}
return nil
}
func (m *DB) getMarked(ctx context.Context) (map[gc.Node]struct{}, error) {
var marked map[gc.Node]struct{}
if err := m.db.View(func(tx *bolt.Tx) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
var (
nodes []gc.Node
wg sync.WaitGroup
roots = make(chan gc.Node)
)
wg.Add(1)
go func() {
defer wg.Done()
for n := range roots {
nodes = append(nodes, n)
}
}()
// Call roots
if err := scanRoots(ctx, tx, roots); err != nil {
cancel()
return err
}
close(roots)
wg.Wait()
refs := func(n gc.Node) ([]gc.Node, error) {
var sn []gc.Node
if err := references(ctx, tx, n, func(nn gc.Node) {
sn = append(sn, nn)
}); err != nil {
return nil, err
}
return sn, nil
}
reachable, err := gc.Tricolor(nodes, refs)
if err != nil {
return err
}
marked = reachable
return nil
}); err != nil {
return nil, err
}
return marked, nil
}
func (m *DB) cleanupSnapshotter(name string) {
ctx := context.Background()
sn, ok := m.ss[name]
if !ok {
return
}
err := sn.garbageCollect(ctx)
if err != nil {
log.G(ctx).WithError(err).WithField("snapshotter", name).Warn("garbage collection failed")
}
}
func (m *DB) cleanupContent() {
ctx := context.Background()
if m.cs == nil {
return
}
err := m.cs.garbageCollect(ctx)
if err != nil {
log.G(ctx).WithError(err).Warn("content garbage collection failed")
}
}

Some files were not shown because too many files have changed in this diff Show More