support running in non-docker-compose context

This commit is contained in:
Jesse Duffield 2019-06-10 19:29:42 +10:00
parent 87c6208577
commit b02c92da33
6 changed files with 121 additions and 78 deletions

View file

@ -46,13 +46,20 @@ func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Translat
return nil, err return nil, err
} }
inDockerComposeProject := true
err = osCommand.RunCommand(config.UserConfig.CommandTemplates.CheckDockerComposeConfig)
if err != nil {
inDockerComposeProject = false
log.Warn(err.Error())
}
return &DockerCommand{ return &DockerCommand{
Log: log, Log: log,
OSCommand: osCommand, OSCommand: osCommand,
Tr: tr, Tr: tr,
Config: config, Config: config,
Client: cli, Client: cli,
InDockerComposeProject: true, // TODO: determine this at startup InDockerComposeProject: inDockerComposeProject,
ErrorChan: errorChan, ErrorChan: errorChan,
}, nil }, nil
} }

View file

@ -110,12 +110,13 @@ type CommandTemplatesConfig struct {
RebuildService string `yaml:"rebuildService,omitempty"` RebuildService string `yaml:"rebuildService,omitempty"`
// ViewContainerLogs is for viewing the container logs in a subprocess. We have this as a separate command in case you want to show all the logs rather than just tail them for the sake of reducing CPU load when in the lazydocker GUI // ViewContainerLogs is for viewing the container logs in a subprocess. We have this as a separate command in case you want to show all the logs rather than just tail them for the sake of reducing CPU load when in the lazydocker GUI
ViewContainerLogs string `yaml:"viewContainerLogs,omitempty"` ViewContainerLogs string `yaml:"viewContainerLogs,omitempty"`
ContainerLogs string `yaml:"containerLogs,omitempty"` ContainerLogs string `yaml:"containerLogs,omitempty"`
ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"` ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"`
AllLogs string `yaml:"allLogs,omitempty"` AllLogs string `yaml:"allLogs,omitempty"`
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"`
} }
type OSConfig struct { type OSConfig struct {
@ -163,17 +164,18 @@ func GetDefaultConfig() UserConfig {
Reporting: "undetermined", Reporting: "undetermined",
ConfirmOnQuit: false, ConfirmOnQuit: false,
CommandTemplates: CommandTemplatesConfig{ CommandTemplates: CommandTemplatesConfig{
RestartService: "docker-compose restart {{ .Name }}", RestartService: "docker-compose restart {{ .Name }}",
RebuildService: "docker-compose up -d --build {{ .Name }}", RebuildService: "docker-compose up -d --build {{ .Name }}",
DockerCompose: "apdev compose", DockerCompose: "docker-compose",
StopService: "apdev stop {{ .Name }}", StopService: "docker-compose stop {{ .Name }}",
ServiceLogs: "apdev logs {{ .Name }}", ServiceLogs: "docker-compose logs {{ .Name }}",
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}", AllLogs: "docker-compose logs --tail=100",
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}", ViewAllLogs: "docker-compose logs",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}", DockerComposeConfig: "docker-compose config",
AllLogs: "apdev logs --tail=100", CheckDockerComposeConfig: "docker-compose config --quiet",
ViewAllLogs: "apdev logs", ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
DockerComposeConfig: "apdev compose config", ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}",
}, },
OS: GetPlatformDefaultConfig(), OS: GetPlatformDefaultConfig(),
Update: UpdateConfig{ Update: UpdateConfig{

View file

@ -67,6 +67,7 @@ type Gui struct {
waitForIntro sync.WaitGroup waitForIntro sync.WaitGroup
T *tasks.TaskManager T *tasks.TaskManager
ErrorChan chan error ErrorChan chan error
CyclableViews []string
} }
type servicePanelState struct { type servicePanelState struct {
@ -122,9 +123,13 @@ type guiState struct {
// NewGui builds a new gui handler // NewGui builds a new gui handler
func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand *commands.OSCommand, tr *i18n.TranslationSet, config *config.AppConfig, errorChan chan error) (*Gui, error) { func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand *commands.OSCommand, tr *i18n.TranslationSet, config *config.AppConfig, errorChan chan error) (*Gui, error) {
previousView := "containers"
if dockerCommand.InDockerComposeProject {
previousView = "services"
}
initialState := guiState{ initialState := guiState{
PreviousView: "services", PreviousView: previousView,
Platform: *oSCommand.Platform, Platform: *oSCommand.Platform,
Panels: &panelStates{ Panels: &panelStates{
Services: &servicePanelState{SelectedLine: -1, ContextIndex: 0}, Services: &servicePanelState{SelectedLine: -1, ContextIndex: 0},
@ -139,6 +144,11 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
}, },
} }
cyclableViews := []string{"status", "containers", "images", "volumes"}
if dockerCommand.InDockerComposeProject {
cyclableViews = []string{"status", "services", "containers", "images", "volumes"}
}
gui := &Gui{ gui := &Gui{
Log: log, Log: log,
DockerCommand: dockerCommand, DockerCommand: dockerCommand,
@ -150,6 +160,7 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
statusManager: &statusManager{}, statusManager: &statusManager{},
T: tasks.NewTaskManager(log), T: tasks.NewTaskManager(log),
ErrorChan: errorChan, ErrorChan: errorChan,
CyclableViews: cyclableViews,
} }
gui.GenerateSentinelErrors() gui.GenerateSentinelErrors()

View file

@ -78,7 +78,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
if currView != nil { if currView != nil {
viewName := currView.Name() viewName := currView.Name()
usePreviouseView := true usePreviouseView := true
for _, view := range cyclableViews { for _, view := range gui.CyclableViews {
if view == viewName { if view == viewName {
currentCyclebleView = viewName currentCyclebleView = viewName
usePreviouseView = false usePreviouseView = false
@ -92,15 +92,26 @@ func (gui *Gui) layout(g *gocui.Gui) error {
usableSpace := height - 4 usableSpace := height - 4
tallPanels := 4 tallPanels := 3
var vHeights map[string]int
vHeights := map[string]int{ if gui.DockerCommand.InDockerComposeProject {
"status": 3, tallPanels++
"services": usableSpace/tallPanels + usableSpace%tallPanels, vHeights = map[string]int{
"containers": usableSpace / tallPanels, "status": 3,
"images": usableSpace / tallPanels, "services": usableSpace/tallPanels + usableSpace%tallPanels,
"volumes": usableSpace / tallPanels, "containers": usableSpace / tallPanels,
"options": 1, "images": usableSpace / tallPanels,
"volumes": usableSpace / tallPanels,
"options": 1,
}
} else {
vHeights = map[string]int{
"status": 3,
"containers": usableSpace/tallPanels + usableSpace%tallPanels,
"images": usableSpace / tallPanels,
"volumes": usableSpace / tallPanels,
"options": 1,
}
} }
if height < 28 { if height < 28 {
@ -110,12 +121,14 @@ func (gui *Gui) layout(g *gocui.Gui) error {
} }
vHeights = map[string]int{ vHeights = map[string]int{
"status": defaultHeight, "status": defaultHeight,
"services": defaultHeight,
"containers": defaultHeight, "containers": defaultHeight,
"images": defaultHeight, "images": defaultHeight,
"volumes": defaultHeight, "volumes": defaultHeight,
"options": defaultHeight, "options": defaultHeight,
} }
if gui.DockerCommand.InDockerComposeProject {
vHeights["services"] = defaultHeight
}
vHeights[currentCyclebleView] = height - defaultHeight*tallPanels - 1 vHeights[currentCyclebleView] = height - defaultHeight*tallPanels - 1
} }
@ -148,25 +161,30 @@ func (gui *Gui) layout(g *gocui.Gui) error {
v.FgColor = gocui.ColorWhite v.FgColor = gocui.ColorWhite
} }
servicesView, err := g.SetViewBeneath("services", "status", vHeights["services"]) var servicesView *gocui.View
if err != nil { aboveContainersView := "status"
if err.Error() != "unknown view" { if gui.DockerCommand.InDockerComposeProject {
return err aboveContainersView = "services"
} servicesView, err = g.SetViewBeneath("services", "status", vHeights["services"])
servicesView.Highlight = true if err != nil {
servicesView.Title = gui.Tr.ServicesTitle if err.Error() != "unknown view" {
servicesView.FgColor = gocui.ColorWhite return err
}
servicesView.Highlight = true
servicesView.Title = gui.Tr.ServicesTitle
servicesView.FgColor = gocui.ColorWhite
gui.focusPoint(0, gui.State.Panels.Services.SelectedLine, len(gui.DockerCommand.Services), servicesView) gui.focusPoint(0, gui.State.Panels.Services.SelectedLine, len(gui.DockerCommand.Services), servicesView)
}
} }
containersView, err := g.SetViewBeneath("containers", "services", vHeights["containers"]) containersView, err := g.SetViewBeneath("containers", aboveContainersView, vHeights["containers"])
if err != nil { if err != nil {
if err.Error() != "unknown view" { if err.Error() != "unknown view" {
return err return err
} }
containersView.Highlight = true containersView.Highlight = true
if gui.Config.UserConfig.Gui.ShowAllContainers { if gui.Config.UserConfig.Gui.ShowAllContainers || !gui.DockerCommand.InDockerComposeProject {
containersView.Title = gui.Tr.ContainersTitle containersView.Title = gui.Tr.ContainersTitle
} else { } else {
containersView.Title = gui.Tr.StandaloneContainersTitle containersView.Title = gui.Tr.StandaloneContainersTitle
@ -255,6 +273,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
lineCount int lineCount int
} }
// TODO: find out if I should add the services view to this.
listViews := map[*gocui.View]listViewState{ listViews := map[*gocui.View]listViewState{
containersView: {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.DockerCommand.Containers)}, containersView: {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.DockerCommand.Containers)},
imagesView: {selectedLine: gui.State.Panels.Images.SelectedLine, lineCount: len(gui.DockerCommand.Images)}, imagesView: {selectedLine: gui.State.Panels.Images.SelectedLine, lineCount: len(gui.DockerCommand.Images)},

View file

@ -9,11 +9,17 @@ import (
) )
func (gui *Gui) getStatusContexts() []string { func (gui *Gui) getStatusContexts() []string {
return []string{"logs", "credits", "config"} if gui.DockerCommand.InDockerComposeProject {
return []string{"logs", "credits", "config"}
}
return []string{"credits"}
} }
func (gui *Gui) getStatusContextTitles() []string { func (gui *Gui) getStatusContextTitles() []string {
return []string{gui.Tr.LogsTitle, gui.Tr.CreditsTitle, gui.Tr.ConfigTitle} if gui.DockerCommand.InDockerComposeProject {
return []string{gui.Tr.LogsTitle, gui.Tr.CreditsTitle, gui.Tr.ConfigTitle}
}
return []string{gui.Tr.CreditsTitle}
} }
func (gui *Gui) refreshStatus() error { func (gui *Gui) refreshStatus() error {
@ -71,20 +77,20 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error {
} }
func (gui *Gui) renderCredits() error { func (gui *Gui) renderCredits() error {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Wrap = true
dashboardString := strings.Join(
[]string{
lazydockerTitle(),
"Copyright (c) 2019 Jesse Duffield",
"Keybindings: https://github.com/jesseduffield/lazydocker/blob/master/docs/keybindings",
"Config Options: https://github.com/jesseduffield/lazydocker/blob/master/docs/Config.md",
"Raise an Issue: https://github.com/jesseduffield/lazydocker/issues",
}, "\n\n")
go gui.T.NewTask(func(stop chan struct{}) { go gui.T.NewTask(func(stop chan struct{}) {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Wrap = true
dashboardString := strings.Join(
[]string{
lazydockerTitle(),
"Copyright (c) 2019 Jesse Duffield",
"Keybindings: https://github.com/jesseduffield/lazydocker/blob/master/docs/keybindings",
"Config Options: https://github.com/jesseduffield/lazydocker/blob/master/docs/Config.md",
"Raise an Issue: https://github.com/jesseduffield/lazydocker/issues",
}, "\n\n")
gui.renderString(gui.g, "main", dashboardString) gui.renderString(gui.g, "main", dashboardString)
}) })
@ -92,11 +98,11 @@ func (gui *Gui) renderCredits() error {
} }
func (gui *Gui) renderAllLogs() error { func (gui *Gui) renderAllLogs() error {
mainView := gui.getMainView()
mainView.Autoscroll = true
mainView.Wrap = true
go gui.T.NewTask(func(stop chan struct{}) { go gui.T.NewTask(func(stop chan struct{}) {
mainView := gui.getMainView()
mainView.Autoscroll = true
mainView.Wrap = true
gui.clearMainView() gui.clearMainView()
cmd := gui.OSCommand.RunCustomCommand(gui.Config.UserConfig.CommandTemplates.AllLogs) cmd := gui.OSCommand.RunCustomCommand(gui.Config.UserConfig.CommandTemplates.AllLogs)
@ -121,11 +127,11 @@ func (gui *Gui) renderAllLogs() error {
} }
func (gui *Gui) renderDockerComposeConfig() error { func (gui *Gui) renderDockerComposeConfig() error {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Wrap = true
go gui.T.NewTask(func(stop chan struct{}) { go gui.T.NewTask(func(stop chan struct{}) {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Wrap = true
config := gui.DockerCommand.DockerComposeConfig() config := gui.DockerCommand.DockerComposeConfig()
gui.renderString(gui.g, "main", config) gui.renderString(gui.g, "main", config)
}) })

View file

@ -10,8 +10,6 @@ import (
"github.com/spkg/bom" "github.com/spkg/bom"
) )
var cyclableViews = []string{"status", "services", "containers", "images", "volumes"}
func (gui *Gui) refreshSidePanels(g *gocui.Gui) error { func (gui *Gui) refreshSidePanels(g *gocui.Gui) error {
// not refreshing containers and services here given that we do it every few milliseconds anyway // not refreshing containers and services here given that we do it every few milliseconds anyway
if err := gui.refreshImages(); err != nil { if err := gui.refreshImages(); err != nil {
@ -26,16 +24,16 @@ func (gui *Gui) refreshSidePanels(g *gocui.Gui) error {
func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error {
var focusedViewName string var focusedViewName string
if v == nil || v.Name() == cyclableViews[len(cyclableViews)-1] { if v == nil || v.Name() == gui.CyclableViews[len(gui.CyclableViews)-1] {
focusedViewName = cyclableViews[0] focusedViewName = gui.CyclableViews[0]
} else { } else {
viewName := v.Name() viewName := v.Name()
for i := range cyclableViews { for i := range gui.CyclableViews {
if viewName == cyclableViews[i] { if viewName == gui.CyclableViews[i] {
focusedViewName = cyclableViews[i+1] focusedViewName = gui.CyclableViews[i+1]
break break
} }
if i == len(cyclableViews)-1 { if i == len(gui.CyclableViews)-1 {
gui.Log.Info("not in list of views") gui.Log.Info("not in list of views")
return nil return nil
} }
@ -51,16 +49,16 @@ func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
var focusedViewName string var focusedViewName string
if v == nil || v.Name() == cyclableViews[0] { if v == nil || v.Name() == gui.CyclableViews[0] {
focusedViewName = cyclableViews[len(cyclableViews)-1] focusedViewName = gui.CyclableViews[len(gui.CyclableViews)-1]
} else { } else {
viewName := v.Name() viewName := v.Name()
for i := range cyclableViews { for i := range gui.CyclableViews {
if viewName == cyclableViews[i] { if viewName == gui.CyclableViews[i] {
focusedViewName = cyclableViews[i-1] focusedViewName = gui.CyclableViews[i-1]
break break
} }
if i == len(cyclableViews)-1 { if i == len(gui.CyclableViews)-1 {
gui.Log.Info("not in list of views") gui.Log.Info("not in list of views")
return nil return nil
} }