Skip to content

Commit ea2919d

Browse files
committed
test: add new test TestPrebuildAndRegularWorkspaceDifferentWorkspaceClass
Test prebuild and regular workspace with different workspace class Signed-off-by: JenTing Hsiao <[email protected]>
1 parent 35a2760 commit ea2919d

File tree

1 file changed

+289
-67
lines changed

1 file changed

+289
-67
lines changed

test/tests/components/ws-manager/prebuild_test.go

Lines changed: 289 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"context"
99
"encoding/json"
1010
"fmt"
11+
"net/rpc"
1112
"path/filepath"
1213
"reflect"
1314
"strings"
@@ -312,73 +313,7 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) {
312313
})
313314
integration.DeferCloser(t, closer)
314315

315-
// check prebuild log message exists
316-
// since the message '🤙 This task ran as a workspace prebuild' is generated by
317-
// a prebuild workspace supervisor, so we add a retry mechanism to make sure that we
318-
// won't check the message too earlier before the supervisor generated it.
319-
var grepResp agent.ExecResponse
320-
var checkPrebuildLog bool
321-
for i := 0; i < 10; i++ {
322-
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
323-
Dir: prebuildLogPath,
324-
Command: "bash",
325-
Args: []string{
326-
"-c",
327-
fmt.Sprintf("grep %s *", prebuildLog),
328-
},
329-
}, &grepResp)
330-
if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" {
331-
checkPrebuildLog = true
332-
break
333-
}
334-
t.Logf("[%d] retry...", i)
335-
time.Sleep(3 * time.Second)
336-
}
337-
338-
if !checkPrebuildLog {
339-
t.Logf("cannot found the prebuild message %s in %s, err:%v, exitCode:%d, stdout:%s", prebuildLog, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)
340-
341-
// somehow, the prebuild log message '🤙 This task ran as a workspace prebuild' does not exists
342-
// we fall back to check the the init task message within the /workspace/.gitpod/prebuild-log-* or not
343-
var grepResp agent.ExecResponse
344-
var checkInitTaskMsg bool
345-
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
346-
Dir: prebuildLogPath,
347-
Command: "bash",
348-
Args: []string{
349-
"-c",
350-
fmt.Sprintf("grep %q *", initTask),
351-
},
352-
}, &grepResp)
353-
if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" {
354-
checkInitTaskMsg = true
355-
}
356-
357-
if !checkInitTaskMsg {
358-
t.Logf("cannot found the init task message %s in %s, err:%v, exitCode:%d, stdout:%s", initTask, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)
359-
360-
// somehow, the init task message does not exist within the /workspace/.gitpod/prebuild-log-*
361-
// we fall back to check the file exists or not
362-
var ls agent.ListDirResponse
363-
err = rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{
364-
Dir: test.WorkspaceRoot,
365-
}, &ls)
366-
if err != nil {
367-
t.Fatal(err)
368-
}
369-
370-
var found bool
371-
for _, f := range ls.Files {
372-
if filepath.Base(f) == "someFile" {
373-
found = true
374-
break
375-
}
376-
}
377-
if !found {
378-
t.Fatal("did not find someFile from previous workspace instance")
379-
}
380-
}
381-
}
316+
checkPrebuildLogExist(t, cfg, rsa, ws, test.WorkspaceRoot)
382317

383318
// check the files/folders permission under .git/ is not root
384319
var findUserResp agent.ExecResponse
@@ -491,6 +426,293 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) {
491426
testEnv.Test(t, f)
492427
}
493428

