status.go
112 lines1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package commands
import (
"flag"
"fmt"
"log"
"os"
"strings"
"time"
)
const statusUsage = `Show deployment status
Usage:
congo status [flags]
Flags:
--server <name> Show status for a specific instance
Shows running services and connectivity for all deployed instances.
Examples:
congo status # all instances
congo status --server web-1 # specific instance
`
func Status() {
fs := flag.NewFlagSet("status", flag.ExitOnError)
fs.Usage = func() { fmt.Print(statusUsage) }
serverName := fs.String("server", "", "Show status for a specific instance")
fs.Parse(os.Args[2:])
cfg, err := loadInfraConfig(".")
if err != nil {
log.Fatalf("load infra.json: %v\n\nRun 'congo init <name>' to create a project first.", err)
}
all := cfg.AllInstances()
if len(all) == 0 {
fmt.Println("No instances deployed.")
fmt.Println()
if len(cfg.Servers) > 0 {
fmt.Println("Server types defined in infra.json:")
for name := range cfg.Servers {
fmt.Printf(" %s\n", name)
}
fmt.Println()
fmt.Println("Provision with: congo launch --new <server-type>")
} else {
fmt.Println("Add server types to infra.json, then run: congo launch --new <name>")
}
return
}
// Filter to a specific server if requested.
if *serverName != "" {
var filtered []Instance
for _, inst := range all {
if inst.Name == *serverName {
filtered = append(filtered, inst)
}
}
if len(filtered) == 0 {
fmt.Fprintf(os.Stderr, "Instance %q not found. Available instances:\n", *serverName)
for _, inst := range all {
fmt.Fprintf(os.Stderr, " %s (%s)\n", inst.Name, inst.IP)
}
os.Exit(1)
}
all = filtered
}
for i, inst := range all {
if i > 0 {
fmt.Println()
}
printInstanceStatus(inst)
}
}
func printInstanceStatus(inst Instance) {
server := inst.toServer()
fmt.Printf("%s (%s)\n", inst.Name, inst.IP)
// Check connectivity with a short timeout.
out, err := server.SSHWithTimeout(5*time.Second, "docker", "ps", "--format", "table {{.Names}}\t{{.Status}}\t{{.Ports}}")
if err != nil {
fmt.Println(" Status: unreachable")
if strings.Contains(err.Error(), "Connection refused") {
fmt.Println(" Hint: server may be stopped or SSH is not running")
} else if strings.Contains(err.Error(), "timed out") || strings.Contains(err.Error(), "deadline exceeded") {
fmt.Println(" Hint: connection timed out — check firewall or server status")
}
return
}
fmt.Println(" Status: connected")
lines := strings.Split(strings.TrimSpace(out), "\n")
if len(lines) <= 1 {
fmt.Println(" Services: none running")
return
}
fmt.Println()
for _, line := range lines {
fmt.Printf(" %s\n", line)
}
}