Path: blob/main/test/tests/components/ws-manager/tasks_test.go
2500 views
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package wsmanager56import (7"context"8"encoding/json"9"fmt"10"testing"11"time"1213csapi "github.com/gitpod-io/gitpod/content-service/api"14gitpod "github.com/gitpod-io/gitpod/gitpod-protocol"15supervisorapi "github.com/gitpod-io/gitpod/supervisor/api"16agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api"17"github.com/gitpod-io/gitpod/test/pkg/integration"18wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"19"sigs.k8s.io/e2e-framework/pkg/envconf"20"sigs.k8s.io/e2e-framework/pkg/features"21)2223func TestRegularWorkspaceTasks(t *testing.T) {24testRepo := "https://github.com/gitpod-io/empty"25testRepoName := "empty"26wsLoc := fmt.Sprintf("/workspace/%s", testRepoName)27tests := []struct {28Name string29Task []gitpod.TasksItems30LookForFile []string31FF []wsmanapi.WorkspaceFeatureFlag32}{33{34Name: "classic",35Task: []gitpod.TasksItems{36{Init: fmt.Sprintf("touch %s/init-ran; exit", wsLoc)},37{Before: fmt.Sprintf("touch %s/before-ran; exit", wsLoc)},38{Command: fmt.Sprintf("touch %s/command-ran; exit", wsLoc)},39},40LookForFile: []string{"init-ran", "before-ran", "command-ran"},41},42}4344f := features.New("ws-manager").45WithLabel("component", "ws-manager").46WithLabel("type", "tasks").47Assess("it can run workspace tasks", func(testCtx context.Context, t *testing.T, cfg *envconf.Config) context.Context {48for _, test := range tests {49test := test50t.Run(test.Name, func(t *testing.T) {51t.Parallel()5253ctx, cancel := context.WithTimeout(testCtx, time.Duration(5*len(tests))*time.Minute)54defer cancel()5556api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())57t.Cleanup(func() {58api.Done(t)59})6061addInitTask := func(swr *wsmanapi.StartWorkspaceRequest) error {62tasks, err := json.Marshal(test.Task)63if err != nil {64return err65}66swr.Spec.Envvars = append(swr.Spec.Envvars, &wsmanapi.EnvironmentVariable{67Name: "GITPOD_TASKS",68Value: string(tasks),69})70swr.Spec.FeatureFlags = test.FF71swr.Spec.Initializer = &csapi.WorkspaceInitializer{72Spec: &csapi.WorkspaceInitializer_Git{73Git: &csapi.GitInitializer{74RemoteUri: testRepo,75CheckoutLocation: testRepoName,76Config: &csapi.GitConfig{},77},78},79}80swr.Spec.WorkspaceLocation = testRepoName81return nil82}8384// TODO: change to use server API to launch the workspace, so we could run the integration test as the user code flow85// which is client -> server -> ws-manager rather than client -> ws-manager directly86nfo, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(addInitTask))87if err != nil {88t.Fatal(err)89}9091t.Cleanup(func() {92sctx, scancel := context.WithTimeout(context.Background(), 5*time.Minute)93defer scancel()9495sapi := integration.NewComponentAPI(sctx, cfg.Namespace(), kubeconfig, cfg.Client())96defer sapi.Done(t)9798if _, err = stopWs(true, sapi); err != nil {99t.Errorf("cannot stop workspace: %q", err)100}101})102103rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(), integration.WithInstanceID(nfo.Req.Id))104integration.DeferCloser(t, closer)105if err != nil {106t.Fatalf("unexpected error instrumenting workspace: %v", err)107}108defer rsa.Close()109110var parsedResp struct {111Result struct {112Tasks []*struct {113State string `json:"state,omitempty"`114} `json:"tasks,omitempty"`115} `json:"result"`116}117supervisorTaskStatusCompleted := false118for i := 1; i < 10; i++ {119var res agent.ExecResponse120err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{121Dir: wsLoc,122Command: "curl",123// nftable rule only forwards to this ip address124Args: []string{"10.0.5.2:22999/_supervisor/v1/status/tasks"},125}, &res)126if err != nil {127t.Fatal(err)128}129err = json.Unmarshal([]byte(res.Stdout), &parsedResp)130if err != nil {131t.Fatalf("cannot decode supervisor status response: %s", err)132}133134if len(parsedResp.Result.Tasks) != len(test.Task) {135t.Fatalf("expected one task to run, but got %d", len(parsedResp.Result.Tasks))136}137if parsedResp.Result.Tasks[0].State == supervisorapi.TaskState_name[int32(supervisorapi.TaskState_closed)] {138supervisorTaskStatusCompleted = true139break140}141// sleep before next attempt hoping that the task completed meanwhile142time.Sleep(6 * time.Second)143}144if !supervisorTaskStatusCompleted {145t.Fatal("tasks did not complete in time")146}147148var ls agent.ListDirResponse149err = rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{150Dir: wsLoc,151}, &ls)152if err != nil {153t.Fatal(err)154}155156for _, lff := range test.LookForFile {157var foundMaker bool158for _, f := range ls.Files {159if f == lff {160foundMaker = true161break162}163}164if !foundMaker {165t.Fatalf("task seems to have run, but cannot find %s it should have created", lff)166}167}168})169}170171return testCtx172}).173Feature()174175testEnv.Test(t, f)176}177178179