Browse Source

add urbit status init to broadcast boostrap

reid 2 năm trước cách đây
mục cha
commit
4978ab4103
4 tập tin đã thay đổi với 131 bổ sung33 xóa
  1. 86 18
      broadcast/broadcast.go
  2. 42 12
      docker/docker.go
  3. 3 3
      main.go
  4. 0 0
      settings/system.json

+ 86 - 18
broadcast/broadcast.go

@@ -3,10 +3,12 @@ package broadcast
 import (
 	"encoding/json"
 	"goseg/config"
+	"goseg/docker"
 	"goseg/structs"
 	"log/slog"
 	"os"
 	"reflect"
+	"strings"
 	"sync"
 	"fmt"
 
@@ -20,7 +22,7 @@ var (
 	mu             sync.RWMutex // synchronize access to broadcastState
 )
 
-func init(){
+func init() {
 	// initialize broadcastState global var
 	config := config.Conf()
 	broadcast, err := bootstrapBroadcastState(config)
@@ -38,6 +40,7 @@ func RegisterClient(conn *websocket.Conn) {
 	if err != nil {
 		return
 	}
+	// when a new ws client registers, send them the current broadcast
 	if err := conn.WriteMessage(websocket.TextMessage, broadcastJson); err != nil {
 		fmt.Println("Error writing response:", err)
 		return
@@ -52,28 +55,93 @@ func UnregisterClient(conn *websocket.Conn) {
 // take in config file and addt'l info to initialize broadcast
 func bootstrapBroadcastState(config structs.SysConfig) (structs.AuthBroadcast, error) {
 	var res structs.AuthBroadcast
+	piers := config.Piers
+	pierStatus, err := docker.GetShipStatus(piers)
+	if err != nil {
+		errmsg := fmt.Sprintf("Unable to bootstrap urbit states: %v",err)
+		logger.Error(errmsg)
+		return res, err
+	}
+	updates := make(map[string]structs.Urbit)
+	for pier, status := range pierStatus {
+		urbit := structs.Urbit{}
+		if existingUrbit, exists := broadcastState.Urbits[pier]; exists {
+			// If the ship already exists in broadcastState, use its current state
+			urbit = existingUrbit
+		}
+		isRunning := (status == "Up" || strings.HasPrefix(status, "Up "))
+		urbit.Info.Running = isRunning
+		updates[pier] = urbit
+	}
+	// update broadcastState
+	err = UpdateBroadcastState(map[string]interface{}{
+		"Urbits": updates,
+	})
+	if err != nil {
+		errmsg := fmt.Sprintf("Unable to update broadcast state: %v", err)
+		logger.Error(errmsg)
+		return res, err
+	}
+	res = GetState()
 	return res, nil
 }
 
+// // update broadcastState with a map of items
+// func UpdateBroadcastState(values map[string]interface{}) error {
+// 	mu.Lock()
+// 	defer mu.Unlock()
+// 	v := reflect.ValueOf(&broadcastState).Elem()
+// 	for key, value := range values {
+// 		// we are matching the map key with the broadcastState item
+// 		field := v.FieldByName(key)
+// 		if !field.IsValid() || !field.CanSet() {
+// 			return fmt.Errorf("field %s does not exist or is not settable", key)
+// 		}
+// 		val := reflect.ValueOf(value)
+// 		if field.Type() != val.Type() {
+// 			return fmt.Errorf("type mismatch for field %s: expected %s, got %s", key, field.Type(), val.Type())
+// 		}
+// 		field.Set(val)
+// 	}
+// 	BroadcastToClients()
+// 	return nil
+// }
+
 // update broadcastState with a map of items
 func UpdateBroadcastState(values map[string]interface{}) error {
-	mu.Lock()
-	defer mu.Unlock()
-	v := reflect.ValueOf(&broadcastState).Elem()
-	for key, value := range values {
-		// we are matching the map key with the broadcastState item
-		field := v.FieldByName(key)
-		if !field.IsValid() || !field.CanSet() {
-			return fmt.Errorf("field %s does not exist or is not settable", key)
-		}
-		val := reflect.ValueOf(value)
-		if field.Type() != val.Type() {
-			return fmt.Errorf("type mismatch for field %s: expected %s, got %s", key, field.Type(), val.Type())
-		}
-		field.Set(val)
-	}
-	BroadcastToClients()
-	return nil
+    mu.Lock()
+    defer mu.Unlock()
+    return recursiveUpdate(reflect.ValueOf(&broadcastState).Elem(), reflect.ValueOf(values))
+}
+
+// this allows us to insert stuff into nested vals and not overwrite the existing contents
+func recursiveUpdate(dst, src reflect.Value) error {
+    if !dst.CanSet() {
+        return fmt.Errorf("field is not settable")
+    }
+    // If both dst and src are maps, handle them recursively
+    if dst.Kind() == reflect.Map && src.Kind() == reflect.Map {
+        for _, key := range src.MapKeys() {
+            srcVal := src.MapIndex(key)
+            // If the key doesn't exist in dst, initialize it
+            dstVal := dst.MapIndex(key)
+            if !dstVal.IsValid() {
+                dstVal = reflect.New(dst.Type().Elem()).Elem()
+            }
+            // Recursive call to handle potential nested maps
+            if err := recursiveUpdate(dstVal, srcVal); err != nil {
+                return err
+            }
+            dst.SetMapIndex(key, dstVal)
+        }
+        return nil
+    }
+    // For non-map fields or direct updates
+    if dst.Type() != src.Type() {
+        return fmt.Errorf("type mismatch: expected %s, got %s", dst.Type(), src.Type())
+    }
+    dst.Set(src)
+    return nil
 }
 
 // return broadcast state

+ 42 - 12
docker/docker.go

@@ -1,23 +1,53 @@
-package main
+package docker
 
 import (
 	"context"
 	"fmt"
+	"log/slog"
+	"os"
 
-	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/client"
+	"github.com/docker/docker/api/types"
 )
 
-func main() {
-	cli, err := client.NewClientWithOpts(client.FromEnv)
-	if err != nil {
-		panic(err)
-	}
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
+var (
+	logger         = slog.New(slog.NewJSONHandler(os.Stdout, nil))
+)
+
+func GetShipStatus(patps []string) (map[string]string, error) {
+    statuses := make(map[string]string)
+	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
 	if err != nil {
-		panic(err)
-	}
-	for _, container := range containers {
-		fmt.Printf("%s %s\n", container.ID[:10], container.Image)
+		errmsg := fmt.Sprintf("Error getting Docker info: %v", err)
+		logger.Error(errmsg)
+		return statuses, err
+	} else {
+		containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
+		if err != nil {
+			errmsg := fmt.Sprintf("Error getting containers: %v",err)
+			logger.Error(errmsg)
+			return statuses, err
+		} else {
+			for _, pier := range patps {
+				found := false
+				for _, container := range containers {
+					for _, name := range container.Names {
+						fasPier := "/" + pier
+						if name == fasPier {
+							statuses[pier] = container.Status
+							found = true
+							break
+						}
+					}
+					if found {
+						break
+					}
+				}
+				if !found {
+					statuses[pier] = "not found"
+				}
+			}
+		}
+		return statuses, nil
 	}
 }

+ 3 - 3
main.go

@@ -26,6 +26,9 @@ func main() {
 	}
 	logger.Info("Starting GroundSeg")
 	logger.Info("Urbit is love <3")
+	r := mux.NewRouter()
+	r.HandleFunc("/ws", ws.WsHandler)
+	http.ListenAndServe(":3000", r)
 	// global SysConfig var is managed through config package
 	conf := config.Conf()
 	internetAvailable := config.NetCheck("1.1.1.1:53")
@@ -50,7 +53,4 @@ func main() {
 	logger.Info(pierList)
 	// block until returns (debug)
 	<-versionUpdateChannel
-	r := mux.NewRouter()
-	r.HandleFunc("/ws", ws.WsHandler)
-	http.ListenAndServe(":3000", r)
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
settings/system.json


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác