Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -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 |
} |
| ... | ... |
@@ -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 |
+[](https://travis-ci.org/containerd/cri) |
|
| 15 |
+[](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 |
+ |
|
| 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 |
*/ |