From b1c5a08a5235bdc3b388c2512fdf4d0a4fc7efcb Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 30 Oct 2023 15:37:07 +0000 Subject: [PATCH 1/9] feat: add dbfakedata for workspace builds and resources This creates `coderdtest.NewWithDatabase` and adds a series of helper functions to `dbfake` that insert structured fake data for resources into the database. It allows us to remove provisionerd from a significant amount of tests which should speed them up and reduce flakes. --- cli/agent_test.go | 78 +++++++++------------- coderd/coderdtest/coderdtest.go | 7 ++ coderd/database/dbfakedata/dbfakedata.go | 83 ++++++++++++++++++++++++ coderd/database/dbgen/dbgen.go | 8 ++- coderd/workspaceagents_test.go | 48 +++++--------- 5 files changed, 143 insertions(+), 81 deletions(-) create mode 100644 coderd/database/dbfakedata/dbfakedata.go diff --git a/cli/agent_test.go b/cli/agent_test.go index dd2266ec14394..61cbc0a2ed785 100644 --- a/cli/agent_test.go +++ b/cli/agent_test.go @@ -16,6 +16,8 @@ import ( "github.com/coder/coder/v2/agent" "github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/coderd/coderdtest" + "github.com/coder/coder/v2/coderd/database" + "github.com/coder/coder/v2/coderd/database/dbfakedata" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk/proto" @@ -68,33 +70,23 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() instanceID := "instanceidentifier" certificates, metadataClient := coderdtest.NewAzureInstanceIdentity(t, instanceID) - client := coderdtest.New(t, &coderdtest.Options{ - AzureCertificates: certificates, - IncludeProvisionerDaemon: true, + client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ + AzureCertificates: certificates, }) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "somename", - Type: "someinstance", - Agents: []*proto.Agent{{ - Auth: &proto.Agent_InstanceId{ - InstanceId: instanceID, - }, - }}, - }}, - }, + ws := dbfakedata.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, + }) + dbfakedata.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "somename", + Type: "someinstance", + Agents: []*proto.Agent{{ + Auth: &proto.Agent_InstanceId{ + InstanceId: instanceID, }, }}, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) inv, _ := clitest.New(t, "agent", "--auth", "azure-instance-identity", "--agent-url", client.URL.String()) inv = inv.WithContext( @@ -103,8 +95,8 @@ func TestWorkspaceAgent(t *testing.T) { ) ctx := inv.Context() clitest.Start(t, inv) - coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) - workspace, err := client.Workspace(ctx, workspace.ID) + coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) + workspace, err := client.Workspace(ctx, ws.ID) require.NoError(t, err) resources := workspace.LatestBuild.Resources if assert.NotEmpty(t, workspace.LatestBuild.Resources) && assert.NotEmpty(t, resources[0].Agents) { @@ -120,33 +112,23 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() instanceID := "instanceidentifier" certificates, metadataClient := coderdtest.NewAWSInstanceIdentity(t, instanceID) - client := coderdtest.New(t, &coderdtest.Options{ - AWSCertificates: certificates, - IncludeProvisionerDaemon: true, + client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ + AWSCertificates: certificates, }) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "somename", - Type: "someinstance", - Agents: []*proto.Agent{{ - Auth: &proto.Agent_InstanceId{ - InstanceId: instanceID, - }, - }}, - }}, - }, + ws := dbfakedata.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, + }) + dbfakedata.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "somename", + Type: "someinstance", + Agents: []*proto.Agent{{ + Auth: &proto.Agent_InstanceId{ + InstanceId: instanceID, }, }}, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) inv, _ := clitest.New(t, "agent", "--auth", "aws-instance-identity", "--agent-url", client.URL.String()) inv = inv.WithContext( @@ -155,8 +137,8 @@ func TestWorkspaceAgent(t *testing.T) { ) clitest.Start(t, inv) ctx := inv.Context() - coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) - workspace, err := client.Workspace(ctx, workspace.ID) + coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) + workspace, err := client.Workspace(ctx, ws.ID) require.NoError(t, err) resources := workspace.LatestBuild.Resources if assert.NotEmpty(t, resources) && assert.NotEmpty(t, resources[0].Agents) { diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 85ceeba1be349..2722f0b346fd9 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -151,6 +151,13 @@ func New(t testing.TB, options *Options) *codersdk.Client { return client } +// NewWithDatabase constructs a codersdk client connected to an in-memory API instance. +// The database is returned to provide direct data manipulation for tests. +func NewWithDatabase(t testing.TB, options *Options) (*codersdk.Client, database.Store) { + client, _, api := NewWithAPI(t, options) + return client, api.Database +} + // NewWithProvisionerCloser returns a client as well as a handle to close // the provisioner. This is a temporary function while work is done to // standardize how provisioners are registered with coderd. The option diff --git a/coderd/database/dbfakedata/dbfakedata.go b/coderd/database/dbfakedata/dbfakedata.go new file mode 100644 index 0000000000000..bc28f1e4053e2 --- /dev/null +++ b/coderd/database/dbfakedata/dbfakedata.go @@ -0,0 +1,83 @@ +package dbfakedata + +import ( + "context" + "database/sql" + "encoding/json" + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/coderd/database" + "github.com/coder/coder/v2/coderd/database/dbauthz" + "github.com/coder/coder/v2/coderd/database/dbgen" + "github.com/coder/coder/v2/coderd/database/dbtime" + "github.com/coder/coder/v2/coderd/provisionerdserver" + "github.com/coder/coder/v2/coderd/telemetry" + sdkproto "github.com/coder/coder/v2/provisionersdk/proto" +) + +// CreateWorkspace inserts a workspace into the database. +func CreateWorkspace(t testing.TB, db database.Store, seed database.Workspace) database.Workspace { + t.Helper() + + // This intentionally fulfills the minimum requirements of the schema. + // Tests can provide a custom template ID if necessary. + if seed.TemplateID == uuid.Nil { + template := dbgen.Template(t, db, database.Template{ + OrganizationID: seed.OrganizationID, + CreatedBy: seed.OwnerID, + }) + seed.TemplateID = template.ID + } + return dbgen.Workspace(t, db, seed) +} + +// CreateWorkspaceBuild inserts a build and a successful job into the database. +func CreateWorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed database.WorkspaceBuild, resources ...*sdkproto.Resource) database.WorkspaceBuild { + t.Helper() + jobID := uuid.New() + seed.JobID = jobID + seed.WorkspaceID = ws.ID + // This intentionally fulfills the minimum requirements of the schema. + // Tests can provide a custom version ID if necessary. + if seed.TemplateVersionID == uuid.Nil { + templateVersion := dbgen.TemplateVersion(t, db, database.TemplateVersion{ + OrganizationID: ws.OrganizationID, + CreatedBy: ws.OwnerID, + }) + seed.TemplateVersionID = templateVersion.ID + } + build := dbgen.WorkspaceBuild(t, db, seed) + + payload, err := json.Marshal(provisionerdserver.WorkspaceProvisionJob{ + WorkspaceBuildID: build.ID, + }) + require.NoError(t, err) + job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ + ID: jobID, + Input: payload, + OrganizationID: ws.OrganizationID, + CompletedAt: sql.NullTime{ + Time: dbtime.Now(), + Valid: true, + }, + }) + CreateProvisionerJobResources(t, db, job.ID, seed.Transition, resources...) + return build +} + +// CreateProvisionerJobResources inserts a series of resources into a provisioner job. +func CreateProvisionerJobResources(t testing.TB, db database.Store, job uuid.UUID, transition database.WorkspaceTransition, resources ...*sdkproto.Resource) { + t.Helper() + if transition == "" { + // Default to start! + transition = database.WorkspaceTransitionStart + } + for _, resource := range resources { + //nolint:gocritic // This is only used by tests. + err := provisionerdserver.InsertWorkspaceResource(dbauthz.AsSystemRestricted(context.Background()), db, job, transition, resource, &telemetry.Snapshot{}) + require.NoError(t, err) + } +} diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index b1146b4f49d81..970709fec9087 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -66,6 +66,12 @@ func AuditLog(t testing.TB, db database.Store, seed database.AuditLog) database. func Template(t testing.TB, db database.Store, seed database.Template) database.Template { id := takeFirst(seed.ID, uuid.New()) + if seed.GroupACL == nil { + // By default, all users in the organization can read the template. + seed.GroupACL = database.TemplateACL{ + seed.OrganizationID.String(): []rbac.Action{rbac.ActionRead}, + } + } err := db.InsertTemplate(genCtx, database.InsertTemplateParams{ ID: id, CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()), @@ -84,7 +90,7 @@ func Template(t testing.TB, db database.Store, seed database.Template) database. }) require.NoError(t, err, "insert template") - template, err := db.GetTemplateByID(context.Background(), id) + template, err := db.GetTemplateByID(genCtx, id) require.NoError(t, err, "get template") return template } diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index 10028f91fa3f3..b7fcc7849f5fc 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -23,6 +23,7 @@ import ( "github.com/coder/coder/v2/agent/agenttest" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" + "github.com/coder/coder/v2/coderd/database/dbfakedata" "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -36,44 +37,27 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() t.Run("Connect", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() tmpDir := t.TempDir() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Directory: tmpDir, - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, - }, - }, - }}, - }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - - anotherClient, _ := coderdtest.CreateAnotherUser(t, client, user.OrganizationID) - workspace := coderdtest.CreateWorkspace(t, anotherClient, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, anotherClient, workspace.LatestBuild.ID) + anotherClient, anotherUser := coderdtest.CreateAnotherUser(t, client, user.OrganizationID) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - workspace, err := anotherClient.Workspace(ctx, workspace.ID) + ws := dbfakedata.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: anotherUser.ID, + }) + dbfakedata.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "aws_instance", + Agents: []*proto.Agent{{ + Id: uuid.NewString(), + Name: "hey", + Directory: tmpDir, + }}, + }) + workspace, err := anotherClient.Workspace(ctx, ws.ID) require.NoError(t, err) require.Equal(t, tmpDir, workspace.LatestBuild.Resources[0].Agents[0].Directory) _, err = anotherClient.WorkspaceAgent(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID) From b622bdd123a5043e50453be4526f7019873f62f9 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 30 Oct 2023 17:46:03 +0000 Subject: [PATCH 2/9] Rename dbfakedata to dbfake --- cli/agent_test.go | 10 +++++----- .../{dbfakedata/dbfakedata.go => dbfake/dbfake.go} | 2 +- coderd/workspaceagents_test.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) rename coderd/database/{dbfakedata/dbfakedata.go => dbfake/dbfake.go} (99%) diff --git a/cli/agent_test.go b/cli/agent_test.go index 61cbc0a2ed785..542ffae2728cb 100644 --- a/cli/agent_test.go +++ b/cli/agent_test.go @@ -17,7 +17,7 @@ import ( "github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" - "github.com/coder/coder/v2/coderd/database/dbfakedata" + "github.com/coder/coder/v2/coderd/database/dbfake" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk/proto" @@ -74,11 +74,11 @@ func TestWorkspaceAgent(t *testing.T) { AzureCertificates: certificates, }) user := coderdtest.CreateFirstUser(t, client) - ws := dbfakedata.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfakedata.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "somename", Type: "someinstance", Agents: []*proto.Agent{{ @@ -116,11 +116,11 @@ func TestWorkspaceAgent(t *testing.T) { AWSCertificates: certificates, }) user := coderdtest.CreateFirstUser(t, client) - ws := dbfakedata.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfakedata.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "somename", Type: "someinstance", Agents: []*proto.Agent{{ diff --git a/coderd/database/dbfakedata/dbfakedata.go b/coderd/database/dbfake/dbfake.go similarity index 99% rename from coderd/database/dbfakedata/dbfakedata.go rename to coderd/database/dbfake/dbfake.go index bc28f1e4053e2..3b5f0e30a3063 100644 --- a/coderd/database/dbfakedata/dbfakedata.go +++ b/coderd/database/dbfake/dbfake.go @@ -1,4 +1,4 @@ -package dbfakedata +package dbfake import ( "context" diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index b7fcc7849f5fc..bf501fc5b4f30 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -23,7 +23,7 @@ import ( "github.com/coder/coder/v2/agent/agenttest" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" - "github.com/coder/coder/v2/coderd/database/dbfakedata" + "github.com/coder/coder/v2/coderd/database/dbfake" "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -45,11 +45,11 @@ func TestWorkspaceAgent(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - ws := dbfakedata.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: anotherUser.ID, }) - dbfakedata.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "aws_instance", Agents: []*proto.Agent{{ Id: uuid.NewString(), From c4d9108b42f01a897a68110e438db0ff13ea05be Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 30 Oct 2023 19:04:34 +0000 Subject: [PATCH 3/9] Migrate workspaceagents_test.go to use the new dbfake --- coderd/database/dbfake/dbfake.go | 41 +++ coderd/workspaceagents_test.go | 589 ++++++++++--------------------- 2 files changed, 227 insertions(+), 403 deletions(-) diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index 3b5f0e30a3063..564508a0e8478 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -15,6 +15,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/provisionerdserver" "github.com/coder/coder/v2/coderd/telemetry" + "github.com/coder/coder/v2/provisionersdk/proto" sdkproto "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -30,10 +31,31 @@ func CreateWorkspace(t testing.TB, db database.Store, seed database.Workspace) d CreatedBy: seed.OwnerID, }) seed.TemplateID = template.ID + seed.OwnerID = template.CreatedBy + seed.OrganizationID = template.OrganizationID } return dbgen.Workspace(t, db, seed) } +// CreateWorkspaceWithAgent is a helper that generates a workspace with a single resource +// that has an agent attached to it. The agent token is returned. +func CreateWorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace) (database.Workspace, string) { + t.Helper() + authToken := uuid.NewString() + ws := CreateWorkspace(t, db, seed) + CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "example", + Type: "aws_instance", + Agents: []*proto.Agent{{ + Id: uuid.NewString(), + Auth: &proto.Agent_Token{ + Token: authToken, + }, + }}, + }) + return ws, authToken +} + // CreateWorkspaceBuild inserts a build and a successful job into the database. func CreateWorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed database.WorkspaceBuild, resources ...*sdkproto.Resource) database.WorkspaceBuild { t.Helper() @@ -43,9 +65,28 @@ func CreateWorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace // This intentionally fulfills the minimum requirements of the schema. // Tests can provide a custom version ID if necessary. if seed.TemplateVersionID == uuid.Nil { + jobID := uuid.New() templateVersion := dbgen.TemplateVersion(t, db, database.TemplateVersion{ + JobID: jobID, OrganizationID: ws.OrganizationID, CreatedBy: ws.OwnerID, + TemplateID: uuid.NullUUID{ + UUID: ws.TemplateID, + Valid: true, + }, + }) + payload, _ := json.Marshal(provisionerdserver.TemplateVersionImportJob{ + TemplateVersionID: templateVersion.ID, + }) + dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ + ID: jobID, + OrganizationID: ws.OrganizationID, + Input: payload, + Type: database.ProvisionerJobTypeTemplateVersionImport, + CompletedAt: sql.NullTime{ + Time: dbtime.Now(), + Valid: true, + }, }) seed.TemplateVersionID = templateVersion.ID } diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index bf501fc5b4f30..031073b453f23 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -42,9 +42,6 @@ func TestWorkspaceAgent(t *testing.T) { tmpDir := t.TempDir() anotherClient, anotherUser := coderdtest.CreateAnotherUser(t, client, user.OrganizationID) - ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) - defer cancel() - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: anotherUser.ID, @@ -53,10 +50,11 @@ func TestWorkspaceAgent(t *testing.T) { Name: "aws_instance", Agents: []*proto.Agent{{ Id: uuid.NewString(), - Name: "hey", Directory: tmpDir, }}, }) + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) + defer cancel() workspace, err := anotherClient.Workspace(ctx, ws.ID) require.NoError(t, err) require.Equal(t, tmpDir, workspace.LatestBuild.Resources[0].Agents[0].Directory) @@ -66,42 +64,25 @@ func TestWorkspaceAgent(t *testing.T) { }) t.Run("HasFallbackTroubleshootingURL", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() tmpDir := t.TempDir() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Directory: tmpDir, - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, - }, - }, + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, + }) + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "aws_instance", + Agents: []*proto.Agent{{ + Id: uuid.NewString(), + Directory: tmpDir, }}, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium) defer cancel() - workspace, err := client.Workspace(ctx, workspace.ID) + workspace, err := client.Workspace(ctx, ws.ID) require.NoError(t, err) require.NotEmpty(t, workspace.LatestBuild.Resources[0].Agents[0].TroubleshootingURL) t.Log(workspace.LatestBuild.Resources[0].Agents[0].TroubleshootingURL) @@ -110,50 +91,39 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() // timeouts can cause error logs to be dropped on shutdown logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug) - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - Logger: &logger, + client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ + Logger: &logger, }) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() tmpDir := t.TempDir() wantTroubleshootingURL := "https://example.com/troubleshoot" - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Directory: tmpDir, - Auth: &proto.Agent_Token{ - Token: authToken, - }, - ConnectionTimeoutSeconds: 1, - TroubleshootingUrl: wantTroubleshootingURL, - }}, - }}, - }, + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + OwnerID: user.UserID, + OrganizationID: user.OrganizationID, + }) + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "example", + Type: "aws_instance", + Agents: []*proto.Agent{{ + Id: uuid.NewString(), + Directory: tmpDir, + Auth: &proto.Agent_Token{ + Token: uuid.NewString(), }, + ConnectionTimeoutSeconds: 1, + TroubleshootingUrl: wantTroubleshootingURL, }}, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium) defer cancel() var err error + var workspace codersdk.Workspace testutil.Eventually(ctx, t, func(ctx context.Context) (done bool) { - workspace, err = client.Workspace(ctx, workspace.ID) + workspace, err = client.Workspace(ctx, ws.ID) if !assert.NoError(t, err) { return false } @@ -167,10 +137,12 @@ func TestWorkspaceAgent(t *testing.T) { t.Run("DisplayApps", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, + }) authToken := uuid.NewString() tmpDir := t.TempDir() apps := &proto.DisplayApps{ @@ -180,44 +152,25 @@ func TestWorkspaceAgent(t *testing.T) { PortForwardingHelper: true, SshHelper: true, } - - echoResp := &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{ - { - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{ - { - Id: uuid.NewString(), - Directory: tmpDir, - Auth: &proto.Agent_Token{ - Token: authToken, - }, - DisplayApps: apps, - }, - }, - }, - }, + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "example", + Type: "aws_instance", + Agents: []*proto.Agent{ + { + Id: uuid.NewString(), + Directory: tmpDir, + Auth: &proto.Agent_Token{ + Token: authToken, }, + DisplayApps: apps, }, - }}, - } - - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, echoResp) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) + }, + }) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() - workspace, err := client.Workspace(ctx, workspace.ID) + workspace, err := client.Workspace(ctx, ws.ID) require.NoError(t, err) agent, err := client.WorkspaceAgent(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID) require.NoError(t, err) @@ -237,21 +190,29 @@ func TestWorkspaceAgent(t *testing.T) { apps.SshHelper = false apps.WebTerminal = false - version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, echoResp, - func(req *codersdk.CreateTemplateVersionRequest) { - req.TemplateID = template.ID - }) - - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - err = client.UpdateActiveTemplateVersion(ctx, template.ID, codersdk.UpdateActiveTemplateVersion{ - ID: version.ID, + // Creating another workspace is easier + ws = dbfake.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "example", + Type: "aws_instance", + Agents: []*proto.Agent{ + { + Id: uuid.NewString(), + Directory: tmpDir, + Auth: &proto.Agent_Token{ + Token: authToken, + }, + DisplayApps: apps, + }, + }, + }) + workspace, err = client.Workspace(ctx, ws.ID) require.NoError(t, err) - // Creating another workspace is just easier. - workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - build := coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - require.NoError(t, err) - agent, err = client.WorkspaceAgent(ctx, build.Resources[0].Agents[0].ID) + + agent, err = client.WorkspaceAgent(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID) require.NoError(t, err) require.Len(t, agent.DisplayApps, 0) }) @@ -262,35 +223,12 @@ func TestWorkspaceAgentLogs(t *testing.T) { t.Run("Success", func(t *testing.T) { t.Parallel() ctx := testutil.Context(t, testutil.WaitMedium) - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, - }, - }, - }}, + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - build := coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(authToken) @@ -307,8 +245,9 @@ func TestWorkspaceAgentLogs(t *testing.T) { }, }) require.NoError(t, err) - - logs, closer, err := client.WorkspaceAgentLogsAfter(ctx, build.Resources[0].Agents[0].ID, 0, true) + workspace, err := client.Workspace(ctx, ws.ID) + require.NoError(t, err) + logs, closer, err := client.WorkspaceAgentLogsAfter(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID, 0, true) require.NoError(t, err) defer func() { _ = closer.Close() @@ -326,36 +265,12 @@ func TestWorkspaceAgentLogs(t *testing.T) { t.Run("Close logs on outdated build", func(t *testing.T) { t.Parallel() ctx := testutil.Context(t, testutil.WaitMedium) - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, - }, - }, - }}, + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - build := coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(authToken) err := agentClient.PatchLogs(ctx, agentsdk.PatchLogs{ @@ -367,8 +282,9 @@ func TestWorkspaceAgentLogs(t *testing.T) { }, }) require.NoError(t, err) - - logs, closer, err := client.WorkspaceAgentLogsAfter(ctx, build.Resources[0].Agents[0].ID, 0, true) + workspace, err := client.Workspace(ctx, ws.ID) + require.NoError(t, err) + logs, closer, err := client.WorkspaceAgentLogsAfter(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID, 0, true) require.NoError(t, err) defer func() { _ = closer.Close() @@ -391,37 +307,13 @@ func TestWorkspaceAgentLogs(t *testing.T) { t.Run("PublishesOnOverflow", func(t *testing.T) { t.Parallel() ctx := testutil.Context(t, testutil.WaitMedium) - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, - }, - }, - }}, + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - - updates, err := client.WatchWorkspace(ctx, workspace.ID) + updates, err := client.WatchWorkspace(ctx, ws.ID) require.NoError(t, err) agentClient := agentsdk.New(client.URL) @@ -458,23 +350,14 @@ func TestWorkspaceAgentListen(t *testing.T) { t.Run("Connect", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - _ = agenttest.New(t, client.URL, authToken) - resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() @@ -552,22 +435,16 @@ func TestWorkspaceAgentListen(t *testing.T) { func TestWorkspaceAgentTailnet(t *testing.T) { t.Parallel() - client, daemonCloser := coderdtest.NewWithProvisionerCloser(t, nil) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() _ = agenttest.New(t, client.URL, authToken) - resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) ctx, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() @@ -596,22 +473,14 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) { require.NoError(t, err) require.True(t, dv.DERP.Config.BlockDirect.Value()) - client, daemonCloser := coderdtest.NewWithProvisionerCloser(t, &coderdtest.Options{ + client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ DeploymentValues: dv, }) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - daemonCloser.Close() - ctx := testutil.Context(t, testutil.WaitLong) // Verify that the manifest has DisableDirectConnections set to true. @@ -622,7 +491,7 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) { require.True(t, manifest.DisableDirectConnections) _ = agenttest.New(t, client.URL, authToken) - resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) agentID := resources[0].Agents[0].ID // Verify that the connection data has no STUN ports and @@ -666,42 +535,17 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) { setup := func(t *testing.T, apps []*proto.App) (*codersdk.Client, uint16, uuid.UUID) { t.Helper() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) coderdPort, err := strconv.Atoi(client.URL.Port()) require.NoError(t, err) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - Apps: apps, - }}, - }}, - }, - }, - }}, + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - _ = agenttest.New(t, client.URL, authToken) - resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) return client, uint16(coderdPort), resources[0].Agents[0].ID } @@ -898,9 +742,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) { func TestWorkspaceAgentAppHealth(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) authToken := uuid.NewString() apps := []*proto.App{ @@ -923,30 +765,21 @@ func TestWorkspaceAgentAppHealth(t *testing.T) { }, }, } - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - Apps: apps, - }}, - }}, - }, + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, + }) + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "example", + Type: "aws_instance", + Agents: []*proto.Agent{{ + Id: uuid.NewString(), + Auth: &proto.Agent_Token{ + Token: authToken, }, + Apps: apps, }}, }) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() @@ -1005,20 +838,12 @@ func TestWorkspaceAgentReportStats(t *testing.T) { t.Run("OK", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(authToken) @@ -1038,12 +863,12 @@ func TestWorkspaceAgentReportStats(t *testing.T) { }) require.NoError(t, err) - newWorkspace, err := client.Workspace(context.Background(), workspace.ID) + newWorkspace, err := client.Workspace(context.Background(), ws.ID) require.NoError(t, err) assert.True(t, - newWorkspace.LastUsedAt.After(workspace.LastUsedAt), - "%s is not after %s", newWorkspace.LastUsedAt, workspace.LastUsedAt, + newWorkspace.LastUsedAt.After(ws.LastUsedAt), + "%s is not after %s", newWorkspace.LastUsedAt, ws.LastUsedAt, ) }) } @@ -1054,21 +879,14 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) { t.Run("Set", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - + workspace, err := client.Workspace(context.Background(), ws.ID) + require.NoError(t, err) for _, res := range workspace.LatestBuild.Resources { for _, a := range res.Agents { require.Equal(t, codersdk.WorkspaceAgentLifecycleCreated, a.LifecycleState) @@ -1126,59 +944,48 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) { func TestWorkspaceAgent_Metadata(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "example", - Type: "aws_instance", - Agents: []*proto.Agent{{ - Metadata: []*proto.Agent_Metadata{ - { - DisplayName: "First Meta", - Key: "foo1", - Script: "echo hi", - Interval: 10, - Timeout: 3, - }, - { - DisplayName: "Second Meta", - Key: "foo2", - Script: "echo howdy", - Interval: 10, - Timeout: 3, - }, - { - DisplayName: "TooLong", - Key: "foo3", - Script: "echo howdy", - Interval: 10, - Timeout: 3, - }, - }, - Id: uuid.NewString(), - Auth: &proto.Agent_Token{ - Token: authToken, - }, - }}, - }}, + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, + }) + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "example", + Type: "aws_instance", + Agents: []*proto.Agent{{ + Metadata: []*proto.Agent_Metadata{ + { + DisplayName: "First Meta", + Key: "foo1", + Script: "echo hi", + Interval: 10, + Timeout: 3, + }, + { + DisplayName: "Second Meta", + Key: "foo2", + Script: "echo howdy", + Interval: 10, + Timeout: 3, + }, + { + DisplayName: "TooLong", + Key: "foo3", + Script: "echo howdy", + Interval: 10, + Timeout: 3, }, }, + Id: uuid.NewString(), + Auth: &proto.Agent_Token{ + Token: authToken, + }, }}, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - + workspace, err := client.Workspace(context.Background(), ws.ID) + require.NoError(t, err) for _, res := range workspace.LatestBuild.Resources { for _, a := range res.Agents { require.Equal(t, codersdk.WorkspaceAgentLifecycleCreated, a.LifecycleState) @@ -1302,21 +1109,12 @@ func TestWorkspaceAgent_Startup(t *testing.T) { t.Run("OK", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(authToken) @@ -1342,7 +1140,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) { }) require.NoError(t, err) - workspace, err = client.Workspace(ctx, workspace.ID) + workspace, err := client.Workspace(ctx, ws.ID) require.NoError(t, err) wsagent, err := client.WorkspaceAgent(ctx, workspace.LatestBuild.Resources[0].Agents[0].ID) @@ -1356,20 +1154,12 @@ func TestWorkspaceAgent_Startup(t *testing.T) { t.Run("InvalidSemver", func(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - authToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + _, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(authToken) @@ -1399,8 +1189,7 @@ func TestWorkspaceAgent_UpdatedDERP(t *testing.T) { require.NoError(t, err) client, closer, api := coderdtest.NewWithAPI(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - DeploymentValues: dv, + DeploymentValues: dv, }) defer closer.Close() user := coderdtest.CreateFirstUser(t, client) @@ -1415,19 +1204,13 @@ func TestWorkspaceAgent_UpdatedDERP(t *testing.T) { api.DERPMapper.Store(&derpMapFn) // Start workspace a workspace agent. - agentToken := uuid.NewString() - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionPlan: echo.PlanComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(agentToken), + ws, agentToken := dbfake.CreateWorkspaceWithAgent(t, api.Database, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) agentCloser := agenttest.New(t, client.URL, agentToken) - resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) agentID := resources[0].Agents[0].ID // Connect from a client. From 003f752bfb3373f0a5a944373dbe661a738d0366 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 30 Oct 2023 19:09:00 +0000 Subject: [PATCH 4/9] Migrate agent_test.go to use the new fakes --- cli/agent_test.go | 78 +++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/cli/agent_test.go b/cli/agent_test.go index 542ffae2728cb..6522a9b7ef929 100644 --- a/cli/agent_test.go +++ b/cli/agent_test.go @@ -19,7 +19,6 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbfake" "github.com/coder/coder/v2/codersdk" - "github.com/coder/coder/v2/provisioner/echo" "github.com/coder/coder/v2/provisionersdk/proto" "github.com/coder/coder/v2/pty/ptytest" ) @@ -30,20 +29,12 @@ func TestWorkspaceAgent(t *testing.T) { t.Run("LogDirectory", func(t *testing.T) { t.Parallel() - authToken := uuid.NewString() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - logDir := t.TempDir() inv, _ := clitest.New(t, "agent", @@ -59,7 +50,7 @@ func TestWorkspaceAgent(t *testing.T) { ctx := inv.Context() pty.ExpectMatchContext(ctx, "agent is starting now") - coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) info, err := os.Stat(filepath.Join(logDir, "coder-agent.log")) require.NoError(t, err) @@ -154,35 +145,24 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() instanceID := "instanceidentifier" validator, metadataClient := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false) - client := coderdtest.New(t, &coderdtest.Options{ - GoogleTokenValidator: validator, - IncludeProvisionerDaemon: true, + client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ + GoogleTokenValidator: validator, }) owner := coderdtest.CreateFirstUser(t, client) - member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) - version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: []*proto.Response{{ - Type: &proto.Response_Apply{ - Apply: &proto.ApplyComplete{ - Resources: []*proto.Resource{{ - Name: "somename", - Type: "someinstance", - Agents: []*proto.Agent{{ - Auth: &proto.Agent_InstanceId{ - InstanceId: instanceID, - }, - }}, - }}, - }, + member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) + ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + OrganizationID: owner.OrganizationID, + OwnerID: memberUser.ID, + }) + dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Name: "somename", + Type: "someinstance", + Agents: []*proto.Agent{{ + Auth: &proto.Agent_InstanceId{ + InstanceId: instanceID, }, }}, }) - template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, member, owner.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) - inv, cfg := clitest.New(t, "agent", "--auth", "google-instance-identity", "--agent-url", client.URL.String()) ptytest.New(t).Attach(inv) clitest.SetupConfig(t, member, cfg) @@ -194,9 +174,8 @@ func TestWorkspaceAgent(t *testing.T) { ) ctx := inv.Context() - - coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) - workspace, err := client.Workspace(ctx, workspace.ID) + coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) + workspace, err := client.Workspace(ctx, ws.ID) require.NoError(t, err) resources := workspace.LatestBuild.Resources if assert.NotEmpty(t, resources) && assert.NotEmpty(t, resources[0].Agents) { @@ -226,19 +205,12 @@ func TestWorkspaceAgent(t *testing.T) { t.Run("PostStartup", func(t *testing.T) { t.Parallel() - authToken := uuid.NewString() - client := coderdtest.New(t, &coderdtest.Options{ - IncludeProvisionerDaemon: true, - }) + client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ - Parse: echo.ParseComplete, - ProvisionApply: echo.ProvisionApplyWithAgent(authToken), + ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + OrganizationID: user.OrganizationID, + OwnerID: user.UserID, }) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) - workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) - coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) logDir := t.TempDir() inv, _ := clitest.New(t, @@ -256,7 +228,7 @@ func TestWorkspaceAgent(t *testing.T) { clitest.Start(t, inv) pty.ExpectMatchContext(inv.Context(), "agent is starting now") - resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID) + resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) require.Len(t, resources, 1) require.Len(t, resources[0].Agents, 1) require.Len(t, resources[0].Agents[0].Subsystems, 2) From 7e0fefdd7f928aea0f5829e1a882e466056fb6a3 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Mon, 30 Oct 2023 19:44:22 +0000 Subject: [PATCH 5/9] Fix comments --- cli/agent_test.go | 16 +++++----- coderd/database/dbfake/dbfake.go | 22 +++++++------- coderd/workspaceagents_test.go | 52 ++++++++++++++++---------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/cli/agent_test.go b/cli/agent_test.go index 6522a9b7ef929..a1f519cf4dada 100644 --- a/cli/agent_test.go +++ b/cli/agent_test.go @@ -31,7 +31,7 @@ func TestWorkspaceAgent(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -65,11 +65,11 @@ func TestWorkspaceAgent(t *testing.T) { AzureCertificates: certificates, }) user := coderdtest.CreateFirstUser(t, client) - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "somename", Type: "someinstance", Agents: []*proto.Agent{{ @@ -107,11 +107,11 @@ func TestWorkspaceAgent(t *testing.T) { AWSCertificates: certificates, }) user := coderdtest.CreateFirstUser(t, client) - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "somename", Type: "someinstance", Agents: []*proto.Agent{{ @@ -150,11 +150,11 @@ func TestWorkspaceAgent(t *testing.T) { }) owner := coderdtest.CreateFirstUser(t, client) member, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: owner.OrganizationID, OwnerID: memberUser.ID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "somename", Type: "someinstance", Agents: []*proto.Agent{{ @@ -207,7 +207,7 @@ func TestWorkspaceAgent(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index 564508a0e8478..d50399a4078ed 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -19,8 +19,8 @@ import ( sdkproto "github.com/coder/coder/v2/provisionersdk/proto" ) -// CreateWorkspace inserts a workspace into the database. -func CreateWorkspace(t testing.TB, db database.Store, seed database.Workspace) database.Workspace { +// Workspace inserts a workspace into the database. +func Workspace(t testing.TB, db database.Store, seed database.Workspace) database.Workspace { t.Helper() // This intentionally fulfills the minimum requirements of the schema. @@ -37,13 +37,13 @@ func CreateWorkspace(t testing.TB, db database.Store, seed database.Workspace) d return dbgen.Workspace(t, db, seed) } -// CreateWorkspaceWithAgent is a helper that generates a workspace with a single resource +// WorkspaceWithAgent is a helper that generates a workspace with a single resource // that has an agent attached to it. The agent token is returned. -func CreateWorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace) (database.Workspace, string) { +func WorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace) (database.Workspace, string) { t.Helper() authToken := uuid.NewString() - ws := CreateWorkspace(t, db, seed) - CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + ws := Workspace(t, db, seed) + WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "example", Type: "aws_instance", Agents: []*proto.Agent{{ @@ -56,8 +56,8 @@ func CreateWorkspaceWithAgent(t testing.TB, db database.Store, seed database.Wor return ws, authToken } -// CreateWorkspaceBuild inserts a build and a successful job into the database. -func CreateWorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed database.WorkspaceBuild, resources ...*sdkproto.Resource) database.WorkspaceBuild { +// WorkspaceBuild inserts a build and a successful job into the database. +func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed database.WorkspaceBuild, resources ...*sdkproto.Resource) database.WorkspaceBuild { t.Helper() jobID := uuid.New() seed.JobID = jobID @@ -105,12 +105,12 @@ func CreateWorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace Valid: true, }, }) - CreateProvisionerJobResources(t, db, job.ID, seed.Transition, resources...) + ProvisionerJobResources(t, db, job.ID, seed.Transition, resources...) return build } -// CreateProvisionerJobResources inserts a series of resources into a provisioner job. -func CreateProvisionerJobResources(t testing.TB, db database.Store, job uuid.UUID, transition database.WorkspaceTransition, resources ...*sdkproto.Resource) { +// ProvisionerJobResources inserts a series of resources into a provisioner job. +func ProvisionerJobResources(t testing.TB, db database.Store, job uuid.UUID, transition database.WorkspaceTransition, resources ...*sdkproto.Resource) { t.Helper() if transition == "" { // Default to start! diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index 031073b453f23..146baec14d1d6 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -42,11 +42,11 @@ func TestWorkspaceAgent(t *testing.T) { tmpDir := t.TempDir() anotherClient, anotherUser := coderdtest.CreateAnotherUser(t, client, user.OrganizationID) - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: anotherUser.ID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "aws_instance", Agents: []*proto.Agent{{ Id: uuid.NewString(), @@ -67,11 +67,11 @@ func TestWorkspaceAgent(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) tmpDir := t.TempDir() - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "aws_instance", Agents: []*proto.Agent{{ Id: uuid.NewString(), @@ -99,11 +99,11 @@ func TestWorkspaceAgent(t *testing.T) { wantTroubleshootingURL := "https://example.com/troubleshoot" - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OwnerID: user.UserID, OrganizationID: user.OrganizationID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "example", Type: "aws_instance", Agents: []*proto.Agent{{ @@ -139,7 +139,7 @@ func TestWorkspaceAgent(t *testing.T) { t.Parallel() client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -152,7 +152,7 @@ func TestWorkspaceAgent(t *testing.T) { PortForwardingHelper: true, SshHelper: true, } - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "example", Type: "aws_instance", Agents: []*proto.Agent{ @@ -191,11 +191,11 @@ func TestWorkspaceAgent(t *testing.T) { apps.WebTerminal = false // Creating another workspace is easier - ws = dbfake.CreateWorkspace(t, db, database.Workspace{ + ws = dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "example", Type: "aws_instance", Agents: []*proto.Agent{ @@ -225,7 +225,7 @@ func TestWorkspaceAgentLogs(t *testing.T) { ctx := testutil.Context(t, testutil.WaitMedium) client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -267,7 +267,7 @@ func TestWorkspaceAgentLogs(t *testing.T) { ctx := testutil.Context(t, testutil.WaitMedium) client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -309,7 +309,7 @@ func TestWorkspaceAgentLogs(t *testing.T) { ctx := testutil.Context(t, testutil.WaitMedium) client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -352,7 +352,7 @@ func TestWorkspaceAgentListen(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -438,7 +438,7 @@ func TestWorkspaceAgentTailnet(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -477,7 +477,7 @@ func TestWorkspaceAgentTailnetDirectDisabled(t *testing.T) { DeploymentValues: dv, }) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -540,7 +540,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) { require.NoError(t, err) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -765,11 +765,11 @@ func TestWorkspaceAgentAppHealth(t *testing.T) { }, }, } - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "example", Type: "aws_instance", Agents: []*proto.Agent{{ @@ -840,7 +840,7 @@ func TestWorkspaceAgentReportStats(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -881,7 +881,7 @@ func TestWorkspaceAgent_LifecycleState(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -947,11 +947,11 @@ func TestWorkspaceAgent_Metadata(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) authToken := uuid.NewString() - ws := dbfake.CreateWorkspace(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) - dbfake.CreateWorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ Name: "example", Type: "aws_instance", Agents: []*proto.Agent{{ @@ -1111,7 +1111,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -1156,7 +1156,7 @@ func TestWorkspaceAgent_Startup(t *testing.T) { client, db := coderdtest.NewWithDatabase(t, nil) user := coderdtest.CreateFirstUser(t, client) - _, authToken := dbfake.CreateWorkspaceWithAgent(t, db, database.Workspace{ + _, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) @@ -1204,7 +1204,7 @@ func TestWorkspaceAgent_UpdatedDERP(t *testing.T) { api.DERPMapper.Store(&derpMapFn) // Start workspace a workspace agent. - ws, agentToken := dbfake.CreateWorkspaceWithAgent(t, api.Database, database.Workspace{ + ws, agentToken := dbfake.WorkspaceWithAgent(t, api.Database, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) From 0422e417ebacb189e141c0e8f141702f6eb6eebd Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Wed, 1 Nov 2023 17:59:24 +0000 Subject: [PATCH 6/9] Try to fix tests --- coderd/database/dbfake/dbfake.go | 38 +++++++++++++++++--------------- coderd/database/dbgen/dbgen.go | 3 --- coderd/workspaceagents_test.go | 6 ----- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index d50399a4078ed..0d8d705edc06d 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -15,7 +15,6 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/provisionerdserver" "github.com/coder/coder/v2/coderd/telemetry" - "github.com/coder/coder/v2/provisionersdk/proto" sdkproto "github.com/coder/coder/v2/provisionersdk/proto" ) @@ -43,12 +42,12 @@ func WorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace t.Helper() authToken := uuid.NewString() ws := Workspace(t, db, seed) - WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &sdkproto.Resource{ Name: "example", Type: "aws_instance", - Agents: []*proto.Agent{{ + Agents: []*sdkproto.Agent{{ Id: uuid.NewString(), - Auth: &proto.Agent_Token{ + Auth: &sdkproto.Agent_Token{ Token: authToken, }, }}, @@ -60,8 +59,25 @@ func WorkspaceWithAgent(t testing.TB, db database.Store, seed database.Workspace func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed database.WorkspaceBuild, resources ...*sdkproto.Resource) database.WorkspaceBuild { t.Helper() jobID := uuid.New() + seed.ID = uuid.New() seed.JobID = jobID seed.WorkspaceID = ws.ID + + // Create a provisioner job for the build! + payload, err := json.Marshal(provisionerdserver.WorkspaceProvisionJob{ + WorkspaceBuildID: seed.ID, + }) + require.NoError(t, err) + job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ + ID: jobID, + Input: payload, + OrganizationID: ws.OrganizationID, + CompletedAt: sql.NullTime{ + Time: dbtime.Now(), + Valid: true, + }, + }) + // This intentionally fulfills the minimum requirements of the schema. // Tests can provide a custom version ID if necessary. if seed.TemplateVersionID == uuid.Nil { @@ -91,20 +107,6 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed seed.TemplateVersionID = templateVersion.ID } build := dbgen.WorkspaceBuild(t, db, seed) - - payload, err := json.Marshal(provisionerdserver.WorkspaceProvisionJob{ - WorkspaceBuildID: build.ID, - }) - require.NoError(t, err) - job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ - ID: jobID, - Input: payload, - OrganizationID: ws.OrganizationID, - CompletedAt: sql.NullTime{ - Time: dbtime.Now(), - Valid: true, - }, - }) ProvisionerJobResources(t, db, job.ID, seed.Transition, resources...) return build } diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 970709fec9087..dcd2a0ac5645e 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -395,9 +395,6 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data require.NoError(t, err) } - job, err = db.GetProvisionerJobByID(genCtx, jobID) - require.NoError(t, err) - return job } diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index 146baec14d1d6..5912e967b2ded 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -153,11 +153,8 @@ func TestWorkspaceAgent(t *testing.T) { SshHelper: true, } dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ - Name: "example", - Type: "aws_instance", Agents: []*proto.Agent{ { - Id: uuid.NewString(), Directory: tmpDir, Auth: &proto.Agent_Token{ Token: authToken, @@ -196,11 +193,8 @@ func TestWorkspaceAgent(t *testing.T) { OwnerID: user.UserID, }) dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ - Name: "example", - Type: "aws_instance", Agents: []*proto.Agent{ { - Id: uuid.NewString(), Directory: tmpDir, Auth: &proto.Agent_Token{ Token: authToken, From e74024dcf178b0ea5a83bd5005a832b778b2203b Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Wed, 1 Nov 2023 18:45:14 +0000 Subject: [PATCH 7/9] Fix tests --- coderd/database/dbfake/dbfake.go | 20 ++++++++++++++------ coderd/database/dbgen/dbgen.go | 3 +++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index 0d8d705edc06d..d7ed1731c7f3d 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/google/uuid" + "github.com/sqlc-dev/pqtype" "github.com/stretchr/testify/require" "github.com/coder/coder/v2/coderd/database" @@ -68,15 +69,22 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed WorkspaceBuildID: seed.ID, }) require.NoError(t, err) - job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ + //nolint:gocritic // This is only used by tests. + job, err := db.InsertProvisionerJob(dbauthz.AsSystemRestricted(context.Background()), database.InsertProvisionerJobParams{ ID: jobID, - Input: payload, + CreatedAt: dbtime.Now(), + UpdatedAt: dbtime.Now(), OrganizationID: ws.OrganizationID, - CompletedAt: sql.NullTime{ - Time: dbtime.Now(), - Valid: true, - }, + InitiatorID: ws.OwnerID, + Provisioner: database.ProvisionerTypeEcho, + StorageMethod: database.ProvisionerStorageMethodFile, + FileID: uuid.New(), + Type: database.ProvisionerJobTypeWorkspaceBuild, + Input: payload, + Tags: nil, + TraceMetadata: pqtype.NullRawMessage{}, }) + require.NoError(t, err, "insert job") // This intentionally fulfills the minimum requirements of the schema. // Tests can provide a custom version ID if necessary. diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index dcd2a0ac5645e..970709fec9087 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -395,6 +395,9 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data require.NoError(t, err) } + job, err = db.GetProvisionerJobByID(genCtx, jobID) + require.NoError(t, err) + return job } From 38495775505075d5e0150bdb3dd31b5209b3f1e6 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Thu, 2 Nov 2023 14:57:51 +0000 Subject: [PATCH 8/9] Actually fix tests --- coderd/database/dbfake/dbfake.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index d7ed1731c7f3d..442361de36834 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -70,7 +70,8 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed }) require.NoError(t, err) //nolint:gocritic // This is only used by tests. - job, err := db.InsertProvisionerJob(dbauthz.AsSystemRestricted(context.Background()), database.InsertProvisionerJobParams{ + ctx := dbauthz.AsSystemRestricted(context.Background()) + job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{ ID: jobID, CreatedAt: dbtime.Now(), UpdatedAt: dbtime.Now(), @@ -85,6 +86,17 @@ func WorkspaceBuild(t testing.TB, db database.Store, ws database.Workspace, seed TraceMetadata: pqtype.NullRawMessage{}, }) require.NoError(t, err, "insert job") + err = db.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{ + ID: job.ID, + UpdatedAt: dbtime.Now(), + Error: sql.NullString{}, + ErrorCode: sql.NullString{}, + CompletedAt: sql.NullTime{ + Time: dbtime.Now(), + Valid: true, + }, + }) + require.NoError(t, err, "complete job") // This intentionally fulfills the minimum requirements of the schema. // Tests can provide a custom version ID if necessary. From cff7aca00bd24f6996034d3b359f1b7e0a20f099 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Thu, 2 Nov 2023 16:43:45 +0000 Subject: [PATCH 9/9] Fix listening ports --- coderd/workspaceagents_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index 5912e967b2ded..b420f4a267284 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -534,10 +534,19 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) { require.NoError(t, err) user := coderdtest.CreateFirstUser(t, client) - ws, authToken := dbfake.WorkspaceWithAgent(t, db, database.Workspace{ + ws := dbfake.Workspace(t, db, database.Workspace{ OrganizationID: user.OrganizationID, OwnerID: user.UserID, }) + authToken := uuid.NewString() + dbfake.WorkspaceBuild(t, db, ws, database.WorkspaceBuild{}, &proto.Resource{ + Agents: []*proto.Agent{{ + Apps: apps, + Auth: &proto.Agent_Token{ + Token: authToken, + }, + }}, + }) _ = agenttest.New(t, client.URL, authToken) resources := coderdtest.AwaitWorkspaceAgents(t, client, ws.ID) return client, uint16(coderdPort), resources[0].Agents[0].ID