package coderd_test import ( "context" "net/http" "testing" "time" "github.com/stretchr/testify/require" "github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner/echo" "github.com/coder/coder/provisionersdk/proto" ) func TestWorkspaceBuild(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) coderdtest.NewProvisionerDaemon(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) _, err := client.WorkspaceBuild(context.Background(), workspace.LatestBuild.ID) require.NoError(t, err) } func TestWorkspaceBuilds(t *testing.T) { t.Parallel() t.Run("Single", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) coderdtest.NewProvisionerDaemon(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) _, err := client.WorkspaceBuilds(context.Background(), workspace.ID) require.NoError(t, err) }) } func TestPatchCancelWorkspaceBuild(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) coderdtest.NewProvisionerDaemon(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, Provision: []*proto.Provision_Response{{ Type: &proto.Provision_Response_Log{ Log: &proto.Log{}, }, }}, ProvisionDryRun: echo.ProvisionComplete, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) var build codersdk.WorkspaceBuild require.Eventually(t, func() bool { var err error build, err = client.WorkspaceBuild(context.Background(), workspace.LatestBuild.ID) require.NoError(t, err) return build.Job.Status == codersdk.ProvisionerJobRunning }, 5*time.Second, 25*time.Millisecond) err := client.CancelWorkspaceBuild(context.Background(), build.ID) require.NoError(t, err) require.Eventually(t, func() bool { var err error build, err = client.WorkspaceBuild(context.Background(), build.ID) require.NoError(t, err) return build.Job.Status == codersdk.ProvisionerJobCanceled }, 5*time.Second, 25*time.Millisecond) } func TestWorkspaceBuildResources(t *testing.T) { t.Parallel() t.Run("ListRunning", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) closeDaemon := coderdtest.NewProvisionerDaemon(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) closeDaemon.Close() template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) _, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID) var apiErr *codersdk.Error require.ErrorAs(t, err, &apiErr) require.Equal(t, http.StatusPreconditionFailed, apiErr.StatusCode()) }) t.Run("List", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) coderdtest.NewProvisionerDaemon(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, Provision: []*proto.Provision_Response{{ Type: &proto.Provision_Response_Complete{ Complete: &proto.Provision_Complete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", Agents: []*proto.Agent{{ Id: "something", Auth: &proto.Agent_Token{}, }}, }, { Name: "another", Type: "example", }}, }, }, }}, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID) require.NoError(t, err) require.NotNil(t, resources) require.Len(t, resources, 2) require.Equal(t, "some", resources[0].Name) require.Equal(t, "example", resources[0].Type) require.Len(t, resources[0].Agents, 1) }) } func TestWorkspaceBuildLogs(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) coderdtest.NewProvisionerDaemon(t, client) before := time.Now() version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, Provision: []*proto.Provision_Response{{ Type: &proto.Provision_Response_Log{ Log: &proto.Log{ Level: proto.LogLevel_INFO, Output: "example", }, }, }, { Type: &proto.Provision_Response_Complete{ Complete: &proto.Provision_Complete{ Resources: []*proto.Resource{{ Name: "some", Type: "example", Agents: []*proto.Agent{{ Id: "something", Auth: &proto.Agent_Token{}, }}, }, { Name: "another", Type: "example", }}, }, }, }}, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) ctx, cancelFunc := context.WithCancel(context.Background()) t.Cleanup(cancelFunc) logs, err := client.WorkspaceBuildLogsAfter(ctx, workspace.LatestBuild.ID, before) require.NoError(t, err) for { log, ok := <-logs if !ok { break } if log.Output == "example" { return } } require.Fail(t, "example message never happened") } func TestWorkspaceBuildState(t *testing.T) { t.Parallel() client := coderdtest.New(t, nil) user := coderdtest.CreateFirstUser(t, client) coderdtest.NewProvisionerDaemon(t, client) wantState := []byte("some kinda state") version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{ Parse: echo.ParseComplete, ProvisionDryRun: echo.ProvisionComplete, Provision: []*proto.Provision_Response{{ Type: &proto.Provision_Response_Complete{ Complete: &proto.Provision_Complete{ State: wantState, }, }, }}, }) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) gotState, err := client.WorkspaceBuildState(context.Background(), workspace.LatestBuild.ID) require.NoError(t, err) require.Equal(t, wantState, gotState) }