mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
allow showing TOP of a container/service
This commit is contained in:
parent
2474c0b34e
commit
344c72f91a
7 changed files with 73 additions and 4 deletions
|
|
@ -418,3 +418,13 @@ func (c *Container) TTYLogsCommand() *exec.Cmd {
|
||||||
func (c *Container) Inspect() (types.ContainerJSON, error) {
|
func (c *Container) Inspect() (types.ContainerJSON, error) {
|
||||||
return c.Client.ContainerInspect(context.Background(), c.ID)
|
return c.Client.ContainerInspect(context.Background(), c.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderTop returns details about the container
|
||||||
|
func (c *Container) RenderTop() (string, error) {
|
||||||
|
result, err := c.Client.ContainerTop(context.Background(), c.ID, []string{})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.RenderTable(append([][]string{result.Titles}, result.Processes...))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,3 +78,14 @@ func (s *Service) ViewLogs() (*exec.Cmd, error) {
|
||||||
|
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderTop renders the process list of the service
|
||||||
|
func (s *Service) RenderTop() (string, error) {
|
||||||
|
templateString := s.OSCommand.Config.UserConfig.CommandTemplates.ServiceTop
|
||||||
|
command := utils.ApplyTemplate(
|
||||||
|
templateString,
|
||||||
|
s.DockerCommand.NewCommandObject(CommandObject{Service: s}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return s.OSCommand.RunCommandWithOutput(command)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ type CommandTemplatesConfig struct {
|
||||||
ViewAllLogs string `yaml:"viewAlLogs,omitempty"`
|
ViewAllLogs string `yaml:"viewAlLogs,omitempty"`
|
||||||
DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"`
|
DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"`
|
||||||
CheckDockerComposeConfig string `yaml:"checkDockerComposeConfig,omitempty"`
|
CheckDockerComposeConfig string `yaml:"checkDockerComposeConfig,omitempty"`
|
||||||
|
ServiceTop string `yaml:"serviceTop,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OSConfig struct {
|
type OSConfig struct {
|
||||||
|
|
@ -188,6 +189,7 @@ func GetDefaultConfig() UserConfig {
|
||||||
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .Container.ID }}",
|
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .Container.ID }}",
|
||||||
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .Container.ID }}",
|
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .Container.ID }}",
|
||||||
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .Container.ID }}",
|
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .Container.ID }}",
|
||||||
|
ServiceTop: "{{ .DockerCompose }} top {{ .Service.Name }}",
|
||||||
},
|
},
|
||||||
CustomCommands: CustomCommands{
|
CustomCommands: CustomCommands{
|
||||||
Containers: []CustomCommand{
|
Containers: []CustomCommand{
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,11 @@ import (
|
||||||
// list panel functions
|
// list panel functions
|
||||||
|
|
||||||
func (gui *Gui) getContainerContexts() []string {
|
func (gui *Gui) getContainerContexts() []string {
|
||||||
return []string{"logs", "stats", "config"}
|
return []string{"logs", "stats", "config", "top"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getContainerContextTitles() []string {
|
func (gui *Gui) getContainerContextTitles() []string {
|
||||||
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ConfigTitle}
|
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ConfigTitle, gui.Tr.TopTitle}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSelectedContainer() (*commands.Container, error) {
|
func (gui *Gui) getSelectedContainer() (*commands.Container, error) {
|
||||||
|
|
@ -101,6 +101,10 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
if err := gui.renderContainerStats(container); err != nil {
|
if err := gui.renderContainerStats(container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "top":
|
||||||
|
if err := gui.renderContainerTop(container); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return errors.New("Unknown context for containers panel")
|
return errors.New("Unknown context for containers panel")
|
||||||
}
|
}
|
||||||
|
|
@ -142,6 +146,21 @@ func (gui *Gui) renderContainerStats(container *commands.Container) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) renderContainerTop(container *commands.Container) error {
|
||||||
|
mainView := gui.getMainView()
|
||||||
|
mainView.Autoscroll = false
|
||||||
|
mainView.Wrap = false
|
||||||
|
|
||||||
|
return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) {
|
||||||
|
contents, err := container.RenderTop()
|
||||||
|
if err != nil {
|
||||||
|
gui.reRenderString(gui.g, "main", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.reRenderString(gui.g, "main", contents)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderContainerLogs(container *commands.Container) error {
|
func (gui *Gui) renderContainerLogs(container *commands.Container) error {
|
||||||
mainView := gui.getMainView()
|
mainView := gui.getMainView()
|
||||||
mainView.Autoscroll = true
|
mainView.Autoscroll = true
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
|
|
@ -13,11 +14,11 @@ import (
|
||||||
// list panel functions
|
// list panel functions
|
||||||
|
|
||||||
func (gui *Gui) getServiceContexts() []string {
|
func (gui *Gui) getServiceContexts() []string {
|
||||||
return []string{"logs", "stats", "container-config"}
|
return []string{"logs", "stats", "container-config", "top"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getServiceContextTitles() []string {
|
func (gui *Gui) getServiceContextTitles() []string {
|
||||||
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ContainerConfigTitle}
|
return []string{gui.Tr.LogsTitle, gui.Tr.StatsTitle, gui.Tr.ContainerConfigTitle, gui.Tr.TopTitle}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getSelectedService() (*commands.Service, error) {
|
func (gui *Gui) getSelectedService() (*commands.Service, error) {
|
||||||
|
|
@ -95,6 +96,10 @@ func (gui *Gui) handleServiceSelect(g *gocui.Gui, v *gocui.View) error {
|
||||||
if err := gui.renderContainerConfig(service.Container); err != nil {
|
if err := gui.renderContainerConfig(service.Container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case "top":
|
||||||
|
if err := gui.renderServiceTop(service); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return errors.New("Unknown context for services panel")
|
return errors.New("Unknown context for services panel")
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +115,21 @@ func (gui *Gui) renderServiceStats(service *commands.Service) error {
|
||||||
return gui.renderContainerStats(service.Container)
|
return gui.renderContainerStats(service.Container)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) renderServiceTop(service *commands.Service) error {
|
||||||
|
mainView := gui.getMainView()
|
||||||
|
mainView.Autoscroll = false
|
||||||
|
mainView.Wrap = false
|
||||||
|
|
||||||
|
return gui.T.NewTickerTask(time.Second, func(stop chan struct{}) { gui.clearMainView() }, func(stop, notifyStopped chan struct{}) {
|
||||||
|
contents, err := service.RenderTop()
|
||||||
|
if err != nil {
|
||||||
|
gui.reRenderString(gui.g, "main", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.reRenderString(gui.g, "main", contents)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) renderServiceLogs(service *commands.Service) error {
|
func (gui *Gui) renderServiceLogs(service *commands.Service) error {
|
||||||
service, err := gui.getSelectedService()
|
service, err := gui.getSelectedService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ type TranslationSet struct {
|
||||||
ServicesTitle string
|
ServicesTitle string
|
||||||
ContainersTitle string
|
ContainersTitle string
|
||||||
StandaloneContainersTitle string
|
StandaloneContainersTitle string
|
||||||
|
TopTitle string
|
||||||
ImagesTitle string
|
ImagesTitle string
|
||||||
VolumesTitle string
|
VolumesTitle string
|
||||||
NoContainers string
|
NoContainers string
|
||||||
|
|
@ -128,6 +129,7 @@ func englishSet() TranslationSet {
|
||||||
ErrorTitle: "Error",
|
ErrorTitle: "Error",
|
||||||
LogsTitle: "Logs",
|
LogsTitle: "Logs",
|
||||||
ConfigTitle: "Config",
|
ConfigTitle: "Config",
|
||||||
|
TopTitle: "Top",
|
||||||
StatsTitle: "Stats",
|
StatsTitle: "Stats",
|
||||||
CreditsTitle: "About",
|
CreditsTitle: "About",
|
||||||
ContainerConfigTitle: "Container Config",
|
ContainerConfigTitle: "Container Config",
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,11 @@ func renderDisplayableList(items []Displayable, config RenderListConfig) (string
|
||||||
stringArrays = append([][]string{config.Header}, stringArrays...)
|
stringArrays = append([][]string{config.Header}, stringArrays...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return RenderTable(stringArrays)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenderTable takes an array of string arrays and returns a table containing the values
|
||||||
|
func RenderTable(stringArrays [][]string) (string, error) {
|
||||||
if !displayArraysAligned(stringArrays) {
|
if !displayArraysAligned(stringArrays) {
|
||||||
return "", errors.New("Each item must return the same number of strings to display")
|
return "", errors.New("Each item must return the same number of strings to display")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue