vendor: update buildkit to opentelemetry support

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2021-06-15 21:02:39 -07:00
parent 6ba080d337
commit 334c93fbbe
829 changed files with 89541 additions and 24438 deletions

File diff suppressed because it is too large Load Diff

View File

@ -517,21 +517,21 @@ file {
number: 1
label: LABEL_OPTIONAL
type: TYPE_UINT64
json_name: "oom_kill_disable"
json_name: "oomKillDisable"
}
field {
name: "under_oom"
number: 2
label: LABEL_OPTIONAL
type: TYPE_UINT64
json_name: "under_oom"
json_name: "underOom"
}
field {
name: "oom_kill"
number: 3
label: LABEL_OPTIONAL
type: TYPE_UINT64
json_name: "oom_kill"
json_name: "oomKill"
}
}
message_type {

View File

@ -1,6 +1,8 @@
# console
[![Build Status](https://travis-ci.org/containerd/console.svg?branch=master)](https://travis-ci.org/containerd/console)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/console)](https://pkg.go.dev/github.com/containerd/console)
[![Build Status](https://github.com/containerd/console/workflows/CI/badge.svg)](https://github.com/containerd/console/actions?query=workflow%3ACI)
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/console)](https://goreportcard.com/report/github.com/containerd/console)
Golang package for dealing with consoles. Light on deps and a simple API.

View File

@ -19,8 +19,6 @@
package console
import (
"os"
"golang.org/x/sys/unix"
)
@ -28,7 +26,7 @@ import (
// The master is returned as the first console and a string
// with the path to the pty slave is returned as the second
func NewPty() (Console, string, error) {
f, err := os.OpenFile("/dev/ptmx", unix.O_RDWR|unix.O_NOCTTY|unix.O_CLOEXEC, 0)
f, err := openpt()
if err != nil {
return nil, "", err
}

View File

@ -4,5 +4,5 @@ go 1.13
require (
github.com/pkg/errors v0.9.1
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
)

View File

@ -1,4 +1,4 @@
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f h1:6Sc1XOXTulBN6imkqo6XoAXDEzoQ4/ro6xy7Vn8+rOM=
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -0,0 +1,45 @@
// +build freebsd,cgo
/*
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 console
import (
"fmt"
"os"
)
/*
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
*/
import "C"
// openpt allocates a new pseudo-terminal and establishes a connection with its
// control device.
func openpt() (*os.File, error) {
fd, err := C.posix_openpt(C.O_RDWR)
if err != nil {
return nil, fmt.Errorf("posix_openpt: %w", err)
}
if _, err := C.grantpt(fd); err != nil {
C.close(fd)
return nil, fmt.Errorf("grantpt: %w", err)
}
return os.NewFile(uintptr(fd), ""), nil
}

View File

@ -0,0 +1,36 @@
// +build freebsd,!cgo
/*
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 console
import (
"os"
)
//
// Implementing the functions below requires cgo support. Non-cgo stubs
// versions are defined below to enable cross-compilation of source code
// that depends on these functions, but the resultant cross-compiled
// binaries cannot actually be used. If the stub function(s) below are
// actually invoked they will display an error message and cause the
// calling process to exit.
//
func openpt() (*os.File, error) {
panic("openpt() support requires cgo.")
}

View File

@ -1,3 +1,5 @@
// +build darwin linux netbsd openbsd solaris
/*
Copyright The containerd Authors.
@ -14,22 +16,15 @@
limitations under the License.
*/
package sys
package console
import "os"
import (
"os"
// IsFifo checks if a file is a (named pipe) fifo
// if the file does not exist then it returns false
func IsFifo(path string) (bool, error) {
stat, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
if stat.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
return true, nil
}
return false, nil
"golang.org/x/sys/unix"
)
// openpt allocates a new pseudo-terminal by opening the /dev/ptmx device
func openpt() (*os.File, error) {
return os.OpenFile("/dev/ptmx", unix.O_RDWR|unix.O_NOCTTY|unix.O_CLOEXEC, 0)
}

View File

@ -1,3 +1,5 @@
// +build freebsd,cgo
/*
Copyright The containerd Authors.
@ -23,6 +25,12 @@ import (
"golang.org/x/sys/unix"
)
/*
#include <stdlib.h>
#include <unistd.h>
*/
import "C"
const (
cmdTcGet = unix.TIOCGETA
cmdTcSet = unix.TIOCSETA
@ -30,8 +38,12 @@ const (
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
// unlockpt should be called before opening the slave side of a pty.
// This does not exist on FreeBSD, it does not allocate controlling terminals on open
func unlockpt(f *os.File) error {
fd := C.int(f.Fd())
if _, err := C.unlockpt(fd); err != nil {
C.close(fd)
return fmt.Errorf("unlockpt: %w", err)
}
return nil
}

View File

@ -0,0 +1,55 @@
// +build freebsd,!cgo
/*
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 console
import (
"fmt"
"os"
"golang.org/x/sys/unix"
)
const (
cmdTcGet = unix.TIOCGETA
cmdTcSet = unix.TIOCSETA
)
//
// Implementing the functions below requires cgo support. Non-cgo stubs
// versions are defined below to enable cross-compilation of source code
// that depends on these functions, but the resultant cross-compiled
// binaries cannot actually be used. If the stub function(s) below are
// actually invoked they will display an error message and cause the
// calling process to exit.
//
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
// unlockpt should be called before opening the slave side of a pty.
func unlockpt(f *os.File) error {
panic("unlockpt() support requires cgo.")
}
// ptsname retrieves the name of the first available pts for the given master.
func ptsname(f *os.File) (string, error) {
n, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN)
if err != nil {
return "", err
}
return fmt.Sprintf("/dev/pts/%d", n), nil
}

View File

@ -19,6 +19,7 @@ package console
import (
"fmt"
"os"
"unsafe"
"golang.org/x/sys/unix"
)
@ -31,13 +32,19 @@ const (
// unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
// unlockpt should be called before opening the slave side of a pty.
func unlockpt(f *os.File) error {
return unix.IoctlSetPointerInt(int(f.Fd()), unix.TIOCSPTLCK, 0)
var u int32
// XXX do not use unix.IoctlSetPointerInt here, see commit dbd69c59b81.
if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))); err != 0 {
return err
}
return nil
}
// ptsname retrieves the name of the first available pts for the given master.
func ptsname(f *os.File) (string, error) {
u, err := unix.IoctlGetInt(int(f.Fd()), unix.TIOCGPTN)
if err != nil {
var u uint32
// XXX do not use unix.IoctlGetInt here, see commit dbd69c59b81.
if _, _, err := unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.TIOCGPTN, uintptr(unsafe.Pointer(&u))); err != 0 {
return "", err
}
return fmt.Sprintf("/dev/pts/%d", u), nil

View File

@ -465,7 +465,6 @@ func (s *store) Writer(ctx context.Context, opts ...content.WriterOpt) (content.
}
var lockErr error
for count := uint64(0); count < 10; count++ {
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1<<count)))
if err := tryLock(wOpts.Ref); err != nil {
if !errdefs.IsUnavailable(err) {
return nil, err
@ -476,6 +475,7 @@ func (s *store) Writer(ctx context.Context, opts ...content.WriterOpt) (content.
lockErr = nil
break
}
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1<<count)))
}
if lockErr != nil {

View File

@ -97,7 +97,14 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) {
return
}
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) (err error) {
defer func() {
err1 := rw.Close()
if err == nil {
err = err1
}
}()
var base content.Info
for _, opt := range opts {
if err := opt(&base); err != nil {

View File

@ -34,4 +34,6 @@ const (
DefaultFIFODir = "/run/containerd/fifo"
// DefaultRuntime is the default linux runtime
DefaultRuntime = "io.containerd.runc.v2"
// DefaultConfigDir is the default location for config files.
DefaultConfigDir = "/etc/containerd"
)

View File

@ -30,6 +30,9 @@ var (
// DefaultStateDir is the default location used by containerd to store
// transient data
DefaultStateDir = filepath.Join(os.Getenv("ProgramData"), "containerd", "state")
// DefaultConfigDir is the default location for config files.
DefaultConfigDir = filepath.Join(os.Getenv("programfiles"), "containerd")
)
const (

View File

@ -17,10 +17,10 @@
package images
import (
"compress/gzip"
"context"
"io"
"github.com/containerd/containerd/archive/compression"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/labels"
"github.com/opencontainers/go-digest"
@ -55,13 +55,14 @@ func GetDiffID(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (
}
defer ra.Close()
r := content.NewReader(ra)
gzR, err := gzip.NewReader(r)
uR, err := compression.DecompressStream(r)
if err != nil {
return "", err
}
defer uR.Close()
digester := digest.Canonical.Digester()
hashW := digester.Hash()
if _, err := io.Copy(hashW, gzR); err != nil {
if _, err := io.Copy(hashW, uR); err != nil {
return "", err
}
if err := ra.Close(); err != nil {

View File

@ -49,6 +49,9 @@ const (
MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto"
// Legacy Docker schema1 manifest
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
// Encypted media types
MediaTypeImageLayerEncrypted = ocispec.MediaTypeImageLayer + "+encrypted"
MediaTypeImageLayerGzipEncrypted = ocispec.MediaTypeImageLayerGzip + "+encrypted"
)
// DiffCompression returns the compression as defined by the layer diff media

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
package sys
package userns
import (
"bufio"

View File

@ -16,7 +16,7 @@
limitations under the License.
*/
package sys
package userns
// RunningInUserNS is a stub for non-Linux systems
// Always returns false

View File

@ -19,15 +19,63 @@
package platforms
import (
"fmt"
"runtime"
"strconv"
"strings"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/sys/windows"
)
// Default returns the default matcher for the platform.
func Default() MatchComparer {
return Ordered(DefaultSpec(), specs.Platform{
OS: "linux",
Architecture: runtime.GOARCH,
})
type matchComparer struct {
defaults Matcher
osVersionPrefix string
}
// Match matches platform with the same windows major, minor
// and build version.
func (m matchComparer) Match(p imagespec.Platform) bool {
if m.defaults.Match(p) {
// TODO(windows): Figure out whether OSVersion is deprecated.
return strings.HasPrefix(p.OSVersion, m.osVersionPrefix)
}
return false
}
// Less sorts matched platforms in front of other platforms.
// For matched platforms, it puts platforms with larger revision
// number in front.
func (m matchComparer) Less(p1, p2 imagespec.Platform) bool {
m1, m2 := m.Match(p1), m.Match(p2)
if m1 && m2 {
r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion)
return r1 > r2
}
return m1 && !m2
}
func revision(v string) int {
parts := strings.Split(v, ".")
if len(parts) < 4 {
return 0
}
r, err := strconv.Atoi(parts[3])
if err != nil {
return 0
}
return r
}
// Default returns the current platform's default platform specification.
func Default() MatchComparer {
major, minor, build := windows.RtlGetNtVersionNumbers()
return matchComparer{
defaults: Ordered(DefaultSpec(), specs.Platform{
OS: "linux",
Architecture: runtime.GOARCH,
}),
osVersionPrefix: fmt.Sprintf("%d.%d.%d", major, minor, build),
}
}

View File

@ -44,17 +44,47 @@ type dockerPusher struct {
tracker StatusTracker
}
// Writer implements Ingester API of content store. This allows the client
// to receive ErrUnavailable when there is already an on-going upload.
// Note that the tracker MUST implement StatusTrackLocker interface to avoid
// race condition on StatusTracker.
func (p dockerPusher) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {
var wOpts content.WriterOpts
for _, opt := range opts {
if err := opt(&wOpts); err != nil {
return nil, err
}
}
if wOpts.Ref == "" {
return nil, errors.Wrap(errdefs.ErrInvalidArgument, "ref must not be empty")
}
return p.push(ctx, wOpts.Desc, wOpts.Ref, true)
}
func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {
return p.push(ctx, desc, remotes.MakeRefKey(ctx, desc), false)
}
func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref string, unavailableOnFail bool) (content.Writer, error) {
if l, ok := p.tracker.(StatusTrackLocker); ok {
l.Lock(ref)
defer l.Unlock(ref)
}
ctx, err := ContextWithRepositoryScope(ctx, p.refspec, true)
if err != nil {
return nil, err
}
ref := remotes.MakeRefKey(ctx, desc)
status, err := p.tracker.GetStatus(ref)
if err == nil {
if status.Offset == status.Total {
if status.Committed && status.Offset == status.Total {
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "ref %v", ref)
}
if unavailableOnFail {
// Another push of this ref is happening elsewhere. The rest of function
// will continue only when `errdefs.IsNotFound(err) == true` (i.e. there
// is no actively-tracked ref already).
return nil, errors.Wrap(errdefs.ErrUnavailable, "push is on-going")
}
// TODO: Handle incomplete status
} else if !errdefs.IsNotFound(err) {
return nil, errors.Wrap(err, "failed to get status")
@ -105,8 +135,11 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
if exists {
p.tracker.SetStatus(ref, Status{
Committed: true,
Status: content.Status{
Ref: ref,
Ref: ref,
Total: desc.Size,
Offset: desc.Size,
// TODO: Set updated time?
},
})
@ -162,8 +195,11 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
case http.StatusOK, http.StatusAccepted, http.StatusNoContent:
case http.StatusCreated:
p.tracker.SetStatus(ref, Status{
Committed: true,
Status: content.Status{
Ref: ref,
Ref: ref,
Total: desc.Size,
Offset: desc.Size,
},
})
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
@ -341,8 +377,6 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
if err := pw.pipe.Close(); err != nil {
return err
}
// TODO: Update status to determine committing
// TODO: timeout waiting for response
resp := <-pw.responseC
if resp.err != nil {
@ -379,6 +413,10 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
return errors.Errorf("got digest %s, expected %s", actual, expected)
}
status.Committed = true
status.UpdatedAt = time.Now()
pw.tracker.SetStatus(pw.ref, status)
return nil
}

View File

@ -17,7 +17,10 @@
package docker
import (
"net"
"net/http"
"github.com/pkg/errors"
)
// HostCapabilities represent the capabilities of the registry
@ -202,12 +205,41 @@ func MatchAllHosts(string) (bool, error) {
// MatchLocalhost is a host match function which returns true for
// localhost.
//
// Note: this does not handle matching of ip addresses in octal,
// decimal or hex form.
func MatchLocalhost(host string) (bool, error) {
for _, s := range []string{"localhost", "127.0.0.1", "[::1]"} {
if len(host) >= len(s) && host[0:len(s)] == s && (len(host) == len(s) || host[len(s)] == ':') {
return true, nil
}
switch {
case host == "::1":
return true, nil
case host == "[::1]":
return true, nil
}
return host == "::1", nil
h, p, err := net.SplitHostPort(host)
// addrError helps distinguish between errors of form
// "no colon in address" and "too many colons in address".
// The former is fine as the host string need not have a
// port. Latter needs to be handled.
addrError := &net.AddrError{
Err: "missing port in address",
Addr: host,
}
if err != nil {
if err.Error() != addrError.Error() {
return false, err
}
// host string without any port specified
h = host
} else if len(p) == 0 {
return false, errors.New("invalid host name format")
}
// use ipv4 dotted decimal for further checking
if h == "localhost" {
h = "127.0.0.1"
}
ip := net.ParseIP(h)
return ip.IsLoopback(), nil
}

View File

@ -286,12 +286,14 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
if lastErr == nil {
lastErr = err
}
log.G(ctx).WithError(err).Info("trying next host")
continue // try another host
}
resp.Body.Close() // don't care about body contents.
if resp.StatusCode > 299 {
if resp.StatusCode == http.StatusNotFound {
log.G(ctx).Info("trying next host - response was http.StatusNotFound")
continue
}
return "", ocispec.Descriptor{}, errors.Errorf("unexpected status code %v: %v", u, resp.Status)

View File

@ -21,6 +21,7 @@ import (
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/moby/locker"
"github.com/pkg/errors"
)
@ -28,6 +29,8 @@ import (
type Status struct {
content.Status
Committed bool
// UploadUUID is used by the Docker registry to reference blob uploads
UploadUUID string
}
@ -38,15 +41,24 @@ type StatusTracker interface {
SetStatus(string, Status)
}
// StatusTrackLocker to track status of operations with lock
type StatusTrackLocker interface {
StatusTracker
Lock(string)
Unlock(string)
}
type memoryStatusTracker struct {
statuses map[string]Status
m sync.Mutex
locker *locker.Locker
}
// NewInMemoryTracker returns a StatusTracker that tracks content status in-memory
func NewInMemoryTracker() StatusTracker {
func NewInMemoryTracker() StatusTrackLocker {
return &memoryStatusTracker{
statuses: map[string]Status{},
locker: locker.New(),
}
}
@ -65,3 +77,11 @@ func (t *memoryStatusTracker) SetStatus(ref string, status Status) {
t.statuses[ref] = status
t.m.Unlock()
}
func (t *memoryStatusTracker) Lock(ref string) {
t.locker.Lock(ref)
}
func (t *memoryStatusTracker) Unlock(ref string) {
t.locker.Unlock(ref)
}

View File

@ -31,6 +31,7 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sync/semaphore"
)
type refKeyPrefix struct{}
@ -55,25 +56,32 @@ func WithMediaTypeKeyPrefix(ctx context.Context, mediaType, prefix string) conte
// used to lookup ongoing processes related to the descriptor. This function
// may look to the context to namespace the reference appropriately.
func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string {
key := desc.Digest.String()
if desc.Annotations != nil {
if name, ok := desc.Annotations[ocispec.AnnotationRefName]; ok {
key = fmt.Sprintf("%s@%s", name, desc.Digest.String())
}
}
if v := ctx.Value(refKeyPrefix{}); v != nil {
values := v.(map[string]string)
if prefix := values[desc.MediaType]; prefix != "" {
return prefix + "-" + desc.Digest.String()
return prefix + "-" + key
}
}
switch mt := desc.MediaType; {
case mt == images.MediaTypeDockerSchema2Manifest || mt == ocispec.MediaTypeImageManifest:
return "manifest-" + desc.Digest.String()
return "manifest-" + key
case mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex:
return "index-" + desc.Digest.String()
return "index-" + key
case images.IsLayerType(mt):
return "layer-" + desc.Digest.String()
return "layer-" + key
case images.IsKnownConfig(mt):
return "config-" + desc.Digest.String()
return "config-" + key
default:
log.G(ctx).Warnf("reference for unknown type: %s", mt)
return "unknown-" + desc.Digest.String()
return "unknown-" + key
}
}
@ -157,7 +165,15 @@ func PushHandler(pusher Pusher, provider content.Provider) images.HandlerFunc {
func push(ctx context.Context, provider content.Provider, pusher Pusher, desc ocispec.Descriptor) error {
log.G(ctx).Debug("push")
cw, err := pusher.Push(ctx, desc)
var (
cw content.Writer
err error
)
if cs, ok := pusher.(content.Ingester); ok {
cw, err = content.OpenWriter(ctx, cs, content.WithRef(MakeRefKey(ctx, desc)), content.WithDescriptor(desc))
} else {
cw, err = pusher.Push(ctx, desc)
}
if err != nil {
if !errdefs.IsAlreadyExists(err) {
return err
@ -181,7 +197,8 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
//
// Base handlers can be provided which will be called before any push specific
// handlers.
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Store, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {
var m sync.Mutex
manifestStack := []ocispec.Descriptor{}
@ -213,7 +230,7 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st
handler = wrapper(handler)
}
if err := images.Dispatch(ctx, handler, nil, desc); err != nil {
if err := images.Dispatch(ctx, handler, limiter, desc); err != nil {
return err
}

View File

@ -45,6 +45,8 @@ type Resolver interface {
Fetcher(ctx context.Context, ref string) (Fetcher, error)
// Pusher returns a new pusher for the provided reference
// The returned Pusher should satisfy content.Ingester and concurrent attempts
// to push the same blob using the Ingester API should result in ErrUnavailable.
Pusher(ctx context.Context, ref string) (Pusher, error)
}

View File

@ -22,11 +22,14 @@ import (
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/Microsoft/hcsshim"
"github.com/pkg/errors"
"golang.org/x/sys/windows"
)
@ -257,12 +260,71 @@ func windowsOpenSequential(path string, mode int, _ uint32) (fd windows.Handle,
return h, e
}
// ForceRemoveAll is the same as os.RemoveAll, but uses hcsshim.DestroyLayer in order
// to delete container layers.
// ForceRemoveAll is the same as os.RemoveAll, but is aware of io.containerd.snapshotter.v1.windows
// and uses hcsshim to unmount and delete container layers contained therein, in the correct order,
// when passed a containerd root data directory (i.e. the `--root` directory for containerd).
func ForceRemoveAll(path string) error {
info := hcsshim.DriverInfo{
HomeDir: filepath.Dir(path),
// snapshots/windows/windows.go init()
const snapshotPlugin = "io.containerd.snapshotter.v1" + "." + "windows"
// snapshots/windows/windows.go NewSnapshotter()
snapshotDir := filepath.Join(path, snapshotPlugin, "snapshots")
if stat, err := os.Stat(snapshotDir); err == nil && stat.IsDir() {
if err := cleanupWCOWLayers(snapshotDir); err != nil {
return errors.Wrapf(err, "failed to cleanup WCOW layers in %s", snapshotDir)
}
}
return hcsshim.DestroyLayer(info, filepath.Base(path))
return os.RemoveAll(path)
}
func cleanupWCOWLayers(root string) error {
// See snapshots/windows/windows.go getSnapshotDir()
var layerNums []int
if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if path != root && info.IsDir() {
if layerNum, err := strconv.Atoi(filepath.Base(path)); err == nil {
layerNums = append(layerNums, layerNum)
} else {
return err
}
return filepath.SkipDir
}
return nil
}); err != nil {
return err
}
sort.Sort(sort.Reverse(sort.IntSlice(layerNums)))
for _, layerNum := range layerNums {
if err := cleanupWCOWLayer(filepath.Join(root, strconv.Itoa(layerNum))); err != nil {
return err
}
}
return nil
}
func cleanupWCOWLayer(layerPath string) error {
info := hcsshim.DriverInfo{
HomeDir: filepath.Dir(layerPath),
}
// ERROR_DEV_NOT_EXIST is returned if the layer is not currently prepared.
if err := hcsshim.UnprepareLayer(info, filepath.Base(layerPath)); err != nil {
if hcserror, ok := err.(*hcsshim.HcsError); !ok || hcserror.Err != windows.ERROR_DEV_NOT_EXIST {
return errors.Wrapf(err, "failed to unprepare %s", layerPath)
}
}
if err := hcsshim.DeactivateLayer(info, filepath.Base(layerPath)); err != nil {
return errors.Wrapf(err, "failed to deactivate %s", layerPath)
}
if err := hcsshim.DestroyLayer(info, filepath.Base(layerPath)); err != nil {
return errors.Wrapf(err, "failed to destroy %s", layerPath)
}
return nil
}

View File

@ -1,5 +1,3 @@
// +build !windows
/*
Copyright The containerd Authors.
@ -24,17 +22,34 @@ import (
"os"
"strconv"
"strings"
"github.com/containerd/containerd/pkg/userns"
"golang.org/x/sys/unix"
)
const (
// OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer
OOMScoreMaxKillable = -999
// OOMScoreAdjMax is from OOM_SCORE_ADJ_MAX https://github.com/torvalds/linux/blob/master/include/uapi/linux/oom.h
// OOMScoreAdjMin is from OOM_SCORE_ADJ_MIN https://github.com/torvalds/linux/blob/v5.10/include/uapi/linux/oom.h#L9
OOMScoreAdjMin = -1000
// OOMScoreAdjMax is from OOM_SCORE_ADJ_MAX https://github.com/torvalds/linux/blob/v5.10/include/uapi/linux/oom.h#L10
OOMScoreAdjMax = 1000
)
// AdjustOOMScore sets the oom score for the provided pid. If the provided score
// is out of range (-1000 - 1000), it is clipped to the min/max value.
func AdjustOOMScore(pid, score int) error {
if score > OOMScoreAdjMax {
score = OOMScoreAdjMax
} else if score < OOMScoreAdjMin {
score = OOMScoreAdjMin
}
return SetOOMScore(pid, score)
}
// SetOOMScore sets the oom score for the provided pid
func SetOOMScore(pid, score int) error {
if score > OOMScoreAdjMax || score < OOMScoreAdjMin {
return fmt.Errorf("value out of range (%d): OOM score must be between %d and %d", score, OOMScoreAdjMin, OOMScoreAdjMax)
}
path := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
f, err := os.OpenFile(path, os.O_WRONLY, 0)
if err != nil {
@ -42,7 +57,7 @@ func SetOOMScore(pid, score int) error {
}
defer f.Close()
if _, err = f.WriteString(strconv.Itoa(score)); err != nil {
if os.IsPermission(err) && (RunningInUserNS() || RunningUnprivileged()) {
if os.IsPermission(err) && (!runningPrivileged() || userns.RunningInUserNS()) {
return nil
}
return err
@ -50,7 +65,8 @@ func SetOOMScore(pid, score int) error {
return nil
}
// GetOOMScoreAdj gets the oom score for a process
// GetOOMScoreAdj gets the oom score for a process. It returns 0 (zero) if either
// no oom score is set, or a sore is set to 0.
func GetOOMScoreAdj(pid int) (int, error) {
path := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
data, err := ioutil.ReadFile(path)
@ -59,3 +75,9 @@ func GetOOMScoreAdj(pid int) (int, error) {
}
return strconv.Atoi(strings.TrimSpace(string(data)))
}
// runningPrivileged returns true if the effective user ID of the
// calling process is 0
func runningPrivileged() bool {
return unix.Geteuid() == 0
}

View File

@ -1,3 +1,5 @@
// +build !linux
/*
Copyright The containerd Authors.
@ -17,10 +19,20 @@
package sys
const (
// OOMScoreAdjMax is not implemented on Windows
// OOMScoreMaxKillable is not implemented on non Linux
OOMScoreMaxKillable = 0
// OOMScoreAdjMax is not implemented on non Linux
OOMScoreAdjMax = 0
)
// AdjustOOMScore sets the oom score for the provided pid. If the provided score
// is out of range (-1000 - 1000), it is clipped to the min/max value.
//
// Not implemented on Windows
func AdjustOOMScore(pid, score int) error {
return nil
}
// SetOOMScore sets the oom score for the process
//
// Not implemented on Windows

View File

@ -1,5 +1,3 @@
// +build !windows
/*
Copyright The containerd Authors.
@ -18,16 +16,8 @@
package sys
import "golang.org/x/sys/unix"
import "github.com/containerd/containerd/pkg/userns"
// RunningPrivileged returns true if the effective user ID of the
// calling process is 0
func RunningPrivileged() bool {
return unix.Geteuid() == 0
}
// RunningUnprivileged returns true if the effective user ID of the
// calling process is not 0
func RunningUnprivileged() bool {
return !RunningPrivileged()
}
// RunningInUserNS detects whether we are currently running in a user namespace.
// Deprecated: use github.com/containerd/containerd/pkg/userns.RunningInUserNS instead.
var RunningInUserNS = userns.RunningInUserNS

View File

@ -23,7 +23,7 @@ var (
Package = "github.com/containerd/containerd"
// Version holds the complete version number. Filled in at linking time.
Version = "1.5.0-beta.4+unknown"
Version = "1.5.2+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time.

View File

@ -1,8 +1,9 @@
# typeurl
[![Build Status](https://travis-ci.org/containerd/typeurl.svg?branch=master)](https://travis-ci.org/containerd/typeurl)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/typeurl)](https://pkg.go.dev/github.com/containerd/typeurl)
[![Build Status](https://github.com/containerd/typeurl/workflows/CI/badge.svg)](https://github.com/containerd/typeurl/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/containerd/typeurl/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/typeurl)
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/typeurl)](https://goreportcard.com/report/github.com/containerd/typeurl)
A Go package for managing the registration, marshaling, and unmarshaling of encoded types.

View File

@ -3,6 +3,6 @@ module github.com/containerd/typeurl
go 1.13
require (
github.com/gogo/protobuf v1.3.1
github.com/gogo/protobuf v1.3.2
github.com/pkg/errors v0.9.1
)

View File

@ -1,7 +1,33 @@
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -28,11 +28,20 @@ import (
)
var (
mu sync.Mutex
mu sync.RWMutex
registry = make(map[reflect.Type]string)
)
var ErrNotFound = errors.New("not found")
// Definitions of common error types used throughout typeurl.
//
// These error types are used with errors.Wrap and errors.Wrapf to add context
// to an error.
//
// To detect an error class, use errors.Is() functions to tell whether an
// error is of this type.
var (
ErrNotFound = errors.New("not found")
)
// Register a type with a base URL for JSON marshaling. When the MarshalAny and
// UnmarshalAny functions are called they will treat the Any type value as JSON.
@ -56,9 +65,9 @@ func Register(v interface{}, args ...string) {
// TypeURL returns the type url for a registered type.
func TypeURL(v interface{}) (string, error) {
mu.Lock()
mu.RLock()
u, ok := registry[tryDereference(v)]
mu.Unlock()
mu.RUnlock()
if !ok {
// fallback to the proto registry if it is a proto message
pb, ok := v.(proto.Message)
@ -119,14 +128,21 @@ func UnmarshalAny(any *types.Any) (interface{}, error) {
return UnmarshalByTypeURL(any.TypeUrl, any.Value)
}
// UnmarshalByTypeURL unmarshals the given type and value to into a concrete type.
func UnmarshalByTypeURL(typeURL string, value []byte) (interface{}, error) {
return unmarshal(typeURL, value, nil)
}
// UnmarshalTo unmarshals the any type into a concrete type passed in the out
// argument. It is identical to UnmarshalAny, but lets clients provide a
// destination type through the out argument.
func UnmarshalTo(any *types.Any, out interface{}) error {
return UnmarshalToByTypeURL(any.TypeUrl, any.Value, out)
}
// UnmarshalTo unmarshals the given type and value into a concrete type passed
// in the out argument. It is identical to UnmarshalByTypeURL, but lets clients
// provide a destination type through the out argument.
func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
_, err := unmarshal(typeURL, value, out)
return err
@ -166,13 +182,16 @@ type urlType struct {
}
func getTypeByUrl(url string) (urlType, error) {
mu.RLock()
for t, u := range registry {
if u == url {
mu.RUnlock()
return urlType{
t: t,
}, nil
}
}
mu.RUnlock()
// fallback to proto registry
t := proto.MessageType(url)
if t != nil {