mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-22 07:11:01 +00:00
support custom commands in services and containers panel
This commit is contained in:
parent
90a04add32
commit
2474c0b34e
6 changed files with 138 additions and 4 deletions
|
|
@ -82,6 +82,7 @@ type UserConfig struct {
|
|||
Reporting string `yaml:"reporting,omitempty"`
|
||||
ConfirmOnQuit bool `yaml:"confirmOnQuit,omitempty"`
|
||||
CommandTemplates CommandTemplatesConfig `yaml:"commandTemplates,omitempty"`
|
||||
CustomCommands CustomCommands `yaml:"customCommands,omitempty"`
|
||||
OS OSConfig `yaml:"oS,omitempty"`
|
||||
Update UpdateConfig `yaml:"update,omitempty"`
|
||||
Stats StatsConfig `yaml:"stats,omitempty"`
|
||||
|
|
@ -146,6 +147,16 @@ type StatsConfig struct {
|
|||
MaxDuration time.Duration `yaml:"maxDuration,omitempty"`
|
||||
}
|
||||
|
||||
type CustomCommands struct {
|
||||
Containers []CustomCommand `yaml:"containers,omitempty"`
|
||||
Services []CustomCommand `yaml:"services,omitempty"`
|
||||
}
|
||||
|
||||
type CustomCommand struct {
|
||||
Attach bool
|
||||
Command string
|
||||
}
|
||||
|
||||
// GetDefaultConfig returns the application default configuration
|
||||
// NOTE: do not default a boolean to true, because false is the boolean zero value and this will be ignored when parsing the user's config
|
||||
func GetDefaultConfig() UserConfig {
|
||||
|
|
@ -178,6 +189,15 @@ func GetDefaultConfig() UserConfig {
|
|||
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .Container.ID }}",
|
||||
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .Container.ID }}",
|
||||
},
|
||||
CustomCommands: CustomCommands{
|
||||
Containers: []CustomCommand{
|
||||
{
|
||||
Attach: true,
|
||||
Command: "docker exec -it {{ .Container.ID }} /bin/bash",
|
||||
},
|
||||
},
|
||||
Services: []CustomCommand{},
|
||||
},
|
||||
OS: GetPlatformDefaultConfig(),
|
||||
Update: UpdateConfig{
|
||||
Method: "never",
|
||||
|
|
|
|||
|
|
@ -497,3 +497,18 @@ func (gui *Gui) handleContainerViewLogs(g *gocui.Gui, v *gocui.View) error {
|
|||
gui.SubProcess = c
|
||||
return gui.Errors.ErrSubProcess
|
||||
}
|
||||
|
||||
func (gui *Gui) handleContainersCustomCommand(g *gocui.Gui, v *gocui.View) error {
|
||||
container, err := gui.getSelectedContainer()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{
|
||||
Container: container,
|
||||
})
|
||||
|
||||
customCommands := gui.Config.UserConfig.CustomCommands.Containers
|
||||
|
||||
return gui.createCustomCommandMenu(customCommands, commandObject)
|
||||
}
|
||||
|
|
|
|||
62
pkg/gui/custom_commands.go
Normal file
62
pkg/gui/custom_commands.go
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazydocker/pkg/commands"
|
||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||
"github.com/jesseduffield/lazydocker/pkg/utils"
|
||||
)
|
||||
|
||||
type customCommandOption struct {
|
||||
customCommand config.CustomCommand
|
||||
description string
|
||||
command string
|
||||
runCommand bool
|
||||
attach bool
|
||||
}
|
||||
|
||||
// GetDisplayStrings is a function.
|
||||
func (r *customCommandOption) GetDisplayStrings(isFocused bool) []string {
|
||||
return []string{r.description}
|
||||
}
|
||||
|
||||
func (gui *Gui) createCustomCommandMenu(customCommands []config.CustomCommand, commandObject commands.CommandObject) error {
|
||||
options := make([]*customCommandOption, len(customCommands)+1)
|
||||
for i, command := range customCommands {
|
||||
resolvedCommand := utils.ApplyTemplate(command.Command, commandObject)
|
||||
|
||||
options[i] = &customCommandOption{
|
||||
customCommand: command,
|
||||
description: resolvedCommand,
|
||||
command: resolvedCommand,
|
||||
runCommand: true,
|
||||
attach: command.Attach,
|
||||
}
|
||||
}
|
||||
options[len(options)-1] = &customCommandOption{
|
||||
description: gui.Tr.Cancel,
|
||||
runCommand: false,
|
||||
}
|
||||
|
||||
handleMenuPress := func(index int) error {
|
||||
option := options[index]
|
||||
if !option.runCommand {
|
||||
return nil
|
||||
}
|
||||
|
||||
// if we have a command for attaching, we attach and return the subprocess error
|
||||
if option.customCommand.Attach {
|
||||
cmd := gui.OSCommand.ExecutableFromString(option.command)
|
||||
gui.SubProcess = cmd
|
||||
return gui.Errors.ErrSubProcess
|
||||
}
|
||||
|
||||
return gui.WithWaitingStatus(gui.Tr.RunningCustomCommandStatus, func() error {
|
||||
if err := gui.OSCommand.RunCommand(option.command); err != nil {
|
||||
return gui.createErrorPanel(gui.g, err.Error())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
return gui.createMenu("", options, len(options), handleMenuPress)
|
||||
}
|
||||
|
|
@ -228,6 +228,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||
Handler: gui.handleContainerViewLogs,
|
||||
Description: gui.Tr.ViewLogs,
|
||||
},
|
||||
{
|
||||
ViewName: "containers",
|
||||
Key: 'c',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleContainersCustomCommand,
|
||||
Description: gui.Tr.RunCustomCommand,
|
||||
},
|
||||
{
|
||||
ViewName: "services",
|
||||
Key: 'd',
|
||||
|
|
@ -284,6 +291,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||
Handler: gui.handleServiceRestartMenu,
|
||||
Description: gui.Tr.ViewRestartOptions,
|
||||
},
|
||||
{
|
||||
ViewName: "services",
|
||||
Key: 'c',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleServicesCustomCommand,
|
||||
Description: gui.Tr.RunCustomCommand,
|
||||
},
|
||||
{
|
||||
ViewName: "images",
|
||||
Key: '[',
|
||||
|
|
|
|||
|
|
@ -344,3 +344,22 @@ func (gui *Gui) createCommandMenu(options []*commandOption, status string) error
|
|||
|
||||
return gui.createMenu("", options, len(options), handleMenuPress)
|
||||
}
|
||||
|
||||
func (gui *Gui) handleServicesCustomCommand(g *gocui.Gui, v *gocui.View) error {
|
||||
service, err := gui.getSelectedService()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
commandObject := gui.DockerCommand.NewCommandObject(commands.CommandObject{
|
||||
Service: service,
|
||||
Container: service.Container,
|
||||
})
|
||||
|
||||
customCommands := gui.Config.UserConfig.CustomCommands.Services
|
||||
if service.Container != nil {
|
||||
customCommands = append(customCommands, gui.Config.UserConfig.CustomCommands.Containers...)
|
||||
}
|
||||
|
||||
return gui.createCustomCommandMenu(customCommands, commandObject)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ type TranslationSet struct {
|
|||
RestartingStatus string
|
||||
StoppingStatus string
|
||||
RemovingStatus string
|
||||
RunningCustomCommandStatus string
|
||||
RemoveService string
|
||||
Stop string
|
||||
Restart string
|
||||
|
|
@ -62,6 +63,7 @@ type TranslationSet struct {
|
|||
StopService string
|
||||
PressEnterToReturn string
|
||||
ViewRestartOptions string
|
||||
RunCustomCommand string
|
||||
|
||||
LogsTitle string
|
||||
ConfigTitle string
|
||||
|
|
@ -72,10 +74,11 @@ type TranslationSet struct {
|
|||
|
||||
func englishSet() TranslationSet {
|
||||
return TranslationSet{
|
||||
PruningStatus: "pruning",
|
||||
RemovingStatus: "removing",
|
||||
RestartingStatus: "restarting",
|
||||
StoppingStatus: "stopping",
|
||||
PruningStatus: "pruning",
|
||||
RemovingStatus: "removing",
|
||||
RestartingStatus: "restarting",
|
||||
StoppingStatus: "stopping",
|
||||
RunningCustomCommandStatus: "running custom command",
|
||||
|
||||
RunningSubprocess: "running subprocess",
|
||||
NoViewMachingNewLineFocusedSwitchStatement: "No view matching newLineFocused switch statement",
|
||||
|
|
@ -110,6 +113,7 @@ func englishSet() TranslationSet {
|
|||
PruneVolumes: "prune unused volumes",
|
||||
PruneImages: "prune unused images",
|
||||
ViewRestartOptions: "view restart options",
|
||||
RunCustomCommand: "run predefined custom command",
|
||||
|
||||
AnonymousReportingTitle: "Help make lazydocker better",
|
||||
AnonymousReportingPrompt: "Would you like to enable anonymous reporting data to help improve lazydocker? (enter/esc)",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue