Merge pull request #2618 from crosbymichael/no-stdin
Don't provide IO when it's not set
This commit is contained in:
commit
12c877f57a
@ -141,6 +141,15 @@ func NewCreator(opts ...Opt) Creator {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if streams.Stdin == nil {
|
||||||
|
fifos.Stdin = ""
|
||||||
|
}
|
||||||
|
if streams.Stdout == nil {
|
||||||
|
fifos.Stdout = ""
|
||||||
|
}
|
||||||
|
if streams.Stderr == nil {
|
||||||
|
fifos.Stderr = ""
|
||||||
|
}
|
||||||
return copyIO(fifos, streams)
|
return copyIO(fifos, streams)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -1481,3 +1482,52 @@ func TestBindLowPortNonOpt(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContainerNoSTDIN(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
client, err := newClient(t, address)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
image Image
|
||||||
|
ctx, cancel = testContext()
|
||||||
|
id = t.Name()
|
||||||
|
)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
image, err = client.GetImage(ctx, testImage)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
container, err := client.NewContainer(ctx, id, WithNewSpec(oci.WithImageConfig(image), withExitStatus(0)), WithNewSnapshot(id, image))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer container.Delete(ctx, WithSnapshotCleanup)
|
||||||
|
|
||||||
|
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStreams(nil, ioutil.Discard, ioutil.Discard)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer task.Delete(ctx)
|
||||||
|
|
||||||
|
statusC, err := task.Wait(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := task.Start(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
status := <-statusC
|
||||||
|
code, _, err := status.Result()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if code != 0 {
|
||||||
|
t.Errorf("expected status 0 from wait but received %d", code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -147,7 +147,7 @@ func (e *execProcess) start(ctx context.Context) (err error) {
|
|||||||
return errors.Wrap(err, "creating new NULL IO")
|
return errors.Wrap(err, "creating new NULL IO")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if e.io, err = runc.NewPipeIO(e.parent.IoUID, e.parent.IoGID); err != nil {
|
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 errors.Wrap(err, "failed to create runc io pipes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
|
|||||||
return errors.Wrap(err, "creating new NULL IO")
|
return errors.Wrap(err, "creating new NULL IO")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if p.io, err = runc.NewPipeIO(p.IoUID, p.IoGID); err != nil {
|
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 errors.Wrap(err, "failed to create OCI runtime io pipes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,3 +399,11 @@ func (p *Init) runtimeError(rErr error, msg string) error {
|
|||||||
return errors.Errorf("%s: %s", msg, rMsg)
|
return errors.Errorf("%s: %s", msg, rMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withConditionalIO(c proc.Stdio) runc.IOOpt {
|
||||||
|
return func(o *runc.IOOption) {
|
||||||
|
o.OpenStdin = c.Stdin != ""
|
||||||
|
o.OpenStdout = c.Stdout != ""
|
||||||
|
o.OpenStderr = c.Stderr != ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -109,7 +109,6 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
|||||||
i.dest(fw, fr)
|
i.dest(fw, fr)
|
||||||
}
|
}
|
||||||
if stdin == "" {
|
if stdin == "" {
|
||||||
rio.Stdin().Close()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
f, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0)
|
f, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
github.com/containerd/go-runc acb7c88cac264acca9b5eae187a117f4d77a1292
|
github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
|
||||||
github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
|
github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
|
||||||
github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
|
github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
|
||||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||||
|
55
vendor/github.com/containerd/go-runc/io.go
generated
vendored
55
vendor/github.com/containerd/go-runc/io.go
generated
vendored
@ -34,6 +34,24 @@ type StartCloser interface {
|
|||||||
CloseAfterStart() error
|
CloseAfterStart() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IOOpt sets I/O creation options
|
||||||
|
type IOOpt func(*IOOption)
|
||||||
|
|
||||||
|
// IOOption holds I/O creation options
|
||||||
|
type IOOption struct {
|
||||||
|
OpenStdin bool
|
||||||
|
OpenStdout bool
|
||||||
|
OpenStderr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultIOOption() *IOOption {
|
||||||
|
return &IOOption{
|
||||||
|
OpenStdin: true,
|
||||||
|
OpenStdout: true,
|
||||||
|
OpenStderr: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newPipe() (*pipe, error) {
|
func newPipe() (*pipe, error) {
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -65,14 +83,23 @@ type pipeIO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *pipeIO) Stdin() io.WriteCloser {
|
func (i *pipeIO) Stdin() io.WriteCloser {
|
||||||
|
if i.in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return i.in.w
|
return i.in.w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *pipeIO) Stdout() io.ReadCloser {
|
func (i *pipeIO) Stdout() io.ReadCloser {
|
||||||
|
if i.out == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return i.out.r
|
return i.out.r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *pipeIO) Stderr() io.ReadCloser {
|
func (i *pipeIO) Stderr() io.ReadCloser {
|
||||||
|
if i.err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return i.err.r
|
return i.err.r
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,28 +110,38 @@ func (i *pipeIO) Close() error {
|
|||||||
i.out,
|
i.out,
|
||||||
i.err,
|
i.err,
|
||||||
} {
|
} {
|
||||||
if cerr := v.Close(); err == nil {
|
if v != nil {
|
||||||
err = cerr
|
if cerr := v.Close(); err == nil {
|
||||||
|
err = cerr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *pipeIO) CloseAfterStart() error {
|
func (i *pipeIO) CloseAfterStart() error {
|
||||||
for _, f := range []*os.File{
|
for _, f := range []*pipe{
|
||||||
i.out.w,
|
i.out,
|
||||||
i.err.w,
|
i.err,
|
||||||
} {
|
} {
|
||||||
f.Close()
|
if f != nil {
|
||||||
|
f.w.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets the io to the exec.Cmd
|
// Set sets the io to the exec.Cmd
|
||||||
func (i *pipeIO) Set(cmd *exec.Cmd) {
|
func (i *pipeIO) Set(cmd *exec.Cmd) {
|
||||||
cmd.Stdin = i.in.r
|
if i.in != nil {
|
||||||
cmd.Stdout = i.out.w
|
cmd.Stdin = i.in.r
|
||||||
cmd.Stderr = i.err.w
|
}
|
||||||
|
if i.out != nil {
|
||||||
|
cmd.Stdout = i.out.w
|
||||||
|
}
|
||||||
|
if i.err != nil {
|
||||||
|
cmd.Stderr = i.err.w
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSTDIO() (IO, error) {
|
func NewSTDIO() (IO, error) {
|
||||||
|
59
vendor/github.com/containerd/go-runc/io_unix.go
generated
vendored
59
vendor/github.com/containerd/go-runc/io_unix.go
generated
vendored
@ -24,8 +24,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewPipeIO creates pipe pairs to be used with runc
|
// NewPipeIO creates pipe pairs to be used with runc
|
||||||
func NewPipeIO(uid, gid int) (i IO, err error) {
|
func NewPipeIO(uid, gid int, opts ...IOOpt) (i IO, err error) {
|
||||||
var pipes []*pipe
|
option := defaultIOOption()
|
||||||
|
for _, o := range opts {
|
||||||
|
o(option)
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
pipes []*pipe
|
||||||
|
stdin, stdout, stderr *pipe
|
||||||
|
)
|
||||||
// cleanup in case of an error
|
// cleanup in case of an error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -34,33 +41,33 @@ func NewPipeIO(uid, gid int) (i IO, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
stdin, err := newPipe()
|
if option.OpenStdin {
|
||||||
if err != nil {
|
if stdin, err = newPipe(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
}
|
||||||
|
pipes = append(pipes, stdin)
|
||||||
|
if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to chown stdin")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stdin)
|
if option.OpenStdout {
|
||||||
if err = unix.Fchown(int(stdin.r.Fd()), uid, gid); err != nil {
|
if stdout, err = newPipe(); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to chown stdin")
|
return nil, err
|
||||||
|
}
|
||||||
|
pipes = append(pipes, stdout)
|
||||||
|
if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to chown stdout")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if option.OpenStderr {
|
||||||
stdout, err := newPipe()
|
if stderr, err = newPipe(); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
|
pipes = append(pipes, stderr)
|
||||||
|
if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to chown stderr")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stdout)
|
|
||||||
if err = unix.Fchown(int(stdout.w.Fd()), uid, gid); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to chown stdout")
|
|
||||||
}
|
|
||||||
|
|
||||||
stderr, err := newPipe()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pipes = append(pipes, stderr)
|
|
||||||
if err = unix.Fchown(int(stderr.w.Fd()), uid, gid); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to chown stderr")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pipeIO{
|
return &pipeIO{
|
||||||
in: stdin,
|
in: stdin,
|
||||||
out: stdout,
|
out: stdout,
|
||||||
|
41
vendor/github.com/containerd/go-runc/io_windows.go
generated
vendored
41
vendor/github.com/containerd/go-runc/io_windows.go
generated
vendored
@ -19,8 +19,15 @@
|
|||||||
package runc
|
package runc
|
||||||
|
|
||||||
// NewPipeIO creates pipe pairs to be used with runc
|
// NewPipeIO creates pipe pairs to be used with runc
|
||||||
func NewPipeIO() (i IO, err error) {
|
func NewPipeIO(opts ...IOOpt) (i IO, err error) {
|
||||||
var pipes []*pipe
|
option := defaultIOOption()
|
||||||
|
for _, o := range opts {
|
||||||
|
o(option)
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
pipes []*pipe
|
||||||
|
stdin, stdout, stderr *pipe
|
||||||
|
)
|
||||||
// cleanup in case of an error
|
// cleanup in case of an error
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -29,24 +36,24 @@ func NewPipeIO() (i IO, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
stdin, err := newPipe()
|
if option.OpenStdin {
|
||||||
if err != nil {
|
if stdin, err = newPipe(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
}
|
||||||
|
pipes = append(pipes, stdin)
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stdin)
|
if option.OpenStdout {
|
||||||
|
if stdout, err = newPipe(); err != nil {
|
||||||
stdout, err := newPipe()
|
return nil, err
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
pipes = append(pipes, stdout)
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stdout)
|
if option.OpenStderr {
|
||||||
|
if stderr, err = newPipe(); err != nil {
|
||||||
stderr, err := newPipe()
|
return nil, err
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
pipes = append(pipes, stderr)
|
||||||
}
|
}
|
||||||
pipes = append(pipes, stderr)
|
|
||||||
|
|
||||||
return &pipeIO{
|
return &pipeIO{
|
||||||
in: stdin,
|
in: stdin,
|
||||||
out: stdout,
|
out: stdout,
|
||||||
|
3
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
3
vendor/github.com/containerd/go-runc/runc.go
generated
vendored
@ -608,9 +608,8 @@ func parseVersion(data []byte) (Version, error) {
|
|||||||
var v Version
|
var v Version
|
||||||
parts := strings.Split(strings.TrimSpace(string(data)), "\n")
|
parts := strings.Split(strings.TrimSpace(string(data)), "\n")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return v, ErrParseRuncVersion
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, p := range []struct {
|
for i, p := range []struct {
|
||||||
dest *string
|
dest *string
|
||||||
split string
|
split string
|
||||||
|
Loading…
Reference in New Issue
Block a user