Skip to content

Commit c01e080

Browse files
committed
[tests] Add integration tests for docker
1 parent dc15065 commit c01e080

File tree

5 files changed

+126
-1
lines changed

5 files changed

+126
-1
lines changed

test/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ require (
1212
github.com/gitpod-io/gitpod/ws-manager/api v0.0.0-00010101000000-000000000000
1313
github.com/go-sql-driver/mysql v1.5.0
1414
github.com/google/uuid v1.2.0
15+
github.com/prometheus/procfs v0.7.3 // indirect
1516
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
17+
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
1618
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
1719
google.golang.org/grpc v1.39.1
1820
k8s.io/api v0.22.0

test/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
650650
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
651651
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
652652
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
653+
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
654+
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
653655
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
654656
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
655657
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=

test/pkg/integration/agent.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ import (
1313
"net/rpc"
1414
"os"
1515
"os/signal"
16+
"strconv"
1617
"syscall"
1718
)
1819

1920
// ServeAgent is the main entrypoint for agents. It establishes flags and starts an RPC server
2021
// on a port passed as flag.
2122
func ServeAgent(rcvr interface{}) {
22-
port := flag.Int("rpc-port", 0, "the port on wich to run the RPC server on")
23+
defaultPort, _ := strconv.Atoi(os.Getenv("AGENT_RPC_PORT"))
24+
port := flag.Int("rpc-port", defaultPort, "the port on wich to run the RPC server on")
2325
flag.Parse()
2426

2527
ta := &testAgent{

test/tests/workspace/docker_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2021 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_test
6+
7+
import (
8+
"testing"
9+
"time"
10+
11+
"github.com/gitpod-io/gitpod/test/pkg/integration"
12+
agent "github.com/gitpod-io/gitpod/test/tests/workspace/workspace_agent/api"
13+
)
14+
15+
func TestRunDocker(t *testing.T) {
16+
it, _ := integration.NewTest(t, 5*time.Minute)
17+
defer it.Done()
18+
19+
ws := integration.LaunchWorkspaceDirectly(it)
20+
instanceID := ws.Req.Id
21+
defer integration.DeleteWorkspace(it, ws.Req.Id)
22+
23+
rsa, err := it.Instrument(integration.ComponentWorkspace, "workspace", integration.WithInstanceID(instanceID), integration.WithWorkspacekitLift(true))
24+
if err != nil {
25+
t.Error(err)
26+
return
27+
}
28+
defer rsa.Close()
29+
30+
var resp agent.ExecResponse
31+
err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{
32+
Dir: "/",
33+
Command: "bash",
34+
Args: []string{
35+
"-c",
36+
"docker run --rm alpine:latest",
37+
},
38+
}, &resp)
39+
if err != nil {
40+
t.Errorf("docker run failed: %v\n%s\n%s", err, resp.Stdout, resp.Stderr)
41+
return
42+
}
43+
44+
if resp.ExitCode != 0 {
45+
t.Errorf("docker run failed: %s\n%s", resp.Stdout, resp.Stderr)
46+
return
47+
}
48+
}

test/tests/workspace/workspace_agent/main.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,88 @@ package main
77
import (
88
"bytes"
99
"fmt"
10+
"io"
1011
"os"
1112
"os/exec"
13+
"strconv"
1214
"strings"
1315

1416
"github.com/gitpod-io/gitpod/test/pkg/integration"
1517
"github.com/gitpod-io/gitpod/test/tests/workspace/workspace_agent/api"
18+
"github.com/prometheus/procfs"
19+
"golang.org/x/sys/unix"
1620
)
1721

1822
func main() {
23+
err := enterSupervisorNamespaces()
24+
if err != nil {
25+
panic(fmt.Sprintf("enterSupervisorNamespaces: %v", err))
26+
}
27+
1928
integration.ServeAgent(new(WorkspaceAgent))
2029
}
2130

31+
func enterSupervisorNamespaces() error {
32+
if os.Getenv("AGENT_IN_RING2") != "" {
33+
return nil
34+
}
35+
36+
nsenter, err := exec.LookPath("nsenter")
37+
if err != nil {
38+
return fmt.Errorf("cannot find nsenter")
39+
}
40+
41+
// This agent expectes to be called using the workspacekit lift (i.e. in ring1).
42+
// We then enter the PID and mount namespace of supervisor.
43+
// First, we need to find the supervisor process
44+
proc, err := procfs.NewFS("/proc")
45+
if err != nil {
46+
return err
47+
}
48+
procs, err := proc.AllProcs()
49+
if err != nil {
50+
return err
51+
}
52+
var supervisorPID int
53+
for _, p := range procs {
54+
cmd, _ := p.CmdLine()
55+
for _, c := range cmd {
56+
if strings.HasSuffix(c, "supervisor") {
57+
supervisorPID = p.PID
58+
break
59+
}
60+
}
61+
if supervisorPID != 0 {
62+
break
63+
}
64+
}
65+
if supervisorPID == 0 {
66+
return fmt.Errorf("no supervisor process found")
67+
}
68+
69+
// Then we copy ourselves to a location that we can access from the supervisor NS
70+
self, err := os.Executable()
71+
if err != nil {
72+
return err
73+
}
74+
fn := fmt.Sprintf("/proc/%d/root/agent", supervisorPID)
75+
dst, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, 0755)
76+
if err != nil {
77+
return err
78+
}
79+
selfFD, err := os.Open(self)
80+
if err != nil {
81+
return err
82+
}
83+
defer selfFD.Close()
84+
_, err = io.Copy(dst, selfFD)
85+
if err != nil {
86+
return fmt.Errorf("error copying agent: %w", err)
87+
}
88+
89+
return unix.Exec(nsenter, append([]string{nsenter, "-t", strconv.Itoa(supervisorPID), "-m", "-p", "/agent"}, os.Args[1:]...), append(os.Environ(), "AGENT_IN_RING2=true"))
90+
}
91+
2292
// WorkspaceAgent provides ingteration test services from within a workspace
2393
type WorkspaceAgent struct {
2494
}
@@ -70,6 +140,7 @@ func (*WorkspaceAgent) Exec(req *api.ExecRequest, resp *api.ExecResponse) (err e
70140
return fmt.Errorf("%s: %w", fullCommand, err)
71141
}
72142
rc = exitError.ExitCode()
143+
err = nil
73144
}
74145

75146
*resp = api.ExecResponse{

0 commit comments

Comments
 (0)