2023-03-15 16:00:52 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2015-07-10 15:56:14 +00:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
2023-05-08 16:15:44 +00:00
|
|
|
"strings"
|
2015-07-10 15:56:14 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/mitchellh/cli"
|
|
|
|
)
|
|
|
|
|
2017-09-05 04:04:32 +00:00
|
|
|
func testSSHCommand(tb testing.TB) (*cli.MockUi, *SSHCommand) {
|
|
|
|
tb.Helper()
|
2015-07-10 15:56:14 +00:00
|
|
|
|
2017-09-05 04:04:32 +00:00
|
|
|
ui := cli.NewMockUi()
|
|
|
|
return ui, &SSHCommand{
|
|
|
|
BaseCommand: &BaseCommand{
|
|
|
|
UI: ui,
|
2015-07-10 15:56:14 +00:00
|
|
|
},
|
|
|
|
}
|
2017-09-05 04:04:32 +00:00
|
|
|
}
|
2015-07-10 22:59:32 +00:00
|
|
|
|
2017-09-05 04:04:32 +00:00
|
|
|
func TestSSHCommand_Run(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
t.Skip("Need a way to setup target infrastructure")
|
2015-07-10 15:56:14 +00:00
|
|
|
}
|
2018-06-14 13:54:48 +00:00
|
|
|
|
|
|
|
func TestParseSSHCommand(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
_, cmd := testSSHCommand(t)
|
2021-04-08 16:43:39 +00:00
|
|
|
tests := []struct {
|
2018-06-14 13:54:48 +00:00
|
|
|
name string
|
|
|
|
args []string
|
|
|
|
hostname string
|
|
|
|
username string
|
|
|
|
port string
|
|
|
|
err error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"Parse just a hostname",
|
|
|
|
[]string{
|
|
|
|
"hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Parse the standard username@hostname",
|
|
|
|
[]string{
|
|
|
|
"username@hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"username",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Parse the username out of -o User=username",
|
|
|
|
[]string{
|
|
|
|
"-o", "User=username",
|
|
|
|
"hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"username",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"If the username is specified with -o User=username and realname@hostname prefer realname@",
|
|
|
|
[]string{
|
|
|
|
"-o", "User=username",
|
|
|
|
"realname@hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"realname",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Parse the port out of -o Port=2222",
|
|
|
|
[]string{
|
|
|
|
"-o", "Port=2222",
|
|
|
|
"hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"2222",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Parse the port out of -p 2222",
|
|
|
|
[]string{
|
|
|
|
"-p", "2222",
|
|
|
|
"hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"2222",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"If port is defined with -o Port=2222 and -p 2244 prefer -p",
|
|
|
|
[]string{
|
|
|
|
"-p", "2244",
|
|
|
|
"-o", "Port=2222",
|
|
|
|
"hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"2244",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Ssh args with a command",
|
|
|
|
[]string{
|
|
|
|
"hostname",
|
|
|
|
"command",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
2019-03-19 13:32:45 +00:00
|
|
|
"Flags after the ssh command are not passed because they are part of the command",
|
2018-06-14 13:54:48 +00:00
|
|
|
[]string{
|
|
|
|
"username@hostname",
|
|
|
|
"command",
|
|
|
|
"-p 22",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"username",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
2018-07-16 14:11:56 +00:00
|
|
|
{
|
|
|
|
"Allow single args which don't have a value",
|
|
|
|
[]string{
|
|
|
|
"-v",
|
|
|
|
"hostname",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Allow single args before and after the hostname and command",
|
|
|
|
[]string{
|
|
|
|
"-v",
|
|
|
|
"hostname",
|
|
|
|
"-v",
|
|
|
|
"command",
|
|
|
|
"-v",
|
|
|
|
},
|
|
|
|
"hostname",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
nil,
|
|
|
|
},
|
2018-06-14 13:54:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
hostname, username, port, err := cmd.parseSSHCommand(test.args)
|
|
|
|
if err != test.err {
|
|
|
|
t.Errorf("got error: %q want %q", err, test.err)
|
|
|
|
}
|
|
|
|
if hostname != test.hostname {
|
|
|
|
t.Errorf("got hostname: %q want %q", hostname, test.hostname)
|
|
|
|
}
|
|
|
|
if username != test.username {
|
|
|
|
t.Errorf("got username: %q want %q", username, test.username)
|
|
|
|
}
|
|
|
|
if port != test.port {
|
|
|
|
t.Errorf("got port: %q want %q", port, test.port)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-07-16 14:11:56 +00:00
|
|
|
|
|
|
|
func TestIsSingleSSHArg(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
_, cmd := testSSHCommand(t)
|
2021-04-08 16:43:39 +00:00
|
|
|
tests := []struct {
|
2018-07-16 14:11:56 +00:00
|
|
|
name string
|
|
|
|
arg string
|
|
|
|
want bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"-v is a single ssh arg",
|
|
|
|
"-v",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"-o is NOT a single ssh arg",
|
|
|
|
"-o",
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Repeated args like -vvv is still a single ssh arg",
|
|
|
|
"-vvv",
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
got := cmd.isSingleSSHArg(test.arg)
|
|
|
|
if got != test.want {
|
|
|
|
t.Errorf("arg %q got %v want %v", test.arg, got, test.want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2023-05-08 16:15:44 +00:00
|
|
|
|
|
|
|
// TestSSHCommandOmitFlagWarning checks if flags warning messages are printed
|
|
|
|
// in the output of the CLI command or not. If so, it will fail.
|
|
|
|
func TestSSHCommandOmitFlagWarning(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ui, cmd := testSSHCommand(t)
|
|
|
|
|
|
|
|
_ = cmd.Run([]string{"-mode", "ca", "-role", "otp_key_role", "user@1.2.3.4", "-extraFlag", "bug"})
|
|
|
|
|
|
|
|
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
|
|
|
|
if strings.Contains(combined, "Command flags must be provided before positional arguments. The following arguments will not be parsed as flags") {
|
|
|
|
t.Fatalf("ssh command displayed flag warnings")
|
|
|
|
}
|
|
|
|
}
|