Skip to content

Commit 1dab5b2

Browse files
batches: check that docker is running when running src batch (#844)
* check docker version before batch * remove debug statement * create wrapper for fastcontext * move executeFastCommand into context.go * cleanup
1 parent cb9c49f commit 1dab5b2

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

cmd/src/batch_common.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,13 @@ func executeBatchSpec(ctx context.Context, ui ui.ExecUI, opts executeBatchSpecOp
268268
return err
269269
}
270270

271-
// In the past, we checked `docker version`, but now we retrieve the number
272-
// of CPUs, since we need that anyway and it performs the same check (is
273-
// Docker working _at all_?).
271+
// In the past, we relied on `getBatchParallelism` to ascertain if docker is running,
272+
// however, we don't always check for the number of CPUs (especially when the -j parallelis)
273+
// flag is passed. This is a more explicit check to confirm docker is working.
274+
if err := docker.CheckVersion(ctx); err != nil {
275+
return err
276+
}
277+
274278
parallelism, err := getBatchParallelism(ctx, opts.flags.parallelism)
275279
if err != nil {
276280
return err
@@ -547,7 +551,7 @@ func parseBatchSpec(ctx context.Context, file string, svc *service.Service, isRe
547551
func checkExecutable(cmd string, args ...string) error {
548552
if err := exec.Command(cmd, args...).Run(); err != nil {
549553
return fmt.Errorf(
550-
"failed to execute \"%s %s\":\n\t%s\n\n'src batch' require %q to be available.",
554+
"failed to execute \"%s %s\":\n\t%s\n\n'src batch' requires %q to be available.",
551555
cmd,
552556
strings.Join(args, " "),
553557
err,

internal/batches/docker/context.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"os"
7+
"os/exec"
78
"sync"
89
"time"
910

@@ -94,3 +95,20 @@ func fastCommandTimeout() (time.Duration, error) {
9495

9596
return fastCommandTimeoutData.timeout, fastCommandTimeoutData.err
9697
}
98+
99+
// executeFastCommand creates a fastCommandContext used to execute docker commands
100+
// with a timeout for docker commands that are supposed to be fast (e.g docker info).
101+
func executeFastCommand(ctx context.Context, args ...string) ([]byte, error) {
102+
dctx, cancel, err := withFastCommandContext(ctx)
103+
if err != nil {
104+
return nil, err
105+
}
106+
defer cancel()
107+
108+
out, err := exec.CommandContext(dctx, "docker", args...).CombinedOutput()
109+
if errors.IsDeadlineExceeded(err) || errors.IsDeadlineExceeded(dctx.Err()) {
110+
return nil, newFastCommandTimeoutError(dctx, args...)
111+
}
112+
113+
return out, err
114+
}

internal/batches/docker/version.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package docker
2+
3+
import (
4+
"context"
5+
"fmt"
6+
)
7+
8+
// CheckVersion is used to check if docker is running. We use this method instead of
9+
// checkExecutable (https://sourcegraph.com/github.com/sourcegraph/src-cli@main/-/blob/cmd/src/batch_common.go?L547%3A6=&popover=pinned)
10+
// to prevent a case where docker commands take too long and results in `src-cli` freezing for some users.
11+
func CheckVersion(ctx context.Context) error {
12+
_, err := executeFastCommand(ctx, "version")
13+
if err != nil {
14+
return fmt.Errorf(
15+
"failed to execute \"docker version\":\n\t%s\n\n'src batch' requires \"docker\" to be available.",
16+
err,
17+
)
18+
}
19+
20+
return nil
21+
}

0 commit comments

Comments
 (0)