Compare commits

...

10 Commits

11 changed files with 304 additions and 263 deletions

View File

@ -7,8 +7,8 @@ BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
# REDOMOD = $(shell if [ -e go.mod ]; then echo go.mod; else echo no go mod; fi) # REDOMOD = $(shell if [ -e go.mod ]; then echo go.mod; else echo no go mod; fi)
REDOMOD = $(shell if [ -e go.sum ]; then echo go.sum exists; else GO111MODULE= go mod init; GO111MODULE= go mod tidy; fi) REDOMOD = $(shell if [ -e go.sum ]; then echo go.sum exists; else GO111MODULE= go mod init; GO111MODULE= go mod tidy; fi)
all: goimports gocui-debugging all: build
# ./zookeeper ./zookeeper list
vet: vet:
@GO111MODULE=off go vet @GO111MODULE=off go vet
@ -20,8 +20,12 @@ nogui:
gocui: build gocui: build
./zookeeper --gui gocui ./zookeeper --gui gocui
gocui-5000: build
./zookeeper --gui gocui --port 5000
gocui-debugging: build gocui-debugging: build
./zookeeper --gui gocui --gui-file ~/go/src/go.wit.com/toolkits/gocui/gocui.so >/tmp/forge.log 2>&1 ./zookeeper --gui gocui --gui-file ~/go/src/go.wit.com/toolkits/gocui/gocui.so
# ./zookeeper --gui gocui --gui-file ~/go/src/go.wit.com/toolkits/gocui/gocui.so >/tmp/forge.log 2>&1
build: goimports vet build: goimports vet
GO111MODULE=off go build -v -x \ GO111MODULE=off go build -v -x \
@ -51,7 +55,7 @@ redomod:
clean: clean:
rm -f go.* rm -f go.*
rm -f zookeeper rm -f zookeeper
go-mod-clean --purge go-mod-clean purge
# git clone the sources and all the golang dependancies into ~/go/src # git clone the sources and all the golang dependancies into ~/go/src
# if you don't have go-clone, you can get it from http://go.wit.com/ # if you don't have go-clone, you can get it from http://go.wit.com/

45
argv.go
View File

