Skip to content

Commit

Permalink
workspace start --ssh
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptronicek committed Oct 30, 2023
1 parent d39145e commit caa71dd
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 56 deletions.
18 changes: 15 additions & 3 deletions components/local-app/cmd/workspace-start.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import (
"github.com/spf13/cobra"
)

var startNonBlocking = false
var startDontWait = false
var startOpenSsh = false
var startOpenEditor = false

// startWorkspaceCommand starts to a given workspace
var startWorkspaceCommand = &cobra.Command{
Expand All @@ -36,6 +38,10 @@ var startWorkspaceCommand = &cobra.Command{
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Minute)
defer cancel()

if startOpenSsh && startOpenEditor {
return fmt.Errorf("Cannot open SSH and editor at the same time")
}

gitpod, err := common.GetGitpodClient(ctx)
if err != nil {
return err
Expand All @@ -52,7 +58,7 @@ var startWorkspaceCommand = &cobra.Command{
return nil
}

if startNonBlocking {
if startDontWait {
fmt.Println("Workspace initialization started")
return nil
}
Expand All @@ -78,6 +84,10 @@ var startWorkspaceCommand = &cobra.Command{

if msg.GetResult().Instance.Status.Phase == v1.WorkspaceInstanceStatus_PHASE_RUNNING {
fmt.Println("Workspace started")
if startOpenSsh {
err = common.SshConnectToWs(ctx, workspaceID, false)
return err
}
break
}

Expand All @@ -100,5 +110,7 @@ var startWorkspaceCommand = &cobra.Command{

func init() {
wsCmd.AddCommand(startWorkspaceCommand)
startWorkspaceCommand.Flags().BoolVarP(&startNonBlocking, "non-blocking", "n", false, "do not wait for workspace to fully start, only initialize")
startWorkspaceCommand.Flags().BoolVarP(&startDontWait, "dont-wait", "d", false, "do not wait for workspace to fully start, only initialize")
startWorkspaceCommand.Flags().BoolVarP(&startOpenSsh, "ssh", "s", false, "open an SSH connection to workspace after starting")
startWorkspaceCommand.Flags().BoolVarP(&startOpenEditor, "open", "e", false, "open the workspace in an editor after starting")
}
6 changes: 3 additions & 3 deletions components/local-app/cmd/workspace-stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/spf13/cobra"
)

var stopNonBlocking = false
var stopDontWait = false

// stopWorkspaceCommand stops to a given workspace
var stopWorkspaceCommand = &cobra.Command{
Expand Down Expand Up @@ -60,7 +60,7 @@ var stopWorkspaceCommand = &cobra.Command{
return nil
}

if stopNonBlocking {
if stopDontWait {
fmt.Println("Workspace stopping")
return nil
}
Expand Down Expand Up @@ -108,5 +108,5 @@ var stopWorkspaceCommand = &cobra.Command{

func init() {
wsCmd.AddCommand(stopWorkspaceCommand)
stopWorkspaceCommand.Flags().BoolVarP(&stopNonBlocking, "non-blocking", "n", false, "do not wait for workspace to fully stop, only initialize")
stopWorkspaceCommand.Flags().BoolVarP(&stopDontWait, "dont-wait", "d", false, "do not wait for workspace to fully stop, only initialize")
}
54 changes: 4 additions & 50 deletions components/local-app/cmd/workspaces-connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@ package cmd

import (
"context"
"fmt"
"os"
"os/exec"
"strings"
"time"

"github.com/bufbuild/connect-go"
v1 "github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1"
"github.com/gitpod-io/local-app/pkg/common"
"github.com/spf13/cobra"
)

var dryRun bool

// connectWorkspaceCommand connects to a given workspace
var connectWorkspaceCommand = &cobra.Command{
Use: "ssh <workspace-id>",
Expand All @@ -37,54 +34,11 @@ var connectWorkspaceCommand = &cobra.Command{
ctx, cancel := context.WithTimeout(cmd.Context(), 5*time.Second)
defer cancel()

gitpod, err := common.GetGitpodClient(ctx)
if err != nil {
return err
}

workspace, err := gitpod.Workspaces.GetWorkspace(ctx, connect.NewRequest(&v1.GetWorkspaceRequest{WorkspaceId: workspaceID}))
if err != nil {
return err
}

wsInfo := workspace.Msg.GetResult()

if wsInfo.Status.Instance.Status.Phase != v1.WorkspaceInstanceStatus_PHASE_RUNNING {
return fmt.Errorf("cannot connect, workspace is not running")
}

token, err := gitpod.Workspaces.GetOwnerToken(ctx, connect.NewRequest(&v1.GetOwnerTokenRequest{WorkspaceId: workspaceID}))
if err != nil {
return err
}

ownerToken := token.Msg.Token

host := strings.Replace(wsInfo.Status.Instance.Status.Url, wsInfo.WorkspaceId, wsInfo.WorkspaceId+".ssh", -1)
host = strings.Replace(host, "https://", "", -1)

if dryRun, err := cmd.Flags().GetBool("dry-run"); err == nil && dryRun {
fmt.Println("ssh", fmt.Sprintf("%s#%s@%s", wsInfo.WorkspaceId, ownerToken, host), "-o", "StrictHostKeyChecking=no")
return nil
}

fmt.Println("Connecting to", wsInfo.Description)

command := exec.Command("ssh", fmt.Sprintf("%s#%s@%s", wsInfo.WorkspaceId, ownerToken, host), "-o", "StrictHostKeyChecking=no")

command.Stdin = os.Stdin
command.Stdout = os.Stdout
command.Stderr = os.Stderr

if err := command.Run(); err != nil {
os.Exit(1)
}

return nil
return common.SshConnectToWs(ctx, workspaceID, dryRun)
},
}

func init() {
wsCmd.AddCommand(connectWorkspaceCommand)
connectWorkspaceCommand.Flags().BoolP("dry-run", "n", false, "Dry run the command")
connectWorkspaceCommand.Flags().BoolVarP(&dryRun, "dry-run", "n", false, "Dry run the command")
}
64 changes: 64 additions & 0 deletions components/local-app/pkg/common/ws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.

package common

import (
"context"
"fmt"
"log/slog"
"os"
"os/exec"
"strings"

"github.com/bufbuild/connect-go"
v1 "github.com/gitpod-io/gitpod/components/public-api/go/experimental/v1"
)

func SshConnectToWs(ctx context.Context, workspaceID string, runDry bool) error {
gitpod, err := GetGitpodClient(ctx)
if err != nil {
return err
}

workspace, err := gitpod.Workspaces.GetWorkspace(ctx, connect.NewRequest(&v1.GetWorkspaceRequest{WorkspaceId: workspaceID}))
if err != nil {
return err
}

wsInfo := workspace.Msg.GetResult()

if wsInfo.Status.Instance.Status.Phase != v1.WorkspaceInstanceStatus_PHASE_RUNNING {
return fmt.Errorf("cannot connect, workspace is not running")
}

token, err := gitpod.Workspaces.GetOwnerToken(ctx, connect.NewRequest(&v1.GetOwnerTokenRequest{WorkspaceId: workspaceID}))
if err != nil {
return err
}

ownerToken := token.Msg.Token

host := strings.Replace(wsInfo.Status.Instance.Status.Url, wsInfo.WorkspaceId, wsInfo.WorkspaceId+".ssh", -1)
host = strings.Replace(host, "https://", "", -1)

if runDry {
fmt.Println("ssh", fmt.Sprintf("%s#%s@%s", wsInfo.WorkspaceId, ownerToken, host), "-o", "StrictHostKeyChecking=no")
return nil
}

slog.Debug("Connecting to", wsInfo.Description)

command := exec.Command("ssh", fmt.Sprintf("%s#%s@%s", wsInfo.WorkspaceId, ownerToken, host), "-o", "StrictHostKeyChecking=no")

command.Stdin = os.Stdin
command.Stdout = os.Stdout
command.Stderr = os.Stderr

if err := command.Run(); err != nil {
return err
}

return nil
}

0 comments on commit caa71dd

Please sign in to comment.