Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/test/tests/components/ws-manager/tasks_test.go
2500 views
1
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package wsmanager
6
7
import (
8
"context"
9
"encoding/json"
10
"fmt"
11
"testing"
12
"time"
13
14
csapi "github.com/gitpod-io/gitpod/content-service/api"
15
gitpod "github.com/gitpod-io/gitpod/gitpod-protocol"
16
supervisorapi "github.com/gitpod-io/gitpod/supervisor/api"
17
agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api"
18
"github.com/gitpod-io/gitpod/test/pkg/integration"
19
wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"
20
"sigs.k8s.io/e2e-framework/pkg/envconf"
21
"sigs.k8s.io/e2e-framework/pkg/features"
22
)
23
24
func TestRegularWorkspaceTasks(t *testing.T) {
25
testRepo := "https://github.com/gitpod-io/empty"
26
testRepoName := "empty"
27
wsLoc := fmt.Sprintf("/workspace/%s", testRepoName)
28
tests := []struct {
29
Name string
30
Task []gitpod.TasksItems
31
LookForFile []string
32
FF []wsmanapi.WorkspaceFeatureFlag
33
}{
34
{
35
Name: "classic",
36
Task: []gitpod.TasksItems{
37
{Init: fmt.Sprintf("touch %s/init-ran; exit", wsLoc)},
38
{Before: fmt.Sprintf("touch %s/before-ran; exit", wsLoc)},
39
{Command: fmt.Sprintf("touch %s/command-ran; exit", wsLoc)},
40
},
41
LookForFile: []string{"init-ran", "before-ran", "command-ran"},
42
},
43
}
44
45
f := features.New("ws-manager").
46
WithLabel("component", "ws-manager").
47
WithLabel("type", "tasks").
48
Assess("it can run workspace tasks", func(testCtx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
49
for _, test := range tests {
50
test := test
51
t.Run(test.Name, func(t *testing.T) {
52
t.Parallel()
53
54
ctx, cancel := context.WithTimeout(testCtx, time.Duration(5*len(tests))*time.Minute)
55
defer cancel()
56
57
api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())
58
t.Cleanup(func() {
59
api.Done(t)
60
})
61
62
addInitTask := func(swr *wsmanapi.StartWorkspaceRequest) error {
63
tasks, err := json.Marshal(test.Task)
64
if err != nil {
65
return err
66
}
67
swr.Spec.Envvars = append(swr.Spec.Envvars, &wsmanapi.EnvironmentVariable{
68
Name: "GITPOD_TASKS",
69
Value: string(tasks),
70
})
71
swr.Spec.FeatureFlags = test.FF
72
swr.Spec.Initializer = &csapi.WorkspaceInitializer{
73
Spec: &csapi.WorkspaceInitializer_Git{
74
Git: &csapi.GitInitializer{
75
RemoteUri: testRepo,
76
CheckoutLocation: testRepoName,
77
Config: &csapi.GitConfig{},
78
},
79
},
80
}
81
swr.Spec.WorkspaceLocation = testRepoName
82
return nil
83
}
84
85
// TODO: change to use server API to launch the workspace, so we could run the integration test as the user code flow
86
// which is client -> server -> ws-manager rather than client -> ws-manager directly
87
nfo, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(addInitTask))
88
if err != nil {
89
t.Fatal(err)
90
}
91
92
t.Cleanup(func() {
93
sctx, scancel := context.WithTimeout(context.Background(), 5*time.Minute)
94
defer scancel()
95
96
sapi := integration.NewComponentAPI(sctx, cfg.Namespace(), kubeconfig, cfg.Client())
97
defer sapi.Done(t)
98
99
if _, err = stopWs(true, sapi); err != nil {
100
t.Errorf("cannot stop workspace: %q", err)
101
}
102
})
103
104
rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(), integration.WithInstanceID(nfo.Req.Id))
105
integration.DeferCloser(t, closer)
106
if err != nil {
107
t.Fatalf("unexpected error instrumenting workspace: %v", err)
108
}
109
defer rsa.Close()
110
111
var parsedResp struct {
112
Result struct {
113
Tasks []*struct {
114
State string `json:"state,omitempty"`
115
} `json:"tasks,omitempty"`
116
} `json:"result"`
117
}
118
supervisorTaskStatusCompleted := false
119
for i := 1; i < 10; i++ {
120
var res agent.ExecResponse
121
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
122
Dir: wsLoc,
123
Command: "curl",
124
// nftable rule only forwards to this ip address
125
Args: []string{"10.0.5.2:22999/_supervisor/v1/status/tasks"},
126
}, &res)
127
if err != nil {
128
t.Fatal(err)
129
}
130
err = json.Unmarshal([]byte(res.Stdout), &parsedResp)
131
if err != nil {
132
t.Fatalf("cannot decode supervisor status response: %s", err)
133
}
134
135
if len(parsedResp.Result.Tasks) != len(test.Task) {
136
t.Fatalf("expected one task to run, but got %d", len(parsedResp.Result.Tasks))
137
}
138
if parsedResp.Result.Tasks[0].State == supervisorapi.TaskState_name[int32(supervisorapi.TaskState_closed)] {
139
supervisorTaskStatusCompleted = true
140
break
141
}
142
// sleep before next attempt hoping that the task completed meanwhile
143
time.Sleep(6 * time.Second)
144
}
145
if !supervisorTaskStatusCompleted {
146
t.Fatal("tasks did not complete in time")
147
}
148
149
var ls agent.ListDirResponse
150
err = rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{
151
Dir: wsLoc,
152
}, &ls)
153
if err != nil {
154
t.Fatal(err)
155
}
156
157
for _, lff := range test.LookForFile {
158
var foundMaker bool
159
for _, f := range ls.Files {
160
if f == lff {
161
foundMaker = true
162
break
163
}
164
}
165
if !foundMaker {
166
t.Fatalf("task seems to have run, but cannot find %s it should have created", lff)
167
}
168
}
169
})
170
}
171
172
return testCtx
173
}).
174
Feature()
175
176
testEnv.Test(t, f)
177
}
178
179