From b6094e0006b8fd73c390429b2b46166048706b84 Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Thu, 26 Aug 2021 21:50:20 +0000 Subject: [PATCH 1/9] Changes to point to RPC service. --- cmd/ghcs/logs.go | 13 ++++- cmd/ghcs/ssh.go | 88 +++---------------------------- internal/codespaces/codespaces.go | 24 +++++++++ internal/codespaces/ssh.go | 4 +- 4 files changed, 43 insertions(+), 86 deletions(-) diff --git a/cmd/ghcs/logs.go b/cmd/ghcs/logs.go index dd8664597..6f93ee3b9 100644 --- a/cmd/ghcs/logs.go +++ b/cmd/ghcs/logs.go @@ -57,7 +57,16 @@ func Logs(tail bool, codespaceName string) error { return fmt.Errorf("connecting to liveshare: %v", err) } - tunnelPort, connClosed, err := codespaces.MakeSSHTunnel(ctx, lsclient, 0) + result, remoteSSHServerPort, sshUser, _, err := codespaces.StartSSHServer(ctx, lsclient) + if err != nil { + return fmt.Errorf("error getting ssh server details: %v", err) + } + + if !result { + return fmt.Errorf("error starting ssh: %v", err) + } + + tunnelPort, connClosed, err := codespaces.MakeSSHTunnel(ctx, lsclient, 0, remoteSSHServerPort) if err != nil { return fmt.Errorf("make ssh tunnel: %v", err) } @@ -67,7 +76,7 @@ func Logs(tail bool, codespaceName string) error { cmdType = "tail -f" } - dst := fmt.Sprintf("%s@localhost", getSSHUser(codespace)) + dst := fmt.Sprintf("%s@localhost", sshUser) stdout, err := codespaces.RunCommand( ctx, tunnelPort, dst, fmt.Sprintf("%v /workspaces/.codespaces/.persistedshare/creation.log", cmdType), ) diff --git a/cmd/ghcs/ssh.go b/cmd/ghcs/ssh.go index 1754f968a..f3e621824 100644 --- a/cmd/ghcs/ssh.go +++ b/cmd/ghcs/ssh.go @@ -1,17 +1,13 @@ package main import ( - "bufio" "context" "fmt" "os" - "strings" - "time" "github.com/github/ghcs/api" "github.com/github/ghcs/cmd/ghcs/output" "github.com/github/ghcs/internal/codespaces" - "github.com/github/go-liveshare" "github.com/spf13/cobra" ) @@ -59,33 +55,23 @@ func SSH(sshProfile, codespaceName string, sshServerPort int) error { return fmt.Errorf("error connecting to liveshare: %v", err) } - terminal, err := liveshare.NewTerminal(lsclient) + result, remoteSSHServerPort, sshUser, _, err := codespaces.StartSSHServer(ctx, lsclient) if err != nil { - return fmt.Errorf("error creating liveshare terminal: %v", err) + return fmt.Errorf("error getting ssh server details: %v", err) } - log.Println("Preparing SSH...") - if sshProfile == "" { - containerID, err := getContainerID(ctx, log, terminal) - if err != nil { - return fmt.Errorf("error getting container id: %v", err) - } - - if err := setupSSH(ctx, log, terminal, containerID, codespace.RepositoryName); err != nil { - return fmt.Errorf("error creating ssh server: %v", err) - } - - log.Print("\n") + if !result { + return fmt.Errorf("error starting ssh: %v", err) } - tunnelPort, tunnelClosed, err := codespaces.MakeSSHTunnel(ctx, lsclient, sshServerPort) + tunnelPort, tunnelClosed, err := codespaces.MakeSSHTunnel(ctx, lsclient, sshServerPort, remoteSSHServerPort) if err != nil { return fmt.Errorf("make ssh tunnel: %v", err) } connectDestination := sshProfile if connectDestination == "" { - connectDestination = fmt.Sprintf("%s@localhost", getSSHUser(codespace)) + connectDestination = fmt.Sprintf("%s@localhost", sshUser) } usingCustomPort := tunnelPort == sshServerPort @@ -105,65 +91,3 @@ func SSH(sshProfile, codespaceName string, sshServerPort int) error { return nil } - -func getContainerID(ctx context.Context, logger *output.Logger, terminal *liveshare.Terminal) (string, error) { - logger.Print(".") - - cmd := terminal.NewCommand( - "/", - "/usr/bin/docker ps -aq --filter label=Type=codespaces --filter status=running", - ) - - stream, err := cmd.Run(ctx) - if err != nil { - return "", fmt.Errorf("error running command: %v", err) - } - - logger.Print(".") - scanner := bufio.NewScanner(stream) - scanner.Scan() - - logger.Print(".") - containerID := scanner.Text() - if err := scanner.Err(); err != nil { - return "", fmt.Errorf("error scanning stream: %v", err) - } - - logger.Print(".") - if err := stream.Close(); err != nil { - return "", fmt.Errorf("error closing stream: %v", err) - } - - return containerID, nil -} - -func setupSSH(ctx context.Context, logger *output.Logger, terminal *liveshare.Terminal, containerID, repositoryName string) error { - setupBashProfileCmd := fmt.Sprintf(`echo "cd /workspaces/%v; export $(cat /workspaces/.codespaces/shared/.env | xargs); exec /bin/zsh;" > /home/codespace/.bash_profile`, repositoryName) - - logger.Print(".") - compositeCommand := []string{setupBashProfileCmd} - cmd := terminal.NewCommand( - "/", - fmt.Sprintf("/usr/bin/docker exec -t %s /bin/bash -c '"+strings.Join(compositeCommand, "; ")+"'", containerID), - ) - stream, err := cmd.Run(ctx) - if err != nil { - return fmt.Errorf("error running command: %v", err) - } - - logger.Print(".") - if err := stream.Close(); err != nil { - return fmt.Errorf("error closing stream: %v", err) - } - - time.Sleep(1 * time.Second) - - return nil -} - -func getSSHUser(codespace *api.Codespace) string { - if codespace.RepositoryNWO == "github/github" { - return "root" - } - return "codespace" -} diff --git a/internal/codespaces/codespaces.go b/internal/codespaces/codespaces.go index 48369cfa0..30173f018 100644 --- a/internal/codespaces/codespaces.go +++ b/internal/codespaces/codespaces.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strconv" "time" "github.com/AlecAivazis/survey/v2" @@ -117,6 +118,29 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient *api.API, tok return lsclient, nil } +func StartSSHServer(ctx context.Context, client *liveshare.Client) (result bool, serverPort int, user string, message string, err error) { + sshRpc, err := liveshare.NewSSHRpc(client) + if err != nil { + return false, 0, "", "", fmt.Errorf("error creating live share: %v", err) + } + + sshRpcResult, err := sshRpc.StartRemoteServer(ctx) + if err != nil { + return false, 0, "", "", fmt.Errorf("error creating live share: %v", err) + } + + if !sshRpcResult.Result { + return false, 0, "", sshRpcResult.Message, nil + } + + portInt, err := strconv.Atoi(sshRpcResult.ServerPort) + if err != nil { + return false, 0, "", "", fmt.Errorf("error parsing port: %v", err) + } + + return sshRpcResult.Result, portInt, sshRpcResult.User, sshRpcResult.Message, err +} + func GetOrChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) { if codespaceName == "" { codespace, err = ChooseCodespace(ctx, apiClient, user) diff --git a/internal/codespaces/ssh.go b/internal/codespaces/ssh.go index 672ba3b7b..cf6118704 100644 --- a/internal/codespaces/ssh.go +++ b/internal/codespaces/ssh.go @@ -14,7 +14,7 @@ import ( "github.com/github/go-liveshare" ) -func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, serverPort int) (int, <-chan error, error) { +func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, serverPort int, remoteSSHPort int) (int, <-chan error, error) { tunnelClosed := make(chan error) server, err := liveshare.NewServer(lsclient) @@ -29,7 +29,7 @@ func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, serverPort i } // TODO(josebalius): This port won't always be 2222 - if err := server.StartSharing(ctx, "sshd", 2222); err != nil { + if err := server.StartSharing(ctx, "sshd", remoteSSHPort); err != nil { return 0, nil, fmt.Errorf("sharing sshd port: %v", err) } From d5a26e1536048ab6294b064960f22c8e5ced71cc Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Thu, 26 Aug 2021 23:14:13 +0000 Subject: [PATCH 2/9] Apply renames on the go-liveshare side. --- internal/codespaces/codespaces.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/codespaces/codespaces.go b/internal/codespaces/codespaces.go index 30173f018..3db66b427 100644 --- a/internal/codespaces/codespaces.go +++ b/internal/codespaces/codespaces.go @@ -119,26 +119,26 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient *api.API, tok } func StartSSHServer(ctx context.Context, client *liveshare.Client) (result bool, serverPort int, user string, message string, err error) { - sshRpc, err := liveshare.NewSSHRpc(client) + sshServer, err := liveshare.NewSSHServer(client) if err != nil { return false, 0, "", "", fmt.Errorf("error creating live share: %v", err) } - sshRpcResult, err := sshRpc.StartRemoteServer(ctx) + sshServerStartResult, err := sshServer.StartRemoteServer(ctx) if err != nil { return false, 0, "", "", fmt.Errorf("error creating live share: %v", err) } - if !sshRpcResult.Result { - return false, 0, "", sshRpcResult.Message, nil + if !sshServerStartResult.Result { + return false, 0, "", sshServerStartResult.Message, nil } - portInt, err := strconv.Atoi(sshRpcResult.ServerPort) + portInt, err := strconv.Atoi(sshServerStartResult.ServerPort) if err != nil { return false, 0, "", "", fmt.Errorf("error parsing port: %v", err) } - return sshRpcResult.Result, portInt, sshRpcResult.User, sshRpcResult.Message, err + return sshServerStartResult.Result, portInt, sshServerStartResult.User, sshServerStartResult.Message, err } func GetOrChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) { From 5db9e2d83e04754f85f18c6a6f9e9834826e86cc Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Mon, 30 Aug 2021 04:48:56 +0000 Subject: [PATCH 3/9] PR changes. --- cmd/ghcs/logs.go | 6 +-- cmd/ghcs/ssh.go | 79 +++++++++++++++++++++++++++++-- internal/codespaces/codespaces.go | 15 +++--- internal/codespaces/ssh.go | 10 ++-- 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/cmd/ghcs/logs.go b/cmd/ghcs/logs.go index 6f93ee3b9..31af10dda 100644 --- a/cmd/ghcs/logs.go +++ b/cmd/ghcs/logs.go @@ -57,15 +57,11 @@ func Logs(tail bool, codespaceName string) error { return fmt.Errorf("connecting to liveshare: %v", err) } - result, remoteSSHServerPort, sshUser, _, err := codespaces.StartSSHServer(ctx, lsclient) + remoteSSHServerPort, sshUser, err := codespaces.StartSSHServer(ctx, lsclient) if err != nil { return fmt.Errorf("error getting ssh server details: %v", err) } - if !result { - return fmt.Errorf("error starting ssh: %v", err) - } - tunnelPort, connClosed, err := codespaces.MakeSSHTunnel(ctx, lsclient, 0, remoteSSHServerPort) if err != nil { return fmt.Errorf("make ssh tunnel: %v", err) diff --git a/cmd/ghcs/ssh.go b/cmd/ghcs/ssh.go index f3e621824..e3e51e08e 100644 --- a/cmd/ghcs/ssh.go +++ b/cmd/ghcs/ssh.go @@ -1,13 +1,17 @@ package main import ( + "bufio" "context" "fmt" "os" + "strings" + "time" "github.com/github/ghcs/api" "github.com/github/ghcs/cmd/ghcs/output" "github.com/github/ghcs/internal/codespaces" + "github.com/github/go-liveshare" "github.com/spf13/cobra" ) @@ -55,15 +59,29 @@ func SSH(sshProfile, codespaceName string, sshServerPort int) error { return fmt.Errorf("error connecting to liveshare: %v", err) } - result, remoteSSHServerPort, sshUser, _, err := codespaces.StartSSHServer(ctx, lsclient) + remoteSSHServerPort, sshUser, err := codespaces.StartSSHServer(ctx, lsclient) if err != nil { return fmt.Errorf("error getting ssh server details: %v", err) } - if !result { - return fmt.Errorf("error starting ssh: %v", err) + terminal, err := liveshare.NewTerminal(lsclient) + if err != nil { + return fmt.Errorf("error creating liveshare terminal: %v", err) } + log.Print("Preparing SSH...") + if sshProfile == "" { + containerID, err := getContainerID(ctx, log, terminal) + if err != nil { + return fmt.Errorf("error getting container id: %v", err) + } + + if err := setupEnv(ctx, log, terminal, containerID, codespace.RepositoryName, sshUser); err != nil { + return fmt.Errorf("error creating ssh server: %v", err) + } + } + log.Print("\n") + tunnelPort, tunnelClosed, err := codespaces.MakeSSHTunnel(ctx, lsclient, sshServerPort, remoteSSHServerPort) if err != nil { return fmt.Errorf("make ssh tunnel: %v", err) @@ -91,3 +109,58 @@ func SSH(sshProfile, codespaceName string, sshServerPort int) error { return nil } + +func getContainerID(ctx context.Context, logger *output.Logger, terminal *liveshare.Terminal) (string, error) { + logger.Print(".") + + cmd := terminal.NewCommand( + "/", + "/usr/bin/docker ps -aq --filter label=Type=codespaces --filter status=running", + ) + + stream, err := cmd.Run(ctx) + if err != nil { + return "", fmt.Errorf("error running command: %v", err) + } + + logger.Print(".") + scanner := bufio.NewScanner(stream) + scanner.Scan() + + logger.Print(".") + containerID := scanner.Text() + if err := scanner.Err(); err != nil { + return "", fmt.Errorf("error scanning stream: %v", err) + } + + logger.Print(".") + if err := stream.Close(); err != nil { + return "", fmt.Errorf("error closing stream: %v", err) + } + + return containerID, nil +} + +func setupEnv(ctx context.Context, logger *output.Logger, terminal *liveshare.Terminal, containerID, repositoryName, containerUser string) error { + setupBashProfileCmd := fmt.Sprintf(`echo "cd /workspaces/%v; export $(cat /workspaces/.codespaces/shared/.env | xargs); exec /bin/zsh;" > /home/%v/.bash_profile`, repositoryName, containerUser) + + logger.Print(".") + compositeCommand := []string{setupBashProfileCmd} + cmd := terminal.NewCommand( + "/", + fmt.Sprintf("/usr/bin/docker exec -t %s /bin/bash -c '"+strings.Join(compositeCommand, "; ")+"'", containerID), + ) + stream, err := cmd.Run(ctx) + if err != nil { + return fmt.Errorf("error running command: %v", err) + } + + logger.Print(".") + if err := stream.Close(); err != nil { + return fmt.Errorf("error closing stream: %v", err) + } + + time.Sleep(1 * time.Second) + + return nil +} diff --git a/internal/codespaces/codespaces.go b/internal/codespaces/codespaces.go index 3db66b427..8b18f7d7d 100644 --- a/internal/codespaces/codespaces.go +++ b/internal/codespaces/codespaces.go @@ -118,27 +118,30 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient *api.API, tok return lsclient, nil } -func StartSSHServer(ctx context.Context, client *liveshare.Client) (result bool, serverPort int, user string, message string, err error) { +// StartSSHServer starts and installs the SSH server in the codespace +// returns the remote port where it is running, the user to use to login +// or an error if something failed. +func StartSSHServer(ctx context.Context, client *liveshare.Client) (serverPort int, user string, err error) { sshServer, err := liveshare.NewSSHServer(client) if err != nil { - return false, 0, "", "", fmt.Errorf("error creating live share: %v", err) + return 0, "", fmt.Errorf("error creating live share: %v", err) } sshServerStartResult, err := sshServer.StartRemoteServer(ctx) if err != nil { - return false, 0, "", "", fmt.Errorf("error creating live share: %v", err) + return 0, "", fmt.Errorf("error starting live share: %v", err) } if !sshServerStartResult.Result { - return false, 0, "", sshServerStartResult.Message, nil + return 0, "", errors.New(sshServerStartResult.Message) } portInt, err := strconv.Atoi(sshServerStartResult.ServerPort) if err != nil { - return false, 0, "", "", fmt.Errorf("error parsing port: %v", err) + return 0, "", fmt.Errorf("error parsing port: %v", err) } - return sshServerStartResult.Result, portInt, sshServerStartResult.User, sshServerStartResult.Message, err + return portInt, sshServerStartResult.User, nil } func GetOrChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) { diff --git a/internal/codespaces/ssh.go b/internal/codespaces/ssh.go index cf6118704..cd944e114 100644 --- a/internal/codespaces/ssh.go +++ b/internal/codespaces/ssh.go @@ -14,7 +14,10 @@ import ( "github.com/github/go-liveshare" ) -func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, serverPort int, remoteSSHPort int) (int, <-chan error, error) { +// MakeSSHTunnel This function initializes the liveshare tunnel +// Creates the tunnel from a local port to a remote port. +// Returns the local port that was used, the channel and the error if any. +func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, localSSHPort int, remoteSSHPort int) (int, <-chan error, error) { tunnelClosed := make(chan error) server, err := liveshare.NewServer(lsclient) @@ -24,11 +27,10 @@ func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, serverPort i rand.Seed(time.Now().Unix()) port := rand.Intn(9999-2000) + 2000 // improve this obviously - if serverPort != 0 { - port = serverPort + if localSSHPort != 0 { + port = localSSHPort } - // TODO(josebalius): This port won't always be 2222 if err := server.StartSharing(ctx, "sshd", remoteSSHPort); err != nil { return 0, nil, fmt.Errorf("sharing sshd port: %v", err) } From 13917a289df253bd819511ee75d7851551b5f86e Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Mon, 30 Aug 2021 04:52:27 +0000 Subject: [PATCH 4/9] Moved function to ssh.go file. --- internal/codespaces/codespaces.go | 27 --------------------------- internal/codespaces/ssh.go | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/internal/codespaces/codespaces.go b/internal/codespaces/codespaces.go index 8b18f7d7d..48369cfa0 100644 --- a/internal/codespaces/codespaces.go +++ b/internal/codespaces/codespaces.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "strconv" "time" "github.com/AlecAivazis/survey/v2" @@ -118,32 +117,6 @@ func ConnectToLiveshare(ctx context.Context, log logger, apiClient *api.API, tok return lsclient, nil } -// StartSSHServer starts and installs the SSH server in the codespace -// returns the remote port where it is running, the user to use to login -// or an error if something failed. -func StartSSHServer(ctx context.Context, client *liveshare.Client) (serverPort int, user string, err error) { - sshServer, err := liveshare.NewSSHServer(client) - if err != nil { - return 0, "", fmt.Errorf("error creating live share: %v", err) - } - - sshServerStartResult, err := sshServer.StartRemoteServer(ctx) - if err != nil { - return 0, "", fmt.Errorf("error starting live share: %v", err) - } - - if !sshServerStartResult.Result { - return 0, "", errors.New(sshServerStartResult.Message) - } - - portInt, err := strconv.Atoi(sshServerStartResult.ServerPort) - if err != nil { - return 0, "", fmt.Errorf("error parsing port: %v", err) - } - - return portInt, sshServerStartResult.User, nil -} - func GetOrChooseCodespace(ctx context.Context, apiClient *api.API, user *api.User, codespaceName string) (codespace *api.Codespace, token string, err error) { if codespaceName == "" { codespace, err = ChooseCodespace(ctx, apiClient, user) diff --git a/internal/codespaces/ssh.go b/internal/codespaces/ssh.go index cd944e114..a1abcf381 100644 --- a/internal/codespaces/ssh.go +++ b/internal/codespaces/ssh.go @@ -2,6 +2,7 @@ package codespaces import ( "context" + "errors" "fmt" "io" "math/rand" @@ -47,6 +48,32 @@ func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, localSSHPort return port, tunnelClosed, nil } +// StartSSHServer starts and installs the SSH server in the codespace +// returns the remote port where it is running, the user to use to login +// or an error if something failed. +func StartSSHServer(ctx context.Context, client *liveshare.Client) (serverPort int, user string, err error) { + sshServer, err := liveshare.NewSSHServer(client) + if err != nil { + return 0, "", fmt.Errorf("error creating live share: %v", err) + } + + sshServerStartResult, err := sshServer.StartRemoteServer(ctx) + if err != nil { + return 0, "", fmt.Errorf("error starting live share: %v", err) + } + + if !sshServerStartResult.Result { + return 0, "", errors.New(sshServerStartResult.Message) + } + + portInt, err := strconv.Atoi(sshServerStartResult.ServerPort) + if err != nil { + return 0, "", fmt.Errorf("error parsing port: %v", err) + } + + return portInt, sshServerStartResult.User, nil +} + func makeSSHArgs(port int, dst, cmd string) ([]string, []string) { connArgs := []string{"-p", strconv.Itoa(port), "-o", "NoHostAuthenticationForLocalhost=yes"} cmdArgs := append([]string{dst, "-X", "-Y", "-C"}, connArgs...) // X11, X11Trust, Compression From 0c066cbd099622d16516b346445050d16f9d68df Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Mon, 30 Aug 2021 05:05:43 +0000 Subject: [PATCH 5/9] Fix compilation error. --- internal/codespaces/states.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/codespaces/states.go b/internal/codespaces/states.go index 5c3dcef45..7b98b12dd 100644 --- a/internal/codespaces/states.go +++ b/internal/codespaces/states.go @@ -45,7 +45,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u return fmt.Errorf("connect to liveshare: %v", err) } - tunnelPort, connClosed, err := MakeSSHTunnel(ctx, lsclient, 0) + tunnelPort, connClosed, err := MakeSSHTunnel(ctx, lsclient, 0, 2222) if err != nil { return fmt.Errorf("make ssh tunnel: %v", err) } From 954d46dce5846c94c2f3cfd07206acacc5208d19 Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Mon, 30 Aug 2021 17:30:28 +0000 Subject: [PATCH 6/9] Changes from comments on pr. --- internal/codespaces/ssh.go | 8 ++------ internal/codespaces/states.go | 7 ++++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/internal/codespaces/ssh.go b/internal/codespaces/ssh.go index a1abcf381..1c3807742 100644 --- a/internal/codespaces/ssh.go +++ b/internal/codespaces/ssh.go @@ -15,9 +15,6 @@ import ( "github.com/github/go-liveshare" ) -// MakeSSHTunnel This function initializes the liveshare tunnel -// Creates the tunnel from a local port to a remote port. -// Returns the local port that was used, the channel and the error if any. func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, localSSHPort int, remoteSSHPort int) (int, <-chan error, error) { tunnelClosed := make(chan error) @@ -48,9 +45,8 @@ func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, localSSHPort return port, tunnelClosed, nil } -// StartSSHServer starts and installs the SSH server in the codespace -// returns the remote port where it is running, the user to use to login -// or an error if something failed. +// StartSSHServer installs (if necessary) and starts the SSH in the codespace. +// It returns the remote port where it is running, the user to log in with, or an error if something failed. func StartSSHServer(ctx context.Context, client *liveshare.Client) (serverPort int, user string, err error) { sshServer, err := liveshare.NewSSHServer(client) if err != nil { diff --git a/internal/codespaces/states.go b/internal/codespaces/states.go index 7b98b12dd..d2aa389ef 100644 --- a/internal/codespaces/states.go +++ b/internal/codespaces/states.go @@ -45,7 +45,12 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u return fmt.Errorf("connect to liveshare: %v", err) } - tunnelPort, connClosed, err := MakeSSHTunnel(ctx, lsclient, 0, 2222) + remoteSSHServerPort, _, err := StartSSHServer(ctx, lsclient) + if err != nil { + return fmt.Errorf("error getting ssh server details: %v", err) + } + + tunnelPort, connClosed, err := MakeSSHTunnel(ctx, lsclient, 0, remoteSSHServerPort) if err != nil { return fmt.Errorf("make ssh tunnel: %v", err) } From 903b7be7dea2d4a0f5a2c9cc4ef3053d90029ca2 Mon Sep 17 00:00:00 2001 From: Edmundo Gonzalez <51725820+edgonmsft@users.noreply.github.com> Date: Mon, 30 Aug 2021 21:01:13 +0000 Subject: [PATCH 7/9] Comments from pr. --- cmd/ghcs/logs.go | 2 +- cmd/ghcs/ssh.go | 2 +- internal/codespaces/ssh.go | 4 +++- internal/codespaces/states.go | 14 +++++--------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/cmd/ghcs/logs.go b/cmd/ghcs/logs.go index ea5531bac..ec9e63a56 100644 --- a/cmd/ghcs/logs.go +++ b/cmd/ghcs/logs.go @@ -57,7 +57,7 @@ func logs(tail bool, codespaceName string) error { return fmt.Errorf("connecting to liveshare: %v", err) } - remoteSSHServerPort, sshUser, err := codespaces.StartSSHServer(ctx, lsclient) + remoteSSHServerPort, sshUser, err := codespaces.StartSSHServer(ctx, lsclient, log) if err != nil { return fmt.Errorf("error getting ssh server details: %v", err) } diff --git a/cmd/ghcs/ssh.go b/cmd/ghcs/ssh.go index fd98397fe..ad8743360 100644 --- a/cmd/ghcs/ssh.go +++ b/cmd/ghcs/ssh.go @@ -59,7 +59,7 @@ func ssh(sshProfile, codespaceName string, sshServerPort int) error { return fmt.Errorf("error connecting to liveshare: %v", err) } - remoteSSHServerPort, sshUser, err := codespaces.StartSSHServer(ctx, lsclient) + remoteSSHServerPort, sshUser, err := codespaces.StartSSHServer(ctx, lsclient, log) if err != nil { return fmt.Errorf("error getting ssh server details: %v", err) } diff --git a/internal/codespaces/ssh.go b/internal/codespaces/ssh.go index 1c3807742..16ffed07b 100644 --- a/internal/codespaces/ssh.go +++ b/internal/codespaces/ssh.go @@ -47,7 +47,9 @@ func MakeSSHTunnel(ctx context.Context, lsclient *liveshare.Client, localSSHPort // StartSSHServer installs (if necessary) and starts the SSH in the codespace. // It returns the remote port where it is running, the user to log in with, or an error if something failed. -func StartSSHServer(ctx context.Context, client *liveshare.Client) (serverPort int, user string, err error) { +func StartSSHServer(ctx context.Context, client *liveshare.Client, log logger) (serverPort int, user string, err error) { + log.Println("Fetching SSH details...") + sshServer, err := liveshare.NewSSHServer(client) if err != nil { return 0, "", fmt.Errorf("error creating live share: %v", err) diff --git a/internal/codespaces/states.go b/internal/codespaces/states.go index d2aa389ef..f3e9cbefe 100644 --- a/internal/codespaces/states.go +++ b/internal/codespaces/states.go @@ -45,7 +45,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u return fmt.Errorf("connect to liveshare: %v", err) } - remoteSSHServerPort, _, err := StartSSHServer(ctx, lsclient) + remoteSSHServerPort, sshUser, err := StartSSHServer(ctx, lsclient, log) if err != nil { return fmt.Errorf("error getting ssh server details: %v", err) } @@ -65,7 +65,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u case err := <-connClosed: return fmt.Errorf("connection closed: %v", err) case <-t.C: - states, err := getPostCreateOutput(ctx, tunnelPort, codespace) + states, err := getPostCreateOutput(ctx, tunnelPort, codespace, sshUser) if err != nil { return fmt.Errorf("get post create output: %v", err) } @@ -75,9 +75,9 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u } } -func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Codespace) ([]PostCreateState, error) { +func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Codespace, user string) ([]PostCreateState, error) { stdout, err := RunCommand( - ctx, tunnelPort, sshDestination(codespace), + ctx, tunnelPort, sshDestination(codespace, user), "cat /workspaces/.codespaces/shared/postCreateOutput.json", ) if err != nil { @@ -101,10 +101,6 @@ func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Cod } // TODO(josebalius): this won't be needed soon -func sshDestination(codespace *api.Codespace) string { - user := "codespace" - if codespace.RepositoryNWO == "github/github" { - user = "root" - } +func sshDestination(codespace *api.Codespace, user string) string { return user + "@localhost" } From 535d832f8abfaaf997931b162411dd7aeedfa4ba Mon Sep 17 00:00:00 2001 From: Jose Garcia Date: Tue, 31 Aug 2021 15:50:04 -0400 Subject: [PATCH 8/9] small tweak --- internal/codespaces/states.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/internal/codespaces/states.go b/internal/codespaces/states.go index f3e9cbefe..274d27951 100644 --- a/internal/codespaces/states.go +++ b/internal/codespaces/states.go @@ -77,7 +77,7 @@ func PollPostCreateStates(ctx context.Context, log logger, apiClient *api.API, u func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Codespace, user string) ([]PostCreateState, error) { stdout, err := RunCommand( - ctx, tunnelPort, sshDestination(codespace, user), + ctx, tunnelPort, fmt.Sprintf("%s@localhost", user), "cat /workspaces/.codespaces/shared/postCreateOutput.json", ) if err != nil { @@ -98,9 +98,4 @@ func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Cod } return output.Steps, nil -} - -// TODO(josebalius): this won't be needed soon -func sshDestination(codespace *api.Codespace, user string) string { - return user + "@localhost" -} +} \ No newline at end of file From ebb04d1753f27fa8747916907e9012c577708e42 Mon Sep 17 00:00:00 2001 From: Jose Garcia Date: Tue, 31 Aug 2021 19:52:32 +0000 Subject: [PATCH 9/9] format code --- internal/codespaces/states.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/codespaces/states.go b/internal/codespaces/states.go index 274d27951..d09c399e4 100644 --- a/internal/codespaces/states.go +++ b/internal/codespaces/states.go @@ -98,4 +98,4 @@ func getPostCreateOutput(ctx context.Context, tunnelPort int, codespace *api.Cod } return output.Steps, nil -} \ No newline at end of file +}