cleaner droplet table views

This commit is contained in:
Jeff Carr 2025-03-11 03:34:30 -05:00
parent e0970840e2
commit d2d04da122
5 changed files with 200 additions and 87 deletions

View File

@ -21,16 +21,52 @@ import (
) )
// refresh the windows & tables the user has open // refresh the windows & tables the user has open
func refresh() { func (admin *adminT) refresh() {
time.Sleep(90 * time.Second)
if argv.Verbose { if argv.Verbose {
log.Info("virtigo scan here") log.Info("virtigo scan here")
} }
url := argv.Server
msg := []byte(`{"message": "Hello"}`)
// display the uptime
if data, err := postData(url+"/uptime", msg); err != nil {
log.Info("Error:", err)
} else {
log.Info("Response:", string(data))
admin.uptime.SetText(string(data))
}
// update the droplet list
if data, err := postData(url+"/DropletsPB", msg); err != nil {
log.Info("Error:", err)
} else {
fmt.Println("Response len:", len(data))
admin.droplets = new(virtpb.Droplets)
if err := admin.droplets.Unmarshal(data); err != nil {
fmt.Println("marshal failed", err)
return
}
fmt.Println("Droplet len=", admin.droplets.Len())
}
// update the hypervisor list
if data, err := postData(url+"/HypervisorPB", msg); err != nil {
log.Info("Error:", err)
} else {
fmt.Println("Response len:", len(data))
admin.hypervisors = new(virtpb.Hypervisors)
if err := admin.hypervisors.Unmarshal(data); err != nil {
fmt.Println("marshal failed", err)
return
}
fmt.Println("Hypervisors len=", admin.hypervisors.Len())
}
} }
var client *http.Client var client *http.Client
func doAdminGui() { func (admin *adminT) doAdminGui() {
me.myGui = gui.New() me.myGui = gui.New()
me.myGui.InitEmbed(resources) me.myGui.InitEmbed(resources)
me.myGui.Default() me.myGui.Default()
@ -49,39 +85,26 @@ func doAdminGui() {
os.Exit(0) os.Exit(0)
} }
admin.uptime = win.Group.NewLabel("uptime")
grid := win.Group.RawGrid() grid := win.Group.RawGrid()
// url := "http://example.com/endpoint"
url := argv.Server
data := []byte(`{"message": "Hello"}`)
grid.NewButton("show hypervisors", func() { grid.NewButton("show hypervisors", func() {
response, err := postData(url, data) if admin.hypervisors == nil {
if err != nil { log.Info("hypervisors not initialized")
fmt.Println("Error:", err) return
} else {
fmt.Println("Response:", string(response))
} }
log.Info("Hypervisors len=", admin.hypervisors.Len())
}) })
grid.NewButton("show droplets", func() { grid.NewButton("show active droplets", func() {
durl := url + "/DropletsPB" if admin.droplets == nil {
data, err := postData(durl, data) log.Info("droplets not initialized")
if err != nil {
fmt.Println("Error:", err)
return return
} }
fmt.Println("Response len:", len(data))
me.droplets = new(virtpb.Droplets)
if err := me.droplets.Unmarshal(data); err != nil {
fmt.Println("marshal failed", err)
return
}
fmt.Println("Droplet len=", me.droplets.Len())
var found *virtpb.Droplets var found *virtpb.Droplets
found = virtpb.NewDroplets() found = virtpb.NewDroplets()
all := me.droplets.All() all := admin.droplets.All()
for all.Scan() { for all.Scan() {
vm := all.Next() vm := all.Next()
if vm.Current.State != virtpb.DropletState_ON { if vm.Current.State != virtpb.DropletState_ON {
@ -89,29 +112,47 @@ func doAdminGui() {
} }
found.Append(vm) found.Append(vm)
} }
dropWin, _ := makeDropletsWindow(found) dropWin := newDropletsWindow()
dropWin.Win.Custom = func() { dropWin.doActiveDroplets(found)
dropWin.win.Custom = func() {
log.Info("hiding droplet table window") log.Info("hiding droplet table window")
} }
}) })
grid.NewButton("uptime", func() { grid.NewButton("inactive droplets", func() {
durl := url + "/uptime" if admin.droplets == nil {
response, err := postData(durl, data) log.Info("droplets not initialized")
if err != nil { return
fmt.Println("Error:", err) }
} else { var found *virtpb.Droplets
fmt.Println("Response:", string(response)) found = virtpb.NewDroplets()
all := admin.droplets.All()
for all.Scan() {
vm := all.Next()
if vm.Current.State == virtpb.DropletState_ON {
continue
}
found.Append(vm)
}
dropWin := newDropletsWindow()
dropWin.doInactiveDroplets(found)
dropWin.win.Custom = func() {
log.Info("hiding droplet table window")
} }
}) })
grid.NextRow()
grid.NewButton("refresh", func() {
admin.refresh()
})
grid.NewButton("clean exit", func() { grid.NewButton("clean exit", func() {
okExit("admin close") okExit("admin close")
}) })
// sit here forever refreshing the GUI // sit here forever refreshing the GUI
for { for {
refresh() admin.refresh()
time.Sleep(90 * time.Second)
} }
} }

