initial take on attaching to container via SDK

This commit is contained in:
Dawid Dziurla 2019-07-07 17:42:46 +02:00
parent cca69e64f3
commit 7a78175eff
No known key found for this signature in database
GPG key ID: 7B6D8368172E9B0B
5 changed files with 78 additions and 11 deletions

1
go.mod
View file

@ -33,6 +33,7 @@ require (
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
github.com/stretchr/testify v1.2.2
github.com/tcnksm/go-gitconfig v0.1.2
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522
gopkg.in/yaml.v2 v2.2.2 // indirect
)

View file

@ -2,9 +2,14 @@ package commands
import (
"context"
"golang.org/x/crypto/ssh/terminal"
"io"
"os"
"os/exec"
"os/signal"
"strconv"
"strings"
"syscall"
"time"
"github.com/docker/docker/api/types"
@ -341,18 +346,80 @@ func (c *Container) Restart() error {
}
// Attach attaches the container
func (c *Container) Attach() (*exec.Cmd, error) {
func (c *Container) Attach() error {
// verify that we can in fact attach to this container
if !c.Details.Config.OpenStdin {
return nil, errors.New(c.Tr.UnattachableContainerError)
return errors.New(c.Tr.UnattachableContainerError)
}
if c.Container.State == "exited" {
return nil, errors.New(c.Tr.CannotAttachStoppedContainerError)
return errors.New(c.Tr.CannotAttachStoppedContainerError)
}
cmd := c.OSCommand.PrepareSubProcess("docker", "attach", "--sig-proxy=false", c.ID)
return cmd, nil
options := types.ContainerAttachOptions{
Stream: true,
Stdin: c.Details.Config.OpenStdin,
Stdout: true,
Stderr: true,
}
hijack, err := c.Client.ContainerAttach(context.Background(), c.ID, options)
if err != nil {
return err
}
if c.Details.Config.OpenStdin {
fd := int(os.Stdin.Fd())
if terminal.IsTerminal(fd) {
oldState, err := terminal.MakeRaw(fd)
if err != nil {
return err
}
defer terminal.Restore(fd, oldState)
go c.resizeIfChanged(fd)
go io.Copy(hijack.Conn, os.Stdin)
}
}
_, err = io.Copy(os.Stdout, hijack.Conn)
if err != nil {
return err
}
hijack.Close()
return nil
}
func (c *Container) resizeIfChanged(fd int) {
channel := make(chan os.Signal)
signal.Notify(channel, syscall.SIGWINCH)
for {
<-channel
c.Resize(fd)
}
}
func (c *Container) Resize(fd int) error {
width, height, err := terminal.GetSize(fd)
if err != nil {
return err
}
options := types.ResizeOptions{
Height: uint(height),
Width: uint(width),
}
err = c.Client.ContainerResize(context.Background(), c.ID, options)
if err != nil {
return err
}
return nil
}
// Top returns process information

View file

@ -56,7 +56,7 @@ func (s *Service) Restart() error {
}
// Attach attaches to the service
func (s *Service) Attach() (*exec.Cmd, error) {
func (s *Service) Attach() error {
return s.Container.Attach()
}

View file

@ -467,12 +467,13 @@ func (gui *Gui) handleContainerAttach(g *gocui.Gui, v *gocui.View) error {
return nil
}
c, err := container.Attach()
err = container.Attach()
if err != nil {
return gui.createErrorPanel(gui.g, err.Error())
}
gui.SubProcess = c
gui.RunWithSubprocesses()
return gui.Errors.ErrSubProcess
}

View file

@ -256,13 +256,11 @@ func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error {
return gui.createErrorPanel(gui.g, gui.Tr.NoContainers)
}
c, err := service.Attach()
err = service.Attach()
if err != nil {
return gui.createErrorPanel(gui.g, err.Error())
}
gui.SubProcess = c
return gui.Errors.ErrSubProcess
}