@ -9,15 +9,27 @@ package main
*/ */
import ( import (
"fmt"
"os"
"go.wit.com/log" "go.wit.com/log"
) )
var argv args var argv args
type args struct { type args struct {
Gui *EmptyCmd `arg:"subcommand:gui" help:"open the gui"`
List *EmptyCmd `arg:"subcommand:list" help:"list the machines in your zoo"`
Upgrade *EmptyCmd `arg:"subcommand:upgrade" help:"upgrade the machines"`
Verbose bool `arg:"--verbose" default:"false" help:"talk more"` Verbose bool `arg:"--verbose" default:"false" help:"talk more"`
Daemon bool `arg:"--daemon" default:"false" help:"run in daemon mode"` Daemon bool `arg:"--daemon" default:"false" help:"run in daemon mode"`
Port int `arg:"--port" default:"8080" help:"port to run on"` Port int `arg:"--port" default:"8080" help:"port to run on"`
NoPort bool `arg:"--no-port" help:"don't open socket"`
Bash bool `arg:"--bash" help:"generate bash completion"`
BashAuto []string `arg:"--auto-complete" help:"todo: move this to go-arg"`
}
type EmptyCmd struct {
} }
func (args) Version() string { func (args) Version() string {
@ -50,3 +62,36 @@ func init() {
ZOOD = log.NewFlag("ZOOD", false, full, short, "show reporting from zood") ZOOD = log.NewFlag("ZOOD", false, full, short, "show reporting from zood")
WARN = log.NewFlag("WARN", true, full, short, "bad things") WARN = log.NewFlag("WARN", true, full, short, "bad things")
} }
// prints help to STDERR // TODO: move everything below this to go-args
func (args) doBashHelp() {
if argv.BashAuto[1] != "''" {
// if this is not blank, then the user has typed something
return
}
if argv.BashAuto[0] != ARGNAME {
// if this is not the name of the command, the user already started doing something
return
}
if argv.BashAuto[0] == ARGNAME {
me.pp.WriteHelp(os.Stderr)
return
}
}
func (args) DoAutoComplete(argv []string) {
switch argv[0] {
case "list":
fmt.Println("")
case "verify":
fmt.Println("on")
case "upgrade":
fmt.Println("")
default:
if argv[0] == ARGNAME {
// list the subcommands here
fmt.Println("help list")
}
}
os.Exit(0)
}

View File

@ -8,7 +8,7 @@ Maintainer: Jeff Carr <jcarr@wit.com>
Architecture: amd64 Architecture: amd64
Depends: Depends:
URL: https://go.wit.com/apps/zookeeper URL: https://go.wit.com/apps/zookeeper
Description: zookeeper for homelab grids Description: manage your homelab cluster
keeps track of things in a grid. Maybe keeps track of things in a grid. Maybe
this is similar to the apache project by this is similar to the apache project by
the same name, but in any case, this is the same name, but in any case, this is

View File

@ -7,9 +7,7 @@ package main
import ( import (
"os" "os"
"time"
"go.wit.com/gui"
"go.wit.com/lib/gadgets" "go.wit.com/lib/gadgets"
"go.wit.com/lib/protobuf/zoopb" "go.wit.com/lib/protobuf/zoopb"
"go.wit.com/log" "go.wit.com/log"
@ -21,7 +19,7 @@ func refresh() {
log.Info("zookeeper scan here") log.Info("zookeeper scan here")
} }
if me.zood != nil { if me.zood != nil {
me.zood.doMachinesUpgradeTable(me.machines) // me.zood.doMachinesUpgradeTable(me.machines)
all := me.machines.All() all := me.machines.All()
for all.Scan() { for all.Scan() {
m := all.Next() m := all.Next()
@ -32,14 +30,11 @@ func refresh() {
me.zood.versionL.SetText(v) me.zood.versionL.SetText(v)
} }
} }
me.zood.refresh()
} }
} }
func doGui() { func doGui() {
me.myGui = gui.New()
me.myGui.InitEmbed(resources)
me.myGui.Default()
win := gadgets.RawBasicWindow("Zookeeper: (inventory your cluster)") win := gadgets.RawBasicWindow("Zookeeper: (inventory your cluster)")
win.Make() win.Make()
win.Show() win.Show()
@ -68,11 +63,9 @@ func doGui() {
log.Info("todo: start a list here!") log.Info("todo: start a list here!")
}) })
// sit here forever refreshing the GUI grid.NewButton("ConfigSave()", func() {
for { saveMachineState()
refresh() })
time.Sleep(90 * time.Second)
}
} }
func saveMachineState() { func saveMachineState() {

119
http.go
View File

@ -5,79 +5,70 @@ package main
import ( import (
"fmt" "fmt"
"io/ioutil" "io"
"net/http" "net/http"
"strings"
"time" "time"
"go.wit.com/lib/protobuf/httppb"
"go.wit.com/log" "go.wit.com/log"
) )
// remove '?' part and trailing '/' /*
func cleanURL(url string) string { if strings.HasPrefix(route, "/repos/") {
url = "/" + strings.Trim(url, "/") pb := gitpb.NewRepos()
return url if err := pb.Unmarshal(reqPB.ClientData); err == nil {
} reqPB.Log("Repos Unmarshal() len=%d", pb.Len())
} else {
func okHandler(w http.ResponseWriter, r *http.Request) { reqPB.Logf("Repos Unmarshal() err=%v", err)
// log.Info("Got URL Path: ", r.URL.Path) }
route := cleanURL(r.URL.Path) result := gitpb.NewRepos()
switch route {
hostname := r.URL.Query().Get("hostname") case "/repos/check":
// flag := r.URL.Query().Get("flag") result = addRequest(pb, reqPB)
reqPB.Logf("repos check result.Len()=%d pb.Len()=%d\n", result.Len(), pb.Len())
msg, err := ioutil.ReadAll(r.Body) // Read the body as []byte case "/repos/pull":
if err != nil { result = pullRequest(pb, reqPB)
log.Info("ReadAll() error =", err) case "/repos/add":
result = addRequest(pb, reqPB)
default:
reqPB.Logf("repos check result.Len()=%d pb.Len()=%d\n", result.Len(), pb.Len())
log.Info("repos", route, "unknown")
}
if err := result.SendReply(w, reqPB); err != nil {
reqPB.Logf("Oh well, Send to client failed. err=%v", err)
}
// todo: logReq(reqPB)
logReqPB(reqPB)
return return
} }
*/
func okHandler(w http.ResponseWriter, r *http.Request) {
reqPB, err := httppb.ReqToPB(r)
reqPB.Logf("START: Got %d bytes from the client", len(reqPB.ClientData))
if err != nil {
reqPB.Logf("httppb err %v", err)
}
route := reqPB.Route
if route == "/" { if route == "/" {
return return
} }
if route == "/machine" { if route == "/machine" {
handleMachine(r, w, hostname, msg) handleMachine(w, reqPB)
return return
} }
/*
if route == "/status" {
var packs *zoopb.Packages
packs = new(zoopb.Packages)
if err := packs.Unmarshal(msg); err != nil {
log.Info("/status proto.Unmarshal() failed on wire message len", len(msg), "from", hostname)
return
}
log.Info("/status Unmarshal worked with msg len", len(msg), "from", hostname)
log.Info("/status hostname", hostname, "has", packs.Len(), "packages installed")
fmt.Fprintln(w, "upgrade")
return
}
*/
// list out the machines and thier version of zood
/*
if route == "/list" {
log.HttpMode(w)
defer log.HttpMode(nil)
loop := me.machines.SortByHostname()
for loop.Scan() {
m := loop.Next()
zood := m.Packages.FindByName("zood")
v := me.targets["zood"] // this is the target version
if zood == nil {
log.Info("machine", m.Hostname, "does not have zood installed")
} else {
log.Info(fmt.Sprintf("zood version %s vs target version %s on machine %s", zood.Version, v, m.Hostname))
}
}
return
}
*/
if route == "/uptime" { if route == "/uptime" {
doUptime(w)
return
}
log.Warn("BAD URL =", route)
}
func doUptime(w io.Writer) {
if me.zood == nil { if me.zood == nil {
fmt.Fprintf(w, "BAD zood == nil\n") fmt.Fprintf(w, "BAD zood == nil\n")
return return
@ -100,22 +91,4 @@ func okHandler(w http.ResponseWriter, r *http.Request) {
} else { } else {
fmt.Fprintf(w, "BAD machine count=(%d) upgrade=(%d) to %s\n", count, bad, me.zood.version) fmt.Fprintf(w, "BAD machine count=(%d) upgrade=(%d) to %s\n", count, bad, me.zood.version)
} }
return
}
log.Warn("BAD URL =", route)
}
// starts and sits waiting for HTTP requests
func startHTTP() {
http.HandleFunc("/", okHandler)
p := fmt.Sprintf(":%d", argv.Port)
log.Println("Running on port", p)
err := http.ListenAndServe(p, nil)
if err != nil {
log.Println("Error starting server:", err)
badExit(err)
}
} }

View File

@ -1,83 +0,0 @@
package main
import (
"fmt"
"net/http"
)
func dumpRemoteAddr(r *http.Request) string {
return r.RemoteAddr
}
func dumpUserAgent(r *http.Request) string {
var all string
for param, values := range r.URL.Query() {
for _, value := range values {
all += fmt.Sprint(" Query:", param, value)
}
}
// hostname := r.URL.Query().Get("hostname")
return r.UserAgent() + all
}
func dumpClient(r *http.Request) {
/*
var host, url, proto, addr, agent string
host = r.Host
url = r.URL.String()
proto = r.Proto
addr = r.RemoteAddr
agent = r.UserAgent()
log.Warn(host, proto, addr, url, agent)
fmt.Fprintln(accessf, time.Now(), host, proto, addr, url, agent)
// return
fmt.Fprintln(clientf)
fmt.Fprintln(clientf, time.Now())
// Basic request information
fmt.Fprintln(clientf, "Method:", r.Method)
fmt.Fprintln(clientf, "URL:", r.URL)
fmt.Fprintln(clientf, "Protocol:", r.Proto)
fmt.Fprintln(clientf, "Host:", r.Host)
fmt.Fprintln(clientf, "Remote Address:", r.RemoteAddr)
// Headers
fmt.Fprintln(clientf, "Headers:")
for name, values := range r.Header {
for _, value := range values {
fmt.Fprintln(clientf, "Headers:", name, value)
}
}
// Query parameters
fmt.Fprintln(clientf, "Query Parameters:")
for param, values := range r.URL.Query() {
for _, value := range values {
fmt.Fprintln(clientf, "Query:", param, value)
}
}
// User-Agent
fmt.Fprintln(clientf, "User-Agent:", r.UserAgent())
// Content Length
fmt.Fprintln(clientf, "Content Length:", r.ContentLength)
// Cookies
fmt.Fprintln(clientf, "Cookies:")
for _, cookie := range r.Cookies() {
fmt.Fprintln(clientf, cookie.Name, cookie.Value)
}
// Request Body (if applicable)
if r.Body != nil {
body, err := ioutil.ReadAll(r.Body)
if err == nil {
fmt.Fprintln(clientf, "Body:", string(body))
}
}
*/
}

View File

@ -6,9 +6,9 @@ package main
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"strings"
"time" "time"
"go.wit.com/lib/protobuf/httppb"
"go.wit.com/lib/protobuf/zoopb" "go.wit.com/lib/protobuf/zoopb"
"go.wit.com/log" "go.wit.com/log"
"google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/timestamppb"
@ -20,25 +20,27 @@ func rawGetHostname(data []byte) *zoopb.Machine {
return newm return newm
} }
func handleMachine(r *http.Request, w http.ResponseWriter, hostname string, data []byte) { func handleMachine(w http.ResponseWriter, reqPB *httppb.HttpRequest) {
hostname = strings.TrimSpace(hostname) // hostname := strings.TrimSpace(reqPB.Hostname)
newm := rawGetHostname(data) newm := rawGetHostname(reqPB.ClientData)
if newm == nil { if newm == nil {
log.Info("unmarshal failed on data len =", len(data)) log.Info("unmarshal failed on data len =", len(reqPB.ClientData))
} }
if hostname != newm.Hostname { /*
if reqPB.Hostname != newm.Hostname {
// log.Info("hostname mismatch", hostname, "vs", newm.Hostname) // log.Info("hostname mismatch", hostname, "vs", newm.Hostname)
hostname = newm.Hostname hostname = newm.Hostname
} }
*/
if hostname == "" { if reqPB.Hostname == "" {
ua := dumpUserAgent(r) ua := reqPB.DumpUserAgent()
ra := dumpRemoteAddr(r) ra := reqPB.DumpRemoteAddr()
log.Info("hostname is blank even after unmarshal. data len =", len(data), ra, ua, newm.Cpus, newm.Hostname) log.Info("hostname is blank even after unmarshal. data len =", len(reqPB.ClientData), ra, ua, newm.Cpus, newm.Hostname)
return return
} }
// log.Info("lookoing for", hostname) // log.Info("lookoing for", hostname)
m := me.machines.FindByHostname(hostname) m := me.machines.FindByHostname(reqPB.Hostname)
if m == nil { if m == nil {
am := new(zoopb.Machine) am := new(zoopb.Machine)
am.Hostname = newm.Hostname am.Hostname = newm.Hostname
@ -47,10 +49,10 @@ func handleMachine(r *http.Request, w http.ResponseWriter, hostname string, data
log.Info("new machine", am.Hostname, am.Memory) log.Info("new machine", am.Hostname, am.Memory)
return return
} }
ua := dumpUserAgent(r) ua := reqPB.DumpUserAgent()
ra := dumpRemoteAddr(r) ra := reqPB.DumpRemoteAddr()
if m.UserAgent != ua { if m.UserAgent != ua {
log.Info("hostname ua changed len =", len(data), ra, hostname, ua) log.Info("hostname ua changed len =", len(reqPB.ClientData), ra, reqPB.Hostname, ua)
m.UserAgent = ua m.UserAgent = ua
} }
if m.Upgrade { if m.Upgrade {
@ -60,11 +62,12 @@ func handleMachine(r *http.Request, w http.ResponseWriter, hostname string, data
} else { } else {
fmt.Fprintln(w, m.UpgradeCmd) fmt.Fprintln(w, m.UpgradeCmd)
} }
m.UpgradeCmd = ""
m.Upgrade = false m.Upgrade = false
} else { } else {
fmt.Fprintln(w, "good") fmt.Fprintln(w, "good")
} }
// log.Info("update machine protobuf", hostname) // log.Info("update machine protobuf", reqPB.hostname)
updateMachine(newm) updateMachine(newm)
} }
@ -112,7 +115,9 @@ func updateMachine(u *zoopb.Machine) string {
} }
m.Laststamp = timestamppb.New(time.Now()) m.Laststamp = timestamppb.New(time.Now())
updatePackages(m, u.Packages) if updatePackages(m, u.Packages) {
// trigger save pb
}
return "upgrade" return "upgrade"
} }
@ -127,20 +132,36 @@ func updatePackages(m *zoopb.Machine, newp *zoopb.Packages) bool {
for loop.Scan() { for loop.Scan() {
p := loop.Next() p := loop.Next()
if p.Name == "zood" { if p.Name == "zood" {
if pold := m.Packages.FindByName("zood"); pold == nil { if updatePackageVersion(m, p) {
changed = true changed = true
log.Log(ZOOD, "updatePackages() new package", p.Name, "version", p.Version, "machine", m.Hostname)
m.Packages.Append(p)
} else {
if p.Version == pold.Version {
log.Log(ZOOD, "updatePackages() unchanged", p.Version, "machine", m.Hostname)
} else {
changed = true
log.Log(NOW, "updatePackages() package", p.Name, "version changed", pold.Version, "to", p.Version, "machine", m.Hostname)
pold.Version = p.Version
} }
} }
if p.Name == "virtigod" {
if updatePackageVersion(m, p) {
changed = true
}
}
if p.Name == "forge" {
if updatePackageVersion(m, p) {
changed = true
}
} }
} }
return changed return changed
} }
func updatePackageVersion(m *zoopb.Machine, pnew *zoopb.Package) bool {
pold := m.Packages.FindByName(pnew.Name)
if pold == nil {
log.Log(NOW, "updatePackages() new package", pnew.Name, "version", pnew.Version, "machine", m.Hostname)
m.Packages.Append(pnew)
return true
}
if pold.Version == pnew.Version {
log.Log(ZOOD, "updatePackages() unchanged", pold.Version, "machine", m.Hostname)
return false
}
log.Log(NOW, "updatePackages() package", pnew.Name, "version changed", pold.Version, "to", pnew.Version, "machine", m.Hostname)
pold.Version = pnew.Version
return true
}

