Skip to content

Commit

Permalink
test: add new test TestPrebuildAndRegularWorkspaceDifferentWorkspaceC…
Browse files Browse the repository at this point in the history
…lass

Test prebuild and regular workspace with different workspace class

Signed-off-by: JenTing Hsiao <[email protected]>
  • Loading branch information
jenting authored and roboquat committed Sep 28, 2022
1 parent 169f8e7 commit 129f9b4
Showing 1 changed file with 261 additions and 87 deletions.
348 changes: 261 additions & 87 deletions test/tests/components/ws-manager/prebuild_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"encoding/json"
"fmt"
"net/rpc"
"path/filepath"
"reflect"
"strings"
Expand Down Expand Up @@ -312,95 +313,11 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) {
})
integration.DeferCloser(t, closer)

// check prebuild log message exists
// since the message '🤙 This task ran as a workspace prebuild' is generated by
// a prebuild workspace supervisor, so we add a retry mechanism to make sure that we
// won't check the message too earlier before the supervisor generated it.
var grepResp agent.ExecResponse
var checkPrebuildLog bool
for i := 0; i < 10; i++ {
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: prebuildLogPath,
Command: "bash",
Args: []string{
"-c",
fmt.Sprintf("grep %s *", prebuildLog),
},
}, &grepResp)
if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" {
checkPrebuildLog = true
break
}
t.Logf("[%d] retry...", i)
time.Sleep(3 * time.Second)
}

if !checkPrebuildLog {
t.Logf("cannot found the prebuild message %s in %s, err:%v, exitCode:%d, stdout:%s", prebuildLog, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)

// somehow, the prebuild log message '🤙 This task ran as a workspace prebuild' does not exists
// we fall back to check the the init task message within the /workspace/.gitpod/prebuild-log-* or not
var grepResp agent.ExecResponse
var checkInitTaskMsg bool
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: prebuildLogPath,
Command: "bash",
Args: []string{
"-c",
fmt.Sprintf("grep %q *", initTask),
},
}, &grepResp)
if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" {
checkInitTaskMsg = true
}

if !checkInitTaskMsg {
t.Logf("cannot found the init task message %s in %s, err:%v, exitCode:%d, stdout:%s", initTask, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)

// somehow, the init task message does not exist within the /workspace/.gitpod/prebuild-log-*
// we fall back to check the file exists or not
var ls agent.ListDirResponse
err = rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{
Dir: test.WorkspaceRoot,
}, &ls)
if err != nil {
t.Fatal(err)
}

var found bool
for _, f := range ls.Files {
if filepath.Base(f) == "someFile" {
found = true
break
}
}
if !found {
t.Fatal("did not find someFile from previous workspace instance")
}
}
}
// checkPrebuildLogExist checks the prebuild log message exists
checkPrebuildLogExist(t, cfg, rsa, ws, test.WorkspaceRoot)

// check the files/folders permission under .git/ is not root
var findUserResp agent.ExecResponse
var gitDir string = fmt.Sprintf("%s/%s", test.WorkspaceRoot, ".git")
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: gitDir,
Command: "find",
Args: []string{"-user", "root"},
}, &findUserResp)
if err != nil || findUserResp.ExitCode != 0 || strings.Trim(findUserResp.Stdout, " \t\n") != "" {
t.Fatalf("incorrect file perimssion under %s folder, err:%v, exitCode:%d, stdout:%s", gitDir, err, findUserResp.ExitCode, findUserResp.Stdout)
}

var findGroupResp agent.ExecResponse
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: gitDir,
Command: "find",
Args: []string{"-group", "root"},
}, &findGroupResp)
if err != nil || findGroupResp.ExitCode != 0 || strings.Trim(findGroupResp.Stdout, " \t\n") != "" {
t.Fatalf("incorrect group perimssion under %s folder, err:%v, exitCode:%d, stdout:%s", gitDir, err, findGroupResp.ExitCode, findGroupResp.Stdout)
}
checkGitFolderPermission(t, rsa, test.WorkspaceRoot)

// write file foobar.txt and stop the workspace
var writeFileResp agent.ExecResponse
Expand Down Expand Up @@ -491,6 +408,263 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) {
testEnv.Test(t, f)
}

