feat(nodes): Add Node via SSH — join any host to Swarm cluster
- client/src/pages/Nodes.tsx:
• Added showAddNode state (useState(false))
• Added 'Add Node' button (green, UserPlus icon) in page header toolbar
• Added 'Add Node via SSH' button in Nodes tab toolbar (always visible)
• Added 'Add Node via SSH' button in empty-state of Nodes tab
• Rendered <AddNodeDialog> overlay when showAddNode=true;
onSuccess refreshes nodesQ + swarmInfoQ then closes dialog
• AddNodeDialog component was already implemented: SSH host/port/user/
password/role inputs, live result display (green/red), command echo
- server/gateway-proxy.ts:
• joinSwarmNodeViaSSH() — POST /api/swarm/join-node with SSH credentials
- server/routers.ts:
• nodes.joinNode mutation — validates input, calls joinSwarmNodeViaSSH,
throws if gateway unavailable
- gateway/internal/api/handlers.go:
• POST /api/swarm/join-node handler (SwarmJoinNodeViaSSH):
retrieves join token, SSHes to remote host via golang.org/x/crypto/ssh,
runs 'docker swarm join --token <token> <managerAddr>',
handles already-member case as success
- gateway/cmd/gateway/main.go:
• Route registered: r.Post("/swarm/join-node", h.SwarmJoinNodeViaSSH)
- gateway/go.mod + go.sum:
• Added golang.org/x/crypto v0.37.0 dependency for SSH client support