Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b5a774a

Browse files
committed
Add create workspace CLI
1 parent 485c07b commit b5a774a

11 files changed

+108
-69
lines changed

cli/clitest/clitest.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,20 @@ import (
44
"archive/tar"
55
"bufio"
66
"bytes"
7-
"context"
87
"errors"
98
"io"
109
"os"
1110
"path/filepath"
1211
"regexp"
1312
"testing"
1413

14+
"github.com/Netflix/go-expect"
1515
"github.com/spf13/cobra"
1616
"github.com/stretchr/testify/require"
1717
"golang.org/x/xerrors"
1818

1919
"github.com/coder/coder/cli"
2020
"github.com/coder/coder/cli/config"
21-
"github.com/coder/coder/coderd"
22-
"github.com/coder/coder/coderd/coderdtest"
2321
"github.com/coder/coder/codersdk"
2422
"github.com/coder/coder/provisioner/echo"
2523
)
@@ -39,20 +37,12 @@ func New(t *testing.T, args ...string) (*cobra.Command, config.Root) {
3937
return cmd, root
4038
}
4139

42-
// CreateInitialUser creates the initial user and write's the session
43-
// token to the config root provided.
44-
func CreateInitialUser(t *testing.T, client *codersdk.Client, root config.Root) coderd.CreateInitialUserRequest {
45-
user := coderdtest.CreateInitialUser(t, client)
46-
resp, err := client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
47-
Email: user.Email,
48-
Password: user.Password,
49-
})
50-
require.NoError(t, err)
51-
err = root.Session().Write(resp.SessionToken)
40+
// SetupConfig applies the URL and SessionToken of the client to the config.
41+
func SetupConfig(t *testing.T, client *codersdk.Client, root config.Root) {
42+
err := root.Session().Write(client.SessionToken)
5243
require.NoError(t, err)
5344
err = root.URL().Write(client.URL.String())
5445
require.NoError(t, err)
55-
return user
5646
}
5747

5848
// CreateProjectVersionSource writes the echo provisioner responses into a
@@ -66,9 +56,9 @@ func CreateProjectVersionSource(t *testing.T, responses *echo.Responses) string
6656
return directory
6757
}
6858

