orchard ssh vm: introduce exec mode (#72)

* orchard ssh vm: introduce exec mode

* Document "tart vm ssh" exec mode
This commit is contained in:
Nikolay Edigaryev
2023-04-05 11:05:27 -04:00
committed by GitHub
parent 4eafec99a5
commit 316f785a0c
2 changed files with 41 additions and 4 deletions
+16
View File
@@ -32,6 +32,8 @@ orchard list vms
### Accessing Virtual Machines
#### SSH
To SSH into a VM use the `orchard ssh` command:
```shell
@@ -40,6 +42,20 @@ orchard ssh vm ventura-base
You can specify the `--username` and `--password` flags to specify the username/password pair to SSH. By default, `admin`/`admin` is used.
You can also execute remote commands instead of spawning a login shell, similarly to the OpenSSH's `ssh` command:
```shell
orchard ssh vm ventura-base "uname -a"
```
You can execute scripts remotely this way, by telling the remote command-line interpreter to read from the standard input and using the redirection operator as follows:
```shell
orchard ssh vm ventura-base "bash -s" < script.sh
```
#### VNC
Similar to `ssh` command, you can use `vnc` command to open Screen Sharing into a remote VM:
```shell
+25 -4
View File
@@ -22,9 +22,9 @@ var wait uint16
func newSSHVMCommand() *cobra.Command {
command := &cobra.Command{
Use: "vm VM_NAME",
Use: "vm VM_NAME [COMMAND]",
Short: "SSH into the VM",
Args: cobra.ExactArgs(1),
Args: cobra.RangeArgs(1, 2),
RunE: runSSHVM,
}
@@ -39,8 +39,16 @@ func newSSHVMCommand() *cobra.Command {
}
func runSSHVM(cmd *cobra.Command, args []string) error {
// Required NAME argument
name := args[0]
// Optional [COMMAND] argument
var command string
if len(args) > 1 {
command = args[1]
}
client, err := client.New()
if err != nil {
return err
@@ -70,6 +78,9 @@ func runSSHVM(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("%w: failed to establish an SSH connection: %v", ErrFailed, err)
}
defer func() {
_ = sshConn.Close()
}()
sshClient := ssh.NewClient(sshConn, chans, reqs)
@@ -77,6 +88,17 @@ func runSSHVM(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("%w: failed to open an SSH session: %v", ErrFailed, err)
}
defer func() {
_ = sshSess.Close()
}()
if command != "" {
sshSess.Stdout = os.Stdout
sshSess.Stderr = os.Stderr
sshSess.Stdin = os.Stdin
return sshSess.Run(command)
}
// Switch controlling terminal into raw mode,
// otherwise ANSI escape sequences that allow
@@ -109,7 +131,6 @@ func runSSHVM(cmd *cobra.Command, args []string) error {
go func() {
_, _ = io.Copy(sshSessStdinPipe, os.Stdin)
_ = sshSessStdinPipe.Close()
_ = sshSess.Close()
}()
// Periodically adjust remote terminal size
@@ -176,7 +197,7 @@ func ChooseUsernameAndPassword(
}
// Fall back
fmt.Println("no credentials specified or found, trying default admin:admin credentials...")
_, _ = fmt.Fprintf(os.Stderr, "no credentials specified or found, trying default admin:admin credentials...")
return "admin", "admin"
}