add client to containermap, add views package, help view

This commit is contained in:
Bradley Cicenas 2017-01-01 22:42:13 +00:00
parent adaa07fd4d
commit 6e87539b9d
7 changed files with 103 additions and 43 deletions

View File

@ -8,6 +8,7 @@ import (
type Container struct { type Container struct {
id string id string
name string
done chan bool done chan bool
stats chan *docker.Stats stats chan *docker.Stats
widgets *Widgets widgets *Widgets

View File

@ -1,23 +1,57 @@
package main package main
import ( import (
"os"
"strings" "strings"
"github.com/fsouza/go-dockerclient" "github.com/fsouza/go-dockerclient"
) )
var filters = map[string][]string{
"status": []string{"running"},
}
func NewContainerMap() *ContainerMap { func NewContainerMap() *ContainerMap {
return &ContainerMap{ // init docker client
containers: make(map[string]*Container), host := os.Getenv("DOCKER_HOST")
sortField: "cpu", if host == "" {
host = "unix:///var/run/docker.sock"
} }
client, err := docker.NewClient(host)
if err != nil {
panic(err)
}
cm := &ContainerMap{
client: client,
containers: make(map[string]*Container),
sortField: SortFields[0],
}
cm.Refresh()
return cm
} }
type ContainerMap struct { type ContainerMap struct {
client *docker.Client
containers map[string]*Container containers map[string]*Container
sortField string sortField string
} }
func (cm *ContainerMap) Refresh() {
opts := docker.ListContainersOptions{
Filters: filters,
}
containers, err := cm.client.ListContainers(opts)
if err != nil {
panic(err)
}
for _, c := range containers {
if _, ok := cm.containers[c.ID[:12]]; ok == false {
cm.Add(c)
}
}
}
// Return number of containers/rows // Return number of containers/rows
func (cm *ContainerMap) Len() uint { func (cm *ContainerMap) Len() uint {
return uint(len(cm.containers)) return uint(len(cm.containers))
@ -28,11 +62,13 @@ func (cm *ContainerMap) Add(c docker.APIContainers) {
name := strings.Replace(c.Names[0], "/", "", 1) // use primary container name name := strings.Replace(c.Names[0], "/", "", 1) // use primary container name
cm.containers[id] = &Container{ cm.containers[id] = &Container{
id: id, id: id,
name: name,
done: make(chan bool), done: make(chan bool),
stats: make(chan *docker.Stats), stats: make(chan *docker.Stats),
widgets: NewWidgets(cid, name), widgets: NewWidgets(id, name),
reader: &StatReader{}, reader: &StatReader{},
} }
cm.containers[id].Collect(cm.client)
} }
// Get a single container, by ID // Get a single container, by ID

30
grid.go
View File

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/bcicen/ctop/views"
ui "github.com/gizak/termui" ui "github.com/gizak/termui"
) )
@ -58,7 +59,7 @@ func (g *Grid) Redraw() {
func header() *ui.Row { func header() *ui.Row {
return ui.NewRow( return ui.NewRow(
ui.NewCol(2, 0, headerPar("NAME")), ui.NewCol(2, 0, headerPar("NAME")),
ui.NewCol(1, 0, headerPar("CID")), ui.NewCol(2, 0, headerPar("CID")),
ui.NewCol(2, 0, headerPar("CPU")), ui.NewCol(2, 0, headerPar("CPU")),
ui.NewCol(2, 0, headerPar("MEM")), ui.NewCol(2, 0, headerPar("MEM")),
ui.NewCol(2, 0, headerPar("NET RX/TX")), ui.NewCol(2, 0, headerPar("NET RX/TX")),
@ -74,12 +75,26 @@ func headerPar(s string) *ui.Par {
return p return p
} }
func Display(g *Grid) { type View func()
func ResetView() {
ui.DefaultEvtStream.ResetHandlers()
ui.Clear()
}
func OpenView(v View) {
ResetView()
defer ResetView()
v()
}
func Display(g *Grid) bool {
var newView View
if err := ui.Init(); err != nil { if err := ui.Init(); err != nil {
panic(err) panic(err)
} }
defer ui.Close() defer ui.Close()
// calculate layout // calculate layout
ui.Body.Align() ui.Body.Align()
g.Cursor() g.Cursor()
@ -97,6 +112,10 @@ func Display(g *Grid) {
g.Cursor() g.Cursor()
} }
}) })
ui.Handle("/sys/kbd/h", func(ui.Event) {
newView = views.Help
ui.StopLoop()
})
ui.Handle("/sys/kbd/q", func(ui.Event) { ui.Handle("/sys/kbd/q", func(ui.Event) {
ui.StopLoop() ui.StopLoop()
}) })
@ -112,4 +131,9 @@ func Display(g *Grid) {
}) })
ui.Loop() ui.Loop()
if newView != nil {
OpenView(newView)
return false
}
return true
} }

