mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-21 23:01:03 +00:00
WIP on subprocesses
This commit is contained in:
parent
54a5890485
commit
f0f96de2b5
7 changed files with 146 additions and 60 deletions
|
|
@ -2,6 +2,7 @@ package commands
|
|||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/fatih/color"
|
||||
|
|
@ -59,3 +60,17 @@ func (s *Service) Attach() (*exec.Cmd, error) {
|
|||
func (s *Service) Top() (types.ContainerProcessList, error) {
|
||||
return s.Container.Top()
|
||||
}
|
||||
|
||||
// ViewLogs attaches to a subprocess viewing the service's logs
|
||||
func (s *Service) ViewLogs() (*exec.Cmd, error) {
|
||||
templateString := s.OSCommand.Config.UserConfig.CommandTemplates.ViewServiceLogs
|
||||
command := utils.ApplyTemplate(templateString, s)
|
||||
|
||||
cmd := s.OSCommand.ExecutableFromString(command)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
Pgid: 0,
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,10 +101,11 @@ type GuiConfig struct {
|
|||
}
|
||||
|
||||
type CommandTemplatesConfig struct {
|
||||
RestartService string `yaml:"restartService,omitempty"`
|
||||
DockerCompose string `yaml:"dockerCompose,omitempty"`
|
||||
StopService string `yaml:"stopService,omitempty"`
|
||||
ServiceLogs string `yaml:"serviceLogs,omitempty"`
|
||||
RestartService string `yaml:"restartService,omitempty"`
|
||||
DockerCompose string `yaml:"dockerCompose,omitempty"`
|
||||
StopService string `yaml:"stopService,omitempty"`
|
||||
ServiceLogs string `yaml:"serviceLogs,omitempty"`
|
||||
ViewServiceLogs string `yaml:"viewServiceLogs,omitempty"`
|
||||
}
|
||||
|
||||
type OSConfig struct {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
// "io"
|
||||
// "io/ioutil"
|
||||
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/go-errors/errors"
|
||||
|
||||
// "strings"
|
||||
|
|
@ -568,51 +563,6 @@ func (gui *Gui) reRenderMain() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
|
||||
// if the error returned from a run is a ErrSubProcess, it runs the subprocess
|
||||
// otherwise it handles the error, possibly by quitting the application
|
||||
func (gui *Gui) RunWithSubprocesses() error {
|
||||
for {
|
||||
if err := gui.Run(); err != nil {
|
||||
if err == gocui.ErrQuit {
|
||||
break
|
||||
} else if err == gui.Errors.ErrSubProcess {
|
||||
if err := gui.runCommand(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) runCommand() error {
|
||||
gui.SubProcess.Stdout = os.Stdout
|
||||
gui.SubProcess.Stderr = os.Stdout
|
||||
gui.SubProcess.Stdin = os.Stdin
|
||||
|
||||
fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(gui.SubProcess.Args, " "), color.FgBlue))
|
||||
|
||||
if err := gui.SubProcess.Run(); err != nil {
|
||||
// not handling the error explicitly because usually we're going to see it
|
||||
// in the output anyway
|
||||
gui.Log.Error(err)
|
||||
}
|
||||
|
||||
gui.SubProcess.Stdout = ioutil.Discard
|
||||
gui.SubProcess.Stderr = ioutil.Discard
|
||||
gui.SubProcess.Stdin = nil
|
||||
gui.SubProcess = nil
|
||||
|
||||
// fmt.Fprintf(os.Stdout, "\n%s", utils.ColoredString(gui.Tr.SLocalize("pressEnterToReturn"), color.FgGreen))
|
||||
|
||||
// fmt.Scanln() // wait for enter press
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) quit(g *gocui.Gui, v *gocui.View) error {
|
||||
if gui.Config.UserConfig.ConfirmOnQuit {
|
||||
return gui.createConfirmationPanel(g, v, "", gui.Tr.SLocalize("ConfirmQuit"), func(g *gocui.Gui, v *gocui.View) error {
|
||||
|
|
|
|||
|
|
@ -64,12 +64,14 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||
Key: 'q',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.quit,
|
||||
}, {
|
||||
ViewName: "",
|
||||
Key: gocui.KeyCtrlC,
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.quit,
|
||||
}, {
|
||||
},
|
||||
// {
|
||||
// ViewName: "",
|
||||
// Key: gocui.KeyCtrlC,
|
||||
// Modifier: gocui.ModNone,
|
||||
// Handler: gui.quit,
|
||||
// },
|
||||
{
|
||||
ViewName: "",
|
||||
Key: gocui.KeyEsc,
|
||||
Modifier: gocui.ModNone,
|
||||
|
|
@ -201,6 +203,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||
Handler: gui.handleServiceAttach,
|
||||
Description: gui.Tr.SLocalize("attach"),
|
||||
},
|
||||
{
|
||||
ViewName: "services",
|
||||
Key: 'm',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleServiceViewLogs,
|
||||
Description: gui.Tr.SLocalize("viewLogs"),
|
||||
},
|
||||
{
|
||||
ViewName: "services",
|
||||
Key: '[',
|
||||
|
|
|
|||
|
|
@ -278,3 +278,18 @@ func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error {
|
|||
gui.SubProcess = c
|
||||
return gui.Errors.ErrSubProcess
|
||||
}
|
||||
|
||||
func (gui *Gui) handleServiceViewLogs(g *gocui.Gui, v *gocui.View) error {
|
||||
service, err := gui.getSelectedService()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c, err := service.ViewLogs()
|
||||
if err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
|
||||
gui.SubProcess = c
|
||||
return gui.Errors.ErrSubProcess
|
||||
}
|
||||
|
|
|
|||
92
pkg/gui/subprocess.go
Normal file
92
pkg/gui/subprocess.go
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||
)
|
||||
|
||||
// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
|
||||
// if the error returned from a run is a ErrSubProcess, it runs the subprocess
|
||||
// otherwise it handles the error, possibly by quitting the application
|
||||
func (gui *Gui) RunWithSubprocesses() error {
|
||||
for {
|
||||
if err := gui.Run(); err != nil {
|
||||
if err == gocui.ErrQuit {
|
||||
break
|
||||
} else if err == gui.Errors.ErrSubProcess {
|
||||
if err := gui.runCommand(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) runCommand() error {
|
||||
gui.SubProcess.Stdout = os.Stdout
|
||||
gui.SubProcess.Stderr = os.Stdout
|
||||
// gui.SubProcess.Stdin = os.Stdin
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
<-c
|
||||
gui.SubProcess.Process.Kill()
|
||||
}()
|
||||
|
||||
w, err := gui.SubProcess.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
input, err := reader.ReadByte()
|
||||
gui.Log.Warn("byte received")
|
||||
gui.Log.Warn(input)
|
||||
if input == 3 {
|
||||
gui.SubProcess.Process.Kill()
|
||||
break
|
||||
}
|
||||
if err != nil && err == io.EOF {
|
||||
gui.SubProcess.Process.Kill()
|
||||
break
|
||||
}
|
||||
w.Write([]byte{input})
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Fprintf(os.Stdout, "\n%s\n\n", utils.ColoredString("+ "+strings.Join(gui.SubProcess.Args, " "), color.FgBlue))
|
||||
|
||||
if err := gui.SubProcess.Run(); err != nil {
|
||||
// not handling the error explicitly because usually we're going to see it
|
||||
// in the output anyway
|
||||
gui.Log.Error(err)
|
||||
}
|
||||
|
||||
gui.SubProcess.Stdout = ioutil.Discard
|
||||
gui.SubProcess.Stderr = ioutil.Discard
|
||||
gui.SubProcess.Stdin = nil
|
||||
gui.SubProcess = nil
|
||||
|
||||
// fmt.Fprintf(os.Stdout, "\n%s", utils.ColoredString(gui.Tr.SLocalize("pressEnterToReturn"), color.FgGreen))
|
||||
|
||||
// fmt.Scanln() // wait for enter press
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -816,6 +816,10 @@ func addEnglish(i18nObject *i18n.Bundle) error {
|
|||
ID: "attach",
|
||||
Other: "attach",
|
||||
},
|
||||
&i18n.Message{
|
||||
ID: "viewLogs",
|
||||
Other: "view logs",
|
||||
},
|
||||
&i18n.Message{
|
||||
ID: "ServicesTitle",
|
||||
Other: "Services",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue