Files
uncloud/internal/sshexec/sshcli.go
T
Luis LavenaandGitHub eea81723b8 feat(ssh+cli): Support SSH CLI on machine init and add commands (#173)
* Add SSHCLIRemote type with buildSSHArgs

Implement's Executor interface (Run, Stream, Close)

* Add UseSSHCLI field to RemoteMachine struct

Allow us to differentiate regular ssh from ssh+cli.

* Parse ssh+cli:// scheme on machine init/add

* Support SSH CLI when provisioning

* Update docs to reflect ssh+cli:// support

* Revert removal of `init` examples

Fixes copy & pasta mistake when documenting the new ssh+cli connection
methods.
2025-11-17 20:11:31 +10:00

73 lines
1.5 KiB
Go

package sshexec
import (
"context"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
)
type SSHCLIRemote struct {
user string
host string
port int
keyPath string
}
func NewSSHCLIRemote(user, host string, port int, keyPath string) *SSHCLIRemote {
return &SSHCLIRemote{
user: user,
host: host,
port: port,
keyPath: keyPath,
}
}
// TODO: Refactor and reuse this with buildDialArgs and buildSSHArgs from
// SSHCLI Connector.
func (r *SSHCLIRemote) buildSSHArgs() []string {
args := []string{"-o", "ConnectTimeout=5"}
if r.port != 0 && r.port != 22 {
args = append(args, "-p", strconv.Itoa(r.port))
}
if r.keyPath != "" {
args = append(args, "-i", r.keyPath)
}
args = append(args, r.user+"@"+r.host)
return args
}
func (r *SSHCLIRemote) Run(ctx context.Context, cmd string) (string, error) {
args := r.buildSSHArgs()
args = append(args, cmd)
execCmd := exec.CommandContext(ctx, "ssh", args...)
output, err := execCmd.CombinedOutput()
if err != nil {
return strings.TrimSpace(string(output)),
fmt.Errorf("run command on remote host: %w: %s", err, string(output))
}
return strings.TrimSpace(string(output)), nil
}
func (r *SSHCLIRemote) Stream(ctx context.Context, cmd string, stdout, stderr io.Writer) error {
args := r.buildSSHArgs()
args = append(args, cmd)
execCmd := exec.CommandContext(ctx, "ssh", args...)
execCmd.Stdout = stdout
execCmd.Stderr = stderr
return execCmd.Run()
}
// no-op as there is no persistent connection.
func (r *SSHCLIRemote) Close() error {
return nil
}