mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
establish SSH connection when adding a new machine
This commit is contained in:
+46
-2
@@ -10,6 +10,7 @@ import (
|
||||
"uncloud/internal/cli/config"
|
||||
"uncloud/internal/machine/api/pb"
|
||||
"uncloud/internal/secret"
|
||||
"uncloud/internal/sshexec"
|
||||
)
|
||||
|
||||
const defaultClusterName = "default"
|
||||
@@ -196,9 +197,52 @@ func (cli *CLI) AddMachine(ctx context.Context, remoteMachine RemoteMachine, clu
|
||||
if err != nil {
|
||||
return fmt.Errorf("connect to cluster: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = c.Close()
|
||||
}()
|
||||
|
||||
sshClient, err := sshexec.Connect(remoteMachine.User, remoteMachine.Host, remoteMachine.Port, remoteMachine.KeyPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"SSH login to remote machine %s: %w",
|
||||
config.NewSSHDestination(remoteMachine.User, remoteMachine.Host, remoteMachine.Port), err,
|
||||
)
|
||||
}
|
||||
machineExec := sshexec.NewRemote(sshClient)
|
||||
|
||||
// TODO: Check if the machine is already provisioned using machineClient and ask the user to reset it first.
|
||||
//conn := connector.NewSSHConnectorFromClient(sshClient)
|
||||
//machineClient, err := client.New(ctx, conn)
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("connect to remote machine API: %w", err)
|
||||
//}
|
||||
|
||||
// TODO: Download and install the latest uncloudd binary by running the install shell script from GitHub.
|
||||
// For now upload the binary using scp manually.
|
||||
if _, err = machineExec.Run(ctx, "which uncloudd"); err != nil {
|
||||
return fmt.Errorf("uncloudd binary not found on the remote machine: %w", err)
|
||||
}
|
||||
|
||||
//req := &pb.AddMachineRequest{
|
||||
// Name: machineName,
|
||||
// Network: &pb.NetworkConfig{
|
||||
//
|
||||
// }
|
||||
//}
|
||||
//resp, err := c.AddMachine(ctx, req)
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("add machine to cluster: %w", err)
|
||||
//}
|
||||
|
||||
// TODO:
|
||||
// --1. Establish a client connection to the remote machine.
|
||||
// --2. Check if the machine is already provisioned and ask the user to reset it first.
|
||||
// --3. Download and install the latest uncloudd binary by running the install shell script from GitHub.
|
||||
// 4. Request token from the remote machine.
|
||||
// 5. Add the machine to the cluster using its token and receive a configuration token.
|
||||
// 6. Request the machine to join the cluster using the configuration token.
|
||||
// 7. Save the machine's SSH connection details in the cluster config.
|
||||
|
||||
fmt.Println("Adding machine to cluster...", c)
|
||||
// TODO
|
||||
//name, connCfg, err := c.AddMachine(ctx, machineName, user, host, port, sshKeyPath)
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("add machine to cluster %q: %w", cluster.Name(), err)
|
||||
|
||||
@@ -2,7 +2,6 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"errors"
|
||||
"fmt"
|
||||
"google.golang.org/grpc"
|
||||
@@ -297,11 +296,3 @@ func (c *ClusterClient) registerNewMachine(
|
||||
}
|
||||
return c.client.AddMachine(ctx, req)
|
||||
}
|
||||
|
||||
func privateKeyFromSecret(s secret.Secret) (ed25519.PrivateKey, error) {
|
||||
// Cluster secret in the config is a hex-encoded private key seed.
|
||||
if len(s) != ed25519.SeedSize {
|
||||
return nil, fmt.Errorf("invalid cluster secret length")
|
||||
}
|
||||
return ed25519.NewKeyFromSeed(s), nil
|
||||
}
|
||||
|
||||
@@ -41,13 +41,23 @@ func NewSSHConnector(cfg *SSHConnectorConfig) *SSHConnector {
|
||||
return c
|
||||
}
|
||||
|
||||
func NewSSHConnectorFromClient(client *ssh.Client) *SSHConnector {
|
||||
return &SSHConnector{client: client}
|
||||
}
|
||||
|
||||
// TODO: handle context cancelation.
|
||||
func (c *SSHConnector) Connect(ctx context.Context) (*grpc.ClientConn, error) {
|
||||
if c.client == nil {
|
||||
// Establish an SSH connection if the SSH client is not provided.
|
||||
if c.config == (SSHConnectorConfig{}) {
|
||||
return nil, fmt.Errorf("SSH connector not configured")
|
||||
}
|
||||
var err error
|
||||
c.client, err = sshexec.Connect(c.config.User, c.config.Host, c.config.Port, c.config.KeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SSH login to %s@%s:%d: %w", c.config.User, c.config.Host, c.config.Port, err)
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := grpc.NewClient(
|
||||
"unix://"+c.config.APISockPath,
|
||||
|
||||
@@ -18,6 +18,8 @@ type MachineConnection struct {
|
||||
PublicKey secret.Secret `toml:"public_key,omitempty"`
|
||||
}
|
||||
|
||||
// SSHDestination represents an SSH destination string in the canonical form of "user@host:port".
|
||||
// The default user "root" and port 22 can be omitted.
|
||||
type SSHDestination string
|
||||
|
||||
func NewSSHDestination(user, host string, port int) SSHDestination {
|
||||
@@ -37,10 +39,16 @@ func (d SSHDestination) Parse() (user string, host string, port int, err error)
|
||||
if strings.Contains(host, "@") {
|
||||
user, host, _ = strings.Cut(host, "@")
|
||||
}
|
||||
if user == "" {
|
||||
user = DefaultSSHUser
|
||||
}
|
||||
h, p, sErr := net.SplitHostPort(host)
|
||||
if sErr == nil {
|
||||
host = h
|
||||
port, err = strconv.Atoi(p)
|
||||
}
|
||||
if port == 0 {
|
||||
port = DefaultSSHPort
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user