package main import ( "context" "fmt" "strings" "time" "github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request" "github.com/spf13/cobra" ) var statusCmd = &cobra.Command{ Use: "status", Short: "Show infrastructure state and health", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { token, _ := cmd.Root().PersistentFlags().GetString("token") return cmdStatus(token) }, } func init() { rootCmd.AddCommand(statusCmd) } func cmdStatus(token string) error { state, err := loadState() if err != nil { return err } naming := state.Naming() svc, err := newService(token) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() fmt.Printf("Zone: %s\n\n", state.Zone) // Server status for _, s := range []struct { name string ss ServerState serviceName string healthURL string }{ {"Appview", state.Appview, naming.Appview(), "http://localhost:5000/health"}, {"Hold", state.Hold, naming.Hold(), "http://localhost:8080/xrpc/_health"}, } { fmt.Printf("%-8s UUID: %s\n", s.name, s.ss.UUID) fmt.Printf(" Public: %s\n", s.ss.PublicIP) fmt.Printf(" Private: %s\n", s.ss.PrivateIP) if s.ss.UUID != "" { details, err := svc.GetServerDetails(ctx, &request.GetServerDetailsRequest{ UUID: s.ss.UUID, }) if err != nil { fmt.Printf(" State: error (%v)\n", err) } else { fmt.Printf(" State: %s\n", details.State) } } // SSH health check if s.ss.PublicIP != "" { output, err := runSSH(s.ss.PublicIP, fmt.Sprintf( "systemctl is-active %s 2>/dev/null || echo 'inactive'; curl -sf %s > /dev/null 2>&1 && echo 'health:ok' || echo 'health:fail'", s.serviceName, s.healthURL, ), false) if err != nil { fmt.Printf(" Service: unreachable\n") } else { lines := strings.Split(strings.TrimSpace(output), "\n") for _, line := range lines { line = strings.TrimSpace(line) if line == "active" || line == "inactive" { fmt.Printf(" Service: %s\n", line) } else if strings.HasPrefix(line, "health:") { fmt.Printf(" Health: %s\n", strings.TrimPrefix(line, "health:")) } } } } fmt.Println() } // Scanner status (runs on hold server) if state.ScannerEnabled { fmt.Printf("Scanner (on hold server)\n") if state.Hold.PublicIP != "" { output, err := runSSH(state.Hold.PublicIP, fmt.Sprintf( "systemctl is-active %s 2>/dev/null || echo 'inactive'; curl -sf http://localhost:9090/healthz > /dev/null 2>&1 && echo 'health:ok' || echo 'health:fail'", naming.Scanner(), ), false) if err != nil { fmt.Printf(" Service: unreachable\n") } else { lines := strings.Split(strings.TrimSpace(output), "\n") for _, line := range lines { line = strings.TrimSpace(line) if line == "active" || line == "inactive" { fmt.Printf(" Service: %s\n", line) } else if strings.HasPrefix(line, "health:") { fmt.Printf(" Health: %s\n", strings.TrimPrefix(line, "health:")) } } } } fmt.Println() } // LB status if state.LB.UUID != "" { fmt.Printf("Load Balancer: %s\n", state.LB.UUID) lb, err := svc.GetLoadBalancer(ctx, &request.GetLoadBalancerRequest{ UUID: state.LB.UUID, }) if err != nil { fmt.Printf(" State: error (%v)\n", err) } else { fmt.Printf(" State: %s\n", lb.OperationalState) for _, n := range lb.Networks { fmt.Printf(" Network (%s): %s\n", n.Type, n.DNSName) } } } fmt.Printf("\nNetwork: %s\n", state.Network.UUID) if state.ObjectStorage.UUID != "" { fmt.Printf("\nObject Storage: %s\n", state.ObjectStorage.UUID) fmt.Printf(" Endpoint: %s\n", state.ObjectStorage.Endpoint) fmt.Printf(" Region: %s\n", state.ObjectStorage.Region) fmt.Printf(" Bucket: %s\n", state.ObjectStorage.Bucket) fmt.Printf(" Access Key: %s\n", state.ObjectStorage.AccessKeyID) } return nil }