more stuff

pull/1/head
Jesse Duffield 5 years ago
parent 159a1883e5
commit 3cfa4a2bda

@ -21,13 +21,15 @@ type App struct {
DockerCommand *commands.DockerCommand
Gui *gui.Gui
Tr *i18n.Localizer
ErrorChan chan error
}
// NewApp bootstrap a new application
func NewApp(config *config.AppConfig) (*App, error) {
app := &App{
closers: []io.Closer{},
Config: config,
closers: []io.Closer{},
Config: config,
ErrorChan: make(chan error),
}
var err error
app.Log = log.NewLogger(config, "23432119147a4367abf7c0de2aa99a2d")
@ -36,11 +38,11 @@ func NewApp(config *config.AppConfig) (*App, error) {
// here is the place to make use of the docker-compose.yml file in the current directory
app.DockerCommand, err = commands.NewDockerCommand(app.Log, app.OSCommand, app.Tr, app.Config)
app.DockerCommand, err = commands.NewDockerCommand(app.Log, app.OSCommand, app.Tr, app.Config, app.ErrorChan)
if err != nil {
return app, err
}
app.Gui, err = gui.NewGui(app.Log, app.DockerCommand, app.OSCommand, app.Tr, config)
app.Gui, err = gui.NewGui(app.Log, app.DockerCommand, app.OSCommand, app.Tr, config, app.ErrorChan)
if err != nil {
return app, err
}

@ -3,6 +3,7 @@ package commands
import (
"context"
"os/exec"
"strconv"
"strings"
"time"
@ -32,6 +33,12 @@ type Container struct {
Details Details
}
type DetailsCollection struct {
InspectDetails Details
CLIStats ContainerCliStat
ClientStats ContainerStats
}
type Details struct {
ID string `json:"Id"`
Created time.Time `json:"Created"`
@ -239,7 +246,31 @@ type ContainerCliStat struct {
// GetDisplayStrings returns the dispaly string of Container
func (c *Container) GetDisplayStrings(isFocused bool) []string {
return []string{utils.ColoredString(c.Container.State, c.GetColor()), utils.ColoredString(c.Name, color.FgWhite), c.Stats.CPUPerc}
return []string{utils.ColoredString(c.Container.State, c.GetColor()), utils.ColoredString(c.Name, color.FgWhite), c.GetDisplayCPUPerc()}
}
// GetDisplayCPUPerc colors the cpu percentage based on how extreme it is
func (c *Container) GetDisplayCPUPerc() string {
if c.Stats.CPUPerc == "" {
return ""
}
percentage, err := strconv.ParseFloat(strings.TrimSuffix(c.Stats.CPUPerc, "%"), 32)
if err != nil {
c.Log.Error(err)
return ""
}
var clr color.Attribute
if percentage > 90 {
clr = color.FgRed
} else if percentage > 50 {
clr = color.FgYellow
} else {
clr = color.FgWhite
}
return utils.ColoredString(c.Stats.CPUPerc, clr)
}
// GetColor Container color
@ -301,7 +332,7 @@ func (c *Container) RestartService() error {
// Attach attaches the container
func (c *Container) Attach() (*exec.Cmd, error) {
// verify that we can in fact attach to this container
if !c.Details.Config.AttachStdin {
if !c.Details.Config.OpenStdin {
return nil, errors.New("Container does not support attaching. You must either run the service with the '-it' flag or use `stdin_open: true, tty: true` in the docker-compose.yml file")
}

@ -24,10 +24,11 @@ type DockerCommand struct {
Config *config.AppConfig
Client *client.Client
InDockerComposeProject bool
ErrorChan chan error
}
// NewDockerCommand it runs git commands
func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer, config *config.AppConfig) (*DockerCommand, error) {
func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localizer, config *config.AppConfig, errorChan chan error) (*DockerCommand, error) {
cli, err := client.NewEnvClient()
if err != nil {
return nil, err
@ -40,17 +41,19 @@ func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localize
Config: config,
Client: cli,
InDockerComposeProject: true, // TODO: determine this at startup
ErrorChan: errorChan,
}, nil
}
// UpdateContainerStats takes a slice of containers and returns the same slice but with new stats added
// TODO: consider using this for everything stats-related
func (c *DockerCommand) UpdateContainerStats(containers []*Container) ([]*Container, error) {
func (c *DockerCommand) UpdateContainerStats(containers []*Container) {
// TODO: consider using a stream rather than polling
command := `docker stats --all --no-trunc --no-stream --format '{{json .}}'`
output, err := c.OSCommand.RunCommandWithOutput(command)
if err != nil {
return nil, err
c.ErrorChan <- err
return
}
jsonStats := "[" + strings.Join(
@ -63,7 +66,8 @@ func (c *DockerCommand) UpdateContainerStats(containers []*Container) ([]*Contai
var stats []ContainerCliStat
if err := json.Unmarshal([]byte(jsonStats), &stats); err != nil {
return nil, err
c.ErrorChan <- err
return
}
for _, stat := range stats {
@ -74,7 +78,9 @@ func (c *DockerCommand) UpdateContainerStats(containers []*Container) ([]*Contai
}
}
return containers, nil
c.Log.Warn("updated containers")
return
}
// GetContainersAndServices returns a slice of docker containers
@ -147,10 +153,7 @@ func (c *DockerCommand) GetContainers() ([]*Container, error) {
c.UpdateContainerDetails(ownContainers)
// ownContainers, err = c.UpdateContainerStats(ownContainers)
// if err != nil {
// return nil, err
// }
c.UpdateContainerStats(ownContainers)
return ownContainers, nil
}

@ -26,7 +26,7 @@ func (s *Service) GetDisplayStrings(isFocused bool) []string {
}
cont := s.Container
return []string{utils.ColoredString(cont.Container.State, cont.GetColor()), utils.ColoredString(s.Name, color.FgWhite), cont.Stats.CPUPerc}
return []string{utils.ColoredString(cont.Container.State, cont.GetColor()), utils.ColoredString(s.Name, color.FgWhite), cont.GetDisplayCPUPerc()}
}
// Remove removes the service's containers

@ -65,7 +65,7 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
if err != gui.Errors.ErrNoContainers {
return err
}
return gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedContainers"))
return nil
}
key := container.ID + "-" + gui.getContainerContexts()[gui.State.Panels.Containers.ContextIndex]
@ -171,7 +171,7 @@ func (gui *Gui) renderContainerLogs(mainView *gocui.View, container *commands.Co
mainView.Autoscroll = true
mainView.Title = "Logs"
if container.Details.Config.AttachStdin {
if container.Details.Config.OpenStdin {
return gui.renderLogsForTTYContainer(mainView, container)
}
return gui.renderLogsForRegularContainer(mainView, container)

@ -74,6 +74,7 @@ type Gui struct {
statusManager *statusManager
waitForIntro sync.WaitGroup
T *tasks.TaskManager
ErrorChan chan error
}
type servicePanelState struct {
@ -118,10 +119,11 @@ type guiState struct {
SubProcessOutput string
MainProcessMutex sync.Mutex
MainProcessChan chan struct{}
Stats map[string]commands.ContainerStats
}
// NewGui builds a new gui handler
func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand *commands.OSCommand, tr *i18n.Localizer, config *config.AppConfig) (*Gui, error) {
func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand *commands.OSCommand, tr *i18n.Localizer, config *config.AppConfig, errorChan chan error) (*Gui, error) {
initialState := guiState{
Containers: make([]*commands.Container, 0),
@ -151,11 +153,13 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
Log: log,
DockerCommand: dockerCommand,
OSCommand: oSCommand,
// TODO: look into this warning
State: initialState,
Config: config,
Tr: tr,
statusManager: &statusManager{},
T: tasks.NewTaskManager(log),
ErrorChan: errorChan,
}
gui.GenerateSentinelErrors()
@ -535,6 +539,12 @@ func (gui *Gui) Run() error {
gui.goEvery(time.Millisecond*500, gui.refreshContainersAndServices)
}()
go func() {
for err := range gui.ErrorChan {
gui.createErrorPanel(gui.g, err.Error())
}
}()
g.SetManager(gocui.ManagerFunc(gui.layout), gocui.ManagerFunc(gui.getFocusLayout()))
if err = gui.keybindings(g); err != nil {
@ -546,7 +556,11 @@ func (gui *Gui) Run() error {
}
func (gui *Gui) reRenderMain() error {
if gui.getMainView().IsTainted() {
mainView := gui.getMainView()
if mainView == nil {
return nil
}
if mainView.IsTainted() {
gui.g.Update(func(g *gocui.Gui) error {
return nil
})

@ -856,5 +856,9 @@ func addEnglish(i18nObject *i18n.Bundle) error {
ID: "PruningStatus",
Other: "pruning",
},
&i18n.Message{
ID: "StopService",
Other: "Are you sure you want to stop this service's containers? (enter/esc)",
},
)
}

Loading…
Cancel
Save