Browse code

Update containerd client and dependencies to v1.2.0-rc.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2018/09/28 00:37:58
Showing 89 changed files
... ...
@@ -1,6 +1,6 @@
1 1
 # the following lines are in sorted order, FYI
2 2
 github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
3
-github.com/Microsoft/hcsshim v0.7.3
3
+github.com/Microsoft/hcsshim v0.7.6
4 4
 github.com/Microsoft/go-winio v0.4.11
5 5
 github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
6 6
 github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
... ...
@@ -75,7 +75,7 @@ github.com/pborman/uuid v1.0
75 75
 google.golang.org/grpc v1.12.0
76 76
 
77 77
 # This does not need to match RUNC_COMMIT as it is used for helper packages but should be newer or equal
78
-github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
78
+github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
79 79
 github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
80 80
 github.com/opencontainers/image-spec v1.0.1
81 81
 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
... ...
@@ -114,14 +114,15 @@ github.com/googleapis/gax-go v2.0.0
114 114
 google.golang.org/genproto 694d95ba50e67b2e363f3483057db5d4910c18f9
115 115
 
116 116
 # containerd
117
-github.com/containerd/containerd d97a907f7f781c0ab8340877d8e6b53cc7f1c2f6
117
+github.com/containerd/containerd 0c5f8f63c3368856c320ae8a1c125e703b73b51d # v1.2.0-rc.1
118 118
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
119
-github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
119
+github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
120 120
 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
121 121
 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
122
+github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch
122 123
 github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
123 124
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
124
-github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
125
+github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
125 126
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
126 127
 
127 128
 # cluster
