mirror of
https://github.com/bcicen/ctop.git
synced 2024-08-30 18:23:19 +00:00
add client to containermap, add views package, help view
This commit is contained in:
parent
adaa07fd4d
commit
6e87539b9d
@ -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
|
||||||
|
@ -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
30
grid.go
@ -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
39
main.go
@ -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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
sort.go
4
sort.go
@ -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
26
views/help.go
Normal 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()
|
||||||
|
}
|
@ -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),
|
||||||
|
Loading…
Reference in New Issue
Block a user