Skip to content

Commit 88e36f6

Browse files
milantracygvisor-bot
authored andcommitted
Deflake docker in gVisor docker tests.
The docker client uses in the tests can catch the docker errors for commands on the host's docker. However, when we start docker daemon inside a docker container, the client can't catch the failure from the nested error message from the docker daemon running inside. To deflake the test, we always retry until we can get expected output from execution logs in the command or timeout. PiperOrigin-RevId: 825263678
1 parent 9095071 commit 88e36f6

File tree

1 file changed

+43
-30
lines changed

1 file changed

+43
-30
lines changed

test/image/image_test.go

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,18 @@ func removeDockerImage(ctx context.Context, imageName string, d *dockerutil.Cont
599599
return nil
600600
}
601601

602+
func dockerInGvisorExecOutput(ctx context.Context, d *dockerutil.Container, cmd []string) (string, error) {
603+
execProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, cmd...)
604+
if err != nil {
605+
return "", fmt.Errorf("docker exec failed: %v", err)
606+
}
607+
output, err := execProc.Logs()
608+
if err != nil {
609+
return "", fmt.Errorf("docker logs failed: %v", err)
610+
}
611+
return output, nil
612+
}
613+
602614
func testDockerRun(ctx context.Context, t *testing.T, d *dockerutil.Container, opts dockerCommandOptions) {
603615
cmd := []string{"docker", "run", "--rm"}
604616
if opts.hostNetwork {
@@ -608,35 +620,44 @@ func testDockerRun(ctx context.Context, t *testing.T, d *dockerutil.Container, o
608620
cmd = append(cmd, "--privileged")
609621
}
610622
cmd = append(cmd, testAlpineImage, "sh", "-c", "apk add curl && apk info -d curl")
611-
execProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, cmd...)
612-
if err != nil {
613-
t.Fatalf("docker exec failed: %v", err)
614-
}
615-
output, err := execProc.Logs()
616-
if err != nil {
617-
t.Fatalf("docker logs failed: %v", err)
618-
}
623+
619624
expectedOutput := "URL retrival utility and library"
620-
if !strings.Contains(output, expectedOutput) {
621-
t.Fatalf("docker didn't get output expected: %q, got: %q", expectedOutput, output)
625+
output := ""
626+
for i := 0; i < 5; i++ {
627+
var err error
628+
output, err = dockerInGvisorExecOutput(ctx, d, cmd)
629+
if err != nil {
630+
t.Fatalf("docker exec failed: %v", err)
631+
}
632+
if strings.Contains(output, expectedOutput) {
633+
// The test passed, no more retries needed.
634+
return
635+
}
636+
time.Sleep(1 * time.Second)
622637
}
638+
t.Fatalf("docker didn't get output expected: %q, got: %q", expectedOutput, output)
623639
}
624640

625641
func testDockerBuild(ctx context.Context, t *testing.T, d *dockerutil.Container, opts dockerCommandOptions) {
626-
parts := []string{"echo", fmt.Sprintf("\"FROM %s\nRUN apk add git\"", testAlpineImage), "|", "docker", "build"}
642+
dockerfileRunCommand := "RUN apk add git"
643+
parts := []string{"echo", fmt.Sprintf("\"FROM %s\n%s\"", testAlpineImage, dockerfileRunCommand), "|", "docker", "build"}
627644
if opts.hostNetwork {
628645
parts = append(parts, "--network", "host")
629646
}
630647
imageName := strings.ToLower(strings.ReplaceAll(testutil.RandomID("test_docker_build"), "/", "-"))
631648
parts = append(parts, "-t", imageName, "-f", "-", ".")
632649
cmd := strings.Join(parts, " ")
633-
dockerBuildProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, "/bin/sh", "-c", cmd)
634-
if err != nil {
635-
t.Fatalf("docker exec failed: %v", err)
636-
}
637-
_, err = dockerBuildProc.Logs()
638-
if err != nil {
639-
t.Fatalf("docker logs failed: %v", err)
650+
for i := 0; i < 5; i++ {
651+
buildOutput, err := dockerInGvisorExecOutput(ctx, d, []string{"/bin/sh", "-c", cmd})
652+
if err != nil {
653+
t.Fatalf("docker exec failed: %v", err)
654+
}
655+
// The docker build output should container the Dockerfile's RUN commands.
656+
if strings.Contains(buildOutput, dockerfileRunCommand) {
657+
// The test passed, no more retries needed.
658+
break
659+
}
660+
time.Sleep(1 * time.Second)
640661
}
641662
defer removeDockerImage(ctx, imageName, d)
642663
if err := checkDockerImage(ctx, imageName, d); err != nil {
@@ -662,13 +683,9 @@ func testDockerExec(ctx context.Context, t *testing.T, d *dockerutil.Container,
662683
}()
663684

664685
for i := 0; i < 10; i++ {
665-
inspectProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, []string{"docker", "container", "inspect", containerName}...)
666-
if err != nil {
667-
t.Fatalf("docker container inspect failed: %v", err)
668-
}
669-
inspectOutput, err := inspectProc.Logs()
686+
inspectOutput, err := dockerInGvisorExecOutput(ctx, d, []string{"docker", "container", "inspect", containerName})
670687
if err != nil {
671-
t.Fatalf("docker logs failed: %v", err)
688+
t.Fatalf("docker exec failed: %v", err)
672689
}
673690
if strings.Contains(inspectOutput, "\"Status\": \"running\"") {
674691
break
@@ -682,14 +699,10 @@ func testDockerExec(ctx context.Context, t *testing.T, d *dockerutil.Container,
682699
}
683700
// Execute echo command in the container.
684701
execCmd = append(execCmd, containerName, "echo", "exec in "+containerName)
685-
execProc, err := d.ExecProcess(ctx, dockerutil.ExecOpts{}, execCmd...)
686-
if err != nil {
687-
t.Fatalf("docker exec failed: %v", err)
688-
}
689702

690-
output, err := execProc.Logs()
703+
output, err := dockerInGvisorExecOutput(ctx, d, execCmd)
691704
if err != nil {
692-
t.Fatalf("docker logs failed: %v", err)
705+
t.Fatalf("docker exec failed: %v", err)
693706
}
694707
expectedOutput := "exec in " + containerName
695708
if !strings.Contains(output, expectedOutput) {

0 commit comments

Comments
 (0)