... ...
@@ -6,6 +6,8 @@ import (
6 6
 
7 7
 // HNSEndpoint represents a network endpoint in HNS
8 8
 type HNSEndpoint = hns.HNSEndpoint
9
+// Namespace represents a Compartment.
10
+type Namespace = hns.Namespace
9 11
 
10 12
 //SystemType represents the type of the system on which actions are done
11 13
 type SystemType string
... ...
@@ -9,15 +9,15 @@ import (
9 9
 // the parent layer provided.
10 10
 func CreateLayer(path, parent string) error {
11 11
 	title := "hcsshim::CreateLayer "
12
-	logrus.Debugf(title+"Flavour %d ID %s parent %s", path, parent)
12
+	logrus.Debugf(title+"ID %s parent %s", path, parent)
13 13
 
14 14
 	err := createLayer(&stdDriverInfo, path, parent)
15 15
 	if err != nil {
16
-		err = hcserror.Errorf(err, title, "path=%s parent=%s flavour=%d", path, parent)
16
+		err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent)
17 17
 		logrus.Error(err)
18 18
 		return err
19 19
 	}
20 20
 
21
-	logrus.Debugf(title+" - succeeded path=%s parent=%s flavour=%d", path, parent)
21
+	logrus.Debugf(title+"- succeeded path=%s parent=%s", path, parent)
22 22
 	return nil
23 23
 }
... ...
@@ -443,7 +443,7 @@ type ContentClient interface {
443 443
 	// Only one active stream may exist at a time for each ref.
444 444
 	//
445 445
 	// Once a write stream has started, it may only write to a single ref, thus
446
-	// once a stream is started, the ref may be ommitted on subsequent writes.
446
+	// once a stream is started, the ref may be omitted on subsequent writes.
447 447
 	//
448 448
 	// For any write transaction represented by a ref, only a single write may
449 449
 	// be made to a given offset. If overlapping writes occur, it is an error.
... ...
@@ -658,7 +658,7 @@ type ContentServer interface {
658 658
 	// Only one active stream may exist at a time for each ref.
659 659
 	//
660 660
 	// Once a write stream has started, it may only write to a single ref, thus
661
-	// once a stream is started, the ref may be ommitted on subsequent writes.
661
+	// once a stream is started, the ref may be omitted on subsequent writes.
662 662
 	//
663 663
 	// For any write transaction represented by a ref, only a single write may
664 664
 	// be made to a given offset. If overlapping writes occur, it is an error.
... ...
@@ -55,7 +55,7 @@ service Content {
55 55
 	// Only one active stream may exist at a time for each ref.
56 56
 	//
57 57
 	// Once a write stream has started, it may only write to a single ref, thus
58
-	// once a stream is started, the ref may be ommitted on subsequent writes.
58
+	// once a stream is started, the ref may be omitted on subsequent writes.
59 59
 	//
60 60
 	// For any write transaction represented by a ref, only a single write may
61 61
 	// be made to a given offset. If overlapping writes occur, it is an error.
... ...
@@ -20,9 +20,15 @@ import (
20 20
 	"bufio"
21 21
 	"bytes"
22 22
 	"compress/gzip"
23
+	"context"
23 24
 	"fmt"
24 25
 	"io"
26
+	"os"
27
+	"os/exec"
28
+	"strconv"
25 29
 	"sync"
30
+
31
+	"github.com/containerd/containerd/log"
26 32
 )
27 33
 
28 34
 type (
... ...
@@ -37,6 +43,13 @@ const (
37 37
 	Gzip
38 38
 )
39 39
 
40
+const disablePigzEnv = "CONTAINERD_DISABLE_PIGZ"
41
+
42
+var (
43
+	initPigz   sync.Once
44
+	unpigzPath string
45
+)
46
+
40 47
 var (
41 48
 	bufioReader32KPool = &sync.Pool{
42 49
 		New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) },
... ...
@@ -79,6 +92,36 @@ func (w *writeCloserWrapper) Close() error {
79 79
 	return nil
80 80
 }
81 81
 
82
+type bufferedReader struct {
83
+	buf *bufio.Reader
84
+}
85
+
86
+func newBufferedReader(r io.Reader) *bufferedReader {
87
+	buf := bufioReader32KPool.Get().(*bufio.Reader)
88
+	buf.Reset(r)
89
+	return &bufferedReader{buf}
90
+}
91
+
92
+func (r *bufferedReader) Read(p []byte) (n int, err error) {
93
+	if r.buf == nil {
94
+		return 0, io.EOF
95
+	}
96
+	n, err = r.buf.Read(p)
97
+	if err == io.EOF {
98
+		r.buf.Reset(nil)
99
+		bufioReader32KPool.Put(r.buf)
100
+		r.buf = nil
101
+	}
102
+	return
103
+}
104
+
105
+func (r *bufferedReader) Peek(n int) ([]byte, error) {
106
+	if r.buf == nil {
107
+		return nil, io.EOF
108
+	}
109
+	return r.buf.Peek(n)
110
+}
111
+
82 112
 // DetectCompression detects the compression algorithm of the source.
83 113
 func DetectCompression(source []byte) Compression {
84 114
 	for compression, m := range map[Compression][]byte{
... ...
@@ -97,8 +140,7 @@ func DetectCompression(source []byte) Compression {
97 97
 
98 98
 // DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
99 99
 func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
100
-	buf := bufioReader32KPool.Get().(*bufio.Reader)
101
-	buf.Reset(archive)
100
+	buf := newBufferedReader(archive)
102 101
 	bs, err := buf.Peek(10)
103 102
 	if err != nil && err != io.EOF {
104 103
 		// Note: we'll ignore any io.EOF error because there are some odd
... ...
@@ -110,22 +152,29 @@ func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
110 110
 		return nil, err
111 111
 	}
112 112
 
113
-	closer := func() error {
114
-		buf.Reset(nil)
115
-		bufioReader32KPool.Put(buf)
116
-		return nil
117
-	}
118 113
 	switch compression := DetectCompression(bs); compression {
119 114
 	case Uncompressed:
120
-		readBufWrapper := &readCloserWrapper{buf, compression, closer}
121
-		return readBufWrapper, nil
115
+		return &readCloserWrapper{
116
+			Reader:      buf,
117
+			compression: compression,
118
+		}, nil
122 119
 	case Gzip:
123
-		gzReader, err := gzip.NewReader(buf)
120
+		ctx, cancel := context.WithCancel(context.Background())
121
+		gzReader, err := gzipDecompress(ctx, buf)
124 122
 		if err != nil {
123
+			cancel()
125 124
 			return nil, err
126 125
 		}
127
-		readBufWrapper := &readCloserWrapper{gzReader, compression, closer}
128
-		return readBufWrapper, nil
126
+
127
+		return &readCloserWrapper{
128
+			Reader:      gzReader,
129
+			compression: compression,
130
+			closer: func() error {
131
+				cancel()
132
+				return gzReader.Close()
133
+			},
134
+		}, nil
135
+
129 136
 	default:
130 137
 		return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension())
131 138
 	}
... ...
@@ -151,3 +200,67 @@ func (compression *Compression) Extension() string {
151 151
 	}
152 152
 	return ""
153 153
 }
154
+
155
+func gzipDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) {
156
+	initPigz.Do(func() {
157
+		if unpigzPath = detectPigz(); unpigzPath != "" {
158
+			log.L.Debug("using pigz for decompression")
159
+		}
160
+	})
161
+
162
+	if unpigzPath == "" {
163
+		return gzip.NewReader(buf)
164
+	}
165
+
166
+	return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf)
167
+}
168
+
169
+func cmdStream(cmd *exec.Cmd, in io.Reader) (io.ReadCloser, error) {
170
+	reader, writer := io.Pipe()
171
+
172
+	cmd.Stdin = in
173
+	cmd.Stdout = writer
174
+
175
+	var errBuf bytes.Buffer
176
+	cmd.Stderr = &errBuf
177
+
178
+	if err := cmd.Start(); err != nil {
179
+		return nil, err
180
+	}
181
+
182
+	go func() {
183
+		if err := cmd.Wait(); err != nil {
184
+			writer.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
185
+		} else {
186
+			writer.Close()
187
+		}
188
+	}()
189
+
190
+	return reader, nil
191
+}
192
+
193
+func detectPigz() string {
194
+	path, err := exec.LookPath("unpigz")
195
+	if err != nil {
196
+		log.L.WithError(err).Debug("unpigz not found, falling back to go gzip")
197
+		return ""
198
+	}
199
+
200
+	// Check if pigz disabled via CONTAINERD_DISABLE_PIGZ env variable
201
+	value := os.Getenv(disablePigzEnv)
202
+	if value == "" {
203
+		return path
204
+	}
205
+
206
+	disable, err := strconv.ParseBool(value)
207
+	if err != nil {
208
+		log.L.WithError(err).Warnf("could not parse %s: %s", disablePigzEnv, value)
209
+		return path
210
+	}
211
+
212
+	if disable {
213
+		return ""
214
+	}
215
+
216
+	return path
217
+}
... ...
@@ -76,6 +76,23 @@ func WithContainerLabels(labels map[string]string) NewContainerOpts {
76 76
 	}
77 77
 }
78 78
 
79
+// WithImageStopSignal sets a well-known containerd label (StopSignalLabel)
80
+// on the container for storing the stop signal specified in the OCI image
81
+// config
82
+func WithImageStopSignal(image Image, defaultSignal string) NewContainerOpts {
83
+	return func(ctx context.Context, _ *Client, c *containers.Container) error {
84
+		if c.Labels == nil {
85
+			c.Labels = make(map[string]string)
86
+		}
87
+		stopSignal, err := GetOCIStopSignal(ctx, image, defaultSignal)
88
+		if err != nil {
89
+			return err
90
+		}
91
+		c.Labels[StopSignalLabel] = stopSignal
92
+		return nil
93
+	}
94
+}
95
+
79 96
 // WithSnapshotter sets the provided snapshotter for use by the container
80 97
 //
81 98
 // This option must appear before other snapshotter options to have an effect.
... ...
@@ -28,12 +28,12 @@ import (
28 28
 //
29 29
 // The resources specified in this object are used to create tasks from the container.
30 30
 type Container struct {
31
-	// ID uniquely identifies the container in a nameapace.
31
+	// ID uniquely identifies the container in a namespace.
32 32
 	//
33 33
 	// This property is required and cannot be changed after creation.
34 34
 	ID string
35 35
 
36
-	// Labels provide metadata extension for a contaienr.
36
+	// Labels provide metadata extension for a container.
37 37
 	//
38 38
 	// These are optional and fully mutable.
39 39
 	Labels map[string]string
... ...
@@ -70,7 +70,7 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, desc o
70 70
 	cw, err := OpenWriter(ctx, cs, WithRef(ref), WithDescriptor(desc))
71 71
 	if err != nil {
72 72
 		if !errdefs.IsAlreadyExists(err) {
73
-			return err
73
+			return errors.Wrap(err, "failed to open writer")
74 74
 		}
75 75
 
76 76
 		return nil // all ready present
... ...
@@ -127,7 +127,7 @@ func OpenWriter(ctx context.Context, cs Ingester, opts ...WriterOpt) (Writer, er
127 127
 func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error {
128 128
 	ws, err := cw.Status()
129 129
 	if err != nil {
130
-		return err
130
+		return errors.Wrap(err, "failed to get status")
131 131
 	}
132 132
 
133 133
 	if ws.Offset > 0 {
... ...
@@ -138,7 +138,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
138 138
 	}
139 139
 
140 140
 	if _, err := copyWithBuffer(cw, r); err != nil {
141
-		return err
141
+		return errors.Wrap(err, "failed to copy")
142 142
 	}
143 143
 
144 144
 	if err := cw.Commit(ctx, size, expected, opts...); err != nil {
... ...
@@ -57,7 +57,7 @@ func (rw *remoteWriter) Status() (content.Status, error) {
57 57
 		Action: contentapi.WriteActionStat,
58 58
 	})
59 59
 	if err != nil {
60
-		return content.Status{}, errors.Wrap(err, "error getting writer status")
60
+		return content.Status{}, errors.Wrap(errdefs.FromGRPC(err), "error getting writer status")
61 61
 	}
62 62
 
63 63
 	return content.Status{
... ...
@@ -82,7 +82,7 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) {
82 82
 		Data:   p,
83 83
 	})
84 84
 	if err != nil {
85
-		return 0, err
85
+		return 0, errors.Wrap(errdefs.FromGRPC(err), "failed to send write")
86 86
 	}
87 87
 
88 88
 	n = int(resp.Offset - offset)
... ...
@@ -112,7 +112,7 @@ func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.
112 112
 		Labels:   base.Labels,
113 113
 	})
114 114
 	if err != nil {
115
-		return errdefs.FromGRPC(err)
115
+		return errors.Wrap(errdefs.FromGRPC(err), "commit failed")
116 116
 	}
117 117
 
118 118
 	if size != 0 && resp.Offset != size {
... ...
@@ -22,6 +22,7 @@ import (
22 22
 
23 23
 	"github.com/containerd/containerd/images"
24 24
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
25
+	"github.com/pkg/errors"
25 26
 )
26 27
 
27 28
 type exportOpts struct {
... ...
@@ -51,7 +52,7 @@ func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocis
51 51
 	}
52 52
 	pr, pw := io.Pipe()
53 53
 	go func() {
54
-		pw.CloseWithError(exporter.Export(ctx, c.ContentStore(), desc, pw))
54
+		pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed"))
55 55
 	}()
56 56
 	return pr, nil
57 57
 }
... ...
@@ -37,6 +37,8 @@ type Image interface {
37 37
 	Name() string
38 38
 	// Target descriptor for the image content
39 39
 	Target() ocispec.Descriptor
40
+	// Labels of the image
41
+	Labels() map[string]string
40 42
 	// Unpack unpacks the image's content into a snapshot
41 43
 	Unpack(context.Context, string) error
42 44
 	// RootFS returns the unpacked diffids that make up images rootfs.
... ...
@@ -86,6 +88,10 @@ func (i *image) Target() ocispec.Descriptor {
86 86
 	return i.i.Target
87 87
 }
88 88
 
89
+func (i *image) Labels() map[string]string {
90
+	return i.i.Labels
91
+}
92
+
89 93
 func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
90 94
 	provider := i.client.ContentStore()
91 95
 	return i.i.RootFS(ctx, provider, i.platform)
92 96
new file mode 100644
... ...
@@ -0,0 +1,262 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+// Package archive provides a Docker and OCI compatible importer
17
+package archive
18
+
19
+import (
20
+	"archive/tar"
21
+	"bytes"
22
+	"context"
23
+	"encoding/json"
24
+	"io"
25
+	"io/ioutil"
26
+	"path"
27
+
28
+	"github.com/containerd/containerd/archive/compression"
29
+	"github.com/containerd/containerd/content"
30
+	"github.com/containerd/containerd/images"
31
+	"github.com/containerd/containerd/log"
32
+	digest "github.com/opencontainers/go-digest"
33
+	specs "github.com/opencontainers/image-spec/specs-go"
34
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
35
+	"github.com/pkg/errors"
36
+)
37
+
38
+// ImportIndex imports an index from a tar achive image bundle
39
+// - implements Docker v1.1, v1.2 and OCI v1.
40
+// - prefers OCI v1 when provided
41
+// - creates OCI index for Docker formats
42
+// - normalizes Docker references and adds as OCI ref name
43
+//      e.g. alpine:latest -> docker.io/library/alpine:latest
44
+// - existing OCI reference names are untouched
45
+// - TODO: support option to compress layers on ingest
46
+func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error) {
47
+	var (
48
+		tr = tar.NewReader(reader)
49
+
50
+		ociLayout ocispec.ImageLayout
51
+		mfsts     []struct {
52
+			Config   string
53
+			RepoTags []string
54
+			Layers   []string
55
+		}
56
+		symlinks = make(map[string]string)
57
+		blobs    = make(map[string]ocispec.Descriptor)
58
+	)
59
+	for {
60
+		hdr, err := tr.Next()
61
+		if err == io.EOF {
62
+			break
63
+		}
64
+		if err != nil {
65
+			return ocispec.Descriptor{}, err
66
+		}
67
+		if hdr.Typeflag == tar.TypeSymlink {
68
+			symlinks[hdr.Name] = path.Join(path.Dir(hdr.Name), hdr.Linkname)
69
+		}
70
+
71
+		if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA {
72
+			if hdr.Typeflag != tar.TypeDir {
73
+				log.G(ctx).WithField("file", hdr.Name).Debug("file type ignored")
74
+			}
75
+			continue
76
+		}
77
+
78
+		hdrName := path.Clean(hdr.Name)
79
+		if hdrName == ocispec.ImageLayoutFile {
80
+			if err = onUntarJSON(tr, &ociLayout); err != nil {
81
+				return ocispec.Descriptor{}, errors.Wrapf(err, "untar oci layout %q", hdr.Name)
82
+			}
83
+		} else if hdrName == "manifest.json" {
84
+			if err = onUntarJSON(tr, &mfsts); err != nil {
85
+				return ocispec.Descriptor{}, errors.Wrapf(err, "untar manifest %q", hdr.Name)
86
+			}
87
+		} else {
88
+			dgst, err := onUntarBlob(ctx, tr, store, hdr.Size, "tar-"+hdrName)
89
+			if err != nil {
90
+				return ocispec.Descriptor{}, errors.Wrapf(err, "failed to ingest %q", hdr.Name)
91
+			}
92
+
93
+			blobs[hdrName] = ocispec.Descriptor{
94
+				Digest: dgst,
95
+				Size:   hdr.Size,
96
+			}
97
+		}
98
+	}
99
+
100
+	// If OCI layout was given, interpret the tar as an OCI layout.
101
+	// When not provided, the layout of the tar will be interpretted
102
+	// as Docker v1.1 or v1.2.
103
+	if ociLayout.Version != "" {
104
+		if ociLayout.Version != ocispec.ImageLayoutVersion {
105
+			return ocispec.Descriptor{}, errors.Errorf("unsupported OCI version %s", ociLayout.Version)
106
+		}
107
+
108
+		idx, ok := blobs["index.json"]
109
+		if !ok {
110
+			return ocispec.Descriptor{}, errors.Errorf("missing index.json in OCI layout %s", ocispec.ImageLayoutVersion)
111
+		}
112
+
113
+		idx.MediaType = ocispec.MediaTypeImageIndex
114
+		return idx, nil
115
+	}
116
+
117
+	if mfsts == nil {
118
+		return ocispec.Descriptor{}, errors.Errorf("unrecognized image format")
119
+	}
120
+
121
+	for name, linkname := range symlinks {
122
+		desc, ok := blobs[linkname]
123
+		if !ok {
124
+			return ocispec.Descriptor{}, errors.Errorf("no target for symlink layer from %q to %q", name, linkname)
125
+		}
126
+		blobs[name] = desc
127
+	}
128
+
129
+	idx := ocispec.Index{
130
+		Versioned: specs.Versioned{
131
+			SchemaVersion: 2,
132
+		},
133
+	}
134
+	for _, mfst := range mfsts {
135
+		config, ok := blobs[mfst.Config]
136
+		if !ok {
137
+			return ocispec.Descriptor{}, errors.Errorf("image config %q not found", mfst.Config)
138
+		}
139
+		config.MediaType = ocispec.MediaTypeImageConfig
140
+
141
+		layers, err := resolveLayers(ctx, store, mfst.Layers, blobs)
142
+		if err != nil {
143
+			return ocispec.Descriptor{}, errors.Wrap(err, "failed to resolve layers")
144
+		}
145
+
146
+		manifest := ocispec.Manifest{
147
+			Versioned: specs.Versioned{
148
+				SchemaVersion: 2,
149
+			},
150
+			Config: config,
151
+			Layers: layers,
152
+		}
153
+
154
+		desc, err := writeManifest(ctx, store, manifest, ocispec.MediaTypeImageManifest)
155
+		if err != nil {
156
+			return ocispec.Descriptor{}, errors.Wrap(err, "write docker manifest")
157
+		}
158
+
159
+		platforms, err := images.Platforms(ctx, store, desc)
160
+		if err != nil {
161
+			return ocispec.Descriptor{}, errors.Wrap(err, "unable to resolve platform")
162
+		}
163
+		if len(platforms) > 0 {
164
+			// Only one platform can be resolved from non-index manifest,
165
+			// The platform can only come from the config included above,
166
+			// if the config has no platform it can be safely ommitted.
167
+			desc.Platform = &platforms[0]
168
+		}
169
+
170
+		if len(mfst.RepoTags) == 0 {
171
+			idx.Manifests = append(idx.Manifests, desc)
172
+		} else {
173
+			// Add descriptor per tag
174
+			for _, ref := range mfst.RepoTags {
175
+				mfstdesc := desc
176
+
177
+				normalized, err := normalizeReference(ref)
178
+				if err != nil {
179
+					return ocispec.Descriptor{}, err
180
+				}
181
+
182
+				mfstdesc.Annotations = map[string]string{
183
+					ocispec.AnnotationRefName: normalized,
184
+				}
185
+
186
+				idx.Manifests = append(idx.Manifests, mfstdesc)
187
+			}
188
+		}
189
+	}
190
+
191
+	return writeManifest(ctx, store, idx, ocispec.MediaTypeImageIndex)
192
+}
193
+
194
+func onUntarJSON(r io.Reader, j interface{}) error {
195
+	b, err := ioutil.ReadAll(r)
196
+	if err != nil {
197
+		return err
198
+	}
199
+	if err := json.Unmarshal(b, j); err != nil {
200
+		return err
201
+	}
202
+	return nil
203
+}
204
+
205
+func onUntarBlob(ctx context.Context, r io.Reader, store content.Ingester, size int64, ref string) (digest.Digest, error) {
206
+	dgstr := digest.Canonical.Digester()
207
+
208
+	if err := content.WriteBlob(ctx, store, ref, io.TeeReader(r, dgstr.Hash()), ocispec.Descriptor{Size: size}); err != nil {
209
+		return "", err
210
+	}
211
+
212
+	return dgstr.Digest(), nil
213
+}
214
+
215
+func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor) ([]ocispec.Descriptor, error) {
216
+	var layers []ocispec.Descriptor
217
+	for _, f := range layerFiles {
218
+		desc, ok := blobs[f]
219
+		if !ok {
220
+			return nil, errors.Errorf("layer %q not found", f)
221
+		}
222
+
223
+		// Open blob, resolve media type
224
+		ra, err := store.ReaderAt(ctx, desc)
225
+		if err != nil {
226
+			return nil, errors.Wrapf(err, "failed to open %q (%s)", f, desc.Digest)
227
+		}
228
+		s, err := compression.DecompressStream(content.NewReader(ra))
229
+		if err != nil {
230
+			return nil, errors.Wrapf(err, "failed to detect compression for %q", f)
231
+		}
232
+		if s.GetCompression() == compression.Uncompressed {
233
+			// TODO: Support compressing and writing back to content store
234
+			desc.MediaType = ocispec.MediaTypeImageLayer
235
+		} else {
236
+			desc.MediaType = ocispec.MediaTypeImageLayerGzip
237
+		}
238
+		s.Close()
239
+
240
+		layers = append(layers, desc)
241
+	}
242
+	return layers, nil
243
+}
244
+
245
+func writeManifest(ctx context.Context, cs content.Ingester, manifest interface{}, mediaType string) (ocispec.Descriptor, error) {
246
+	manifestBytes, err := json.Marshal(manifest)
247
+	if err != nil {
248
+		return ocispec.Descriptor{}, err
249
+	}
250
+
251
+	desc := ocispec.Descriptor{
252
+		MediaType: mediaType,
253
+		Digest:    digest.FromBytes(manifestBytes),
254
+		Size:      int64(len(manifestBytes)),
255
+	}
256
+	if err := content.WriteBlob(ctx, cs, "manifest-"+desc.Digest.String(), bytes.NewReader(manifestBytes), desc); err != nil {
257
+		return ocispec.Descriptor{}, err
258
+	}
259
+
260
+	return desc, nil
261
+}
0 262
new file mode 100644
... ...
@@ -0,0 +1,86 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package archive
17
+
18
+import (
19
+	"strings"
20
+
21
+	"github.com/containerd/cri/pkg/util"
22
+	digest "github.com/opencontainers/go-digest"
23
+	"github.com/pkg/errors"
24
+)
25
+
26
+// FilterRefPrefix restricts references to having the given image
27
+// prefix. Tag-only references will have the prefix prepended.
28
+func FilterRefPrefix(image string) func(string) string {
29
+	return refTranslator(image, true)
30
+}
31
+
32
+// AddRefPrefix prepends the given image prefix to tag-only references,
33
+// while leaving returning full references unmodified.
34
+func AddRefPrefix(image string) func(string) string {
35
+	return refTranslator(image, false)
36
+}
37
+
38
+// refTranslator creates a reference which only has a tag or verifies
39
+// a full reference.
40
+func refTranslator(image string, checkPrefix bool) func(string) string {
41
+	return func(ref string) string {
42
+		// Check if ref is full reference
43
+		if strings.ContainsAny(ref, "/:@") {
44
+			// If not prefixed, don't include image
45
+			if checkPrefix && !isImagePrefix(ref, image) {
46
+				return ""
47
+			}
48
+			return ref
49
+		}
50
+		return image + ":" + ref
51
+	}
52
+}
53
+
54
+func isImagePrefix(s, prefix string) bool {
55
+	if !strings.HasPrefix(s, prefix) {
56
+		return false
57
+	}
58
+	if len(s) > len(prefix) {
59
+		switch s[len(prefix)] {
60
+		case '/', ':', '@':
61
+			// Prevent matching partial namespaces
62
+		default:
63
+			return false
64
+		}
65
+	}
66
+	return true
67
+}
68
+
69
+func normalizeReference(ref string) (string, error) {
70
+	// TODO: Replace this function to not depend on reference package
71
+	normalized, err := util.NormalizeImageRef(ref)
72
+	if err != nil {
73
+		return "", errors.Wrapf(err, "normalize image ref %q", ref)
74
+	}
75
+
76
+	return normalized.String(), nil
77
+}
78
+
79
+// DigestTranslator creates a digest reference by adding the
80
+// digest to an image name
81
+func DigestTranslator(prefix string) func(digest.Digest) string {
82
+	return func(dgst digest.Digest) string {
83
+		return prefix + "@" + dgst.String()
84
+	}
85
+}
... ...
@@ -129,6 +129,13 @@ type platformManifest struct {
129 129
 
130 130
 // Manifest resolves a manifest from the image for the given platform.
131 131
 //
132
+// When a manifest descriptor inside of a manifest index does not have
133
+// a platform defined, the platform from the image config is considered.
134
+//
135
+// If the descriptor points to a non-index manifest, then the manifest is
136
+// unmarshalled and returned without considering the platform inside of the
137
+// config.
138
+//
132 139
 // TODO(stevvooe): This violates the current platform agnostic approach to this
133 140
 // package by returning a specific manifest type. We'll need to refactor this
134 141
 // to return a manifest descriptor or decide that we want to bring the API in
... ...
@@ -152,7 +159,7 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
152 152
 				return nil, err
153 153
 			}
154 154
 
155
-			if platform != nil {
155
+			if desc.Digest != image.Digest && platform != nil {
156 156
 				if desc.Platform != nil && !platform.Match(*desc.Platform) {
157 157
 					return nil, nil
158 158
 				}
... ...
@@ -27,7 +27,7 @@ import (
27 27
 // Importer is the interface for image importer.
28 28
 type Importer interface {
29 29
 	// Import imports an image from a tar stream.
30
-	Import(ctx context.Context, store content.Store, reader io.Reader) ([]Image, error)
30
+	Import(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error)
31 31
 }
32 32
 
33 33
 // Exporter is the interface for image exporter.
... ...
@@ -18,35 +18,61 @@ package containerd
18 18
 
19 19
 import (
20 20
 	"context"
21
+	"encoding/json"
21 22
 	"io"
22 23
 
24
+	"github.com/containerd/containerd/content"
23 25
 	"github.com/containerd/containerd/errdefs"
24 26
 	"github.com/containerd/containerd/images"
27
+	"github.com/containerd/containerd/images/archive"
28
+	digest "github.com/opencontainers/go-digest"
29
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
25 30
 )
26 31
 
27 32
 type importOpts struct {
33
+	indexName string
34
+	imageRefT func(string) string
35
+	dgstRefT  func(digest.Digest) string
28 36
 }
29 37
 
30 38
 // ImportOpt allows the caller to specify import specific options
31
-type ImportOpt func(c *importOpts) error
39
+type ImportOpt func(*importOpts) error
40
+
41
+// WithImageRefTranslator is used to translate the index reference
42
+// to an image reference for the image store.
43
+func WithImageRefTranslator(f func(string) string) ImportOpt {
44
+	return func(c *importOpts) error {
45
+		c.imageRefT = f
46
+		return nil
47
+	}
48
+}
32 49
 
33
-func resolveImportOpt(opts ...ImportOpt) (importOpts, error) {
34
-	var iopts importOpts
35
-	for _, o := range opts {
36
-		if err := o(&iopts); err != nil {
37
-			return iopts, err
38
-		}
50
+// WithDigestRef is used to create digest images for each
51
+// manifest in the index.
52
+func WithDigestRef(f func(digest.Digest) string) ImportOpt {
53
+	return func(c *importOpts) error {
54
+		c.dgstRefT = f
55
+		return nil
56
+	}
57
+}
58
+
59
+// WithIndexName creates a tag pointing to the imported index
60
+func WithIndexName(name string) ImportOpt {
61
+	return func(c *importOpts) error {
62
+		c.indexName = name
63
+		return nil
39 64
 	}
40
-	return iopts, nil
41 65
 }
42 66
 
43 67
 // Import imports an image from a Tar stream using reader.
44 68
 // Caller needs to specify importer. Future version may use oci.v1 as the default.
45 69
 // Note that unreferrenced blobs may be imported to the content store as well.
46
-func (c *Client) Import(ctx context.Context, importer images.Importer, reader io.Reader, opts ...ImportOpt) ([]Image, error) {
47
-	_, err := resolveImportOpt(opts...) // unused now
48
-	if err != nil {
49
-		return nil, err
70
+func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt) ([]images.Image, error) {
71
+	var iopts importOpts
72
+	for _, o := range opts {
73
+		if err := o(&iopts); err != nil {
74
+			return nil, err
75
+		}
50 76
 	}
51 77
 
52 78
 	ctx, done, err := c.WithLease(ctx)
... ...
@@ -55,31 +81,86 @@ func (c *Client) Import(ctx context.Context, importer images.Importer, reader io
55 55
 	}
56 56
 	defer done(ctx)
57 57
 
58
-	imgrecs, err := importer.Import(ctx, c.ContentStore(), reader)
58
+	index, err := archive.ImportIndex(ctx, c.ContentStore(), reader)
59 59
 	if err != nil {
60
-		// is.Update() is not called on error
61 60
 		return nil, err
62 61
 	}
63 62
 
64
-	is := c.ImageService()
65
-	var images []Image
66
-	for _, imgrec := range imgrecs {
67
-		if updated, err := is.Update(ctx, imgrec, "target"); err != nil {
63
+	var (
64
+		imgs []images.Image
65
+		cs   = c.ContentStore()
66
+		is   = c.ImageService()
67
+	)
68
+
69
+	if iopts.indexName != "" {
70
+		imgs = append(imgs, images.Image{
71
+			Name:   iopts.indexName,
72
+			Target: index,
73
+		})
74
+	}
75
+
76
+	var handler images.HandlerFunc
77
+	handler = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
78
+		// Only save images at top level
79
+		if desc.Digest != index.Digest {
80
+			return images.Children(ctx, cs, desc)
81
+		}
82
+
83
+		p, err := content.ReadBlob(ctx, cs, desc)
84
+		if err != nil {
85
+			return nil, err
86
+		}
87
+
88
+		var idx ocispec.Index
89
+		if err := json.Unmarshal(p, &idx); err != nil {
90
+			return nil, err
91
+		}
92
+
93
+		for _, m := range idx.Manifests {
94
+			if ref := m.Annotations[ocispec.AnnotationRefName]; ref != "" {
95
+				if iopts.imageRefT != nil {
96
+					ref = iopts.imageRefT(ref)
97
+				}
98
+				if ref != "" {
99
+					imgs = append(imgs, images.Image{
100
+						Name:   ref,
101
+						Target: m,
102
+					})
103
+				}
104
+			}
105
+			if iopts.dgstRefT != nil {
106
+				ref := iopts.dgstRefT(m.Digest)
107
+				if ref != "" {
108
+					imgs = append(imgs, images.Image{
109
+						Name:   ref,
110
+						Target: m,
111
+					})
112
+				}
113
+			}
114
+		}
115
+
116
+		return idx.Manifests, nil
117
+	}
118
+
119
+	handler = images.SetChildrenLabels(cs, handler)
120
+	if err := images.Walk(ctx, handler, index); err != nil {
121
+		return nil, err
122
+	}
123
+
124
+	for i := range imgs {
125
+		img, err := is.Update(ctx, imgs[i], "target")
126
+		if err != nil {
68 127
 			if !errdefs.IsNotFound(err) {
69 128
 				return nil, err
70 129
 			}
71 130
 
72
-			created, err := is.Create(ctx, imgrec)
131
+			img, err = is.Create(ctx, imgs[i])
73 132
 			if err != nil {
74 133
 				return nil, err
75 134
 			}
76
-
77
-			imgrec = created
78
-		} else {
79
-			imgrec = updated
80 135
 		}
81
-
82
-		images = append(images, NewImage(c, imgrec))
136
+		imgs[i] = img
83 137
 	}
84
-	return images, nil
138
+
139
+	return imgs, nil
85 140
 }
... ...
@@ -553,7 +553,9 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig
553 553
 	nw.l.RLock()
554 554
 	defer nw.l.RUnlock()
555 555
 
556
-	return update(ctx, nw.db, func(tx *bolt.Tx) error {
556
+	var innerErr error
557
+
558
+	if err := update(ctx, nw.db, func(tx *bolt.Tx) error {
557 559
 		bkt := getIngestsBucket(tx, nw.namespace)
558 560
 		if bkt != nil {
559 561
 			if err := bkt.DeleteBucket([]byte(nw.ref)); err != nil && err != bolt.ErrBucketNotFound {
... ...
@@ -562,13 +564,20 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig
562 562
 		}
563 563
 		dgst, err := nw.commit(ctx, tx, size, expected, opts...)
564 564
 		if err != nil {
565
-			return err
565
+			if !errdefs.IsAlreadyExists(err) {
566
+				return err
567
+			}
568
+			innerErr = err
566 569
 		}
567 570
 		if err := removeIngestLease(ctx, tx, nw.ref); err != nil {
568 571
 			return err
569 572
 		}
570 573
 		return addContentLease(ctx, tx, dgst)
571
-	})
574
+	}); err != nil {
575
+		return err
576
+	}
577
+
578
+	return innerErr
572 579
 }
573 580
 
574 581
 func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) (digest.Digest, error) {
... ...
@@ -611,7 +620,7 @@ func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64,
611 611
 	bkt, err := createBlobBucket(tx, nw.namespace, actual)
612 612
 	if err != nil {
613 613
 		if err == bolt.ErrBucketExists {
614
-			return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
614
+			return actual, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
615 615
 		}
616 616
 		return "", err
617 617
 	}
... ...
@@ -167,6 +167,7 @@ func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
167 167
 				Destination: "/proc",
168 168
 				Type:        "proc",
169 169
 				Source:      "proc",
170
+				Options:     []string{"nosuid", "noexec", "nodev"},
170 171
 			},
171 172
 			{
172 173
 				Destination: "/dev",
... ...
@@ -268,6 +268,14 @@ func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts {
268 268
 	}
269 269
 }
270 270
 
271
+// WithNewPrivileges turns off the NoNewPrivileges feature flag in the spec
272
+func WithNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
273
+	setProcess(s)
274
+	s.Process.NoNewPrivileges = false
275
+
276
+	return nil
277
+}
278
+
271 279
 // WithImageConfig configures the spec to from the configuration of an Image
272 280
 func WithImageConfig(image Image) SpecOpts {
273 281
 	return WithImageConfigArgs(image, nil)
... ...
@@ -646,6 +654,10 @@ func WithUsername(username string) SpecOpts {
646 646
 // The passed in user can be either a uid or a username.
647 647
 func WithAdditionalGIDs(userstr string) SpecOpts {
648 648
 	return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
649
+		// For LCOW additional GID's not supported
650
+		if s.Windows != nil {
651
+			return nil
652
+		}
649 653
 		setProcess(s)
650 654
 		setAdditionalGids := func(root string) error {
651 655
 			var username string
... ...
@@ -1003,3 +1015,14 @@ var WithPrivileged = Compose(
1003 1003
 	WithApparmorProfile(""),
1004 1004
 	WithSeccompUnconfined,
1005 1005
 )
1006
+
1007
+// WithWindowsHyperV sets the Windows.HyperV section for HyperV isolation of containers.
1008
+func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
1009
+	if s.Windows == nil {
1010
+		s.Windows = &specs.Windows{}
1011
+	}
1012
+	if s.Windows.HyperV == nil {
1013
+		s.Windows.HyperV = &specs.WindowsHyperV{}
1014
+	}
1015
+	return nil
1016
+}
1006 1017
new file mode 100644
... ...
@@ -0,0 +1,317 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package docker
17
+
18
+import (
19
+	"context"
20
+	"encoding/base64"
21
+	"encoding/json"
22
+	"fmt"
23
+	"io"
24
+	"io/ioutil"
25
+	"net/http"
26
+	"net/url"
27
+	"strings"
28
+	"sync"
29
+	"time"
30
+
31
+	"github.com/containerd/containerd/errdefs"
32
+	"github.com/containerd/containerd/log"
33
+	"github.com/pkg/errors"
34
+	"github.com/sirupsen/logrus"
35
+	"golang.org/x/net/context/ctxhttp"
36
+)
37
+
38
+type dockerAuthorizer struct {
39
+	credentials func(string) (string, string, error)
40
+
41
+	client *http.Client
42
+	mu     sync.Mutex
43
+
44
+	auth map[string]string
45
+}
46
+
47
+// NewAuthorizer creates a Docker authorizer using the provided function to
48
+// get credentials for the token server or basic auth.
49
+func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
50
+	if client == nil {
51
+		client = http.DefaultClient
52
+	}
53
+	return &dockerAuthorizer{
54
+		credentials: f,
55
+		client:      client,
56
+		auth:        map[string]string{},
57
+	}
58
+}
59
+
60
+func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
61
+	// TODO: Lookup matching challenge and scope rather than just host
62
+	if auth := a.getAuth(req.URL.Host); auth != "" {
63
+		req.Header.Set("Authorization", auth)
64
+	}
65
+
66
+	return nil
67
+}
68
+
69
+func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
70
+	last := responses[len(responses)-1]
71
+	host := last.Request.URL.Host
72
+	for _, c := range parseAuthHeader(last.Header) {
73
+		if c.scheme == bearerAuth {
74
+			if err := invalidAuthorization(c, responses); err != nil {
75
+				// TODO: Clear token
76
+				a.setAuth(host, "")
77
+				return err
78
+			}
79
+
80
+			// TODO(dmcg): Store challenge, not token
81
+			// Move token fetching to authorize
82
+			if err := a.setTokenAuth(ctx, host, c.parameters); err != nil {
83
+				return err
84
+			}
85
+
86
+			return nil
87
+		} else if c.scheme == basicAuth {
88
+			// TODO: Resolve credentials on authorize
89
+			username, secret, err := a.credentials(host)
90
+			if err != nil {
91
+				return err
92
+			}
93
+			if username != "" && secret != "" {
94
+				auth := username + ":" + secret
95
+				a.setAuth(host, fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
96
+				return nil
97
+			}
98
+		}
99
+	}
100
+
101
+	return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
102
+}
103
+
104
+func (a *dockerAuthorizer) getAuth(host string) string {
105
+	a.mu.Lock()
106
+	defer a.mu.Unlock()
107
+
108
+	return a.auth[host]
109
+}
110
+
111
+func (a *dockerAuthorizer) setAuth(host string, auth string) bool {
112
+	a.mu.Lock()
113
+	defer a.mu.Unlock()
114
+
115
+	changed := a.auth[host] != auth
116
+	a.auth[host] = auth
117
+
118
+	return changed
119
+}
120
+
121
+func (a *dockerAuthorizer) setTokenAuth(ctx context.Context, host string, params map[string]string) error {
122
+	realm, ok := params["realm"]
123
+	if !ok {
124
+		return errors.New("no realm specified for token auth challenge")
125
+	}
126
+
127
+	realmURL, err := url.Parse(realm)
128
+	if err != nil {
129
+		return errors.Wrap(err, "invalid token auth challenge realm")
130
+	}
131
+
132
+	to := tokenOptions{
133
+		realm:   realmURL.String(),
134
+		service: params["service"],
135
+	}
136
+
137
+	to.scopes = getTokenScopes(ctx, params)
138
+	if len(to.scopes) == 0 {
139
+		return errors.Errorf("no scope specified for token auth challenge")
140
+	}
141
+
142
+	if a.credentials != nil {
143
+		to.username, to.secret, err = a.credentials(host)
144
+		if err != nil {
145
+			return err
146
+		}
147
+	}
148
+
149
+	var token string
150
+	if to.secret != "" {
151
+		// Credential information is provided, use oauth POST endpoint
152
+		token, err = a.fetchTokenWithOAuth(ctx, to)
153
+		if err != nil {
154
+			return errors.Wrap(err, "failed to fetch oauth token")
155
+		}
156
+	} else {
157
+		// Do request anonymously
158
+		token, err = a.fetchToken(ctx, to)
159
+		if err != nil {
160
+			return errors.Wrap(err, "failed to fetch anonymous token")
161
+		}
162
+	}
163
+	a.setAuth(host, fmt.Sprintf("Bearer %s", token))
164
+
165
+	return nil
166
+}
167
+
168
+type tokenOptions struct {
169
+	realm    string
170
+	service  string
171
+	scopes   []string
172
+	username string
173
+	secret   string
174
+}
175
+
176
+type postTokenResponse struct {
177
+	AccessToken  string    `json:"access_token"`
178
+	RefreshToken string    `json:"refresh_token"`
179
+	ExpiresIn    int       `json:"expires_in"`
180
+	IssuedAt     time.Time `json:"issued_at"`
181
+	Scope        string    `json:"scope"`
182
+}
183
+
184
+func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
185
+	form := url.Values{}
186
+	form.Set("scope", strings.Join(to.scopes, " "))
187
+	form.Set("service", to.service)
188
+	// TODO: Allow setting client_id
189
+	form.Set("client_id", "containerd-client")
190
+
191
+	if to.username == "" {
192
+		form.Set("grant_type", "refresh_token")
193
+		form.Set("refresh_token", to.secret)
194
+	} else {
195
+		form.Set("grant_type", "password")
196
+		form.Set("username", to.username)
197
+		form.Set("password", to.secret)
198
+	}
199
+
200
+	resp, err := ctxhttp.PostForm(ctx, a.client, to.realm, form)
201
+	if err != nil {
202
+		return "", err
203
+	}
204
+	defer resp.Body.Close()
205
+
206
+	// Registries without support for POST may return 404 for POST /v2/token.
207
+	// As of September 2017, GCR is known to return 404.
208
+	// As of February 2018, JFrog Artifactory is known to return 401.
209
+	if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
210
+		return a.fetchToken(ctx, to)
211
+	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
212
+		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
213
+		log.G(ctx).WithFields(logrus.Fields{
214
+			"status": resp.Status,
215
+			"body":   string(b),
216
+		}).Debugf("token request failed")
217
+		// TODO: handle error body and write debug output
218
+		return "", errors.Errorf("unexpected status: %s", resp.Status)
219
+	}
220
+
221
+	decoder := json.NewDecoder(resp.Body)
222
+
223
+	var tr postTokenResponse
224
+	if err = decoder.Decode(&tr); err != nil {
225
+		return "", fmt.Errorf("unable to decode token response: %s", err)
226
+	}
227
+
228
+	return tr.AccessToken, nil
229
+}
230
+
231
+type getTokenResponse struct {
232
+	Token        string    `json:"token"`
233
+	AccessToken  string    `json:"access_token"`
234
+	ExpiresIn    int       `json:"expires_in"`
235
+	IssuedAt     time.Time `json:"issued_at"`
236
+	RefreshToken string    `json:"refresh_token"`
237
+}
238
+
239
+// getToken fetches a token using a GET request
240
+func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
241
+	req, err := http.NewRequest("GET", to.realm, nil)
242
+	if err != nil {
243
+		return "", err
244
+	}
245
+
246
+	reqParams := req.URL.Query()
247
+
248
+	if to.service != "" {
249
+		reqParams.Add("service", to.service)
250
+	}
251
+
252
+	for _, scope := range to.scopes {
253
+		reqParams.Add("scope", scope)
254
+	}
255
+
256
+	if to.secret != "" {
257
+		req.SetBasicAuth(to.username, to.secret)
258
+	}
259
+
260
+	req.URL.RawQuery = reqParams.Encode()
261
+
262
+	resp, err := ctxhttp.Do(ctx, a.client, req)
263
+	if err != nil {
264
+		return "", err
265
+	}
266
+	defer resp.Body.Close()
267
+
268
+	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
269
+		// TODO: handle error body and write debug output
270
+		return "", errors.Errorf("unexpected status: %s", resp.Status)
271
+	}
272
+
273
+	decoder := json.NewDecoder(resp.Body)
274
+
275
+	var tr getTokenResponse
276
+	if err = decoder.Decode(&tr); err != nil {
277
+		return "", fmt.Errorf("unable to decode token response: %s", err)
278
+	}
279
+
280
+	// `access_token` is equivalent to `token` and if both are specified
281
+	// the choice is undefined.  Canonicalize `access_token` by sticking
282
+	// things in `token`.
283
+	if tr.AccessToken != "" {
284
+		tr.Token = tr.AccessToken
285
+	}
286
+
287
+	if tr.Token == "" {
288
+		return "", ErrNoToken
289
+	}
290
+
291
+	return tr.Token, nil
292
+}
293
+
294
+func invalidAuthorization(c challenge, responses []*http.Response) error {
295
+	errStr := c.parameters["error"]
296
+	if errStr == "" {
297
+		return nil
298
+	}
299
+
300
+	n := len(responses)
301
+	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
302
+		return nil
303
+	}
304
+
305
+	return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
306
+}
307
+
308
+func sameRequest(r1, r2 *http.Request) bool {
309
+	if r1.Method != r2.Method {
310
+		return false
311
+	}
312
+	if *r1.URL != *r2.URL {
313
+		return false
314
+	}
315
+	return true
316
+}
... ...
@@ -18,18 +18,13 @@ package docker
18 18
 
19 19
 import (
20 20
 	"context"
21
-	"encoding/json"
22
-	"fmt"
23
-	"io"
24
-	"io/ioutil"
25 21
 	"net/http"
26 22
 	"net/url"
27 23
 	"path"
28 24
 	"strconv"
29 25
 	"strings"
30
-	"sync"
31
-	"time"
32 26
 
27
+	"github.com/containerd/containerd/errdefs"
33 28
 	"github.com/containerd/containerd/images"
34 29
 	"github.com/containerd/containerd/log"
35 30
 	"github.com/containerd/containerd/reference"
... ...
@@ -51,19 +46,37 @@ var (
51 51
 	ErrInvalidAuthorization = errors.New("authorization failed")
52 52
 )
53 53
 
54
-type dockerResolver struct {
55
-	credentials func(string) (string, string, error)
56
-	host        func(string) (string, error)
57
-	plainHTTP   bool
58
-	client      *http.Client
59
-	tracker     StatusTracker
54
+// Authorizer is used to authorize HTTP requests based on 401 HTTP responses.
55
+// An Authorizer is responsible for caching tokens or credentials used by
56
+// requests.
57
+type Authorizer interface {
58
+	// Authorize sets the appropriate `Authorization` header on the given
59
+	// request.
60
+	//
61
+	// If no authorization is found for the request, the request remains
62
+	// unmodified. It may also add an `Authorization` header as
63
+	//  "bearer <some bearer token>"
64
+	//  "basic <base64 encoded credentials>"
65
+	Authorize(context.Context, *http.Request) error
66
+
67
+	// AddResponses adds a 401 response for the authorizer to consider when
68
+	// authorizing requests. The last response should be unauthorized and
69
+	// the previous requests are used to consider redirects and retries
70
+	// that may have led to the 401.
71
+	//
72
+	// If response is not handled, returns `ErrNotImplemented`
73
+	AddResponses(context.Context, []*http.Response) error
60 74
 }
61 75
 
62 76
 // ResolverOptions are used to configured a new Docker register resolver
63 77
 type ResolverOptions struct {
78
+	// Authorizer is used to authorize registry requests
79
+	Authorizer Authorizer
80
+
64 81
 	// Credentials provides username and secret given a host.
65 82
 	// If username is empty but a secret is given, that secret
66 83
 	// is interpretted as a long lived token.
84
+	// Deprecated: use Authorizer
67 85
 	Credentials func(string) (string, string, error)
68 86
 
69 87
 	// Host provides the hostname given a namespace.
... ...
@@ -89,22 +102,31 @@ func DefaultHost(ns string) (string, error) {
89 89
 	return ns, nil
90 90
 }
91 91
 
92
+type dockerResolver struct {
93
+	auth      Authorizer
94
+	host      func(string) (string, error)
95
+	plainHTTP bool
96
+	client    *http.Client
97
+	tracker   StatusTracker
98
+}
99
+
92 100
 // NewResolver returns a new resolver to a Docker registry
93 101
 func NewResolver(options ResolverOptions) remotes.Resolver {
94
-	tracker := options.Tracker
95
-	if tracker == nil {
96
-		tracker = NewInMemoryTracker()
102
+	if options.Tracker == nil {
103
+		options.Tracker = NewInMemoryTracker()
104
+	}
105
+	if options.Host == nil {
106
+		options.Host = DefaultHost
97 107
 	}
98
-	host := options.Host
99
-	if host == nil {
100
-		host = DefaultHost
108
+	if options.Authorizer == nil {
109
+		options.Authorizer = NewAuthorizer(options.Client, options.Credentials)
101 110
 	}
102 111
 	return &dockerResolver{
103
-		credentials: options.Credentials,
104
-		host:        host,
105
-		plainHTTP:   options.PlainHTTP,
106
-		client:      options.Client,
107
-		tracker:     tracker,
112
+		auth:      options.Authorizer,
113
+		host:      options.Host,
114
+		plainHTTP: options.PlainHTTP,
115
+		client:    options.Client,
116
+		tracker:   options.Tracker,
108 117
 	}
109 118
 }
110 119
 
... ...
@@ -272,18 +294,14 @@ type dockerBase struct {
272 272
 	refspec reference.Spec
273 273
 	base    url.URL
274 274
 
275
-	client           *http.Client
276
-	useBasic         bool
277
-	username, secret string
278
-	token            string
279
-	mu               sync.Mutex
275
+	client *http.Client
276
+	auth   Authorizer
280 277
 }
281 278
 
282 279
 func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
283 280
 	var (
284
-		err              error
285
-		base             url.URL
286
-		username, secret string
281
+		err  error
282
+		base url.URL
287 283
 	)
288 284
 
289 285
 	host := refspec.Hostname()
... ...
@@ -300,61 +318,40 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
300 300
 		base.Scheme = "http"
301 301
 	}
302 302
 
303
-	if r.credentials != nil {
304
-		username, secret, err = r.credentials(base.Host)
305
-		if err != nil {
306
-			return nil, err
307
-		}
308
-	}
309
-
310 303
 	prefix := strings.TrimPrefix(refspec.Locator, host+"/")
311 304
 	base.Path = path.Join("/v2", prefix)
312 305
 
313 306
 	return &dockerBase{
314
-		refspec:  refspec,
315
-		base:     base,
316
-		client:   r.client,
317
-		username: username,
318
-		secret:   secret,
307
+		refspec: refspec,
308
+		base:    base,
309
+		client:  r.client,
310
+		auth:    r.auth,
319 311
 	}, nil
320 312
 }
321 313
 
322
-func (r *dockerBase) getToken() string {
323
-	r.mu.Lock()
324
-	defer r.mu.Unlock()
325
-
326
-	return r.token
327
-}
328
-
329
-func (r *dockerBase) setToken(token string) bool {
330
-	r.mu.Lock()
331
-	defer r.mu.Unlock()
332
-
333
-	changed := r.token != token
334
-	r.token = token
335
-
336
-	return changed
337
-}
338
-
339 314
 func (r *dockerBase) url(ps ...string) string {
340 315
 	url := r.base
341 316
 	url.Path = path.Join(url.Path, path.Join(ps...))
342 317
 	return url.String()
343 318
 }
344 319
 
345
-func (r *dockerBase) authorize(req *http.Request) {
346
-	token := r.getToken()
347
-	if r.useBasic {
348
-		req.SetBasicAuth(r.username, r.secret)
349
-	} else if token != "" {
350
-		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
320
+func (r *dockerBase) authorize(ctx context.Context, req *http.Request) error {
321
+	// Check if has header for host
322
+	if r.auth != nil {
323
+		if err := r.auth.Authorize(ctx, req); err != nil {
324
+			return err
325
+		}
351 326
 	}
327
+
328
+	return nil
352 329
 }
353 330
 
354 331
 func (r *dockerBase) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
355 332
 	ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", req.URL.String()))
356 333
 	log.G(ctx).WithField("request.headers", req.Header).WithField("request.method", req.Method).Debug("do request")
357
-	r.authorize(req)
334
+	if err := r.authorize(ctx, req); err != nil {
335
+		return nil, errors.Wrap(err, "failed to authorize")
336
+	}
358 337
 	resp, err := ctxhttp.Do(ctx, r.client, req)
359 338
 	if err != nil {
360 339
 		return nil, errors.Wrap(err, "failed to do request")
... ...
@@ -392,23 +389,14 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
392 392
 	last := responses[len(responses)-1]
393 393
 	if last.StatusCode == http.StatusUnauthorized {
394 394
 		log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized")
395
-		for _, c := range parseAuthHeader(last.Header) {
396
-			if c.scheme == bearerAuth {
397
-				if err := invalidAuthorization(c, responses); err != nil {
398
-					r.setToken("")
399
-					return nil, err
400
-				}
401
-				if err := r.setTokenAuth(ctx, c.parameters); err != nil {
402
-					return nil, err
403
-				}
404
-				return copyRequest(req)
405
-			} else if c.scheme == basicAuth {
406
-				if r.username != "" && r.secret != "" {
407
-					r.useBasic = true
408
-				}
395
+		if r.auth != nil {
396
+			if err := r.auth.AddResponses(ctx, responses); err == nil {
409 397
 				return copyRequest(req)
398
+			} else if !errdefs.IsNotImplemented(err) {
399
+				return nil, err
410 400
 			}
411 401
 		}
402
+
412 403
 		return nil, nil
413 404
 	} else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead {
414 405
 		// Support registries which have not properly implemented the HEAD method for
... ...
@@ -424,30 +412,6 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
424 424
 	return nil, nil
425 425
 }
426 426
 
427
-func invalidAuthorization(c challenge, responses []*http.Response) error {
428
-	errStr := c.parameters["error"]
429
-	if errStr == "" {
430
-		return nil
431
-	}
432
-
433
-	n := len(responses)
434
-	if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
435
-		return nil
436
-	}
437
-
438
-	return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
439
-}
440
-
441
-func sameRequest(r1, r2 *http.Request) bool {
442
-	if r1.Method != r2.Method {
443
-		return false
444
-	}
445
-	if *r1.URL != *r2.URL {
446
-		return false
447
-	}
448
-	return true
449
-}
450
-
451 427
 func copyRequest(req *http.Request) (*http.Request, error) {
452 428
 	ireq := *req
453 429
 	if ireq.GetBody != nil {
... ...
@@ -459,167 +423,3 @@ func copyRequest(req *http.Request) (*http.Request, error) {
459 459
 	}
460 460
 	return &ireq, nil
461 461
 }
462
-
463
-func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string) error {
464
-	realm, ok := params["realm"]
465
-	if !ok {
466
-		return errors.New("no realm specified for token auth challenge")
467
-	}
468
-
469
-	realmURL, err := url.Parse(realm)
470
-	if err != nil {
471
-		return fmt.Errorf("invalid token auth challenge realm: %s", err)
472
-	}
473
-
474
-	to := tokenOptions{
475
-		realm:   realmURL.String(),
476
-		service: params["service"],
477
-	}
478
-
479
-	to.scopes = getTokenScopes(ctx, params)
480
-	if len(to.scopes) == 0 {
481
-		return errors.Errorf("no scope specified for token auth challenge")
482
-	}
483
-
484
-	var token string
485
-	if r.secret != "" {
486
-		// Credential information is provided, use oauth POST endpoint
487
-		token, err = r.fetchTokenWithOAuth(ctx, to)
488
-		if err != nil {
489
-			return errors.Wrap(err, "failed to fetch oauth token")
490
-		}
491
-	} else {
492
-		// Do request anonymously
493
-		token, err = r.fetchToken(ctx, to)
494
-		if err != nil {
495
-			return errors.Wrap(err, "failed to fetch anonymous token")
496
-		}
497
-	}
498
-	r.setToken(token)
499
-
500
-	return nil
501
-}
502
-
503
-type tokenOptions struct {
504
-	realm   string
505
-	service string
506
-	scopes  []string
507
-}
508
-
509
-type postTokenResponse struct {
510
-	AccessToken  string    `json:"access_token"`
511
-	RefreshToken string    `json:"refresh_token"`
512
-	ExpiresIn    int       `json:"expires_in"`
513
-	IssuedAt     time.Time `json:"issued_at"`
514
-	Scope        string    `json:"scope"`
515
-}
516
-
517
-func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
518
-	form := url.Values{}
519
-	form.Set("scope", strings.Join(to.scopes, " "))
520
-	form.Set("service", to.service)
521
-	// TODO: Allow setting client_id
522
-	form.Set("client_id", "containerd-dist-tool")
523
-
524
-	if r.username == "" {
525
-		form.Set("grant_type", "refresh_token")
526
-		form.Set("refresh_token", r.secret)
527
-	} else {
528
-		form.Set("grant_type", "password")
529
-		form.Set("username", r.username)
530
-		form.Set("password", r.secret)
531
-	}
532
-
533
-	resp, err := ctxhttp.PostForm(ctx, r.client, to.realm, form)
534
-	if err != nil {
535
-		return "", err
536
-	}
537
-	defer resp.Body.Close()
538
-
539
-	// Registries without support for POST may return 404 for POST /v2/token.
540
-	// As of September 2017, GCR is known to return 404.
541
-	// As of February 2018, JFrog Artifactory is known to return 401.
542
-	if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
543
-		return r.fetchToken(ctx, to)
544
-	} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
545
-		b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
546
-		log.G(ctx).WithFields(logrus.Fields{
547
-			"status": resp.Status,
548
-			"body":   string(b),
549
-		}).Debugf("token request failed")
550
-		// TODO: handle error body and write debug output
551
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
552
-	}
553
-
554
-	decoder := json.NewDecoder(resp.Body)
555
-
556
-	var tr postTokenResponse
557
-	if err = decoder.Decode(&tr); err != nil {
558
-		return "", fmt.Errorf("unable to decode token response: %s", err)
559
-	}
560
-
561
-	return tr.AccessToken, nil
562
-}
563
-
564
-type getTokenResponse struct {
565
-	Token        string    `json:"token"`
566
-	AccessToken  string    `json:"access_token"`
567
-	ExpiresIn    int       `json:"expires_in"`
568
-	IssuedAt     time.Time `json:"issued_at"`
569
-	RefreshToken string    `json:"refresh_token"`
570
-}
571
-
572
-// getToken fetches a token using a GET request
573
-func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
574
-	req, err := http.NewRequest("GET", to.realm, nil)
575
-	if err != nil {
576
-		return "", err
577
-	}
578
-
579
-	reqParams := req.URL.Query()
580
-
581
-	if to.service != "" {
582
-		reqParams.Add("service", to.service)
583
-	}
584
-
585
-	for _, scope := range to.scopes {
586
-		reqParams.Add("scope", scope)
587
-	}
588
-
589
-	if r.secret != "" {
590
-		req.SetBasicAuth(r.username, r.secret)
591
-	}
592
-
593
-	req.URL.RawQuery = reqParams.Encode()
594
-
595
-	resp, err := ctxhttp.Do(ctx, r.client, req)
596
-	if err != nil {
597
-		return "", err
598
-	}
599
-	defer resp.Body.Close()
600
-
601
-	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
602
-		// TODO: handle error body and write debug output
603
-		return "", errors.Errorf("unexpected status: %s", resp.Status)
604
-	}
605
-
606
-	decoder := json.NewDecoder(resp.Body)
607
-
608
-	var tr getTokenResponse
609
-	if err = decoder.Decode(&tr); err != nil {
610
-		return "", fmt.Errorf("unable to decode token response: %s", err)
611
-	}
612
-
613
-	// `access_token` is equivalent to `token` and if both are specified
614
-	// the choice is undefined.  Canonicalize `access_token` by sticking
615
-	// things in `token`.
616
-	if tr.AccessToken != "" {
617
-		tr.Token = tr.AccessToken
618
-	}
619
-
620
-	if tr.Token == "" {
621
-		return "", ErrNoToken
622
-	}
623
-
624
-	return tr.Token, nil
625
-}
... ...
@@ -46,6 +46,9 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
46 46
 		return nil, err
47 47
 	}
48 48
 	path = filepath.Join(path, id)
49
+	if err := os.Mkdir(path, 0711); err != nil {
50
+		return nil, err
51
+	}
49 52
 	defer func() {
50 53
 		if err != nil {
51 54
 			os.RemoveAll(path)
... ...
@@ -60,10 +63,6 @@ func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
60 60
 			os.RemoveAll(workDir)
61 61
 		}
62 62
 	}()
63
-
64
-	if err := os.Mkdir(path, 0711); err != nil {
65
-		return nil, err
66
-	}
67 63
 	if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil {
68 64
 		return nil, err
69 65
 	}
70 66
new file mode 100644
... ...
@@ -0,0 +1,60 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"syscall"
20
+
21
+	"golang.org/x/sys/unix"
22
+)
23
+
24
+var signalMap = map[string]syscall.Signal{
25
+	"ABRT":   unix.SIGABRT,
26
+	"ALRM":   unix.SIGALRM,
27
+	"BUS":    unix.SIGBUS,
28
+	"CHLD":   unix.SIGCHLD,
29
+	"CLD":    unix.SIGCLD,
30
+	"CONT":   unix.SIGCONT,
31
+	"FPE":    unix.SIGFPE,
32
+	"HUP":    unix.SIGHUP,
33
+	"ILL":    unix.SIGILL,
34
+	"INT":    unix.SIGINT,
35
+	"IO":     unix.SIGIO,
36
+	"IOT":    unix.SIGIOT,
37
+	"KILL":   unix.SIGKILL,
38
+	"PIPE":   unix.SIGPIPE,
39
+	"POLL":   unix.SIGPOLL,
40
+	"PROF":   unix.SIGPROF,
41
+	"PWR":    unix.SIGPWR,
42
+	"QUIT":   unix.SIGQUIT,
43
+	"SEGV":   unix.SIGSEGV,
44
+	"STKFLT": unix.SIGSTKFLT,
45
+	"STOP":   unix.SIGSTOP,
46
+	"SYS":    unix.SIGSYS,
47
+	"TERM":   unix.SIGTERM,
48
+	"TRAP":   unix.SIGTRAP,
49
+	"TSTP":   unix.SIGTSTP,
50
+	"TTIN":   unix.SIGTTIN,
51
+	"TTOU":   unix.SIGTTOU,
52
+	"URG":    unix.SIGURG,
53
+	"USR1":   unix.SIGUSR1,
54
+	"USR2":   unix.SIGUSR2,
55
+	"VTALRM": unix.SIGVTALRM,
56
+	"WINCH":  unix.SIGWINCH,
57
+	"XCPU":   unix.SIGXCPU,
58
+	"XFSZ":   unix.SIGXFSZ,
59
+}
0 60
new file mode 100644
... ...
@@ -0,0 +1,58 @@
0
+// +build darwin freebsd solaris
1
+
2
+/*
3
+   Copyright The containerd Authors.
4
+
5
+   Licensed under the Apache License, Version 2.0 (the "License");
6
+   you may not use this file except in compliance with the License.
7
+   You may obtain a copy of the License at
8
+
9
+       http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+   Unless required by applicable law or agreed to in writing, software
12
+   distributed under the License is distributed on an "AS IS" BASIS,
13
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+   See the License for the specific language governing permissions and
15
+   limitations under the License.
16
+*/
17
+
18
+package containerd
19
+
20
+import (
21
+	"syscall"
22
+
23
+	"golang.org/x/sys/unix"
24
+)
25
+
26
+var signalMap = map[string]syscall.Signal{
27
+	"ABRT":   unix.SIGABRT,
28
+	"ALRM":   unix.SIGALRM,
29
+	"BUS":    unix.SIGBUS,
30
+	"CHLD":   unix.SIGCHLD,
31
+	"CONT":   unix.SIGCONT,
32
+	"FPE":    unix.SIGFPE,
33
+	"HUP":    unix.SIGHUP,
34
+	"ILL":    unix.SIGILL,
35
+	"INT":    unix.SIGINT,
36
+	"IO":     unix.SIGIO,
37
+	"IOT":    unix.SIGIOT,
38
+	"KILL":   unix.SIGKILL,
39
+	"PIPE":   unix.SIGPIPE,
40
+	"PROF":   unix.SIGPROF,
41
+	"QUIT":   unix.SIGQUIT,
42
+	"SEGV":   unix.SIGSEGV,
43
+	"STOP":   unix.SIGSTOP,
44
+	"SYS":    unix.SIGSYS,
45
+	"TERM":   unix.SIGTERM,
46
+	"TRAP":   unix.SIGTRAP,
47
+	"TSTP":   unix.SIGTSTP,
48
+	"TTIN":   unix.SIGTTIN,
49
+	"TTOU":   unix.SIGTTOU,
50
+	"URG":    unix.SIGURG,
51
+	"USR1":   unix.SIGUSR1,
52
+	"USR2":   unix.SIGUSR2,
53
+	"VTALRM": unix.SIGVTALRM,
54
+	"WINCH":  unix.SIGWINCH,
55
+	"XCPU":   unix.SIGXCPU,
56
+	"XFSZ":   unix.SIGXFSZ,
57
+}
0 58
new file mode 100644
... ...
@@ -0,0 +1,39 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"syscall"
20
+
21
+	"golang.org/x/sys/windows"
22
+)
23
+
24
+var signalMap = map[string]syscall.Signal{
25
+	"HUP":    syscall.Signal(windows.SIGHUP),
26
+	"INT":    syscall.Signal(windows.SIGINT),
27
+	"QUIT":   syscall.Signal(windows.SIGQUIT),
28
+	"SIGILL": syscall.Signal(windows.SIGILL),
29
+	"TRAP":   syscall.Signal(windows.SIGTRAP),
30
+	"ABRT":   syscall.Signal(windows.SIGABRT),
31
+	"BUS":    syscall.Signal(windows.SIGBUS),
32
+	"FPE":    syscall.Signal(windows.SIGFPE),
33
+	"KILL":   syscall.Signal(windows.SIGKILL),
34
+	"SEGV":   syscall.Signal(windows.SIGSEGV),
35
+	"PIPE":   syscall.Signal(windows.SIGPIPE),
36
+	"ALRM":   syscall.Signal(windows.SIGALRM),
37
+	"TERM":   syscall.Signal(windows.SIGTERM),
38
+}
0 39
new file mode 100644
... ...
@@ -0,0 +1,105 @@
0
+/*
1
+   Copyright The containerd Authors.
2
+
3
+   Licensed under the Apache License, Version 2.0 (the "License");
4
+   you may not use this file except in compliance with the License.
5
+   You may obtain a copy of the License at
6
+
7
+       http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+   Unless required by applicable law or agreed to in writing, software
10
+   distributed under the License is distributed on an "AS IS" BASIS,
11
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+   See the License for the specific language governing permissions and
13
+   limitations under the License.
14
+*/
15
+
16
+package containerd
17
+
18
+import (
19
+	"context"
20
+	"encoding/json"
21
+	"fmt"
22
+	"strconv"
23
+	"strings"
24
+	"syscall"
25
+
26
+	"github.com/containerd/containerd/content"
27
+	"github.com/containerd/containerd/images"
28
+	"github.com/opencontainers/image-spec/specs-go/v1"
29
+)
30
+
31
+// StopSignalLabel is a well-known containerd label for storing the stop
32
+// signal specified in the OCI image config
33
+const StopSignalLabel = "io.containerd.image.config.stop-signal"
34
+
35
+// GetStopSignal retrieves the container stop signal, specified by the
36
+// well-known containerd label (StopSignalLabel)
37
+func GetStopSignal(ctx context.Context, container Container, defaultSignal syscall.Signal) (syscall.Signal, error) {
38
+	labels, err := container.Labels(ctx)
39
+	if err != nil {
40
+		return -1, err
41
+	}
42
+
43
+	if stopSignal, ok := labels[StopSignalLabel]; ok {
44
+		return ParseSignal(stopSignal)
45
+	}
46
+
47
+	return defaultSignal, nil
48
+}
49
+
50
+// GetOCIStopSignal retrieves the stop signal specified in the OCI image config
51
+func GetOCIStopSignal(ctx context.Context, image Image, defaultSignal string) (string, error) {
52
+	_, err := ParseSignal(defaultSignal)
53
+	if err != nil {
54
+		return "", err
55
+	}
56
+	ic, err := image.Config(ctx)
57
+	if err != nil {
58
+		return "", err
59
+	}
60
+	var (
61
+		ociimage v1.Image
62
+		config   v1.ImageConfig
63
+	)
64
+	switch ic.MediaType {
65
+	case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config:
66
+		p, err := content.ReadBlob(ctx, image.ContentStore(), ic)
67
+		if err != nil {
68
+			return "", err
69
+		}
70
+
71
+		if err := json.Unmarshal(p, &ociimage); err != nil {
72
+			return "", err
73
+		}
74
+		config = ociimage.Config
75
+	default:
76
+		return "", fmt.Errorf("unknown image config media type %s", ic.MediaType)
77
+	}
78
+
79
+	if config.StopSignal == "" {
80
+		return defaultSignal, nil
81
+	}
82
+
83
+	return config.StopSignal, nil
84
+}
85
+
86
+// ParseSignal parses a given string into a syscall.Signal
87
+// it checks that the signal exists in the platform-appropriate signalMap
88
+func ParseSignal(rawSignal string) (syscall.Signal, error) {
89
+	s, err := strconv.Atoi(rawSignal)
90
+	if err == nil {
91
+		sig := syscall.Signal(s)
92
+		for _, msig := range signalMap {
93
+			if sig == msig {
94
+				return sig, nil
95
+			}
96
+		}
97
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
98
+	}
99
+	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
100
+	if !ok {
101
+		return -1, fmt.Errorf("unknown signal %q", rawSignal)
102
+	}
103
+	return signal, nil
104
+}
... ...
@@ -4,7 +4,7 @@ github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
4 4
 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
5 5
 github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
6 6
 github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
7
-github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
7
+github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
8 8
 github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
9 9
 github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
10 10
 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
... ...
@@ -20,7 +20,7 @@ github.com/gogo/protobuf v1.0.0
20 20
 github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
21 21
 github.com/golang/protobuf v1.1.0
22 22
 github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
23
-github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
23
+github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
24 24
 github.com/sirupsen/logrus v1.0.0
25 25
 github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
26 26
 golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
... ...
@@ -33,10 +33,10 @@ golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
33 33
 github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
34 34
 github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
35 35
 github.com/Microsoft/go-winio v0.4.10
36
-github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
36
+github.com/Microsoft/hcsshim v0.7.6
37 37
 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
38 38
 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
39
-github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
39
+github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
40 40
 github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
41 41
 gotest.tools v2.1.0
42 42
 github.com/google/go-cmp v0.1.0
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package devices
2 18
 
3 19
 import "fmt"
... ...
@@ -1,5 +1,21 @@
1 1
 // +build linux darwin freebsd solaris
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package devices
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package devices
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package driver
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build linux darwin freebsd solaris
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package driver
4 20
 
5 21
 import (
... ...
@@ -13,7 +29,11 @@ import (
13 13
 )
14 14
 
15 15
 func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
16
-	return devices.Mknod(path, mode, major, minor)
16
+	err := devices.Mknod(path, mode, major, minor)
17
+	if err != nil {
18
+		err = &os.PathError{Op: "mknod", Path: path, Err: err}
19
+	}
20
+	return err
17 21
 }
18 22
 
19 23
 func (d *driver) Mkfifo(path string, mode os.FileMode) error {
... ...
@@ -22,7 +42,11 @@ func (d *driver) Mkfifo(path string, mode os.FileMode) error {
22 22
 	}
23 23
 	// mknod with a mode that has ModeNamedPipe set creates a fifo, not a
24 24
 	// device.
25
-	return devices.Mknod(path, mode, 0, 0)
25
+	err := devices.Mknod(path, mode, 0, 0)
26
+	if err != nil {
27
+		err = &os.PathError{Op: "mkfifo", Path: path, Err: err}
28
+	}
29
+	return err
26 30
 }
27 31
 
28 32
 // Getxattr returns all of the extended attributes for the file at path p.
... ...
@@ -1,18 +1,33 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package driver
2 18
 
3 19
 import (
4 20
 	"os"
5 21
 
6 22
 	"github.com/containerd/continuity/sysx"
7
-	"github.com/pkg/errors"
8 23
 )
9 24
 
10 25
 func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
11
-	return errors.Wrap(ErrNotSupported, "cannot create device node on Windows")
26
+	return &os.PathError{Op: "mknod", Path: path, Err: ErrNotSupported}
12 27
 }
13 28
 
14 29
 func (d *driver) Mkfifo(path string, mode os.FileMode) error {
15
-	return errors.Wrap(ErrNotSupported, "cannot create fifo on Windows")
30
+	return &os.PathError{Op: "mkfifo", Path: path, Err: ErrNotSupported}
16 31
 }
17 32
 
18 33
 // Lchmod changes the mode of an file not following symlinks.
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package driver
2 18
 
3 19
 import (
... ...
@@ -15,5 +31,9 @@ func (d *driver) Lchmod(path string, mode os.FileMode) error {
15 15
 		return nil
16 16
 	}
17 17
 
18
-	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
18
+	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
19
+	if err != nil {
20
+		err = &os.PathError{Op: "lchmod", Path: path, Err: err}
21
+	}
22
+	return err
19 23
 }
... ...
@@ -1,5 +1,21 @@
1 1
 // +build darwin freebsd solaris
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package driver
4 20
 
5 21
 import (
... ...
@@ -10,5 +26,9 @@ import (
10 10
 
11 11
 // Lchmod changes the mode of a file not following symlinks.
12 12
 func (d *driver) Lchmod(path string, mode os.FileMode) error {
13
-	return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
13
+	err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
14
+	if err != nil {
15
+		err = &os.PathError{Op: "lchmod", Path: path, Err: err}
16
+	}
17
+	return err
14 18
 }
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package driver
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build solaris darwin freebsd
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build !windows
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build linux
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import "context"
... ...
@@ -1,5 +1,21 @@
1 1
 // +build !windows
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build windows
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import "os"
... ...
@@ -1,5 +1,21 @@
1 1
 // +build !windows
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import "os"
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -232,12 +248,6 @@ func walkLink(root, path string, linksWalked *int) (newpath string, islink bool,
232 232
 	if err != nil {
233 233
 		return "", false, err
234 234
 	}
235
-	if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) {
236
-		newpath = newpath[:len(root)]
237
-		if !strings.HasPrefix(newpath, "/") {
238
-			newpath = "/" + newpath
239
-		}
240
-	}
241 235
 	*linksWalked++
242 236
 	return newpath, true, nil
243 237
 }
... ...
@@ -1,5 +1,21 @@
1 1
 // +build darwin freebsd
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package fs
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package fs
2 18
 
3 19
 import "time"
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build linux darwin freebsd solaris
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package continuity
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import "os"
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package pathdriver
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package proto
2 18
 
3 19
 //go:generate protoc --go_out=. manifest.proto
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build linux darwin freebsd solaris
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package continuity
4 20
 
5 21
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package continuity
2 18
 
3 19
 import "os"
... ...
@@ -1,5 +1,21 @@
1 1
 // +build !windows
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package syscallx
4 20
 
5 21
 import "syscall"
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package syscallx
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package sysx
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package sysx
2 18
 
3 19
 import (
... ...
@@ -1,3 +1,19 @@
1
+/*
2
+   Copyright The containerd Authors.
3
+
4
+   Licensed under the Apache License, Version 2.0 (the "License");
5
+   you may not use this file except in compliance with the License.
6
+   You may obtain a copy of the License at
7
+
8
+       http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+   Unless required by applicable law or agreed to in writing, software
11
+   distributed under the License is distributed on an "AS IS" BASIS,
12
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+   See the License for the specific language governing permissions and
14
+   limitations under the License.
15
+*/
16
+
1 17
 package sysx
2 18
 
3 19
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build darwin freebsd
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package sysx
4 20
 
5 21
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build linux darwin
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package sysx
4 20
 
5 21
 import (
... ...
@@ -1,5 +1,21 @@
1 1
 // +build !linux,!darwin
2 2
 
3
+/*
4
+   Copyright The containerd Authors.
5
+
6
+   Licensed under the Apache License, Version 2.0 (the "License");
7
+   you may not use this file except in compliance with the License.
8
+   You may obtain a copy of the License at
9
+
10
+       http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+   Unless required by applicable law or agreed to in writing, software
13
+   distributed under the License is distributed on an "AS IS" BASIS,
14
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+   See the License for the specific language governing permissions and
16
+   limitations under the License.
17
+*/
18
+
3 19
 package sysx
4 20
 
5 21
 import (
6 22
new file mode 100644
... ...
@@ -0,0 +1,201 @@
0
+                                 Apache License
1
+                           Version 2.0, January 2004
2
+                        http://www.apache.org/licenses/
3
+
4
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
5
+
6
+   1. Definitions.
7
+
8
+      "License" shall mean the terms and conditions for use, reproduction,
9
+      and distribution as defined by Sections 1 through 9 of this document.
10
+
11
+      "Licensor" shall mean the copyright owner or entity authorized by
12
+      the copyright owner that is granting the License.
13
+
14
+      "Legal Entity" shall mean the union of the acting entity and all
15
+      other entities that control, are controlled by, or are under common
16
+      control with that entity. For the purposes of this definition,
17
+      "control" means (i) the power, direct or indirect, to cause the
18
+      direction or management of such entity, whether by contract or
19
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
+      outstanding shares, or (iii) beneficial ownership of such entity.
21
+
22
+      "You" (or "Your") shall mean an individual or Legal Entity
23
+      exercising permissions granted by this License.
24
+
25
+      "Source" form shall mean the preferred form for making modifications,
26
+      including but not limited to software source code, documentation
27
+      source, and configuration files.
28
+
29
+      "Object" form shall mean any form resulting from mechanical
30
+      transformation or translation of a Source form, including but
31
+      not limited to compiled object code, generated documentation,
32
+      and conversions to other media types.
33
+
34
+      "Work" shall mean the work of authorship, whether in Source or
35
+      Object form, made available under the License, as indicated by a
36
+      copyright notice that is included in or attached to the work
37
+      (an example is provided in the Appendix below).
38
+
39
+      "Derivative Works" shall mean any work, whether in Source or Object
40
+      form, that is based on (or derived from) the Work and for which the
41
+      editorial revisions, annotations, elaborations, or other modifications
42
+      represent, as a whole, an original work of authorship. For the purposes
43
+      of this License, Derivative Works shall not include works that remain
44
+      separable from, or merely link (or bind by name) to the interfaces of,
45
+      the Work and Derivative Works thereof.
46
+
47
+      "Contribution" shall mean any work of authorship, including
48
+      the original version of the Work and any modifications or additions
49
+      to that Work or Derivative Works thereof, that is intentionally
50
+      submitted to Licensor for inclusion in the Work by the copyright owner
51
+      or by an individual or Legal Entity authorized to submit on behalf of
52
+      the copyright owner. For the purposes of this definition, "submitted"
53
+      means any form of electronic, verbal, or written communication sent
54
+      to the Licensor or its representatives, including but not limited to
55
+      communication on electronic mailing lists, source code control systems,
56
+      and issue tracking systems that are managed by, or on behalf of, the
57
+      Licensor for the purpose of discussing and improving the Work, but
58
+      excluding communication that is conspicuously marked or otherwise
59
+      designated in writing by the copyright owner as "Not a Contribution."
60
+
61
+      "Contributor" shall mean Licensor and any individual or Legal Entity
62
+      on behalf of whom a Contribution has been received by Licensor and
63
+      subsequently incorporated within the Work.
64
+
65
+   2. Grant of Copyright License. Subject to the terms and conditions of
66
+      this License, each Contributor hereby grants to You a perpetual,
67
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
68
+      copyright license to reproduce, prepare Derivative Works of,
69
+      publicly display, publicly perform, sublicense, and distribute the
70
+      Work and such Derivative Works in Source or Object form.
71
+
72
+   3. Grant of Patent License. Subject to the terms and conditions of
73
+      this License, each Contributor hereby grants to You a perpetual,
74
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
75
+      (except as stated in this section) patent license to make, have made,
76
+      use, offer to sell, sell, import, and otherwise transfer the Work,
77
+      where such license applies only to those patent claims licensable
78
+      by such Contributor that are necessarily infringed by their
79
+      Contribution(s) alone or by combination of their Contribution(s)
80
+      with the Work to which such Contribution(s) was submitted. If You
81
+      institute patent litigation against any entity (including a
82
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
83
+      or a Contribution incorporated within the Work constitutes direct
84
+      or contributory patent infringement, then any patent licenses
85
+      granted to You under this License for that Work shall terminate
86
+      as of the date such litigation is filed.
87
+
88
+   4. Redistribution. You may reproduce and distribute copies of the
89
+      Work or Derivative Works thereof in any medium, with or without
90
+      modifications, and in Source or Object form, provided that You
91
+      meet the following conditions:
92
+
93
+      (a) You must give any other recipients of the Work or
94
+          Derivative Works a copy of this License; and
95
+
96
+      (b) You must cause any modified files to carry prominent notices
97
+          stating that You changed the files; and
98
+
99
+      (c) You must retain, in the Source form of any Derivative Works
100
+          that You distribute, all copyright, patent, trademark, and
101
+          attribution notices from the Source form of the Work,
102
+          excluding those notices that do not pertain to any part of
103
+          the Derivative Works; and
104
+
105
+      (d) If the Work includes a "NOTICE" text file as part of its
106
+          distribution, then any Derivative Works that You distribute must
107
+          include a readable copy of the attribution notices contained
108
+          within such NOTICE file, excluding those notices that do not
109
+          pertain to any part of the Derivative Works, in at least one
110
+          of the following places: within a NOTICE text file distributed
111
+          as part of the Derivative Works; within the Source form or
112
+          documentation, if provided along with the Derivative Works; or,
113
+          within a display generated by the Derivative Works, if and
114
+          wherever such third-party notices normally appear. The contents
115
+          of the NOTICE file are for informational purposes only and
116
+          do not modify the License. You may add Your own attribution
117
+          notices within Derivative Works that You distribute, alongside
118
+          or as an addendum to the NOTICE text from the Work, provided
119
+          that such additional attribution notices cannot be construed
120
+          as modifying the License.
121
+
122
+      You may add Your own copyright statement to Your modifications and
123
+      may provide additional or different license terms and conditions
124
+      for use, reproduction, or distribution of Your modifications, or
125
+      for any such Derivative Works as a whole, provided Your use,
126
+      reproduction, and distribution of the Work otherwise complies with
127
+      the conditions stated in this License.
128
+
129
+   5. Submission of Contributions. Unless You explicitly state otherwise,
130
+      any Contribution intentionally submitted for inclusion in the Work
131
+      by You to the Licensor shall be under the terms and conditions of
132
+      this License, without any additional terms or conditions.
133
+      Notwithstanding the above, nothing herein shall supersede or modify
134
+      the terms of any separate license agreement you may have executed
135
+      with Licensor regarding such Contributions.
136
+
137
+   6. Trademarks. This License does not grant permission to use the trade
138
+      names, trademarks, service marks, or product names of the Licensor,
139
+      except as required for reasonable and customary use in describing the
140
+      origin of the Work and reproducing the content of the NOTICE file.
141
+
142
+   7. Disclaimer of Warranty. Unless required by applicable law or
143
+      agreed to in writing, Licensor provides the Work (and each
144
+      Contributor provides its Contributions) on an "AS IS" BASIS,
145
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
146
+      implied, including, without limitation, any warranties or conditions
147
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
148
+      PARTICULAR PURPOSE. You are solely responsible for determining the
149
+      appropriateness of using or redistributing the Work and assume any
150
+      risks associated with Your exercise of permissions under this License.
151
+
152
+   8. Limitation of Liability. In no event and under no legal theory,
153
+      whether in tort (including negligence), contract, or otherwise,
154
+      unless required by applicable law (such as deliberate and grossly
155
+      negligent acts) or agreed to in writing, shall any Contributor be
156
+      liable to You for damages, including any direct, indirect, special,
157
+      incidental, or consequential damages of any character arising as a
158
+      result of this License or out of the use or inability to use the
159
+      Work (including but not limited to damages for loss of goodwill,
160
+      work stoppage, computer failure or malfunction, or any and all
161
+      other commercial damages or losses), even if such Contributor
162
+      has been advised of the possibility of such damages.
163
+
164
+   9. Accepting Warranty or Additional Liability. While redistributing
165
+      the Work or Derivative Works thereof, You may choose to offer,
166
+      and charge a fee for, acceptance of support, warranty, indemnity,
167
+      or other liability obligations and/or rights consistent with this
168
+      License. However, in accepting such obligations, You may act only
169
+      on Your own behalf and on Your sole responsibility, not on behalf
170
+      of any other Contributor, and only if You agree to indemnify,
171
+      defend, and hold each Contributor harmless for any liability
172
+      incurred by, or claims asserted against, such Contributor by reason
173
+      of your accepting any such warranty or additional liability.
174
+
175
+   END OF TERMS AND CONDITIONS
176
+
177
+   APPENDIX: How to apply the Apache License to your work.
178
+
179
+      To apply the Apache License to your work, attach the following
180
+      boilerplate notice, with the fields enclosed by brackets "{}"
181
+      replaced with your own identifying information. (Don't include
182
+      the brackets!)  The text should be enclosed in the appropriate
183
+      comment syntax for the file format. We also recommend that a
184
+      file or class name and description of purpose be included on the
185
+      same "printed page" as the copyright notice for easier
186
+      identification within third-party archives.
187
+
188
+   Copyright {yyyy} {name of copyright owner}
189
+
190
+   Licensed under the Apache License, Version 2.0 (the "License");
191
+   you may not use this file except in compliance with the License.
192
+   You may obtain a copy of the License at
193
+
194
+       http://www.apache.org/licenses/LICENSE-2.0
195
+
196
+   Unless required by applicable law or agreed to in writing, software
197
+   distributed under the License is distributed on an "AS IS" BASIS,
198
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
199
+   See the License for the specific language governing permissions and
200
+   limitations under the License.
0 201
new file mode 100644
... ...
@@ -0,0 +1,176 @@
0
+# cri
1
+<p align="center">
2
+<img src="https://kubernetes.io/images/favicon.png" width="50" height="50">
3
+<img src="https://containerd.io/img/containerd-dark.png" width="200" >
4
+</p>
5
+
6
+*Note: The standalone `cri-containerd` binary is end-of-life. `cri-containerd` is
7
+transitioning from a standalone binary that talks to containerd to a plugin within
8
+containerd. This github branch is for the `cri` plugin. See
9
+[standalone-cri-containerd branch](https://github.com/containerd/cri/tree/standalone-cri-containerd)
10
+for information about the standalone version of `cri-containerd`.*
11
+
12
+*Note: You need to [drain your node](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/) before upgrading from standalone `cri-containerd` to containerd with `cri` plugin.*
13
+
14
+[![Build Status](https://api.travis-ci.org/containerd/cri.svg?style=flat-square)](https://travis-ci.org/containerd/cri)
15
+[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/cri)](https://goreportcard.com/report/github.com/containerd/cri)
16
+
17
+`cri` is a [containerd](https://containerd.io/) plugin implementation of Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto).
18
+
19
+With it, you could run Kubernetes using containerd as the container runtime.
20
+![cri](./docs/cri.png)
21
+## Current Status
22
+`cri` is a native plugin of containerd 1.1 and above. It is built into containerd and enabled by default.
23
+
24
+`cri` is in GA:
25
+* It is feature complete.
26
+* It (the GA version) works with Kubernetes 1.10 and above.
27
+* It has passed all [CRI validation tests](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md).
28
+* It has passed all [node e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-node-tests.md).
29
+* It has passed all [e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-tests.md).
30
+
31
+See [test dashboard](https://k8s-testgrid.appspot.com/sig-node-containerd)
32
+## Support Metrics
33
+| CRI-Containerd Version | Containerd Version | Kubernetes Version | CRI Version |
34
+|:----------------------:|:------------------:|:------------------:|:-----------:|
35
+|     v1.0.0-alpha.x     |                    |      1.7, 1.8      |   v1alpha1  |
36
+|      v1.0.0-beta.x     |                    |        1.9         |   v1alpha1  |
37
+|       End-Of-Life      |        v1.1        |        1.10+       |   v1alpha2  |
38
+|                        |        HEAD        |        1.10+       |   v1alpha2  |
39
+
40
+## Production Quality Cluster on GCE
41
+For a production quality cluster on GCE brought up with `kube-up.sh` refer [here](docs/kube-up.md).
42
+## Installing with Ansible and Kubeadm
43
+For a multi node cluster installer and bring up steps using ansible and kubeadm refer [here](contrib/ansible/README.md).
44
+## Custom Installation
45
+For non ansible users, you can download the `cri-containerd` release tarball and deploy
46
+kubernetes cluster using kubeadm as described [here](docs/installation.md).
47
+## Getting Started for Developers
48
+### Binary Dependencies and Specifications
49
+The current release of the `cri` plugin has the following dependencies:
50
+* [containerd](https://github.com/containerd/containerd)
51
+* [runc](https://github.com/opencontainers/runc)
52
+* [CNI](https://github.com/containernetworking/cni)
53
+
54
+See [versions](./vendor.conf) of these dependencies `cri` is tested with.
55
+
56
+As containerd and runc move to their respective general availability releases,
57
+we will do our best to rebase/retest `cri` with these releases on a
58
+weekly/monthly basis. Similarly, given that `cri` uses the Open
59
+Container Initiative (OCI) [image](https://github.com/opencontainers/image-spec)
60
+and [runtime](https://github.com/opencontainers/runtime-spec) specifications, we
61
+will also do our best to update `cri` to the latest releases of these
62
+specifications as appropriate.
63
+### Install Dependencies
64
+1. Install development libraries:
65
+* **libseccomp development library.** Required by `cri` and runc seccomp support. `libseccomp-dev` (Ubuntu, Debian) / `libseccomp-devel`
66
+(Fedora, CentOS, RHEL). On releases of Ubuntu <=Trusty and Debian <=jessie a
67
+backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty.
68
+* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL)
69
+2. Install **`socat`** (required by portforward).
70
+2. Install and setup a go 1.10 development environment.
71
+3. Make a local clone of this repository.
72
+4. Install binary dependencies by running the following command from your cloned `cri/` project directory:
73
+```bash
74
+# Note: install.deps installs the above mentioned runc, containerd, and CNI
75
+# binary dependencies. install.deps is only provided for general use and ease of
76
+# testing. To customize `runc` and `containerd` build tags and/or to configure
77
+# `cni`, please follow instructions in their documents.
78
+make install.deps
79
+```
80
+### Build and Install `cri`
81
+To build and install a version of containerd with the `cri` plugin, enter the
82
+following commands from your `cri` project directory:
83
+```bash
84
+make
85
+sudo make install
86
+```
87
+*NOTE: The version of containerd built and installed from the `Makefile` is only for
88
+testing purposes. The version tag carries the suffix "-TEST".*
89
+#### Build Tags
90
+`cri` supports optional build tags for compiling support of various features.
91
+To add build tags to the make option the `BUILD_TAGS` variable must be set.
92
+
93
+```bash
94
+make BUILD_TAGS='seccomp apparmor'
95
+```
96
+
97
+| Build Tag | Feature                            | Dependency                      |
98
+|-----------|------------------------------------|---------------------------------|
99
+| seccomp   | syscall filtering                  | libseccomp development library  |
100
+| selinux   | selinux process and mount labeling | <none>                          |
101
+| apparmor  | apparmor profile support           | <none>                          |
102
+### Validate Your `cri` Setup
103
+A Kubernetes incubator project called [cri-tools](https://github.com/kubernetes-sigs/cri-tools)
104
+includes programs for exercising CRI implementations such as the `cri` plugin.
105
+More importantly, cri-tools includes the program `critest` which is used for running
106
+[CRI Validation Testing](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md).
107
+
108
+Run the CRI Validation test to validate your installation of `containerd` with `cri` built in:
109
+```bash
110
+make test-cri
111
+```
112
+### Running a Kubernetes local cluster
113
+If you already have a working development environment for supported Kubernetes
114
+version, you can try `cri` in a local cluster:
115
+
116
+1. Start the version of `containerd` with `cri` plugin that you built and installed
117
+above as root in a first terminal:
118
+```bash
119
+sudo containerd
120
+```
121
+2. From the Kubernetes project directory startup a local cluster using `containerd`:
122
+```bash
123
+CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='unix:///run/containerd/containerd.sock' ./hack/local-up-cluster.sh
124
+```
125
+### Test
126
+See [here](./docs/testing.md) for information about test.
127
+## Using crictl
128
+See [here](./docs/crictl.md) for information about using `crictl` to debug
129
+pods, containers, and images.
130
+## Configurations
131
+See [here](./docs/config.md) for information about how to configure cri plugins
132
+and [here](https://github.com/containerd/containerd/blob/master/docs/man/containerd-config.1.md)
133
+for information about how to configure containerd
134
+## Documentation
135
+See [here](./docs) for additional documentation.
136
+## Contributing
137
+Interested in contributing? Check out the [documentation](./CONTRIBUTING.md).
138
+
139
+## Communication
140
+This project was originally established in April of 2017 in the Kubernetes
141
+Incubator program. After reaching the Beta stage, In January of 2018, the
142
+project was merged into [containerd](https://github.com/containerd/containerd).
143
+
144
+For async communication and long running discussions please use issues and pull
145
+requests on this github repo. This will be the best place to discuss design and
146
+implementation.
147
+
148
+For sync communication we have a community slack with a #containerd channel that
149
+everyone is welcome to join and chat about development.
150
+
151
+**Slack:** https://dockr.ly/community
152
+
153
+## Other Communications
154
+As this project is tightly coupled to CRI and CRI-Tools and they are Kubernetes
155
+projects, some of our project communications take place in the Kubernetes' SIG:
156
+`sig-node.`
157
+
158
+For more information about `sig-node`, `CRI`, and the `CRI-Tools` projects:
159
+* [sig-node community site](https://github.com/kubernetes/community/tree/master/sig-node)
160
+* Slack: `#sig-node` channel in Kubernetes (kubernetes.slack.com)
161
+* Mailing List: https://groups.google.com/forum/#!forum/kubernetes-sig-node
162
+
163
+### Reporting Security Issues
164
+
165
+__If you are reporting a security issue, please reach out discreetly at security@containerd.io__.
166
+
167
+## Licenses
168
+The containerd codebase is released under the [Apache 2.0 license](https://github.com/containerd/containerd/blob/master/LICENSE.code).
169
+The README.md file, and files in the "docs" folder are licensed under the
170
+Creative Commons Attribution 4.0 International License under the terms and
171
+conditions set forth in the file "[LICENSE.docs](https://github.com/containerd/containerd/blob/master/LICENSE.docs)". You may obtain a duplicate
172
+copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.
173
+
174
+## Code of Conduct
175
+This project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
0 176
new file mode 100644
... ...
@@ -0,0 +1,42 @@
0
+/*
1
+Copyright 2017 The Kubernetes Authors.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+    http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+package util
17
+
18
+import (
19
+	"encoding/json"
20
+
21
+	"github.com/pkg/errors"
22
+)
23
+
24
+// DeepCopy makes a deep copy from src into dst.
25
+func DeepCopy(dst interface{}, src interface{}) error {
26
+	if dst == nil {
27
+		return errors.New("dst cannot be nil")
28
+	}
29
+	if src == nil {
30
+		return errors.New("src cannot be nil")
31
+	}
32
+	bytes, err := json.Marshal(src)
33
+	if err != nil {
34
+		return errors.Wrap(err, "unable to marshal src")
35
+	}
36
+	err = json.Unmarshal(bytes, dst)
37
+	if err != nil {
38
+		return errors.Wrap(err, "unable to unmarshal into dst")
39
+	}
40
+	return nil
41
+}
0 42
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+/*
1
+Copyright 2017 The Kubernetes Authors.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+    http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+package util
17
+
18
+import (
19
+	"encoding/hex"
20
+	"math/rand"
21
+)
22
+
23
+// GenerateID generates a random unique id.
24
+func GenerateID() string {
25
+	b := make([]byte, 32)
26
+	rand.Read(b)
27
+	return hex.EncodeToString(b)
28
+}
0 29
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+/*
1
+Copyright 2017 The Kubernetes Authors.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+    http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+package util
17
+
18
+import (
19
+	"github.com/docker/distribution/reference"
20
+)
21
+
22
+// NormalizeImageRef normalizes the image reference following the docker convention. This is added
23
+// mainly for backward compatibility.
24
+// The reference returned can only be either tagged or digested. For reference contains both tag
25
+// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
26
+// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
27
+// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
28
+func NormalizeImageRef(ref string) (reference.Named, error) {
29
+	named, err := reference.ParseNormalizedNamed(ref)
30
+	if err != nil {
31
+		return nil, err
32
+	}
33
+	if _, ok := named.(reference.NamedTagged); ok {
34
+		if canonical, ok := named.(reference.Canonical); ok {
35
+			// The reference is both tagged and digested, only
36
+			// return digested.
37
+			newNamed, err := reference.WithName(canonical.Name())
38
+			if err != nil {
39
+				return nil, err
40
+			}
41
+			newCanonical, err := reference.WithDigest(newNamed, canonical.Digest())
42
+			if err != nil {
43
+				return nil, err
44
+			}
45
+			return newCanonical, nil
46
+		}
47
+	}
48
+	return reference.TagNameOnly(named), nil
49
+}
0 50
new file mode 100644
... ...
@@ -0,0 +1,59 @@
0
+/*
1
+Copyright 2017 The Kubernetes Authors.
2
+
3
+Licensed under the Apache License, Version 2.0 (the "License");
4
+you may not use this file except in compliance with the License.
5
+You may obtain a copy of the License at
6
+
7
+    http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+Unless required by applicable law or agreed to in writing, software
10
+distributed under the License is distributed on an "AS IS" BASIS,
11
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+See the License for the specific language governing permissions and
13
+limitations under the License.
14
+*/
15
+
16
+package util
17
+
18
+import "strings"
19
+
20
+// InStringSlice checks whether a string is inside a string slice.
21
+// Comparison is case insensitive.
22
+func InStringSlice(ss []string, str string) bool {
23
+	for _, s := range ss {
24
+		if strings.ToLower(s) == strings.ToLower(str) {
25
+			return true
26
+		}
27
+	}
28
+	return false
29
+}
30
+
31
+// SubtractStringSlice subtracts string from string slice.
32
+// Comparison is case insensitive.
33
+func SubtractStringSlice(ss []string, str string) []string {
34
+	var res []string
35
+	for _, s := range ss {
36
+		if strings.ToLower(s) == strings.ToLower(str) {
37
+			continue
38
+		}
39
+		res = append(res, s)
40
+	}
41
+	return res
42
+}
43
+
44
+// MergeStringSlices merges 2 string slices into one and remove duplicated elements.
45
+func MergeStringSlices(a []string, b []string) []string {
46
+	set := map[string]struct{}{}
47
+	for _, s := range a {
48
+		set[s] = struct{}{}
49
+	}
50
+	for _, s := range b {
51
+		set[s] = struct{}{}
52
+	}
53
+	var ss []string
54
+	for s := range set {
55
+		ss = append(ss, s)
56
+	}
57
+	return ss
58
+}
0 59
new file mode 100644
... ...
@@ -0,0 +1,78 @@
0
+github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
1
+github.com/blang/semver v3.1.0
2
+github.com/boltdb/bolt v1.3.1
3
+github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
4
+github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
5
+github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
6
+github.com/containerd/containerd 1950f791d9225ffe061c77e74e292bcb3c428a04
7
+github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
8
+github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
9
+github.com/containerd/go-cni 6d7b509a054a3cb1c35ed1865d4fde2f0cb547cd
10
+github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
11
+github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
12
+github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
13
+github.com/containernetworking/cni v0.6.0
14
+github.com/containernetworking/plugins v0.7.0
15
+github.com/coreos/go-systemd v14
16
+github.com/davecgh/go-spew v1.1.0
17
+github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621
18
+github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
19
+github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
20
+github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
21
+github.com/docker/go-units v0.3.1
22
+github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
23
+github.com/emicklei/go-restful v2.2.1
24
+github.com/ghodss/yaml v1.0.0
25
+github.com/godbus/dbus v3
26
+github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
27
+github.com/gogo/protobuf v1.0.0
28
+github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed
29
+github.com/golang/protobuf v1.1.0
30
+github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c
31
+github.com/grpc-ecosystem/go-grpc-prometheus v1.1
32
+github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55
33
+github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
34
+github.com/json-iterator/go 1.1.5
35
+github.com/matttproud/golang_protobuf_extensions v1.0.0
36
+github.com/Microsoft/go-winio v0.4.10
37
+github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
38
+github.com/modern-go/concurrent 1.0.3
39
+github.com/modern-go/reflect2 1.0.1
40
+github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
41
+github.com/opencontainers/image-spec v1.0.1
42
+github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
43
+github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce
44
+github.com/opencontainers/runtime-tools v0.6.0
45
+github.com/opencontainers/selinux b6fa367ed7f534f9ba25391cc2d467085dbb445a
46
+github.com/pkg/errors v0.8.0
47
+github.com/pmezard/go-difflib v1.0.0
48
+github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
49
+github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
50
+github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
51
+github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
52
+github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
53
+github.com/sirupsen/logrus v1.0.0
54
+github.com/stretchr/testify v1.1.4
55
+github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
56
+github.com/tchap/go-patricia v2.2.6
57
+github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
58
+github.com/xeipuuv/gojsonpointer 4e3ac2762d5f479393488629ee9370b50873b3a6
59
+github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b
60
+github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874
61
+golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067
62
+golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
63
+golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4
64
+golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
65
+golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys
66
+golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
67
+golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
68
+google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
69
+google.golang.org/grpc v1.12.0
70
+gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
71
+gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77
72
+k8s.io/api 012f271b5d41baad56190c5f1ae19bff16df0fd8
73
+k8s.io/apimachinery 6429050ef506887d121f3e7306e894f8900d8a63
74
+k8s.io/apiserver e9312c15296b6c2c923ebd5031ff5d1d5fd022d7
75
+k8s.io/client-go 37c3c02ec96533daec0dbda1f39a6b1d68505c79
76
+k8s.io/kubernetes v1.12.0-beta.1
77
+k8s.io/utils 982821ea41da7e7c15f3d3738921eb2e7e241ccd
... ...
@@ -110,12 +110,16 @@ func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) err
110 110
 	}
111 111
 
112 112
 	select {
113
+	case <-ctx.Done():
114
+		return ctx.Err()
113 115
 	case c.calls <- call:
114 116
 	case <-c.done:
115 117
 		return c.err
116 118
 	}
117 119
 
118 120
 	select {
121
+	case <-ctx.Done():
122
+		return ctx.Err()
119 123
 	case err := <-errs:
120 124
 		return filterCloseErr(err)
121 125
 	case <-c.done:
... ...
@@ -127,13 +127,13 @@ func (s *Server) Serve(ctx context.Context, l net.Listener) error {
127 127
 
128 128
 func (s *Server) Shutdown(ctx context.Context) error {
129 129
 	s.mu.Lock()
130
-	lnerr := s.closeListeners()
131 130
 	select {
132 131
 	case <-s.done:
133 132
 	default:
134 133
 		// protected by mutex
135 134
 		close(s.done)
136 135
 	}
136
+	lnerr := s.closeListeners()
137 137
 	s.mu.Unlock()
138 138
 
139 139
 	ticker := time.NewTicker(200 * time.Millisecond)
... ...
@@ -87,6 +87,18 @@ You can run a specific test case by setting the `TESTFLAGS` variable.
87 87
 # make test TESTFLAGS="-run=SomeTestFunction"
88 88
 ```
89 89
 
90
+You can run a specific integration test by setting the `TESTPATH` variable.
91
+
92
+```bash
93
+# make test TESTPATH="/checkpoint.bats"
94
+```
95
+
96
+You can run a test in your proxy environment by setting `DOCKER_BUILD_PROXY` and `DOCKER_RUN_PROXY` variables.
97
+
98
+```bash
99
+# make test DOCKER_BUILD_PROXY="--build-arg HTTP_PROXY=http://yourproxy/" DOCKER_RUN_PROXY="-e HTTP_PROXY=http://yourproxy/"
100
+```
101
+
90 102
 ### Dependencies Management
91 103
 
92 104
 `runc` uses [vndr](https://github.com/LK4D4/vndr) for dependencies management.
... ...
@@ -13,7 +13,7 @@ import (
13 13
 	"strings"
14 14
 	"time"
15 15
 
16
-	"github.com/docker/go-units"
16
+	units "github.com/docker/go-units"
17 17
 )
18 18
 
19 19
 const (
... ...
@@ -103,7 +103,7 @@ func FindCgroupMountpointDir() (string, error) {
103 103
 		}
104 104
 
105 105
 		if postSeparatorFields[0] == "cgroup" {
106
-			// Check that the mount is properly formated.
106
+			// Check that the mount is properly formatted.
107 107
 			if numPostFields < 3 {
108 108
 				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
109 109
 			}
... ...
@@ -151,19 +151,20 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount,
151 151
 			Root:       fields[3],
152 152
 		}
153 153
 		for _, opt := range strings.Split(fields[len(fields)-1], ",") {
154
-			if !ss[opt] {
154
+			seen, known := ss[opt]
155
+			if !known || (!all && seen) {
155 156
 				continue
156 157
 			}
158
+			ss[opt] = true
157 159
 			if strings.HasPrefix(opt, cgroupNamePrefix) {
158
-				m.Subsystems = append(m.Subsystems, opt[len(cgroupNamePrefix):])
159
-			} else {
160
-				m.Subsystems = append(m.Subsystems, opt)
161
-			}
162
-			if !all {
163
-				numFound++
160
+				opt = opt[len(cgroupNamePrefix):]
164 161
 			}
162
+			m.Subsystems = append(m.Subsystems, opt)
163
+			numFound++
164
+		}
165
+		if len(m.Subsystems) > 0 || all {
166
+			res = append(res, m)
165 167
 		}
166
-		res = append(res, m)
167 168
 	}
168 169
 	if err := scanner.Err(); err != nil {
169 170
 		return nil, err
... ...
@@ -187,7 +188,7 @@ func GetCgroupMounts(all bool) ([]Mount, error) {
187 187
 
188 188
 	allMap := make(map[string]bool)
189 189
 	for s := range allSubsystems {
190
-		allMap[s] = true
190
+		allMap[s] = false
191 191
 	}
192 192
 	return getCgroupMountsHelper(allMap, f, all)
193 193
 }
... ...
@@ -262,7 +263,7 @@ func getCgroupPathHelper(subsystem, cgroup string) (string, error) {
262 262
 	}
263 263
 
264 264
 	// This is needed for nested containers, because in /proc/self/cgroup we
265
-	// see pathes from host, which don't exist in container.
265
+	// see paths from host, which don't exist in container.
266 266
 	relCgroup, err := filepath.Rel(root, cgroup)
267 267
 	if err != nil {
268 268
 		return "", err
... ...
@@ -10,8 +10,8 @@ The `nsenter` package will `import "C"` and it uses [cgo](https://golang.org/cmd
10 10
 package. In cgo, if the import of "C" is immediately preceded by a comment, that comment, 
11 11
 called the preamble, is used as a header when compiling the C parts of the package.
12 12
 So every time we  import package `nsenter`, the C code function `nsexec()` would be 
13
-called. And package `nsenter` is now only imported in `main_unix.go`, so every time
14
-before we call `cmd.Start` on linux, that C code would run.
13
+called. And package `nsenter` is only imported in `init.go`, so every time the runc
14
+`init` command is invoked, that C code is run.
15 15
 
16 16
 Because `nsexec()` must be run before the Go runtime in order to use the
17 17
 Linux kernel namespace, you must `import` this library into a package if
... ...
@@ -37,7 +37,7 @@ the parent `nsexec()` will exit and the child `nsexec()` process will
37 37
 return to allow the Go runtime take over.
38 38
 
39 39
 NOTE: We do both `setns(2)` and `clone(2)` even if we don't have any
40
-CLONE_NEW* clone flags because we must fork a new process in order to
40
+`CLONE_NEW*` clone flags because we must fork a new process in order to
41 41
 enter the PID namespace.
42 42
 
43 43
 
... ...
@@ -211,7 +211,7 @@ static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len)
211 211
 
212 212
 	/*
213 213
 	 * If @app is NULL, execve will segfault. Just check it here and bail (if
214
-	 * we're in this path, the caller is already getting desparate and there
214
+	 * we're in this path, the caller is already getting desperate and there
215 215
 	 * isn't a backup to this failing). This usually would be a configuration
216 216
 	 * or programming issue.
217 217
 	 */