// TestPrebuildAndRegularWorkspaceDifferentWorkspaceClass
// - create a prebuild with small workspace class (20Gi disk)
// - create the workspace from prebulid with large workspace class (30Gi disk)
// - make sure either one of the condition mets
// - the prebuild log message exists
// - the init task message exists
// - the init task generated file exists
//
// - make sure the .git/ folder with correct permission
// - create a prebuild with large workspace class (30Gi disk) separately
// - create the workspace from prebuild with small workspace class (20Gi disk) separately
// - make sure the workspace can't start
func TestPrebuildAndRegularWorkspaceDifferentWorkspaceClass(t *testing.T) {
f := features.New("prebuild").
WithLabel("component", "ws-manager").
Assess("it should open workspace with different workspace class", func(_ context.Context, t *testing.T, cfg *envconf.Config) context.Context {
tests := []struct {
Name string
PrebuildWorkspaceClass string
RegularWorkspaceClass string
ContextURL string
WorkspaceRoot string
CheckoutLocation string
ShouldFailToOpenRegularWorkspace bool
}{
{
Name: "prebuild-small-regular-large-workspace-class",
// TODO: do not use hard-code workspace class name to prevent if we change to different environment to run the test
PrebuildWorkspaceClass: "small",
RegularWorkspaceClass: "default",
//
ContextURL: "https://github.com/gitpod-io/empty",
CheckoutLocation: "empty",
WorkspaceRoot: "/workspace/empty",
},
{
Name: "prebuild-large-regular-small-workspace-class",
// TODO: do not use hard-code workspace class name to prevent if we change to different environment to run the test
PrebuildWorkspaceClass: "default",
RegularWorkspaceClass: "small",
//
ContextURL: "https://github.com/gitpod-io/empty",
CheckoutLocation: "empty",
WorkspaceRoot: "/workspace/empty",
ShouldFailToOpenRegularWorkspace: true,
},
}

ctx, cancel := context.WithTimeout(context.Background(), time.Duration(10*len(tests))*time.Minute)
defer cancel()

for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())
t.Cleanup(func() {
api.Done(t)
})

// create a prebuild and stop workspace
_, prebuildStopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error {
req.Type = wsmanapi.WorkspaceType_PREBUILD
req.Spec.Class = test.PrebuildWorkspaceClass
req.Spec.Envvars = append(req.Spec.Envvars, &wsmanapi.EnvironmentVariable{
Name: "GITPOD_TASKS",
Value: fmt.Sprintf(`[{ "init": %q }]`, initTask),
})
req.Spec.FeatureFlags = []wsmanapi.WorkspaceFeatureFlag{wsmanapi.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM}
req.Spec.Initializer = &csapi.WorkspaceInitializer{
Spec: &csapi.WorkspaceInitializer_Git{
Git: &csapi.GitInitializer{
RemoteUri: test.ContextURL,
CheckoutLocation: test.CheckoutLocation,
Config: &csapi.GitConfig{},
},
},
}
req.Spec.WorkspaceLocation = test.CheckoutLocation
return nil
}))
if err != nil {
t.Fatalf("cannot launch a workspace: %q", err)
}

prebuildSnapshot, vsInfo, err := stopWorkspaceAndFindSnapshot(prebuildStopWs, api)
if err != nil {
t.Fatalf("stop workspace and find snapshot error: %v", err)
}

t.Logf("prebuild snapshot: %s", prebuildSnapshot)
if vsInfo != nil {
t.Logf("vsName: %s, vsHandle: %s", vsInfo.VolumeSnapshotName, vsInfo.VolumeSnapshotHandle)
}

// launch the workspace from prebuild
ws, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error {
req.Spec.Class = test.RegularWorkspaceClass
req.Spec.FeatureFlags = []wsmanapi.WorkspaceFeatureFlag{wsmanapi.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM}
req.Spec.Initializer = &csapi.WorkspaceInitializer{
Spec: &csapi.WorkspaceInitializer_Prebuild{
Prebuild: &csapi.PrebuildInitializer{
Prebuild: &csapi.SnapshotInitializer{
Snapshot: prebuildSnapshot,
FromVolumeSnapshot: true,
},
Git: []*csapi.GitInitializer{
{
RemoteUri: test.ContextURL,
CheckoutLocation: test.CheckoutLocation,
Config: &csapi.GitConfig{},
},
},
},
},
}
req.Spec.VolumeSnapshot = vsInfo
req.Spec.WorkspaceLocation = test.CheckoutLocation
return nil
}))
if err != nil {
if test.ShouldFailToOpenRegularWorkspace {
return
}
t.Fatalf("cannot launch a workspace: %q", err)
}
if test.ShouldFailToOpenRegularWorkspace {
t.Fatal("should failed on launch a workspace")
return
}

