Update deps after move to containerd org
This updates containerd to use the latest versions of cgroups, fifo, console, and go-runc from the containerd org. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
24
vendor/github.com/containerd/go-runc/LICENSE
generated
vendored
Normal file
24
vendor/github.com/containerd/go-runc/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2016 Michael Crosby. crosbymichael@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
42
vendor/github.com/containerd/go-runc/README.md
generated
vendored
Normal file
42
vendor/github.com/containerd/go-runc/README.md
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# go-runc
|
||||
|
||||
[](https://travis-ci.org/containerd/go-runc)
|
||||
|
||||
|
||||
This is a package for consuming the [runc](https://github.com/opencontainers/runc) binary in your Go applications.
|
||||
It tries to expose all the settings and features of the runc CLI. If there is something missing then add it, its opensource!
|
||||
|
||||
This needs runc @ [a9610f2c0](https://github.com/opencontainers/runc/commit/a9610f2c0237d2636d05a031ec8659a70e75ffeb)
|
||||
or greater.
|
||||
|
||||
## Docs
|
||||
|
||||
Docs can be found at [godoc.org](https://godoc.org/github.com/containerd/go-runc).
|
||||
|
||||
|
||||
## LICENSE - MIT
|
||||
|
||||
Copyright (c) 2016 Michael Crosby. crosbymichael@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
98
vendor/github.com/containerd/go-runc/console.go
generated
vendored
Normal file
98
vendor/github.com/containerd/go-runc/console.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// +build cgo
|
||||
|
||||
package runc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
)
|
||||
|
||||
// NewConsoleSocket creates a new unix socket at the provided path to accept a
|
||||
// pty master created by runc for use by the container
|
||||
func NewConsoleSocket(path string) (*Socket, error) {
|
||||
abs, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l, err := net.Listen("unix", abs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Socket{
|
||||
l: l,
|
||||
path: abs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewTempConsoleSocket returns a temp console socket for use with a container
|
||||
// On Close(), the socket is deleted
|
||||
func NewTempConsoleSocket() (*Socket, error) {
|
||||
dir, err := ioutil.TempDir("", "pty")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
abs, err := filepath.Abs(filepath.Join(dir, "pty.sock"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l, err := net.Listen("unix", abs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Socket{
|
||||
l: l,
|
||||
rmdir: true,
|
||||
path: abs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Socket is a unix socket that accepts the pty master created by runc
|
||||
type Socket struct {
|
||||
path string
|
||||
rmdir bool
|
||||
l net.Listener
|
||||
}
|
||||
|
||||
// Path returns the path to the unix socket on disk
|
||||
func (c *Socket) Path() string {
|
||||
return c.path
|
||||
}
|
||||
|
||||
// ReceiveMaster blocks until the socket receives the pty master
|
||||
func (c *Socket) ReceiveMaster() (console.Console, error) {
|
||||
conn, err := c.l.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
unix, ok := conn.(*net.UnixConn)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("received connection which was not a unix socket")
|
||||
}
|
||||
sock, err := unix.File()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := utils.RecvFd(sock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return console.ConsoleFromFile(f)
|
||||
}
|
||||
|
||||
// Close closes the unix socket
|
||||
func (c *Socket) Close() error {
|
||||
err := c.l.Close()
|
||||
if c.rmdir {
|
||||
if rerr := os.RemoveAll(filepath.Dir(c.path)); err == nil {
|
||||
err = rerr
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
14
vendor/github.com/containerd/go-runc/container.go
generated
vendored
Normal file
14
vendor/github.com/containerd/go-runc/container.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package runc
|
||||
|
||||
import "time"
|
||||
|
||||
// Container hold information for a runc container
|
||||
type Container struct {
|
||||
ID string `json:"id"`
|
||||
Pid int `json:"pid"`
|
||||
Status string `json:"status"`
|
||||
Bundle string `json:"bundle"`
|
||||
Rootfs string `json:"rootfs"`
|
||||
Created time.Time `json:"created"`
|
||||
Annotations map[string]string `json:"annotations"`
|
||||
}
|
||||
84
vendor/github.com/containerd/go-runc/events.go
generated
vendored
Normal file
84
vendor/github.com/containerd/go-runc/events.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package runc
|
||||
|
||||
type Event struct {
|
||||
// Type are the event type generated by runc
|
||||
// If the type is "error" then check the Err field on the event for
|
||||
// the actual error
|
||||
Type string `json:"type"`
|
||||
ID string `json:"id"`
|
||||
Stats *Stats `json:"data,omitempty"`
|
||||
// Err has a read error if we were unable to decode the event from runc
|
||||
Err error `json:"-"`
|
||||
}
|
||||
|
||||
type Stats struct {
|
||||
Cpu Cpu `json:"cpu"`
|
||||
Memory Memory `json:"memory"`
|
||||
Pids Pids `json:"pids"`
|
||||
Blkio Blkio `json:"blkio"`
|
||||
Hugetlb map[string]Hugetlb `json:"hugetlb"`
|
||||
}
|
||||
|
||||
type Hugetlb struct {
|
||||
Usage uint64 `json:"usage,omitempty"`
|
||||
Max uint64 `json:"max,omitempty"`
|
||||
Failcnt uint64 `json:"failcnt"`
|
||||
}
|
||||
|
||||
type BlkioEntry struct {
|
||||
Major uint64 `json:"major,omitempty"`
|
||||
Minor uint64 `json:"minor,omitempty"`
|
||||
Op string `json:"op,omitempty"`
|
||||
Value uint64 `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type Blkio struct {
|
||||
IoServiceBytesRecursive []BlkioEntry `json:"ioServiceBytesRecursive,omitempty"`
|
||||
IoServicedRecursive []BlkioEntry `json:"ioServicedRecursive,omitempty"`
|
||||
IoQueuedRecursive []BlkioEntry `json:"ioQueueRecursive,omitempty"`
|
||||
IoServiceTimeRecursive []BlkioEntry `json:"ioServiceTimeRecursive,omitempty"`
|
||||
IoWaitTimeRecursive []BlkioEntry `json:"ioWaitTimeRecursive,omitempty"`
|
||||
IoMergedRecursive []BlkioEntry `json:"ioMergedRecursive,omitempty"`
|
||||
IoTimeRecursive []BlkioEntry `json:"ioTimeRecursive,omitempty"`
|
||||
SectorsRecursive []BlkioEntry `json:"sectorsRecursive,omitempty"`
|
||||
}
|
||||
|
||||
type Pids struct {
|
||||
Current uint64 `json:"current,omitempty"`
|
||||
Limit uint64 `json:"limit,omitempty"`
|
||||
}
|
||||
|
||||
type Throttling struct {
|
||||
Periods uint64 `json:"periods,omitempty"`
|
||||
ThrottledPeriods uint64 `json:"throttledPeriods,omitempty"`
|
||||
ThrottledTime uint64 `json:"throttledTime,omitempty"`
|
||||
}
|
||||
|
||||
type CpuUsage struct {
|
||||
// Units: nanoseconds.
|
||||
Total uint64 `json:"total,omitempty"`
|
||||
Percpu []uint64 `json:"percpu,omitempty"`
|
||||
Kernel uint64 `json:"kernel"`
|
||||
User uint64 `json:"user"`
|
||||
}
|
||||
|
||||
type Cpu struct {
|
||||
Usage CpuUsage `json:"usage,omitempty"`
|
||||
Throttling Throttling `json:"throttling,omitempty"`
|
||||
}
|
||||
|
||||
type MemoryEntry struct {
|
||||
Limit uint64 `json:"limit"`
|
||||
Usage uint64 `json:"usage,omitempty"`
|
||||
Max uint64 `json:"max,omitempty"`
|
||||
Failcnt uint64 `json:"failcnt"`
|
||||
}
|
||||
|
||||
type Memory struct {
|
||||
Cache uint64 `json:"cache,omitempty"`
|
||||
Usage MemoryEntry `json:"usage,omitempty"`
|
||||
Swap MemoryEntry `json:"swap,omitempty"`
|
||||
Kernel MemoryEntry `json:"kernel,omitempty"`
|
||||
KernelTCP MemoryEntry `json:"kernelTCP,omitempty"`
|
||||
Raw map[string]uint64 `json:"raw,omitempty"`
|
||||
}
|
||||
165
vendor/github.com/containerd/go-runc/io.go
generated
vendored
Normal file
165
vendor/github.com/containerd/go-runc/io.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
package runc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type IO interface {
|
||||
io.Closer
|
||||
Stdin() io.WriteCloser
|
||||
Stdout() io.ReadCloser
|
||||
Stderr() io.ReadCloser
|
||||
Set(*exec.Cmd)
|
||||
}
|
||||
|
||||
type StartCloser interface {
|
||||
CloseAfterStart() error
|
||||
}
|
||||
|
||||
// NewPipeIO creates pipe pairs to be used with runc
|
||||
func NewPipeIO(uid, gid int) (i IO, err error) {
|
||||
var pipes []*pipe
|
||||
// cleanup in case of an error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
for _, p := range pipes {
|
||||
p.Close()
|
||||
}
|
||||
}
|
||||
}()
|
||||
stdin, err := newPipe(uid, gid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pipes = append(pipes, stdin)
|
||||
|
||||
stdout, err := newPipe(uid, gid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pipes = append(pipes, stdout)
|
||||
|
||||
stderr, err := newPipe(uid, gid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pipes = append(pipes, stderr)
|
||||
|
||||
return &pipeIO{
|
||||
in: stdin,
|
||||
out: stdout,
|
||||
err: stderr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newPipe(uid, gid int) (*pipe, error) {
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := unix.Fchown(int(r.Fd()), uid, gid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := unix.Fchown(int(w.Fd()), uid, gid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pipe{
|
||||
r: r,
|
||||
w: w,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type pipe struct {
|
||||
r *os.File
|
||||
w *os.File
|
||||
}
|
||||
|
||||
func (p *pipe) Close() error {
|
||||
err := p.r.Close()
|
||||
if werr := p.w.Close(); err == nil {
|
||||
err = werr
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type pipeIO struct {
|
||||
in *pipe
|
||||
out *pipe
|
||||
err *pipe
|
||||
}
|
||||
|
||||
func (i *pipeIO) Stdin() io.WriteCloser {
|
||||
return i.in.w
|
||||
}
|
||||
|
||||
func (i *pipeIO) Stdout() io.ReadCloser {
|
||||
return i.out.r
|
||||
}
|
||||
|
||||
func (i *pipeIO) Stderr() io.ReadCloser {
|
||||
return i.err.r
|
||||
}
|
||||
|
||||
func (i *pipeIO) Close() error {
|
||||
var err error
|
||||
for _, v := range []*pipe{
|
||||
i.in,
|
||||
i.out,
|
||||
i.err,
|
||||
} {
|
||||
if cerr := v.Close(); err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *pipeIO) CloseAfterStart() error {
|
||||
for _, f := range []*os.File{
|
||||
i.out.w,
|
||||
i.err.w,
|
||||
} {
|
||||
f.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set sets the io to the exec.Cmd
|
||||
func (i *pipeIO) Set(cmd *exec.Cmd) {
|
||||
cmd.Stdin = i.in.r
|
||||
cmd.Stdout = i.out.w
|
||||
cmd.Stderr = i.err.w
|
||||
}
|
||||
|
||||
func NewSTDIO() (IO, error) {
|
||||
return &stdio{}, nil
|
||||
}
|
||||
|
||||
type stdio struct {
|
||||
}
|
||||
|
||||
func (s *stdio) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stdio) Set(cmd *exec.Cmd) {
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
|
||||
func (s *stdio) Stdin() io.WriteCloser {
|
||||
return os.Stdin
|
||||
}
|
||||
|
||||
func (s *stdio) Stdout() io.ReadCloser {
|
||||
return os.Stdout
|
||||
}
|
||||
|
||||
func (s *stdio) Stderr() io.ReadCloser {
|
||||
return os.Stderr
|
||||
}
|
||||
50
vendor/github.com/containerd/go-runc/monitor.go
generated
vendored
Normal file
50
vendor/github.com/containerd/go-runc/monitor.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package runc
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var Monitor ProcessMonitor = &defaultMonitor{}
|
||||
|
||||
// ProcessMonitor is an interface for process monitoring
|
||||
//
|
||||
// It allows daemons using go-runc to have a SIGCHLD handler
|
||||
// to handle exits without introducing races between the handler
|
||||
// and go's exec.Cmd
|
||||
// These methods should match the methods exposed by exec.Cmd to provide
|
||||
// a consistent experience for the caller
|
||||
type ProcessMonitor interface {
|
||||
Output(*exec.Cmd) ([]byte, error)
|
||||
CombinedOutput(*exec.Cmd) ([]byte, error)
|
||||
Run(*exec.Cmd) error
|
||||
Start(*exec.Cmd) error
|
||||
Wait(*exec.Cmd) (int, error)
|
||||
}
|
||||
|
||||
type defaultMonitor struct {
|
||||
}
|
||||
|
||||
func (m *defaultMonitor) Output(c *exec.Cmd) ([]byte, error) {
|
||||
return c.Output()
|
||||
}
|
||||
|
||||
func (m *defaultMonitor) CombinedOutput(c *exec.Cmd) ([]byte, error) {
|
||||
return c.CombinedOutput()
|
||||
}
|
||||
|
||||
func (m *defaultMonitor) Run(c *exec.Cmd) error {
|
||||
return c.Run()
|
||||
}
|
||||
|
||||
func (m *defaultMonitor) Start(c *exec.Cmd) error {
|
||||
return c.Start()
|
||||
}
|
||||
|
||||
func (m *defaultMonitor) Wait(c *exec.Cmd) (int, error) {
|
||||
status, err := c.Process.Wait()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return status.Sys().(syscall.WaitStatus).ExitStatus(), nil
|
||||
}
|
||||
553
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
Normal file
553
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
package runc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
// Format is the type of log formatting options avaliable
|
||||
type Format string
|
||||
|
||||
const (
|
||||
none Format = ""
|
||||
JSON Format = "json"
|
||||
Text Format = "text"
|
||||
// DefaultCommand is the default command for Runc
|
||||
DefaultCommand = "runc"
|
||||
)
|
||||
|
||||
// Runc is the client to the runc cli
|
||||
type Runc struct {
|
||||
//If command is empty, DefaultCommand is used
|
||||
Command string
|
||||
Root string
|
||||
Debug bool
|
||||
Log string
|
||||
LogFormat Format
|
||||
PdeathSignal syscall.Signal
|
||||
Criu string
|
||||
}
|
||||
|
||||
// List returns all containers created inside the provided runc root directory
|
||||
func (r *Runc) List(context context.Context) ([]*Container, error) {
|
||||
data, err := Monitor.Output(r.command(context, "list", "--format=json"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []*Container
|
||||
if err := json.Unmarshal(data, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// State returns the state for the container provided by id
|
||||
func (r *Runc) State(context context.Context, id string) (*Container, error) {
|
||||
data, err := Monitor.CombinedOutput(r.command(context, "state", id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", err, data)
|
||||
}
|
||||
var c Container
|
||||
if err := json.Unmarshal(data, &c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
type ConsoleSocket interface {
|
||||
Path() string
|
||||
}
|
||||
|
||||
type CreateOpts struct {
|
||||
IO
|
||||
// PidFile is a path to where a pid file should be created
|
||||
PidFile string
|
||||
ConsoleSocket ConsoleSocket
|
||||
Detach bool
|
||||
NoPivot bool
|
||||
NoNewKeyring bool
|
||||
ExtraFiles []*os.File
|
||||
}
|
||||
|
||||
func (o *CreateOpts) args() (out []string, err error) {
|
||||
if o.PidFile != "" {
|
||||
abs, err := filepath.Abs(o.PidFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, "--pid-file", abs)
|
||||
}
|
||||
if o.ConsoleSocket != nil {
|
||||
out = append(out, "--console-socket", o.ConsoleSocket.Path())
|
||||
}
|
||||
if o.NoPivot {
|
||||
out = append(out, "--no-pivot")
|
||||
}
|
||||
if o.NoNewKeyring {
|
||||
out = append(out, "--no-new-keyring")
|
||||
}
|
||||
if o.Detach {
|
||||
out = append(out, "--detach")
|
||||
}
|
||||
if o.ExtraFiles != nil {
|
||||
out = append(out, "--preserve-fds", strconv.Itoa(len(o.ExtraFiles)))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Create creates a new container and returns its pid if it was created successfully
|
||||
func (r *Runc) Create(context context.Context, id, bundle string, opts *CreateOpts) error {
|
||||
args := []string{"create", "--bundle", bundle}
|
||||
if opts != nil {
|
||||
oargs, err := opts.args()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args = append(args, oargs...)
|
||||
}
|
||||
cmd := r.command(context, append(args, id)...)
|
||||
if opts != nil && opts.IO != nil {
|
||||
opts.Set(cmd)
|
||||
}
|
||||
cmd.ExtraFiles = opts.ExtraFiles
|
||||
|
||||
if cmd.Stdout == nil && cmd.Stderr == nil {
|
||||
data, err := Monitor.CombinedOutput(cmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", err, data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := Monitor.Start(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
if opts != nil && opts.IO != nil {
|
||||
if c, ok := opts.IO.(StartCloser); ok {
|
||||
if err := c.CloseAfterStart(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err := Monitor.Wait(cmd)
|
||||
return err
|
||||
}
|
||||
|
||||
// Start will start an already created container
|
||||
func (r *Runc) Start(context context.Context, id string) error {
|
||||
return r.runOrError(r.command(context, "start", id))
|
||||
}
|
||||
|
||||
type ExecOpts struct {
|
||||
IO
|
||||
PidFile string
|
||||
ConsoleSocket ConsoleSocket
|
||||
Detach bool
|
||||
}
|
||||
|
||||
func (o *ExecOpts) args() (out []string, err error) {
|
||||
if o.ConsoleSocket != nil {
|
||||
out = append(out, "--console-socket", o.ConsoleSocket.Path())
|
||||
}
|
||||
if o.Detach {
|
||||
out = append(out, "--detach")
|
||||
}
|
||||
if o.PidFile != "" {
|
||||
abs, err := filepath.Abs(o.PidFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, "--pid-file", abs)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Exec executres and additional process inside the container based on a full
|
||||
// OCI Process specification
|
||||
func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts *ExecOpts) error {
|
||||
f, err := ioutil.TempFile("", "runc-process")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
err = json.NewEncoder(f).Encode(spec)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args := []string{"exec", "--process", f.Name()}
|
||||
if opts != nil {
|
||||
oargs, err := opts.args()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args = append(args, oargs...)
|
||||
}
|
||||
cmd := r.command(context, append(args, id)...)
|
||||
if opts != nil && opts.IO != nil {
|
||||
opts.Set(cmd)
|
||||
}
|
||||
if cmd.Stdout == nil && cmd.Stderr == nil {
|
||||
data, err := Monitor.CombinedOutput(cmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", err, data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := Monitor.Start(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
if opts != nil && opts.IO != nil {
|
||||
if c, ok := opts.IO.(StartCloser); ok {
|
||||
if err := c.CloseAfterStart(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = Monitor.Wait(cmd)
|
||||
return err
|
||||
}
|
||||
|
||||
// Run runs the create, start, delete lifecycle of the container
|
||||
// and returns its exit status after it has exited
|
||||
func (r *Runc) Run(context context.Context, id, bundle string, opts *CreateOpts) (int, error) {
|
||||
args := []string{"run", "--bundle", bundle}
|
||||
if opts != nil {
|
||||
oargs, err := opts.args()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
args = append(args, oargs...)
|
||||
}
|
||||
cmd := r.command(context, append(args, id)...)
|
||||
if opts != nil {
|
||||
opts.Set(cmd)
|
||||
}
|
||||
if err := Monitor.Start(cmd); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return Monitor.Wait(cmd)
|
||||
}
|
||||
|
||||
// Delete deletes the container
|
||||
func (r *Runc) Delete(context context.Context, id string) error {
|
||||
return r.runOrError(r.command(context, "delete", id))
|
||||
}
|
||||
|
||||
// KillOpts specifies options for killing a container and its processes
|
||||
type KillOpts struct {
|
||||
All bool
|
||||
}
|
||||
|
||||
func (o *KillOpts) args() (out []string) {
|
||||
if o.All {
|
||||
out = append(out, "--all")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Kill sends the specified signal to the container
|
||||
func (r *Runc) Kill(context context.Context, id string, sig int, opts *KillOpts) error {
|
||||
args := []string{
|
||||
"kill",
|
||||
}
|
||||
if opts != nil {
|
||||
args = append(args, opts.args()...)
|
||||
}
|
||||
return r.runOrError(r.command(context, append(args, id, strconv.Itoa(sig))...))
|
||||
}
|
||||
|
||||
// Stats return the stats for a container like cpu, memory, and io
|
||||
func (r *Runc) Stats(context context.Context, id string) (*Stats, error) {
|
||||
cmd := r.command(context, "events", "--stats", id)
|
||||
rd, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
rd.Close()
|
||||
Monitor.Wait(cmd)
|
||||
}()
|
||||
if err := Monitor.Start(cmd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var e Event
|
||||
if err := json.NewDecoder(rd).Decode(&e); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.Stats, nil
|
||||
}
|
||||
|
||||
// Events returns an event stream from runc for a container with stats and OOM notifications
|
||||
func (r *Runc) Events(context context.Context, id string, interval time.Duration) (chan *Event, error) {
|
||||
cmd := r.command(context, "events", fmt.Sprintf("--interval=%ds", int(interval.Seconds())), id)
|
||||
rd, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := Monitor.Start(cmd); err != nil {
|
||||
rd.Close()
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
dec = json.NewDecoder(rd)
|
||||
c = make(chan *Event, 128)
|
||||
)
|
||||
go func() {
|
||||
defer func() {
|
||||
close(c)
|
||||
rd.Close()
|
||||
Monitor.Wait(cmd)
|
||||
}()
|
||||
for {
|
||||
var e Event
|
||||
if err := dec.Decode(&e); err != nil {
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
e = Event{
|
||||
Type: "error",
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
c <- &e
|
||||
}
|
||||
}()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Pause the container with the provided id
|
||||
func (r *Runc) Pause(context context.Context, id string) error {
|
||||
return r.runOrError(r.command(context, "pause", id))
|
||||
}
|
||||
|
||||
// Resume the container with the provided id
|
||||
func (r *Runc) Resume(context context.Context, id string) error {
|
||||
return r.runOrError(r.command(context, "resume", id))
|
||||
}
|
||||
|
||||
// Ps lists all the processes inside the container returning their pids
|
||||
func (r *Runc) Ps(context context.Context, id string) ([]int, error) {
|
||||
data, err := Monitor.CombinedOutput(r.command(context, "ps", "--format", "json", id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", err, data)
|
||||
}
|
||||
var pids []int
|
||||
if err := json.Unmarshal(data, &pids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pids, nil
|
||||
}
|
||||
|
||||
type CheckpointOpts struct {
|
||||
// ImagePath is the path for saving the criu image file
|
||||
ImagePath string
|
||||
// WorkDir is the working directory for criu
|
||||
WorkDir string
|
||||
// ParentPath is the path for previous image files from a pre-dump
|
||||
ParentPath string
|
||||
// AllowOpenTCP allows open tcp connections to be checkpointed
|
||||
AllowOpenTCP bool
|
||||
// AllowExternalUnixSockets allows external unix sockets to be checkpointed
|
||||
AllowExternalUnixSockets bool
|
||||
// AllowTerminal allows the terminal(pty) to be checkpointed with a container
|
||||
AllowTerminal bool
|
||||
// CriuPageServer is the address:port for the criu page server
|
||||
CriuPageServer string
|
||||
// FileLocks handle file locks held by the container
|
||||
FileLocks bool
|
||||
// Cgroups is the cgroup mode for how to handle the checkpoint of a container's cgroups
|
||||
Cgroups CgroupMode
|
||||
// EmptyNamespaces creates a namespace for the container but does not save its properties
|
||||
// Provide the namespaces you wish to be checkpointed without their settings on restore
|
||||
EmptyNamespaces []string
|
||||
}
|
||||
|
||||
type CgroupMode string
|
||||
|
||||
const (
|
||||
Soft CgroupMode = "soft"
|
||||
Full CgroupMode = "full"
|
||||
Strict CgroupMode = "strict"
|
||||
)
|
||||
|
||||
func (o *CheckpointOpts) args() (out []string) {
|
||||
if o.ImagePath != "" {
|
||||
out = append(out, "--image-path", o.ImagePath)
|
||||
}
|
||||
if o.WorkDir != "" {
|
||||
out = append(out, "--work-path", o.WorkDir)
|
||||
}
|
||||
if o.ParentPath != "" {
|
||||
out = append(out, "--parent-path", o.ParentPath)
|
||||
}
|
||||
if o.AllowOpenTCP {
|
||||
out = append(out, "--tcp-established")
|
||||
}
|
||||
if o.AllowExternalUnixSockets {
|
||||
out = append(out, "--ext-unix-sk")
|
||||
}
|
||||
if o.AllowTerminal {
|
||||
out = append(out, "--shell-job")
|
||||
}
|
||||
if o.CriuPageServer != "" {
|
||||
out = append(out, "--page-server", o.CriuPageServer)
|
||||
}
|
||||
if o.FileLocks {
|
||||
out = append(out, "--file-locks")
|
||||
}
|
||||
if string(o.Cgroups) != "" {
|
||||
out = append(out, "--manage-cgroups-mode", string(o.Cgroups))
|
||||
}
|
||||
for _, ns := range o.EmptyNamespaces {
|
||||
out = append(out, "--empty-ns", ns)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type CheckpointAction func([]string) []string
|
||||
|
||||
// LeaveRunning keeps the container running after the checkpoint has been completed
|
||||
func LeaveRunning(args []string) []string {
|
||||
return append(args, "--leave-running")
|
||||
}
|
||||
|
||||
// PreDump allows a pre-dump of the checkpoint to be made and completed later
|
||||
func PreDump(args []string) []string {
|
||||
return append(args, "--pre-dump")
|
||||
}
|
||||
|
||||
// Checkpoint allows you to checkpoint a container using criu
|
||||
func (r *Runc) Checkpoint(context context.Context, id string, opts *CheckpointOpts, actions ...CheckpointAction) error {
|
||||
args := []string{"checkpoint"}
|
||||
if opts != nil {
|
||||
args = append(args, opts.args()...)
|
||||
}
|
||||
for _, a := range actions {
|
||||
args = a(args)
|
||||
}
|
||||
return r.runOrError(r.command(context, append(args, id)...))
|
||||
}
|
||||
|
||||
type RestoreOpts struct {
|
||||
CheckpointOpts
|
||||
IO
|
||||
|
||||
Detach bool
|
||||
PidFile string
|
||||
NoSubreaper bool
|
||||
NoPivot bool
|
||||
}
|
||||
|
||||
func (o *RestoreOpts) args() ([]string, error) {
|
||||
out := o.CheckpointOpts.args()
|
||||
if o.Detach {
|
||||
out = append(out, "--detach")
|
||||
}
|
||||
if o.PidFile != "" {
|
||||
abs, err := filepath.Abs(o.PidFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, "--pid-file", abs)
|
||||
}
|
||||
if o.NoPivot {
|
||||
out = append(out, "--no-pivot")
|
||||
}
|
||||
if o.NoSubreaper {
|
||||
out = append(out, "-no-subreaper")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Restore restores a container with the provide id from an existing checkpoint
|
||||
func (r *Runc) Restore(context context.Context, id, bundle string, opts *RestoreOpts) (int, error) {
|
||||
args := []string{"restore"}
|
||||
if opts != nil {
|
||||
oargs, err := opts.args()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
args = append(args, oargs...)
|
||||
}
|
||||
args = append(args, "--bundle", bundle)
|
||||
cmd := r.command(context, append(args, id)...)
|
||||
if opts != nil {
|
||||
opts.Set(cmd)
|
||||
}
|
||||
if err := Monitor.Start(cmd); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return Monitor.Wait(cmd)
|
||||
}
|
||||
|
||||
// Update updates the current container with the provided resource spec
|
||||
func (r *Runc) Update(context context.Context, id string, resources *specs.LinuxResources) error {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := json.NewEncoder(buf).Encode(resources); err != nil {
|
||||
return err
|
||||
}
|
||||
args := []string{"update", "--resources", "-", id}
|
||||
cmd := r.command(context, args...)
|
||||
cmd.Stdin = buf
|
||||
return r.runOrError(cmd)
|
||||
}
|
||||
|
||||
func (r *Runc) args() (out []string) {
|
||||
if r.Root != "" {
|
||||
out = append(out, "--root", r.Root)
|
||||
}
|
||||
if r.Debug {
|
||||
out = append(out, "--debug")
|
||||
}
|
||||
if r.Log != "" {
|
||||
out = append(out, "--log", r.Log)
|
||||
}
|
||||
if r.LogFormat != none {
|
||||
out = append(out, "--log-format", string(r.LogFormat))
|
||||
}
|
||||
if r.Criu != "" {
|
||||
out = append(out, "--criu", r.Criu)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *Runc) command(context context.Context, args ...string) *exec.Cmd {
|
||||
command := r.Command
|
||||
if command == "" {
|
||||
command = DefaultCommand
|
||||
}
|
||||
cmd := exec.CommandContext(context, command, append(r.args(), args...)...)
|
||||
if r.PdeathSignal != 0 {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Pdeathsig: r.PdeathSignal,
|
||||
}
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// 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>
|
||||
func (r *Runc) runOrError(cmd *exec.Cmd) error {
|
||||
if cmd.Stdout != nil || cmd.Stderr != nil {
|
||||
return Monitor.Run(cmd)
|
||||
}
|
||||
data, err := Monitor.CombinedOutput(cmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", err, data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
28
vendor/github.com/containerd/go-runc/utils.go
generated
vendored
Normal file
28
vendor/github.com/containerd/go-runc/utils.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package runc
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ReadPidFile reads the pid file at the provided path and returns
|
||||
// the pid or an error if the read and conversion is unsuccessful
|
||||
func ReadPidFile(path string) (int, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return strconv.Atoi(string(data))
|
||||
}
|
||||
|
||||
const exitSignalOffset = 128
|
||||
|
||||
// exitStatus returns the correct exit status for a process based on if it
|
||||
// was signaled or exited cleanly
|
||||
func exitStatus(status syscall.WaitStatus) int {
|
||||
if status.Signaled() {
|
||||
return exitSignalOffset + int(status.Signal())
|
||||
}
|
||||
return status.ExitStatus()
|
||||
}
|
||||
Reference in New Issue
Block a user