Fix BZZZ deployment system and deploy to ironwood

## Major Fixes:
1. **Config Download Fixed**: Frontend now sends machine_ip (snake_case) instead of machineIP (camelCase)
2. **Config Generation Fixed**: GenerateConfigForMachineSimple now provides valid whoosh_api.base_url
3. **Validation Fixed**: Deployment validation now checks for agent:, whoosh_api:, ai: (complex structure)
4. **Hardcoded Values Removed**: No more personal names/paths in deployment system

## Deployment Results:
-  Config validation passes: "Configuration loaded and validated successfully"
-  Remote deployment works: BZZZ starts in normal mode on deployed machines
-  ironwood (192.168.1.113) successfully deployed with systemd service
-  P2P networking operational with peer discovery

## Technical Details:
- Updated api/setup_manager.go: Fixed config generation and validation logic
- Updated main.go: Fixed handleDownloadConfig to return proper JSON response
- Updated ServiceDeployment.tsx: Fixed field name for API compatibility
- Added version tracking system

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-08-31 21:49:05 +10:00
parent be761cfe20
commit da1b42dc33
14 changed files with 923 additions and 285 deletions

67
main.go
View File

@@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"reflect"
"runtime"
"time"
"chorus.services/bzzz/api"
@@ -20,6 +21,7 @@ import (
"chorus.services/bzzz/p2p"
"chorus.services/bzzz/pkg/config"
"chorus.services/bzzz/pkg/crypto"
"chorus.services/bzzz/pkg/version"
"chorus.services/bzzz/pkg/dht"
"chorus.services/bzzz/pkg/election"
"chorus.services/bzzz/pkg/health"
@@ -105,12 +107,22 @@ func main() {
// Parse command line arguments
var configPath string
var setupMode bool
var showVersion bool
flag.StringVar(&configPath, "config", "", "Path to configuration file")
flag.BoolVar(&setupMode, "setup", false, "Start in setup mode")
flag.BoolVar(&showVersion, "version", false, "Show version information")
flag.Parse()
fmt.Println("🚀 Starting Bzzz v1.0.2 + HMMM P2P Task Coordination System...")
// Handle version flag
if showVersion {
fmt.Printf("BZZZ %s\n", version.FullVersion())
fmt.Printf("Build Date: %s\n", time.Now().Format("2006-01-02"))
fmt.Printf("Go Version: %s\n", runtime.Version())
return
}
fmt.Printf("🚀 Starting Bzzz %s + HMMM P2P Task Coordination System...\n", version.FullVersion())
// Determine config file path with priority order:
// 1. Command line argument
@@ -515,7 +527,7 @@ func main() {
shutdownManager := shutdown.NewManager(30*time.Second, &simpleLogger{})
// Initialize health manager
healthManager := health.NewManager(node.ID().ShortString(), "v0.2.0", &simpleLogger{})
healthManager := health.NewManager(node.ID().ShortString(), version.FullVersion(), &simpleLogger{})
healthManager.SetShutdownManager(shutdownManager)
// Register health checks
@@ -936,7 +948,7 @@ func announceCapabilitiesOnChange(ps *pubsub.PubSub, nodeID string, cfg *config.
"node_id": nodeID,
"capabilities": cfg.Agent.Capabilities,
"models": cfg.Agent.Models,
"version": "0.2.0",
"version": version.Version(),
"specialization": cfg.Agent.Specialization,
}
@@ -1246,6 +1258,8 @@ func startSetupMode(configPath string) {
http.HandleFunc("/api/setup/discover-machines", corsHandler(handleDiscoverMachines(setupManager)))
http.HandleFunc("/api/setup/test-ssh", corsHandler(handleTestSSH(setupManager)))
http.HandleFunc("/api/setup/deploy-service", corsHandler(handleDeployService(setupManager)))
http.HandleFunc("/api/setup/download-config", corsHandler(handleDownloadConfig(setupManager)))
http.HandleFunc("/api/version", corsHandler(handleVersion()))
http.HandleFunc("/api/health", corsHandler(handleSetupHealth))
fmt.Printf("🎯 Setup interface available at: http://localhost:8090\n")
@@ -1320,6 +1334,53 @@ func handleSetupRequired(sm *api.SetupManager) http.HandlerFunc {
}
}
func handleVersion() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
response := map[string]interface{}{
"version": version.Version(),
"full_version": version.FullVersion(),
"timestamp": time.Now().Unix(),
}
json.NewEncoder(w).Encode(response)
}
}
func handleDownloadConfig(sm *api.SetupManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var req struct {
MachineIP string `json:"machine_ip"`
Config map[string]interface{} `json:"config"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
// Generate the same config that would be deployed
configYAML, err := sm.GenerateConfigForMachineSimple(req.MachineIP, req.Config)
if err != nil {
http.Error(w, fmt.Sprintf("Failed to generate config: %v", err), http.StatusInternalServerError)
return
}
// Return JSON response with YAML content
w.Header().Set("Content-Type", "application/json")
response := map[string]interface{}{
"success": true,
"configYAML": configYAML,
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
}
func handleSystemDetection(sm *api.SetupManager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")