mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-23 23:51:03 +00:00
initial take on attaching to container via SDK
This commit is contained in:
parent
cca69e64f3
commit
7a78175eff
5 changed files with 78 additions and 11 deletions
1
go.mod
1
go.mod
|
|
@ -33,6 +33,7 @@ require (
|
||||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad
|
||||||
github.com/stretchr/testify v1.2.2
|
github.com/stretchr/testify v1.2.2
|
||||||
github.com/tcnksm/go-gitconfig v0.1.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
|
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522
|
||||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,14 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
|
@ -341,18 +346,80 @@ func (c *Container) Restart() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach attaches the container
|
// 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
|
// verify that we can in fact attach to this container
|
||||||
if !c.Details.Config.OpenStdin {
|
if !c.Details.Config.OpenStdin {
|
||||||
return nil, errors.New(c.Tr.UnattachableContainerError)
|
return errors.New(c.Tr.UnattachableContainerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Container.State == "exited" {
|
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)
|
options := types.ContainerAttachOptions{
|
||||||
return cmd, nil
|
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
|
// Top returns process information
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ func (s *Service) Restart() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach attaches to the service
|
// Attach attaches to the service
|
||||||
func (s *Service) Attach() (*exec.Cmd, error) {
|
func (s *Service) Attach() error {
|
||||||
return s.Container.Attach()
|
return s.Container.Attach()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -467,12 +467,13 @@ func (gui *Gui) handleContainerAttach(g *gocui.Gui, v *gocui.View) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := container.Attach()
|
err = container.Attach()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.createErrorPanel(gui.g, err.Error())
|
return gui.createErrorPanel(gui.g, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.SubProcess = c
|
gui.RunWithSubprocesses()
|
||||||
|
|
||||||
return gui.Errors.ErrSubProcess
|
return gui.Errors.ErrSubProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,13 +256,11 @@ func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error {
|
||||||
return gui.createErrorPanel(gui.g, gui.Tr.NoContainers)
|
return gui.createErrorPanel(gui.g, gui.Tr.NoContainers)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := service.Attach()
|
err = service.Attach()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.createErrorPanel(gui.g, err.Error())
|
return gui.createErrorPanel(gui.g, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.SubProcess = c
|
|
||||||
return gui.Errors.ErrSubProcess
|
return gui.Errors.ErrSubProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue