Skip to content

Commit

Permalink
feat(context): Get ssh hostname from context, instead of hard-coded s…
Browse files Browse the repository at this point in the history
…tring (#1020)

* fix: Use envd-server in the context

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* feat: Add ssh address discovery

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

* fix: Remove unused struct

Signed-off-by: Ce Gao <cegao@tensorchord.ai>

Signed-off-by: Ce Gao <cegao@tensorchord.ai>
  • Loading branch information
gaocegege committed Oct 13, 2022
1 parent 51af450 commit 0fc4d8d
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 15 deletions.
4 changes: 2 additions & 2 deletions docs/proposals/20220603-kubernetes-vendor.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ Users may use `envd` to build the image, and use it on Kubernetes. Thus they nee
The end-to-end process will be:

```
$ envd context create --name test --builder-name test --use --builder kube-pod --runner server --runner-addr http://localhost:2222
$ envd context create --name test --builder-name test --use --builder kube-pod --runner server --runner-addr http://localhost:8080
$ envd login
$ envd build
$ envd push
$ envd run --env test --image test
or
$ envd context create --name test --builder-name test --use --builder kube-pod --runner server --runner-addr http://localhost:2222
$ envd context create --name test --builder-name test --use --builder kube-pod --runner server --runner-addr http://localhost:8080
$ envd login
$ envd up
```
Expand Down
9 changes: 8 additions & 1 deletion pkg/app/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,14 @@ func create(clicontext *cli.Context) error {
logrus.Debugf("container %s is running", res.Name)

logrus.Debugf("add entry %s to SSH config.", res.Name)
hostname, err := c.GetSSHHostname()
if err != nil {
return errors.Wrap(err, "failed to get the ssh hostname")
}

eo := sshconfig.EntryOptions{
Name: res.Name,
IFace: localhost,
IFace: hostname,
Port: res.SSHPort,
PrivateKeyPath: clicontext.Path("private-key"),
EnableHostKeyCheck: false,
Expand All @@ -111,6 +116,8 @@ func create(clicontext *cli.Context) error {
opt.Port = res.SSHPort
opt.AgentForwarding = false
opt.User = res.Name
opt.Server = hostname

sshClient, err := ssh.NewClient(opt)
if err != nil {
return errors.Wrap(err, "failed to create the ssh client")
Expand Down
19 changes: 13 additions & 6 deletions pkg/app/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ import (
"github.com/tensorchord/envd/pkg/types"
)

const (
localhost = "127.0.0.1"
)

var CommandUp = &cli.Command{
Name: "up",
Category: CategoryBasic,
Expand Down Expand Up @@ -120,9 +116,13 @@ var CommandUp = &cli.Command{
}

func up(clicontext *cli.Context) error {
c, err := home.GetManager().ContextGetCurrent()
if err != nil {
return errors.Wrap(err, "failed to get the current context")
}
buildOpt, err := ParseBuildOpt(clicontext)
if err != nil {
return err
return errors.Wrap(err, "failed to parse the build options")
}

ctr := filepath.Base(buildOpt.BuildContextDir)
Expand Down Expand Up @@ -197,9 +197,14 @@ func up(clicontext *cli.Context) error {
logrus.Debugf("container %s is running", res.Name)

logrus.Debugf("add entry %s to SSH config.", ctr)
hostname, err := c.GetSSHHostname()
if err != nil {
return errors.Wrap(err, "failed to get the ssh hostname")
}

eo := sshconfig.EntryOptions{
Name: ctr,
IFace: localhost,
IFace: hostname,
Port: res.SSHPort,
PrivateKeyPath: clicontext.Path("private-key"),
EnableHostKeyCheck: false,
Expand All @@ -218,6 +223,8 @@ func up(clicontext *cli.Context) error {
if err != nil {
return errors.Wrap(err, "failed to create the ssh client")
}
opt.Server = hostname

if err := sshClient.Attach(); err != nil {
return errors.Wrap(err, "failed to attach to the container")
}
Expand Down
20 changes: 16 additions & 4 deletions pkg/envd/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,24 @@ func New(ctx context.Context, opt Options) (Engine, error) {
if opt.Context.Runner == types.RunnerTypeEnvdServer {
ac, err := home.GetManager().AuthGetCurrent()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to get the auth information")
}

cli, err := envdclient.NewClientWithOpts(envdclient.FromEnv)
// Get the runner host.
opts := []envdclient.Opt{
envdclient.WithTLSClientConfigFromEnv(),
}
if opt.Context.RunnerAddress != nil {
opts = append(opts,
envdclient.WithHost(*opt.Context.RunnerAddress))
} else {
opts = append(opts,
envdclient.WithHostFromEnv())
}

cli, err := envdclient.NewClientWithOpts(opts...)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to create the envd-server client")
}
return &envdServerEngine{
Client: cli,
Expand All @@ -51,7 +63,7 @@ func New(ctx context.Context, opt Options) (Engine, error) {
cli, err := client.NewClientWithOpts(
client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to create the docker client")
}
return &dockerEngine{
Client: cli,
Expand Down
1 change: 0 additions & 1 deletion pkg/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ type Options struct {

func DefaultOptions() Options {
return Options{
Server: "localhost",
User: "envd",
Auth: true,
PrivateKeyPwd: "",
Expand Down
14 changes: 14 additions & 0 deletions pkg/types/envd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/moby/buildkit/util/system"

"github.com/tensorchord/envd/pkg/util/netutil"
"github.com/tensorchord/envd/pkg/version"
)

Expand Down Expand Up @@ -278,3 +279,16 @@ func parsePyPICommands(lst string) ([]string, error) {
err := json.Unmarshal([]byte(lst), &pkgs)
return pkgs, err
}

func (c Context) GetSSHHostname() (string, error) {
if c.RunnerAddress == nil {
return "localhost", nil
}

// TODO(gaocegege): Check ENVD_SERVER_HOST.
hostname, err := netutil.GetHost(*c.RunnerAddress)
if err != nil {
return "", err
}
return hostname, nil
}
20 changes: 19 additions & 1 deletion pkg/util/netutil/netutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@

package netutil

import "net"
import (
"fmt"
"net"
"net/url"
)

// GetFreePort returns an available port in the host.
func GetFreePort() (int, error) {
l, err := net.Listen("tcp", ":0")
if err != nil {
Expand All @@ -24,3 +29,16 @@ func GetFreePort() (int, error) {
defer l.Close()
return l.Addr().(*net.TCPAddr).Port, nil
}

// GetHost get the IP address from the address.
func GetHost(addr string) (string, error) {
if u, err := url.Parse(addr); err != nil {
return "", err
} else {
h := u.Hostname()
if h == "" {
return "", fmt.Errorf("failed to get the hostname from %s", addr)
}
return h, nil
}
}
46 changes: 46 additions & 0 deletions pkg/util/netutil/netutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,49 @@ func TestGetFreePort(t *testing.T) {
assert.NoError(t, err)
assert.NotEqual(t, port, 0)
}

func TestGetHost(t *testing.T) {
tcs := []struct {
host string
expected string
err bool
}{
{
host: "https://localhost:8080",
expected: "localhost",
err: false,
},
{
host: "localhost:8080",
expected: "",
err: true,
},
{
host: "http://localhost:8080",
expected: "localhost",
err: false,
},
{
host: "http://1.1.1.1:8080",
expected: "1.1.1.1",
err: false,
},
}
for _, tc := range tcs {
host, err := GetHost(tc.host)
if tc.err == true {
if err == nil {
t.Error("expect to get the error, but got nil")
}
continue
}
if tc.err == false {
if err != nil {
t.Errorf("unexpected error %v", err)
}
if host != tc.expected {
t.Errorf("expected %s, got %s", tc.expected, host)
}
}
}
}

0 comments on commit 0fc4d8d

Please sign in to comment.