From c669eb5fef2d589aa1a7ee476883fb1b8e994dad Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 11:30:56 -0600 Subject: [PATCH 01/10] chore: use access url from env resource pool --- coder-sdk/env.go | 13 +++++---- coder-sdk/request.go | 13 +++++++-- coder-sdk/resourcepools.go | 8 ++++++ coder-sdk/ws.go | 23 +++++++++++++++- internal/cmd/configssh.go | 26 ++++++++++-------- internal/cmd/shell.go | 5 ++-- internal/coderutil/env.go | 55 +++++++++++++++++++++++++++++++++++++ internal/sync/singlefile.go | 3 +- internal/sync/sync.go | 9 +++--- 9 files changed, 127 insertions(+), 28 deletions(-) create mode 100644 internal/coderutil/env.go diff --git a/coder-sdk/env.go b/coder-sdk/env.go index e985c238..3e2fafd6 100644 --- a/coder-sdk/env.go +++ b/coder-sdk/env.go @@ -3,6 +3,7 @@ package coder import ( "context" "net/http" + "net/url" "time" "cdr.dev/wsep" @@ -147,13 +148,13 @@ func (c Client) EditEnvironment(ctx context.Context, envID string, req UpdateEnv // DialWsep dials an environments command execution interface // See https://github.com/cdr/wsep for details. -func (c Client) DialWsep(ctx context.Context, envID string) (*websocket.Conn, error) { - return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/wsep") +func (c Client) DialWsep(ctx context.Context, accessURL *url.URL, envID string) (*websocket.Conn, error) { + return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/wsep", withBaseURL(accessURL)) } // DialExecutor gives a remote execution interface for performing commands inside an environment. -func (c Client) DialExecutor(ctx context.Context, envID string) (wsep.Execer, error) { - ws, err := c.DialWsep(ctx, envID) +func (c Client) DialExecutor(ctx context.Context, accessURL *url.URL, envID string) (wsep.Execer, error) { + ws, err := c.DialWsep(ctx, accessURL, envID) if err != nil { return nil, err } @@ -161,8 +162,8 @@ func (c Client) DialExecutor(ctx context.Context, envID string) (wsep.Execer, er } // DialIDEStatus opens a websocket connection for cpu load metrics on the environment. -func (c Client) DialIDEStatus(ctx context.Context, envID string) (*websocket.Conn, error) { - return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/ide/api/status") +func (c Client) DialIDEStatus(ctx context.Context, accessURL *url.URL, envID string) (*websocket.Conn, error) { + return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/ide/api/status", withBaseURL(accessURL)) } // DialEnvironmentBuildLog opens a websocket connection for the environment build log messages. diff --git a/coder-sdk/request.go b/coder-sdk/request.go index 14a59b5e..0424d2da 100644 --- a/coder-sdk/request.go +++ b/coder-sdk/request.go @@ -12,12 +12,21 @@ import ( ) // request is a helper to set the cookie, marshal the payload and execute the request. -func (c Client) request(ctx context.Context, method, path string, in interface{}) (*http.Response, error) { +func (c Client) request(ctx context.Context, method, path string, in interface{}, options ...requestOption) (*http.Response, error) { // Create a default http client with the auth in the cookie. client, err := c.newHTTPClient() if err != nil { return nil, xerrors.Errorf("new http client: %w", err) } + url := *c.BaseURL + + var config requestOptions + for _, o := range options { + o(&config) + } + if config.BaseURLOverride != nil { + url = *config.BaseURLOverride + } // If we have incoming data, encode it as json. var payload io.Reader @@ -30,7 +39,7 @@ func (c Client) request(ctx context.Context, method, path string, in interface{} } // Create the http request. - req, err := http.NewRequestWithContext(ctx, method, c.BaseURL.String()+path, payload) + req, err := http.NewRequestWithContext(ctx, method, url.String()+path, payload) if err != nil { return nil, xerrors.Errorf("create request: %w", err) } diff --git a/coder-sdk/resourcepools.go b/coder-sdk/resourcepools.go index e94e2ec5..dc701a3f 100644 --- a/coder-sdk/resourcepools.go +++ b/coder-sdk/resourcepools.go @@ -17,6 +17,9 @@ type ResourcePool struct { DevurlHost string `json:"devurl_host"` NamespaceWhitelist []string `json:"namespace_whitelist"` OrgWhitelist []string `json:"org_whitelist"` + + // TODO@cmoog wait for this to merge + AccessURL string `json:"access_url"` } // ResourcePoolByID fetches a resource pool entity by its unique ID. @@ -39,6 +42,11 @@ func (c *Client) ResourcePools(ctx context.Context) ([]ResourcePool, error) { if err := c.requestBody(ctx, http.MethodGet, "/api/private/resource-pools", nil, &pools); err != nil { return nil, err } + + // TODO@cmoog remove this shim + for ix := range pools { + pools[ix].AccessURL = "https://us.cdr.cmoog.dev" + } return pools, nil } diff --git a/coder-sdk/ws.go b/coder-sdk/ws.go index 5dad6293..f761a8be 100644 --- a/coder-sdk/ws.go +++ b/coder-sdk/ws.go @@ -3,14 +3,35 @@ package coder import ( "context" "net/http" + "net/url" "nhooyr.io/websocket" ) +type requestOptions struct { + BaseURLOverride *url.URL +} + +type requestOption func(*requestOptions) + +func withBaseURL(base *url.URL) func(o *requestOptions) { + return func(o *requestOptions) { + o.BaseURLOverride = base + } +} + // dialWebsocket establish the websocket connection while setting the authentication header. -func (c Client) dialWebsocket(ctx context.Context, path string) (*websocket.Conn, error) { +func (c Client) dialWebsocket(ctx context.Context, path string, options ...requestOption) (*websocket.Conn, error) { // Make a copy of the url so we can update the scheme to ws(s) without mutating the state. url := *c.BaseURL + var config requestOptions + for _, o := range options { + o(&config) + } + if config.BaseURLOverride != nil { + url = *config.BaseURLOverride + } + if url.Scheme == "https" { url.Scheme = "wss" } else { diff --git a/internal/cmd/configssh.go b/internal/cmd/configssh.go index 38f1145c..7a04688e 100644 --- a/internal/cmd/configssh.go +++ b/internal/cmd/configssh.go @@ -15,6 +15,7 @@ import ( "cdr.dev/coder-cli/pkg/clog" "cdr.dev/coder-cli/coder-sdk" + "cdr.dev/coder-cli/internal/coderutil" "cdr.dev/coder-cli/internal/config" "github.com/spf13/cobra" "golang.org/x/xerrors" @@ -112,11 +113,13 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st return xerrors.Errorf("check if SSH is available: unable to connect to SSH endpoint: %w", err) } - newConfig, err := makeNewConfigs(user.Username, envs, privateKeyFilepath) + envsWithPools, err := coderutil.EnvsWithPool(ctx, client, envs) if err != nil { - return xerrors.Errorf("make new ssh configurations: %w", err) + return xerrors.Errorf("resolve env pools: %w", err) } + newConfig := makeNewConfigs(user.Username, envsWithPools, privateKeyFilepath) + err = os.MkdirAll(filepath.Dir(*configpath), os.ModePerm) if err != nil { return xerrors.Errorf("make configuration directory: %w", err) @@ -203,23 +206,22 @@ func writeSSHKey(ctx context.Context, client *coder.Client, privateKeyPath strin return ioutil.WriteFile(privateKeyPath, []byte(key.PrivateKey), 0400) } -func makeNewConfigs(userName string, envs []coder.Environment, privateKeyFilepath string) (string, error) { - hostname, err := configuredHostname() - if err != nil { - return "", err - } - +func makeNewConfigs(userName string, envs []coderutil.EnvWithPool, privateKeyFilepath string) string { newConfig := fmt.Sprintf("\n%s\n%s\n\n", sshStartToken, sshStartMessage) for _, env := range envs { - if !env.SSHAvailable { + if !env.Env.SSHAvailable { continue } - - newConfig += makeSSHConfig(hostname, userName, env.Name, privateKeyFilepath) + u, err := url.Parse(env.Pool.AccessURL) + if err != nil { + clog.LogWarn("invalid access url", clog.Causef("malformed url: %q", env.Pool.AccessURL)) + continue + } + newConfig += makeSSHConfig(u.Host, userName, env.Env.Name, privateKeyFilepath) } newConfig += fmt.Sprintf("\n%s\n", sshEndToken) - return newConfig, nil + return newConfig } func makeSSHConfig(host, userName, envName, privateKeyFilepath string) string { diff --git a/internal/cmd/shell.go b/internal/cmd/shell.go index 26902be9..f52cd0eb 100644 --- a/internal/cmd/shell.go +++ b/internal/cmd/shell.go @@ -16,6 +16,7 @@ import ( "cdr.dev/coder-cli/coder-sdk" "cdr.dev/coder-cli/internal/activity" + "cdr.dev/coder-cli/internal/coderutil" "cdr.dev/coder-cli/internal/x/xterminal" "cdr.dev/coder-cli/pkg/clog" "cdr.dev/wsep" @@ -161,9 +162,9 @@ func runCommand(ctx context.Context, envName, command string, args []string) err ctx, cancel := context.WithCancel(ctx) defer cancel() - conn, err := client.DialWsep(ctx, env.ID) + conn, err := coderutil.DialEnvWsep(ctx, client, env) if err != nil { - return xerrors.Errorf("dial websocket: %w", err) + return xerrors.Errorf("dial executor: %w", err) } go heartbeat(ctx, conn, 15*time.Second) diff --git a/internal/coderutil/env.go b/internal/coderutil/env.go new file mode 100644 index 00000000..a2361d1a --- /dev/null +++ b/internal/coderutil/env.go @@ -0,0 +1,55 @@ +package coderutil + +import ( + "context" + "net/url" + + "cdr.dev/coder-cli/coder-sdk" + "golang.org/x/xerrors" + "nhooyr.io/websocket" +) + +func DialEnvWsep(ctx context.Context, client *coder.Client, env *coder.Environment) (*websocket.Conn, error) { + resourcePool, err := client.ResourcePoolByID(ctx, env.ResourcePoolID) + if err != nil { + return nil, xerrors.Errorf("get env resource pool: %w", err) + } + accessURL, err := url.Parse(resourcePool.AccessURL) + if err != nil { + return nil, xerrors.Errorf("invalid resource pool access url: %w", err) + } + + conn, err := client.DialWsep(ctx, accessURL, env.ID) + if err != nil { + return nil, xerrors.Errorf("dial websocket: %w", err) + } + return conn, nil +} + +type EnvWithPool struct { + Env coder.Environment + Pool coder.ResourcePool +} + +func EnvsWithPool(ctx context.Context, client *coder.Client, envs []coder.Environment) ([]EnvWithPool, error) { + pooledEnvs := make([]EnvWithPool, len(envs)) + pools, err := client.ResourcePools(ctx) + if err != nil { + return nil, err + } + poolMap := make(map[string]coder.ResourcePool, len(pools)) + for _, p := range pools { + poolMap[p.ID] = p + } + for _, e := range envs { + envPool, ok := poolMap[e.ResourcePoolID] + if !ok { + return nil, xerrors.Errorf("fetch env resource pool: %w", coder.ErrNotFound) + } + pooledEnvs = append(pooledEnvs, EnvWithPool{ + Env: e, + Pool: envPool, + }) + } + return pooledEnvs, nil +} diff --git a/internal/sync/singlefile.go b/internal/sync/singlefile.go index 0cc03ef0..31745f93 100644 --- a/internal/sync/singlefile.go +++ b/internal/sync/singlefile.go @@ -10,6 +10,7 @@ import ( "strings" "cdr.dev/coder-cli/coder-sdk" + "cdr.dev/coder-cli/internal/coderutil" "cdr.dev/wsep" "golang.org/x/xerrors" "nhooyr.io/websocket" @@ -17,7 +18,7 @@ import ( // SingleFile copies the given file into the remote dir or remote path of the given coder.Environment. func SingleFile(ctx context.Context, local, remoteDir string, env *coder.Environment, client *coder.Client) error { - conn, err := client.DialWsep(ctx, env.ID) + conn, err := coderutil.DialEnvWsep(ctx, client, env) if err != nil { return xerrors.Errorf("dial remote execer: %w", err) } diff --git a/internal/sync/sync.go b/internal/sync/sync.go index fcca0518..34713ad7 100644 --- a/internal/sync/sync.go +++ b/internal/sync/sync.go @@ -24,6 +24,7 @@ import ( "cdr.dev/coder-cli/coder-sdk" "cdr.dev/coder-cli/internal/activity" + "cdr.dev/coder-cli/internal/coderutil" "cdr.dev/coder-cli/pkg/clog" "cdr.dev/wsep" ) @@ -89,9 +90,9 @@ func (s Sync) syncPaths(delete bool, local, remote string) error { } func (s Sync) remoteCmd(ctx context.Context, prog string, args ...string) error { - conn, err := s.Client.DialWsep(ctx, s.Env.ID) + conn, err := coderutil.DialEnvWsep(ctx, s.Client, &s.Env) if err != nil { - return xerrors.Errorf("dial websocket: %w", err) + return xerrors.Errorf("dial executor: %w", err) } defer func() { _ = conn.Close(websocket.CloseNormalClosure, "") }() // Best effort. @@ -270,9 +271,9 @@ func (s Sync) Version() (string, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - conn, err := s.Client.DialWsep(ctx, s.Env.ID) + conn, err := coderutil.DialEnvWsep(ctx, s.Client, &s.Env) if err != nil { - return "", err + return "", xerrors.Errorf("dial env executor: %w", err) } defer func() { _ = conn.Close(websocket.CloseNormalClosure, "") }() // Best effort. From ad6830ae402afdc2d25f99058bb9ed96a5358940 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 12:02:49 -0600 Subject: [PATCH 02/10] fixup! chore: use access url from env resource pool --- coder-sdk/env.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/coder-sdk/env.go b/coder-sdk/env.go index 3e2fafd6..31f4d087 100644 --- a/coder-sdk/env.go +++ b/coder-sdk/env.go @@ -148,13 +148,13 @@ func (c Client) EditEnvironment(ctx context.Context, envID string, req UpdateEnv // DialWsep dials an environments command execution interface // See https://github.com/cdr/wsep for details. -func (c Client) DialWsep(ctx context.Context, accessURL *url.URL, envID string) (*websocket.Conn, error) { - return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/wsep", withBaseURL(accessURL)) +func (c Client) DialWsep(ctx context.Context, baseURL *url.URL, envID string) (*websocket.Conn, error) { + return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/wsep", withBaseURL(baseURL)) } // DialExecutor gives a remote execution interface for performing commands inside an environment. -func (c Client) DialExecutor(ctx context.Context, accessURL *url.URL, envID string) (wsep.Execer, error) { - ws, err := c.DialWsep(ctx, accessURL, envID) +func (c Client) DialExecutor(ctx context.Context, baseURL *url.URL, envID string) (wsep.Execer, error) { + ws, err := c.DialWsep(ctx, baseURL, envID) if err != nil { return nil, err } @@ -162,8 +162,8 @@ func (c Client) DialExecutor(ctx context.Context, accessURL *url.URL, envID stri } // DialIDEStatus opens a websocket connection for cpu load metrics on the environment. -func (c Client) DialIDEStatus(ctx context.Context, accessURL *url.URL, envID string) (*websocket.Conn, error) { - return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/ide/api/status", withBaseURL(accessURL)) +func (c Client) DialIDEStatus(ctx context.Context, baseURl *url.URL, envID string) (*websocket.Conn, error) { + return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/ide/api/status", withBaseURL(baseURl)) } // DialEnvironmentBuildLog opens a websocket connection for the environment build log messages. From 6adc01b17fc11d35156c7b709400ad20de7636b6 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 12:06:46 -0600 Subject: [PATCH 03/10] fixup! chore: use access url from env resource pool --- coder-sdk/env.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coder-sdk/env.go b/coder-sdk/env.go index 31f4d087..9201aedc 100644 --- a/coder-sdk/env.go +++ b/coder-sdk/env.go @@ -162,8 +162,8 @@ func (c Client) DialExecutor(ctx context.Context, baseURL *url.URL, envID string } // DialIDEStatus opens a websocket connection for cpu load metrics on the environment. -func (c Client) DialIDEStatus(ctx context.Context, baseURl *url.URL, envID string) (*websocket.Conn, error) { - return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/ide/api/status", withBaseURL(baseURl)) +func (c Client) DialIDEStatus(ctx context.Context, baseURL *url.URL, envID string) (*websocket.Conn, error) { + return c.dialWebsocket(ctx, "/proxy/environments/"+envID+"/ide/api/status", withBaseURL(baseURL)) } // DialEnvironmentBuildLog opens a websocket connection for the environment build log messages. From b646d9513508996a92167add1ed74f2e8200fff8 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 12:19:57 -0600 Subject: [PATCH 04/10] fixup! chore: use access url from env resource pool --- internal/coderutil/env.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/coderutil/env.go b/internal/coderutil/env.go index a2361d1a..8aa37a9e 100644 --- a/internal/coderutil/env.go +++ b/internal/coderutil/env.go @@ -27,7 +27,7 @@ func DialEnvWsep(ctx context.Context, client *coder.Client, env *coder.Environme } type EnvWithPool struct { - Env coder.Environment + Env coder.Environment Pool coder.ResourcePool } From 9010f771cdadc52858642123bf7a657d15de0c20 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 12:23:24 -0600 Subject: [PATCH 05/10] fixup! chore: use access url from env resource pool --- internal/coderutil/doc.go | 2 ++ internal/coderutil/env.go | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 internal/coderutil/doc.go diff --git a/internal/coderutil/doc.go b/internal/coderutil/doc.go new file mode 100644 index 00000000..5a7d8e14 --- /dev/null +++ b/internal/coderutil/doc.go @@ -0,0 +1,2 @@ +// Package coderutil providers utilities for high-level operations on coder-sdk entities. +package coderutil diff --git a/internal/coderutil/env.go b/internal/coderutil/env.go index 8aa37a9e..49de49fb 100644 --- a/internal/coderutil/env.go +++ b/internal/coderutil/env.go @@ -9,6 +9,8 @@ import ( "nhooyr.io/websocket" ) +// DialEnvWsep dials the executor endpoint using the https://github.com/cdr/wsep message protocol. +// The proper resource pool access URL is used. func DialEnvWsep(ctx context.Context, client *coder.Client, env *coder.Environment) (*websocket.Conn, error) { resourcePool, err := client.ResourcePoolByID(ctx, env.ResourcePoolID) if err != nil { @@ -26,11 +28,13 @@ func DialEnvWsep(ctx context.Context, client *coder.Client, env *coder.Environme return conn, nil } +// EnvWithPool composes an Environment entity with its associated ResourcePool. type EnvWithPool struct { Env coder.Environment Pool coder.ResourcePool } +// EnvsWithPool performs the composition of each Environment with its associated ResourcePool. func EnvsWithPool(ctx context.Context, client *coder.Client, envs []coder.Environment) ([]EnvWithPool, error) { pooledEnvs := make([]EnvWithPool, len(envs)) pools, err := client.ResourcePools(ctx) From 19e53c7ef91de8fbfa88ee17dfea15e74dfedcdf Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 17:14:31 -0600 Subject: [PATCH 06/10] fix: use proper SSH enabled bool flag --- coder-sdk/env.go | 1 - coder-sdk/resourcepools.go | 10 ++------ internal/cmd/configssh.go | 48 ++++++-------------------------------- 3 files changed, 9 insertions(+), 50 deletions(-) diff --git a/coder-sdk/env.go b/coder-sdk/env.go index 9201aedc..03ac3c71 100644 --- a/coder-sdk/env.go +++ b/coder-sdk/env.go @@ -33,7 +33,6 @@ type Environment struct { LastOpenedAt time.Time `json:"last_opened_at" table:"-"` LastConnectionAt time.Time `json:"last_connection_at" table:"-"` AutoOffThreshold Duration `json:"auto_off_threshold" table:"-"` - SSHAvailable bool `json:"ssh_available" table:"-"` UseContainerVM bool `json:"use_container_vm" table:"CVM"` ResourcePoolID string `json:"resource_pool_id" table:"-"` } diff --git a/coder-sdk/resourcepools.go b/coder-sdk/resourcepools.go index dc701a3f..2556aa37 100644 --- a/coder-sdk/resourcepools.go +++ b/coder-sdk/resourcepools.go @@ -17,9 +17,8 @@ type ResourcePool struct { DevurlHost string `json:"devurl_host"` NamespaceWhitelist []string `json:"namespace_whitelist"` OrgWhitelist []string `json:"org_whitelist"` - - // TODO@cmoog wait for this to merge - AccessURL string `json:"access_url"` + SSHEnabled bool `json:"ssh_enabled"` + AccessURL string `json:"envproxy_access_url"` } // ResourcePoolByID fetches a resource pool entity by its unique ID. @@ -42,11 +41,6 @@ func (c *Client) ResourcePools(ctx context.Context) ([]ResourcePool, error) { if err := c.requestBody(ctx, http.MethodGet, "/api/private/resource-pools", nil, &pools); err != nil { return nil, err } - - // TODO@cmoog remove this shim - for ix := range pools { - pools[ix].AccessURL = "https://us.cdr.cmoog.dev" - } return pools, nil } diff --git a/internal/cmd/configssh.go b/internal/cmd/configssh.go index 7a04688e..911b8412 100644 --- a/internal/cmd/configssh.go +++ b/internal/cmd/configssh.go @@ -4,13 +4,11 @@ import ( "context" "fmt" "io/ioutil" - "net" "net/url" "os" "os/user" "path/filepath" "strings" - "time" "cdr.dev/coder-cli/pkg/clog" @@ -104,20 +102,15 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st return xerrors.New("no environments found") } - if !sshAvailable(envs) { - return xerrors.New("SSH is disabled or not available for any environments in your Coder Enterprise deployment.") - } - - err = canConnectSSH(ctx) - if err != nil { - return xerrors.Errorf("check if SSH is available: unable to connect to SSH endpoint: %w", err) - } - envsWithPools, err := coderutil.EnvsWithPool(ctx, client, envs) if err != nil { return xerrors.Errorf("resolve env pools: %w", err) } + if !sshAvailable(envsWithPools) { + return xerrors.New("SSH is disabled or not available for any environments in your Coder Enterprise deployment.") + } + newConfig := makeNewConfigs(user.Username, envsWithPools, privateKeyFilepath) err = os.MkdirAll(filepath.Dir(*configpath), os.ModePerm) @@ -162,42 +155,15 @@ func removeOldConfig(config string) (string, bool) { } // sshAvailable returns true if SSH is available for at least one environment. -func sshAvailable(envs []coder.Environment) bool { +func sshAvailable(envs []coderutil.EnvWithPool) bool { for _, env := range envs { - if env.SSHAvailable { + if env.Pool.SSHEnabled { return true } } - return false } -// canConnectSSH returns an error if we cannot dial the SSH port. -func canConnectSSH(ctx context.Context) error { - ctx, cancel := context.WithTimeout(ctx, 3*time.Second) - defer cancel() - - host, err := configuredHostname() - if err != nil { - return xerrors.Errorf("get configured manager hostname: %w", err) - } - - var ( - dialer net.Dialer - hostPort = net.JoinHostPort(host, "22") - ) - conn, err := dialer.DialContext(ctx, "tcp", hostPort) - if err != nil { - if err == context.DeadlineExceeded { - err = xerrors.New("timed out after 3 seconds") - } - return xerrors.Errorf("dial tcp://%v: %w", hostPort, err) - } - conn.Close() - - return nil -} - func writeSSHKey(ctx context.Context, client *coder.Client, privateKeyPath string) error { key, err := client.SSHKey(ctx) if err != nil { @@ -209,7 +175,7 @@ func writeSSHKey(ctx context.Context, client *coder.Client, privateKeyPath strin func makeNewConfigs(userName string, envs []coderutil.EnvWithPool, privateKeyFilepath string) string { newConfig := fmt.Sprintf("\n%s\n%s\n\n", sshStartToken, sshStartMessage) for _, env := range envs { - if !env.Env.SSHAvailable { + if !env.Pool.SSHEnabled { continue } u, err := url.Parse(env.Pool.AccessURL) From 8cd4a49e0b9cfa190770939c45780bfe17efb639 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 17:16:10 -0600 Subject: [PATCH 07/10] fixup! fix: use proper SSH enabled bool flag --- internal/cmd/configssh.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/cmd/configssh.go b/internal/cmd/configssh.go index 911b8412..17894778 100644 --- a/internal/cmd/configssh.go +++ b/internal/cmd/configssh.go @@ -203,6 +203,7 @@ func makeSSHConfig(host, userName, envName, privateKeyFilepath string) string { `, envName, host, userName, envName, privateKeyFilepath) } +//nolint:deadcode,unused func configuredHostname() (string, error) { u, err := config.URL.Read() if err != nil { From 4df1a576c5717107133a2aedfa8ad50ba51fe411 Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 17:31:15 -0600 Subject: [PATCH 08/10] fixup! fix: use proper SSH enabled bool flag --- internal/cmd/configssh.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/cmd/configssh.go b/internal/cmd/configssh.go index 17894778..2254c565 100644 --- a/internal/cmd/configssh.go +++ b/internal/cmd/configssh.go @@ -176,6 +176,10 @@ func makeNewConfigs(userName string, envs []coderutil.EnvWithPool, privateKeyFil newConfig := fmt.Sprintf("\n%s\n%s\n\n", sshStartToken, sshStartMessage) for _, env := range envs { if !env.Pool.SSHEnabled { + clog.LogWarn(fmt.Sprintf("SSH is not enabled for %q", env.Env.Name), + clog.BlankLine, + clog.Tipf("ask an infrastructure administrator to enable SSH for this resource pool"), + ) continue } u, err := url.Parse(env.Pool.AccessURL) From 8f039a93e10754ed4ba67d3f4abfa06c5750b40e Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 17:31:43 -0600 Subject: [PATCH 09/10] fixup! fix: use proper SSH enabled bool flag --- internal/cmd/configssh.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/configssh.go b/internal/cmd/configssh.go index 2254c565..62ba4f60 100644 --- a/internal/cmd/configssh.go +++ b/internal/cmd/configssh.go @@ -176,7 +176,7 @@ func makeNewConfigs(userName string, envs []coderutil.EnvWithPool, privateKeyFil newConfig := fmt.Sprintf("\n%s\n%s\n\n", sshStartToken, sshStartMessage) for _, env := range envs { if !env.Pool.SSHEnabled { - clog.LogWarn(fmt.Sprintf("SSH is not enabled for %q", env.Env.Name), + clog.LogWarn(fmt.Sprintf("SSH access is not enabled for pool %q", env.Pool.Name), clog.BlankLine, clog.Tipf("ask an infrastructure administrator to enable SSH for this resource pool"), ) From 4dea056a78776cb77c4ea241fa68af11a8acb08d Mon Sep 17 00:00:00 2001 From: Charlie Moog Date: Thu, 14 Jan 2021 17:32:01 -0600 Subject: [PATCH 10/10] fixup! fix: use proper SSH enabled bool flag --- internal/cmd/configssh.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/configssh.go b/internal/cmd/configssh.go index 62ba4f60..562e5225 100644 --- a/internal/cmd/configssh.go +++ b/internal/cmd/configssh.go @@ -176,7 +176,7 @@ func makeNewConfigs(userName string, envs []coderutil.EnvWithPool, privateKeyFil newConfig := fmt.Sprintf("\n%s\n%s\n\n", sshStartToken, sshStartMessage) for _, env := range envs { if !env.Pool.SSHEnabled { - clog.LogWarn(fmt.Sprintf("SSH access is not enabled for pool %q", env.Pool.Name), + clog.LogWarn(fmt.Sprintf("SSH is not enabled for pool %q", env.Pool.Name), clog.BlankLine, clog.Tipf("ask an infrastructure administrator to enable SSH for this resource pool"), )