Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/test/tests/workspace/process_limit_test.go
2498 views
1
// Copyright (c) 2023 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 workspace
6
7
import (
8
"context"
9
"errors"
10
"strings"
11
"testing"
12
"time"
13
14
agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api"
15
"github.com/gitpod-io/gitpod/test/pkg/integration"
16
wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"
17
"sigs.k8s.io/e2e-framework/pkg/envconf"
18
"sigs.k8s.io/e2e-framework/pkg/features"
19
)
20
21
func TestProcessLimit(t *testing.T) {
22
f := features.New("process limit").
23
WithLabel("component", "workspace").
24
WithLabel("type", "process limit").
25
Assess("it has a proc limit", func(testCtx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
26
t.Parallel()
27
28
ctx, cancel := context.WithTimeout(testCtx, time.Duration(5*time.Minute))
29
defer cancel()
30
31
api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())
32
t.Cleanup(func() {
33
api.Done(t)
34
})
35
36
nfo, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api)
37
if err != nil {
38
t.Fatal(err)
39
}
40
41
t.Cleanup(func() {
42
sctx, scancel := context.WithTimeout(context.Background(), 5*time.Minute)
43
defer scancel()
44
45
sapi := integration.NewComponentAPI(sctx, cfg.Namespace(), kubeconfig, cfg.Client())
46
defer sapi.Done(t)
47
48
if _, err = stopWs(true, sapi); err != nil {
49
t.Errorf("cannot stop workspace: %v", err)
50
}
51
})
52
53
rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(), integration.WithInstanceID(nfo.Req.Id))
54
integration.DeferCloser(t, closer)
55
if err != nil {
56
t.Fatalf("unexpected error instrumenting workspace: %v", err)
57
}
58
defer rsa.Close()
59
60
// Sometimes the workspace stops once we run out of processes (supervisor will exit with a failure),
61
// so also start watching for the workspace to stop and observe its exit status.
62
ready := make(chan struct{}, 1)
63
stopStatus := make(chan *wsmanapi.WorkspaceStatus, 1)
64
go func() {
65
status, err := integration.WaitForWorkspaceStop(t, ctx, ready, api, nfo.Req.Id, nfo.WorkspaceID, integration.WorkspaceCanFail)
66
if err != nil {
67
if !errors.Is(err, context.Canceled) {
68
// If context got canceled, we're just shutting down the test
69
// and the workspace didn't exit due to reaching the process limit.
70
t.Errorf("error waiting for workspace stop: %v", err)
71
}
72
stopStatus <- nil
73
return
74
}
75
76
t.Logf("workspace stopped: %v", stopStatus)
77
stopStatus <- status
78
}()
79
80
t.Logf("creating processes")
81
var res agent.ExecResponse
82
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
83
Dir: "/workspace",
84
Command: "bash",
85
Args: []string{"-c", "timeout 20s bash -c 'while true; do sleep 20 && date & done'"},
86
}, &res)
87
if err != nil {
88
t.Logf("exec failed, most likely the workspace failed due to the process limit, so check for workspace failure status instead. Exec err: %v", err)
89
select {
90
case <-ctx.Done():
91
t.Fatalf("expected workspace to stop, but it didn't")
92
case s := <-stopStatus:
93
if s == nil {
94
t.Fatalf("there was an error getting the workspace stop status")
95
}
96
97
if s.Conditions == nil || s.Conditions.Failed == "" {
98
t.Fatalf("expected workspace to fail, but it didn't: %v", s)
99
}
100
t.Logf("workspace stopped and failed (as expected): %v", s)
101
}
102
return testCtx
103
}
104
105
t.Logf("checking output for fork errors due to process limiting")
106
if !strings.Contains(res.Stdout, "bash: fork: retry: Resource temporarily unavailable") {
107
t.Errorf("expected fork error (Resource temporarily unavailable), but got none (%d): %s", res.ExitCode, res.Stdout)
108
}
109
110
return testCtx
111
}).
112
Feature()
113
114
testEnv.Test(t, f)
115
}
116
117