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
}
inDockerComposeProject := true
err = osCommand.RunCommand(config.UserConfig.CommandTemplates.CheckDockerComposeConfig)
if err != nil {
inDockerComposeProject = false
log.Warn(err.Error())
}
return &DockerCommand{
Log: log,
OSCommand: osCommand,
Tr: tr,
Config: config,
Client: cli,
InDockerComposeProject: true, // TODO: determine this at startup
InDockerComposeProject: inDockerComposeProject,
ErrorChan: errorChan,
}, nil
}

View file

@ -110,12 +110,13 @@ type CommandTemplatesConfig struct {
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 string `yaml:"viewContainerLogs,omitempty"`
ContainerLogs string `yaml:"containerLogs,omitempty"`
ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"`
AllLogs string `yaml:"allLogs,omitempty"`
ViewAllLogs string `yaml:"viewAlLogs,omitempty"`
DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"`
ViewContainerLogs string `yaml:"viewContainerLogs,omitempty"`
ContainerLogs string `yaml:"containerLogs,omitempty"`
ContainerTTYLogs string `yaml:"containerTTYLogs,omitempty"`
AllLogs string `yaml:"allLogs,omitempty"`
ViewAllLogs string `yaml:"viewAlLogs,omitempty"`
DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"`
CheckDockerComposeConfig string `yaml:"checkDockerComposeConfig,omitempty"`
}
type OSConfig struct {
@ -163,17 +164,18 @@ func GetDefaultConfig() UserConfig {
Reporting: "undetermined",
ConfirmOnQuit: false,
CommandTemplates: CommandTemplatesConfig{
RestartService: "docker-compose restart {{ .Name }}",
RebuildService: "docker-compose up -d --build {{ .Name }}",
DockerCompose: "apdev compose",
StopService: "apdev stop {{ .Name }}",
ServiceLogs: "apdev logs {{ .Name }}",
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}",
AllLogs: "apdev logs --tail=100",
ViewAllLogs: "apdev logs",
DockerComposeConfig: "apdev compose config",
RestartService: "docker-compose restart {{ .Name }}",
RebuildService: "docker-compose up -d --build {{ .Name }}",
DockerCompose: "docker-compose",
StopService: "docker-compose stop {{ .Name }}",
ServiceLogs: "docker-compose logs {{ .Name }}",
AllLogs: "docker-compose logs --tail=100",
ViewAllLogs: "docker-compose logs",
DockerComposeConfig: "docker-compose config",
CheckDockerComposeConfig: "docker-compose config --quiet",
ContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ViewContainerLogs: "docker logs --timestamps --follow --tail=100 {{ .ID }}",
ContainerTTYLogs: "docker logs --follow --tail=100 {{ .ID }}",
},
OS: GetPlatformDefaultConfig(),
Update: UpdateConfig{

View file

@ -67,6 +67,7 @@ type Gui struct {
waitForIntro sync.WaitGroup
T *tasks.TaskManager
ErrorChan chan error
CyclableViews []string
}
type servicePanelState struct {
@ -122,9 +123,13 @@ type guiState struct {
// 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) {
previousView := "containers"
if dockerCommand.InDockerComposeProject {
previousView = "services"
}
initialState := guiState{
PreviousView: "services",
PreviousView: previousView,
Platform: *oSCommand.Platform,
Panels: &panelStates{
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{
Log: log,
DockerCommand: dockerCommand,
@ -150,6 +160,7 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
statusManager: &statusManager{},
T: tasks.NewTaskManager(log),
ErrorChan: errorChan,
CyclableViews: cyclableViews,
}
gui.GenerateSentinelErrors()

View file

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

View file

@ -9,11 +9,17 @@ import (
)
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 {
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 {
@ -71,20 +77,20 @@ func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) 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{}) {
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)
})
@ -92,11 +98,11 @@ func (gui *Gui) renderCredits() error {
}
func (gui *Gui) renderAllLogs() error {
mainView := gui.getMainView()
mainView.Autoscroll = true
mainView.Wrap = true
go gui.T.NewTask(func(stop chan struct{}) {
mainView := gui.getMainView()
mainView.Autoscroll = true
mainView.Wrap = true
gui.clearMainView()
cmd := gui.OSCommand.RunCustomCommand(gui.Config.UserConfig.CommandTemplates.AllLogs)
@ -121,11 +127,11 @@ func (gui *Gui) renderAllLogs() error {
}
func (gui *Gui) renderDockerComposeConfig() error {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Wrap = true
go gui.T.NewTask(func(stop chan struct{}) {
mainView := gui.getMainView()
mainView.Autoscroll = false
mainView.Wrap = true
config := gui.DockerCommand.DockerComposeConfig()
gui.renderString(gui.g, "main", config)
})

View file

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