69-
// StdoutLogs provides a writer to t.Log that strips
70-
// all ANSI escape codes.
71-
func StdoutLogs(t *testing.T) io.Writer {
59+
// NewConsole creates a new TTY bound to the command provided.
60+
// All ANSI escape codes are stripped to provide clean output.
61+
func NewConsole(t *testing.T, cmd *cobra.Command) *expect.Console {
7262
reader, writer := io.Pipe()
7363
scanner := bufio.NewScanner(reader)
7464
t.Cleanup(func() {
@@ -83,7 +73,12 @@ func StdoutLogs(t *testing.T) io.Writer {
8373
t.Log(stripAnsi.ReplaceAllString(scanner.Text(), ""))
8474
}
8575
}()
86-
return writer
76+
77+
console, err := expect.NewConsole(expect.WithStdout(writer))
78+
require.NoError(t, err)
79+
cmd.SetIn(console.Tty())
80+
cmd.SetOut(console.Tty())
81+
return console
8782
}
8883

8984
func extractTar(data []byte, directory string) error {

cli/login_test.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@ package cli_test
33
import (
44
"testing"
55

6-
"github.com/stretchr/testify/require"
7-
86
"github.com/coder/coder/cli/clitest"
97
"github.com/coder/coder/coderd/coderdtest"
10-
11-
"github.com/ActiveState/termtest/expect"
8+
"github.com/stretchr/testify/require"
129
)
1310

1411
func TestLogin(t *testing.T) {
@@ -23,12 +20,9 @@ func TestLogin(t *testing.T) {
2320

2421
t.Run("InitialUserTTY", func(t *testing.T) {
2522
t.Parallel()
26-
console, err := expect.NewConsole(expect.WithStdout(clitest.StdoutLogs(t)))
27-
require.NoError(t, err)
2823
client := coderdtest.New(t)
2924
root, _ := clitest.New(t, "login", client.URL.String())
30-
root.SetIn(console.Tty())
31-
root.SetOut(console.Tty())
25+
console := clitest.NewConsole(t, root)
3226
go func() {
3327
err := root.Execute()
3428
require.NoError(t, err)
@@ -44,12 +38,12 @@ func TestLogin(t *testing.T) {
4438
for i := 0; i < len(matches); i += 2 {
4539
match := matches[i]
4640
value := matches[i+1]
47-
_, err = console.ExpectString(match)
41+
_, err := console.ExpectString(match)
4842
require.NoError(t, err)
4943
_, err = console.SendLine(value)
5044
require.NoError(t, err)
5145
}
52-
_, err = console.ExpectString("Welcome to Coder")
46+
_, err := console.ExpectString("Welcome to Coder")
5347
require.NoError(t, err)
5448
})
5549
}

cli/projectcreate_test.go

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cli_test
33
import (
44
"testing"
55

6-
"github.com/ActiveState/termtest/expect"
76
"github.com/stretchr/testify/require"
87

98
"github.com/coder/coder/cli/clitest"
@@ -17,18 +16,16 @@ func TestProjectCreate(t *testing.T) {
1716
t.Parallel()
1817
t.Run("NoParameters", func(t *testing.T) {
1918
t.Parallel()
20-
console, err := expect.NewConsole(expect.WithStdout(clitest.StdoutLogs(t)))
21-
require.NoError(t, err)
2219
client := coderdtest.New(t)
20+
coderdtest.CreateInitialUser(t, client)
2321
source := clitest.CreateProjectVersionSource(t, &echo.Responses{
2422
Parse: echo.ParseComplete,
2523
Provision: echo.ProvisionComplete,
2624
})
2725
cmd, root := clitest.New(t, "projects", "create", "--directory", source, "--provisioner", string(database.ProvisionerTypeEcho))
28-
_ = clitest.CreateInitialUser(t, client, root)
26+
clitest.SetupConfig(t, client, root)
2927
_ = coderdtest.NewProvisionerDaemon(t, client)
30-
cmd.SetIn(console.Tty())
31-
cmd.SetOut(console.Tty())
28+
console := clitest.NewConsole(t, cmd)
3229
closeChan := make(chan struct{})
3330
go func() {
3431
err := cmd.Execute()
@@ -45,7 +42,7 @@ func TestProjectCreate(t *testing.T) {
4542
for i := 0; i < len(matches); i += 2 {
4643
match := matches[i]
4744
value := matches[i+1]
48-
_, err = console.ExpectString(match)
45+
_, err := console.ExpectString(match)
4946
require.NoError(t, err)
5047
_, err = console.SendLine(value)
5148
require.NoError(t, err)
@@ -55,9 +52,8 @@ func TestProjectCreate(t *testing.T) {
5552

5653
t.Run("Parameter", func(t *testing.T) {
5754
t.Parallel()
58-
console, err := expect.NewConsole(expect.WithStdout(clitest.StdoutLogs(t)))
59-
require.NoError(t, err)
6055
client := coderdtest.New(t)
56+
coderdtest.CreateInitialUser(t, client)
6157
source := clitest.CreateProjectVersionSource(t, &echo.Responses{
6258
Parse: []*proto.Parse_Response{{
6359
Type: &proto.Parse_Response_Complete{
@@ -74,10 +70,9 @@ func TestProjectCreate(t *testing.T) {
7470
Provision: echo.ProvisionComplete,
7571
})
7672
cmd, root := clitest.New(t, "projects", "create", "--directory", source, "--provisioner", string(database.ProvisionerTypeEcho))
77-
_ = clitest.CreateInitialUser(t, client, root)
78-
_ = coderdtest.NewProvisionerDaemon(t, client)
79-
cmd.SetIn(console.Tty())
80-
cmd.SetOut(console.Tty())
73+
clitest.SetupConfig(t, client, root)
74+
coderdtest.NewProvisionerDaemon(t, client)
75+
console := clitest.NewConsole(t, cmd)
8176
closeChan := make(chan struct{})
8277
go func() {
8378
err := cmd.Execute()
@@ -95,7 +90,7 @@ func TestProjectCreate(t *testing.T) {
9590
for i := 0; i < len(matches); i += 2 {
9691
match := matches[i]
9792
value := matches[i+1]
98-
_, err = console.ExpectString(match)
93+
_, err := console.ExpectString(match)
9994
require.NoError(t, err)
10095
_, err = console.SendLine(value)
10196
require.NoError(t, err)

cli/root.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ func createClient(cmd *cobra.Command) (*codersdk.Client, error) {
8686
return nil, err
8787
}
8888
client := codersdk.New(serverURL)
89-
return client, client.SetSessionToken(token)
89+
client.SessionToken = token
90+
return client, nil
9091
}
9192

9293
// currentOrganization returns the currently active organization for the authenticated user.

cli/workspacecreate.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ func workspaceCreate() *cobra.Command {
3636
name, err = prompt(cmd, &promptui.Prompt{
3737
Label: "What's your workspace's name?",
3838
Validate: func(s string) error {
39+
if s == "" {
40+
return xerrors.Errorf("You must provide a name!")
41+
}
3942
workspace, _ := client.Workspace(cmd.Context(), "", s)
4043
if workspace.ID.String() != uuid.Nil.String() {
4144
return xerrors.New("A workspace already exists with that name!")

cli/workspacecreate_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cli_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/coder/coder/cli/clitest"
7+
"github.com/coder/coder/coderd/coderdtest"
8+
"github.com/coder/coder/provisioner/echo"
9+
"github.com/coder/coder/provisionersdk/proto"
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestWorkspaceCreate(t *testing.T) {
14+
t.Parallel()
15+
t.Run("Create", func(t *testing.T) {
16+
t.Parallel()
17+
client := coderdtest.New(t)
18+
user := coderdtest.CreateInitialUser(t, client)
19+
_ = coderdtest.NewProvisionerDaemon(t, client)
20+
job := coderdtest.CreateProjectImportProvisionerJob(t, client, user.Organization, &echo.Responses{
21+
Parse: echo.ParseComplete,
22+
Provision: []*proto.Provision_Response{{
23+
Type: &proto.Provision_Response_Complete{
24+
Complete: &proto.Provision_Complete{
25+
Resources: []*proto.Resource{{
26+
Name: "example",
27+
Type: "aws_instance",
28+
}},
29+
},
30+
},
31+
}},
32+
})
33+
coderdtest.AwaitProvisionerJob(t, client, user.Organization, job.ID)
34+
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
35+
cmd, root := clitest.New(t, "workspaces", "create", project.Name)
36+
clitest.SetupConfig(t, client, root)
37+
38+
console := clitest.NewConsole(t, cmd)
39+
closeChan := make(chan struct{})
40+
go func() {
41+
err := cmd.Execute()
42+
require.NoError(t, err)
43+
close(closeChan)
44+
}()
45+
46+
matches := []string{
47+
"name?", "workspace-name",
48+
"Create workspace", "y",
49+
}
50+
for i := 0; i < len(matches); i += 2 {
51+
match := matches[i]
52+
value := matches[i+1]
53+
_, err := console.ExpectString(match)
54+
require.NoError(t, err)
55+
_, err = console.SendLine(value)
56+
require.NoError(t, err)
57+
}
58+
_, err := console.ExpectString("Create")
59+
require.NoError(t, err)
60+
<-closeChan
61+
})
62+
}

coderd/coderdtest/coderdtest.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ func CreateInitialUser(t *testing.T, client *codersdk.Client) coderd.CreateIniti
117117
Password: req.Password,
118118
})
119119
require.NoError(t, err)
120-
err = client.SetSessionToken(login.SessionToken)
121-
require.NoError(t, err)
120+
client.SessionToken = login.SessionToken
122121
return req
123122
}
124123

coderd/provisionerdaemons.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,11 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
195195
if err != nil {
196196
return nil, failJob(fmt.Sprintf("get project: %s", err))
197197
}
198-
organization, err := server.Database.GetOrganizationByID(ctx, project.OrganizationID)
199-
if err != nil {
200-
return nil, failJob(fmt.Sprintf("get organization: %s", err))
201-
}
202198

203199
// Compute parameters for the workspace to consume.
204200
parameters, err := parameter.Compute(ctx, server.Database, parameter.ComputeScope{
205201
ProjectImportJobID: projectVersion.ImportJobID,
206-
OrganizationID: organization.ID,
202+
OrganizationID: job.OrganizationID,
207203
ProjectID: uuid.NullUUID{
208204
UUID: project.ID,
209205
Valid: true,
@@ -226,6 +222,11 @@ func (server *provisionerdServer) AcquireJob(ctx context.Context, _ *proto.Empty
226222
}
227223
protoParameters = append(protoParameters, converted)
228224
}
225+
protoParameters = append(protoParameters, &sdkproto.ParameterValue{
226+
DestinationScheme: sdkproto.ParameterDestination_PROVISIONER_VARIABLE,
227+
Name: parameter.CoderWorkspaceTransition,
228+
Value: string(workspaceHistory.Transition),
229+
})
229230

230231
protoJob.Type = &proto.AcquiredJob_WorkspaceProvision_{
231232
WorkspaceProvision: &proto.AcquiredJob_WorkspaceProvision{

coderd/provisionerjobs.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ func (api *api) postProvisionerImportJobByOrganization(rw http.ResponseWriter, r
112112
StorageMethod: database.ProvisionerStorageMethodFile,
113113
StorageSource: file.Hash,
114114
Type: database.ProvisionerJobTypeProjectVersionImport,
115+
Input: []byte{'{', '}'},
115116
})
116117
if err != nil {
117118
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{

coderd/workspaces_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestPostWorkspaceByUser(t *testing.T) {
7373
Password: anotherUser.Password,
7474
})
7575
require.NoError(t, err)
76-
err = client.SetSessionToken(token.SessionToken)
76+
client.SessionToken = token.SessionToken
7777
require.NoError(t, err)
7878

7979
_, err = client.CreateWorkspace(context.Background(), "", coderd.CreateWorkspaceRequest{

codersdk/client.go

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"fmt"
99
"io"
1010
"net/http"
11-
"net/http/cookiejar"
1211
"net/url"
1312
"strings"
1413

@@ -28,27 +27,12 @@ func New(serverURL *url.URL) *Client {
2827

2928
// Client is an HTTP caller for methods to the Coder API.
3029
type Client struct {
31-
URL *url.URL
30+
URL *url.URL
31+
SessionToken string
3232

3333
httpClient *http.Client
3434
}
3535

36-
// SetSessionToken applies the provided token to the current client.
37-
func (c *Client) SetSessionToken(token string) error {
38-
if c.httpClient.Jar == nil {
39-
var err error
40-
c.httpClient.Jar, err = cookiejar.New(nil)
41-
if err != nil {
42-
return err
43-
}
44-
}
45-
c.httpClient.Jar.SetCookies(c.URL, []*http.Cookie{{
46-
Name: httpmw.AuthCookie,
47-
Value: token,
48-
}})
49-
return nil
50-
}
51-
5236
// request performs an HTTP request with the body provided.
5337
// The caller is responsible for closing the response body.
5438
func (c *Client) request(ctx context.Context, method, path string, body interface{}, opts ...func(r *http.Request)) (*http.Response, error) {
@@ -76,6 +60,10 @@ func (c *Client) request(ctx context.Context, method, path string, body interfac
7660
if err != nil {
7761
return nil, xerrors.Errorf("create request: %w", err)
7862
}
63+
req.AddCookie(&http.Cookie{
64+
Name: httpmw.AuthCookie,
65+
Value: c.SessionToken,
66+
})
7967
if body != nil {
8068
req.Header.Set("Content-Type", "application/json")
8169
}

0 commit comments

Comments
 (0)