37
main.go
View File

@ -4,12 +4,12 @@
package main package main
import ( import (
"embed"
"os" "os"
"time" "time"
"go.wit.com/dev/alexflint/arg" "go.wit.com/dev/alexflint/arg"
"go.wit.com/gui" "go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/httppb"
"go.wit.com/lib/protobuf/zoopb" "go.wit.com/lib/protobuf/zoopb"
"go.wit.com/log" "go.wit.com/log"
) )
@ -17,25 +17,19 @@ import (
var VERSION string var VERSION string
var BUILDTIME string var BUILDTIME string
//go:embed resources/* var ARGNAME string = "zookeeper"
var resources embed.FS
func main() { func main() {
var pp *arg.Parser me = new(mainType)
gui.InitArg() prep.Bash(ARGNAME, argv.DoAutoComplete) // this line should be: prep.Bash(argv)
pp = arg.MustParse(&argv) me.myGui = prep.Gui() // prepares the GUI package for go-args
me.pp = arg.MustParse(&argv)
if pp == nil {
pp.WriteHelp(os.Stdout)
os.Exit(0)
}
if argv.Daemon { if argv.Daemon {
// turn off timestamps for STDOUT (systemd adds them) // turn off timestamps for STDOUT (systemd adds them)
log.DaemonMode(true) log.DaemonMode(true)
} }
me = new(zookeep)
me.hostname, _ = os.Hostname() me.hostname, _ = os.Hostname()
me.pollDelay = time.Hour me.pollDelay = time.Hour
me.machines = zoopb.NewMachines() me.machines = zoopb.NewMachines()
@ -43,11 +37,22 @@ func main() {
log.Warn("load config failed", err) log.Warn("load config failed", err)
os.Exit(-1) os.Exit(-1)
} }
// me.upgrade = make(map[string]bool) // used to trigger upgrade attempts if argv.List != nil {
log.Info("do list here")
okExit("")
}
go NewWatchdog() go NewWatchdog()
if !argv.NoPort {
go httppb.StartHTTP(okHandler, argv.Port)
}
go startHTTP() me.myGui.Start() // loads the GUI toolkit
doGui() // start making our forge GUI
doGui() // sit here forever refreshing the GUI
for {
refresh()
time.Sleep(90 * time.Second)
}
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -6,15 +6,18 @@ package main
import ( import (
"time" "time"
"go.wit.com/dev/alexflint/arg"
"go.wit.com/gui" "go.wit.com/gui"
"go.wit.com/lib/gadgets" "go.wit.com/lib/gadgets"
"go.wit.com/lib/gui/prep"
"go.wit.com/lib/protobuf/zoopb" "go.wit.com/lib/protobuf/zoopb"
) )
var me *zookeep var me *mainType
// this app's variables // this app's variables
type zookeep struct { type mainType struct {
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
hostname string // my fqdn dns zookeeper hostname hostname string // my fqdn dns zookeeper hostname
pollDelay time.Duration // how often to report our status pollDelay time.Duration // how often to report our status
dog *time.Ticker // the watchdog timer dog *time.Ticker // the watchdog timer
@ -24,7 +27,7 @@ type zookeep struct {
machines *zoopb.Machines // every machine that has reported itself to the zookeeper machines *zoopb.Machines // every machine that has reported itself to the zookeeper
targets map[string]string // what versions the machines should be running targets map[string]string // what versions the machines should be running
upgrade map[string]bool // use this to trigger builds upgrade map[string]bool // use this to trigger builds
myGui *gui.Node // the gui toolkit handle myGui *prep.GuiPrep // the gui toolkit handle
machinesWin *gadgets.GenericWindow // the machines gui window machinesWin *gadgets.GenericWindow // the machines gui window
machinesBox *gui.Node // the machines gui parent box widget machinesBox *gui.Node // the machines gui parent box widget
machinesTB *zoopb.MachinesTable // the machines gui table buffer machinesTB *zoopb.MachinesTable // the machines gui table buffer

View File

@ -21,6 +21,8 @@ type stdTableWin struct {
TB *zoopb.MachinesTable // the machines gui table buffer TB *zoopb.MachinesTable // the machines gui table buffer
version string // the current zood version version string // the current zood version
versionL *gui.Node // label widget to display the current zood version versionL *gui.Node // label widget to display the current zood version
outOfDate *gui.Node // checkbox to only show out of date droplets
showAll *gui.Node // show everything in the zoo
update bool // if the window should be updated update bool // if the window should be updated
} }
@ -35,39 +37,102 @@ func (w *stdTableWin) Toggle() {
} }
func makeZoodWin() *stdTableWin { func makeZoodWin() *stdTableWin {
zood := new(stdTableWin) stdw := new(stdTableWin)
zood.win = gadgets.NewGenericWindow("zood daemon versions", "todo: add global controls here") stdw.win = gadgets.NewGenericWindow("zood daemon versions", "todo: add global controls here")
zood.win.Custom = func() { stdw.win.Custom = func() {
log.Info("test delete window here") log.Info("test delete window here")
} }
grid := zood.win.Group.RawGrid()
grid := stdw.win.Group.RawGrid()
grid.NewButton("save machines.pb", func() { grid.NewButton("save machines.pb", func() {
saveMachineState() saveMachineState()
}) })
grid.NewButton("show active", func() { grid.NewButton("show active", func() {
zood.doMachinesUpgradeTable(me.machines) stdw.doMachinesUpgradeTable(me.machines)
}) })
grid.NewButton("refresh", func() { grid.NewButton("refresh", func() {
refresh() stdw.refresh()
}) })
zood.versionL = grid.NewLabel("scan")
grid.NewButton("show out of date", func() { stdw.versionL = grid.NewLabel("scan")
stdw.outOfDate = grid.NewCheckbox("out of date")
stdw.showAll = grid.NewCheckbox("all")
grid.NewButton("upgrade 10", func() {
sendUpgrade(10)
})
grid.NewButton("upgrade all", func() {
sendUpgrade(-1)
})
// make a box at the bottom of the window for the protobuf table
stdw.box = stdw.win.Bottom.Box().SetProgName("TBOX")
stdw.doMachinesUpgradeTable(me.machines)
return stdw
}
func sendUpgrade(i int) {
var count int
all := me.machines.All()
for all.Scan() {
m := all.Next()
mtime := m.Laststamp.AsTime()
if time.Since(mtime) > 10*time.Hour {
continue
}
if m.FindVersion("zood") != me.zood.version {
count += 1
m.Upgrade = true
log.Info("upgrade", m.Hostname, count)
}
if i == -1 || count > i {
return
}
}
}
func (stdw *stdTableWin) refresh() {
if stdw.outOfDate.Checked() {
log.Info("refresh() showing out of date zoo")
found := zoopb.NewMachines() found := zoopb.NewMachines()
all := me.machines.All() all := me.machines.All()
for all.Scan() { for all.Scan() {
m := all.Next() m := all.Next()
if !stdw.showAll.Checked() {
// skip non-active zoo members
mtime := m.Laststamp.AsTime()
if time.Since(mtime) > 10*time.Hour {
continue
}
}
if m.FindVersion("zood") != me.zood.version { if m.FindVersion("zood") != me.zood.version {
found.Append(m) found.Append(m)
} }
} }
zood.doMachinesUpgradeTable(found) stdw.doMachinesUpgradeTable(found)
}) return
}
if stdw.showAll.Checked() {
log.Info("refresh() showing everything in zoo")
stdw.doMachinesUpgradeTable(me.machines)
return
}
// make a box at the bottom of the window for the protobuf table log.Info("refresh() only show active zoo")
zood.box = zood.win.Bottom.Box().SetProgName("TBOX") found := zoopb.NewMachines()
zood.doMachinesUpgradeTable(me.machines) all := me.machines.All()
for all.Scan() {
return zood m := all.Next()
mtime := m.Laststamp.AsTime()
// now := time.Now()
if time.Since(mtime) > 10*time.Hour {
continue
}
found.Append(m)
}
stdw.doMachinesUpgradeTable(found)
} }
func (zood *stdTableWin) doMachinesUpgradeTable(pb *zoopb.Machines) { func (zood *stdTableWin) doMachinesUpgradeTable(pb *zoopb.Machines) {
@ -145,10 +210,26 @@ func AddMachinesPB(tbox *gui.Node, pb *zoopb.Machines) *zoopb.MachinesTable {
m.UpgradeCmd = "apt install virtigod" m.UpgradeCmd = "apt install virtigod"
} }
forgebut := t.AddButtonFunc("forge", func(m *zoopb.Machine) string {
ver := m.FindVersion("forge")
if ver == "n/a" {
return ""
}
return ver
})
forgebut.Custom = func(m *zoopb.Machine) {
log.Info("Triggering machine", m.Hostname, "to upgrade forge")
m.Upgrade = true
m.UpgradeCmd = "apt install forge"
}
delf := func(m *zoopb.Machine) string { delf := func(m *zoopb.Machine) string {
return "delete" return "delete"
} }
t.AddButtonFunc("delete", delf) delbut := t.AddButtonFunc("delete", delf)
delbut.Custom = func(m *zoopb.Machine) {
log.Info("Need to delete the protobuf record here", m.Hostname)
}
/* /*
// show if the machine needs to be upgraded // show if the machine needs to be upgraded