defer func() {
// stop workspace in defer function to prevent we forget to stop the workspace
if err := stopWorkspace(t, cfg, stopWs); err != nil {
t.Errorf("cannot stop workspace: %q", err)
}
}()

rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(),
integration.WithInstanceID(ws.Req.Id),
)
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
rsa.Close()
})
integration.DeferCloser(t, closer)

// checkPrebuildLogExist checks the prebuild log message exists
checkPrebuildLogExist(t, cfg, rsa, ws, test.WorkspaceRoot)

// check the files/folders permission under .git/ is not root
checkGitFolderPermission(t, rsa, test.WorkspaceRoot)
})
}
return ctx
}).
Feature()

testEnv.Test(t, f)
}

// checkPrebuildLogExist checks the prebuild log message exists
func checkPrebuildLogExist(t *testing.T, cfg *envconf.Config, rsa *rpc.Client, ws *integration.LaunchWorkspaceDirectlyResult, wsRoot string) {
// since the message '🤙 This task ran as a workspace prebuild' is generated by
// a prebuild workspace supervisor, so we add a retry mechanism to make sure that we
// won't check the message too earlier before the supervisor generated it.
var (
err error
grepResp agent.ExecResponse
checkPrebuildLog bool
)
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: prebuildLogPath,
Command: "bash",
Args: []string{
"-c",
fmt.Sprintf("grep %s *", prebuildLog),
},
}, &grepResp)
if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" {
checkPrebuildLog = true
}
if checkPrebuildLog {
return
}

t.Logf("cannot found the prebuild message %s in %s, err:%v, exitCode:%d, stdout:%s", prebuildLog, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)

// somehow, the prebuild log message '🤙 This task ran as a workspace prebuild' does not exists
// we fall back to check the the init task message within the /workspace/.gitpod/prebuild-log-* or not
var grepResp1 agent.ExecResponse
var checkInitTaskMsg bool
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: prebuildLogPath,
Command: "bash",
Args: []string{
"-c",
fmt.Sprintf("grep %q *", initTask),
},
}, &grepResp1)
if err == nil && grepResp1.ExitCode == 0 && strings.Trim(grepResp1.Stdout, " \t\n") != "" {
checkInitTaskMsg = true
}
if checkInitTaskMsg {
return
}

t.Logf("cannot found the init task message %s in %s, err:%v, exitCode:%d, stdout:%s", initTask, prebuildLogPath, err, grepResp.ExitCode, grepResp.Stdout)

// somehow, the init task message does not exist within the /workspace/.gitpod/prebuild-log-*
// we fall back to check the file exists or not
var ls agent.ListDirResponse
err = rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{
Dir: wsRoot,
}, &ls)
if err != nil {
t.Fatal(err)
}

var found bool
for _, f := range ls.Files {
if filepath.Base(f) == "someFile" {
found = true
break
}
}
if found {
return
}
t.Fatal("did not find someFile from previous workspace instance")
}

// checkGitFolderPermission checks the files/folders permission under .git/ is not root
func checkGitFolderPermission(t *testing.T, rsa *rpc.Client, workspaceRoot string) {
var findUserResp agent.ExecResponse
var gitDir string = fmt.Sprintf("%s/%s", workspaceRoot, ".git")

err := rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: gitDir,
Command: "find",
Args: []string{"-user", "root"},
}, &findUserResp)
if err != nil || findUserResp.ExitCode != 0 || strings.Trim(findUserResp.Stdout, " \t\n") != "" {
t.Fatalf("incorrect file perimssion under %s folder, err:%v, exitCode:%d, stdout:%s", gitDir, err, findUserResp.ExitCode, findUserResp.Stdout)
}

var findGroupResp agent.ExecResponse
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
Dir: gitDir,
Command: "find",
Args: []string{"-group", "root"},
}, &findGroupResp)
if err != nil || findGroupResp.ExitCode != 0 || strings.Trim(findGroupResp.Stdout, " \t\n") != "" {
t.Fatalf("incorrect group perimssion under %s folder, err:%v, exitCode:%d, stdout:%s", gitDir, err, findGroupResp.ExitCode, findGroupResp.Stdout)
}
}

func stopWorkspaceAndFindSnapshot(StopWorkspaceFunc integration.StopWorkspaceFunc, api *integration.ComponentAPI) (string, *wsmanapi.VolumeSnapshotInfo, error) {
lastStatus, err := StopWorkspaceFunc(true, api)
if err != nil {
Expand Down

0 comments on commit 129f9b4

Please sign in to comment.