429+
// TestPrebuildAndRegularWorkspaceDifferentWorkspaceClass
430+
// - create a prebuild with small/large workspace class (20Gi/30Gi disk)
431+
// - the user preference is large workspace class (30Gi disk)
432+
// - open the workspace from prebuild
433+
// - make sure either one of the condition mets
434+
// - the prebuild log message exists
435+
// - the init task message exists
436+
// - the init task generated file exists
437+
//
438+
// - make sure the .git/ folder with correct permission
439+
// - make sure the user disk size is 30Gi
440+
func TestPrebuildAndRegularWorkspaceDifferentWorkspaceClass(t *testing.T) {
441+
f := features.New("prebuild").
442+
WithLabel("component", "ws-manager").
443+
Assess("it should open workspace with different workspace class", func(_ context.Context, t *testing.T, cfg *envconf.Config) context.Context {
444+
tests := []struct {
445+
Name string
446+
PrebuildWorkspaceClass string
447+
RegularWorkspaceClass string
448+
ContextURL string
449+
WorkspaceRoot string
450+
CheckoutLocation string
451+
ShouldFail bool
452+
}{
453+
{
454+
Name: "prebuild-small-regular-large-workspace-class",
455+
// TODO: do not use hard-code workspace class name to prevent if we change to different environment to run the test
456+
PrebuildWorkspaceClass: "small",
457+
RegularWorkspaceClass: "default",
458+
//
459+
ContextURL: "https://github.com/gitpod-io/empty",
460+
CheckoutLocation: "empty",
461+
WorkspaceRoot: "/workspace/empty",
462+
},
463+
{
464+
Name: "prebuild-large-regular-small-workspace-class",
465+
// TODO: do not use hard-code workspace class name to prevent if we change to different environment to run the test
466+
PrebuildWorkspaceClass: "default",
467+
RegularWorkspaceClass: "small",
468+
//
469+
ContextURL: "https://github.com/gitpod-io/empty",
470+
CheckoutLocation: "empty",
471+
WorkspaceRoot: "/workspace/empty",
472+
ShouldFail: true,
473+
},
474+
}
475+
476+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(10*len(tests))*time.Minute)
477+
defer cancel()
478+
479+
for _, test := range tests {
480+
t.Run(test.Name, func(t *testing.T) {
481+
api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())
482+
t.Cleanup(func() {
483+
api.Done(t)
484+
})
485+
486+
// create a prebuild and stop workspace
487+
_, prebuildStopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error {
488+
req.Type = wsmanapi.WorkspaceType_PREBUILD
489+
req.Spec.Class = test.PrebuildWorkspaceClass
490+
req.Spec.Envvars = append(req.Spec.Envvars, &wsmanapi.EnvironmentVariable{
491+
Name: "GITPOD_TASKS",
492+
Value: fmt.Sprintf(`[{ "init": %q }]`, initTask),
493+
})
494+
req.Spec.FeatureFlags = []wsmanapi.WorkspaceFeatureFlag{wsmanapi.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM}
495+
req.Spec.Initializer = &csapi.WorkspaceInitializer{
496+
Spec: &csapi.WorkspaceInitializer_Git{
497+
Git: &csapi.GitInitializer{
498+
RemoteUri: test.ContextURL,
499+
CheckoutLocation: test.CheckoutLocation,
500+
Config: &csapi.GitConfig{},
501+
},
502+
},
503+
}
504+
req.Spec.WorkspaceLocation = test.CheckoutLocation
505+
return nil
506+
}))
507+
if err != nil {
508+
t.Fatalf("cannot launch a workspace: %q", err)
509+
}
510+
511+
prebuildSnapshot, vsInfo, err := stopWorkspaceAndFindSnapshot(prebuildStopWs, api)
512+
if err != nil {
513+
t.Fatalf("stop workspace and find snapshot error: %v", err)
514+
}
515+
516+
t.Logf("prebuild snapshot: %s", prebuildSnapshot)
517+
if vsInfo != nil {
518+
t.Logf("vsName: %s, vsHandle: %s", vsInfo.VolumeSnapshotName, vsInfo.VolumeSnapshotHandle)
519+
}
520+
521+
var (
522+
ws *integration.LaunchWorkspaceDirectlyResult
523+
stopWs integration.StopWorkspaceFunc
524+
)
525+
if test.ShouldFail {
526+
// launch the workspace from prebuild
527+
ws, stopWs, err = integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error {
528+
// TODO: do not use hard-code workspace class name to prevent if we change to different environment to run the test
529+
req.Spec.Class = test.RegularWorkspaceClass
530+
req.Spec.FeatureFlags = []wsmanapi.WorkspaceFeatureFlag{wsmanapi.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM}
531+
req.Spec.Initializer = &csapi.WorkspaceInitializer{
532+
Spec: &csapi.WorkspaceInitializer_Prebuild{
533+
Prebuild: &csapi.PrebuildInitializer{
534+
Prebuild: &csapi.SnapshotInitializer{
535+
Snapshot: prebuildSnapshot,
536+
FromVolumeSnapshot: true,
537+
},
538+
Git: []*csapi.GitInitializer{
539+
{
540+
RemoteUri: test.ContextURL,
541+
CheckoutLocation: test.CheckoutLocation,
542+
Config: &csapi.GitConfig{},
543+
},
544+
},
545+
},
546+
},
547+
}
548+
req.Spec.VolumeSnapshot = vsInfo
549+
req.Spec.WorkspaceLocation = test.CheckoutLocation
550+
return nil
551+
}), integration.WithWaitWorkspaceForOpts(integration.WorkspaceCanFail))
552+
} else {
553+
// launch the workspace from prebuild
554+
ws, stopWs, err = integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error {
555+
// TODO: do not use hard-code workspace class name to prevent if we change to different environment to run the test
556+
req.Spec.Class = test.RegularWorkspaceClass
557+
req.Spec.FeatureFlags = []wsmanapi.WorkspaceFeatureFlag{wsmanapi.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM}
558+
req.Spec.Initializer = &csapi.WorkspaceInitializer{
559+
Spec: &csapi.WorkspaceInitializer_Prebuild{
560+
Prebuild: &csapi.PrebuildInitializer{
561+
Prebuild: &csapi.SnapshotInitializer{
562+
Snapshot: prebuildSnapshot,
563+
FromVolumeSnapshot: true,
564+
},
565+
Git: []*csapi.GitInitializer{
566+
{
567+
RemoteUri: test.ContextURL,
568+
CheckoutLocation: test.CheckoutLocation,
569+
Config: &csapi.GitConfig{},
570+
},
571+
},
572+
},
573+
},
574+
}
575+
req.Spec.VolumeSnapshot = vsInfo
576+
req.Spec.WorkspaceLocation = test.CheckoutLocation
577+
return nil
578+
}))
579+
}
580+
if err != nil {
581+
t.Fatalf("cannot launch a workspace: %q", err)
582+
}
583+
584+
if test.ShouldFail {
585+
return
586+
}
587+
588+
defer func() {
589+
// stop workspace in defer function to prevent we forget to stop the workspace
590+
if err := stopWorkspace(t, cfg, stopWs); err != nil {
591+
t.Errorf("cannot stop workspace: %q", err)
592+
}
593+
}()
594+
595+
rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(),
596+
integration.WithInstanceID(ws.Req.Id),
597+
)
598+
if err != nil {
599+
t.Fatal(err)
600+
}
601+
t.Cleanup(func() {
602+
rsa.Close()
603+
})
604+
integration.DeferCloser(t, closer)
605+
606+
// checkPrebuildLogExist checks the prebuild log message exists
607+
checkPrebuildLogExist(t, cfg, rsa, ws, test.WorkspaceRoot)
608+
609+
// check the files/folders permission under .git/ is not root
610+
checkGitFolderPermission(t, rsa, test.WorkspaceRoot)
611+
})
612+
}
613+
return ctx
614+
}).
615+
Feature()
616+
617+
testEnv.Test(t, f)
618+
}
619+
620+
// checkPrebuildLogExist checks the prebuild log message exists
621+
func checkPrebuildLogExist(t *testing.T, cfg *envconf.Config, rsa *rpc.Client, ws *integration.LaunchWorkspaceDirectlyResult, wsRoot string) {
622+
// since the message '🤙 This task ran as a workspace prebuild' is generated by
623+
// a prebuild workspace supervisor, so we add a retry mechanism to make sure that we
624+
// won't check the message too earlier before the supervisor generated it.
625+
var (
626+
err error
627+
grepResp agent.ExecResponse
628+
checkPrebuildLog bool
629+
)
630+
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
631+
Dir: prebuildLogPath,
632+
Command: "bash",
633+
Args: []string{
634+
"-c",
635+
fmt.Sprintf("grep %s *", prebuildLog),
636+
},
637+
}, &grepResp)
638+
if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" {
639+
checkPrebuildLog = true
640+
}
641+
if checkPrebuildLog {
642+
return
643+
}
644+
645+
t.Logf("cannot found the prebuild message %s in %s, err:%v, exitCode:%d, stdout:%s", prebuildLog, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)
646+
647+
// somehow, the prebuild log message '🤙 This task ran as a workspace prebuild' does not exists
648+
// we fall back to check the the init task message within the /workspace/.gitpod/prebuild-log-* or not
649+
var grepResp1 agent.ExecResponse
650+
var checkInitTaskMsg bool
651+
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
652+
Dir: prebuildLogPath,
653+
Command: "bash",
654+
Args: []string{
655+
"-c",
656+
fmt.Sprintf("grep %q *", initTask),
657+
},
658+
}, &grepResp1)
659+
if err == nil && grepResp1.ExitCode == 0 && strings.Trim(grepResp1.Stdout, " \t\n") != "" {
660+
checkInitTaskMsg = true
661+
}
662+
if checkInitTaskMsg {
663+
return
664+
}
665+
666+
t.Logf("cannot found the init task message %s in %s, err:%v, exitCode:%d, stdout:%s", initTask, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)
667+
668+
// somehow, the init task message does not exist within the /workspace/.gitpod/prebuild-log-*
669+
// we fall back to check the file exists or not
670+
var ls agent.ListDirResponse
671+
err = rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{
672+
Dir: wsRoot,
673+
}, &ls)
674+
if err != nil {
675+
t.Fatal(err)
676+
}
677+
678+
var found bool
679+
for _, f := range ls.Files {
680+
if filepath.Base(f) == "someFile" {
681+
found = true
682+
break
683+
}
684+
}
685+
if found {
686+
return
687+
}
688+
t.Fatal("did not find someFile from previous workspace instance")
689+
}
690+
691+
// checkGitFolderPermission checks the files/folders permission under .git/ is not root
692+
func checkGitFolderPermission(t *testing.T, rsa *rpc.Client, workspaceRoot string) {
693+
var findUserResp agent.ExecResponse
694+
var gitDir string = fmt.Sprintf("%s/%s", workspaceRoot, ".git")
695+
696+
err := rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
697+
Dir: gitDir,
698+
Command: "find",
699+
Args: []string{"-user", "root"},
700+
}, &findUserResp)
701+
if err != nil || findUserResp.ExitCode != 0 || strings.Trim(findUserResp.Stdout, " \t\n") != "" {
702+
t.Fatalf("incorrect file perimssion under %s folder, err:%v, exitCode:%d, stdout:%s", gitDir, err, findUserResp.ExitCode, findUserResp.Stdout)
703+
}
704+
705+
var findGroupResp agent.ExecResponse
706+
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
707+
Dir: gitDir,
708+
Command: "find",
709+
Args: []string{"-group", "root"},
710+
}, &findGroupResp)
711+
if err != nil || findGroupResp.ExitCode != 0 || strings.Trim(findGroupResp.Stdout, " \t\n") != "" {
712+
t.Fatalf("incorrect group perimssion under %s folder, err:%v, exitCode:%d, stdout:%s", gitDir, err, findGroupResp.ExitCode, findGroupResp.Stdout)
713+
}
714+
}
715+
494716
func stopWorkspaceAndFindSnapshot(StopWorkspaceFunc integration.StopWorkspaceFunc, api *integration.ComponentAPI) (string, *wsmanapi.VolumeSnapshotInfo, error) {
495717
lastStatus, err := StopWorkspaceFunc(true, api)
496718
if err != nil {

0 commit comments

Comments
 (0)