View File

@ -154,6 +154,7 @@ func makeDropletsWindow(pb *virtpb.Droplets) (*GenericWindow, *virtpb.DropletsTa
}) })
t.AddMemory() t.AddMemory()
t.AddCpus() t.AddCpus()
t.AddSpicePort()
t.AddTimeFunc("age", func(d *virtpb.Droplet) time.Time { t.AddTimeFunc("age", func(d *virtpb.Droplet) time.Time {
age := d.Current.OnSince.AsTime() age := d.Current.OnSince.AsTime()
log.Info("age", d.Hostname, virtpb.FormatDuration(time.Since(age))) log.Info("age", d.Hostname, virtpb.FormatDuration(time.Since(age)))

View File

@ -38,7 +38,8 @@ func main() {
} }
if argv.Server != "" { if argv.Server != "" {
doAdminGui() me.admin = new(adminT)
me.admin.doAdminGui()
okExit("admin close") okExit("admin close")
} }

View File

@ -36,11 +36,15 @@ type virtigoT struct {
missingDropletTimeout time.Duration // how long a droplet can be missing for missingDropletTimeout time.Duration // how long a droplet can be missing for
status *gui.Node // the cluster status status *gui.Node // the cluster status
lastuptime *gui.Node // the last time uptime was checked by Kuma lastuptime *gui.Node // the last time uptime was checked by Kuma
admin *adminT // the admin struct
}
type adminT struct {
// admin mode // admin mode
droplets *virtpb.Droplets // your droplets droplets *virtpb.Droplets // your droplets
hypervisors *virtpb.Hypervisors // yep hypervisors *virtpb.Hypervisors // yep
events *virtpb.Events // yep events *virtpb.Events // yep
uptime *gui.Node // the uptime message
} }
// the stuff that is needed for a hypervisor // the stuff that is needed for a hypervisor

View File

@ -4,7 +4,9 @@
package main package main
import ( import (
"strings"
"sync" "sync"
"time"
"go.wit.com/gui" "go.wit.com/gui"
"go.wit.com/lib/gadgets" "go.wit.com/lib/gadgets"
@ -16,6 +18,7 @@ type stdDropletTableWin struct {
sync.Mutex sync.Mutex
win *gadgets.GenericWindow // the machines gui window win *gadgets.GenericWindow // the machines gui window
box *gui.Node // the machines gui parent box widget box *gui.Node // the machines gui parent box widget
pb *virtpb.Droplets // the droplets protobuf
TB *virtpb.DropletsTable // the gui table buffer TB *virtpb.DropletsTable // the gui table buffer
update bool // if the window should be updated update bool // if the window should be updated
} }
@ -30,39 +33,29 @@ func (w *stdDropletTableWin) Toggle() {
w.win.Toggle() w.win.Toggle()
} }
func makeDropletsWin() *stdDropletTableWin { func newDropletsWindow() *stdDropletTableWin {
dwin := new(stdDropletTableWin) dwin := new(stdDropletTableWin)
dwin.win = gadgets.NewGenericWindow("virtigo current droplets", "who is squirreling around?") dwin.win = gadgets.NewGenericWindow("virtigo current droplets", "")
dwin.win.Custom = func() { dwin.win.Custom = func() {
log.Info("test delete window here") log.Info("test delete window here")
} }
grid := dwin.win.Group.RawGrid()
grid.NewButton("show droplets", func() {
var count int
found := virtpb.NewDroplets()
all := me.droplets.All()
for all.Scan() {
e := all.Next()
count += 1
found.Append(e)
if count > 20 {
break
}
}
dwin.doDropletsTable(found)
})
/*
grid.NewButton("Save Current", func() {
log.Info("droplets len =", me.droplets.Len())
me.droplets.Save()
})
*/
// make a box at the bottom of the window for the protobuf table // make a box at the bottom of the window for the protobuf table
dwin.box = dwin.win.Bottom.Box().SetProgName("TBOX") dwin.box = dwin.win.Bottom.Box().SetProgName("TBOX")
// doTable(me.droplets) return dwin
}
func makeWindownDropletsPB(pb *virtpb.Droplets) *stdDropletTableWin {
dwin := new(stdDropletTableWin)
dwin.win = gadgets.NewGenericWindow("virtigo current droplets", "")
dwin.win.Custom = func() {
log.Info("test delete window here")
}
// make a box at the bottom of the window for the protobuf table
dwin.box = dwin.win.Bottom.Box().SetProgName("TBOX")
dwin.doDropletsTable(pb)
return dwin return dwin
} }
@ -76,7 +69,7 @@ func (dwin *stdDropletTableWin) doDropletsTable(currentDroplets *virtpb.Droplets
} }
// display the protobuf // display the protobuf
dwin.TB = AddDropletsPB(dwin.box, currentDroplets) dwin.TB = addDropletsPB(dwin.box, currentDroplets)
f := func(e *virtpb.Droplet) { f := func(e *virtpb.Droplet) {
log.Info("Triggered. do something here", e.Hostname) log.Info("Triggered. do something here", e.Hostname)
// m.Enabled = true // m.Enabled = true
@ -84,34 +77,107 @@ func (dwin *stdDropletTableWin) doDropletsTable(currentDroplets *virtpb.Droplets
dwin.TB.Custom(f) dwin.TB.Custom(f)
} }
func AddDropletsPB(tbox *gui.Node, pb *virtpb.Droplets) *virtpb.DropletsTable { func addDropletsPB(tbox *gui.Node, pb *virtpb.Droplets) *virtpb.DropletsTable {
t := pb.NewTable("DropletsPB") t := pb.NewTable("DropletsPB")
t.NewUuid() t.NewUuid()
t.SetParent(tbox) t.SetParent(tbox)
/* vp := t.AddButtonFunc("start", func(p *virtpb.Droplet) string {
ctimef := func(e *virtpb.Droplet) string { return "poweron"
ctime := e.Ctime.AsTime() })
return ctime.Format("2006/01/02 15:04") vp.Custom = func(d *virtpb.Droplet) {
log.Info("power on the droplet here:", d.Hostname)
} }
t.AddStringFunc("ctime", ctimef)
etimef := func(e *virtpb.Droplet) string {
etime := e.Etime.AsTime()
s := etime.Format("2006/01/02 15:04")
if strings.HasPrefix(s, "1970/") {
// just show a blank if it's not set
return ""
}
return s
}
t.AddStringFunc("etime", etimef)
*/
t.AddHostname() t.AddHostname()
// t.AddAddress() t.AddMemory()
// t.AddWhere() t.AddCpus()
// t.AddLocalPort()
t.ShowTable() t.ShowTable()
return t return t
} }
// default window for active running droplets
func (dw *stdDropletTableWin) doInactiveDroplets(pb *virtpb.Droplets) {
dw.Lock()
defer dw.Unlock()
// erase the old table
if dw.TB != nil {
dw.TB.Delete()
dw.TB = nil
}
// init the table
dw.pb = pb
t := dw.pb.NewTable("DropletsPB Off")
t.NewUuid()
t.SetParent(dw.box)
// pick the columns
t.AddHostname()
t.AddMemory()
t.AddCpus()
// final setup and display the table
dw.TB = t
f := func(e *virtpb.Droplet) {
log.Info("Triggered. do something here", e.Hostname)
// m.Enabled = true
}
dw.TB.Custom(f)
dw.TB.ShowTable()
}
// default window for active running droplets
func (dw *stdDropletTableWin) doActiveDroplets(pb *virtpb.Droplets) {
dw.Lock()
defer dw.Unlock()
if dw.TB != nil {
dw.TB.Delete()
dw.TB = nil
}
dw.pb = pb
t := dw.pb.NewTable("DropletsPB On")
t.NewUuid()
t.SetParent(dw.box)
t.AddHostname()
t.AddStringFunc("location", func(d *virtpb.Droplet) string {
return d.Current.Hypervisor
})
t.AddMemory()
t.AddCpus()
t.AddSpicePort()
t.AddTimeFunc("age", func(d *virtpb.Droplet) time.Time {
age := d.Current.OnSince.AsTime()
log.Info("age", d.Hostname, virtpb.FormatDuration(time.Since(age)))
return age
})
t.AddStringFunc("State", func(d *virtpb.Droplet) string {
if d.Current.State == virtpb.DropletState_ON {
return "ON"
}
if d.Current.State == virtpb.DropletState_OFF {
return "OFF"
}
return "UNKNOWN"
})
t.AddStringFunc("mac addr", func(d *virtpb.Droplet) string {
var macs []string
for _, n := range d.Networks {
macs = append(macs, n.Mac)
}
tmp := strings.Join(macs, "\n")
return strings.TrimSpace(tmp)
})
t.ShowTable()
// display the protobuf
dw.TB = t
f := func(e *virtpb.Droplet) {
log.Info("Triggered. do something here", e.Hostname)
// m.Enabled = true
}
dw.TB.Custom(f)
}