Skip to content

Commit bf0ae8f

Browse files
authored
feat: Refactor API routes to use UUIDs instead of friendly names (coder#401)
* Add client for agent * Cleanup code * Fix linting error * Rename routes to be simpler * Rename workspace history to workspace build * Refactor HTTP middlewares to use UUIDs * Cleanup routes * Compiles! * Fix files and organizations * Fix querying * Fix agent lock * Cleanup database abstraction * Add parameters * Fix linting errors * Fix log race * Lock on close wait * Fix log cleanup * Fix e2e tests * Fix upstream version of opencensus-go * Update coderdtest.go * Fix coverpkg * Fix codecov ignore
1 parent 330686f commit bf0ae8f

File tree

115 files changed

+5676
-4480
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+5676
-4480
lines changed

.github/workflows/coder.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ jobs:
157157
GOMAXPROCS: ${{ runner.os == 'Windows' && 1 || 2 }}
158158
run: gotestsum --junitfile="gotests.xml" --packages="./..." --
159159
-covermode=atomic -coverprofile="gotests.coverage"
160+
-coverpkg=./...,github.com/coder/coder/codersdk
160161
-timeout=3m -count=$GOCOUNT -race -short -failfast
161162

162163
- name: Upload DataDog Trace
@@ -172,6 +173,7 @@ jobs:
172173
if: runner.os == 'Linux'
173174
run: DB=true gotestsum --junitfile="gotests.xml" --packages="./..." --
174175
-covermode=atomic -coverprofile="gotests.coverage" -timeout=3m
176+
-coverpkg=./...,github.com/coder/coder/codersdk
175177
-count=1 -race -parallel=2 -failfast
176178

177179
- name: Upload DataDog Trace

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
"go.lintFlags": ["--fast"],
77
"go.lintOnSave": "package",
88
"go.coverOnSave": true,
9+
// The codersdk is used by coderd another other packages extensively.
10+
// To reduce redundancy in tests, it's covered by other packages.
11+
"go.testFlags": ["-coverpkg=./.,github.com/coder/coder/codersdk"],
912
"go.coverageDecorator": {
1013
"type": "gutter",
1114
"coveredHighlightColor": "rgba(64,128,128,0.5)",

agent/agent.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ type Options struct {
5959
Logger slog.Logger
6060
}
6161

62-
type Dialer func(ctx context.Context) (*peerbroker.Listener, error)
62+
type Dialer func(ctx context.Context, options *peer.ConnOptions) (*peerbroker.Listener, error)
6363

64-
func New(dialer Dialer, options *Options) io.Closer {
64+
func New(dialer Dialer, options *peer.ConnOptions) io.Closer {
6565
ctx, cancelFunc := context.WithCancel(context.Background())
6666
server := &server{
6767
clientDialer: dialer,
@@ -75,11 +75,12 @@ func New(dialer Dialer, options *Options) io.Closer {
7575

7676
type server struct {
7777
clientDialer Dialer
78-
options *Options
78+
options *peer.ConnOptions
7979

80-
closeCancel context.CancelFunc
81-
closeMutex sync.Mutex
82-
closed chan struct{}
80+
connCloseWait sync.WaitGroup
81+
closeCancel context.CancelFunc
82+
closeMutex sync.Mutex
83+
closed chan struct{}
8384

8485
sshServer *ssh.Server
8586
}
@@ -249,7 +250,7 @@ func (s *server) run(ctx context.Context) {
249250
// An exponential back-off occurs when the connection is failing to dial.
250251
// This is to prevent server spam in case of a coderd outage.
251252
for retrier := retry.New(50*time.Millisecond, 10*time.Second); retrier.Wait(ctx); {
252-
peerListener, err = s.clientDialer(ctx)
253+
peerListener, err = s.clientDialer(ctx, s.options)
253254
if err != nil {
254255
if errors.Is(err, context.Canceled) {
255256
return
@@ -279,11 +280,18 @@ func (s *server) run(ctx context.Context) {
279280
s.run(ctx)
280281
return
281282
}
283+
s.closeMutex.Lock()
284+
s.connCloseWait.Add(1)
285+
s.closeMutex.Unlock()
282286
go s.handlePeerConn(ctx, conn)
283287
}
284288
}
285289

286290
func (s *server) handlePeerConn(ctx context.Context, conn *peer.Conn) {
291+
go func() {
292+
<-conn.Closed()
293+
s.connCloseWait.Done()
294+
}()
287295
for {
288296
channel, err := conn.Accept(ctx)
289297
if err != nil {
@@ -325,5 +333,6 @@ func (s *server) Close() error {
325333
close(s.closed)
326334
s.closeCancel()
327335
_ = s.sshServer.Close()
336+
s.connCloseWait.Wait()
328337
return nil
329338
}

agent/agent_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,9 @@ func TestAgent(t *testing.T) {
9494

9595
func setup(t *testing.T) proto.DRPCPeerBrokerClient {
9696
client, server := provisionersdk.TransportPipe()
97-
closer := agent.New(func(ctx context.Context) (*peerbroker.Listener, error) {
98-
return peerbroker.Listen(server, nil, &peer.ConnOptions{
99-
Logger: slogtest.Make(t, nil),
100-
})
101-
}, &agent.Options{
97+
closer := agent.New(func(ctx context.Context, opts *peer.ConnOptions) (*peerbroker.Listener, error) {
98+
return peerbroker.Listen(server, nil, opts)
99+
}, &peer.ConnOptions{
102100
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
103101
})
104102
t.Cleanup(func() {

cli/login.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func login() *cobra.Command {
5959
}
6060

6161
client := codersdk.New(serverURL)
62-
hasInitialUser, err := client.HasInitialUser(cmd.Context())
62+
hasInitialUser, err := client.HasFirstUser(cmd.Context())
6363
if err != nil {
6464
return xerrors.Errorf("has initial user: %w", err)
6565
}
@@ -119,7 +119,7 @@ func login() *cobra.Command {
119119
return xerrors.Errorf("specify password prompt: %w", err)
120120
}
121121

122-
_, err = client.CreateInitialUser(cmd.Context(), coderd.CreateInitialUserRequest{
122+
_, err = client.CreateFirstUser(cmd.Context(), coderd.CreateFirstUserRequest{
123123
Email: email,
124124
Username: username,
125125
Password: password,

cli/login_test.go

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package cli_test
22

33
import (
4-
"context"
54
"testing"
65

76
"github.com/stretchr/testify/require"
87

98
"github.com/coder/coder/cli/clitest"
10-
"github.com/coder/coder/coderd"
119
"github.com/coder/coder/coderd/coderdtest"
1210
"github.com/coder/coder/pty/ptytest"
1311
)
@@ -56,18 +54,7 @@ func TestLogin(t *testing.T) {
5654
t.Run("ExistingUserValidTokenTTY", func(t *testing.T) {
5755
t.Parallel()
5856
client := coderdtest.New(t, nil)
59-
_, err := client.CreateInitialUser(context.Background(), coderd.CreateInitialUserRequest{
60-
Username: "test-user",
61-
Email: "test-user@coder.com",
62-
Organization: "acme-corp",
63-
Password: "password",
64-
})
65-
require.NoError(t, err)
66-
token, err := client.LoginWithPassword(context.Background(), coderd.LoginWithPasswordRequest{
67-
Email: "test-user@coder.com",
68-
Password: "password",
69-
})
70-
require.NoError(t, err)
57+
coderdtest.CreateFirstUser(t, client)
7158

7259
root, _ := clitest.New(t, "login", client.URL.String(), "--force-tty", "--no-open")
7360
pty := ptytest.New(t)
@@ -79,20 +66,14 @@ func TestLogin(t *testing.T) {
7966
}()
8067

8168
pty.ExpectMatch("Paste your token here:")
82-
pty.WriteLine(token.SessionToken)
69+
pty.WriteLine(client.SessionToken)
8370
pty.ExpectMatch("Welcome to Coder")
8471
})
8572

8673
t.Run("ExistingUserInvalidTokenTTY", func(t *testing.T) {
8774
t.Parallel()
8875
client := coderdtest.New(t, nil)
89-
_, err := client.CreateInitialUser(context.Background(), coderd.CreateInitialUserRequest{
90-
Username: "test-user",
91-
Email: "test-user@coder.com",
92-
Organization: "acme-corp",
93-
Password: "password",
94-
})
95-
require.NoError(t, err)
76+
coderdtest.CreateFirstUser(t, client)
9677

9778
root, _ := clitest.New(t, "login", client.URL.String(), "--force-tty", "--no-open")
9879
pty := ptytest.New(t)

cli/projectcreate.go

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func projectCreate() *cobra.Command {
5656
Default: filepath.Base(directory),
5757
Label: "What's your project's name?",
5858
Validate: func(s string) error {
59-
project, _ := client.Project(cmd.Context(), organization.Name, s)
59+
project, _ := client.ProjectByName(cmd.Context(), organization.ID, s)
6060
if project.ID.String() != uuid.Nil.String() {
6161
return xerrors.New("A project already exists with that name!")
6262
}
@@ -71,9 +71,9 @@ func projectCreate() *cobra.Command {
7171
if err != nil {
7272
return err
7373
}
74-
project, err := client.CreateProject(cmd.Context(), organization.Name, coderd.CreateProjectRequest{
75-
Name: name,
76-
VersionImportJobID: job.ID,
74+
project, err := client.CreateProject(cmd.Context(), organization.ID, coderd.CreateProjectRequest{
75+
Name: name,
76+
VersionID: job.ID,
7777
})
7878
if err != nil {
7979
return err
@@ -118,7 +118,7 @@ func projectCreate() *cobra.Command {
118118
return cmd
119119
}
120120

121-
func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, organization coderd.Organization, provisioner database.ProvisionerType, directory string, parameters ...coderd.CreateParameterValueRequest) (*coderd.ProvisionerJob, error) {
121+
func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, organization coderd.Organization, provisioner database.ProvisionerType, directory string, parameters ...coderd.CreateParameterRequest) (*coderd.ProjectVersion, error) {
122122
spin := spinner.New(spinner.CharSets[5], 100*time.Millisecond)
123123
spin.Writer = cmd.OutOrStdout()
124124
spin.Suffix = " Uploading current directory..."
@@ -133,13 +133,13 @@ func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, o
133133
if err != nil {
134134
return nil, err
135135
}
136-
resp, err := client.UploadFile(cmd.Context(), codersdk.ContentTypeTar, tarData)
136+
resp, err := client.Upload(cmd.Context(), codersdk.ContentTypeTar, tarData)
137137
if err != nil {
138138
return nil, err
139139
}
140140

141141
before := time.Now()
142-
job, err := client.CreateProjectImportJob(cmd.Context(), organization.Name, coderd.CreateProjectImportJobRequest{
142+
version, err := client.CreateProjectVersion(cmd.Context(), organization.ID, coderd.CreateProjectVersionRequest{
143143
StorageMethod: database.ProvisionerStorageMethodFile,
144144
StorageSource: resp.Hash,
145145
Provisioner: provisioner,
@@ -149,7 +149,7 @@ func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, o
149149
return nil, err
150150
}
151151
spin.Suffix = " Waiting for the import to complete..."
152-
logs, err := client.ProjectImportJobLogsAfter(cmd.Context(), organization.Name, job.ID, before)
152+
logs, err := client.ProjectVersionLogsAfter(cmd.Context(), version.ID, before)
153153
if err != nil {
154154
return nil, err
155155
}
@@ -162,22 +162,22 @@ func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, o
162162
logBuffer = append(logBuffer, log)
163163
}
164164

165-
job, err = client.ProjectImportJob(cmd.Context(), organization.Name, job.ID)
165+
version, err = client.ProjectVersion(cmd.Context(), version.ID)
166166
if err != nil {
167167
return nil, err
168168
}
169-
parameterSchemas, err := client.ProjectImportJobSchemas(cmd.Context(), organization.Name, job.ID)
169+
parameterSchemas, err := client.ProjectVersionSchema(cmd.Context(), version.ID)
170170
if err != nil {
171171
return nil, err
172172
}
173-
parameterValues, err := client.ProjectImportJobParameters(cmd.Context(), organization.Name, job.ID)
173+
parameterValues, err := client.ProjectVersionParameters(cmd.Context(), version.ID)
174174
if err != nil {
175175
return nil, err
176176
}
177177
spin.Stop()
178178

179-
if provisionerd.IsMissingParameterError(job.Error) {
180-
valuesBySchemaID := map[string]coderd.ComputedParameterValue{}
179+
if provisionerd.IsMissingParameterError(version.Job.Error) {
180+
valuesBySchemaID := map[string]coderd.ProjectVersionParameter{}
181181
for _, parameterValue := range parameterValues {
182182
valuesBySchemaID[parameterValue.SchemaID.String()] = parameterValue
183183
}
@@ -192,7 +192,7 @@ func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, o
192192
if err != nil {
193193
return nil, err
194194
}
195-
parameters = append(parameters, coderd.CreateParameterValueRequest{
195+
parameters = append(parameters, coderd.CreateParameterRequest{
196196
Name: parameterSchema.Name,
197197
SourceValue: value,
198198
SourceScheme: database.ParameterSourceSchemeData,
@@ -202,21 +202,20 @@ func validateProjectVersionSource(cmd *cobra.Command, client *codersdk.Client, o
202202
return validateProjectVersionSource(cmd, client, organization, provisioner, directory, parameters...)
203203
}
204204

205-
if job.Status != coderd.ProvisionerJobStatusSucceeded {
205+
if version.Job.Status != coderd.ProvisionerJobSucceeded {
206206
for _, log := range logBuffer {
207207
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s %s\n", color.HiGreenString("[tf]"), log.Output)
208208
}
209-
210-
return nil, xerrors.New(job.Error)
209+
return nil, xerrors.New(version.Job.Error)
211210
}
212211

213212
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s Successfully imported project source!\n", color.HiGreenString("✓"))
214213

215-
resources, err := client.ProjectImportJobResources(cmd.Context(), organization.Name, job.ID)
214+
resources, err := client.ProjectVersionResources(cmd.Context(), version.ID)
216215
if err != nil {
217216
return nil, err
218217
}
219-
return &job, displayProjectImportInfo(cmd, parameterSchemas, parameterValues, resources)
218+
return &version, displayProjectImportInfo(cmd, parameterSchemas, parameterValues, resources)
220219
}
221220

222221
func tarDirectory(directory string) ([]byte, error) {

cli/projectcreate_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func TestProjectCreate(t *testing.T) {
1818
t.Run("NoParameters", func(t *testing.T) {
1919
t.Parallel()
2020
client := coderdtest.New(t, nil)
21-
coderdtest.CreateInitialUser(t, client)
21+
coderdtest.CreateFirstUser(t, client)
2222
source := clitest.CreateProjectVersionSource(t, &echo.Responses{
2323
Parse: echo.ParseComplete,
2424
Provision: echo.ProvisionComplete,
@@ -54,7 +54,7 @@ func TestProjectCreate(t *testing.T) {
5454
t.Run("Parameter", func(t *testing.T) {
5555
t.Parallel()
5656
client := coderdtest.New(t, nil)
57-
coderdtest.CreateInitialUser(t, client)
57+
coderdtest.CreateFirstUser(t, client)
5858
source := clitest.CreateProjectVersionSource(t, &echo.Responses{
5959
Parse: []*proto.Parse_Response{{
6060
Type: &proto.Parse_Response_Complete{

cli/projectlist.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func projectList() *cobra.Command {
2323
if err != nil {
2424
return err
2525
}
26-
projects, err := client.Projects(cmd.Context(), organization.Name)
26+
projects, err := client.ProjectsByOrganization(cmd.Context(), organization.ID)
2727
if err != nil {
2828
return err
2929
}

cli/projectlist_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func TestProjectList(t *testing.T) {
1515
t.Run("None", func(t *testing.T) {
1616
t.Parallel()
1717
client := coderdtest.New(t, nil)
18-
coderdtest.CreateInitialUser(t, client)
18+
coderdtest.CreateFirstUser(t, client)
1919
cmd, root := clitest.New(t, "projects", "list")
2020
clitest.SetupConfig(t, client, root)
2121
pty := ptytest.New(t)
@@ -33,12 +33,12 @@ func TestProjectList(t *testing.T) {
3333
t.Run("List", func(t *testing.T) {
3434
t.Parallel()
3535
client := coderdtest.New(t, nil)
36-
user := coderdtest.CreateInitialUser(t, client)
36+
user := coderdtest.CreateFirstUser(t, client)
3737
daemon := coderdtest.NewProvisionerDaemon(t, client)
38-
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
39-
coderdtest.AwaitProjectImportJob(t, client, user.Organization, job.ID)
38+
version := coderdtest.CreateProjectVersion(t, client, user.OrganizationID, nil)
39+
coderdtest.AwaitProjectVersionJob(t, client, version.ID)
4040
_ = daemon.Close()
41-
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
41+
project := coderdtest.CreateProject(t, client, user.OrganizationID, version.ID)
4242
cmd, root := clitest.New(t, "projects", "list")
4343
clitest.SetupConfig(t, client, root)
4444
pty := ptytest.New(t)

cli/projects.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func projects() *cobra.Command {
4040
return cmd
4141
}
4242

43-
func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.ParameterSchema, parameterValues []coderd.ComputedParameterValue, resources []coderd.ProvisionerJobResource) error {
44-
schemaByID := map[string]coderd.ParameterSchema{}
43+
func displayProjectImportInfo(cmd *cobra.Command, parameterSchemas []coderd.ProjectVersionParameterSchema, parameterValues []coderd.ProjectVersionParameter, resources []coderd.WorkspaceResource) error {
44+
schemaByID := map[string]coderd.ProjectVersionParameterSchema{}
4545
for _, schema := range parameterSchemas {
4646
schemaByID[schema.ID.String()] = schema
4747
}

cli/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func createClient(cmd *cobra.Command) (*codersdk.Client, error) {
108108

109109
// currentOrganization returns the currently active organization for the authenticated user.
110110
func currentOrganization(cmd *cobra.Command, client *codersdk.Client) (coderd.Organization, error) {
111-
orgs, err := client.UserOrganizations(cmd.Context(), "me")
111+
orgs, err := client.OrganizationsByUser(cmd.Context(), "me")
112112
if err != nil {
113113
return coderd.Organization{}, nil
114114
}

0 commit comments

Comments
 (0)