2022-01-25 19:52:58 +00:00
package coderd_test
import (
"context"
2022-06-14 16:21:30 +00:00
"fmt"
2022-02-06 00:24:51 +00:00
"net/http"
2022-06-14 13:46:33 +00:00
"strings"
2022-01-25 19:52:58 +00:00
"testing"
2022-04-07 09:03:35 +00:00
"time"
2022-01-25 19:52:58 +00:00
"github.com/google/uuid"
"github.com/stretchr/testify/require"
2022-05-11 22:03:02 +00:00
"github.com/coder/coder/coderd/autobuild/schedule"
2022-01-25 19:52:58 +00:00
"github.com/coder/coder/coderd/coderdtest"
2022-06-14 13:46:33 +00:00
"github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/coderd/util/ptr"
2022-01-25 19:52:58 +00:00
"github.com/coder/coder/codersdk"
2022-06-14 13:46:33 +00:00
"github.com/coder/coder/cryptorand"
2022-03-07 17:40:54 +00:00
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto"
2022-08-09 17:17:00 +00:00
"github.com/coder/coder/testutil"
2022-01-25 19:52:58 +00:00
)
2022-05-19 14:29:10 +00:00
func TestWorkspace ( t * testing . T ) {
t . Parallel ( )
t . Run ( "OK" , func ( t * testing . T ) {
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-05-19 14:29:10 +00:00
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
ws , err := client . Workspace ( ctx , workspace . ID )
2022-05-19 14:29:10 +00:00
require . NoError ( t , err )
2022-06-17 17:41:11 +00:00
require . Equal ( t , user . UserID , ws . LatestBuild . InitiatorID )
require . Equal ( t , codersdk . BuildReasonInitiator , ws . LatestBuild . Reason )
2022-05-19 14:29:10 +00:00
} )
t . Run ( "Deleted" , func ( t * testing . T ) {
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-05-19 14:29:10 +00:00
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
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 )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-06-06 17:23:02 +00:00
// Getting with deleted=true should still work.
2022-08-09 17:17:00 +00:00
_ , err := client . DeletedWorkspace ( ctx , workspace . ID )
2022-06-06 17:23:02 +00:00
require . NoError ( t , err )
2022-05-19 14:29:10 +00:00
// Delete the workspace
2022-08-09 17:17:00 +00:00
build , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-05-19 18:04:44 +00:00
Transition : codersdk . WorkspaceTransitionDelete ,
2022-05-19 14:29:10 +00:00
} )
require . NoError ( t , err , "delete the workspace" )
coderdtest . AwaitWorkspaceBuildJob ( t , client , build . ID )
// Getting with deleted=true should work.
2022-08-09 17:17:00 +00:00
workspaceNew , err := client . DeletedWorkspace ( ctx , workspace . ID )
2022-05-19 14:29:10 +00:00
require . NoError ( t , err )
require . Equal ( t , workspace . ID , workspaceNew . ID )
// Getting with deleted=false should not work.
2022-08-09 17:17:00 +00:00
_ , err = client . Workspace ( ctx , workspace . ID )
2022-05-19 14:29:10 +00:00
require . Error ( t , err )
require . ErrorContains ( t , err , "410" ) // gone
} )
}
2022-05-18 23:15:19 +00:00
func TestAdminViewAllWorkspaces ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-05-18 23:15:19 +00:00
coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . Workspace ( ctx , workspace . ID )
2022-03-07 17:40:54 +00:00
require . NoError ( t , err )
2022-05-18 23:15:19 +00:00
2022-08-09 17:17:00 +00:00
otherOrg , err := client . CreateOrganization ( ctx , codersdk . CreateOrganizationRequest {
2022-05-18 23:15:19 +00:00
Name : "default-test" ,
} )
require . NoError ( t , err , "create other org" )
// This other user is not in the first user's org. Since other is an admin, they can
// still see the "first" user's workspace.
2022-08-15 19:40:19 +00:00
other := coderdtest . CreateAnotherUser ( t , client , otherOrg . ID , rbac . RoleOwner ( ) )
2022-08-09 17:17:00 +00:00
otherWorkspaces , err := other . Workspaces ( ctx , codersdk . WorkspaceFilter { } )
2022-05-18 23:15:19 +00:00
require . NoError ( t , err , "(other) fetch workspaces" )
2022-08-09 17:17:00 +00:00
firstWorkspaces , err := other . Workspaces ( ctx , codersdk . WorkspaceFilter { } )
2022-05-18 23:15:19 +00:00
require . NoError ( t , err , "(first) fetch workspaces" )
require . ElementsMatch ( t , otherWorkspaces , firstWorkspaces )
2022-02-06 00:24:51 +00:00
}
2022-01-25 19:52:58 +00:00
2022-05-16 19:36:27 +00:00
func TestPostWorkspacesByOrganization ( t * testing . T ) {
2022-03-22 19:17:50 +00:00
t . Parallel ( )
2022-05-16 19:36:27 +00:00
t . Run ( "InvalidTemplate" , func ( t * testing . T ) {
2022-03-22 19:17:50 +00:00
t . Parallel ( )
client := coderdtest . New ( t , nil )
user := coderdtest . CreateFirstUser ( t , client )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . CreateWorkspace ( ctx , user . OrganizationID , codersdk . CreateWorkspaceRequest {
2022-05-16 19:36:27 +00:00
TemplateID : uuid . New ( ) ,
Name : "workspace" ,
} )
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusBadRequest , apiErr . StatusCode ( ) )
} )
t . Run ( "NoTemplateAccess" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , nil )
first := coderdtest . CreateFirstUser ( t , client )
2022-08-15 19:40:19 +00:00
other := coderdtest . CreateAnotherUser ( t , client , first . OrganizationID , rbac . RoleMember ( ) , rbac . RoleOwner ( ) )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
org , err := other . CreateOrganization ( ctx , codersdk . CreateOrganizationRequest {
2022-05-16 19:36:27 +00:00
Name : "another" ,
} )
require . NoError ( t , err )
version := coderdtest . CreateTemplateVersion ( t , other , org . ID , nil )
template := coderdtest . CreateTemplate ( t , other , org . ID , version . ID )
2022-08-09 17:17:00 +00:00
_ , err = client . CreateWorkspace ( ctx , first . OrganizationID , codersdk . CreateWorkspaceRequest {
2022-05-16 19:36:27 +00:00
TemplateID : template . ID ,
Name : "workspace" ,
} )
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusUnauthorized , apiErr . StatusCode ( ) )
} )
t . Run ( "AlreadyExists" , func ( t * testing . T ) {
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-05-16 19:36:27 +00:00
user := coderdtest . CreateFirstUser ( 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 )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . CreateWorkspace ( ctx , user . OrganizationID , codersdk . CreateWorkspaceRequest {
2022-05-16 19:36:27 +00:00
TemplateID : template . ID ,
Name : workspace . Name ,
} )
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusConflict , apiErr . StatusCode ( ) )
} )
t . Run ( "Create" , func ( t * testing . T ) {
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-05-16 19:36:27 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-05-16 19:36:27 +00:00
_ = coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
} )
2022-05-30 19:19:17 +00:00
2022-06-07 12:37:45 +00:00
t . Run ( "TemplateCustomTTL" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
templateTTL := 24 * time . Hour . Milliseconds ( )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID , func ( ctr * codersdk . CreateTemplateRequest ) {
ctr . MaxTTLMillis = ptr . Ref ( templateTTL )
} )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID , func ( cwr * codersdk . CreateWorkspaceRequest ) {
cwr . TTLMillis = nil // ensure that no default TTL is set
} )
// TTL should be set by the template
require . Equal ( t , template . MaxTTLMillis , templateTTL )
require . Equal ( t , template . MaxTTLMillis , template . MaxTTLMillis , workspace . TTLMillis )
} )
2022-05-30 19:19:17 +00:00
t . Run ( "InvalidTTL" , func ( t * testing . T ) {
t . Parallel ( )
t . Run ( "BelowMin" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( 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 )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-05-30 19:19:17 +00:00
req := codersdk . CreateWorkspaceRequest {
2022-06-07 12:37:45 +00:00
TemplateID : template . ID ,
Name : "testing" ,
TTLMillis : ptr . Ref ( ( 59 * time . Second ) . Milliseconds ( ) ) ,
2022-05-30 19:19:17 +00:00
}
2022-08-09 17:17:00 +00:00
_ , err := client . CreateWorkspace ( ctx , template . OrganizationID , req )
2022-05-30 19:19:17 +00:00
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusBadRequest , apiErr . StatusCode ( ) )
2022-06-07 12:37:45 +00:00
require . Len ( t , apiErr . Validations , 1 )
require . Equal ( t , apiErr . Validations [ 0 ] . Field , "ttl_ms" )
2022-07-27 21:20:02 +00:00
require . Equal ( t , "time until shutdown must be at least one minute" , apiErr . Validations [ 0 ] . Detail )
2022-05-30 19:19:17 +00:00
} )
t . Run ( "AboveMax" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( 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 )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-05-30 19:19:17 +00:00
req := codersdk . CreateWorkspaceRequest {
2022-06-07 12:37:45 +00:00
TemplateID : template . ID ,
Name : "testing" ,
2022-07-27 21:20:02 +00:00
TTLMillis : ptr . Ref ( template . MaxTTLMillis + time . Minute . Milliseconds ( ) ) ,
2022-05-30 19:19:17 +00:00
}
2022-08-09 17:17:00 +00:00
_ , err := client . CreateWorkspace ( ctx , template . OrganizationID , req )
2022-05-30 19:19:17 +00:00
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusBadRequest , apiErr . StatusCode ( ) )
2022-06-07 12:37:45 +00:00
require . Len ( t , apiErr . Validations , 1 )
require . Equal ( t , apiErr . Validations [ 0 ] . Field , "ttl_ms" )
2022-07-27 21:20:02 +00:00
require . Equal ( t , "time until shutdown must be less than 7 days" , apiErr . Validations [ 0 ] . Detail )
2022-05-30 19:19:17 +00:00
} )
} )
2022-06-07 12:37:45 +00:00
t . Run ( "InvalidAutostart" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( 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 )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-06-07 12:37:45 +00:00
req := codersdk . CreateWorkspaceRequest {
TemplateID : template . ID ,
Name : "testing" ,
AutostartSchedule : ptr . Ref ( "CRON_TZ=US/Central * * * * *" ) ,
}
2022-08-09 17:17:00 +00:00
_ , err := client . CreateWorkspace ( ctx , template . OrganizationID , req )
2022-06-07 12:37:45 +00:00
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusBadRequest , apiErr . StatusCode ( ) )
require . Len ( t , apiErr . Validations , 1 )
require . Equal ( t , apiErr . Validations [ 0 ] . Field , "schedule" )
require . Equal ( t , apiErr . Validations [ 0 ] . Detail , "Minimum autostart interval 1m0s below template minimum 1h0m0s" )
} )
2022-05-16 19:36:27 +00:00
}
func TestWorkspaceByOwnerAndName ( t * testing . T ) {
t . Parallel ( )
t . Run ( "NotFound" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , nil )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . WorkspaceByOwnerAndName ( ctx , codersdk . Me , "something" , codersdk . WorkspaceOptions { } )
2022-05-16 19:36:27 +00:00
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
2022-06-03 19:36:08 +00:00
require . Equal ( t , http . StatusUnauthorized , apiErr . StatusCode ( ) )
2022-05-16 19:36:27 +00:00
} )
t . Run ( "Get" , func ( t * testing . T ) {
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-05-16 19:36:27 +00:00
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . WorkspaceByOwnerAndName ( ctx , codersdk . Me , workspace . Name , codersdk . WorkspaceOptions { } )
2022-03-22 19:17:50 +00:00
require . NoError ( t , err )
} )
2022-06-08 18:04:05 +00:00
t . Run ( "Deleted" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
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 )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-06-08 18:04:05 +00:00
// Given:
// We delete the workspace
2022-08-09 17:17:00 +00:00
build , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-06-08 18:04:05 +00:00
Transition : codersdk . WorkspaceTransitionDelete ,
} )
require . NoError ( t , err , "delete the workspace" )
coderdtest . AwaitWorkspaceBuildJob ( t , client , build . ID )
// Then:
// When we call without includes_deleted, we don't expect to get the workspace back
2022-08-09 17:17:00 +00:00
_ , err = client . WorkspaceByOwnerAndName ( ctx , workspace . OwnerName , workspace . Name , codersdk . WorkspaceOptions { } )
2022-06-14 15:14:05 +00:00
require . ErrorContains ( t , err , "404" )
2022-06-08 18:04:05 +00:00
// Then:
// When we call with includes_deleted, we should get the workspace back
2022-08-09 17:17:00 +00:00
workspaceNew , err := client . WorkspaceByOwnerAndName ( ctx , workspace . OwnerName , workspace . Name , codersdk . WorkspaceOptions { IncludeDeleted : true } )
2022-06-10 14:58:42 +00:00
require . NoError ( t , err )
require . Equal ( t , workspace . ID , workspaceNew . ID )
// Given:
// We recreate the workspace with the same name
2022-08-09 17:17:00 +00:00
workspace , err = client . CreateWorkspace ( ctx , user . OrganizationID , codersdk . CreateWorkspaceRequest {
2022-06-10 14:58:42 +00:00
TemplateID : workspace . TemplateID ,
Name : workspace . Name ,
AutostartSchedule : workspace . AutostartSchedule ,
TTLMillis : workspace . TTLMillis ,
} )
require . NoError ( t , err )
coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
// Then:
// We can fetch the most recent workspace
2022-08-09 17:17:00 +00:00
workspaceNew , err = client . WorkspaceByOwnerAndName ( ctx , workspace . OwnerName , workspace . Name , codersdk . WorkspaceOptions { } )
2022-06-10 14:58:42 +00:00
require . NoError ( t , err )
require . Equal ( t , workspace . ID , workspaceNew . ID )
// Given:
// We delete the workspace again
2022-08-09 17:17:00 +00:00
build , err = client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-06-10 14:58:42 +00:00
Transition : codersdk . WorkspaceTransitionDelete ,
} )
require . NoError ( t , err , "delete the workspace" )
coderdtest . AwaitWorkspaceBuildJob ( t , client , build . ID )
// Then:
// When we fetch the deleted workspace, we get the most recently deleted one
2022-08-09 17:17:00 +00:00
workspaceNew , err = client . WorkspaceByOwnerAndName ( ctx , workspace . OwnerName , workspace . Name , codersdk . WorkspaceOptions { IncludeDeleted : true } )
2022-06-08 18:04:05 +00:00
require . NoError ( t , err )
require . Equal ( t , workspace . ID , workspaceNew . ID )
} )
2022-03-22 19:17:50 +00:00
}
2022-06-14 13:46:33 +00:00
// TestWorkspaceFilter creates a set of workspaces, users, and organizations
// to run various filters against for testing.
2022-06-06 19:43:16 +00:00
func TestWorkspaceFilter ( t * testing . T ) {
t . Parallel ( )
2022-07-08 18:01:00 +00:00
// Manual tests still occur below, so this is safe to disable.
t . Skip ( "This test is slow and flaky. See: https://github.com/coder/coder/issues/2854" )
// nolint:unused
2022-06-14 13:46:33 +00:00
type coderUser struct {
* codersdk . Client
User codersdk . User
Org codersdk . Organization
}
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
first := coderdtest . CreateFirstUser ( t , client )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
2022-08-21 22:32:53 +00:00
t . Cleanup ( cancel )
2022-08-09 17:17:00 +00:00
2022-06-14 13:46:33 +00:00
users := make ( [ ] coderUser , 0 )
for i := 0 ; i < 10 ; i ++ {
2022-08-15 19:40:19 +00:00
userClient := coderdtest . CreateAnotherUser ( t , client , first . OrganizationID , rbac . RoleOwner ( ) )
2022-08-09 17:17:00 +00:00
user , err := userClient . User ( ctx , codersdk . Me )
2022-06-14 13:46:33 +00:00
require . NoError ( t , err , "fetch me" )
2022-06-25 11:22:59 +00:00
if i % 3 == 0 {
2022-08-09 17:17:00 +00:00
user , err = client . UpdateUserProfile ( ctx , user . ID . String ( ) , codersdk . UpdateUserProfileRequest {
2022-06-25 11:22:59 +00:00
Username : strings . ToUpper ( user . Username ) ,
} )
require . NoError ( t , err , "uppercase username" )
}
2022-08-09 17:17:00 +00:00
org , err := userClient . CreateOrganization ( ctx , codersdk . CreateOrganizationRequest {
2022-06-14 13:46:33 +00:00
Name : user . Username + "-org" ,
} )
require . NoError ( t , err , "create org" )
users = append ( users , coderUser {
Client : userClient ,
User : user ,
Org : org ,
} )
}
type madeWorkspace struct {
Owner codersdk . User
Workspace codersdk . Workspace
Template codersdk . Template
}
availTemplates := make ( [ ] codersdk . Template , 0 )
allWorkspaces := make ( [ ] madeWorkspace , 0 )
2022-06-25 11:22:59 +00:00
upperTemplates := make ( [ ] string , 0 )
2022-06-14 13:46:33 +00:00
// Create some random workspaces
2022-06-25 11:22:59 +00:00
var count int
for i , user := range users {
2022-06-14 13:46:33 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . Org . ID , nil )
// Create a template & workspace in the user's org
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-06-25 11:22:59 +00:00
var template codersdk . Template
if i % 3 == 0 {
template = coderdtest . CreateTemplate ( t , client , user . Org . ID , version . ID , func ( request * codersdk . CreateTemplateRequest ) {
request . Name = strings . ToUpper ( request . Name )
} )
upperTemplates = append ( upperTemplates , template . Name )
} else {
template = coderdtest . CreateTemplate ( t , client , user . Org . ID , version . ID )
}
2022-06-14 13:46:33 +00:00
availTemplates = append ( availTemplates , template )
2022-06-25 11:22:59 +00:00
workspace := coderdtest . CreateWorkspace ( t , user . Client , template . OrganizationID , template . ID , func ( request * codersdk . CreateWorkspaceRequest ) {
if count % 3 == 0 {
request . Name = strings . ToUpper ( request . Name )
}
} )
2022-06-14 13:46:33 +00:00
allWorkspaces = append ( allWorkspaces , madeWorkspace {
Workspace : workspace ,
Template : template ,
Owner : user . User ,
} )
// Make a workspace with a random template
idx , _ := cryptorand . Intn ( len ( availTemplates ) )
randTemplate := availTemplates [ idx ]
randWorkspace := coderdtest . CreateWorkspace ( t , user . Client , randTemplate . OrganizationID , randTemplate . ID )
allWorkspaces = append ( allWorkspaces , madeWorkspace {
Workspace : randWorkspace ,
Template : randTemplate ,
Owner : user . User ,
} )
}
// Make sure all workspaces are done. Do it after all are made
for i , w := range allWorkspaces {
latest := coderdtest . AwaitWorkspaceBuildJob ( t , client , w . Workspace . LatestBuild . ID )
allWorkspaces [ i ] . Workspace . LatestBuild = latest
}
// --- Setup done ---
testCases := [ ] struct {
Name string
Filter codersdk . WorkspaceFilter
// If FilterF is true, we include it in the expected results
FilterF func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool
} {
{
Name : "All" ,
Filter : codersdk . WorkspaceFilter { } ,
FilterF : func ( _ codersdk . WorkspaceFilter , _ madeWorkspace ) bool {
return true
} ,
} ,
{
Name : "Owner" ,
Filter : codersdk . WorkspaceFilter {
2022-06-25 11:22:59 +00:00
Owner : strings . ToUpper ( users [ 2 ] . User . Username ) ,
2022-06-14 13:46:33 +00:00
} ,
FilterF : func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool {
2022-06-25 11:22:59 +00:00
return strings . EqualFold ( workspace . Owner . Username , f . Owner )
2022-06-14 13:46:33 +00:00
} ,
} ,
{
Name : "TemplateName" ,
Filter : codersdk . WorkspaceFilter {
2022-06-25 11:22:59 +00:00
Template : strings . ToUpper ( allWorkspaces [ 5 ] . Template . Name ) ,
2022-06-14 13:46:33 +00:00
} ,
FilterF : func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool {
2022-06-25 11:22:59 +00:00
return strings . EqualFold ( workspace . Template . Name , f . Template )
} ,
} ,
{
Name : "UpperTemplateName" ,
Filter : codersdk . WorkspaceFilter {
Template : upperTemplates [ 0 ] ,
} ,
FilterF : func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool {
return strings . EqualFold ( workspace . Template . Name , f . Template )
2022-06-14 13:46:33 +00:00
} ,
} ,
{
Name : "Name" ,
Filter : codersdk . WorkspaceFilter {
// Use a common letter... one has to have this letter in it
Name : "a" ,
} ,
FilterF : func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool {
2022-06-25 11:22:59 +00:00
return strings . ContainsAny ( workspace . Workspace . Name , "Aa" )
2022-06-14 13:46:33 +00:00
} ,
} ,
{
Name : "Q-Owner/Name" ,
Filter : codersdk . WorkspaceFilter {
2022-06-25 11:22:59 +00:00
FilterQuery : allWorkspaces [ 5 ] . Owner . Username + "/" + strings . ToUpper ( allWorkspaces [ 5 ] . Workspace . Name ) ,
2022-06-14 13:46:33 +00:00
} ,
2022-06-25 11:22:59 +00:00
FilterF : func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool {
if strings . EqualFold ( workspace . Owner . Username , allWorkspaces [ 5 ] . Owner . Username ) &&
strings . Contains ( strings . ToLower ( workspace . Workspace . Name ) , strings . ToLower ( allWorkspaces [ 5 ] . Workspace . Name ) ) {
return true
}
return false
2022-06-14 13:46:33 +00:00
} ,
} ,
{
Name : "Many filters" ,
Filter : codersdk . WorkspaceFilter {
Owner : allWorkspaces [ 3 ] . Owner . Username ,
Template : allWorkspaces [ 3 ] . Template . Name ,
Name : allWorkspaces [ 3 ] . Workspace . Name ,
} ,
FilterF : func ( f codersdk . WorkspaceFilter , workspace madeWorkspace ) bool {
2022-06-25 11:22:59 +00:00
if strings . EqualFold ( workspace . Owner . Username , f . Owner ) &&
strings . Contains ( strings . ToLower ( workspace . Workspace . Name ) , strings . ToLower ( f . Name ) ) &&
strings . EqualFold ( workspace . Template . Name , f . Template ) {
return true
}
return false
2022-06-14 13:46:33 +00:00
} ,
} ,
}
for _ , c := range testCases {
c := c
t . Run ( c . Name , func ( t * testing . T ) {
t . Parallel ( )
2022-08-09 17:17:00 +00:00
workspaces , err := client . Workspaces ( ctx , c . Filter )
2022-06-14 13:46:33 +00:00
require . NoError ( t , err , "fetch workspaces" )
exp := make ( [ ] codersdk . Workspace , 0 )
for _ , made := range allWorkspaces {
if c . FilterF ( c . Filter , made ) {
exp = append ( exp , made . Workspace )
}
}
require . ElementsMatch ( t , exp , workspaces , "expected workspaces returned" )
} )
}
}
// TestWorkspaceFilterManual runs some specific setups with basic checks.
func TestWorkspaceFilterManual ( t * testing . T ) {
t . Parallel ( )
2022-06-06 19:43:16 +00:00
t . Run ( "Name" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-06-06 19:43:16 +00:00
// full match
2022-08-09 17:17:00 +00:00
ws , err := client . Workspaces ( ctx , codersdk . WorkspaceFilter {
2022-06-06 19:43:16 +00:00
Name : workspace . Name ,
} )
require . NoError ( t , err )
require . Len ( t , ws , 1 , workspace . Name )
require . Equal ( t , workspace . ID , ws [ 0 ] . ID )
// partial match
2022-08-09 17:17:00 +00:00
ws , err = client . Workspaces ( ctx , codersdk . WorkspaceFilter {
2022-06-06 19:43:16 +00:00
Name : workspace . Name [ 1 : len ( workspace . Name ) - 2 ] ,
} )
require . NoError ( t , err )
require . Len ( t , ws , 1 )
require . Equal ( t , workspace . ID , ws [ 0 ] . ID )
// no match
2022-08-09 17:17:00 +00:00
ws , err = client . Workspaces ( ctx , codersdk . WorkspaceFilter {
2022-06-06 19:43:16 +00:00
Name : "$$$$" ,
} )
require . NoError ( t , err )
require . Len ( t , ws , 0 )
} )
2022-06-14 13:46:33 +00:00
t . Run ( "Template" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
template2 := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
_ = coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template2 . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-06-14 13:46:33 +00:00
// empty
2022-08-09 17:17:00 +00:00
ws , err := client . Workspaces ( ctx , codersdk . WorkspaceFilter { } )
2022-06-14 13:46:33 +00:00
require . NoError ( t , err )
require . Len ( t , ws , 2 )
// single template
2022-08-09 17:17:00 +00:00
ws , err = client . Workspaces ( ctx , codersdk . WorkspaceFilter {
2022-06-14 13:46:33 +00:00
Template : template . Name ,
} )
require . NoError ( t , err )
require . Len ( t , ws , 1 )
require . Equal ( t , workspace . ID , ws [ 0 ] . ID )
} )
t . Run ( "FilterQuery" , func ( t * testing . T ) {
t . Parallel ( )
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
template2 := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
_ = coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template2 . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-06-14 13:46:33 +00:00
// single workspace
2022-08-09 17:17:00 +00:00
ws , err := client . Workspaces ( ctx , codersdk . WorkspaceFilter {
2022-06-14 13:46:33 +00:00
FilterQuery : fmt . Sprintf ( "template:%s %s/%s" , template . Name , workspace . OwnerName , workspace . Name ) ,
} )
require . NoError ( t , err )
require . Len ( t , ws , 1 )
require . Equal ( t , workspace . ID , ws [ 0 ] . ID )
} )
2022-06-06 19:43:16 +00:00
}
2022-03-07 17:40:54 +00:00
func TestPostWorkspaceBuild ( t * testing . T ) {
2022-02-06 00:24:51 +00:00
t . Parallel ( )
2022-04-06 17:42:40 +00:00
t . Run ( "NoTemplateVersion" , func ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-04-06 17:42:40 +00:00
TemplateVersionID : uuid . New ( ) ,
2022-05-19 18:04:44 +00:00
Transition : codersdk . WorkspaceTransitionStart ,
2022-01-25 19:52:58 +00:00
} )
2022-02-06 00:24:51 +00:00
require . Error ( t , err )
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusBadRequest , apiErr . StatusCode ( ) )
2022-01-25 19:52:58 +00:00
} )
2022-04-06 17:42:40 +00:00
t . Run ( "TemplateVersionFailedImport" , func ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , & echo . Responses {
2022-03-07 17:40:54 +00:00
Provision : [ ] * proto . Provision_Response { { } } ,
2022-01-25 19:52:58 +00:00
} )
2022-04-06 17:42:40 +00:00
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . CreateWorkspace ( ctx , user . OrganizationID , codersdk . CreateWorkspaceRequest {
2022-04-06 17:42:40 +00:00
TemplateID : template . ID ,
Name : "workspace" ,
2022-01-25 19:52:58 +00:00
} )
2022-02-06 00:24:51 +00:00
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
2022-03-07 17:40:54 +00:00
require . Equal ( t , http . StatusPreconditionFailed , apiErr . StatusCode ( ) )
2022-01-25 19:52:58 +00:00
} )
2022-03-07 17:40:54 +00:00
t . Run ( "AlreadyActive" , func ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-06-27 18:50:52 +00:00
client , closer := coderdtest . NewWithProvisionerCloser ( t , nil )
defer closer . Close ( )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-06-27 18:50:52 +00:00
closer . Close ( )
2022-03-07 17:40:54 +00:00
// Close here so workspace build doesn't process!
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-04-06 17:42:40 +00:00
TemplateVersionID : template . ActiveVersionID ,
2022-05-19 18:04:44 +00:00
Transition : codersdk . WorkspaceTransitionStart ,
2022-01-25 19:52:58 +00:00
} )
require . Error ( t , err )
2022-02-06 00:24:51 +00:00
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusConflict , apiErr . StatusCode ( ) )
2022-01-25 19:52:58 +00:00
} )
2022-05-18 16:33:33 +00:00
t . Run ( "IncrementBuildNumber" , func ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-03-22 19:17:50 +00:00
coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
build , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-04-06 17:42:40 +00:00
TemplateVersionID : template . ActiveVersionID ,
2022-05-19 18:04:44 +00:00
Transition : codersdk . WorkspaceTransitionStart ,
2022-03-07 17:40:54 +00:00
} )
require . NoError ( t , err )
2022-05-18 16:33:33 +00:00
require . Equal ( t , workspace . LatestBuild . BuildNumber + 1 , build . BuildNumber )
2022-01-25 19:52:58 +00:00
} )
2022-05-02 22:51:58 +00:00
t . Run ( "WithState" , func ( t * testing . T ) {
t . Parallel ( )
2022-06-27 18:50:52 +00:00
client := coderdtest . New ( t , & coderdtest . Options {
IncludeProvisionerD : true ,
} )
2022-05-02 22:51:58 +00:00
user := coderdtest . CreateFirstUser ( 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 )
coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
wantState := [ ] byte ( "something" )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
build , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-05-02 22:51:58 +00:00
TemplateVersionID : template . ActiveVersionID ,
2022-05-19 18:04:44 +00:00
Transition : codersdk . WorkspaceTransitionStart ,
2022-05-02 22:51:58 +00:00
ProvisionerState : wantState ,
} )
require . NoError ( t , err )
2022-08-09 17:17:00 +00:00
gotState , err := client . WorkspaceBuildState ( ctx , build . ID )
2022-05-02 22:51:58 +00:00
require . NoError ( t , err )
require . Equal ( t , wantState , gotState )
} )
2022-03-22 19:17:50 +00:00
t . Run ( "Delete" , func ( t * testing . T ) {
2022-03-07 17:40:54 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-03-22 19:17:50 +00:00
coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
build , err := client . CreateWorkspaceBuild ( ctx , workspace . ID , codersdk . CreateWorkspaceBuildRequest {
2022-05-19 18:04:44 +00:00
Transition : codersdk . WorkspaceTransitionDelete ,
2022-03-07 17:40:54 +00:00
} )
require . NoError ( t , err )
2022-05-18 16:33:33 +00:00
require . Equal ( t , workspace . LatestBuild . BuildNumber + 1 , build . BuildNumber )
2022-03-22 19:17:50 +00:00
coderdtest . AwaitWorkspaceBuildJob ( t , client , build . ID )
2022-08-09 17:17:00 +00:00
workspaces , err := client . Workspaces ( ctx , codersdk . WorkspaceFilter {
2022-06-03 19:36:08 +00:00
Owner : user . UserID . String ( ) ,
} )
2022-03-07 17:40:54 +00:00
require . NoError ( t , err )
2022-03-22 19:17:50 +00:00
require . Len ( t , workspaces , 0 )
2022-03-07 17:40:54 +00:00
} )
2022-02-06 00:24:51 +00:00
}
2022-03-07 17:40:54 +00:00
func TestWorkspaceBuildByName ( t * testing . T ) {
2022-02-06 00:24:51 +00:00
t . Parallel ( )
2022-03-07 17:40:54 +00:00
t . Run ( "NotFound" , func ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
_ , err := client . WorkspaceBuildByName ( ctx , workspace . ID , "something" )
2022-03-07 17:40:54 +00:00
var apiErr * codersdk . Error
require . ErrorAs ( t , err , & apiErr )
require . Equal ( t , http . StatusNotFound , apiErr . StatusCode ( ) )
2022-01-25 19:52:58 +00:00
} )
2022-03-07 17:40:54 +00:00
t . Run ( "Found" , func ( t * testing . T ) {
2022-01-25 19:52:58 +00:00
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-03-07 17:40:54 +00:00
user := coderdtest . CreateFirstUser ( t , client )
2022-04-06 17:42:40 +00:00
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
2022-04-25 21:11:03 +00:00
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
build , err := client . WorkspaceBuild ( ctx , workspace . LatestBuild . ID )
2022-03-07 17:40:54 +00:00
require . NoError ( t , err )
2022-08-09 17:17:00 +00:00
_ , err = client . WorkspaceBuildByName ( ctx , workspace . ID , build . Name )
2022-01-25 19:52:58 +00:00
require . NoError ( t , err )
} )
}
2022-04-07 09:03:35 +00:00
func TestWorkspaceUpdateAutostart ( t * testing . T ) {
t . Parallel ( )
2022-08-09 17:17:00 +00:00
dublinLoc := mustLocation ( t , "Europe/Dublin" )
2022-04-07 09:03:35 +00:00
testCases := [ ] struct {
name string
2022-06-02 10:23:34 +00:00
schedule * string
2022-04-07 09:03:35 +00:00
expectedError string
at time . Time
expectedNext time . Time
expectedInterval time . Duration
} {
{
name : "disable autostart" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "" ) ,
2022-04-07 09:03:35 +00:00
expectedError : "" ,
} ,
{
name : "friday to monday" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "CRON_TZ=Europe/Dublin 30 9 * * 1-5" ) ,
2022-04-07 09:03:35 +00:00
expectedError : "" ,
at : time . Date ( 2022 , 5 , 6 , 9 , 31 , 0 , 0 , dublinLoc ) ,
expectedNext : time . Date ( 2022 , 5 , 9 , 9 , 30 , 0 , 0 , dublinLoc ) ,
expectedInterval : 71 * time . Hour + 59 * time . Minute ,
} ,
{
name : "monday to tuesday" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "CRON_TZ=Europe/Dublin 30 9 * * 1-5" ) ,
2022-04-07 09:03:35 +00:00
expectedError : "" ,
at : time . Date ( 2022 , 5 , 9 , 9 , 31 , 0 , 0 , dublinLoc ) ,
expectedNext : time . Date ( 2022 , 5 , 10 , 9 , 30 , 0 , 0 , dublinLoc ) ,
expectedInterval : 23 * time . Hour + 59 * time . Minute ,
} ,
{
// DST in Ireland began on Mar 27 in 2022 at 0100. Forward 1 hour.
name : "DST start" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "CRON_TZ=Europe/Dublin 30 9 * * *" ) ,
2022-04-07 09:03:35 +00:00
expectedError : "" ,
at : time . Date ( 2022 , 3 , 26 , 9 , 31 , 0 , 0 , dublinLoc ) ,
expectedNext : time . Date ( 2022 , 3 , 27 , 9 , 30 , 0 , 0 , dublinLoc ) ,
expectedInterval : 22 * time . Hour + 59 * time . Minute ,
} ,
{
// DST in Ireland ends on Oct 30 in 2022 at 0200. Back 1 hour.
name : "DST end" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "CRON_TZ=Europe/Dublin 30 9 * * *" ) ,
2022-04-07 09:03:35 +00:00
expectedError : "" ,
at : time . Date ( 2022 , 10 , 29 , 9 , 31 , 0 , 0 , dublinLoc ) ,
expectedNext : time . Date ( 2022 , 10 , 30 , 9 , 30 , 0 , 0 , dublinLoc ) ,
expectedInterval : 24 * time . Hour + 59 * time . Minute ,
} ,
{
name : "invalid location" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "CRON_TZ=Imaginary/Place 30 9 * * 1-5" ) ,
2022-06-07 12:37:45 +00:00
expectedError : "parse schedule: provided bad location Imaginary/Place: unknown time zone Imaginary/Place" ,
2022-04-07 09:03:35 +00:00
} ,
{
name : "invalid schedule" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "asdf asdf asdf " ) ,
2022-06-07 12:37:45 +00:00
expectedError : ` validate weekly schedule: expected schedule to consist of 5 fields with an optional CRON_TZ=<timezone> prefix ` ,
2022-04-18 16:04:48 +00:00
} ,
{
name : "only 3 values" ,
2022-06-02 10:23:34 +00:00
schedule : ptr . Ref ( "CRON_TZ=Europe/Dublin 30 9 *" ) ,
2022-06-07 12:37:45 +00:00
expectedError : ` validate weekly schedule: expected schedule to consist of 5 fields with an optional CRON_TZ=<timezone> prefix ` ,
2022-04-07 09:03:35 +00:00
} ,
}
for _ , testCase := range testCases {
testCase := testCase
t . Run ( testCase . name , func ( t * testing . T ) {
t . Parallel ( )
var (
2022-05-19 22:47:45 +00:00
client = coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-04-07 09:03:35 +00:00
user = coderdtest . CreateFirstUser ( t , client )
version = coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
_ = coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
project = coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
2022-05-23 22:31:41 +00:00
workspace = coderdtest . CreateWorkspace ( t , client , user . OrganizationID , project . ID , func ( cwr * codersdk . CreateWorkspaceRequest ) {
cwr . AutostartSchedule = nil
2022-06-02 10:23:34 +00:00
cwr . TTLMillis = nil
2022-05-23 22:31:41 +00:00
} )
2022-04-07 09:03:35 +00:00
)
// ensure test invariant: new workspaces have no autostart schedule.
require . Empty ( t , workspace . AutostartSchedule , "expected newly-minted workspace to have no autostart schedule" )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-04-07 09:03:35 +00:00
err := client . UpdateWorkspaceAutostart ( ctx , workspace . ID , codersdk . UpdateWorkspaceAutostartRequest {
Schedule : testCase . schedule ,
} )
if testCase . expectedError != "" {
2022-06-03 21:48:09 +00:00
require . ErrorContains ( t , err , testCase . expectedError , "Invalid autostart schedule" )
2022-04-07 09:03:35 +00:00
return
}
require . NoError ( t , err , "expected no error setting workspace autostart schedule" )
updated , err := client . Workspace ( ctx , workspace . ID )
require . NoError ( t , err , "fetch updated workspace" )
2022-06-02 10:23:34 +00:00
if testCase . schedule == nil || * testCase . schedule == "" {
require . Nil ( t , updated . AutostartSchedule )
2022-04-07 09:03:35 +00:00
return
}
2022-06-02 10:23:34 +00:00
require . EqualValues ( t , * testCase . schedule , * updated . AutostartSchedule , "expected autostart schedule to equal requested" )
sched , err := schedule . Weekly ( * updated . AutostartSchedule )
2022-04-07 09:03:35 +00:00
require . NoError ( t , err , "parse returned schedule" )
next := sched . Next ( testCase . at )
require . Equal ( t , testCase . expectedNext , next , "unexpected next scheduled autostart time" )
interval := next . Sub ( testCase . at )
require . Equal ( t , testCase . expectedInterval , interval , "unexpected interval" )
} )
}
t . Run ( "NotFound" , func ( t * testing . T ) {
var (
client = coderdtest . New ( t , nil )
_ = coderdtest . CreateFirstUser ( t , client )
wsid = uuid . New ( )
req = codersdk . UpdateWorkspaceAutostartRequest {
2022-06-02 10:23:34 +00:00
Schedule : ptr . Ref ( "9 30 1-5" ) ,
2022-04-07 09:03:35 +00:00
}
)
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-04-07 09:03:35 +00:00
err := client . UpdateWorkspaceAutostart ( ctx , wsid , req )
require . IsType ( t , err , & codersdk . Error { } , "expected codersdk.Error" )
coderSDKErr , _ := err . ( * codersdk . Error ) //nolint:errorlint
require . Equal ( t , coderSDKErr . StatusCode ( ) , 404 , "expected status code 404" )
2022-06-14 15:14:05 +00:00
require . Contains ( t , coderSDKErr . Message , "Resource not found" , "unexpected response code" )
2022-04-07 09:03:35 +00:00
} )
}
2022-05-26 17:08:11 +00:00
func TestWorkspaceUpdateTTL ( t * testing . T ) {
2022-04-07 09:03:35 +00:00
t . Parallel ( )
testCases := [ ] struct {
2022-06-14 16:09:24 +00:00
name string
ttlMillis * int64
expectedError string
modifyTemplate func ( * codersdk . CreateTemplateRequest )
2022-04-07 09:03:35 +00:00
} {
{
2022-06-14 16:09:24 +00:00
name : "disable ttl" ,
ttlMillis : nil ,
expectedError : "" ,
2022-06-09 21:10:24 +00:00
} ,
{
2022-06-14 16:09:24 +00:00
name : "update ttl" ,
ttlMillis : ptr . Ref ( 12 * time . Hour . Milliseconds ( ) ) ,
expectedError : "" ,
2022-04-07 09:03:35 +00:00
} ,
{
2022-05-30 19:19:17 +00:00
name : "below minimum ttl" ,
2022-06-02 10:23:34 +00:00
ttlMillis : ptr . Ref ( ( 30 * time . Second ) . Milliseconds ( ) ) ,
2022-07-27 21:20:02 +00:00
expectedError : "time until shutdown must be at least one minute" ,
2022-05-30 19:19:17 +00:00
} ,
{
2022-06-14 16:09:24 +00:00
name : "minimum ttl" ,
ttlMillis : ptr . Ref ( time . Minute . Milliseconds ( ) ) ,
expectedError : "" ,
2022-05-30 19:19:17 +00:00
} ,
{
2022-06-14 16:09:24 +00:00
name : "maximum ttl" ,
ttlMillis : ptr . Ref ( ( 24 * 7 * time . Hour ) . Milliseconds ( ) ) ,
expectedError : "" ,
2022-04-07 09:03:35 +00:00
} ,
2022-05-30 19:19:17 +00:00
{
name : "above maximum ttl" ,
2022-06-02 10:23:34 +00:00
ttlMillis : ptr . Ref ( ( 24 * 7 * time . Hour + time . Minute ) . Milliseconds ( ) ) ,
2022-07-27 21:20:02 +00:00
expectedError : "time until shutdown must be less than 7 days" ,
2022-05-30 19:19:17 +00:00
} ,
2022-06-07 12:37:45 +00:00
{
name : "above template maximum ttl" ,
ttlMillis : ptr . Ref ( ( 12 * time . Hour ) . Milliseconds ( ) ) ,
2022-07-27 21:20:02 +00:00
expectedError : "ttl_ms: time until shutdown must be below template maximum 8h0m0s" ,
2022-06-07 12:37:45 +00:00
modifyTemplate : func ( ctr * codersdk . CreateTemplateRequest ) { ctr . MaxTTLMillis = ptr . Ref ( ( 8 * time . Hour ) . Milliseconds ( ) ) } ,
} ,
2022-04-07 09:03:35 +00:00
}
for _ , testCase := range testCases {
testCase := testCase
t . Run ( testCase . name , func ( t * testing . T ) {
t . Parallel ( )
2022-06-07 12:37:45 +00:00
mutators := make ( [ ] func ( * codersdk . CreateTemplateRequest ) , 0 )
if testCase . modifyTemplate != nil {
mutators = append ( mutators , testCase . modifyTemplate )
}
2022-04-07 09:03:35 +00:00
var (
2022-05-19 22:47:45 +00:00
client = coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-04-07 09:03:35 +00:00
user = coderdtest . CreateFirstUser ( t , client )
version = coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
_ = coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-06-07 12:37:45 +00:00
project = coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID , mutators ... )
2022-05-23 22:31:41 +00:00
workspace = coderdtest . CreateWorkspace ( t , client , user . OrganizationID , project . ID , func ( cwr * codersdk . CreateWorkspaceRequest ) {
cwr . AutostartSchedule = nil
2022-06-02 10:23:34 +00:00
cwr . TTLMillis = nil
2022-05-23 22:31:41 +00:00
} )
2022-06-09 21:10:24 +00:00
_ = coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
2022-04-07 09:03:35 +00:00
)
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-05-19 19:09:27 +00:00
err := client . UpdateWorkspaceTTL ( ctx , workspace . ID , codersdk . UpdateWorkspaceTTLRequest {
2022-06-02 10:23:34 +00:00
TTLMillis : testCase . ttlMillis ,
2022-04-07 09:03:35 +00:00
} )
if testCase . expectedError != "" {
2022-05-30 19:19:17 +00:00
require . ErrorContains ( t , err , testCase . expectedError , "unexpected error when setting workspace autostop schedule" )
2022-04-07 09:03:35 +00:00
return
}
require . NoError ( t , err , "expected no error setting workspace autostop schedule" )
updated , err := client . Workspace ( ctx , workspace . ID )
require . NoError ( t , err , "fetch updated workspace" )
2022-06-02 10:23:34 +00:00
require . Equal ( t , testCase . ttlMillis , updated . TTLMillis , "expected autostop ttl to equal requested" )
2022-04-07 09:03:35 +00:00
} )
}
t . Run ( "NotFound" , func ( t * testing . T ) {
var (
client = coderdtest . New ( t , nil )
_ = coderdtest . CreateFirstUser ( t , client )
wsid = uuid . New ( )
2022-05-19 19:09:27 +00:00
req = codersdk . UpdateWorkspaceTTLRequest {
2022-06-02 10:23:34 +00:00
TTLMillis : ptr . Ref ( time . Hour . Milliseconds ( ) ) ,
2022-04-07 09:03:35 +00:00
}
)
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-05-19 19:09:27 +00:00
err := client . UpdateWorkspaceTTL ( ctx , wsid , req )
2022-04-07 09:03:35 +00:00
require . IsType ( t , err , & codersdk . Error { } , "expected codersdk.Error" )
coderSDKErr , _ := err . ( * codersdk . Error ) //nolint:errorlint
require . Equal ( t , coderSDKErr . StatusCode ( ) , 404 , "expected status code 404" )
2022-06-14 15:14:05 +00:00
require . Contains ( t , coderSDKErr . Message , "Resource not found" , "unexpected response code" )
2022-04-07 09:03:35 +00:00
} )
}
2022-05-26 17:08:11 +00:00
func TestWorkspaceExtend ( t * testing . T ) {
t . Parallel ( )
var (
2022-06-14 21:39:15 +00:00
ttl = 8 * time . Hour
newDeadline = time . Now ( ) . Add ( ttl + time . Hour ) . UTC ( )
2022-05-26 17:08:11 +00:00
client = coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
user = coderdtest . CreateFirstUser ( t , client )
version = coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
_ = coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
2022-06-14 21:39:15 +00:00
template = coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
workspace = coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID , func ( cwr * codersdk . CreateWorkspaceRequest ) {
cwr . TTLMillis = ptr . Ref ( ttl . Milliseconds ( ) )
} )
_ = coderdtest . AwaitWorkspaceBuildJob ( t , client , workspace . LatestBuild . ID )
2022-05-26 17:08:11 +00:00
)
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
defer cancel ( )
2022-05-26 17:08:11 +00:00
workspace , err := client . Workspace ( ctx , workspace . ID )
require . NoError ( t , err , "fetch provisioned workspace" )
2022-06-14 21:39:15 +00:00
oldDeadline := workspace . LatestBuild . Deadline
2022-05-26 17:08:11 +00:00
// Updating the deadline should succeed
req := codersdk . PutExtendWorkspaceRequest {
Deadline : newDeadline ,
}
err = client . PutExtendWorkspace ( ctx , workspace . ID , req )
require . NoError ( t , err , "failed to extend workspace" )
// Ensure deadline set correctly
updated , err := client . Workspace ( ctx , workspace . ID )
require . NoError ( t , err , "failed to fetch updated workspace" )
2022-06-14 21:39:15 +00:00
require . WithinDuration ( t , newDeadline , updated . LatestBuild . Deadline , time . Minute )
2022-05-26 17:08:11 +00:00
// Zero time should fail
err = client . PutExtendWorkspace ( ctx , workspace . ID , codersdk . PutExtendWorkspaceRequest {
Deadline : time . Time { } ,
} )
2022-05-27 14:45:22 +00:00
require . ErrorContains ( t , err , "deadline: Validation failed for tag \"required\" with value: \"0001-01-01 00:00:00 +0000 UTC\"" , "setting an empty deadline on a workspace should fail" )
2022-05-26 17:08:11 +00:00
2022-06-15 14:32:02 +00:00
// Updating with a deadline less than 30 minutes in the future should fail
deadlineTooSoon := time . Now ( ) . Add ( 15 * time . Minute ) // XXX: time.Now
2022-06-14 21:39:15 +00:00
err = client . PutExtendWorkspace ( ctx , workspace . ID , codersdk . PutExtendWorkspaceRequest {
Deadline : deadlineTooSoon ,
} )
2022-07-29 14:01:17 +00:00
require . ErrorContains ( t , err , "unexpected status code 400: Cannot extend workspace: new deadline must be at least 30 minutes in the future" , "setting a deadline less than 30 minutes in the future should fail" )
2022-06-14 21:39:15 +00:00
// And with a deadline greater than the template max_ttl should also fail
deadlineExceedsMaxTTL := time . Now ( ) . Add ( time . Duration ( template . MaxTTLMillis ) * time . Millisecond ) . Add ( time . Minute )
err = client . PutExtendWorkspace ( ctx , workspace . ID , codersdk . PutExtendWorkspaceRequest {
Deadline : deadlineExceedsMaxTTL ,
} )
2022-07-29 14:01:17 +00:00
require . ErrorContains ( t , err , "unexpected status code 400: Cannot extend workspace: new deadline is greater than template allows" , "setting a deadline greater than that allowed by the template should fail" )
2022-06-14 21:39:15 +00:00
// Updating with a deadline 30 minutes in the future should succeed
deadlineJustSoonEnough := time . Now ( ) . Add ( 30 * time . Minute )
2022-05-26 17:08:11 +00:00
err = client . PutExtendWorkspace ( ctx , workspace . ID , codersdk . PutExtendWorkspaceRequest {
2022-06-14 21:39:15 +00:00
Deadline : deadlineJustSoonEnough ,
2022-05-26 17:08:11 +00:00
} )
2022-06-14 21:39:15 +00:00
require . NoError ( t , err , "setting a deadline at least 30 minutes in the future should succeed" )
2022-05-30 19:19:17 +00:00
2022-06-14 21:39:15 +00:00
// Updating with a deadline an hour before the previous deadline should succeed
2022-05-30 19:19:17 +00:00
err = client . PutExtendWorkspace ( ctx , workspace . ID , codersdk . PutExtendWorkspaceRequest {
2022-06-14 21:39:15 +00:00
Deadline : oldDeadline . Add ( - time . Hour ) ,
2022-05-30 19:19:17 +00:00
} )
2022-06-14 21:39:15 +00:00
require . NoError ( t , err , "setting an earlier deadline should not fail" )
2022-05-26 17:08:11 +00:00
// Ensure deadline still set correctly
updated , err = client . Workspace ( ctx , workspace . ID )
require . NoError ( t , err , "failed to fetch updated workspace" )
2022-06-14 21:39:15 +00:00
require . WithinDuration ( t , oldDeadline . Add ( - time . Hour ) , updated . LatestBuild . Deadline , time . Minute )
2022-05-26 17:08:11 +00:00
}
2022-05-18 21:16:26 +00:00
func TestWorkspaceWatcher ( t * testing . T ) {
t . Parallel ( )
2022-05-19 22:47:45 +00:00
client := coderdtest . New ( t , & coderdtest . Options { IncludeProvisionerD : true } )
2022-05-18 21:16:26 +00:00
user := coderdtest . CreateFirstUser ( t , client )
version := coderdtest . CreateTemplateVersion ( t , client , user . OrganizationID , nil )
coderdtest . AwaitTemplateVersionJob ( t , client , version . ID )
template := coderdtest . CreateTemplate ( t , client , user . OrganizationID , version . ID )
workspace := coderdtest . CreateWorkspace ( t , client , user . OrganizationID , template . ID )
2022-08-09 17:17:00 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , testutil . WaitLong )
2022-05-18 21:16:26 +00:00
defer cancel ( )
2022-08-09 17:17:00 +00:00
w , err := client . Workspace ( ctx , workspace . ID )
require . NoError ( t , err )
2022-05-18 21:16:26 +00:00
wc , err := client . WatchWorkspace ( ctx , w . ID )
require . NoError ( t , err )
for i := 0 ; i < 3 ; i ++ {
_ , more := <- wc
require . True ( t , more )
}
cancel ( )
require . EqualValues ( t , codersdk . Workspace { } , <- wc )
}
2022-05-19 19:09:27 +00:00
func mustLocation ( t * testing . T , location string ) * time . Location {
t . Helper ( )
loc , err := time . LoadLocation ( location )
if err != nil {
t . Errorf ( "failed to load location %s: %s" , location , err . Error ( ) )
}
return loc
}