39
main.go
View File

@ -2,43 +2,14 @@ package main
import ( import (
"os" "os"
"github.com/fsouza/go-dockerclient"
) )
func getContainers(client *docker.Client) []docker.APIContainers {
filters := make(map[string][]string)
filters["status"] = []string{"running"}
opts := docker.ListContainersOptions{
Filters: filters,
}
containers, err := client.ListContainers(opts)
if err != nil {
panic(err)
}
return containers
}
func main() { func main() {
dockerhost := os.Getenv("DOCKER_HOST")
if dockerhost == "" {
dockerhost = "unix:///var/run/docker.sock"
}
client, err := docker.NewClient(dockerhost)
if err != nil {
panic(err)
}
g := NewGrid() g := NewGrid()
for _, c := range getContainers(client) { for {
g.containers.Add(c) exit := Display(g)
if exit {
os.Exit(0)
}
} }
for _, c := range g.containers.All() {
c.Collect(client)
}
Display(g)
} }

View File

@ -4,6 +4,8 @@ import (
"sort" "sort"
) )
var SortFields = []string{"id", "name", "cpu", "mem"}
type ByID []*Container type ByID []*Container
func (a ByID) Len() int { return len(a) } func (a ByID) Len() int { return len(a) }
@ -14,7 +16,7 @@ type ByName []*Container
func (a ByName) Len() int { return len(a) } func (a ByName) Len() int { return len(a) }
func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByName) Less(i, j int) bool { return a[i].id < a[j].id } func (a ByName) Less(i, j int) bool { return a[i].name < a[j].name }
type ByCPU []*Container type ByCPU []*Container

26
views/help.go Normal file
View File

@ -0,0 +1,26 @@
package views
import (
"strings"
ui "github.com/gizak/termui"
)
var helpDialog = []string{
"[h] - open this help dialog",
"[q] - exit ctop",
}
func Help() {
p := ui.NewPar(strings.Join(helpDialog, "\n"))
p.Height = 10
p.Width = 50
p.TextFgColor = ui.ColorWhite
p.BorderLabel = "Help"
p.BorderFg = ui.ColorCyan
ui.Render(p)
ui.Handle("/sys/kbd/q", func(ui.Event) {
ui.StopLoop()
})
ui.Loop()
}

View File

@ -18,7 +18,7 @@ type Widgets struct {
func (w *Widgets) MakeRow() *ui.Row { func (w *Widgets) MakeRow() *ui.Row {
return ui.NewRow( return ui.NewRow(
ui.NewCol(2, 0, w.name), ui.NewCol(2, 0, w.name),
ui.NewCol(1, 0, w.cid), ui.NewCol(2, 0, w.cid),
ui.NewCol(2, 0, w.cpu), ui.NewCol(2, 0, w.cpu),
ui.NewCol(2, 0, w.memory), ui.NewCol(2, 0, w.memory),
ui.NewCol(2, 0, w.net), ui.NewCol(2, 0, w.net),