diff --git a/test/tests/components/ws-manager/prebuild_test.go b/test/tests/components/ws-manager/prebuild_test.go index ad0b6d1a445ba3..4085949842c6e5 100644 --- a/test/tests/components/ws-manager/prebuild_test.go +++ b/test/tests/components/ws-manager/prebuild_test.go @@ -180,8 +180,22 @@ func TestPrebuildWorkspaceTaskFail(t *testing.T) { const ( prebuildLogPath string = "/workspace/.gitpod" prebuildLog string = "'🤙 This task ran as a workspace prebuild'" + initTask string = "echo \"some output\" > someFile; sleep 90;" ) +// TestOpenWorkspaceFromPrebuild +// - create a prebuild +// - open the workspace from prebuild +// - make sure the .git/ folder with correct permission +// - make sure either one of the condition mets +// - the prebuild log message exists +// - the init task message exists +// - the init task generated file exists +// +// - write a new file foobar.txt +// - stop the workspace +// - relaunch the workspace +// - make sure the file foobar.txt exists func TestOpenWorkspaceFromPrebuild(t *testing.T) { f := features.New("prebuild"). WithLabel("component", "ws-manager"). @@ -223,7 +237,7 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) { req.Type = wsmanapi.WorkspaceType_PREBUILD req.Spec.Envvars = append(req.Spec.Envvars, &wsmanapi.EnvironmentVariable{ Name: "GITPOD_TASKS", - Value: `[{ "init": "echo \"some output\" > someFile; sleep 60; exit 0;" }]`, + Value: fmt.Sprintf(`[{ "init": %q }]`, initTask), }) req.Spec.FeatureFlags = test.FF req.Spec.Initializer = &csapi.WorkspaceInitializer{ @@ -248,6 +262,7 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) { if err != nil { t.Fatalf("stop workspace and find snapshot error: %v", err) } + t.Logf("prebuild snapshot: %s, vsName: %s, vsHandle: %s", prebuildSnapshot, vsInfo.VolumeSnapshotName, vsInfo.VolumeSnapshotHandle) // launch the workspace from prebuild ws, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error { @@ -298,8 +313,11 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) { integration.DeferCloser(t, closer) // check prebuild log message exists - var resp agent.ExecResponse - var checkPrebuildSuccess bool + // 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, @@ -308,26 +326,89 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) { "-c", fmt.Sprintf("grep %s *", prebuildLog), }, - }, &resp) - if err == nil && resp.ExitCode == 0 && strings.Trim(resp.Stdout, " \t\n") != "" { - checkPrebuildSuccess = true + }, &grepResp) + if err == nil && grepResp.ExitCode == 0 && strings.Trim(grepResp.Stdout, " \t\n") != "" { + checkPrebuildLog = true break } - - // wait 3 seconds and check + t.Logf("[%d] retry...", i) time.Sleep(3 * time.Second) } - if !checkPrebuildSuccess { - t.Fatalf("cannot found the prebuild message %s in %s, err:%v, exitCode:%d, stdout:%s", prebuildLog, prebuildLogPath, err, resp.ExitCode, resp.Stdout) + 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") + } + } + } + + // 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) } // write file foobar.txt and stop the workspace + var writeFileResp agent.ExecResponse err = rsa.Call("WorkspaceAgent.WriteFile", &agent.WriteFileRequest{ Path: fmt.Sprintf("%s/foobar.txt", test.WorkspaceRoot), Content: []byte("hello world"), Mode: 0644, - }, &resp) + }, &writeFileResp) if err != nil { t.Fatalf("cannot write file %s", fmt.Sprintf("%s/foobar.txt", test.WorkspaceRoot)) } @@ -343,6 +424,7 @@ func TestOpenWorkspaceFromPrebuild(t *testing.T) { if err != nil { t.Fatal(err) } + t.Logf("vsName: %s, vsHandle: %s", vsInfo.VolumeSnapshotName, vsInfo.VolumeSnapshotHandle) // reopen the workspace and make sure the file foobar.txt exists ws1, stopWs1, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(req *wsmanapi.StartWorkspaceRequest) error { @@ -414,7 +496,7 @@ func stopWorkspaceAndFindSnapshot(StopWorkspaceFunc integration.StopWorkspaceFun if err != nil { return "", nil, err } - if lastStatus == nil && lastStatus.Conditions == nil { + if lastStatus == nil || lastStatus.Conditions == nil || lastStatus.Conditions.VolumeSnapshot == nil { return "", nil, nil } return lastStatus.Conditions.Snapshot, lastStatus.Conditions.VolumeSnapshot, nil