From d3e84881bb9d746867059560d259934eb84f22dd Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Wed, 11 May 2022 19:38:41 +1000 Subject: [PATCH 1/4] remove custom command from default config given that it is now inbuilt --- docs/Config.md | 19 +++++++++++++------ pkg/config/app_config.go | 14 ++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/Config.md b/docs/Config.md index 56af7d2b..485d28e3 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -46,12 +46,6 @@ commandTemplates: dockerComposeConfig: '{{ .DockerCompose }} config' checkDockerComposeConfig: '{{ .DockerCompose }} config --quiet' serviceTop: '{{ .DockerCompose }} top {{ .Service.Name }}' -customCommands: - containers: - - name: bash - attach: true - command: "docker exec -it {{ .Container.ID }} /bin/sh -c 'eval $(grep ^$(id -un): /etc/passwd | cut -d : -f 7-)'" - serviceNames: [] oS: openCommand: open {{filename}} openLinkCommand: open {{link}} @@ -84,3 +78,16 @@ The available attributes are: - bold - reverse # useful for high-contrast - underline + +## Custom Commands + +You can add custom commands like so: + +```yaml +customCommands: + containers: + - name: bash + attach: true + command: 'docker exec -it {{ .Container.ID }} bash' + serviceNames: [] +``` diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index 1653b253..a537157d 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -339,16 +339,10 @@ func GetDefaultConfig() UserConfig { ViewContainerLogs: "docker logs --timestamps --follow --since=60m {{ .Container.ID }}", }, CustomCommands: CustomCommands{ - Containers: []CustomCommand{ - { - Name: "bash", - Command: "docker exec -it {{ .Container.ID }} /bin/sh -c 'eval $(grep ^$(id -un): /etc/passwd | cut -d : -f 7-)'", - Attach: true, - }, - }, - Services: []CustomCommand{}, - Images: []CustomCommand{}, - Volumes: []CustomCommand{}, + Containers: []CustomCommand{}, + Services: []CustomCommand{}, + Images: []CustomCommand{}, + Volumes: []CustomCommand{}, }, BulkCommands: CustomCommands{ Services: []CustomCommand{ From 62be3d99243d03db102d409f0472036020dc76d1 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Wed, 11 May 2022 19:38:53 +1000 Subject: [PATCH 2/4] allow forcing an image removal --- pkg/gui/images_panel.go | 17 +++- pkg/i18n/english.go | 198 ++++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 99 deletions(-) diff --git a/pkg/gui/images_panel.go b/pkg/gui/images_panel.go index e28195fd..0d5aba6c 100644 --- a/pkg/gui/images_panel.go +++ b/pkg/gui/images_panel.go @@ -212,17 +212,30 @@ func (gui *Gui) handleImagesRemoveMenu(g *gocui.Gui, v *gocui.View) error { shortSha := Image.ID[7:17] + // TODO: have a way of toggling in a menu instead of showing each permutation as a separate menu item options := []*removeImageOption{ { description: gui.Tr.Remove, command: "docker image rm " + shortSha, - configOptions: types.ImageRemoveOptions{PruneChildren: true}, + configOptions: types.ImageRemoveOptions{PruneChildren: true, Force: false}, runCommand: true, }, { description: gui.Tr.RemoveWithoutPrune, command: "docker image rm --no-prune " + shortSha, - configOptions: types.ImageRemoveOptions{PruneChildren: false}, + configOptions: types.ImageRemoveOptions{PruneChildren: false, Force: false}, + runCommand: true, + }, + { + description: gui.Tr.RemoveWithForce, + command: "docker image rm --force " + shortSha, + configOptions: types.ImageRemoveOptions{PruneChildren: true, Force: true}, + runCommand: true, + }, + { + description: gui.Tr.RemoveWithoutPruneWithForce, + command: "docker image rm --no-prune --force " + shortSha, + configOptions: types.ImageRemoveOptions{PruneChildren: false, Force: true}, runCommand: true, }, { diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 608e384a..b7c53864 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -26,65 +26,67 @@ type TranslationSet struct { CannotAccessDockerSocketError string CannotKillChildError string - Donate string - Cancel string - CustomCommandTitle string - BulkCommandTitle string - Remove string - HideStopped string - ForceRemove string - RemoveWithVolumes string - MustForceToRemoveContainer string - Confirm string - Return string - FocusMain string - StopContainer string - RestartingStatus string - StoppingStatus string - RemovingStatus string - RunningCustomCommandStatus string - RunningBulkCommandStatus string - RemoveService string - Stop string - Restart string - Rebuild string - Recreate string - PreviousContext string - NextContext string - Attach string - ViewLogs string - ServicesTitle string - ContainersTitle string - StandaloneContainersTitle string - TopTitle string - ImagesTitle string - VolumesTitle string - NoContainers string - NoContainer string - NoImages string - NoVolumes string - RemoveImage string - RemoveVolume string - RemoveWithoutPrune string - PruneImages string - PruneContainers string - PruneVolumes string - ConfirmPruneContainers string - ConfirmStopContainers string - ConfirmRemoveContainers string - ConfirmPruneImages string - ConfirmPruneVolumes string - PruningStatus string - StopService string - PressEnterToReturn string - StopAllContainers string - RemoveAllContainers string - ViewRestartOptions string - ExecShell string - RunCustomCommand string - ViewBulkCommands string - OpenInBrowser string - SortContainersByState string + Donate string + Cancel string + CustomCommandTitle string + BulkCommandTitle string + Remove string + HideStopped string + ForceRemove string + RemoveWithVolumes string + MustForceToRemoveContainer string + Confirm string + Return string + FocusMain string + StopContainer string + RestartingStatus string + StoppingStatus string + RemovingStatus string + RunningCustomCommandStatus string + RunningBulkCommandStatus string + RemoveService string + Stop string + Restart string + Rebuild string + Recreate string + PreviousContext string + NextContext string + Attach string + ViewLogs string + ServicesTitle string + ContainersTitle string + StandaloneContainersTitle string + TopTitle string + ImagesTitle string + VolumesTitle string + NoContainers string + NoContainer string + NoImages string + NoVolumes string + RemoveImage string + RemoveVolume string + RemoveWithoutPrune string + RemoveWithoutPruneWithForce string + RemoveWithForce string + PruneImages string + PruneContainers string + PruneVolumes string + ConfirmPruneContainers string + ConfirmStopContainers string + ConfirmRemoveContainers string + ConfirmPruneImages string + ConfirmPruneVolumes string + PruningStatus string + StopService string + PressEnterToReturn string + StopAllContainers string + RemoveAllContainers string + ViewRestartOptions string + ExecShell string + RunCustomCommand string + ViewBulkCommands string + OpenInBrowser string + SortContainersByState string LogsTitle string ConfigTitle string @@ -124,44 +126,46 @@ func englishSet() TranslationSet { Donate: "Donate", Confirm: "Confirm", - Return: "return", - FocusMain: "focus main panel", - Navigate: "navigate", - Execute: "execute", - Close: "close", - Menu: "menu", - MenuTitle: "Menu", - Scroll: "scroll", - OpenConfig: "open lazydocker config", - EditConfig: "edit lazydocker config", - Cancel: "cancel", - Remove: "remove", - HideStopped: "hide/show stopped containers", - ForceRemove: "force remove", - RemoveWithVolumes: "remove with volumes", - RemoveService: "remove containers", - Stop: "stop", - Restart: "restart", - Rebuild: "rebuild", - Recreate: "recreate", - PreviousContext: "previous tab", - NextContext: "next tab", - Attach: "attach", - ViewLogs: "view logs", - RemoveImage: "remove image", - RemoveVolume: "remove volume", - RemoveWithoutPrune: "remove without deleting untagged parents", - PruneContainers: "prune exited containers", - PruneVolumes: "prune unused volumes", - PruneImages: "prune unused images", - StopAllContainers: "stop all containers", - RemoveAllContainers: "remove all containers (forced)", - ViewRestartOptions: "view restart options", - ExecShell: "exec shell", - RunCustomCommand: "run predefined custom command", - ViewBulkCommands: "view bulk commands", - OpenInBrowser: "open in browser (first port is http)", - SortContainersByState: "sort containers by state", + Return: "return", + FocusMain: "focus main panel", + Navigate: "navigate", + Execute: "execute", + Close: "close", + Menu: "menu", + MenuTitle: "Menu", + Scroll: "scroll", + OpenConfig: "open lazydocker config", + EditConfig: "edit lazydocker config", + Cancel: "cancel", + Remove: "remove", + HideStopped: "hide/show stopped containers", + ForceRemove: "force remove", + RemoveWithVolumes: "remove with volumes", + RemoveService: "remove containers", + Stop: "stop", + Restart: "restart", + Rebuild: "rebuild", + Recreate: "recreate", + PreviousContext: "previous tab", + NextContext: "next tab", + Attach: "attach", + ViewLogs: "view logs", + RemoveImage: "remove image", + RemoveVolume: "remove volume", + RemoveWithoutPrune: "remove without deleting untagged parents", + RemoveWithoutPruneWithForce: "remove (forced) without deleting untagged parents", + RemoveWithForce: "remove (forced)", + PruneContainers: "prune exited containers", + PruneVolumes: "prune unused volumes", + PruneImages: "prune unused images", + StopAllContainers: "stop all containers", + RemoveAllContainers: "remove all containers (forced)", + ViewRestartOptions: "view restart options", + ExecShell: "exec shell", + RunCustomCommand: "run predefined custom command", + ViewBulkCommands: "view bulk commands", + OpenInBrowser: "open in browser (first port is http)", + SortContainersByState: "sort containers by state", GlobalTitle: "Global", MainTitle: "Main", From b4509fb45ee8cc212bbcd026e67333763fcc33e8 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Wed, 11 May 2022 19:41:53 +1000 Subject: [PATCH 3/4] add TODO's for using the docker SDK --- pkg/commands/container.go | 1 + pkg/config/app_config.go | 3 ++- pkg/gui/containers_panel.go | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/commands/container.go b/pkg/commands/container.go index 61201318..c7d425a2 100644 --- a/pkg/commands/container.go +++ b/pkg/commands/container.go @@ -197,6 +197,7 @@ func (c *Container) Attach() (*exec.Cmd, error) { } c.Log.Warn(fmt.Sprintf("attaching to container %s", c.Name)) + // TODO: use SDK cmd := c.OSCommand.PrepareSubProcess("docker", "attach", "--sig-proxy=false", c.ID) return cmd, nil } diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index a537157d..b9aef7ce 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -336,7 +336,8 @@ func GetDefaultConfig() UserConfig { DockerComposeConfig: "{{ .DockerCompose }} config", CheckDockerComposeConfig: "{{ .DockerCompose }} config --quiet", ServiceTop: "{{ .DockerCompose }} top {{ .Service.Name }}", - ViewContainerLogs: "docker logs --timestamps --follow --since=60m {{ .Container.ID }}", + // TODO: use SDK + ViewContainerLogs: "docker logs --timestamps --follow --since=60m {{ .Container.ID }}", }, CustomCommands: CustomCommands{ Containers: []CustomCommand{}, diff --git a/pkg/gui/containers_panel.go b/pkg/gui/containers_panel.go index 3df23c75..97caae31 100644 --- a/pkg/gui/containers_panel.go +++ b/pkg/gui/containers_panel.go @@ -569,6 +569,8 @@ func (gui *Gui) handleContainersExecShell(g *gocui.Gui, v *gocui.View) error { commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{ Container: container, }) + + // TODO: use SDK resolvedCommand := utils.ApplyTemplate("docker exec -it {{ .Container.ID }} /bin/sh -c 'eval $(grep ^$(id -un): /etc/passwd | cut -d : -f 7-)'", commandObject) // attach and return the subprocess error cmd := gui.OSCommand.ExecutableFromString(resolvedCommand) From 2f08e0942afb26ddffd82b0ba1fc61ea3b27c15c Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Wed, 11 May 2022 19:48:11 +1000 Subject: [PATCH 4/4] support starting a service --- docs/Config.md | 1 + pkg/commands/service.go | 10 ++++++++++ pkg/config/app_config.go | 4 ++++ pkg/gui/keybindings.go | 7 +++++++ pkg/gui/services_panel.go | 15 +++++++++++++++ pkg/i18n/english.go | 4 ++++ 6 files changed, 41 insertions(+) diff --git a/docs/Config.md b/docs/Config.md index 485d28e3..1636b210 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -34,6 +34,7 @@ logs: commandTemplates: dockerCompose: docker-compose restartService: '{{ .DockerCompose }} restart {{ .Service.Name }}' + startService: '{{ .DockerCompose }} start {{ .Service.Name }}' stopService: '{{ .DockerCompose }} stop {{ .Service.Name }}' serviceLogs: '{{ .DockerCompose }} logs --since=60m --follow {{ .Service.Name }}' viewServiceLogs: '{{ .DockerCompose }} logs --follow {{ .Service.Name }}' diff --git a/pkg/commands/service.go b/pkg/commands/service.go index ca8af1db..269e119f 100644 --- a/pkg/commands/service.go +++ b/pkg/commands/service.go @@ -56,6 +56,16 @@ func (s *Service) Restart() error { return s.OSCommand.RunCommand(command) } +// Restart starts the service +func (s *Service) Start() error { + templateString := s.OSCommand.Config.UserConfig.CommandTemplates.StartService + command := utils.ApplyTemplate( + templateString, + s.DockerCommand.NewCommandObject(CommandObject{Service: s}), + ) + return s.OSCommand.RunCommand(command) +} + // Attach attaches to the service func (s *Service) Attach() (*exec.Cmd, error) { return s.Container.Attach() diff --git a/pkg/config/app_config.go b/pkg/config/app_config.go index b9aef7ce..5526feb7 100644 --- a/pkg/config/app_config.go +++ b/pkg/config/app_config.go @@ -121,6 +121,9 @@ type CommandTemplatesConfig struct { // .Service.Name }} RestartService string `yaml:"restartService,omitempty"` + // StartService is just like the above but for starting + StartService string `yaml:"startService,omitempty"` + // DockerCompose is for your docker-compose command. You may want to combine a // few different docker-compose.yml files together, in which case you can set // this to "docker-compose -f foo/docker-compose.yml -f @@ -326,6 +329,7 @@ func GetDefaultConfig() UserConfig { CommandTemplates: CommandTemplatesConfig{ DockerCompose: "docker-compose", RestartService: "{{ .DockerCompose }} restart {{ .Service.Name }}", + StartService: "{{ .DockerCompose }} start {{ .Service.Name }}", RebuildService: "{{ .DockerCompose }} up -d --build {{ .Service.Name }}", RecreateService: "{{ .DockerCompose }} up -d --force-recreate {{ .Service.Name }}", StopService: "{{ .DockerCompose }} stop {{ .Service.Name }}", diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index cfb9c42f..875a26e9 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -297,6 +297,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { Handler: gui.handleServiceRestart, Description: gui.Tr.Restart, }, + { + ViewName: "services", + Key: 'S', + Modifier: gocui.ModNone, + Handler: gui.handleServiceStart, + Description: gui.Tr.Start, + }, { ViewName: "services", Key: 'a', diff --git a/pkg/gui/services_panel.go b/pkg/gui/services_panel.go index d311afce..da7a8b6e 100644 --- a/pkg/gui/services_panel.go +++ b/pkg/gui/services_panel.go @@ -251,6 +251,21 @@ func (gui *Gui) handleServiceRestart(g *gocui.Gui, v *gocui.View) error { }) } +func (gui *Gui) handleServiceStart(g *gocui.Gui, v *gocui.View) error { + service, err := gui.getSelectedService() + if err != nil { + return nil + } + + return gui.WithWaitingStatus(gui.Tr.StartingStatus, func() error { + if err := service.Start(); err != nil { + return gui.createErrorPanel(gui.g, err.Error()) + } + + return nil + }) +} + func (gui *Gui) handleServiceAttach(g *gocui.Gui, v *gocui.View) error { service, err := gui.getSelectedService() if err != nil { diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index b7c53864..5dbfdb5c 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -40,6 +40,7 @@ type TranslationSet struct { FocusMain string StopContainer string RestartingStatus string + StartingStatus string StoppingStatus string RemovingStatus string RunningCustomCommandStatus string @@ -47,6 +48,7 @@ type TranslationSet struct { RemoveService string Stop string Restart string + Start string Rebuild string Recreate string PreviousContext string @@ -108,6 +110,7 @@ func englishSet() TranslationSet { PruningStatus: "pruning", RemovingStatus: "removing", RestartingStatus: "restarting", + StartingStatus: "starting", StoppingStatus: "stopping", RunningCustomCommandStatus: "running custom command", RunningBulkCommandStatus: "running bulk command", @@ -144,6 +147,7 @@ func englishSet() TranslationSet { RemoveService: "remove containers", Stop: "stop", Restart: "restart", + Start: "start", Rebuild: "rebuild", Recreate: "recreate", PreviousContext: "previous tab",