From 43c6da22b976b6050f86dca50564a4c2b08caee0 Mon Sep 17 00:00:00 2001 From: baude Date: Thu, 10 Jan 2019 12:15:33 -0600 Subject: Add darwin support for remote-client Add the ability to cross-compile podman remote for OSX. Also, add image exists and tag to remote-client. Signed-off-by: baude --- libpod/adapter/runtime_remote.go | 18 ++- libpod/container_api.go | 20 ++++ libpod/container_attach.go | 179 ---------------------------- libpod/container_attach_linux.go | 162 +++++++++++++++++++++++++ libpod/container_attach_unsupported.go | 11 ++ libpod/lock/shm_lock_manager_unsupported.go | 4 +- libpod/runtime_volume_unsupported.go | 19 +++ 7 files changed, 229 insertions(+), 184 deletions(-) delete mode 100644 libpod/container_attach.go create mode 100644 libpod/container_attach_linux.go create mode 100644 libpod/container_attach_unsupported.go create mode 100644 libpod/runtime_volume_unsupported.go (limited to 'libpod') diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go index 2f22dd36b..0fe5c449a 100644 --- a/libpod/adapter/runtime_remote.go +++ b/libpod/adapter/runtime_remote.go @@ -66,6 +66,7 @@ type remoteImage struct { Names []string Digest digest.Digest isParent bool + Runtime *LocalRuntime } // GetImages returns a slice of containerimages over a varlink connection @@ -80,7 +81,7 @@ func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { if len(i.RepoTags) > 1 { name = i.RepoTags[0] } - newImage, err := imageInListToContainerImage(i, name) + newImage, err := imageInListToContainerImage(i, name, r) if err != nil { return nil, err } @@ -89,7 +90,7 @@ func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) { return newImages, nil } -func imageInListToContainerImage(i iopodman.ImageInList, name string) (*ContainerImage, error) { +func imageInListToContainerImage(i iopodman.ImageInList, name string, runtime *LocalRuntime) (*ContainerImage, error) { imageParts, err := image.DecomposeString(name) if err != nil { return nil, err @@ -111,6 +112,7 @@ func imageInListToContainerImage(i iopodman.ImageInList, name string) (*Containe Repository: imageParts.Registry, Names: i.RepoTags, isParent: i.IsParent, + Runtime: runtime, } return &ContainerImage{ri}, nil } @@ -121,7 +123,7 @@ func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { if err != nil { return nil, err } - return imageInListToContainerImage(img, name) + return imageInListToContainerImage(img, name, r) } @@ -173,3 +175,13 @@ func (ci *ContainerImage) Labels(ctx context.Context) (map[string]string, error) func (ci *ContainerImage) Dangling() bool { return len(ci.Names()) == 0 } + +// TagImage ... +func (ci *ContainerImage) TagImage(tag string) error { + _, err := iopodman.TagImage().Call(ci.Runtime.Conn, ci.ID(), tag) + return err +} + +func (r RemoteRuntime) RemoveImage(force bool) error { + return nil +} diff --git a/libpod/container_api.go b/libpod/container_api.go index 4eaf737b0..149867759 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -3,6 +3,7 @@ package libpod import ( "context" "fmt" + "io" "io/ioutil" "os" "strconv" @@ -413,6 +414,25 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir return waitErr } +// AttachStreams contains streams that will be attached to the container +type AttachStreams struct { + // OutputStream will be attached to container's STDOUT + OutputStream io.WriteCloser + // ErrorStream will be attached to container's STDERR + ErrorStream io.WriteCloser + // InputStream will be attached to container's STDIN + InputStream io.Reader + // AttachOutput is whether to attach to STDOUT + // If false, stdout will not be attached + AttachOutput bool + // AttachError is whether to attach to STDERR + // If false, stdout will not be attached + AttachError bool + // AttachInput is whether to attach to STDIN + // If false, stdout will not be attached + AttachInput bool +} + // Attach attaches to a container func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize) error { if !c.batched { diff --git a/libpod/container_attach.go b/libpod/container_attach.go deleted file mode 100644 index f925c3897..000000000 --- a/libpod/container_attach.go +++ /dev/null @@ -1,179 +0,0 @@ -package libpod - -import ( - "fmt" - "io" - "net" - "os" - "path/filepath" - - "github.com/containers/libpod/pkg/kubeutils" - "github.com/containers/libpod/utils" - "github.com/docker/docker/pkg/term" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" - "k8s.io/client-go/tools/remotecommand" -) - -//#include -// extern int unix_path_length(){struct sockaddr_un addr; return sizeof(addr.sun_path) - 1;} -import "C" - -/* Sync with stdpipe_t in conmon.c */ -const ( - AttachPipeStdin = 1 - AttachPipeStdout = 2 - AttachPipeStderr = 3 -) - -// AttachStreams contains streams that will be attached to the container -type AttachStreams struct { - // OutputStream will be attached to container's STDOUT - OutputStream io.WriteCloser - // ErrorStream will be attached to container's STDERR - ErrorStream io.WriteCloser - // InputStream will be attached to container's STDIN - InputStream io.Reader - // AttachOutput is whether to attach to STDOUT - // If false, stdout will not be attached - AttachOutput bool - // AttachError is whether to attach to STDERR - // If false, stdout will not be attached - AttachError bool - // AttachInput is whether to attach to STDIN - // If false, stdout will not be attached - AttachInput bool -} - -// Attach to the given container -// Does not check if state is appropriate -func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { - if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { - return errors.Wrapf(ErrInvalidArg, "must provide at least one stream to attach to") - } - - // Check the validity of the provided keys first - var err error - detachKeys := []byte{} - if len(keys) > 0 { - detachKeys, err = term.ToBytes(keys) - if err != nil { - return errors.Wrapf(err, "invalid detach keys") - } - } - - logrus.Debugf("Attaching to container %s", c.ID()) - - return c.attachContainerSocket(resize, detachKeys, streams, startContainer) -} - -// attachContainerSocket connects to the container's attach socket and deals with the IO -// TODO add a channel to allow interrupting -func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool) error { - kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) { - controlPath := filepath.Join(c.bundlePath(), "ctl") - controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0) - if err != nil { - logrus.Debugf("Could not open ctl file: %v", err) - return - } - defer controlFile.Close() - - logrus.Debugf("Received a resize event: %+v", size) - if _, err = fmt.Fprintf(controlFile, "%d %d %d\n", 1, size.Height, size.Width); err != nil { - logrus.Warnf("Failed to write to control file to resize terminal: %v", err) - } - }) - - socketPath := c.AttachSocketPath() - - maxUnixLength := int(C.unix_path_length()) - if maxUnixLength < len(socketPath) { - socketPath = socketPath[0:maxUnixLength] - } - - logrus.Debug("connecting to socket ", socketPath) - - conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) - if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath) - } - defer conn.Close() - - if startContainer { - if err := c.start(); err != nil { - return err - } - } - - receiveStdoutError := make(chan error) - go func() { - receiveStdoutError <- redirectResponseToOutputStreams(streams.OutputStream, streams.ErrorStream, streams.AttachOutput, streams.AttachError, conn) - }() - - stdinDone := make(chan error) - go func() { - var err error - if streams.AttachInput { - _, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys) - conn.CloseWrite() - } - stdinDone <- err - }() - - select { - case err := <-receiveStdoutError: - return err - case err := <-stdinDone: - if _, ok := err.(utils.DetachError); ok { - return nil - } - if streams.AttachOutput || streams.AttachError { - return <-receiveStdoutError - } - } - return nil -} - -func redirectResponseToOutputStreams(outputStream, errorStream io.Writer, writeOutput, writeError bool, conn io.Reader) error { - var err error - buf := make([]byte, 8192+1) /* Sync with conmon STDIO_BUF_SIZE */ - for { - nr, er := conn.Read(buf) - if nr > 0 { - var dst io.Writer - var doWrite bool - switch buf[0] { - case AttachPipeStdout: - dst = outputStream - doWrite = writeOutput - case AttachPipeStderr: - dst = errorStream - doWrite = writeError - default: - logrus.Infof("Received unexpected attach type %+d", buf[0]) - } - - if doWrite { - nw, ew := dst.Write(buf[1:nr]) - if ew != nil { - err = ew - break - } - if nr != nw+1 { - err = io.ErrShortWrite - break - } - } - } - if er == io.EOF { - break - } - if er != nil { - err = er - break - } - } - return err -} diff --git a/libpod/container_attach_linux.go b/libpod/container_attach_linux.go new file mode 100644 index 000000000..1d6f0bd96 --- /dev/null +++ b/libpod/container_attach_linux.go @@ -0,0 +1,162 @@ +//+build linux + +package libpod + +import ( + "fmt" + "io" + "net" + "os" + "path/filepath" + + "github.com/containers/libpod/pkg/kubeutils" + "github.com/containers/libpod/utils" + "github.com/docker/docker/pkg/term" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" + "k8s.io/client-go/tools/remotecommand" +) + +//#include +// extern int unix_path_length(){struct sockaddr_un addr; return sizeof(addr.sun_path) - 1;} +import "C" + +/* Sync with stdpipe_t in conmon.c */ +const ( + AttachPipeStdin = 1 + AttachPipeStdout = 2 + AttachPipeStderr = 3 +) + +// Attach to the given container +// Does not check if state is appropriate +func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { + if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { + return errors.Wrapf(ErrInvalidArg, "must provide at least one stream to attach to") + } + + // Check the validity of the provided keys first + var err error + detachKeys := []byte{} + if len(keys) > 0 { + detachKeys, err = term.ToBytes(keys) + if err != nil { + return errors.Wrapf(err, "invalid detach keys") + } + } + + logrus.Debugf("Attaching to container %s", c.ID()) + + return c.attachContainerSocket(resize, detachKeys, streams, startContainer) +} + +// attachContainerSocket connects to the container's attach socket and deals with the IO +// TODO add a channel to allow interrupting +func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool) error { + kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) { + controlPath := filepath.Join(c.bundlePath(), "ctl") + controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0) + if err != nil { + logrus.Debugf("Could not open ctl file: %v", err) + return + } + defer controlFile.Close() + + logrus.Debugf("Received a resize event: %+v", size) + if _, err = fmt.Fprintf(controlFile, "%d %d %d\n", 1, size.Height, size.Width); err != nil { + logrus.Warnf("Failed to write to control file to resize terminal: %v", err) + } + }) + + socketPath := c.AttachSocketPath() + + maxUnixLength := int(C.unix_path_length()) + if maxUnixLength < len(socketPath) { + socketPath = socketPath[0:maxUnixLength] + } + + logrus.Debug("connecting to socket ", socketPath) + + conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) + if err != nil { + return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath) + } + defer conn.Close() + + if startContainer { + if err := c.start(); err != nil { + return err + } + } + + receiveStdoutError := make(chan error) + go func() { + receiveStdoutError <- redirectResponseToOutputStreams(streams.OutputStream, streams.ErrorStream, streams.AttachOutput, streams.AttachError, conn) + }() + + stdinDone := make(chan error) + go func() { + var err error + if streams.AttachInput { + _, err = utils.CopyDetachable(conn, streams.InputStream, detachKeys) + conn.CloseWrite() + } + stdinDone <- err + }() + + select { + case err := <-receiveStdoutError: + return err + case err := <-stdinDone: + if _, ok := err.(utils.DetachError); ok { + return nil + } + if streams.AttachOutput || streams.AttachError { + return <-receiveStdoutError + } + } + return nil +} + +func redirectResponseToOutputStreams(outputStream, errorStream io.Writer, writeOutput, writeError bool, conn io.Reader) error { + var err error + buf := make([]byte, 8192+1) /* Sync with conmon STDIO_BUF_SIZE */ + for { + nr, er := conn.Read(buf) + if nr > 0 { + var dst io.Writer + var doWrite bool + switch buf[0] { + case AttachPipeStdout: + dst = outputStream + doWrite = writeOutput + case AttachPipeStderr: + dst = errorStream + doWrite = writeError + default: + logrus.Infof("Received unexpected attach type %+d", buf[0]) + } + + if doWrite { + nw, ew := dst.Write(buf[1:nr]) + if ew != nil { + err = ew + break + } + if nr != nw+1 { + err = io.ErrShortWrite + break + } + } + } + if er == io.EOF { + break + } + if er != nil { + err = er + break + } + } + return err +} diff --git a/libpod/container_attach_unsupported.go b/libpod/container_attach_unsupported.go new file mode 100644 index 000000000..068652b29 --- /dev/null +++ b/libpod/container_attach_unsupported.go @@ -0,0 +1,11 @@ +//+build !linux + +package libpod + +import ( + "k8s.io/client-go/tools/remotecommand" +) + +func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { + return ErrNotImplemented +} diff --git a/libpod/lock/shm_lock_manager_unsupported.go b/libpod/lock/shm_lock_manager_unsupported.go index a1340fcd1..cbdb2f7bc 100644 --- a/libpod/lock/shm_lock_manager_unsupported.go +++ b/libpod/lock/shm_lock_manager_unsupported.go @@ -9,12 +9,12 @@ import "fmt" type SHMLockManager struct{} // NewSHMLockManager is not supported on this platform -func NewSHMLockManager(numLocks uint32) (Manager, error) { +func NewSHMLockManager(path string, numLocks uint32) (Manager, error) { return nil, fmt.Errorf("not supported") } // OpenSHMLockManager is not supported on this platform -func OpenSHMLockManager(numLocks uint32) (Manager, error) { +func OpenSHMLockManager(path string, numLocks uint32) (Manager, error) { return nil, fmt.Errorf("not supported") } diff --git a/libpod/runtime_volume_unsupported.go b/libpod/runtime_volume_unsupported.go new file mode 100644 index 000000000..d87459759 --- /dev/null +++ b/libpod/runtime_volume_unsupported.go @@ -0,0 +1,19 @@ +// +build !linux + +package libpod + +import ( + "context" +) + +func (r *Runtime) removeVolume(ctx context.Context, v *Volume, force, prune bool) error { + return ErrNotImplemented +} + +func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) { + return nil, ErrNotImplemented +} + +func (r *Runtime) NewVolume(ctx context.Context, options ...VolumeCreateOption) (*Volume, error) { + return nil, ErrNotImplemented +} -- cgit v1.2.3-54-g00ecf