summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/shim/runsc/BUILD16
-rw-r--r--pkg/shim/runsc/runsc.go49
-rw-r--r--pkg/shim/v1/proc/BUILD35
-rw-r--r--pkg/shim/v1/proc/deleted_state.go12
-rw-r--r--pkg/shim/v1/proc/exec.go25
-rw-r--r--pkg/shim/v1/proc/exec_state.go16
-rw-r--r--pkg/shim/v1/proc/init.go80
-rw-r--r--pkg/shim/v1/proc/init_state.go18
-rw-r--r--pkg/shim/v1/proc/io.go5
-rw-r--r--pkg/shim/v1/proc/process.go6
-rw-r--r--pkg/shim/v1/proc/types.go10
-rw-r--r--pkg/shim/v1/proc/utils.go2
-rw-r--r--pkg/shim/v1/shim/BUILD38
-rw-r--r--pkg/shim/v1/shim/platform.go10
-rw-r--r--pkg/shim/v1/shim/service.go68
-rw-r--r--pkg/shim/v1/utils/BUILD26
-rw-r--r--pkg/shim/v1/utils/volumes.go41
-rw-r--r--pkg/shim/v2/BUILD41
-rw-r--r--pkg/shim/v2/epoll.go6
-rw-r--r--pkg/shim/v2/options/BUILD11
-rw-r--r--pkg/shim/v2/service.go115
-rw-r--r--pkg/shim/v2/service_linux.go10
-rw-r--r--pkg/test/criutil/criutil.go66
23 files changed, 461 insertions, 245 deletions
diff --git a/pkg/shim/runsc/BUILD b/pkg/shim/runsc/BUILD
new file mode 100644
index 000000000..4d388ca05
--- /dev/null
+++ b/pkg/shim/runsc/BUILD
@@ -0,0 +1,16 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "runsc",
+ srcs = [
+ "runsc.go",
+ "utils.go",
+ ],
+ visibility = ["//:sandbox"],
+ deps = [
+ "@com_github_containerd_go_runc//:go_default_library",
+ "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ ],
+)
diff --git a/pkg/shim/runsc/runsc.go b/pkg/shim/runsc/runsc.go
index 41ba9c3af..50807d0c5 100644
--- a/pkg/shim/runsc/runsc.go
+++ b/pkg/shim/runsc/runsc.go
@@ -34,10 +34,10 @@ import (
var Monitor runc.ProcessMonitor = runc.Monitor
-// DefaultCommand is the default command for Runsc
+// DefaultCommand is the default command for Runsc.
const DefaultCommand = "runsc"
-// Runsc is the client to the runsc cli
+// Runsc is the client to the runsc cli.
type Runsc struct {
Command string
PdeathSignal syscall.Signal
@@ -48,7 +48,7 @@ type Runsc struct {
Config map[string]string
}
-// List returns all containers created inside the provided runsc root directory
+// List returns all containers created inside the provided runsc root directory.
func (r *Runsc) List(context context.Context) ([]*runc.Container, error) {
data, err := cmdOutput(r.command(context, "list", "--format=json"), false)
if err != nil {
@@ -61,7 +61,7 @@ func (r *Runsc) List(context context.Context) ([]*runc.Container, error) {
return out, nil
}
-// State returns the state for the container provided by id
+// State returns the state for the container provided by id.
func (r *Runsc) State(context context.Context, id string) (*runc.Container, error) {
data, err := cmdOutput(r.command(context, "state", id), true)
if err != nil {
@@ -76,9 +76,11 @@ func (r *Runsc) State(context context.Context, id string) (*runc.Container, erro
type CreateOpts struct {
runc.IO
- // PidFile is a path to where a pid file should be created
- PidFile string
ConsoleSocket runc.ConsoleSocket
+
+ // PidFile is a path to where a pid file should be created.
+ PidFile string
+
// UserLog is a path to where runsc user log should be generated.
UserLog string
}
@@ -100,7 +102,7 @@ func (o *CreateOpts) args() (out []string, err error) {
return out, nil
}
-// Create creates a new container and returns its pid if it was created successfully
+// Create creates a new container and returns its pid if it was created successfully.
func (r *Runsc) Create(context context.Context, id, bundle string, opts *CreateOpts) error {
args := []string{"create", "--bundle", bundle}
if opts != nil {
@@ -141,7 +143,7 @@ func (r *Runsc) Create(context context.Context, id, bundle string, opts *CreateO
return err
}
-// Start will start an already created container
+// Start will start an already created container.
func (r *Runsc) Start(context context.Context, id string, cio runc.IO) error {
cmd := r.command(context, "start", id)
if cio != nil {
@@ -181,6 +183,7 @@ type waitResult struct {
}
// Wait will wait for a running container, and return its exit status.
+//
// TODO(random-liu): Add exec process support.
func (r *Runsc) Wait(context context.Context, id string) (int, error) {
data, err := cmdOutput(r.command(context, "wait", id), true)
@@ -226,8 +229,8 @@ func (o *ExecOpts) args() (out []string, err error) {
return out, nil
}
-// Exec executres and additional process inside the container based on a full
-// OCI Process specification
+// Exec executes an additional process inside the container based on a full OCI
+// Process specification.
func (r *Runsc) Exec(context context.Context, id string, spec specs.Process, opts *ExecOpts) error {
f, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "runsc-process")
if err != nil {
@@ -276,8 +279,8 @@ func (r *Runsc) Exec(context context.Context, id string, spec specs.Process, opt
return err
}
-// Run runs the create, start, delete lifecycle of the container
-// and returns its exit status after it has exited
+// Run runs the create, start, delete lifecycle of the container and returns
+// its exit status after it has exited.
func (r *Runsc) Run(context context.Context, id, bundle string, opts *CreateOpts) (int, error) {
args := []string{"run", "--bundle", bundle}
if opts != nil {
@@ -309,7 +312,7 @@ func (o *DeleteOpts) args() (out []string) {
return out
}
-// Delete deletes the container
+// Delete deletes the container.
func (r *Runsc) Delete(context context.Context, id string, opts *DeleteOpts) error {
args := []string{"delete"}
if opts != nil {
@@ -318,7 +321,7 @@ func (r *Runsc) Delete(context context.Context, id string, opts *DeleteOpts) err
return r.runOrError(r.command(context, append(args, id)...))
}
-// KillOpts specifies options for killing a container and its processes
+// KillOpts specifies options for killing a container and its processes.
type KillOpts struct {
All bool
Pid int
@@ -334,7 +337,7 @@ func (o *KillOpts) args() (out []string) {
return out
}
-// Kill sends the specified signal to the container
+// Kill sends the specified signal to the container.
func (r *Runsc) Kill(context context.Context, id string, sig int, opts *KillOpts) error {
args := []string{
"kill",
@@ -345,7 +348,7 @@ func (r *Runsc) Kill(context context.Context, id string, sig int, opts *KillOpts
return r.runOrError(r.command(context, append(args, id, strconv.Itoa(sig))...))
}
-// Stats return the stats for a container like cpu, memory, and io
+// Stats return the stats for a container like cpu, memory, and I/O.
func (r *Runsc) Stats(context context.Context, id string) (*runc.Stats, error) {
cmd := r.command(context, "events", "--stats", id)
rd, err := cmd.StdoutPipe()
@@ -367,7 +370,7 @@ func (r *Runsc) Stats(context context.Context, id string) (*runc.Stats, error) {
return e.Stats, nil
}
-// Events returns an event stream from runsc for a container with stats and OOM notifications
+// Events returns an event stream from runsc for a container with stats and OOM notifications.
func (r *Runsc) Events(context context.Context, id string, interval time.Duration) (chan *runc.Event, error) {
cmd := r.command(context, "events", fmt.Sprintf("--interval=%ds", int(interval.Seconds())), id)
rd, err := cmd.StdoutPipe()
@@ -406,7 +409,7 @@ func (r *Runsc) Events(context context.Context, id string, interval time.Duratio
return c, nil
}
-// Ps lists all the processes inside the container returning their pids
+// Ps lists all the processes inside the container returning their pids.
func (r *Runsc) Ps(context context.Context, id string) ([]int, error) {
data, err := cmdOutput(r.command(context, "ps", "--format", "json", id), true)
if err != nil {
@@ -419,7 +422,7 @@ func (r *Runsc) Ps(context context.Context, id string) ([]int, error) {
return pids, nil
}
-// Top lists all the processes inside the container returning the full ps data
+// Top lists all the processes inside the container returning the full ps data.
func (r *Runsc) Top(context context.Context, id string) (*runc.TopResults, error) {
data, err := cmdOutput(r.command(context, "ps", "--format", "table", id), true)
if err != nil {
@@ -450,10 +453,10 @@ func (r *Runsc) args() []string {
return args
}
-// runOrError will run the provided command. If an error is
-// encountered and neither Stdout or Stderr was set the error and the
-// stderr of the command will be returned in the format of <error>:
-// <stderr>
+// runOrError will run the provided command.
+//
+// If an error is encountered and neither Stdout or Stderr was set the error
+// will be returned in the format of <error>: <stderr>.
func (r *Runsc) runOrError(cmd *exec.Cmd) error {
if cmd.Stdout != nil || cmd.Stderr != nil {
ec, err := Monitor.Start(cmd)
diff --git a/pkg/shim/v1/proc/BUILD b/pkg/shim/v1/proc/BUILD
new file mode 100644
index 000000000..a59bf198d
--- /dev/null
+++ b/pkg/shim/v1/proc/BUILD
@@ -0,0 +1,35 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "proc",
+ srcs = [
+ "deleted_state.go",
+ "exec.go",
+ "exec_state.go",
+ "init.go",
+ "init_state.go",
+ "io.go",
+ "process.go",
+ "types.go",
+ "utils.go",
+ ],
+ visibility = [
+ "//pkg/shim:__subpackages__",
+ "//shim:__subpackages__",
+ ],
+ deps = [
+ "//pkg/shim/runsc",
+ "@com_github_containerd_console//:go_default_library",
+ "@com_github_containerd_containerd//errdefs:go_default_library",
+ "@com_github_containerd_containerd//log:go_default_library",
+ "@com_github_containerd_containerd//mount:go_default_library",
+ "@com_github_containerd_containerd//runtime/proc:go_default_library",
+ "@com_github_containerd_fifo//:go_default_library",
+ "@com_github_containerd_go_runc//:go_default_library",
+ "@com_github_gogo_protobuf//types:go_default_library",
+ "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@org_golang_x_sys//unix:go_default_library",
+ ],
+)
diff --git a/pkg/shim/v1/proc/deleted_state.go b/pkg/shim/v1/proc/deleted_state.go
index 0196c96dd..52aad40ac 100644
--- a/pkg/shim/v1/proc/deleted_state.go
+++ b/pkg/shim/v1/proc/deleted_state.go
@@ -17,33 +17,33 @@ package proc
import (
"context"
+ "fmt"
"github.com/containerd/console"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/runtime/proc"
- "github.com/pkg/errors"
)
type deletedState struct{}
func (*deletedState) Resize(ws console.WinSize) error {
- return errors.Errorf("cannot resize a deleted process")
+ return fmt.Errorf("cannot resize a deleted process")
}
func (*deletedState) Start(ctx context.Context) error {
- return errors.Errorf("cannot start a deleted process")
+ return fmt.Errorf("cannot start a deleted process")
}
func (*deletedState) Delete(ctx context.Context) error {
- return errors.Wrap(errdefs.ErrNotFound, "cannot delete a deleted process")
+ return fmt.Errorf("cannot delete a deleted process: %w", errdefs.ErrNotFound)
}
func (*deletedState) Kill(ctx context.Context, sig uint32, all bool) error {
- return errors.Wrap(errdefs.ErrNotFound, "cannot kill a deleted process")
+ return fmt.Errorf("cannot kill a deleted process: %w", errdefs.ErrNotFound)
}
func (*deletedState) SetExited(status int) {}
func (*deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
- return nil, errors.Errorf("cannot exec in a deleted state")
+ return nil, fmt.Errorf("cannot exec in a deleted state")
}
diff --git a/pkg/shim/v1/proc/exec.go b/pkg/shim/v1/proc/exec.go
index 6821e09cd..4ef9cf6cf 100644
--- a/pkg/shim/v1/proc/exec.go
+++ b/pkg/shim/v1/proc/exec.go
@@ -31,7 +31,6 @@ import (
"github.com/containerd/fifo"
runc "github.com/containerd/go-runc"
specs "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/shim/runsc"
@@ -151,9 +150,11 @@ func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error {
if err := e.parent.runtime.Kill(ctx, e.parent.id, int(sig), &runsc.KillOpts{
Pid: internalPid,
}); err != nil {
- // If this returns error, consider the process has already stopped.
+ // If this returns error, consider the process has
+ // already stopped.
+ //
// TODO: Fix after signal handling is fixed.
- return errors.Wrapf(errdefs.ErrNotFound, err.Error())
+ return fmt.Errorf("%s: %w", err.Error(), errdefs.ErrNotFound)
}
}
return nil
@@ -182,16 +183,16 @@ func (e *execProcess) start(ctx context.Context) (err error) {
)
if e.stdio.Terminal {
if socket, err = runc.NewTempConsoleSocket(); err != nil {
- return errors.Wrap(err, "failed to create runc console socket")
+ return fmt.Errorf("failed to create runc console socket: %w", err)
}
defer socket.Close()
} else if e.stdio.IsNull() {
if e.io, err = runc.NewNullIO(); err != nil {
- return errors.Wrap(err, "creating new NULL IO")
+ return fmt.Errorf("creating new NULL IO: %w", err)
}
} else {
if e.io, err = runc.NewPipeIO(e.parent.IoUID, e.parent.IoGID, withConditionalIO(e.stdio)); err != nil {
- return errors.Wrap(err, "failed to create runc io pipes")
+ return fmt.Errorf("failed to create runc io pipes: %w", err)
}
}
opts := &runsc.ExecOpts{
@@ -217,7 +218,7 @@ func (e *execProcess) start(ctx context.Context) (err error) {
if e.stdio.Stdin != "" {
sc, err := fifo.OpenFifo(context.Background(), e.stdio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0)
if err != nil {
- return errors.Wrapf(err, "failed to open stdin fifo %s", e.stdio.Stdin)
+ return fmt.Errorf("failed to open stdin fifo %s: %w", e.stdio.Stdin, err)
}
e.closers = append(e.closers, sc)
e.stdin = sc
@@ -228,25 +229,25 @@ func (e *execProcess) start(ctx context.Context) (err error) {
if socket != nil {
console, err := socket.ReceiveMaster()
if err != nil {
- return errors.Wrap(err, "failed to retrieve console master")
+ return fmt.Errorf("failed to retrieve console master: %w", err)
}
if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, &copyWaitGroup); err != nil {
- return errors.Wrap(err, "failed to start console copy")
+ return fmt.Errorf("failed to start console copy: %w", err)
}
} else if !e.stdio.IsNull() {
if err := copyPipes(ctx, e.io, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, &copyWaitGroup); err != nil {
- return errors.Wrap(err, "failed to start io pipe copy")
+ return fmt.Errorf("failed to start io pipe copy: %w", err)
}
}
copyWaitGroup.Wait()
pid, err := runc.ReadPidFile(opts.PidFile)
if err != nil {
- return errors.Wrap(err, "failed to retrieve OCI runtime exec pid")
+ return fmt.Errorf("failed to retrieve OCI runtime exec pid: %w", err)
}
e.pid = pid
internalPid, err := runc.ReadPidFile(opts.InternalPidFile)
if err != nil {
- return errors.Wrap(err, "failed to retrieve OCI runtime exec internal pid")
+ return fmt.Errorf("failed to retrieve OCI runtime exec internal pid: %w", err)
}
e.internalPid = internalPid
go func() {
diff --git a/pkg/shim/v1/proc/exec_state.go b/pkg/shim/v1/proc/exec_state.go
index 5416cb601..4dcda8b44 100644
--- a/pkg/shim/v1/proc/exec_state.go
+++ b/pkg/shim/v1/proc/exec_state.go
@@ -17,9 +17,9 @@ package proc
import (
"context"
+ "fmt"
"github.com/containerd/console"
- "github.com/pkg/errors"
)
type execState interface {
@@ -43,7 +43,7 @@ func (s *execCreatedState) transition(name string) error {
case "deleted":
s.p.execState = &deletedState{}
default:
- return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
+ return fmt.Errorf("invalid state transition %q to %q", stateName(s), name)
}
return nil
}
@@ -87,7 +87,7 @@ func (s *execRunningState) transition(name string) error {
case "stopped":
s.p.execState = &execStoppedState{p: s.p}
default:
- return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
+ return fmt.Errorf("invalid state transition %q to %q", stateName(s), name)
}
return nil
}
@@ -97,11 +97,11 @@ func (s *execRunningState) Resize(ws console.WinSize) error {
}
func (s *execRunningState) Start(ctx context.Context) error {
- return errors.Errorf("cannot start a running process")
+ return fmt.Errorf("cannot start a running process")
}
func (s *execRunningState) Delete(ctx context.Context) error {
- return errors.Errorf("cannot delete a running process")
+ return fmt.Errorf("cannot delete a running process")
}
func (s *execRunningState) Kill(ctx context.Context, sig uint32, all bool) error {
@@ -125,17 +125,17 @@ func (s *execStoppedState) transition(name string) error {
case "deleted":
s.p.execState = &deletedState{}
default:
- return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
+ return fmt.Errorf("invalid state transition %q to %q", stateName(s), name)
}
return nil
}
func (s *execStoppedState) Resize(ws console.WinSize) error {
- return errors.Errorf("cannot resize a stopped container")
+ return fmt.Errorf("cannot resize a stopped container")
}
func (s *execStoppedState) Start(ctx context.Context) error {
- return errors.Errorf("cannot start a stopped process")
+ return fmt.Errorf("cannot start a stopped process")
}
func (s *execStoppedState) Delete(ctx context.Context) error {
diff --git a/pkg/shim/v1/proc/init.go b/pkg/shim/v1/proc/init.go
index 0771540a9..b429cb94f 100644
--- a/pkg/shim/v1/proc/init.go
+++ b/pkg/shim/v1/proc/init.go
@@ -18,6 +18,7 @@ package proc
import (
"context"
"encoding/json"
+ "fmt"
"io"
"path/filepath"
"strings"
@@ -33,23 +34,22 @@ import (
"github.com/containerd/fifo"
runc "github.com/containerd/go-runc"
specs "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
"gvisor.dev/gvisor/pkg/shim/runsc"
)
-// InitPidFile name of the file that contains the init pid
+// InitPidFile name of the file that contains the init pid.
const InitPidFile = "init.pid"
-// Init represents an initial process for a container
+// Init represents an initial process for a container.
type Init struct {
wg sync.WaitGroup
initState initState
// mu is used to ensure that `Start()` and `Exited()` calls return in
- // the right order when invoked in separate go routines.
- // This is the case within the shim implementation as it makes use of
- // the reaper interface.
+ // the right order when invoked in separate go routines. This is the
+ // case within the shim implementation as it makes use of the reaper
+ // interface.
mu sync.Mutex
waitBlock chan struct{}
@@ -76,7 +76,7 @@ type Init struct {
Monitor ProcessMonitor
}
-// NewRunsc returns a new runsc instance for a process
+// NewRunsc returns a new runsc instance for a process.
func NewRunsc(root, path, namespace, runtime string, config map[string]string) *runsc.Runsc {
if root == "" {
root = RunscRoot
@@ -91,7 +91,7 @@ func NewRunsc(root, path, namespace, runtime string, config map[string]string) *
}
}
-// New returns a new init process
+// New returns a new init process.
func New(id string, runtime *runsc.Runsc, stdio proc.Stdio) *Init {
p := &Init{
id: id,
@@ -104,21 +104,21 @@ func New(id string, runtime *runsc.Runsc, stdio proc.Stdio) *Init {
return p
}
-// Create the process with the provided config
+// Create the process with the provided config.
func (p *Init) Create(ctx context.Context, r *CreateConfig) (err error) {
var socket *runc.Socket
if r.Terminal {
if socket, err = runc.NewTempConsoleSocket(); err != nil {
- return errors.Wrap(err, "failed to create OCI runtime console socket")
+ return fmt.Errorf("failed to create OCI runtime console socket: %w", err)
}
defer socket.Close()
} else if hasNoIO(r) {
if p.io, err = runc.NewNullIO(); err != nil {
- return errors.Wrap(err, "creating new NULL IO")
+ return fmt.Errorf("creating new NULL IO: %w", err)
}
} else {
if p.io, err = runc.NewPipeIO(p.IoUID, p.IoGID, withConditionalIO(p.stdio)); err != nil {
- return errors.Wrap(err, "failed to create OCI runtime io pipes")
+ return fmt.Errorf("failed to create OCI runtime io pipes: %w", err)
}
}
pidFile := filepath.Join(p.Bundle, InitPidFile)
@@ -139,7 +139,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) (err error) {
if r.Stdin != "" {
sc, err := fifo.OpenFifo(context.Background(), r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0)
if err != nil {
- return errors.Wrapf(err, "failed to open stdin fifo %s", r.Stdin)
+ return fmt.Errorf("failed to open stdin fifo %s: %w", r.Stdin, err)
}
p.stdin = sc
p.closers = append(p.closers, sc)
@@ -150,58 +150,58 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) (err error) {
if socket != nil {
console, err := socket.ReceiveMaster()
if err != nil {
- return errors.Wrap(err, "failed to retrieve console master")
+ return fmt.Errorf("failed to retrieve console master: %w", err)
}
console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg, &copyWaitGroup)
if err != nil {
- return errors.Wrap(err, "failed to start console copy")
+ return fmt.Errorf("failed to start console copy: %w", err)
}
p.console = console
} else if !hasNoIO(r) {
if err := copyPipes(ctx, p.io, r.Stdin, r.Stdout, r.Stderr, &p.wg, &copyWaitGroup); err != nil {
- return errors.Wrap(err, "failed to start io pipe copy")
+ return fmt.Errorf("failed to start io pipe copy: %w", err)
}
}
copyWaitGroup.Wait()
pid, err := runc.ReadPidFile(pidFile)
if err != nil {
- return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
+ return fmt.Errorf("failed to retrieve OCI runtime container pid: %w", err)
}
p.pid = pid
return nil
}
-// Wait for the process to exit
+// Wait waits for the process to exit.
func (p *Init) Wait() {
<-p.waitBlock
}
-// ID of the process
+// ID returns the ID of the process.
func (p *Init) ID() string {
return p.id
}
-// Pid of the process
+// Pid returns the PID of the process.
func (p *Init) Pid() int {
return p.pid
}
-// ExitStatus of the process
+// ExitStatus returns the exit status of the process.
func (p *Init) ExitStatus() int {
p.mu.Lock()
defer p.mu.Unlock()
return p.status
}
-// ExitedAt at time when the process exited
+// ExitedAt returns the time when the process exited.
func (p *Init) ExitedAt() time.Time {
p.mu.Lock()
defer p.mu.Unlock()
return p.exited
}
-// Status of the process
+// Status returns the status of the process.
func (p *Init) Status(ctx context.Context) (string, error) {
p.mu.Lock()
defer p.mu.Unlock()
@@ -215,7 +215,7 @@ func (p *Init) Status(ctx context.Context) (string, error) {
return p.convertStatus(c.Status), nil
}
-// Start the init process
+// Start starts the init process.
func (p *Init) Start(ctx context.Context) error {
p.mu.Lock()
defer p.mu.Unlock()
@@ -250,7 +250,7 @@ func (p *Init) start(ctx context.Context) error {
return nil
}
-// SetExited of the init process with the next status
+// SetExited set the exit stauts of the init process.
func (p *Init) SetExited(status int) {
p.mu.Lock()
defer p.mu.Unlock()
@@ -265,7 +265,7 @@ func (p *Init) setExited(status int) {
close(p.waitBlock)
}
-// Delete the init process
+// Delete deletes the init process.
func (p *Init) Delete(ctx context.Context) error {
p.mu.Lock()
defer p.mu.Unlock()
@@ -298,13 +298,13 @@ func (p *Init) delete(ctx context.Context) error {
if err2 := mount.UnmountAll(p.Rootfs, 0); err2 != nil {
log.G(ctx).WithError(err2).Warn("failed to cleanup rootfs mount")
if err == nil {
- err = errors.Wrap(err2, "failed rootfs umount")
+ err = fmt.Errorf("failed rootfs umount: %w", err2)
}
}
return err
}
-// Resize the init processes console
+// Resize resizes the init processes console.
func (p *Init) Resize(ws console.WinSize) error {
p.mu.Lock()
defer p.mu.Unlock()
@@ -322,7 +322,7 @@ func (p *Init) resize(ws console.WinSize) error {
return p.console.Resize(ws)
}
-// Kill the init process
+// Kill kills the init process.
func (p *Init) Kill(ctx context.Context, signal uint32, all bool) error {
p.mu.Lock()
defer p.mu.Unlock()
@@ -340,7 +340,7 @@ func (p *Init) kill(context context.Context, signal uint32, all bool) error {
c, err := p.runtime.State(context, p.id)
if err != nil {
if strings.Contains(err.Error(), "does not exist") {
- return errors.Wrapf(errdefs.ErrNotFound, "no such process")
+ return fmt.Errorf("no such process: %w", errdefs.ErrNotFound)
}
return p.runtimeError(err, "OCI runtime state failed")
}
@@ -348,7 +348,7 @@ func (p *Init) kill(context context.Context, signal uint32, all bool) error {
// If the container is not in running state, directly return
// "no such process"
if p.convertStatus(c.Status) == "stopped" {
- return errors.Wrapf(errdefs.ErrNotFound, "no such process")
+ return fmt.Errorf("no such process: %w", errdefs.ErrNotFound)
}
killErr = p.runtime.Kill(context, p.id, int(signal), &runsc.KillOpts{
All: all,
@@ -362,7 +362,7 @@ func (p *Init) kill(context context.Context, signal uint32, all bool) error {
return p.runtimeError(killErr, "kill timeout")
}
-// KillAll processes belonging to the init process
+// KillAll kills all processes belonging to the init process.
func (p *Init) KillAll(context context.Context) error {
p.mu.Lock()
defer p.mu.Unlock()
@@ -380,17 +380,17 @@ func (p *Init) killAll(context context.Context) error {
return nil
}
-// Stdin of the process
+// Stdin returns the stdin of the process.
func (p *Init) Stdin() io.Closer {
return p.stdin
}
-// Runtime returns the OCI runtime configured for the init process
+// Runtime returns the OCI runtime configured for the init process.
func (p *Init) Runtime() *runsc.Runsc {
return p.runtime
}
-// Exec returns a new child process
+// Exec returns a new child process.
func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
p.mu.Lock()
defer p.mu.Unlock()
@@ -398,7 +398,7 @@ func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Proce
return p.initState.Exec(ctx, path, r)
}
-// exec returns a new exec'd process
+// exec returns a new exec'd process.
func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
// process exec request
var spec specs.Process
@@ -424,7 +424,7 @@ func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Proce
return e, nil
}
-// Stdio of the process
+// Stdio returns the stdio of the process.
func (p *Init) Stdio() proc.Stdio {
return p.stdio
}
@@ -437,11 +437,11 @@ func (p *Init) runtimeError(rErr error, msg string) error {
rMsg, err := getLastRuntimeError(p.runtime)
switch {
case err != nil:
- return errors.Wrapf(rErr, "%s: %s (%s)", msg, "unable to retrieve OCI runtime error", err.Error())
+ return fmt.Errorf("%s: %w (unable to retrieve OCI runtime error: %v)", msg, rErr, err)
case rMsg == "":
- return errors.Wrap(rErr, msg)
+ return fmt.Errorf("%s: %w", msg, rErr)
default:
- return errors.Errorf("%s: %s", msg, rMsg)
+ return fmt.Errorf("%s: %s", msg, rMsg)
}
}
diff --git a/pkg/shim/v1/proc/init_state.go b/pkg/shim/v1/proc/init_state.go
index 868646b6c..509f27762 100644
--- a/pkg/shim/v1/proc/init_state.go
+++ b/pkg/shim/v1/proc/init_state.go
@@ -17,11 +17,11 @@ package proc
import (
"context"
+ "fmt"
"github.com/containerd/console"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/runtime/proc"
- "github.com/pkg/errors"
)
type initState interface {
@@ -46,7 +46,7 @@ func (s *createdState) transition(name string) error {
case "deleted":
s.p.initState = &deletedState{}
default:
- return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
+ return fmt.Errorf("invalid state transition %q to %q", stateName(s), name)
}
return nil
}
@@ -107,7 +107,7 @@ func (s *runningState) transition(name string) error {
case "stopped":
s.p.initState = &stoppedState{p: s.p}
default:
- return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
+ return fmt.Errorf("invalid state transition %q to %q", stateName(s), name)
}
return nil
}
@@ -117,11 +117,11 @@ func (s *runningState) Resize(ws console.WinSize) error {
}
func (s *runningState) Start(ctx context.Context) error {
- return errors.Errorf("cannot start a running process")
+ return fmt.Errorf("cannot start a running process")
}
func (s *runningState) Delete(ctx context.Context) error {
- return errors.Errorf("cannot delete a running process")
+ return fmt.Errorf("cannot delete a running process")
}
func (s *runningState) Kill(ctx context.Context, sig uint32, all bool) error {
@@ -149,17 +149,17 @@ func (s *stoppedState) transition(name string) error {
case "deleted":
s.p.initState = &deletedState{}
default:
- return errors.Errorf("invalid state transition %q to %q", stateName(s), name)
+ return fmt.Errorf("invalid state transition %q to %q", stateName(s), name)
}
return nil
}
func (s *stoppedState) Resize(ws console.WinSize) error {
- return errors.Errorf("cannot resize a stopped container")
+ return fmt.Errorf("cannot resize a stopped container")
}
func (s *stoppedState) Start(ctx context.Context) error {
- return errors.Errorf("cannot start a stopped process")
+ return fmt.Errorf("cannot start a stopped process")
}
func (s *stoppedState) Delete(ctx context.Context) error {
@@ -178,5 +178,5 @@ func (s *stoppedState) SetExited(status int) {
}
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
- return nil, errors.Errorf("cannot exec in a stopped state")
+ return nil, fmt.Errorf("cannot exec in a stopped state")
}
diff --git a/pkg/shim/v1/proc/io.go b/pkg/shim/v1/proc/io.go
index 2677b4e54..5313c7a50 100644
--- a/pkg/shim/v1/proc/io.go
+++ b/pkg/shim/v1/proc/io.go
@@ -150,8 +150,9 @@ func (c *countingWriteCloser) Close() error {
return c.WriteCloser.Close()
}
-// isFifo checks if a file is a fifo
-// if the file does not exist then it returns false
+// isFifo checks if a file is a 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 {
diff --git a/pkg/shim/v1/proc/process.go b/pkg/shim/v1/proc/process.go
index 1bfa99f4c..d462c3eef 100644
--- a/pkg/shim/v1/proc/process.go
+++ b/pkg/shim/v1/proc/process.go
@@ -16,10 +16,10 @@
package proc
import (
- "github.com/pkg/errors"
+ "fmt"
)
-// RunscRoot is the path to the root runsc state directory
+// RunscRoot is the path to the root runsc state directory.
const RunscRoot = "/run/containerd/runsc"
func stateName(v interface{}) string {
@@ -33,5 +33,5 @@ func stateName(v interface{}) string {
case *stoppedState:
return "stopped"
}
- panic(errors.Errorf("invalid state %v", v))
+ panic(fmt.Errorf("invalid state %v", v))
}
diff --git a/pkg/shim/v1/proc/types.go b/pkg/shim/v1/proc/types.go
index dcd43bcca..5c215de5f 100644
--- a/pkg/shim/v1/proc/types.go
+++ b/pkg/shim/v1/proc/types.go
@@ -23,7 +23,7 @@ import (
runc "github.com/containerd/go-runc"
)
-// Mount holds filesystem mount configuration
+// Mount holds filesystem mount configuration.
type Mount struct {
Type string
Source string
@@ -31,7 +31,7 @@ type Mount struct {
Options []string
}
-// CreateConfig hold task creation configuration
+// CreateConfig hold task creation configuration.
type CreateConfig struct {
ID string
Bundle string
@@ -44,7 +44,7 @@ type CreateConfig struct {
Options *google_protobuf.Any
}
-// ExecConfig holds exec creation configuration
+// ExecConfig holds exec creation configuration.
type ExecConfig struct {
ID string
Terminal bool
@@ -54,14 +54,14 @@ type ExecConfig struct {
Spec *google_protobuf.Any
}
-// Exit is the type of exit events
+// Exit is the type of exit events.
type Exit struct {
Timestamp time.Time
ID string
Status int
}
-// ProcessMonitor monitors process exit changes
+// ProcessMonitor monitors process exit changes.
type ProcessMonitor interface {
// Subscribe to process exit changes
Subscribe() chan runc.Exit
diff --git a/pkg/shim/v1/proc/utils.go b/pkg/shim/v1/proc/utils.go
index 6e7dbdad7..716de2f59 100644
--- a/pkg/shim/v1/proc/utils.go
+++ b/pkg/shim/v1/proc/utils.go
@@ -34,8 +34,6 @@ const (
// inside the sandbox.
var ExitCh = make(chan Exit, bufferSize)
-// TODO(random-liu): This can be a utility.
-
// TODO(mlaventure): move to runc package?
func getLastRuntimeError(r *runsc.Runsc) (string, error) {
if r.Log == "" {
diff --git a/pkg/shim/v1/shim/BUILD b/pkg/shim/v1/shim/BUILD
new file mode 100644
index 000000000..02cffbb01
--- /dev/null
+++ b/pkg/shim/v1/shim/BUILD
@@ -0,0 +1,38 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "shim",
+ srcs = [
+ "platform.go",
+ "service.go",
+ ],
+ visibility = [
+ "//pkg/shim:__subpackages__",
+ "//shim:__subpackages__",
+ ],
+ deps = [
+ "//pkg/shim/runsc",
+ "//pkg/shim/v1/proc",
+ "//pkg/shim/v1/utils",
+ "@com_github_containerd_console//:go_default_library",
+ "@com_github_containerd_containerd//api/events:go_default_library",
+ "@com_github_containerd_containerd//api/types/task:go_default_library",
+ "@com_github_containerd_containerd//errdefs:go_default_library",
+ "@com_github_containerd_containerd//events:go_default_library",
+ "@com_github_containerd_containerd//log:go_default_library",
+ "@com_github_containerd_containerd//mount:go_default_library",
+ "@com_github_containerd_containerd//namespaces:go_default_library",
+ "@com_github_containerd_containerd//runtime:go_default_library",
+ "@com_github_containerd_containerd//runtime/linux/runctypes:go_default_library",
+ "@com_github_containerd_containerd//runtime/proc:go_default_library",
+ "@com_github_containerd_containerd//runtime/v1/shim:go_default_library",
+ "@com_github_containerd_containerd//runtime/v1/shim/v1:go_default_library",
+ "@com_github_containerd_fifo//:go_default_library",
+ "@com_github_containerd_typeurl//:go_default_library",
+ "@com_github_gogo_protobuf//types:go_default_library",
+ "@org_golang_google_grpc//codes:go_default_library",
+ "@org_golang_google_grpc//status:go_default_library",
+ ],
+)
diff --git a/pkg/shim/v1/shim/platform.go b/pkg/shim/v1/shim/platform.go
index 86252c3f5..f6795563c 100644
--- a/pkg/shim/v1/shim/platform.go
+++ b/pkg/shim/v1/shim/platform.go
@@ -17,13 +17,13 @@ package shim
import (
"context"
+ "fmt"
"io"
"sync"
"syscall"
"github.com/containerd/console"
"github.com/containerd/fifo"
- "github.com/pkg/errors"
)
type linuxPlatform struct {
@@ -32,7 +32,7 @@ type linuxPlatform struct {
func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) (console.Console, error) {
if p.epoller == nil {
- return nil, errors.New("uninitialized epoller")
+ return nil, fmt.Errorf("uninitialized epoller")
}
epollConsole, err := p.epoller.Add(console)
@@ -79,11 +79,11 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
func (p *linuxPlatform) ShutdownConsole(ctx context.Context, cons console.Console) error {
if p.epoller == nil {
- return errors.New("uninitialized epoller")
+ return fmt.Errorf("uninitialized epoller")
}
epollConsole, ok := cons.(*console.EpollConsole)
if !ok {
- return errors.Errorf("expected EpollConsole, got %#v", cons)
+ return fmt.Errorf("expected EpollConsole, got %#v", cons)
}
return epollConsole.Shutdown(p.epoller.CloseConsole)
}
@@ -100,7 +100,7 @@ func (s *Service) initPlatform() error {
}
epoller, err := console.NewEpoller()
if err != nil {
- return errors.Wrap(err, "failed to initialize epoller")
+ return fmt.Errorf("failed to initialize epoller: %w", err)
}
s.platform = &linuxPlatform{
epoller: epoller,
diff --git a/pkg/shim/v1/shim/service.go b/pkg/shim/v1/shim/service.go
index aac172801..7b0280ed2 100644
--- a/pkg/shim/v1/shim/service.go
+++ b/pkg/shim/v1/shim/service.go
@@ -37,8 +37,6 @@ import (
shimapi "github.com/containerd/containerd/runtime/v1/shim/v1"
"github.com/containerd/typeurl"
ptypes "github.com/gogo/protobuf/types"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -57,7 +55,7 @@ var (
}
)
-// Config contains shim specific configuration
+// Config contains shim specific configuration.
type Config struct {
Path string
Namespace string
@@ -66,17 +64,12 @@ type Config struct {
RunscConfig map[string]string
}
-// NewService returns a new shim service that can be used via GRPC
+// NewService returns a new shim service that can be used via GRPC.
func NewService(config Config, publisher events.Publisher) (*Service, error) {
if config.Namespace == "" {
return nil, fmt.Errorf("shim namespace cannot be empty")
}
ctx := namespaces.WithNamespace(context.Background(), config.Namespace)
- ctx = log.WithLogger(ctx, logrus.WithFields(logrus.Fields{
- "namespace": config.Namespace,
- "path": config.Path,
- "pid": os.Getpid(),
- }))
s := &Service{
config: config,
context: ctx,
@@ -86,13 +79,13 @@ func NewService(config Config, publisher events.Publisher) (*Service, error) {
}
go s.processExits()
if err := s.initPlatform(); err != nil {
- return nil, errors.Wrap(err, "failed to initialized platform behavior")
+ return nil, fmt.Errorf("failed to initialized platform behavior: %w", err)
}
go s.forward(publisher)
return s, nil
}
-// Service is the shim implementation of a remote shim over GRPC
+// Service is the shim implementation of a remote shim over GRPC.
type Service struct {
mu sync.Mutex
@@ -108,7 +101,7 @@ type Service struct {
bundle string
}
-// Create a new initial process and container with the underlying OCI runtime
+// Create creates a new initial process and container with the underlying OCI runtime.
func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *shimapi.CreateTaskResponse, err error) {
s.mu.Lock()
defer s.mu.Unlock()
@@ -153,7 +146,7 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *
Options: rm.Options,
}
if err := m.Mount(rootfs); err != nil {
- return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
+ return nil, fmt.Errorf("failed to mount rootfs component %v: %w", m, err)
}
}
process, err := newInit(
@@ -169,7 +162,8 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *
if err := process.Create(ctx, config); err != nil {
return nil, errdefs.ToGRPC(err)
}
- // save the main task id and bundle to the shim for additional requests
+ // Save the main task id and bundle to the shim for additional
+ // requests.
s.id = r.ID
s.bundle = r.Bundle
pid := process.Pid()
@@ -179,7 +173,7 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *
}, nil
}
-// Start a process
+// Start starts a process.
func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*shimapi.StartResponse, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
@@ -194,7 +188,7 @@ func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*shimapi.
}, nil
}
-// Delete the initial process and container
+// Delete deletes the initial process and container.
func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteResponse, error) {
p, err := s.getInitProcess()
if err != nil {
@@ -214,7 +208,7 @@ func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteR
}, nil
}
-// DeleteProcess deletes an exec'd process
+// DeleteProcess deletes an exec'd process.
func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessRequest) (*shimapi.DeleteResponse, error) {
if r.ID == s.id {
return nil, status.Errorf(codes.InvalidArgument, "cannot delete init process with DeleteProcess")
@@ -236,7 +230,7 @@ func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessReq
}, nil
}
-// Exec an additional process inside the container
+// Exec spawns an additional process inside the container.
func (s *Service) Exec(ctx context.Context, r *shimapi.ExecProcessRequest) (*ptypes.Empty, error) {
s.mu.Lock()
@@ -268,7 +262,7 @@ func (s *Service) Exec(ctx context.Context, r *shimapi.ExecProcessRequest) (*pty
return empty, nil
}
-// ResizePty of a process
+// ResizePty resises the terminal of a process.
func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*ptypes.Empty, error) {
if r.ID == "" {
return nil, errdefs.ToGRPCf(errdefs.ErrInvalidArgument, "id not provided")
@@ -287,7 +281,7 @@ func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*
return empty, nil
}
-// State returns runtime state information for a process
+// State returns runtime state information for a process.
func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.StateResponse, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
@@ -321,17 +315,17 @@ func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.
}, nil
}
-// Pause the container
+// Pause pauses the container.
func (s *Service) Pause(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Resume the container
+// Resume resumes the container.
func (s *Service) Resume(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Kill a process with the provided signal
+// Kill kills a process with the provided signal.
func (s *Service) Kill(ctx context.Context, r *shimapi.KillRequest) (*ptypes.Empty, error) {
if r.ID == "" {
p, err := s.getInitProcess()
@@ -354,7 +348,7 @@ func (s *Service) Kill(ctx context.Context, r *shimapi.KillRequest) (*ptypes.Emp
return empty, nil
}
-// ListPids returns all pids inside the container
+// ListPids returns all pids inside the container.
func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*shimapi.ListPidsResponse, error) {
pids, err := s.getContainerPids(ctx, r.ID)
if err != nil {
@@ -372,7 +366,7 @@ func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*sh
}
a, err := typeurl.MarshalAny(d)
if err != nil {
- return nil, errors.Wrapf(err, "failed to marshal process %d info", pid)
+ return nil, fmt.Errorf("failed to marshal process %d info: %w", pid, err)
}
pInfo.Info = a
break
@@ -385,7 +379,7 @@ func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*sh
}, nil
}
-// CloseIO of a process
+// CloseIO closes the I/O context of a process.
func (s *Service) CloseIO(ctx context.Context, r *shimapi.CloseIORequest) (*ptypes.Empty, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
@@ -393,30 +387,30 @@ func (s *Service) CloseIO(ctx context.Context, r *shimapi.CloseIORequest) (*ptyp
}
if stdin := p.Stdin(); stdin != nil {
if err := stdin.Close(); err != nil {
- return nil, errors.Wrap(err, "close stdin")
+ return nil, fmt.Errorf("close stdin: %w", err)
}
}
return empty, nil
}
-// Checkpoint the container
+// Checkpoint checkpoints the container.
func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskRequest) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// ShimInfo returns shim information such as the shim's pid
+// ShimInfo returns shim information such as the shim's pid.
func (s *Service) ShimInfo(ctx context.Context, r *ptypes.Empty) (*shimapi.ShimInfoResponse, error) {
return &shimapi.ShimInfoResponse{
ShimPid: uint32(os.Getpid()),
}, nil
}
-// Update a running container
+// Update updates a running container.
func (s *Service) Update(ctx context.Context, r *shimapi.UpdateTaskRequest) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Wait for a process to exit
+// Wait waits for a process to exit.
func (s *Service) Wait(ctx context.Context, r *shimapi.WaitRequest) (*shimapi.WaitResponse, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
@@ -451,7 +445,7 @@ func (s *Service) checkProcesses(e proc.Exit) {
for _, p := range s.allProcesses() {
if p.ID() == e.ID {
if ip, ok := p.(*proc.Init); ok {
- // Ensure all children are killed
+ // Ensure all children are killed.
if err := ip.KillAll(s.context); err != nil {
log.G(s.context).WithError(err).WithField("id", ip.ID()).
Error("failed to kill init's children")
@@ -495,7 +489,7 @@ func (s *Service) forward(publisher events.Publisher) {
}
}
-// getInitProcess returns initial process
+// getInitProcess returns the init process.
func (s *Service) getInitProcess() (rproc.Process, error) {
s.mu.Lock()
defer s.mu.Unlock()
@@ -506,7 +500,7 @@ func (s *Service) getInitProcess() (rproc.Process, error) {
return p, nil
}
-// getExecProcess returns exec process
+// getExecProcess returns the given exec process.
func (s *Service) getExecProcess(id string) (rproc.Process, error) {
s.mu.Lock()
defer s.mu.Unlock()
@@ -534,7 +528,7 @@ func getTopic(ctx context.Context, e interface{}) string {
case *eventstypes.TaskExecStarted:
return runtime.TaskExecStartedEventTopic
default:
- logrus.Warnf("no topic for type %#v", e)
+ log.L.Printf("no topic for type %#v", e)
}
return runtime.TaskUnknownTopic
}
@@ -551,10 +545,10 @@ func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace string,
spec, err := utils.ReadSpec(r.Bundle)
if err != nil {
- return nil, errors.Wrap(err, "read oci spec")
+ return nil, fmt.Errorf("read oci spec: %w", err)
}
if err := utils.UpdateVolumeAnnotations(r.Bundle, spec); err != nil {
- return nil, errors.Wrap(err, "update volume annotations")
+ return nil, fmt.Errorf("update volume annotations: %w", err)
}
runsc.FormatLogPath(r.ID, config)
diff --git a/pkg/shim/v1/utils/BUILD b/pkg/shim/v1/utils/BUILD
new file mode 100644
index 000000000..9045781e1
--- /dev/null
+++ b/pkg/shim/v1/utils/BUILD
@@ -0,0 +1,26 @@
+load("//tools:defs.bzl", "go_library", "go_test")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "utils",
+ srcs = [
+ "utils.go",
+ "volumes.go",
+ ],
+ visibility = [
+ "//pkg/shim:__subpackages__",
+ "//shim:__subpackages__",
+ ],
+ deps = [
+ "@com_github_containerd_cri//pkg/annotations:go_default_library",
+ "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ ],
+)
+
+go_test(
+ name = "utils_test",
+ size = "small",
+ srcs = ["volumes_test.go"],
+ library = ":utils",
+)
diff --git a/pkg/shim/v1/utils/volumes.go b/pkg/shim/v1/utils/volumes.go
index 7323e7245..e4e9bf9b1 100644
--- a/pkg/shim/v1/utils/volumes.go
+++ b/pkg/shim/v1/utils/volumes.go
@@ -23,8 +23,6 @@ import (
"github.com/containerd/cri/pkg/annotations"
specs "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
const volumeKeyPrefix = "dev.gvisor.spec.mount."
@@ -32,13 +30,13 @@ const volumeKeyPrefix = "dev.gvisor.spec.mount."
var kubeletPodsDir = "/var/lib/kubelet/pods"
// volumeName gets volume name from volume annotation key, example:
-// dev.gvisor.spec.mount.NAME.share
+// dev.gvisor.spec.mount.NAME.share
func volumeName(k string) string {
return strings.SplitN(strings.TrimPrefix(k, volumeKeyPrefix), ".", 2)[0]
}
// volumeFieldName gets volume field name from volume annotation key, example:
-// `type` is the field of dev.gvisor.spec.mount.NAME.type
+// `type` is the field of dev.gvisor.spec.mount.NAME.type
func volumeFieldName(k string) string {
parts := strings.Split(strings.TrimPrefix(k, volumeKeyPrefix), ".")
return parts[len(parts)-1]
@@ -48,16 +46,16 @@ func volumeFieldName(k string) string {
func podUID(s *specs.Spec) (string, error) {
sandboxLogDir := s.Annotations[annotations.SandboxLogDir]
if sandboxLogDir == "" {
- return "", errors.New("no sandbox log path annotation")
+ return "", fmt.Errorf("no sandbox log path annotation")
}
fields := strings.Split(filepath.Base(sandboxLogDir), "_")
switch len(fields) {
- case 1: // This is the old CRI logging path
+ case 1: // This is the old CRI logging path.
return fields[0], nil
- case 3: // This is the new CRI logging path
+ case 3: // This is the new CRI logging path.
return fields[2], nil
}
- return "", errors.Errorf("unexpected sandbox log path %q", sandboxLogDir)
+ return "", fmt.Errorf("unexpected sandbox log path %q", sandboxLogDir)
}
// isVolumeKey checks whether an annotation key is for volume.
@@ -79,7 +77,7 @@ func volumePath(volume, uid string) (string, error) {
return "", err
}
if len(dirs) != 1 {
- return "", errors.Errorf("unexpected matched volume list %v", dirs)
+ return "", fmt.Errorf("unexpected matched volume list %v", dirs)
}
return dirs[0], nil
}
@@ -103,7 +101,7 @@ func UpdateVolumeAnnotations(bundle string, s *specs.Spec) error {
if err != nil {
// Skip if we can't get pod UID, because this doesn't work
// for containerd 1.1.
- logrus.WithError(err).Error("Can't get pod uid")
+ fmt.Errorf("Can't get pod uid: %w", err)
return nil
}
}
@@ -117,22 +115,25 @@ func UpdateVolumeAnnotations(bundle string, s *specs.Spec) error {
}
volume := volumeName(k)
if uid != "" {
- // This is a sandbox
+ // This is a sandbox.
path, err := volumePath(volume, uid)
if err != nil {
- return errors.Wrapf(err, "get volume path for %q", volume)
+ return fmt.Errorf("get volume path for %q: %w", volume, err)
}
s.Annotations[volumeSourceKey(volume)] = path
updated = true
} else {
- // This is a container
+ // This is a container.
for i := range s.Mounts {
- // An error is returned for sandbox if source annotation
- // is not successfully applied, so it is guaranteed that
- // the source annotation for sandbox has already been
- // successfully applied at this point.
- // The volume name is unique inside a pod, so matching without
- // podUID is fine here.
+ // An error is returned for sandbox if source
+ // annotation is not successfully applied, so
+ // it is guaranteed that the source annotation
+ // for sandbox has already been successfully
+ // applied at this point.
+ //
+ // The volume name is unique inside a pod, so
+ // matching without podUID is fine here.
+ //
// TODO: Pass podUID down to shim for containers to do
// more accurate matching.
if yes, _ := isVolumePath(volume, s.Mounts[i].Source); yes {
@@ -147,7 +148,7 @@ func UpdateVolumeAnnotations(bundle string, s *specs.Spec) error {
if !updated {
return nil
}
- // Update bundle
+ // Update bundle.
b, err := json.Marshal(s)
if err != nil {
return err
diff --git a/pkg/shim/v2/BUILD b/pkg/shim/v2/BUILD
new file mode 100644
index 000000000..450f62979
--- /dev/null
+++ b/pkg/shim/v2/BUILD
@@ -0,0 +1,41 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "v2",
+ srcs = [
+ "epoll.go",
+ "service.go",
+ "service_linux.go",
+ ],
+ visibility = ["//shim:__subpackages__"],
+ deps = [
+ "//pkg/shim/runsc",
+ "//pkg/shim/v1/proc",
+ "//pkg/shim/v1/utils",
+ "//pkg/shim/v2/options",
+ "//runsc/specutils",
+ "@com_github_burntsushi_toml//:go_default_library",
+ "@com_github_containerd_cgroups//:go_default_library",
+ "@com_github_containerd_cgroups//stats/v1:go_default_library",
+ "@com_github_containerd_console//:go_default_library",
+ "@com_github_containerd_containerd//api/events:go_default_library",
+ "@com_github_containerd_containerd//api/types/task:go_default_library",
+ "@com_github_containerd_containerd//errdefs:go_default_library",
+ "@com_github_containerd_containerd//events:go_default_library",
+ "@com_github_containerd_containerd//log:go_default_library",
+ "@com_github_containerd_containerd//mount:go_default_library",
+ "@com_github_containerd_containerd//namespaces:go_default_library",
+ "@com_github_containerd_containerd//runtime:go_default_library",
+ "@com_github_containerd_containerd//runtime/linux/runctypes:go_default_library",
+ "@com_github_containerd_containerd//runtime/proc:go_default_library",
+ "@com_github_containerd_containerd//runtime/v2/shim:go_default_library",
+ "@com_github_containerd_containerd//runtime/v2/task:go_default_library",
+ "@com_github_containerd_cri//pkg/api/runtimeoptions/v1:go_default_library",
+ "@com_github_containerd_fifo//:go_default_library",
+ "@com_github_containerd_typeurl//:go_default_library",
+ "@com_github_gogo_protobuf//types:go_default_library",
+ "@org_golang_x_sys//unix:go_default_library",
+ ],
+)
diff --git a/pkg/shim/v2/epoll.go b/pkg/shim/v2/epoll.go
index 57a2c5452..45cc38c2a 100644
--- a/pkg/shim/v2/epoll.go
+++ b/pkg/shim/v2/epoll.go
@@ -19,13 +19,13 @@ package v2
import (
"context"
+ "fmt"
"sync"
"github.com/containerd/cgroups"
eventstypes "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/runtime"
- "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@@ -71,7 +71,7 @@ func (e *epoller) run(ctx context.Context) {
if err == unix.EINTR {
continue
}
- logrus.WithError(err).Error("cgroups: epoll wait")
+ fmt.Errorf("cgroups: epoll wait: %w", err)
}
for i := 0; i < n; i++ {
e.process(ctx, uintptr(events[i].Fd))
@@ -117,7 +117,7 @@ func (e *epoller) process(ctx context.Context, fd uintptr) {
if err := e.publisher.Publish(ctx, runtime.TaskOOMEventTopic, &eventstypes.TaskOOM{
ContainerID: i.id,
}); err != nil {
- logrus.WithError(err).Error("publish OOM event")
+ fmt.Errorf("publish OOM event: %w", err)
}
}
diff --git a/pkg/shim/v2/options/BUILD b/pkg/shim/v2/options/BUILD
new file mode 100644
index 000000000..ca212e874
--- /dev/null
+++ b/pkg/shim/v2/options/BUILD
@@ -0,0 +1,11 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "options",
+ srcs = [
+ "options.go",
+ ],
+ visibility = ["//:sandbox"],
+)
diff --git a/pkg/shim/v2/service.go b/pkg/shim/v2/service.go
index 0cff82a89..c67b1beba 100644
--- a/pkg/shim/v2/service.go
+++ b/pkg/shim/v2/service.go
@@ -16,6 +16,7 @@ package v2
import (
"context"
+ "fmt"
"io/ioutil"
"os"
"os/exec"
@@ -26,6 +27,7 @@ import (
"github.com/BurntSushi/toml"
"github.com/containerd/cgroups"
+ metrics "github.com/containerd/cgroups/stats/v1"
"github.com/containerd/console"
eventstypes "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/api/types/task"
@@ -42,14 +44,13 @@ import (
runtimeoptions "github.com/containerd/cri/pkg/api/runtimeoptions/v1"
"github.com/containerd/typeurl"
ptypes "github.com/gogo/protobuf/types"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/shim/runsc"
"gvisor.dev/gvisor/pkg/shim/v1/proc"
"gvisor.dev/gvisor/pkg/shim/v1/utils"
"gvisor.dev/gvisor/pkg/shim/v2/options"
+ "gvisor.dev/gvisor/runsc/specutils"
)
var (
@@ -68,7 +69,7 @@ var _ = (taskAPI.TaskService)(&service{})
// we assume that a config.toml should exist in the runtime root.
const configFile = "config.toml"
-// New returns a new shim service that can be used via GRPC
+// New returns a new shim service that can be used via GRPC.
func New(ctx context.Context, id string, publisher events.Publisher) (shim.Shim, error) {
ep, err := newOOMEpoller(publisher)
if err != nil {
@@ -89,13 +90,13 @@ func New(ctx context.Context, id string, publisher events.Publisher) (shim.Shim,
runsc.Monitor = shim.Default
if err := s.initPlatform(); err != nil {
cancel()
- return nil, errors.Wrap(err, "failed to initialized platform behavior")
+ return nil, fmt.Errorf("failed to initialized platform behavior: %w", err)
}
go s.forward(publisher)
return s, nil
}
-// service is the shim implementation of a remote shim over GRPC
+// service is the shim implementation of a remote shim over GRPC.
type service struct {
mu sync.Mutex
@@ -179,7 +180,7 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
return "", err
}
if err := shim.SetScore(cmd.Process.Pid); err != nil {
- return "", errors.Wrap(err, "failed to set OOM Score on shim")
+ return "", fmt.Errorf("failed to set OOM Score on shim: %w", err)
}
return address, nil
}
@@ -201,10 +202,10 @@ func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error)
if err := r.Delete(ctx, s.id, &runsc.DeleteOpts{
Force: true,
}); err != nil {
- logrus.WithError(err).Warn("failed to remove runc container")
+ log.L.Printf("failed to remove runc container: %v", err)
}
if err := mount.UnmountAll(filepath.Join(path, "rootfs"), 0); err != nil {
- logrus.WithError(err).Warn("failed to cleanup rootfs mount")
+ log.L.Printf("failed to cleanup rootfs mount: %v", err)
}
return &taskAPI.DeleteResponse{
ExitedAt: time.Now(),
@@ -224,14 +225,15 @@ func (s *service) writeRuntime(path, runtime string) error {
return ioutil.WriteFile(filepath.Join(path, "runtime"), []byte(runtime), 0600)
}
-// Create a new initial process and container with the underlying OCI runtime
+// Create creates a new initial process and container with the underlying OCI
+// runtime.
func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *taskAPI.CreateTaskResponse, err error) {
s.mu.Lock()
defer s.mu.Unlock()
ns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
- return nil, errors.Wrap(err, "create namespace")
+ return nil, fmt.Errorf("create namespace: %w", err)
}
// Read from root for now.
@@ -258,7 +260,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
path = filepath.Join(root, configFile)
if _, err := os.Stat(path); err != nil {
if !os.IsNotExist(err) {
- return nil, errors.Wrapf(err, "stat config file %q", path)
+ return nil, fmt.Errorf("stat config file %q: %w", path, err)
}
// A config file in runtime root is not required.
path = ""
@@ -268,15 +270,15 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
break
}
if o.TypeUrl != options.OptionType {
- return nil, errors.Errorf("unsupported runtimeoptions %q", o.TypeUrl)
+ return nil, fmt.Errorf("unsupported runtimeoptions %q", o.TypeUrl)
}
path = o.ConfigPath
default:
- return nil, errors.Errorf("unsupported option type %q", r.Options.TypeUrl)
+ return nil, fmt.Errorf("unsupported option type %q", r.Options.TypeUrl)
}
if path != "" {
if _, err = toml.DecodeFile(path, &opts); err != nil {
- return nil, errors.Wrapf(err, "decode config file %q", path)
+ return nil, fmt.Errorf("decode config file %q: %w", path, err)
}
}
}
@@ -312,8 +314,8 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
}
defer func() {
if err != nil {
- if err2 := mount.UnmountAll(rootfs, 0); err2 != nil {
- logrus.WithError(err2).Warn("failed to cleanup rootfs mount")
+ if err := mount.UnmountAll(rootfs, 0); err != nil {
+ log.L.Printf("failed to cleanup rootfs mount: %v", err)
}
}
}()
@@ -324,7 +326,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
Options: rm.Options,
}
if err := m.Mount(rootfs); err != nil {
- return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
+ return nil, fmt.Errorf("failed to mount rootfs component %v: %w", m, err)
}
}
process, err := newInit(
@@ -343,20 +345,21 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
if err := process.Create(ctx, config); err != nil {
return nil, errdefs.ToGRPC(err)
}
- // save the main task id and bundle to the shim for additional requests
+ // Save the main task id and bundle to the shim for additional
+ // requests.
s.id = r.ID
s.bundle = r.Bundle
- // Set up OOM notification on the sandbox's cgroup. This is done on sandbox
- // create since the sandbox process will be created here.
+ // Set up OOM notification on the sandbox's cgroup. This is done on
+ // sandbox create since the sandbox process will be created here.
pid := process.Pid()
if pid > 0 {
cg, err := cgroups.Load(cgroups.V1, cgroups.PidPath(pid))
if err != nil {
- return nil, errors.Wrapf(err, "loading cgroup for %d", pid)
+ return nil, fmt.Errorf("loading cgroup for %d: %w", pid, err)
}
if err := s.oomPoller.add(s.id, cg); err != nil {
- return nil, errors.Wrapf(err, "add cg to OOM monitor")
+ return nil, fmt.Errorf("add cg to OOM monitor: %w", err)
}
}
s.task = process
@@ -367,7 +370,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
}
-// Start a process
+// Start starts a process.
func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.StartResponse, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -383,7 +386,7 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
}, nil
}
-// Delete the initial process and container
+// Delete deletes the initial process and container.
func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAPI.DeleteResponse, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -411,7 +414,7 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
}, nil
}
-// Exec an additional process inside the container
+// Exec spawns an additional process inside the container.
func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*ptypes.Empty, error) {
s.mu.Lock()
p := s.processes[r.ExecID]
@@ -440,7 +443,7 @@ func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*pty
return empty, nil
}
-// ResizePty of a process
+// ResizePty resizes the terminal of a process.
func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*ptypes.Empty, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -456,7 +459,7 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
return empty, nil
}
-// State returns runtime state information for a process
+// State returns runtime state information for a process.
func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.StateResponse, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -490,17 +493,17 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
}, nil
}
-// Pause the container
+// Pause the container.
func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Resume the container
+// Resume the container.
func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Kill a process with the provided signal
+// Kill a process with the provided signal.
func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Empty, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -515,7 +518,7 @@ func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Emp
return empty, nil
}
-// Pids returns all pids inside the container
+// Pids returns all pids inside the container.
func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.PidsResponse, error) {
pids, err := s.getContainerPids(ctx, r.ID)
if err != nil {
@@ -533,7 +536,7 @@ func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.Pi
}
a, err := typeurl.MarshalAny(d)
if err != nil {
- return nil, errors.Wrapf(err, "failed to marshal process %d info", pid)
+ return nil, fmt.Errorf("failed to marshal process %d info: %w", pid, err)
}
pInfo.Info = a
break
@@ -546,7 +549,7 @@ func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.Pi
}, nil
}
-// CloseIO of a process
+// CloseIO closes the I/O context of a process.
func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptypes.Empty, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -554,18 +557,18 @@ func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptyp
}
if stdin := p.Stdin(); stdin != nil {
if err := stdin.Close(); err != nil {
- return nil, errors.Wrap(err, "close stdin")
+ return nil, fmt.Errorf("close stdin: %w", err)
}
}
return empty, nil
}
-// Checkpoint the container
+// Checkpoint checkpoints the container.
func (s *service) Checkpoint(ctx context.Context, r *taskAPI.CheckpointTaskRequest) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Connect returns shim information such as the shim's pid
+// Connect returns shim information such as the shim's pid.
func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*taskAPI.ConnectResponse, error) {
var pid int
if s.task != nil {
@@ -605,52 +608,52 @@ func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.
// gvisor currently (as of 2020-03-03) only returns the total memory
// usage and current PID value[0]. However, we copy the common fields here
// so that future updates will propagate correct information. We're
- // using the cgroups.Metrics structure so we're returning the same type
+ // using the metrics.Metrics structure so we're returning the same type
// as runc.
//
// [0]: https://github.com/google/gvisor/blob/277a0d5a1fbe8272d4729c01ee4c6e374d047ebc/runsc/boot/events.go#L61-L81
- data, err := typeurl.MarshalAny(&cgroups.Metrics{
- CPU: &cgroups.CPUStat{
- Usage: &cgroups.CPUUsage{
+ data, err := typeurl.MarshalAny(&metrics.Metrics{
+ CPU: &metrics.CPUStat{
+ Usage: &metrics.CPUUsage{
Total: stats.Cpu.Usage.Total,
Kernel: stats.Cpu.Usage.Kernel,
User: stats.Cpu.Usage.User,
PerCPU: stats.Cpu.Usage.Percpu,
},
- Throttling: &cgroups.Throttle{
+ Throttling: &metrics.Throttle{
Periods: stats.Cpu.Throttling.Periods,
ThrottledPeriods: stats.Cpu.Throttling.ThrottledPeriods,
ThrottledTime: stats.Cpu.Throttling.ThrottledTime,
},
},
- Memory: &cgroups.MemoryStat{
+ Memory: &metrics.MemoryStat{
Cache: stats.Memory.Cache,
- Usage: &cgroups.MemoryEntry{
+ Usage: &metrics.MemoryEntry{
Limit: stats.Memory.Usage.Limit,
Usage: stats.Memory.Usage.Usage,
Max: stats.Memory.Usage.Max,
Failcnt: stats.Memory.Usage.Failcnt,
},
- Swap: &cgroups.MemoryEntry{
+ Swap: &metrics.MemoryEntry{
Limit: stats.Memory.Swap.Limit,
Usage: stats.Memory.Swap.Usage,
Max: stats.Memory.Swap.Max,
Failcnt: stats.Memory.Swap.Failcnt,
},
- Kernel: &cgroups.MemoryEntry{
+ Kernel: &metrics.MemoryEntry{
Limit: stats.Memory.Kernel.Limit,
Usage: stats.Memory.Kernel.Usage,
Max: stats.Memory.Kernel.Max,
Failcnt: stats.Memory.Kernel.Failcnt,
},
- KernelTCP: &cgroups.MemoryEntry{
+ KernelTCP: &metrics.MemoryEntry{
Limit: stats.Memory.KernelTCP.Limit,
Usage: stats.Memory.KernelTCP.Usage,
Max: stats.Memory.KernelTCP.Max,
Failcnt: stats.Memory.KernelTCP.Failcnt,
},
},
- Pids: &cgroups.PidsStat{
+ Pids: &metrics.PidsStat{
Current: stats.Pids.Current,
Limit: stats.Pids.Limit,
},
@@ -663,12 +666,12 @@ func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.
}, nil
}
-// Update a running container
+// Update updates a running container.
func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*ptypes.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
-// Wait for a process to exit
+// Wait waits for a process to exit.
func (s *service) Wait(ctx context.Context, r *taskAPI.WaitRequest) (*taskAPI.WaitResponse, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
@@ -697,7 +700,7 @@ func (s *service) checkProcesses(e proc.Exit) {
for _, p := range s.allProcesses() {
if p.ID() == e.ID {
if ip, ok := p.(*proc.Init); ok {
- // Ensure all children are killed
+ // Ensure all children are killed.
if err := ip.KillAll(s.context); err != nil {
log.G(s.context).WithError(err).WithField("id", ip.ID()).
Error("failed to kill init's children")
@@ -733,7 +736,7 @@ func (s *service) getContainerPids(ctx context.Context, id string) ([]uint32, er
p := s.task
s.mu.Unlock()
if p == nil {
- return nil, errors.Wrapf(errdefs.ErrFailedPrecondition, "container must be created")
+ return nil, fmt.Errorf("container must be created: %w", errdefs.ErrFailedPrecondition)
}
ps, err := p.(*proc.Init).Runtime().Ps(ctx, id)
if err != nil {
@@ -752,7 +755,7 @@ func (s *service) forward(publisher events.Publisher) {
err := publisher.Publish(ctx, getTopic(e), e)
cancel()
if err != nil {
- logrus.WithError(err).Error("post event")
+ fmt.Errorf("post event: %w", err)
}
}
}
@@ -787,7 +790,7 @@ func getTopic(e interface{}) string {
case *eventstypes.TaskExecStarted:
return runtime.TaskExecStartedEventTopic
default:
- logrus.Warnf("no topic for type %#v", e)
+ log.L.Printf("no topic for type %#v", e)
}
return runtime.TaskUnknownTopic
}
@@ -795,10 +798,10 @@ func getTopic(e interface{}) string {
func newInit(ctx context.Context, path, workDir, namespace string, platform rproc.Platform, r *proc.CreateConfig, options *options.Options, rootfs string) (*proc.Init, error) {
spec, err := utils.ReadSpec(r.Bundle)
if err != nil {
- return nil, errors.Wrap(err, "read oci spec")
+ return nil, fmt.Errorf("read oci spec: %w", err)
}
if err := utils.UpdateVolumeAnnotations(r.Bundle, spec); err != nil {
- return nil, errors.Wrap(err, "update volume annotations")
+ return nil, fmt.Errorf("update volume annotations: %w", err)
}
runsc.FormatLogPath(r.ID, options.RunscConfig)
runtime := proc.NewRunsc(options.Root, path, namespace, options.BinaryName, options.RunscConfig)
@@ -814,7 +817,7 @@ func newInit(ctx context.Context, path, workDir, namespace string, platform rpro
p.WorkDir = workDir
p.IoUID = int(options.IoUid)
p.IoGID = int(options.IoGid)
- p.Sandbox = utils.IsSandbox(spec)
+ p.Sandbox = specutils.SpecContainerType(spec) == specutils.ContainerTypeSandbox
p.UserLog = utils.UserLogPath(spec)
p.Monitor = shim.Default
return p, nil
diff --git a/pkg/shim/v2/service_linux.go b/pkg/shim/v2/service_linux.go
index cd259cd44..257c58812 100644
--- a/pkg/shim/v2/service_linux.go
+++ b/pkg/shim/v2/service_linux.go
@@ -19,13 +19,13 @@ package v2
import (
"context"
+ "fmt"
"io"
"sync"
"syscall"
"github.com/containerd/console"
"github.com/containerd/fifo"
- "github.com/pkg/errors"
)
type linuxPlatform struct {
@@ -34,7 +34,7 @@ type linuxPlatform struct {
func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) (console.Console, error) {
if p.epoller == nil {
- return nil, errors.New("uninitialized epoller")
+ return nil, fmt.Errorf("uninitialized epoller")
}
epollConsole, err := p.epoller.Add(console)
@@ -81,11 +81,11 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
func (p *linuxPlatform) ShutdownConsole(ctx context.Context, cons console.Console) error {
if p.epoller == nil {
- return errors.New("uninitialized epoller")
+ return fmt.Errorf("uninitialized epoller")
}
epollConsole, ok := cons.(*console.EpollConsole)
if !ok {
- return errors.Errorf("expected EpollConsole, got %#v", cons)
+ return fmt.Errorf("expected EpollConsole, got %#v", cons)
}
return epollConsole.Shutdown(p.epoller.CloseConsole)
}
@@ -102,7 +102,7 @@ func (s *service) initPlatform() error {
}
epoller, err := console.NewEpoller()
if err != nil {
- return errors.Wrap(err, "failed to initialize epoller")
+ return fmt.Errorf("failed to initialize epoller: %w", err)
}
s.platform = &linuxPlatform{
epoller: epoller,
diff --git a/pkg/test/criutil/criutil.go b/pkg/test/criutil/criutil.go
index 8fed29ff5..4c63d669a 100644
--- a/pkg/test/criutil/criutil.go
+++ b/pkg/test/criutil/criutil.go
@@ -22,6 +22,9 @@ import (
"fmt"
"os"
"os/exec"
+ "path"
+ "regexp"
+ "strconv"
"strings"
"time"
@@ -33,28 +36,44 @@ import (
type Crictl struct {
logger testutil.Logger
endpoint string
+ runpArgs []string
cleanup []func()
}
// resolvePath attempts to find binary paths. It may set the path to invalid,
// which will cause the execution to fail with a sensible error.
func resolvePath(executable string) string {
+ runtime, err := dockerutil.RuntimePath()
+ if err == nil {
+ // Check first the directory of the runtime itself.
+ if dir := path.Dir(runtime); dir != "" && dir != "." {
+ guess := path.Join(dir, executable)
+ if fi, err := os.Stat(guess); err == nil && (fi.Mode()&0111) != 0 {
+ return guess
+ }
+ }
+ }
+
+ // Try to find via the path.
guess, err := exec.LookPath(executable)
- if err != nil {
- guess = fmt.Sprintf("/usr/local/bin/%s", executable)
+ if err == nil {
+ return guess
}
- return guess
+
+ // Return a default path.
+ return fmt.Sprintf("/usr/local/bin/%s", executable)
}
// NewCrictl returns a Crictl configured with a timeout and an endpoint over
// which it will talk to containerd.
-func NewCrictl(logger testutil.Logger, endpoint string) *Crictl {
+func NewCrictl(logger testutil.Logger, endpoint string, runpArgs []string) *Crictl {
// Attempt to find the executable, but don't bother propagating the
// error at this point. The first command executed will return with a
// binary not found error.
return &Crictl{
logger: logger,
endpoint: endpoint,
+ runpArgs: runpArgs,
}
}
@@ -67,8 +86,8 @@ func (cc *Crictl) CleanUp() {
}
// RunPod creates a sandbox. It corresponds to `crictl runp`.
-func (cc *Crictl) RunPod(sbSpecFile string) (string, error) {
- podID, err := cc.run("runp", sbSpecFile)
+func (cc *Crictl) RunPod(runtime, sbSpecFile string) (string, error) {
+ podID, err := cc.run("runp", "--runtime", runtime, sbSpecFile)
if err != nil {
return "", fmt.Errorf("runp failed: %v", err)
}
@@ -79,10 +98,39 @@ func (cc *Crictl) RunPod(sbSpecFile string) (string, error) {
// Create creates a container within a sandbox. It corresponds to `crictl
// create`.
func (cc *Crictl) Create(podID, contSpecFile, sbSpecFile string) (string, error) {
- podID, err := cc.run("create", podID, contSpecFile, sbSpecFile)
+ // In version 1.16.0, crictl annoying starting attempting to pull the
+ // container, even if it was already available locally. We therefore
+ // need to parse the version and add an appropriate --no-pull argument
+ // since the image has already been loaded locally.
+ out, err := cc.run("-v")
+ r := regexp.MustCompile("crictl version ([0-9]+)\\.([0-9]+)\\.([0-9+])")
+ vs := r.FindStringSubmatch(out)
+ if len(vs) != 4 {
+ return "", fmt.Errorf("crictl -v had unexpected output: %s", out)
+ }
+ major, err := strconv.ParseUint(vs[1], 10, 64)
+ if err != nil {
+ return "", fmt.Errorf("crictl had invalid version: %v (%s)", err, out)
+ }
+ minor, err := strconv.ParseUint(vs[2], 10, 64)
if err != nil {
+ return "", fmt.Errorf("crictl had invalid version: %v (%s)", err, out)
+ }
+
+ args := []string{"create"}
+ if (major == 1 && minor >= 16) || major > 1 {
+ args = append(args, "--no-pull")
+ }
+ args = append(args, podID)
+ args = append(args, contSpecFile)
+ args = append(args, sbSpecFile)
+
+ podID, err = cc.run(args...)
+ if err != nil {
+ time.Sleep(10 * time.Minute) // XXX
return "", fmt.Errorf("create failed: %v", err)
}
+
// Strip the trailing newline from crictl output.
return strings.TrimSpace(podID), nil
}
@@ -260,7 +308,7 @@ func (cc *Crictl) StopContainer(contID string) error {
// StartPodAndContainer starts a sandbox and container in that sandbox. It
// returns the pod ID and container ID.
-func (cc *Crictl) StartPodAndContainer(image, sbSpec, contSpec string) (string, string, error) {
+func (cc *Crictl) StartPodAndContainer(runtime, image, sbSpec, contSpec string) (string, string, error) {
if err := cc.Import(image); err != nil {
return "", "", err
}
@@ -277,7 +325,7 @@ func (cc *Crictl) StartPodAndContainer(image, sbSpec, contSpec string) (string,
}
cc.cleanup = append(cc.cleanup, cleanup)
- podID, err := cc.RunPod(sbSpecFile)
+ podID, err := cc.RunPod(runtime, sbSpecFile)
if err != nil {
return "", "", err
}