terraform/vendor/github.com/scaleway/scaleway-cli/pkg/sshcommand/sshcommand.go

125 lines
2.5 KiB
Go

package sshcommand
import (
"fmt"
"runtime"
"strings"
)
// Command contains settings to build a ssh command
type Command struct {
Host string
User string
Port int
SSHOptions []string
Gateway *Command
Command []string
Debug bool
NoEscapeCommand bool
SkipHostKeyChecking bool
Quiet bool
AllocateTTY bool
EnableSSHKeyForwarding bool
isGateway bool
}
// New returns a minimal Command
func New(host string) *Command {
return &Command{
Host: host,
}
}
func (c *Command) applyDefaults() {
if strings.Contains(c.Host, "@") {
parts := strings.Split(c.Host, "@")
c.User = parts[0]
c.Host = parts[1]
}
if c.Port == 0 {
c.Port = 22
}
if c.isGateway {
c.SSHOptions = []string{"-W", "%h:%p"}
}
}
// Slice returns an execve compatible slice of arguments
func (c *Command) Slice() []string {
c.applyDefaults()
slice := []string{}
slice = append(slice, "ssh")
if c.EnableSSHKeyForwarding {
slice = append(slice, "-A")
}
if c.Quiet {
slice = append(slice, "-q")
}
if c.SkipHostKeyChecking {
slice = append(slice, "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no")
}
if len(c.SSHOptions) > 0 {
slice = append(slice, c.SSHOptions...)
}
if c.Gateway != nil {
c.Gateway.isGateway = true
slice = append(slice, "-o", "ProxyCommand="+c.Gateway.String())
}
if c.User != "" {
slice = append(slice, "-l", c.User)
}
slice = append(slice, c.Host)
if c.AllocateTTY {
slice = append(slice, "-t", "-t")
}
slice = append(slice, "-p", fmt.Sprintf("%d", c.Port))
if len(c.Command) > 0 {
slice = append(slice, "--", "/bin/sh", "-e")
if c.Debug {
slice = append(slice, "-x")
}
slice = append(slice, "-c")
var escapedCommand []string
if c.NoEscapeCommand {
escapedCommand = c.Command
} else {
escapedCommand = []string{}
for _, part := range c.Command {
escapedCommand = append(escapedCommand, fmt.Sprintf("%q", part))
}
}
slice = append(slice, fmt.Sprintf("%q", strings.Join(escapedCommand, " ")))
}
if runtime.GOOS == "windows" {
slice[len(slice)-1] = slice[len(slice)-1] + " " // Why ?
}
return slice
}
// String returns a copy-pasteable command, useful for debugging
func (c *Command) String() string {
slice := c.Slice()
for i := range slice {
quoted := fmt.Sprintf("%q", slice[i])
if strings.Contains(slice[i], " ") || len(quoted) != len(slice[i])+2 {
slice[i] = quoted
}
}
return strings.Join(slice, " ")
}