Skip to content

feat: restart stopped workspaces on ssh command #11050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 8, 2023
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Add unit test
  • Loading branch information
Emyrk committed Dec 5, 2023
commit 0d129487c70f29e8885102629692d0d45274e54b
61 changes: 61 additions & 0 deletions cli/ssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import (
"testing"
"time"

"github.com/coder/coder/v2/provisioner/echo"
"github.com/google/uuid"

"github.com/coder/coder/v2/coderd/rbac"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
Expand Down Expand Up @@ -86,6 +91,62 @@ func TestSSH(t *testing.T) {
pty.WriteLine("exit")
<-cmdDone
})
t.Run("StartStoppedWorkspace", func(t *testing.T) {
t.Parallel()

//store, ps := dbtestutil.NewDB(t)
//ownerClient := coderdtest.New(t, &coderdtest.Options{Pubsub: ps, Database: store, IncludeProvisionerDaemon: true})
//ownerClient.SetLogger(slogtest.Make(t, nil).Named("client").Leveled(slog.LevelDebug))
//first := coderdtest.CreateFirstUser(t, ownerClient)
//client, user := coderdtest.CreateAnotherUser(t, ownerClient, first.OrganizationID)
//
//// Create a stopped workspace.
//workspaceData := dbfake.WorkspaceBuild(t, store, database.Workspace{
// OrganizationID: first.OrganizationID,
// OwnerID: user.ID,
//}).Seed(database.WorkspaceBuild{
// Transition: database.WorkspaceTransitionStop,
//}).WithAgent().Do()
//workspace := workspaceData.Workspace
//
authToken := uuid.NewString()
ownerClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, ownerClient)
client, _ := coderdtest.CreateAnotherUser(t, ownerClient, owner.OrganizationID, rbac.RoleTemplateAdmin())
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionPlan: echo.PlanComplete,
ProvisionApply: echo.ProvisionApplyWithAgent(authToken),
})
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
workspace := coderdtest.CreateWorkspace(t, client, owner.OrganizationID, template.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
// Stop the workspace
workspaceBuild := coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStop)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspaceBuild.ID)

//
inv, root := clitest.New(t, "ssh", workspace.Name)
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t).Attach(inv)

ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

cmdDone := tGo(t, func() {
err := inv.WithContext(ctx).Run()
assert.NoError(t, err)
})
pty.ExpectMatch("⧗ Running")
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this has the potential to be racy, i.e. workspace started before we end up streaming logs. 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

That is a good point. I am unsure how to prevent that 🤔.

We really should have a controllable provisioner in our unit tests to trigger this stuff 😢

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, we have coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) before I run exit which is sufficient to wait for the workspace to be ready.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I think workspace being ready shouldn't be an issue. But I'm wondering if the provisioner log missing could be an issue depending on at what stage of the workspace lifecycle we connect to it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, I removed it because I check if the agent is ready right below it. So That agent ready will always work, even if we miss the logs.


_ = agenttest.New(t, client.URL, authToken)
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)

// Shells on Mac, Windows, and Linux all exit shells with the "exit" command.
pty.WriteLine("exit")
<-cmdDone
})
t.Run("ShowTroubleshootingURLAfterTimeout", func(t *testing.T) {
t.Parallel()

Expand Down