Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"io/ioutil"
"net"
"net/url"
"os"
"os/user"
"path/filepath"
Expand Down Expand Up @@ -43,16 +44,27 @@ func (e ErrConnect) Error() string {

// parseHost parses and normalizes <user>@<host:port> from a given string.
func (c *SSHClient) parseHost(host string) error {
c.host = host
// https://golang.org/pkg/net/url/#URL
// [scheme:][//[userinfo@]host][/]path[?query][#fragment]
if !strings.Contains(host, "://") && !strings.HasPrefix(host, "//") {
host = "ssh://" + host
}

hostURL, err := url.Parse(host)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you test this with:

127.0.0.1
localhost
localhost:22
ssh://localhost

etc.?

I know url.Parse(host) had some issues with localhost URLs.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VojtechVitek what is the issues?

here is a simple test:

sup kadefor$ cat ssh_test.go
package sup

import (
	"fmt"
	"testing"
)

func Test_parseHost(t *testing.T) {
	hosts := []string{
		"127.0.0.1",
		"localhost",
		"localhost:22",
		"ssh://localhost",

		"tom@127.0.0.1",
		"tom@localhost",
		"tom@localhost:22",
		"ssh://tom@localhost",

		"tom:11@@33@127.0.0.1",
		"tom:11@@33@localhost",
		"tom:11@@33@localhost:22",
		"ssh://tom:11@@33@localhost",
	}

	for _, host := range hosts {
		c := &SSHClient{}
		err := c.parseHost(host)
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Printf("%s\n\t%v\n", host, c)
		}
	}
}
sup kadefor$ go test
127.0.0.1
	&{<nil> <nil> kadefor 127.0.0.1:22 <nil> <nil> <nil> false false false export SUP_HOST="127.0.0.1:22"; }
localhost
	&{<nil> <nil> kadefor localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
localhost:22
	&{<nil> <nil> kadefor localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
ssh://localhost
	&{<nil> <nil> kadefor localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
tom@127.0.0.1
	&{<nil> <nil> tom 127.0.0.1:22 <nil> <nil> <nil> false false false export SUP_HOST="127.0.0.1:22"; }
tom@localhost
	&{<nil> <nil> tom localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
tom@localhost:22
	&{<nil> <nil> tom localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
ssh://tom@localhost
	&{<nil> <nil> tom localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
tom:11@@33@127.0.0.1
	&{<nil> <nil> tom 127.0.0.1:22 <nil> <nil> <nil> false false false export SUP_HOST="127.0.0.1:22"; }
tom:11@@33@localhost
	&{<nil> <nil> tom localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
tom:11@@33@localhost:22
	&{<nil> <nil> tom localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
ssh://tom:11@@33@localhost
	&{<nil> <nil> tom localhost:22 <nil> <nil> <nil> false false false export SUP_HOST="localhost:22"; }
PASS
ok  	github.com/pressly/sup	0.014s

if err != nil {
return err
}

// Remove extra "ssh://" schema
if len(c.host) > 6 && c.host[:6] == "ssh://" {
c.host = c.host[6:]
// Add default port, if not set
hostname := hostURL.Hostname()
port := hostURL.Port()
if port == "" {
port = "22"
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice refactor, thanks!

c.host = net.JoinHostPort(hostname, port)

if at := strings.Index(c.host, "@"); at != -1 {
c.user = c.host[:at]
c.host = c.host[at+1:]
if u := hostURL.User.Username(); u != "" {
c.user = u
}

// Add default user, if not set
Expand All @@ -64,14 +76,7 @@ func (c *SSHClient) parseHost(host string) error {
c.user = u.Username
}

if strings.Index(c.host, "/") != -1 {
return ErrConnect{c.user, c.host, "unexpected slash in the host URL"}
}

// Add default port, if not set
if strings.Index(c.host, ":") == -1 {
c.host += ":22"
}
c.env = c.env + `export SUP_HOST="` + c.host + `";`

return nil
}
Expand Down
2 changes: 1 addition & 1 deletion sup.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (sup *Stackup) Run(network *Network, envVars EnvList, commands ...*Command)

// SSH client.
remote := &SSHClient{
env: env + `export SUP_HOST="` + host + `";`,
env: env,
user: network.User,
color: Colors[i%len(Colors)],
}
Expand Down