vendor: update containerd to v1.2.0-rc.1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>docker-18.09
parent
c8f1541b0b
commit
fb9e2c1030
|
@ -232,7 +232,7 @@ export JAEGER_TRACE=0.0.0.0:6831
|
|||
|
||||
### Supported runc version
|
||||
|
||||
During development, BuildKit is tested with the version of runc that is being used by the containerd repository. Please refer to [runc.md](https://github.com/containerd/containerd/blob/v1.1.3/RUNC.md) for more information.
|
||||
During development, BuildKit is tested with the version of runc that is being used by the containerd repository. Please refer to [runc.md](https://github.com/containerd/containerd/blob/v1.2.0-rc.1/RUNC.md) for more information.
|
||||
|
||||
### Running BuildKit without root privileges
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ type buildOpt struct {
|
|||
func main() {
|
||||
var opt buildOpt
|
||||
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.1.3", "containerd version")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
|
||||
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
|
||||
flag.Parse()
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ type buildOpt struct {
|
|||
func main() {
|
||||
var opt buildOpt
|
||||
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.1.3", "containerd version")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
|
||||
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
|
||||
flag.Parse()
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ type buildOpt struct {
|
|||
func main() {
|
||||
var opt buildOpt
|
||||
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.1.3", "containerd version")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
|
||||
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
|
||||
flag.Parse()
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ type buildOpt struct {
|
|||
func main() {
|
||||
var opt buildOpt
|
||||
flag.BoolVar(&opt.withContainerd, "with-containerd", true, "enable containerd worker")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.1.3", "containerd version")
|
||||
flag.StringVar(&opt.containerd, "containerd", "v1.2.0-rc.1", "containerd version")
|
||||
flag.StringVar(&opt.runc, "runc", "dd56ece8236d6d9e5bed4ea0c31fe53c7b873ff4", "runc version")
|
||||
flag.StringVar(&opt.buildkit, "buildkit", "master", "buildkit version")
|
||||
flag.Parse()
|
||||
|
|
|
@ -43,7 +43,7 @@ func run() error {
|
|||
_ = buildkitd
|
||||
|
||||
containerd, err := gb.BuildExe(gobuild.BuildOpt{
|
||||
Source: llb.Git("github.com/containerd/containerd", "v1.1.3"),
|
||||
Source: llb.Git("github.com/containerd/containerd", "v1.2.0-rc.1"),
|
||||
MountPath: "/go/src/github.com/containerd/containerd",
|
||||
Pkg: "github.com/containerd/containerd/cmd/containerd",
|
||||
BuildTags: []string{"no_btrfs"},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
ARG RUNC_VERSION=00dc70017d222b178a002ed30e9321b12647af2d
|
||||
ARG CONTAINERD_VERSION=v1.1.3
|
||||
ARG CONTAINERD_VERSION=v1.2.0-rc.1
|
||||
# containerd v1.0 for integration tests
|
||||
ARG CONTAINERD10_VERSION=v1.0.3
|
||||
# available targets: buildkitd, buildkitd.oci_only, buildkitd.containerd_only
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# syntax = tonistiigi/dockerfile:runmount20180925
|
||||
|
||||
ARG RUNC_VERSION=00dc70017d222b178a002ed30e9321b12647af2d
|
||||
ARG CONTAINERD_VERSION=v1.1.3
|
||||
ARG CONTAINERD_VERSION=v1.2.0-rc.1
|
||||
# containerd v1.0 for integration tests
|
||||
ARG CONTAINERD10_VERSION=v1.0.3
|
||||
# available targets: buildkitd, buildkitd.oci_only, buildkitd.containerd_only
|
||||
|
|
|
@ -6,7 +6,7 @@ github.com/davecgh/go-spew v1.1.0
|
|||
github.com/pmezard/go-difflib v1.0.0
|
||||
golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2
|
||||
|
||||
github.com/containerd/containerd d97a907f7f781c0ab8340877d8e6b53cc7f1c2f6
|
||||
github.com/containerd/containerd 1a5f9a3434ac53c0e9d27093ecc588e0c281c333
|
||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
||||
github.com/sirupsen/logrus v1.0.0
|
||||
|
@ -16,9 +16,9 @@ golang.org/x/net 0ed95abb35c445290478a5348a7b38bb154135fd
|
|||
github.com/gogo/protobuf v1.0.0
|
||||
github.com/gogo/googleapis b23578765ee54ff6bceff57f397d833bf4ca6869
|
||||
github.com/golang/protobuf v1.1.0
|
||||
github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
|
||||
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
|
||||
github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
|
||||
github.com/Microsoft/go-winio v0.4.11
|
||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
|
||||
|
@ -28,8 +28,9 @@ google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
|||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||
github.com/Microsoft/hcsshim v0.7.3
|
||||
github.com/Microsoft/hcsshim v0.7.9
|
||||
golang.org/x/crypto 0709b304e793a5edb4a2c0145f281ecdc20838a4
|
||||
github.com/containerd/cri 8506fe836677cc3bb23a16b68145128243d843b5 # release/1.2 branch
|
||||
|
||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
||||
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
|
||||
// HNSEndpoint represents a network endpoint in HNS
|
||||
type HNSEndpoint = hns.HNSEndpoint
|
||||
// Namespace represents a Compartment.
|
||||
type Namespace = hns.Namespace
|
||||
|
||||
//SystemType represents the type of the system on which actions are done
|
||||
type SystemType string
|
||||
|
|
|
@ -9,15 +9,15 @@ import (
|
|||
// the parent layer provided.
|
||||
func CreateLayer(path, parent string) error {
|
||||
title := "hcsshim::CreateLayer "
|
||||
logrus.Debugf(title+"Flavour %d ID %s parent %s", path, parent)
|
||||
logrus.Debugf(title+"ID %s parent %s", path, parent)
|
||||
|
||||
err := createLayer(&stdDriverInfo, path, parent)
|
||||
if err != nil {
|
||||
err = hcserror.Errorf(err, title, "path=%s parent=%s flavour=%d", path, parent)
|
||||
err = hcserror.Errorf(err, title, "path=%s parent=%s", path, parent)
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" - succeeded path=%s parent=%s flavour=%d", path, parent)
|
||||
logrus.Debugf(title+"- succeeded path=%s parent=%s", path, parent)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
package hcsshim
|
||||
|
||||
// IsTP4 returns whether the currently running Windows build is at least TP4.
|
||||
func IsTP4() bool {
|
||||
return false
|
||||
}
|
|
@ -443,7 +443,7 @@ type ContentClient interface {
|
|||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be ommitted on subsequent writes.
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
|
@ -658,7 +658,7 @@ type ContentServer interface {
|
|||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be ommitted on subsequent writes.
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
|
|
|
@ -55,7 +55,7 @@ service Content {
|
|||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be ommitted on subsequent writes.
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
|
|
|
@ -20,9 +20,15 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -37,6 +43,13 @@ const (
|
|||
Gzip
|
||||
)
|
||||
|
||||
const disablePigzEnv = "CONTAINERD_DISABLE_PIGZ"
|
||||
|
||||
var (
|
||||
initPigz sync.Once
|
||||
unpigzPath string
|
||||
)
|
||||
|
||||
var (
|
||||
bufioReader32KPool = &sync.Pool{
|
||||
New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) },
|
||||
|
@ -79,6 +92,36 @@ func (w *writeCloserWrapper) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type bufferedReader struct {
|
||||
buf *bufio.Reader
|
||||
}
|
||||
|
||||
func newBufferedReader(r io.Reader) *bufferedReader {
|
||||
buf := bufioReader32KPool.Get().(*bufio.Reader)
|
||||
buf.Reset(r)
|
||||
return &bufferedReader{buf}
|
||||
}
|
||||
|
||||
func (r *bufferedReader) Read(p []byte) (n int, err error) {
|
||||
if r.buf == nil {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n, err = r.buf.Read(p)
|
||||
if err == io.EOF {
|
||||
r.buf.Reset(nil)
|
||||
bufioReader32KPool.Put(r.buf)
|
||||
r.buf = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *bufferedReader) Peek(n int) ([]byte, error) {
|
||||
if r.buf == nil {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return r.buf.Peek(n)
|
||||
}
|
||||
|
||||
// DetectCompression detects the compression algorithm of the source.
|
||||
func DetectCompression(source []byte) Compression {
|
||||
for compression, m := range map[Compression][]byte{
|
||||
|
@ -97,8 +140,7 @@ func DetectCompression(source []byte) Compression {
|
|||
|
||||
// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
|
||||
func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
|
||||
buf := bufioReader32KPool.Get().(*bufio.Reader)
|
||||
buf.Reset(archive)
|
||||
buf := newBufferedReader(archive)
|
||||
bs, err := buf.Peek(10)
|
||||
if err != nil && err != io.EOF {
|
||||
// Note: we'll ignore any io.EOF error because there are some odd
|
||||
|
@ -110,22 +152,29 @@ func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
closer := func() error {
|
||||
buf.Reset(nil)
|
||||
bufioReader32KPool.Put(buf)
|
||||
return nil
|
||||
}
|
||||
switch compression := DetectCompression(bs); compression {
|
||||
case Uncompressed:
|
||||
readBufWrapper := &readCloserWrapper{buf, compression, closer}
|
||||
return readBufWrapper, nil
|
||||
return &readCloserWrapper{
|
||||
Reader: buf,
|
||||
compression: compression,
|
||||
}, nil
|
||||
case Gzip:
|
||||
gzReader, err := gzip.NewReader(buf)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
gzReader, err := gzipDecompress(ctx, buf)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
readBufWrapper := &readCloserWrapper{gzReader, compression, closer}
|
||||
return readBufWrapper, nil
|
||||
|
||||
return &readCloserWrapper{
|
||||
Reader: gzReader,
|
||||
compression: compression,
|
||||
closer: func() error {
|
||||
cancel()
|
||||
return gzReader.Close()
|
||||
},
|
||||
}, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported compression format %s", (&compression).Extension())
|
||||
}
|
||||
|
@ -151,3 +200,67 @@ func (compression *Compression) Extension() string {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func gzipDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) {
|
||||
initPigz.Do(func() {
|
||||
if unpigzPath = detectPigz(); unpigzPath != "" {
|
||||
log.L.Debug("using pigz for decompression")
|
||||
}
|
||||
})
|
||||
|
||||
if unpigzPath == "" {
|
||||
return gzip.NewReader(buf)
|
||||
}
|
||||
|
||||
return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf)
|
||||
}
|
||||
|
||||
func cmdStream(cmd *exec.Cmd, in io.Reader) (io.ReadCloser, error) {
|
||||
reader, writer := io.Pipe()
|
||||
|
||||
cmd.Stdin = in
|
||||
cmd.Stdout = writer
|
||||
|
||||
var errBuf bytes.Buffer
|
||||
cmd.Stderr = &errBuf
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := cmd.Wait(); err != nil {
|
||||
writer.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
|
||||
} else {
|
||||
writer.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
func detectPigz() string {
|
||||
path, err := exec.LookPath("unpigz")
|
||||
if err != nil {
|
||||
log.L.WithError(err).Debug("unpigz not found, falling back to go gzip")
|
||||
return ""
|
||||
}
|
||||
|
||||
// Check if pigz disabled via CONTAINERD_DISABLE_PIGZ env variable
|
||||
value := os.Getenv(disablePigzEnv)
|
||||
if value == "" {
|
||||
return path
|
||||
}
|
||||
|
||||
disable, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
log.L.WithError(err).Warnf("could not parse %s: %s", disablePigzEnv, value)
|
||||
return path
|
||||
}
|
||||
|
||||
if disable {
|
||||
return ""
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
|
|
@ -76,6 +76,23 @@ func WithContainerLabels(labels map[string]string) NewContainerOpts {
|
|||
}
|
||||
}
|
||||
|
||||
// WithImageStopSignal sets a well-known containerd label (StopSignalLabel)
|
||||
// on the container for storing the stop signal specified in the OCI image
|
||||
// config
|
||||
func WithImageStopSignal(image Image, defaultSignal string) NewContainerOpts {
|
||||
return func(ctx context.Context, _ *Client, c *containers.Container) error {
|
||||
if c.Labels == nil {
|
||||
c.Labels = make(map[string]string)
|
||||
}
|
||||
stopSignal, err := GetOCIStopSignal(ctx, image, defaultSignal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Labels[StopSignalLabel] = stopSignal
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSnapshotter sets the provided snapshotter for use by the container
|
||||
//
|
||||
// This option must appear before other snapshotter options to have an effect.
|
||||
|
|
|
@ -28,12 +28,12 @@ import (
|
|||
//
|
||||
// The resources specified in this object are used to create tasks from the container.
|
||||
type Container struct {
|
||||
// ID uniquely identifies the container in a nameapace.
|
||||
// ID uniquely identifies the container in a namespace.
|
||||
//
|
||||
// This property is required and cannot be changed after creation.
|
||||
ID string
|
||||
|
||||
// Labels provide metadata extension for a contaienr.
|
||||
// Labels provide metadata extension for a container.
|
||||
//
|
||||
// These are optional and fully mutable.
|
||||
Labels map[string]string
|
||||
|
|
|
@ -70,7 +70,7 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, desc o
|
|||
cw, err := OpenWriter(ctx, cs, WithRef(ref), WithDescriptor(desc))
|
||||
if err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to open writer")
|
||||
}
|
||||
|
||||
return nil // all ready present
|
||||
|
@ -127,7 +127,7 @@ func OpenWriter(ctx context.Context, cs Ingester, opts ...WriterOpt) (Writer, er
|
|||
func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error {
|
||||
ws, err := cw.Status()
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to get status")
|
||||
}
|
||||
|
||||
if ws.Offset > 0 {
|
||||
|
@ -138,7 +138,7 @@ func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected dige
|
|||
}
|
||||
|
||||
if _, err := copyWithBuffer(cw, r); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to copy")
|
||||
}
|
||||
|
||||
if err := cw.Commit(ctx, size, expected, opts...); err != nil {
|
||||
|
|
|
@ -57,7 +57,7 @@ func (rw *remoteWriter) Status() (content.Status, error) {
|
|||
Action: contentapi.WriteActionStat,
|
||||
})
|
||||
if err != nil {
|
||||
return content.Status{}, errors.Wrap(err, "error getting writer status")
|
||||
return content.Status{}, errors.Wrap(errdefs.FromGRPC(err), "error getting writer status")
|
||||
}
|
||||
|
||||
return content.Status{
|
||||
|
@ -82,7 +82,7 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) {
|
|||
Data: p,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrap(errdefs.FromGRPC(err), "failed to send write")
|
||||
}
|
||||
|
||||
n = int(resp.Offset - offset)
|
||||
|
@ -112,7 +112,7 @@ func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.
|
|||
Labels: base.Labels,
|
||||
})
|
||||
if err != nil {
|
||||
return errdefs.FromGRPC(err)
|
||||
return errors.Wrap(errdefs.FromGRPC(err), "commit failed")
|
||||
}
|
||||
|
||||
if size != 0 && resp.Offset != size {
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/images"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type exportOpts struct {
|
||||
|
@ -51,7 +52,7 @@ func (c *Client) Export(ctx context.Context, exporter images.Exporter, desc ocis
|
|||
}
|
||||
pr, pw := io.Pipe()
|
||||
go func() {
|
||||
pw.CloseWithError(exporter.Export(ctx, c.ContentStore(), desc, pw))
|
||||
pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed"))
|
||||
}()
|
||||
return pr, nil
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ type Image interface {
|
|||
Name() string
|
||||
// Target descriptor for the image content
|
||||
Target() ocispec.Descriptor
|
||||
// Labels of the image
|
||||
Labels() map[string]string
|
||||
// Unpack unpacks the image's content into a snapshot
|
||||
Unpack(context.Context, string) error
|
||||
// RootFS returns the unpacked diffids that make up images rootfs.
|
||||
|
@ -86,6 +88,10 @@ func (i *image) Target() ocispec.Descriptor {
|
|||
return i.i.Target
|
||||
}
|
||||
|
||||
func (i *image) Labels() map[string]string {
|
||||
return i.i.Labels
|
||||
}
|
||||
|
||||
func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
|
||||
provider := i.client.ContentStore()
|
||||
return i.i.RootFS(ctx, provider, i.platform)
|
||||
|
|
262
vendor/github.com/containerd/containerd/images/archive/importer.go
generated
vendored
Normal file
262
vendor/github.com/containerd/containerd/images/archive/importer.go
generated
vendored
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package archive provides a Docker and OCI compatible importer
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"github.com/containerd/containerd/archive/compression"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/log"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
specs "github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ImportIndex imports an index from a tar achive image bundle
|
||||
// - implements Docker v1.1, v1.2 and OCI v1.
|
||||
// - prefers OCI v1 when provided
|
||||
// - creates OCI index for Docker formats
|
||||
// - normalizes Docker references and adds as OCI ref name
|
||||
// e.g. alpine:latest -> docker.io/library/alpine:latest
|
||||
// - existing OCI reference names are untouched
|
||||
// - TODO: support option to compress layers on ingest
|
||||
func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error) {
|
||||
var (
|
||||
tr = tar.NewReader(reader)
|
||||
|
||||
ociLayout ocispec.ImageLayout
|
||||
mfsts []struct {
|
||||
Config string
|
||||
RepoTags []string
|
||||
Layers []string
|
||||
}
|
||||
symlinks = make(map[string]string)
|
||||
blobs = make(map[string]ocispec.Descriptor)
|
||||
)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
if hdr.Typeflag == tar.TypeSymlink {
|
||||
symlinks[hdr.Name] = path.Join(path.Dir(hdr.Name), hdr.Linkname)
|
||||
}
|
||||
|
||||
if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA {
|
||||
if hdr.Typeflag != tar.TypeDir {
|
||||
log.G(ctx).WithField("file", hdr.Name).Debug("file type ignored")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
hdrName := path.Clean(hdr.Name)
|
||||
if hdrName == ocispec.ImageLayoutFile {
|
||||
if err = onUntarJSON(tr, &ociLayout); err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrapf(err, "untar oci layout %q", hdr.Name)
|
||||
}
|
||||
} else if hdrName == "manifest.json" {
|
||||
if err = onUntarJSON(tr, &mfsts); err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrapf(err, "untar manifest %q", hdr.Name)
|
||||
}
|
||||
} else {
|
||||
dgst, err := onUntarBlob(ctx, tr, store, hdr.Size, "tar-"+hdrName)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrapf(err, "failed to ingest %q", hdr.Name)
|
||||
}
|
||||
|
||||
blobs[hdrName] = ocispec.Descriptor{
|
||||
Digest: dgst,
|
||||
Size: hdr.Size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If OCI layout was given, interpret the tar as an OCI layout.
|
||||
// When not provided, the layout of the tar will be interpretted
|
||||
// as Docker v1.1 or v1.2.
|
||||
if ociLayout.Version != "" {
|
||||
if ociLayout.Version != ocispec.ImageLayoutVersion {
|
||||
return ocispec.Descriptor{}, errors.Errorf("unsupported OCI version %s", ociLayout.Version)
|
||||
}
|
||||
|
||||
idx, ok := blobs["index.json"]
|
||||
if !ok {
|
||||
return ocispec.Descriptor{}, errors.Errorf("missing index.json in OCI layout %s", ocispec.ImageLayoutVersion)
|
||||
}
|
||||
|
||||
idx.MediaType = ocispec.MediaTypeImageIndex
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
if mfsts == nil {
|
||||
return ocispec.Descriptor{}, errors.Errorf("unrecognized image format")
|
||||
}
|
||||
|
||||
for name, linkname := range symlinks {
|
||||
desc, ok := blobs[linkname]
|
||||
if !ok {
|
||||
return ocispec.Descriptor{}, errors.Errorf("no target for symlink layer from %q to %q", name, linkname)
|
||||
}
|
||||
blobs[name] = desc
|
||||
}
|
||||
|
||||
idx := ocispec.Index{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
}
|
||||
for _, mfst := range mfsts {
|
||||
config, ok := blobs[mfst.Config]
|
||||
if !ok {
|
||||
return ocispec.Descriptor{}, errors.Errorf("image config %q not found", mfst.Config)
|
||||
}
|
||||
config.MediaType = ocispec.MediaTypeImageConfig
|
||||
|
||||
layers, err := resolveLayers(ctx, store, mfst.Layers, blobs)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to resolve layers")
|
||||
}
|
||||
|
||||
manifest := ocispec.Manifest{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Config: config,
|
||||
Layers: layers,
|
||||
}
|
||||
|
||||
desc, err := writeManifest(ctx, store, manifest, ocispec.MediaTypeImageManifest)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "write docker manifest")
|
||||
}
|
||||
|
||||
platforms, err := images.Platforms(ctx, store, desc)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "unable to resolve platform")
|
||||
}
|
||||
if len(platforms) > 0 {
|
||||
// Only one platform can be resolved from non-index manifest,
|
||||
// The platform can only come from the config included above,
|
||||
// if the config has no platform it can be safely ommitted.
|
||||
desc.Platform = &platforms[0]
|
||||
}
|
||||
|
||||
if len(mfst.RepoTags) == 0 {
|
||||
idx.Manifests = append(idx.Manifests, desc)
|
||||
} else {
|
||||
// Add descriptor per tag
|
||||
for _, ref := range mfst.RepoTags {
|
||||
mfstdesc := desc
|
||||
|
||||
normalized, err := normalizeReference(ref)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
mfstdesc.Annotations = map[string]string{
|
||||
ocispec.AnnotationRefName: normalized,
|
||||
}
|
||||
|
||||
idx.Manifests = append(idx.Manifests, mfstdesc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return writeManifest(ctx, store, idx, ocispec.MediaTypeImageIndex)
|
||||
}
|
||||
|
||||
func onUntarJSON(r io.Reader, j interface{}) error {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(b, j); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func onUntarBlob(ctx context.Context, r io.Reader, store content.Ingester, size int64, ref string) (digest.Digest, error) {
|
||||
dgstr := digest.Canonical.Digester()
|
||||
|
||||
if err := content.WriteBlob(ctx, store, ref, io.TeeReader(r, dgstr.Hash()), ocispec.Descriptor{Size: size}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dgstr.Digest(), nil
|
||||
}
|
||||
|
||||
func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
var layers []ocispec.Descriptor
|
||||
for _, f := range layerFiles {
|
||||
desc, ok := blobs[f]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("layer %q not found", f)
|
||||
}
|
||||
|
||||
// Open blob, resolve media type
|
||||
ra, err := store.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to open %q (%s)", f, desc.Digest)
|
||||
}
|
||||
s, err := compression.DecompressStream(content.NewReader(ra))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to detect compression for %q", f)
|
||||
}
|
||||
if s.GetCompression() == compression.Uncompressed {
|
||||
// TODO: Support compressing and writing back to content store
|
||||
desc.MediaType = ocispec.MediaTypeImageLayer
|
||||
} else {
|
||||
desc.MediaType = ocispec.MediaTypeImageLayerGzip
|
||||
}
|
||||
s.Close()
|
||||
|
||||
layers = append(layers, desc)
|
||||
}
|
||||
return layers, nil
|
||||
}
|
||||
|
||||
func writeManifest(ctx context.Context, cs content.Ingester, manifest interface{}, mediaType string) (ocispec.Descriptor, error) {
|
||||
manifestBytes, err := json.Marshal(manifest)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
desc := ocispec.Descriptor{
|
||||
MediaType: mediaType,
|
||||
Digest: digest.FromBytes(manifestBytes),
|
||||
Size: int64(len(manifestBytes)),
|
||||
}
|
||||
if err := content.WriteBlob(ctx, cs, "manifest-"+desc.Digest.String(), bytes.NewReader(manifestBytes), desc); err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
return desc, nil
|
||||
}
|
86
vendor/github.com/containerd/containerd/images/archive/reference.go
generated
vendored
Normal file
86
vendor/github.com/containerd/containerd/images/archive/reference.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package archive
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/cri/pkg/util"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FilterRefPrefix restricts references to having the given image
|
||||
// prefix. Tag-only references will have the prefix prepended.
|
||||
func FilterRefPrefix(image string) func(string) string {
|
||||
return refTranslator(image, true)
|
||||
}
|
||||
|
||||
// AddRefPrefix prepends the given image prefix to tag-only references,
|
||||
// while leaving returning full references unmodified.
|
||||
func AddRefPrefix(image string) func(string) string {
|
||||
return refTranslator(image, false)
|
||||
}
|
||||
|
||||
// refTranslator creates a reference which only has a tag or verifies
|
||||
// a full reference.
|
||||
func refTranslator(image string, checkPrefix bool) func(string) string {
|
||||
return func(ref string) string {
|
||||
// Check if ref is full reference
|
||||
if strings.ContainsAny(ref, "/:@") {
|
||||
// If not prefixed, don't include image
|
||||
if checkPrefix && !isImagePrefix(ref, image) {
|
||||
return ""
|
||||
}
|
||||
return ref
|
||||
}
|
||||
return image + ":" + ref
|
||||
}
|
||||
}
|
||||
|
||||
func isImagePrefix(s, prefix string) bool {
|
||||
if !strings.HasPrefix(s, prefix) {
|
||||
return false
|
||||
}
|
||||
if len(s) > len(prefix) {
|
||||
switch s[len(prefix)] {
|
||||
case '/', ':', '@':
|
||||
// Prevent matching partial namespaces
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func normalizeReference(ref string) (string, error) {
|
||||
// TODO: Replace this function to not depend on reference package
|
||||
normalized, err := util.NormalizeImageRef(ref)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "normalize image ref %q", ref)
|
||||
}
|
||||
|
||||
return normalized.String(), nil
|
||||
}
|
||||
|
||||
// DigestTranslator creates a digest reference by adding the
|
||||
// digest to an image name
|
||||
func DigestTranslator(prefix string) func(digest.Digest) string {
|
||||
return func(dgst digest.Digest) string {
|
||||
return prefix + "@" + dgst.String()
|
||||
}
|
||||
}
|
|
@ -129,6 +129,13 @@ type platformManifest struct {
|
|||
|
||||
// Manifest resolves a manifest from the image for the given platform.
|
||||
//
|
||||
// When a manifest descriptor inside of a manifest index does not have
|
||||
// a platform defined, the platform from the image config is considered.
|
||||
//
|
||||
// If the descriptor points to a non-index manifest, then the manifest is
|
||||
// unmarshalled and returned without considering the platform inside of the
|
||||
// config.
|
||||
//
|
||||
// TODO(stevvooe): This violates the current platform agnostic approach to this
|
||||
// package by returning a specific manifest type. We'll need to refactor this
|
||||
// to return a manifest descriptor or decide that we want to bring the API in
|
||||
|
@ -152,7 +159,7 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if platform != nil {
|
||||
if desc.Digest != image.Digest && platform != nil {
|
||||
if desc.Platform != nil && !platform.Match(*desc.Platform) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
// Importer is the interface for image importer.
|
||||
type Importer interface {
|
||||
// Import imports an image from a tar stream.
|
||||
Import(ctx context.Context, store content.Store, reader io.Reader) ([]Image, error)
|
||||
Import(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
// Exporter is the interface for image exporter.
|
||||
|
|
|
@ -94,7 +94,7 @@ func blobRecord(cs content.Provider, desc ocispec.Descriptor) tarRecord {
|
|||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
r, err := cs.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrap(err, "failed to get reader")
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
|
@ -103,7 +103,7 @@ func blobRecord(cs content.Provider, desc ocispec.Descriptor) tarRecord {
|
|||
|
||||
n, err := io.Copy(io.MultiWriter(w, dgstr.Hash()), content.NewReader(r))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return 0, errors.Wrap(err, "failed to copy to tar")
|
||||
}
|
||||
if dgstr.Digest() != desc.Digest {
|
||||
return 0, errors.Errorf("unexpected digest %s copied", dgstr.Digest())
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package oci provides the importer and the exporter for OCI Image Spec.
|
||||
package oci
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// V1Importer implements OCI Image Spec v1.
|
||||
type V1Importer struct {
|
||||
// ImageName is preprended to either `:` + OCI ref name or `@` + digest (for anonymous refs).
|
||||
// This field is mandatory atm, but may change in the future. maybe ref map[string]string as in moby/moby#33355
|
||||
ImageName string
|
||||
}
|
||||
|
||||
var _ images.Importer = &V1Importer{}
|
||||
|
||||
// Import implements Importer.
|
||||
func (oi *V1Importer) Import(ctx context.Context, store content.Store, reader io.Reader) ([]images.Image, error) {
|
||||
if oi.ImageName == "" {
|
||||
return nil, errors.New("ImageName not set")
|
||||
}
|
||||
tr := tar.NewReader(reader)
|
||||
var imgrecs []images.Image
|
||||
foundIndexJSON := false
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA {
|
||||
continue
|
||||
}
|
||||
hdrName := path.Clean(hdr.Name)
|
||||
if hdrName == "index.json" {
|
||||
if foundIndexJSON {
|
||||
return nil, errors.New("duplicated index.json")
|
||||
}
|
||||
foundIndexJSON = true
|
||||
imgrecs, err = onUntarIndexJSON(tr, oi.ImageName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(hdrName, "blobs/") {
|
||||
if err := onUntarBlob(ctx, tr, store, hdrName, hdr.Size); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundIndexJSON {
|
||||
return nil, errors.New("no index.json found")
|
||||
}
|
||||
for _, img := range imgrecs {
|
||||
err := setGCRefContentLabels(ctx, store, img.Target)
|
||||
if err != nil {
|
||||
return imgrecs, err
|
||||
}
|
||||
}
|
||||
// FIXME(AkihiroSuda): set GC labels for unreferrenced blobs (i.e. with unknown media types)?
|
||||
return imgrecs, nil
|
||||
}
|
||||
|
||||
func onUntarIndexJSON(r io.Reader, imageName string) ([]images.Image, error) {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var idx ocispec.Index
|
||||
if err := json.Unmarshal(b, &idx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var imgrecs []images.Image
|
||||
for _, m := range idx.Manifests {
|
||||
ref, err := normalizeImageRef(imageName, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imgrecs = append(imgrecs, images.Image{
|
||||
Name: ref,
|
||||
Target: m,
|
||||
})
|
||||
}
|
||||
return imgrecs, nil
|
||||
}
|
||||
|
||||
func normalizeImageRef(imageName string, manifest ocispec.Descriptor) (string, error) {
|
||||
digest := manifest.Digest
|
||||
if digest == "" {
|
||||
return "", errors.Errorf("manifest with empty digest: %v", manifest)
|
||||
}
|
||||
ociRef := manifest.Annotations[ocispec.AnnotationRefName]
|
||||
if ociRef == "" {
|
||||
return imageName + "@" + digest.String(), nil
|
||||
}
|
||||
return imageName + ":" + ociRef, nil
|
||||
}
|
||||
|
||||
func onUntarBlob(ctx context.Context, r io.Reader, store content.Ingester, name string, size int64) error {
|
||||
// name is like "blobs/sha256/deadbeef"
|
||||
split := strings.Split(name, "/")
|
||||
if len(split) != 3 {
|
||||
return errors.Errorf("unexpected name: %q", name)
|
||||
}
|
||||
algo := digest.Algorithm(split[1])
|
||||
if !algo.Available() {
|
||||
return errors.Errorf("unsupported algorithm: %s", algo)
|
||||
}
|
||||
dgst := digest.NewDigestFromHex(algo.String(), split[2])
|
||||
return content.WriteBlob(ctx, store, "unknown-"+dgst.String(), r, ocispec.Descriptor{Size: size, Digest: dgst})
|
||||
}
|
||||
|
||||
// GetChildrenDescriptors returns children blob descriptors for the following supported types:
|
||||
// - images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest
|
||||
// - images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex
|
||||
func GetChildrenDescriptors(r io.Reader, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
|
||||
var manifest ocispec.Manifest
|
||||
if err := json.NewDecoder(r).Decode(&manifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append([]ocispec.Descriptor{manifest.Config}, manifest.Layers...), nil
|
||||
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
|
||||
var index ocispec.Index
|
||||
if err := json.NewDecoder(r).Decode(&index); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return index.Manifests, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func setGCRefContentLabels(ctx context.Context, store content.Store, desc ocispec.Descriptor) error {
|
||||
info, err := store.Info(ctx, desc.Digest)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
// when the archive is created from multi-arch image,
|
||||
// it may contain only blobs for a certain platform.
|
||||
// So ErrNotFound (on manifest list) is expected here.
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
ra, err := store.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ra.Close()
|
||||
r := content.NewReader(ra)
|
||||
children, err := GetChildrenDescriptors(r, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.Labels == nil {
|
||||
info.Labels = map[string]string{}
|
||||
}
|
||||
for i, child := range children {
|
||||
// Note: child blob is not guaranteed to be written to the content store. (multi-arch)
|
||||
info.Labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = child.Digest.String()
|
||||
}
|
||||
if _, err := store.Update(ctx, info, "labels"); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, child := range children {
|
||||
if err := setGCRefContentLabels(ctx, store, child); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -18,35 +18,61 @@ package containerd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type importOpts struct {
|
||||
indexName string
|
||||
imageRefT func(string) string
|
||||
dgstRefT func(digest.Digest) string
|
||||
}
|
||||
|
||||
// ImportOpt allows the caller to specify import specific options
|
||||
type ImportOpt func(c *importOpts) error
|
||||
type ImportOpt func(*importOpts) error
|
||||
|
||||
func resolveImportOpt(opts ...ImportOpt) (importOpts, error) {
|
||||
var iopts importOpts
|
||||
for _, o := range opts {
|
||||
if err := o(&iopts); err != nil {
|
||||
return iopts, err
|
||||
}
|
||||
// WithImageRefTranslator is used to translate the index reference
|
||||
// to an image reference for the image store.
|
||||
func WithImageRefTranslator(f func(string) string) ImportOpt {
|
||||
return func(c *importOpts) error {
|
||||
c.imageRefT = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDigestRef is used to create digest images for each
|
||||
// manifest in the index.
|
||||
func WithDigestRef(f func(digest.Digest) string) ImportOpt {
|
||||
return func(c *importOpts) error {
|
||||
c.dgstRefT = f
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithIndexName creates a tag pointing to the imported index
|
||||
func WithIndexName(name string) ImportOpt {
|
||||
return func(c *importOpts) error {
|
||||
c.indexName = name
|
||||
return nil
|
||||
}
|
||||
return iopts, nil
|
||||
}
|
||||
|
||||
// Import imports an image from a Tar stream using reader.
|
||||
// Caller needs to specify importer. Future version may use oci.v1 as the default.
|
||||
// Note that unreferrenced blobs may be imported to the content store as well.
|
||||
func (c *Client) Import(ctx context.Context, importer images.Importer, reader io.Reader, opts ...ImportOpt) ([]Image, error) {
|
||||
_, err := resolveImportOpt(opts...) // unused now
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt) ([]images.Image, error) {
|
||||
var iopts importOpts
|
||||
for _, o := range opts {
|
||||
if err := o(&iopts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ctx, done, err := c.WithLease(ctx)
|
||||
|
@ -55,31 +81,86 @@ func (c *Client) Import(ctx context.Context, importer images.Importer, reader io
|
|||
}
|
||||
defer done(ctx)
|
||||
|
||||
imgrecs, err := importer.Import(ctx, c.ContentStore(), reader)
|
||||
index, err := archive.ImportIndex(ctx, c.ContentStore(), reader)
|
||||
if err != nil {
|
||||
// is.Update() is not called on error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
is := c.ImageService()
|
||||
var images []Image
|
||||
for _, imgrec := range imgrecs {
|
||||
if updated, err := is.Update(ctx, imgrec, "target"); err != nil {
|
||||
var (
|
||||
imgs []images.Image
|
||||
cs = c.ContentStore()
|
||||
is = c.ImageService()
|
||||
)
|
||||
|
||||
if iopts.indexName != "" {
|
||||
imgs = append(imgs, images.Image{
|
||||
Name: iopts.indexName,
|
||||
Target: index,
|
||||
})
|
||||
}
|
||||
|
||||
var handler images.HandlerFunc
|
||||
handler = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
// Only save images at top level
|
||||
if desc.Digest != index.Digest {
|
||||
return images.Children(ctx, cs, desc)
|
||||
}
|
||||
|
||||
p, err := content.ReadBlob(ctx, cs, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var idx ocispec.Index
|
||||
if err := json.Unmarshal(p, &idx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range idx.Manifests {
|
||||
if ref := m.Annotations[ocispec.AnnotationRefName]; ref != "" {
|
||||
if iopts.imageRefT != nil {
|
||||
ref = iopts.imageRefT(ref)
|
||||
}
|
||||
if ref != "" {
|
||||
imgs = append(imgs, images.Image{
|
||||
Name: ref,
|
||||
Target: m,
|
||||
})
|
||||
}
|
||||
}
|
||||
if iopts.dgstRefT != nil {
|
||||
ref := iopts.dgstRefT(m.Digest)
|
||||
if ref != "" {
|
||||
imgs = append(imgs, images.Image{
|
||||
Name: ref,
|
||||
Target: m,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idx.Manifests, nil
|
||||
}
|
||||
|
||||
handler = images.SetChildrenLabels(cs, handler)
|
||||
if err := images.Walk(ctx, handler, index); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range imgs {
|
||||
img, err := is.Update(ctx, imgs[i], "target")
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
created, err := is.Create(ctx, imgrec)
|
||||
img, err = is.Create(ctx, imgs[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imgrec = created
|
||||
} else {
|
||||
imgrec = updated
|
||||
}
|
||||
|
||||
images = append(images, NewImage(c, imgrec))
|
||||
imgs[i] = img
|
||||
}
|
||||
return images, nil
|
||||
|
||||
return imgs, nil
|
||||
}
|
||||
|
|
|
@ -553,7 +553,9 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig
|
|||
nw.l.RLock()
|
||||
defer nw.l.RUnlock()
|
||||
|
||||
return update(ctx, nw.db, func(tx *bolt.Tx) error {
|
||||
var innerErr error
|
||||
|
||||
if err := update(ctx, nw.db, func(tx *bolt.Tx) error {
|
||||
bkt := getIngestsBucket(tx, nw.namespace)
|
||||
if bkt != nil {
|
||||
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
|
|||
}
|
||||
dgst, err := nw.commit(ctx, tx, size, expected, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
innerErr = err
|
||||
}
|
||||
if err := removeIngestLease(ctx, tx, nw.ref); err != nil {
|
||||
return err
|
||||
}
|
||||
return addContentLease(ctx, tx, dgst)
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return innerErr
|
||||
}
|
||||
|
||||
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,
|
|||
bkt, err := createBlobBucket(tx, nw.namespace, actual)
|
||||
if err != nil {
|
||||
if err == bolt.ErrBucketExists {
|
||||
return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
|
||||
return actual, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@ func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
|
|||
Destination: "/proc",
|
||||
Type: "proc",
|
||||
Source: "proc",
|
||||
Options: []string{"nosuid", "noexec", "nodev"},
|
||||
},
|
||||
{
|
||||
Destination: "/dev",
|
||||
|
|
|
@ -268,6 +268,14 @@ func WithLinuxNamespace(ns specs.LinuxNamespace) SpecOpts {
|
|||
}
|
||||
}
|
||||
|
||||
// WithNewPrivileges turns off the NoNewPrivileges feature flag in the spec
|
||||
func WithNewPrivileges(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setProcess(s)
|
||||
s.Process.NoNewPrivileges = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithImageConfig configures the spec to from the configuration of an Image
|
||||
func WithImageConfig(image Image) SpecOpts {
|
||||
return WithImageConfigArgs(image, nil)
|
||||
|
@ -646,6 +654,10 @@ func WithUsername(username string) SpecOpts {
|
|||
// The passed in user can be either a uid or a username.
|
||||
func WithAdditionalGIDs(userstr string) SpecOpts {
|
||||
return func(ctx context.Context, client Client, c *containers.Container, s *Spec) (err error) {
|
||||
// For LCOW additional GID's not supported
|
||||
if s.Windows != nil {
|
||||
return nil
|
||||
}
|
||||
setProcess(s)
|
||||
setAdditionalGids := func(root string) error {
|
||||
var username string
|
||||
|
@ -1003,3 +1015,14 @@ var WithPrivileged = Compose(
|
|||
WithApparmorProfile(""),
|
||||
WithSeccompUnconfined,
|
||||
)
|
||||
|
||||
// WithWindowsHyperV sets the Windows.HyperV section for HyperV isolation of containers.
|
||||
func WithWindowsHyperV(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
if s.Windows == nil {
|
||||
s.Windows = &specs.Windows{}
|
||||
}
|
||||
if s.Windows.HyperV == nil {
|
||||
s.Windows.HyperV = &specs.WindowsHyperV{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -74,6 +74,22 @@ func getCPUInfo(pattern string) (info string, err error) {
|
|||
}
|
||||
|
||||
func getCPUVariant() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Windows only supports v7 for ARM32 and v8 for ARM64 and so we can use
|
||||
// runtime.GOARCH to determine the variants
|
||||
var variant string
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
variant = "v8"
|
||||
case "arm":
|
||||
variant = "v7"
|
||||
default:
|
||||
variant = "unknown"
|
||||
}
|
||||
|
||||
return variant
|
||||
}
|
||||
|
||||
variant, err := getCPUInfo("Cpu architecture")
|
||||
if err != nil {
|
||||
log.L.WithError(err).Error("failure getting variant")
|
||||
|
|
317
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
Normal file
317
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
)
|
||||
|
||||
type dockerAuthorizer struct {
|
||||
credentials func(string) (string, string, error)
|
||||
|
||||
client *http.Client
|
||||
mu sync.Mutex
|
||||
|
||||
auth map[string]string
|
||||
}
|
||||
|
||||
// NewAuthorizer creates a Docker authorizer using the provided function to
|
||||
// get credentials for the token server or basic auth.
|
||||
func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
|
||||
if client == nil {
|
||||
client = http.DefaultClient
|
||||
}
|
||||
return &dockerAuthorizer{
|
||||
credentials: f,
|
||||
client: client,
|
||||
auth: map[string]string{},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
|
||||
// TODO: Lookup matching challenge and scope rather than just host
|
||||
if auth := a.getAuth(req.URL.Host); auth != "" {
|
||||
req.Header.Set("Authorization", auth)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
|
||||
last := responses[len(responses)-1]
|
||||
host := last.Request.URL.Host
|
||||
for _, c := range parseAuthHeader(last.Header) {
|
||||
if c.scheme == bearerAuth {
|
||||
if err := invalidAuthorization(c, responses); err != nil {
|
||||
// TODO: Clear token
|
||||
a.setAuth(host, "")
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(dmcg): Store challenge, not token
|
||||
// Move token fetching to authorize
|
||||
if err := a.setTokenAuth(ctx, host, c.parameters); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
} else if c.scheme == basicAuth {
|
||||
// TODO: Resolve credentials on authorize
|
||||
username, secret, err := a.credentials(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if username != "" && secret != "" {
|
||||
auth := username + ":" + secret
|
||||
a.setAuth(host, fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) getAuth(host string) string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
return a.auth[host]
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) setAuth(host string, auth string) bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
changed := a.auth[host] != auth
|
||||
a.auth[host] = auth
|
||||
|
||||
return changed
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) setTokenAuth(ctx context.Context, host string, params map[string]string) error {
|
||||
realm, ok := params["realm"]
|
||||
if !ok {
|
||||
return errors.New("no realm specified for token auth challenge")
|
||||
}
|
||||
|
||||
realmURL, err := url.Parse(realm)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid token auth challenge realm")
|
||||
}
|
||||
|
||||
to := tokenOptions{
|
||||
realm: realmURL.String(),
|
||||
service: params["service"],
|
||||
}
|
||||
|
||||
to.scopes = getTokenScopes(ctx, params)
|
||||
if len(to.scopes) == 0 {
|
||||
return errors.Errorf("no scope specified for token auth challenge")
|
||||
}
|
||||
|
||||
if a.credentials != nil {
|
||||
to.username, to.secret, err = a.credentials(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var token string
|
||||
if to.secret != "" {
|
||||
// Credential information is provided, use oauth POST endpoint
|
||||
token, err = a.fetchTokenWithOAuth(ctx, to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to fetch oauth token")
|
||||
}
|
||||
} else {
|
||||
// Do request anonymously
|
||||
token, err = a.fetchToken(ctx, to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to fetch anonymous token")
|
||||
}
|
||||
}
|
||||
a.setAuth(host, fmt.Sprintf("Bearer %s", token))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type tokenOptions struct {
|
||||
realm string
|
||||
service string
|
||||
scopes []string
|
||||
username string
|
||||
secret string
|
||||
}
|
||||
|
||||
type postTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
IssuedAt time.Time `json:"issued_at"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
|
||||
form := url.Values{}
|
||||
form.Set("scope", strings.Join(to.scopes, " "))
|
||||
form.Set("service", to.service)
|
||||
// TODO: Allow setting client_id
|
||||
form.Set("client_id", "containerd-client")
|
||||
|
||||
if to.username == "" {
|
||||
form.Set("grant_type", "refresh_token")
|
||||
form.Set("refresh_token", to.secret)
|
||||
} else {
|
||||
form.Set("grant_type", "password")
|
||||
form.Set("username", to.username)
|
||||
form.Set("password", to.secret)
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.PostForm(ctx, a.client, to.realm, form)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Registries without support for POST may return 404 for POST /v2/token.
|
||||
// As of September 2017, GCR is known to return 404.
|
||||
// As of February 2018, JFrog Artifactory is known to return 401.
|
||||
if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
|
||||
return a.fetchToken(ctx, to)
|
||||
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"status": resp.Status,
|
||||
"body": string(b),
|
||||
}).Debugf("token request failed")
|
||||
// TODO: handle error body and write debug output
|
||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
|
||||
var tr postTokenResponse
|
||||
if err = decoder.Decode(&tr); err != nil {
|
||||
return "", fmt.Errorf("unable to decode token response: %s", err)
|
||||
}
|
||||
|
||||
return tr.AccessToken, nil
|
||||
}
|
||||
|
||||
type getTokenResponse struct {
|
||||
Token string `json:"token"`
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
IssuedAt time.Time `json:"issued_at"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
// getToken fetches a token using a GET request
|
||||
func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
||||
req, err := http.NewRequest("GET", to.realm, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
reqParams := req.URL.Query()
|
||||
|
||||
if to.service != "" {
|
||||
reqParams.Add("service", to.service)
|
||||
}
|
||||
|
||||
for _, scope := range to.scopes {
|
||||
reqParams.Add("scope", scope)
|
||||
}
|
||||
|
||||
if to.secret != "" {
|
||||
req.SetBasicAuth(to.username, to.secret)
|
||||
}
|
||||
|
||||
req.URL.RawQuery = reqParams.Encode()
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, a.client, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
// TODO: handle error body and write debug output
|
||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
|
||||
var tr getTokenResponse
|
||||
if err = decoder.Decode(&tr); err != nil {
|
||||
return "", fmt.Errorf("unable to decode token response: %s", err)
|
||||
}
|
||||
|
||||
// `access_token` is equivalent to `token` and if both are specified
|
||||
// the choice is undefined. Canonicalize `access_token` by sticking
|
||||
// things in `token`.
|
||||
if tr.AccessToken != "" {
|
||||
tr.Token = tr.AccessToken
|
||||
}
|
||||
|
||||
if tr.Token == "" {
|
||||
return "", ErrNoToken
|
||||
}
|
||||
|
||||
return tr.Token, nil
|
||||
}
|
||||
|
||||
func invalidAuthorization(c challenge, responses []*http.Response) error {
|
||||
errStr := c.parameters["error"]
|
||||
if errStr == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := len(responses)
|
||||
if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
|
||||
}
|
||||
|
||||
func sameRequest(r1, r2 *http.Request) bool {
|
||||
if r1.Method != r2.Method {
|
||||
return false
|
||||
}
|
||||
if *r1.URL != *r2.URL {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -18,18 +18,13 @@ package docker
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/reference"
|
||||
|
@ -51,19 +46,37 @@ var (
|
|||
ErrInvalidAuthorization = errors.New("authorization failed")
|
||||
)
|
||||
|
||||
type dockerResolver struct {
|
||||
credentials func(string) (string, string, error)
|
||||
host func(string) (string, error)
|
||||
plainHTTP bool
|
||||
client *http.Client
|
||||
tracker StatusTracker
|
||||
// Authorizer is used to authorize HTTP requests based on 401 HTTP responses.
|
||||
// An Authorizer is responsible for caching tokens or credentials used by
|
||||
// requests.
|
||||
type Authorizer interface {
|
||||
// Authorize sets the appropriate `Authorization` header on the given
|
||||
// request.
|
||||
//
|
||||
// If no authorization is found for the request, the request remains
|
||||
// unmodified. It may also add an `Authorization` header as
|
||||
// "bearer <some bearer token>"
|
||||
// "basic <base64 encoded credentials>"
|
||||
Authorize(context.Context, *http.Request) error
|
||||
|
||||
// AddResponses adds a 401 response for the authorizer to consider when
|
||||
// authorizing requests. The last response should be unauthorized and
|
||||
// the previous requests are used to consider redirects and retries
|
||||
// that may have led to the 401.
|
||||
//
|
||||
// If response is not handled, returns `ErrNotImplemented`
|
||||
AddResponses(context.Context, []*http.Response) error
|
||||
}
|
||||
|
||||
// ResolverOptions are used to configured a new Docker register resolver
|
||||
type ResolverOptions struct {
|
||||
// Authorizer is used to authorize registry requests
|
||||
Authorizer Authorizer
|
||||
|
||||
// Credentials provides username and secret given a host.
|
||||
// If username is empty but a secret is given, that secret
|
||||
// is interpretted as a long lived token.
|
||||
// Deprecated: use Authorizer
|
||||
Credentials func(string) (string, string, error)
|
||||
|
||||
// Host provides the hostname given a namespace.
|
||||
|
@ -89,22 +102,31 @@ func DefaultHost(ns string) (string, error) {
|
|||
return ns, nil
|
||||
}
|
||||
|
||||
type dockerResolver struct {
|
||||
auth Authorizer
|
||||
host func(string) (string, error)
|
||||
plainHTTP bool
|
||||
client *http.Client
|
||||
tracker StatusTracker
|
||||
}
|
||||
|
||||
// NewResolver returns a new resolver to a Docker registry
|
||||
func NewResolver(options ResolverOptions) remotes.Resolver {
|
||||
tracker := options.Tracker
|
||||
if tracker == nil {
|
||||
tracker = NewInMemoryTracker()
|
||||
if options.Tracker == nil {
|
||||
options.Tracker = NewInMemoryTracker()
|
||||
}
|
||||
host := options.Host
|
||||
if host == nil {
|
||||
host = DefaultHost
|
||||
if options.Host == nil {
|
||||
options.Host = DefaultHost
|
||||
}
|
||||
if options.Authorizer == nil {
|
||||
options.Authorizer = NewAuthorizer(options.Client, options.Credentials)
|
||||
}
|
||||
return &dockerResolver{
|
||||
credentials: options.Credentials,
|
||||
host: host,
|
||||
plainHTTP: options.PlainHTTP,
|
||||
client: options.Client,
|
||||
tracker: tracker,
|
||||
auth: options.Authorizer,
|
||||
host: options.Host,
|
||||
plainHTTP: options.PlainHTTP,
|
||||
client: options.Client,
|
||||
tracker: options.Tracker,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,18 +294,14 @@ type dockerBase struct {
|
|||
refspec reference.Spec
|
||||
base url.URL
|
||||
|
||||
client *http.Client
|
||||
useBasic bool
|
||||
username, secret string
|
||||
token string
|
||||
mu sync.Mutex
|
||||
client *http.Client
|
||||
auth Authorizer
|
||||
}
|
||||
|
||||
func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
|
||||
var (
|
||||
err error
|
||||
base url.URL
|
||||
username, secret string
|
||||
err error
|
||||
base url.URL
|
||||
)
|
||||
|
||||
host := refspec.Hostname()
|
||||
|
@ -300,61 +318,40 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
|
|||
base.Scheme = "http"
|
||||
}
|
||||
|
||||
if r.credentials != nil {
|
||||
username, secret, err = r.credentials(base.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
prefix := strings.TrimPrefix(refspec.Locator, host+"/")
|
||||
base.Path = path.Join("/v2", prefix)
|
||||
|
||||
return &dockerBase{
|
||||
refspec: refspec,
|
||||
base: base,
|
||||
client: r.client,
|
||||
username: username,
|
||||
secret: secret,
|
||||
refspec: refspec,
|
||||
base: base,
|
||||
client: r.client,
|
||||
auth: r.auth,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *dockerBase) getToken() string {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
return r.token
|
||||
}
|
||||
|
||||
func (r *dockerBase) setToken(token string) bool {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
changed := r.token != token
|
||||
r.token = token
|
||||
|
||||
return changed
|
||||
}
|
||||
|
||||
func (r *dockerBase) url(ps ...string) string {
|
||||
url := r.base
|
||||
url.Path = path.Join(url.Path, path.Join(ps...))
|
||||
return url.String()
|
||||
}
|
||||
|
||||
func (r *dockerBase) authorize(req *http.Request) {
|
||||
token := r.getToken()
|
||||
if r.useBasic {
|
||||
req.SetBasicAuth(r.username, r.secret)
|
||||
} else if token != "" {
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
func (r *dockerBase) authorize(ctx context.Context, req *http.Request) error {
|
||||
// Check if has header for host
|
||||
if r.auth != nil {
|
||||
if err := r.auth.Authorize(ctx, req); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *dockerBase) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", req.URL.String()))
|
||||
log.G(ctx).WithField("request.headers", req.Header).WithField("request.method", req.Method).Debug("do request")
|
||||
r.authorize(req)
|
||||
if err := r.authorize(ctx, req); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to authorize")
|
||||
}
|
||||
resp, err := ctxhttp.Do(ctx, r.client, req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to do request")
|
||||
|
@ -392,23 +389,14 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
|
|||
last := responses[len(responses)-1]
|
||||
if last.StatusCode == http.StatusUnauthorized {
|
||||
log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized")
|
||||
for _, c := range parseAuthHeader(last.Header) {
|
||||
if c.scheme == bearerAuth {
|
||||
if err := invalidAuthorization(c, responses); err != nil {
|
||||
r.setToken("")
|
||||
return nil, err
|
||||
}
|
||||
if err := r.setTokenAuth(ctx, c.parameters); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return copyRequest(req)
|
||||
} else if c.scheme == basicAuth {
|
||||
if r.username != "" && r.secret != "" {
|
||||
r.useBasic = true
|
||||
}
|
||||
if r.auth != nil {
|
||||
if err := r.auth.AddResponses(ctx, responses); err == nil {
|
||||
return copyRequest(req)
|
||||
} else if !errdefs.IsNotImplemented(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
} else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead {
|
||||
// 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
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func invalidAuthorization(c challenge, responses []*http.Response) error {
|
||||
errStr := c.parameters["error"]
|
||||
if errStr == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := len(responses)
|
||||
if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
|
||||
}
|
||||
|
||||
func sameRequest(r1, r2 *http.Request) bool {
|
||||
if r1.Method != r2.Method {
|
||||
return false
|
||||
}
|
||||
if *r1.URL != *r2.URL {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func copyRequest(req *http.Request) (*http.Request, error) {
|
||||
ireq := *req
|
||||
if ireq.GetBody != nil {
|
||||
|
@ -459,167 +423,3 @@ func copyRequest(req *http.Request) (*http.Request, error) {
|
|||
}
|
||||
return &ireq, nil
|
||||
}
|
||||
|
||||
func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string) error {
|
||||
realm, ok := params["realm"]
|
||||
if !ok {
|
||||
return errors.New("no realm specified for token auth challenge")
|
||||
}
|
||||
|
||||
realmURL, err := url.Parse(realm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid token auth challenge realm: %s", err)
|
||||
}
|
||||
|
||||
to := tokenOptions{
|
||||
realm: realmURL.String(),
|
||||
service: params["service"],
|
||||
}
|
||||
|
||||
to.scopes = getTokenScopes(ctx, params)
|
||||
if len(to.scopes) == 0 {
|
||||
return errors.Errorf("no scope specified for token auth challenge")
|
||||
}
|
||||
|
||||
var token string
|
||||
if r.secret != "" {
|
||||
// Credential information is provided, use oauth POST endpoint
|
||||
token, err = r.fetchTokenWithOAuth(ctx, to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to fetch oauth token")
|
||||
}
|
||||
} else {
|
||||
// Do request anonymously
|
||||
token, err = r.fetchToken(ctx, to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to fetch anonymous token")
|
||||
}
|
||||
}
|
||||
r.setToken(token)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type tokenOptions struct {
|
||||
realm string
|
||||
service string
|
||||
scopes []string
|
||||
}
|
||||
|
||||
type postTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
IssuedAt time.Time `json:"issued_at"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
|
||||
form := url.Values{}
|
||||
form.Set("scope", strings.Join(to.scopes, " "))
|
||||
form.Set("service", to.service)
|
||||
// TODO: Allow setting client_id
|
||||
form.Set("client_id", "containerd-dist-tool")
|
||||
|
||||
if r.username == "" {
|
||||
form.Set("grant_type", "refresh_token")
|
||||
form.Set("refresh_token", r.secret)
|
||||
} else {
|
||||
form.Set("grant_type", "password")
|
||||
form.Set("username", r.username)
|
||||
form.Set("password", r.secret)
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.PostForm(ctx, r.client, to.realm, form)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Registries without support for POST may return 404 for POST /v2/token.
|
||||
// As of September 2017, GCR is known to return 404.
|
||||
// As of February 2018, JFrog Artifactory is known to return 401.
|
||||
if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
|
||||
return r.fetchToken(ctx, to)
|
||||
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"status": resp.Status,
|
||||
"body": string(b),
|
||||
}).Debugf("token request failed")
|
||||
// TODO: handle error body and write debug output
|
||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
|
||||
var tr postTokenResponse
|
||||
if err = decoder.Decode(&tr); err != nil {
|
||||
return "", fmt.Errorf("unable to decode token response: %s", err)
|
||||
}
|
||||
|
||||
return tr.AccessToken, nil
|
||||
}
|
||||
|
||||
type getTokenResponse struct {
|
||||
Token string `json:"token"`
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
IssuedAt time.Time `json:"issued_at"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
// getToken fetches a token using a GET request
|
||||
func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
||||
req, err := http.NewRequest("GET", to.realm, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
reqParams := req.URL.Query()
|
||||
|
||||
if to.service != "" {
|
||||
reqParams.Add("service", to.service)
|
||||
}
|
||||
|
||||
for _, scope := range to.scopes {
|
||||
reqParams.Add("scope", scope)
|
||||
}
|
||||
|
||||
if r.secret != "" {
|
||||
req.SetBasicAuth(r.username, r.secret)
|
||||
}
|
||||
|
||||
req.URL.RawQuery = reqParams.Encode()
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, r.client, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
// TODO: handle error body and write debug output
|
||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
|
||||
var tr getTokenResponse
|
||||
if err = decoder.Decode(&tr); err != nil {
|
||||
return "", fmt.Errorf("unable to decode token response: %s", err)
|
||||
}
|
||||
|
||||
// `access_token` is equivalent to `token` and if both are specified
|
||||
// the choice is undefined. Canonicalize `access_token` by sticking
|
||||
// things in `token`.
|
||||
if tr.AccessToken != "" {
|
||||
tr.Token = tr.AccessToken
|
||||
}
|
||||
|
||||
if tr.Token == "" {
|
||||
return "", ErrNoToken
|
||||
}
|
||||
|
||||
return tr.Token, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var signalMap = map[string]syscall.Signal{
|
||||
"ABRT": unix.SIGABRT,
|
||||
"ALRM": unix.SIGALRM,
|
||||
"BUS": unix.SIGBUS,
|
||||
"CHLD": unix.SIGCHLD,
|
||||
"CLD": unix.SIGCLD,
|
||||
"CONT": unix.SIGCONT,
|
||||
"FPE": unix.SIGFPE,
|
||||
"HUP": unix.SIGHUP,
|
||||
"ILL": unix.SIGILL,
|
||||
"INT": unix.SIGINT,
|
||||
"IO": unix.SIGIO,
|
||||
"IOT": unix.SIGIOT,
|
||||
"KILL": unix.SIGKILL,
|
||||
"PIPE": unix.SIGPIPE,
|
||||
"POLL": unix.SIGPOLL,
|
||||
"PROF": unix.SIGPROF,
|
||||
"PWR": unix.SIGPWR,
|
||||
"QUIT": unix.SIGQUIT,
|
||||
"SEGV": unix.SIGSEGV,
|
||||
"STKFLT": unix.SIGSTKFLT,
|
||||
"STOP": unix.SIGSTOP,
|
||||
"SYS": unix.SIGSYS,
|
||||
"TERM": unix.SIGTERM,
|
||||
"TRAP": unix.SIGTRAP,
|
||||
"TSTP": unix.SIGTSTP,
|
||||
"TTIN": unix.SIGTTIN,
|
||||
"TTOU": unix.SIGTTOU,
|
||||
"URG": unix.SIGURG,
|
||||
"USR1": unix.SIGUSR1,
|
||||
"USR2": unix.SIGUSR2,
|
||||
"VTALRM": unix.SIGVTALRM,
|
||||
"WINCH": unix.SIGWINCH,
|
||||
"XCPU": unix.SIGXCPU,
|
||||
"XFSZ": unix.SIGXFSZ,
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// +build darwin freebsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var signalMap = map[string]syscall.Signal{
|
||||
"ABRT": unix.SIGABRT,
|
||||
"ALRM": unix.SIGALRM,
|
||||
"BUS": unix.SIGBUS,
|
||||
"CHLD": unix.SIGCHLD,
|
||||
"CONT": unix.SIGCONT,
|
||||
"FPE": unix.SIGFPE,
|
||||
"HUP": unix.SIGHUP,
|
||||
"ILL": unix.SIGILL,
|
||||
"INT": unix.SIGINT,
|
||||
"IO": unix.SIGIO,
|
||||
"IOT": unix.SIGIOT,
|
||||
"KILL": unix.SIGKILL,
|
||||
"PIPE": unix.SIGPIPE,
|
||||
"PROF": unix.SIGPROF,
|
||||
"QUIT": unix.SIGQUIT,
|
||||
"SEGV": unix.SIGSEGV,
|
||||
"STOP": unix.SIGSTOP,
|
||||
"SYS": unix.SIGSYS,
|
||||
"TERM": unix.SIGTERM,
|
||||
"TRAP": unix.SIGTRAP,
|
||||
"TSTP": unix.SIGTSTP,
|
||||
"TTIN": unix.SIGTTIN,
|
||||
"TTOU": unix.SIGTTOU,
|
||||
"URG": unix.SIGURG,
|
||||
"USR1": unix.SIGUSR1,
|
||||
"USR2": unix.SIGUSR2,
|
||||
"VTALRM": unix.SIGVTALRM,
|
||||
"WINCH": unix.SIGWINCH,
|
||||
"XCPU": unix.SIGXCPU,
|
||||
"XFSZ": unix.SIGXFSZ,
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var signalMap = map[string]syscall.Signal{
|
||||
"HUP": syscall.Signal(windows.SIGHUP),
|
||||
"INT": syscall.Signal(windows.SIGINT),
|
||||
"QUIT": syscall.Signal(windows.SIGQUIT),
|
||||
"SIGILL": syscall.Signal(windows.SIGILL),
|
||||
"TRAP": syscall.Signal(windows.SIGTRAP),
|
||||
"ABRT": syscall.Signal(windows.SIGABRT),
|
||||
"BUS": syscall.Signal(windows.SIGBUS),
|
||||
"FPE": syscall.Signal(windows.SIGFPE),
|
||||
"KILL": syscall.Signal(windows.SIGKILL),
|
||||
"SEGV": syscall.Signal(windows.SIGSEGV),
|
||||
"PIPE": syscall.Signal(windows.SIGPIPE),
|
||||
"ALRM": syscall.Signal(windows.SIGALRM),
|
||||
"TERM": syscall.Signal(windows.SIGTERM),
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// StopSignalLabel is a well-known containerd label for storing the stop
|
||||
// signal specified in the OCI image config
|
||||
const StopSignalLabel = "io.containerd.image.config.stop-signal"
|
||||
|
||||
// GetStopSignal retrieves the container stop signal, specified by the
|
||||
// well-known containerd label (StopSignalLabel)
|
||||
func GetStopSignal(ctx context.Context, container Container, defaultSignal syscall.Signal) (syscall.Signal, error) {
|
||||
labels, err := container.Labels(ctx)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if stopSignal, ok := labels[StopSignalLabel]; ok {
|
||||
return ParseSignal(stopSignal)
|
||||
}
|
||||
|
||||
return defaultSignal, nil
|
||||
}
|
||||
|
||||
// GetOCIStopSignal retrieves the stop signal specified in the OCI image config
|
||||
func GetOCIStopSignal(ctx context.Context, image Image, defaultSignal string) (string, error) {
|
||||
_, err := ParseSignal(defaultSignal)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ic, err := image.Config(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var (
|
||||
ociimage v1.Image
|
||||
config v1.ImageConfig
|
||||
)
|
||||
switch ic.MediaType {
|
||||
case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config:
|
||||
p, err := content.ReadBlob(ctx, image.ContentStore(), ic)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(p, &ociimage); err != nil {
|
||||
return "", err
|
||||
}
|
||||
config = ociimage.Config
|
||||
default:
|
||||
return "", fmt.Errorf("unknown image config media type %s", ic.MediaType)
|
||||
}
|
||||
|
||||
if config.StopSignal == "" {
|
||||
return defaultSignal, nil
|
||||
}
|
||||
|
||||
return config.StopSignal, nil
|
||||
}
|
||||
|
||||
// ParseSignal parses a given string into a syscall.Signal
|
||||
// it checks that the signal exists in the platform-appropriate signalMap
|
||||
func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
||||
s, err := strconv.Atoi(rawSignal)
|
||||
if err == nil {
|
||||
sig := syscall.Signal(s)
|
||||
for _, msig := range signalMap {
|
||||
if sig == msig {
|
||||
return sig, nil
|
||||
}
|
||||
}
|
||||
return -1, fmt.Errorf("unknown signal %q", rawSignal)
|
||||
}
|
||||
signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("unknown signal %q", rawSignal)
|
||||
}
|
||||
return signal, nil
|
||||
}
|
|
@ -4,7 +4,7 @@ github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
|
|||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||
github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
|
||||
github.com/containerd/continuity f44b615e492bdfb371aae2f76ec694d9da1db537
|
||||
github.com/containerd/continuity bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
|
||||
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
|
||||
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||
|
@ -20,7 +20,7 @@ github.com/gogo/protobuf v1.0.0
|
|||
github.com/gogo/googleapis 08a7655d27152912db7aaf4f983275eaf8d128ef
|
||||
github.com/golang/protobuf v1.1.0
|
||||
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353 # v1.0.1-45-geba862d
|
||||
github.com/opencontainers/runc 20aff4f0488c6d4b8df4d85b4f63f1f704c11abd
|
||||
github.com/opencontainers/runc 00dc70017d222b178a002ed30e9321b12647af2d
|
||||
github.com/sirupsen/logrus v1.0.0
|
||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
||||
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
||||
|
@ -32,18 +32,18 @@ github.com/opencontainers/image-spec v1.0.1
|
|||
golang.org/x/sync 450f422ab23cf9881c94e2db30cac0eb1b7cf80c
|
||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
||||
github.com/Microsoft/go-winio v0.4.10
|
||||
github.com/Microsoft/hcsshim 44c060121b68e8bdc40b411beba551f3b4ee9e55
|
||||
github.com/Microsoft/go-winio v0.4.11
|
||||
github.com/Microsoft/hcsshim v0.7.9
|
||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||
github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
|
||||
github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
|
||||
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||
gotest.tools v2.1.0
|
||||
github.com/google/go-cmp v0.1.0
|
||||
go.etcd.io/bbolt v1.3.1-etcd.8
|
||||
|
||||
# cri dependencies
|
||||
github.com/containerd/cri 9f39e3289533fc228c5e5fcac0a6dbdd60c6047b # release/1.2 branch
|
||||
github.com/containerd/cri 8506fe836677cc3bb23a16b68145128243d843b5 # release/1.2 branch
|
||||
github.com/containerd/go-cni 6d7b509a054a3cb1c35ed1865d4fde2f0cb547cd
|
||||
github.com/blang/semver v3.1.0
|
||||
github.com/containernetworking/cni v0.6.0
|
||||
|
@ -73,12 +73,12 @@ golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4
|
|||
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
|
||||
gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
||||
gopkg.in/yaml.v2 v2.2.1
|
||||
k8s.io/api 012f271b5d41baad56190c5f1ae19bff16df0fd8
|
||||
k8s.io/apimachinery 6429050ef506887d121f3e7306e894f8900d8a63
|
||||
k8s.io/apiserver e9312c15296b6c2c923ebd5031ff5d1d5fd022d7
|
||||
k8s.io/client-go 37c3c02ec96533daec0dbda1f39a6b1d68505c79
|
||||
k8s.io/kubernetes v1.12.0-beta.1
|
||||
k8s.io/utils 982821ea41da7e7c15f3d3738921eb2e7e241ccd
|
||||
k8s.io/api kubernetes-1.12.0
|
||||
k8s.io/apimachinery kubernetes-1.12.0
|
||||
k8s.io/apiserver kubernetes-1.12.0
|
||||
k8s.io/client-go kubernetes-1.12.0
|
||||
k8s.io/kubernetes v1.12.0
|
||||
k8s.io/utils cd34563cd63c2bd7c6fe88a73c4dcf34ed8a67cb
|
||||
|
||||
# zfs dependencies
|
||||
github.com/containerd/zfs 9a0b8b8b5982014b729cd34eb7cd7a11062aa6ec
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package devices
|
||||
|
||||
import "fmt"
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package devices
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package devices
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
|
@ -13,7 +29,11 @@ import (
|
|||
)
|
||||
|
||||
func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
|
||||
return devices.Mknod(path, mode, major, minor)
|
||||
err := devices.Mknod(path, mode, major, minor)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "mknod", Path: path, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) Mkfifo(path string, mode os.FileMode) error {
|
||||
|
@ -22,7 +42,11 @@ func (d *driver) Mkfifo(path string, mode os.FileMode) error {
|
|||
}
|
||||
// mknod with a mode that has ModeNamedPipe set creates a fifo, not a
|
||||
// device.
|
||||
return devices.Mknod(path, mode, 0, 0)
|
||||
err := devices.Mknod(path, mode, 0, 0)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "mkfifo", Path: path, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Getxattr returns all of the extended attributes for the file at path p.
|
||||
|
|
|
@ -1,18 +1,33 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (d *driver) Mknod(path string, mode os.FileMode, major, minor int) error {
|
||||
return errors.Wrap(ErrNotSupported, "cannot create device node on Windows")
|
||||
return &os.PathError{Op: "mknod", Path: path, Err: ErrNotSupported}
|
||||
}
|
||||
|
||||
func (d *driver) Mkfifo(path string, mode os.FileMode) error {
|
||||
return errors.Wrap(ErrNotSupported, "cannot create fifo on Windows")
|
||||
return &os.PathError{Op: "mkfifo", Path: path, Err: ErrNotSupported}
|
||||
}
|
||||
|
||||
// Lchmod changes the mode of an file not following symlinks.
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
|
@ -15,5 +31,9 @@ func (d *driver) Lchmod(path string, mode os.FileMode) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
|
||||
err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), 0)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "lchmod", Path: path, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build darwin freebsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
|
@ -10,5 +26,9 @@ import (
|
|||
|
||||
// Lchmod changes the mode of a file not following symlinks.
|
||||
func (d *driver) Lchmod(path string, mode os.FileMode) error {
|
||||
return unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
|
||||
err := unix.Fchmodat(unix.AT_FDCWD, path, uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "lchmod", Path: path, Err: err}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package driver
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build solaris darwin freebsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import "context"
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
var metadataFiles map[string]bool
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
// TODO: Any more metadata files generated by Windows layers?
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import "os"
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import "os"
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
@ -232,12 +248,6 @@ func walkLink(root, path string, linksWalked *int) (newpath string, islink bool,
|
|||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
if filepath.IsAbs(newpath) && strings.HasPrefix(newpath, root) {
|
||||
newpath = newpath[:len(root)]
|
||||
if !strings.HasPrefix(newpath, "/") {
|
||||
newpath = "/" + newpath
|
||||
}
|
||||
}
|
||||
*linksWalked++
|
||||
return newpath, true, nil
|
||||
}
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build darwin freebsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import "time"
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import "os"
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pathdriver
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package proto
|
||||
|
||||
//go:generate protoc --go_out=. manifest.proto
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package continuity
|
||||
|
||||
import "os"
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syscallx
|
||||
|
||||
import "syscall"
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package syscallx
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sysx
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sysx
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sysx
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build darwin freebsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sysx
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build linux darwin
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sysx
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
// +build !linux,!darwin
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sysx
|
||||
|
||||
import (
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,176 @@
|
|||
# cri
|
||||
<p align="center">
|
||||
<img src="https://kubernetes.io/images/favicon.png" width="50" height="50">
|
||||
<img src="https://containerd.io/img/containerd-dark.png" width="200" >
|
||||
</p>
|
||||
|
||||
*Note: The standalone `cri-containerd` binary is end-of-life. `cri-containerd` is
|
||||
transitioning from a standalone binary that talks to containerd to a plugin within
|
||||
containerd. This github branch is for the `cri` plugin. See
|
||||
[standalone-cri-containerd branch](https://github.com/containerd/cri/tree/standalone-cri-containerd)
|
||||
for information about the standalone version of `cri-containerd`.*
|
||||
|
||||
*Note: You need to [drain your node](https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/) before upgrading from standalone `cri-containerd` to containerd with `cri` plugin.*
|
||||
|
||||
[![Build Status](https://api.travis-ci.org/containerd/cri.svg?style=flat-square)](https://travis-ci.org/containerd/cri)
|
||||
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/cri)](https://goreportcard.com/report/github.com/containerd/cri)
|
||||
|
||||
`cri` is a [containerd](https://containerd.io/) plugin implementation of Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/apis/cri/runtime/v1alpha2/api.proto).
|
||||
|
||||
With it, you could run Kubernetes using containerd as the container runtime.
|
||||
![cri](./docs/cri.png)
|
||||
## Current Status
|
||||
`cri` is a native plugin of containerd 1.1 and above. It is built into containerd and enabled by default.
|
||||
|
||||
`cri` is in GA:
|
||||
* It is feature complete.
|
||||
* It (the GA version) works with Kubernetes 1.10 and above.
|
||||
* It has passed all [CRI validation tests](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md).
|
||||
* It has passed all [node e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-node-tests.md).
|
||||
* It has passed all [e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-tests.md).
|
||||
|
||||
See [test dashboard](https://k8s-testgrid.appspot.com/sig-node-containerd)
|
||||
## Support Metrics
|
||||
| CRI-Containerd Version | Containerd Version | Kubernetes Version | CRI Version |
|
||||
|:----------------------:|:------------------:|:------------------:|:-----------:|
|
||||
| v1.0.0-alpha.x | | 1.7, 1.8 | v1alpha1 |
|
||||
| v1.0.0-beta.x | | 1.9 | v1alpha1 |
|
||||
| End-Of-Life | v1.1 | 1.10+ | v1alpha2 |
|
||||
| | HEAD | 1.10+ | v1alpha2 |
|
||||
|
||||
## Production Quality Cluster on GCE
|
||||
For a production quality cluster on GCE brought up with `kube-up.sh` refer [here](docs/kube-up.md).
|
||||
## Installing with Ansible and Kubeadm
|
||||
For a multi node cluster installer and bring up steps using ansible and kubeadm refer [here](contrib/ansible/README.md).
|
||||
## Custom Installation
|
||||
For non ansible users, you can download the `cri-containerd` release tarball and deploy
|
||||
kubernetes cluster using kubeadm as described [here](docs/installation.md).
|
||||
## Getting Started for Developers
|
||||
### Binary Dependencies and Specifications
|
||||
The current release of the `cri` plugin has the following dependencies:
|
||||
* [containerd](https://github.com/containerd/containerd)
|
||||
* [runc](https://github.com/opencontainers/runc)
|
||||
* [CNI](https://github.com/containernetworking/cni)
|
||||
|
||||
See [versions](./vendor.conf) of these dependencies `cri` is tested with.
|
||||
|
||||
As containerd and runc move to their respective general availability releases,
|
||||
we will do our best to rebase/retest `cri` with these releases on a
|
||||
weekly/monthly basis. Similarly, given that `cri` uses the Open
|
||||
Container Initiative (OCI) [image](https://github.com/opencontainers/image-spec)
|
||||
and [runtime](https://github.com/opencontainers/runtime-spec) specifications, we
|
||||
will also do our best to update `cri` to the latest releases of these
|
||||
specifications as appropriate.
|
||||
### Install Dependencies
|
||||
1. Install development libraries:
|
||||
* **libseccomp development library.** Required by `cri` and runc seccomp support. `libseccomp-dev` (Ubuntu, Debian) / `libseccomp-devel`
|
||||
(Fedora, CentOS, RHEL). On releases of Ubuntu <=Trusty and Debian <=jessie a
|
||||
backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty.
|
||||
* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL)
|
||||
2. Install **`socat`** (required by portforward).
|
||||
2. Install and setup a go 1.10 development environment.
|
||||
3. Make a local clone of this repository.
|
||||
4. Install binary dependencies by running the following command from your cloned `cri/` project directory:
|
||||
```bash
|
||||
# Note: install.deps installs the above mentioned runc, containerd, and CNI
|
||||
# binary dependencies. install.deps is only provided for general use and ease of
|
||||
# testing. To customize `runc` and `containerd` build tags and/or to configure
|
||||
# `cni`, please follow instructions in their documents.
|
||||
make install.deps
|
||||
```
|
||||
### Build and Install `cri`
|
||||
To build and install a version of containerd with the `cri` plugin, enter the
|
||||
following commands from your `cri` project directory:
|
||||
```bash
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
*NOTE: The version of containerd built and installed from the `Makefile` is only for
|
||||
testing purposes. The version tag carries the suffix "-TEST".*
|
||||
#### Build Tags
|
||||
`cri` supports optional build tags for compiling support of various features.
|
||||
To add build tags to the make option the `BUILD_TAGS` variable must be set.
|
||||
|
||||
```bash
|
||||
make BUILD_TAGS='seccomp apparmor'
|
||||
```
|
||||
|
||||
| Build Tag | Feature | Dependency |
|
||||
|-----------|------------------------------------|---------------------------------|
|
||||
| seccomp | syscall filtering | libseccomp development library |
|
||||
| selinux | selinux process and mount labeling | <none> |
|
||||
| apparmor | apparmor profile support | <none> |
|
||||
### Validate Your `cri` Setup
|
||||
A Kubernetes incubator project called [cri-tools](https://github.com/kubernetes-sigs/cri-tools)
|
||||
includes programs for exercising CRI implementations such as the `cri` plugin.
|
||||
More importantly, cri-tools includes the program `critest` which is used for running
|
||||
[CRI Validation Testing](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md).
|
||||
|
||||
Run the CRI Validation test to validate your installation of `containerd` with `cri` built in:
|
||||
```bash
|
||||
make test-cri
|
||||
```
|
||||
### Running a Kubernetes local cluster
|
||||
If you already have a working development environment for supported Kubernetes
|
||||
version, you can try `cri` in a local cluster:
|
||||
|
||||
1. Start the version of `containerd` with `cri` plugin that you built and installed
|
||||
above as root in a first terminal:
|
||||
```bash
|
||||
sudo containerd
|
||||
```
|
||||
2. From the Kubernetes project directory startup a local cluster using `containerd`:
|
||||
```bash
|
||||
CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='unix:///run/containerd/containerd.sock' ./hack/local-up-cluster.sh
|
||||
```
|
||||
### Test
|
||||
See [here](./docs/testing.md) for information about test.
|
||||
## Using crictl
|
||||
See [here](./docs/crictl.md) for information about using `crictl` to debug
|
||||
pods, containers, and images.
|
||||
## Configurations
|
||||
See [here](./docs/config.md) for information about how to configure cri plugins
|
||||
and [here](https://github.com/containerd/containerd/blob/master/docs/man/containerd-config.1.md)
|
||||
for information about how to configure containerd
|
||||
## Documentation
|
||||
See [here](./docs) for additional documentation.
|
||||
## Contributing
|
||||
Interested in contributing? Check out the [documentation](./CONTRIBUTING.md).
|
||||
|
||||
## Communication
|
||||
This project was originally established in April of 2017 in the Kubernetes
|
||||
Incubator program. After reaching the Beta stage, In January of 2018, the
|
||||
project was merged into [containerd](https://github.com/containerd/containerd).
|
||||
|
||||
For async communication and long running discussions please use issues and pull
|
||||
requests on this github repo. This will be the best place to discuss design and
|
||||
implementation.
|
||||
|
||||
For sync communication we have a community slack with a #containerd channel that
|
||||
everyone is welcome to join and chat about development.
|
||||
|
||||
**Slack:** https://dockr.ly/community
|
||||
|
||||
## Other Communications
|
||||
As this project is tightly coupled to CRI and CRI-Tools and they are Kubernetes
|
||||
projects, some of our project communications take place in the Kubernetes' SIG:
|
||||
`sig-node.`
|
||||
|
||||
For more information about `sig-node`, `CRI`, and the `CRI-Tools` projects:
|
||||
* [sig-node community site](https://github.com/kubernetes/community/tree/master/sig-node)
|
||||
* Slack: `#sig-node` channel in Kubernetes (kubernetes.slack.com)
|
||||
* Mailing List: https://groups.google.com/forum/#!forum/kubernetes-sig-node
|
||||
|
||||
### Reporting Security Issues
|
||||
|
||||
__If you are reporting a security issue, please reach out discreetly at security@containerd.io__.
|
||||
|
||||
## Licenses
|
||||
The containerd codebase is released under the [Apache 2.0 license](https://github.com/containerd/containerd/blob/master/LICENSE.code).
|
||||
The README.md file, and files in the "docs" folder are licensed under the
|
||||
Creative Commons Attribution 4.0 International License under the terms and
|
||||
conditions set forth in the file "[LICENSE.docs](https://github.com/containerd/containerd/blob/master/LICENSE.docs)". You may obtain a duplicate
|
||||
copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/.
|
||||
|
||||
## Code of Conduct
|
||||
This project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DeepCopy makes a deep copy from src into dst.
|
||||
func DeepCopy(dst interface{}, src interface{}) error {
|
||||
if dst == nil {
|
||||
return errors.New("dst cannot be nil")
|
||||
}
|
||||
if src == nil {
|
||||
return errors.New("src cannot be nil")
|
||||
}
|
||||
bytes, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to marshal src")
|
||||
}
|
||||
err = json.Unmarshal(bytes, dst)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to unmarshal into dst")
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
// GenerateID generates a random unique id.
|
||||
func GenerateID() string {
|
||||
b := make([]byte, 32)
|
||||
rand.Read(b)
|
||||
return hex.EncodeToString(b)
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"github.com/docker/distribution/reference"
|
||||
)
|
||||
|
||||
// NormalizeImageRef normalizes the image reference following the docker convention. This is added
|
||||
// mainly for backward compatibility.
|
||||
// The reference returned can only be either tagged or digested. For reference contains both tag
|
||||
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
||||
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
||||
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
||||
func NormalizeImageRef(ref string) (reference.Named, error) {
|
||||
named, err := reference.ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := named.(reference.NamedTagged); ok {
|
||||
if canonical, ok := named.(reference.Canonical); ok {
|
||||
// The reference is both tagged and digested, only
|
||||
// return digested.
|
||||
newNamed, err := reference.WithName(canonical.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newCanonical, err := reference.WithDigest(newNamed, canonical.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newCanonical, nil
|
||||
}
|
||||
}
|
||||
return reference.TagNameOnly(named), nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue