Skip to content

Commit 1ac4bf8

Browse files
milantracygvisor-bot
authored andcommitted
Add tests that run docker exec command in gvisor.
PiperOrigin-RevId: 775593936
1 parent ca812bc commit 1ac4bf8

File tree

1 file changed

+143
-18
lines changed

1 file changed

+143
-18
lines changed

test/image/image_test.go

Lines changed: 143 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -405,50 +405,82 @@ func dockerInGvisorCapabilities() []string {
405405
}
406406

407407
func TestDockerOverlayWithHostNetwork(t *testing.T) {
408-
testDocker(t, true, true, false)
408+
ctx := context.Background()
409+
d := startDockerdInGvisor(ctx, t, true)
410+
defer d.CleanUp(ctx)
411+
testDockerBuild(ctx, t, d, true)
412+
testDockerRun(ctx, t, d, true, false)
413+
testDockerExec(ctx, t, d, false)
409414
}
410415

411416
func TestPrivilegedDockerOverlayWithHostNetwork(t *testing.T) {
412-
testDocker(t, true, true, true)
417+
ctx := context.Background()
418+
d := startDockerdInGvisor(ctx, t, true)
419+
defer d.CleanUp(ctx)
420+
testDockerRun(ctx, t, d, true, true)
421+
testDockerExec(ctx, t, d, true)
413422
}
414423

415424
func TestDockerOverlay(t *testing.T) {
416-
testDocker(t, true, false, false)
425+
ctx := context.Background()
426+
d := startDockerdInGvisor(ctx, t, true)
427+
defer d.CleanUp(ctx)
428+
testDockerBuild(ctx, t, d, false)
429+
testDockerRun(ctx, t, d, false, false)
430+
testDockerExec(ctx, t, d, false)
417431
}
418432

419433
func TestPrivilegedDockerOverlay(t *testing.T) {
420-
testDocker(t, true, false, true)
434+
ctx := context.Background()
435+
d := startDockerdInGvisor(ctx, t, true)
436+
defer d.CleanUp(ctx)
437+
testDockerRun(ctx, t, d, false, true)
438+
testDockerExec(ctx, t, d, true)
421439
}
422440

423441
func TestDockerWithHostNetwork(t *testing.T) {
424-
testDocker(t, false, true, false)
442+
ctx := context.Background()
443+
d := startDockerdInGvisor(ctx, t, false)
444+
defer d.CleanUp(ctx)
445+
testDockerBuild(ctx, t, d, true)
446+
testDockerRun(ctx, t, d, true, false)
447+
testDockerExec(ctx, t, d, false)
425448
}
426449

427450
func TestPrivilegedDockerWithHostNetwork(t *testing.T) {
428-
testDocker(t, false, true, true)
451+
ctx := context.Background()
452+
d := startDockerdInGvisor(ctx, t, false)
453+
defer d.CleanUp(ctx)
454+
testDockerRun(ctx, t, d, true, true)
455+
testDockerExec(ctx, t, d, true)
429456
}
430457

431458
func TestDocker(t *testing.T) {
459+
ctx := context.Background()
460+
d := startDockerdInGvisor(ctx, t, false)
461+
defer d.CleanUp(ctx)
462+
testDockerBuild(ctx, t, d, false)
432463
// Overlayfs can't be built on top of another overlayfs, so docket has
433464
// to fall back to the vfs driver.
434-
testDocker(t, false, false, false)
465+
testDockerRun(ctx, t, d, false, false)
466+
testDockerExec(ctx, t, d, false)
435467
}
436468

437469
func TestPrivilegedDocker(t *testing.T) {
470+
ctx := context.Background()
471+
d := startDockerdInGvisor(ctx, t, true)
472+
defer d.CleanUp(ctx)
438473
// Overlayfs can't be built on top of another overlayfs, so docket has
439474
// to fall back to the vfs driver.
440-
testDocker(t, false, false, true)
475+
testDockerRun(ctx, t, d, false, true)
476+
testDockerExec(ctx, t, d, true)
441477
}
442478

443-
func testDocker(t *testing.T, overlay, hostNetwork, startPrivilegedContainer bool) {
444-
if testutil.IsRunningWithHostNet() {
445-
t.Skip("docker doesn't work with hostinet")
446-
}
447-
ctx := context.Background()
479+
// The container returned by this function has to be cleaned up by the caller.
480+
func startDockerdInGvisor(ctx context.Context, t *testing.T, overlay bool) *dockerutil.Container {
448481
d := dockerutil.MakeContainerWithRuntime(ctx, t, "-docker")
449-
defer d.CleanUp(ctx)
450482

451-
// Start the container.
483+
// Start the container which starts dockerd.
452484
opts := dockerutil.RunOpts{
453485
Image: "basic/docker",
454486
CapAdd: dockerInGvisorCapabilities(),
@@ -477,27 +509,120 @@ func testDocker(t *testing.T, overlay, hostNetwork, startPrivilegedContainer boo
477509
}
478510
// Wait for the docker daemon.
479511
for i := 0; i < 10; i++ {
480-
output, err := d.Exec(ctx, dockerutil.ExecOpts{}, "docker", "info")
481-
t.Logf("== docker info ==\n%s", output)
512+
_, err := d.Exec(ctx, dockerutil.ExecOpts{}, "docker", "info")
482513
if err != nil {
483514
t.Logf("docker exec failed: %v", err)
484515
time.Sleep(5 * time.Second)
485516
continue
486517
}
487518
break
488519
}
520+
return d
521+
}
522+
523+
func testDockerRun(ctx context.Context, t *testing.T, d *dockerutil.Container, hostNetwork, startPrivilegedContainer bool) {
524+
if testutil.IsRunningWithHostNet() {
525+
t.Skip("docker doesn't work with hostinet")
526+
}
489527
cmd := []string{"docker", "run", "--rm"}
490528
if hostNetwork {
491529
cmd = append(cmd, "--network", "host")
492530
}
493531
if startPrivilegedContainer {
494532
cmd = append(cmd, "--privileged")
495533
}
496-
cmd = append(cmd, "alpine", "sh", "-c", "apk add curl && curl -h")
534+
cmd = append(cmd, "alpine", "sh", "-c", "apk add curl && apk info -d curl")
535+
execProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, cmd...)
536+
if err != nil {
537+
t.Fatalf("docker exec failed: %v", err)
538+
}
539+
output, err := execProc.Logs()
540+
if err != nil {
541+
t.Fatalf("docker logs failed: %v", err)
542+
}
543+
expectedOutput := "URL retrival utility and library"
544+
if !strings.Contains(output, expectedOutput) {
545+
t.Fatalf("docker didn't get output expected: %q, got: %q", expectedOutput, output)
546+
}
547+
}
548+
549+
func testDockerBuild(ctx context.Context, t *testing.T, d *dockerutil.Container, hostNetwork bool) {
550+
if testutil.IsRunningWithHostNet() {
551+
t.Skip("docker doesn't work with hostinet")
552+
}
553+
cmd := []string{"echo", "-e", "FROM alpine:3.19\nRUN apk add git", "|", "docker", "build"}
554+
if hostNetwork {
555+
cmd = append(cmd, "--network", "host")
556+
}
557+
imageName := "test_docker_build_in_gvisor"
558+
cmd = append(cmd, "-t", imageName, "-f", "-", ".")
559+
_, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, cmd...)
560+
if err != nil {
561+
t.Fatalf("docker exec failed: %v", err)
562+
}
563+
inspectImage, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, []string{"docker", "image", "inspect", imageName}...)
564+
if err != nil {
565+
t.Fatalf("docker exec failed: %v", err)
566+
}
567+
got, err := inspectImage.Logs()
568+
if err != nil {
569+
t.Fatalf("docker logs failed: %v", err)
570+
}
571+
output := imageName + ":latest"
572+
if !strings.Contains(got, output) {
573+
t.Fatalf("docker didn't get output expected: %q, got: %q", output, got)
574+
}
575+
}
576+
577+
func testDockerExec(ctx context.Context, t *testing.T, d *dockerutil.Container, privileged bool) {
578+
if testutil.IsRunningWithHostNet() {
579+
t.Skip("docker doesn't work with hostinet")
580+
}
581+
containerName := "test_docker_exec"
582+
// TODO(b/425970478): Remove host pidns once setns pidns is supported.
583+
// Start a container with a sleep command to ensure that the container
584+
// doesn't exit immediately.
585+
cmd := []string{"docker", "run", "--rm", "-d", "--pid", "host", "--name", containerName, "alpine", "sleep", "180"}
497586
_, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, cmd...)
587+
if err != nil {
588+
t.Fatalf("docker run failed: %v", err)
589+
}
590+
591+
for i := 0; i < 10; i++ {
592+
inspectProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, []string{"docker", "container", "inspect", containerName}...)
593+
if err != nil {
594+
t.Fatalf("docker container inspect failed: %v", err)
595+
}
596+
inspectOutput, err := inspectProc.Logs()
597+
if err != nil {
598+
t.Fatalf("docker logs failed: %v", err)
599+
}
600+
if strings.Contains(inspectOutput, "\"Status\": \"running\"") {
601+
break
602+
}
603+
t.Logf("docker container inspect output: %q", inspectOutput)
604+
time.Sleep(5 * time.Second)
605+
}
606+
607+
execCmd := []string{"docker", "exec"}
608+
if privileged {
609+
execCmd = append(execCmd, "--privileged")
610+
}
611+
// Execute echo command in the container.
612+
execCmd = append(execCmd, containerName, "echo", "exec in "+containerName)
613+
execProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, execCmd...)
498614
if err != nil {
499615
t.Fatalf("docker exec failed: %v", err)
500616
}
617+
618+
output, err := execProc.Logs()
619+
if err != nil {
620+
t.Fatalf("docker logs failed: %v", err)
621+
}
622+
expectedOutput := "exec in " + containerName
623+
if !strings.Contains(output, expectedOutput) {
624+
t.Fatalf("docker didn't get output expected: %q, got: %q", expectedOutput, output)
625+
}
501626
}
502627

503628
func TestMain(m *testing.M) {

0 commit comments

Comments
 (0)