summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-07 09:01:45 -0500
committerJeff Carr <[email protected]>2025-10-07 09:01:45 -0500
commite9e0dd856c77ad3c2f54a53a3ca0eef23f69ede1 (patch)
treef1f5bc8001b64f5527c3f84b318e4a99c7678340
parentf46ce34f817930945fd5de53a8cdf4a10b62bded (diff)
new package
-rw-r--r--apt.go28
-rw-r--r--distro.go61
-rw-r--r--hw.go33
-rw-r--r--init.go47
-rw-r--r--old/apt.go39
-rw-r--r--old/apt_darwin.go11
-rw-r--r--old/apt_windows.go11
-rw-r--r--update.go118
-rw-r--r--wit.go135
9 files changed, 483 insertions, 0 deletions
diff --git a/apt.go b/apt.go
index 1854790..357a3a1 100644
--- a/apt.go
+++ b/apt.go
@@ -4,8 +4,11 @@
package debian
import (
+ "fmt"
+
"github.com/go-cmd/cmd"
"go.wit.com/lib/fhelp"
+ "go.wit.com/lib/protobuf/zoopb"
"go.wit.com/log"
)
@@ -53,3 +56,28 @@ func AptUpdate() error {
}
return nil
}
+
+// init the installed package list
+func initPackages(me *zoopb.Machine) {
+ // Get the list of installed packages for the detected distro
+ newP, err := getPackageList(me.Distro)
+ if err != nil {
+ fmt.Println("Error:", err)
+ return
+ }
+
+ if me.Packages == nil {
+ me.Packages = new(zoopb.Packages)
+ }
+
+ // Print the installed packages and their versions
+ for pkg, version := range newP {
+ new1 := new(zoopb.Package)
+ new1.Name = pkg
+ new1.Version = version
+ me.Packages.Append(new1)
+ // log.Info("added", new1.Name, "failed")
+ }
+
+ getMemory(me)
+}
diff --git a/distro.go b/distro.go
new file mode 100644
index 0000000..a912e2f
--- /dev/null
+++ b/distro.go
@@ -0,0 +1,61 @@
+// Copyright 2024 WIT.COM Inc.
+
+package debian
+
+// simple stab at making a human readable distro name
+// this is for displaying in a table in the zookeeper app
+// it's just so you can easily see what machines in your grid are
+// doing what
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "runtime"
+ "strings"
+)
+
+func initDistro() string {
+ switch runtime.GOOS {
+ case "windows":
+ return "windows"
+ case "macos":
+ return "macos"
+ case "linux":
+ // Detect the Linux distribution
+ distro := detectDistro()
+ if distro == "" {
+ fmt.Println("Unable to detect Linux distribution.")
+ distro = "fixme"
+ }
+
+ fmt.Printf("Detected distribution: %s\n", distro)
+ return distro
+ default:
+ return runtime.GOOS
+ }
+}
+
+// detectDistro returns the Linux distribution name (if possible)
+func detectDistro() string {
+ // Check if we're on Linux
+
+ // Try to read /etc/os-release to determine the distro
+ file, err := os.Open("/etc/os-release")
+ if err != nil {
+ return ""
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "ID=") {
+ parts := strings.SplitN(line, "=", 2)
+ if len(parts) == 2 {
+ return strings.Trim(parts[1], `"`)
+ }
+ }
+ }
+ return ""
+}
diff --git a/hw.go b/hw.go
new file mode 100644
index 0000000..fd8f182
--- /dev/null
+++ b/hw.go
@@ -0,0 +1,33 @@
+package debian
+
+import (
+ "fmt"
+ "runtime"
+
+ "go.wit.com/lib/protobuf/zoopb"
+ "golang.org/x/sys/unix"
+)
+
+// init the installed package list
+func getMemory(me *zoopb.Machine) {
+ // Get number of CPUs
+ numCPUs := runtime.NumCPU()
+
+ // Get total system memory
+ var sysInfo unix.Sysinfo_t
+ err := unix.Sysinfo(&sysInfo)
+ if err != nil {
+ fmt.Println("Error getting system info:", err)
+ return
+ }
+
+ // Convert memory from bytes to GB
+ m := float64(sysInfo.Totalram) * float64(sysInfo.Unit)
+ me.Memory = int64(m)
+ me.Cpus = int64(numCPUs)
+
+ // totalMemGB := float64(sysInfo.Totalram) * float64(sysInfo.Unit) / (1024 * 1024 * 1024)
+ // Print results
+ // fmt.Printf("Total Memory: %.2f GB\n", totalMemGB)
+ // fmt.Printf("Number of CPUs: %d\n", numCPUs)
+}
diff --git a/init.go b/init.go
new file mode 100644
index 0000000..b529f8d
--- /dev/null
+++ b/init.go
@@ -0,0 +1,47 @@
+package debian
+
+import (
+ "os"
+
+ "go.wit.com/lib/config"
+ "go.wit.com/lib/protobuf/zoopb"
+ "go.wit.com/log"
+)
+
+// sent via -ldflags
+var VERSION string
+var BUILDTIME string
+
+/*
+func (m *zoopb.Machine) SinceLastUpdate() time.Duration {
+ age := m.Laststamp.AsTime()
+ return time.Since(age)
+}
+*/
+
+func InitMachine() (*zoopb.Machine, string) {
+ var fullname string
+ var err error
+ m := new(zoopb.Machine)
+ if fullname, err = config.LoadPB(m, "forge", "machine"); err != nil {
+ log.Info("zoopb.ConfigLoad() failed", err)
+ }
+ hostname, _ := os.Hostname()
+ m.Hostname = hostname
+ m.Distro = detectDistro()
+ m.Packages = zoopb.NewPackages()
+ initPackages(m)
+
+ InitWitMirrors(m)
+ config.SavePB(m, fullname)
+
+ return m, fullname
+}
+
+func InitDaemon() *zoopb.Machine {
+ m := new(zoopb.Machine)
+ m.Load()
+ InitWitMirrors(m)
+ m.Save()
+ return m
+}
diff --git a/old/apt.go b/old/apt.go
new file mode 100644
index 0000000..4b9018b
--- /dev/null
+++ b/old/apt.go
@@ -0,0 +1,39 @@
+package zoopb
+
+import (
+ "fmt"
+)
+
+// init the installed package list
+func initPackages(me *Machine) {
+ // Get the list of installed packages for the detected distro
+ newP, err := getPackageList(me.Distro)
+ if err != nil {
+ fmt.Println("Error:", err)
+ return
+ }
+
+ if me.Packages == nil {
+ me.Packages = new(Packages)
+ }
+
+ // Print the installed packages and their versions
+ for pkg, version := range newP {
+ new1 := new(Package)
+ new1.Name = pkg
+ new1.Version = version
+ me.Packages.Append(new1)
+ // log.Info("added", new1.Name, "failed")
+ }
+
+ me.getMemory()
+}
+
+/*
+func (me *Machine) addNew(name string, version string) {
+ new1 := new(Package)
+ new1.Name = name
+ new1.Version = version
+ me.Packages.Append(new1)
+}
+*/
diff --git a/old/apt_darwin.go b/old/apt_darwin.go
new file mode 100644
index 0000000..0fc8e0f
--- /dev/null
+++ b/old/apt_darwin.go
@@ -0,0 +1,11 @@
+package zoopb
+
+import (
+ "go.wit.com/log"
+)
+
+// getPackageList returns the list of installed packages based on the distro
+func getPackageList(distro string) (map[string]string, error) {
+ log.Info("zoopb: have not done macos yet, skipping okay")
+ return nil, nil
+}
diff --git a/old/apt_windows.go b/old/apt_windows.go
new file mode 100644
index 0000000..feec104
--- /dev/null
+++ b/old/apt_windows.go
@@ -0,0 +1,11 @@
+package zoopb
+
+import (
+ "go.wit.com/log"
+)
+
+// getPackageList returns the list of installed packages based on the distro
+func getPackageList(distro string) (map[string]string, error) {
+ log.Info("zoopb: have not done windows yet, skipping okay")
+ return nil, nil
+}
diff --git a/update.go b/update.go
new file mode 100644
index 0000000..0033447
--- /dev/null
+++ b/update.go
@@ -0,0 +1,118 @@
+package debian
+
+import (
+ "bufio"
+ "fmt"
+ "os/exec"
+ "strings"
+
+ "go.wit.com/lib/protobuf/zoopb"
+ "go.wit.com/log"
+)
+
+// getPackageList returns the list of installed packages based on the distro
+func getPackageList(distro string) (map[string]string, error) {
+ var cmd *exec.Cmd
+
+ // Run the appropriate command based on the detected distribution
+ switch distro {
+ case "ubuntu", "debian":
+ return dpkgQuery()
+ case "fedora", "centos", "rhel":
+ cmd = exec.Command("rpm", "-qa")
+ case "arch", "manjaro":
+ cmd = exec.Command("pacman", "-Q")
+ default:
+ return nil, fmt.Errorf("unsupported distribution: %s", distro)
+ }
+
+ // Capture the command's output
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ return nil, fmt.Errorf("error running command: %v", err)
+ }
+
+ // todo: Split the output into lines and return
+ lines := strings.Split(string(output), "\n")
+ log.Info("output had", len(lines), "lines")
+ return nil, nil
+}
+
+func dpkgQuery() (map[string]string, error) {
+ // Run the dpkg-query command to list installed packages and versions
+ cmd := exec.Command("dpkg-query", "-W", "-f=${Package} ${Version}\n")
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, err
+ }
+
+ // Start the command execution
+ if err := cmd.Start(); err != nil {
+ return nil, err
+ }
+ defer cmd.Wait()
+
+ // Create a map to store package names and versions
+ installedPackages := make(map[string]string)
+
+ // Use a scanner to read the output of the command line by line
+ scanner := bufio.NewScanner(stdout)
+ for scanner.Scan() {
+ line := scanner.Text()
+ // Split each line into package name and version
+ parts := strings.SplitN(line, " ", 2)
+ if len(parts) == 2 {
+ packageName := parts[0]
+ version := parts[1]
+ installedPackages[packageName] = version
+ }
+ }
+
+ // Return the map with package names and versions
+ return installedPackages, scanner.Err()
+}
+
+/*
+func (me *Machine) UpdatePackages() string {
+ log.Info("fixme. broken after move to autogenpb")
+ return ""
+}
+*/
+
+func UpdatePackages(me *zoopb.Machine) string {
+ // Get the list of installed packages for the detected distro
+ newP, err := getPackageList(me.Distro)
+ if err != nil {
+ fmt.Println("Error:", err)
+ return fmt.Sprintln("getPackageList()", err)
+ }
+
+ var newCounter, changeCounter int
+ // Print the installed packages and their versions
+ for pname, version := range newP {
+ found := me.Packages.FindByName(pname)
+ if found == nil {
+ log.Info("adding new", pname, version)
+ new1 := new(zoopb.Package)
+ new1.Name = pname
+ new1.Version = version
+ me.Packages.Append(new1)
+ newCounter += 1
+ } else {
+ found.Version = version
+ // panic("redo this. broken after autogenpb. was never right anyway")
+ //if me.Packages.Update(found) {
+ // changeCounter += 1
+ //}
+ }
+ }
+
+ footer := fmt.Sprintf("%s has distro %s with %d packages installed", me.Hostname, me.Distro, me.Packages.Len())
+ if changeCounter != 0 {
+ footer += fmt.Sprintf(" (%d changed)", changeCounter)
+ }
+ if newCounter != 0 {
+ footer += fmt.Sprintf(" (%d new)", newCounter)
+ }
+ return footer
+}
diff --git a/wit.go b/wit.go
new file mode 100644
index 0000000..10d1f52
--- /dev/null
+++ b/wit.go
@@ -0,0 +1,135 @@
+package debian
+
+import (
+ "bufio"
+ "os"
+ "strings"
+
+ "go.wit.com/lib/fhelp"
+ "go.wit.com/lib/protobuf/zoopb"
+)
+
+// obviously a hack at this point
+// read the package list file from mirrors.wit.com
+func InitWitMirrors(m *zoopb.Machine) error {
+ m.Wit = zoopb.NewPackages()
+ err := scanPackageListFile(m, "/var/lib/apt/lists/mirrors.wit.com_wit_dists_sid_main_binary-amd64_Packages")
+ return err
+}
+
+// adds the package if the name isn't there
+// if it's newer, remove the old package and use the new one
+func AddIfNewer(all *zoopb.Packages, p *zoopb.Package) {
+ check := all.FindByName(p.Name)
+ if check == nil {
+ all.Append(p)
+ return
+ }
+ v1, _ := fhelp.NewDebVersion(check.Version)
+ v2, _ := fhelp.NewDebVersion(p.Version)
+ if v1.Equal(v2) {
+ // log.Info("do nothing", v1, v2)
+ return
+ }
+ if v1.LessThan(v2) {
+ // log.Info("removing", v1, "using", v2)
+ all.Delete(check)
+ all.Append(p)
+ } else {
+ // log.Info("keeping", v1, "got:", v2)
+ }
+}
+
+// breaks up the apt list file into sections
+// then sends each section to be processed
+// and added to zoopb.Machine.Wit
+func scanPackageListFile(m *zoopb.Machine, filename string) error {
+ file, err := os.Open(filename)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ scanner := bufio.NewScanner(file)
+ var debInfo string
+ for scanner.Scan() {
+ line := scanner.Text()
+ if line == "" {
+ p := parsePackageInfo(debInfo)
+ AddIfNewer(m.Wit, p)
+ debInfo = ""
+ }
+ debInfo += line + "\n"
+ }
+ p := parsePackageInfo(debInfo)
+ m.Wit.Append(p)
+ return nil
+}
+
+/*
+func (m *Machine) addPackage(name string, version string, filename string) {
+ if name == "" {
+ return
+ }
+ // log.Info("addPackage:", name, version, filename)
+ var deb *DebPackage
+ var ok bool
+ deb, ok = allp[name]
+ if !ok {
+ deb = NewPackage()
+ deb.name.SetLabel(name)
+ allp[name] = deb
+ }
+ newversion := new(Version)
+ newversion.v = version
+ newversion.file = filename
+ deb.versions = append(deb.versions, newversion)
+}
+*/
+
+// parses dpkg -s foo.deb
+func parsePackageInfo(lines string) *zoopb.Package {
+ var name string
+ var version string
+ var filename string
+ var gopath string
+
+ for _, line := range strings.Split(lines, "\n") {
+ if line == "" {
+ continue
+ }
+ if strings.HasPrefix(line, " ") {
+ // these are usually Description: lines
+ continue
+ }
+ if strings.HasPrefix(line, "#") {
+ // skip comment lines. (probably doesn't happen in debian list files
+ continue
+ }
+ line = strings.TrimSpace(line)
+ parts := strings.Split(line, " ")
+ if len(parts) < 2 {
+ continue
+ }
+ if parts[0] == "Package:" {
+ name = parts[1]
+ }
+ if parts[0] == "Version:" {
+ version = parts[1]
+ }
+ if parts[0] == "Filename:" {
+ filename = strings.Join(parts[1:], " ")
+ }
+ if parts[0] == "GoPath:" {
+ gopath = parts[1]
+ }
+ }
+
+ p := zoopb.Package{
+ Name: name,
+ Version: version,
+ PkgName: filename,
+ SrcPath: gopath,
+ }
+
+ return &p
+}