mirror of
https://github.com/mudler/luet.git
synced 2025-09-08 10:39:19 +00:00
Update gomod and vendor
This commit is contained in:
715
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
Normal file
715
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
Normal file
@@ -0,0 +1,715 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package runc
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
// Format is the type of log formatting options avaliable
|
||||
type Format string
|
||||
|
||||
// TopBody represents the structured data of the full ps output
|
||||
type TopResults struct {
|
||||
// Processes running in the container, where each is process is an array of values corresponding to the headers
|
||||
Processes [][]string `json:"Processes"`
|
||||
|
||||
// Headers are the names of the columns
|
||||
Headers []string `json:"Headers"`
|
||||
}
|
||||
|
||||
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
|
||||
Setpgid bool
|
||||
Criu string
|
||||
SystemdCgroup bool
|
||||
Rootless *bool // nil stands for "auto"
|
||||
}
|
||||
|
||||
// List returns all containers created inside the provided runc root directory
|
||||
func (r *Runc) List(context context.Context) ([]*Container, error) {
|
||||
data, err := cmdOutput(r.command(context, "list", "--format=json"), false)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []*Container
|
||||
if err := json.Unmarshal(data.Bytes(), &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 := cmdOutput(r.command(context, "state", id), true)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", err, data.String())
|
||||
}
|
||||
var c Container
|
||||
if err := json.Unmarshal(data.Bytes(), &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 := cmdOutput(cmd, true)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", err, data.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if 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
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err := Monitor.Wait(cmd, ec)
|
||||
if err == nil && status != 0 {
|
||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
||||
}
|
||||
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(os.Getenv("XDG_RUNTIME_DIR"), "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 := cmdOutput(cmd, true)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", err, data.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if 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
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err := Monitor.Wait(cmd, ec)
|
||||
if err == nil && status != 0 {
|
||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
||||
}
|
||||
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.IO != nil {
|
||||
opts.Set(cmd)
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
status, err := Monitor.Wait(cmd, ec)
|
||||
if err == nil && status != 0 {
|
||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
type DeleteOpts struct {
|
||||
Force bool
|
||||
}
|
||||
|
||||
func (o *DeleteOpts) args() (out []string) {
|
||||
if o.Force {
|
||||
out = append(out, "--force")
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Delete deletes the container
|
||||
func (r *Runc) Delete(context context.Context, id string, opts *DeleteOpts) error {
|
||||
args := []string{"delete"}
|
||||
if opts != nil {
|
||||
args = append(args, opts.args()...)
|
||||
}
|
||||
return r.runOrError(r.command(context, append(args, 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
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
rd.Close()
|
||||
Monitor.Wait(cmd, ec)
|
||||
}()
|
||||
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
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if 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, ec)
|
||||
}()
|
||||
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 := cmdOutput(r.command(context, "ps", "--format", "json", id), true)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", err, data.String())
|
||||
}
|
||||
var pids []int
|
||||
if err := json.Unmarshal(data.Bytes(), &pids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pids, nil
|
||||
}
|
||||
|
||||
// Top lists all the processes inside the container returning the full ps data
|
||||
func (r *Runc) Top(context context.Context, id string, psOptions string) (*TopResults, error) {
|
||||
data, err := cmdOutput(r.command(context, "ps", "--format", "table", id, psOptions), true)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %s", err, data.String())
|
||||
}
|
||||
|
||||
topResults, err := ParsePSOutput(data.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: ", err)
|
||||
}
|
||||
return topResults, 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
|
||||
ConsoleSocket ConsoleSocket
|
||||
}
|
||||
|
||||
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.ConsoleSocket != nil {
|
||||
out = append(out, "--console-socket", o.ConsoleSocket.Path())
|
||||
}
|
||||
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.IO != nil {
|
||||
opts.Set(cmd)
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
if opts != nil && opts.IO != nil {
|
||||
if c, ok := opts.IO.(StartCloser); ok {
|
||||
if err := c.CloseAfterStart(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err := Monitor.Wait(cmd, ec)
|
||||
if err == nil && status != 0 {
|
||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
||||
}
|
||||
return status, err
|
||||
}
|
||||
|
||||
// Update updates the current container with the provided resource spec
|
||||
func (r *Runc) Update(context context.Context, id string, resources *specs.LinuxResources) error {
|
||||
buf := getBuf()
|
||||
defer putBuf(buf)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
var ErrParseRuncVersion = errors.New("unable to parse runc version")
|
||||
|
||||
type Version struct {
|
||||
Runc string
|
||||
Commit string
|
||||
Spec string
|
||||
}
|
||||
|
||||
// Version returns the runc and runtime-spec versions
|
||||
func (r *Runc) Version(context context.Context) (Version, error) {
|
||||
data, err := cmdOutput(r.command(context, "--version"), false)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return Version{}, err
|
||||
}
|
||||
return parseVersion(data.Bytes())
|
||||
}
|
||||
|
||||
func parseVersion(data []byte) (Version, error) {
|
||||
var v Version
|
||||
parts := strings.Split(strings.TrimSpace(string(data)), "\n")
|
||||
|
||||
if len(parts) > 0 {
|
||||
if !strings.HasPrefix(parts[0], "runc version ") {
|
||||
return v, nil
|
||||
}
|
||||
v.Runc = parts[0][13:]
|
||||
|
||||
for _, part := range parts[1:] {
|
||||
if strings.HasPrefix(part, "commit: ") {
|
||||
v.Commit = part[8:]
|
||||
} else if strings.HasPrefix(part, "spec: ") {
|
||||
v.Spec = part[6:]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
if r.SystemdCgroup {
|
||||
out = append(out, "--systemd-cgroup")
|
||||
}
|
||||
if r.Rootless != nil {
|
||||
// nil stands for "auto" (differs from explicit "false")
|
||||
out = append(out, "--rootless="+strconv.FormatBool(*r.Rootless))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// 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 {
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
status, err := Monitor.Wait(cmd, ec)
|
||||
if err == nil && status != 0 {
|
||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
||||
}
|
||||
return err
|
||||
}
|
||||
data, err := cmdOutput(cmd, true)
|
||||
defer putBuf(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", err, data.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// callers of cmdOutput are expected to call putBuf on the returned Buffer
|
||||
// to ensure it is released back to the shared pool after use.
|
||||
func cmdOutput(cmd *exec.Cmd, combined bool) (*bytes.Buffer, error) {
|
||||
b := getBuf()
|
||||
|
||||
cmd.Stdout = b
|
||||
if combined {
|
||||
cmd.Stderr = b
|
||||
}
|
||||
ec, err := Monitor.Start(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status, err := Monitor.Wait(cmd, ec)
|
||||
if err == nil && status != 0 {
|
||||
err = fmt.Errorf("%s did not terminate successfully", cmd.Args[0])
|
||||
}
|
||||
|
||||
return b, err
|
||||
}
|
Reference in New Issue
Block a user