diff --git a/builder/builder.go b/builder/builder.go index c9c96d85c6a3..fabd53f24507 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -346,6 +346,7 @@ type CreateOpts struct { Use bool Endpoint string Append bool + Timeout time.Duration } func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts CreateOpts) (*Builder, error) { @@ -525,8 +526,10 @@ func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts Cre return nil, err } - cancelCtx, cancel := context.WithCancelCause(ctx) - timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + timeoutCtx, cancel := context.WithCancelCause(ctx) + if opts.Timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, opts.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } defer func() { cancel(errors.WithStack(context.Canceled)) }() nodes, err := b.LoadNodes(timeoutCtx, WithData()) diff --git a/commands/create.go b/commands/create.go index d49fda4e1301..025a3750ff25 100644 --- a/commands/create.go +++ b/commands/create.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "time" "github.com/docker/buildx/builder" "github.com/docker/buildx/driver" @@ -27,6 +28,7 @@ type createOptions struct { buildkitdFlags string buildkitdConfigFile string bootstrap bool + timeout time.Duration // upgrade bool // perform upgrade of the driver } @@ -61,6 +63,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg Use: in.use, Endpoint: ep, Append: in.actionAppend, + Timeout: in.timeout, }) if err != nil { return err @@ -120,6 +123,7 @@ func createCmd(dockerCli command.Cli) *cobra.Command { flags.BoolVar(&options.actionAppend, "append", false, "Append a node to builder instead of changing it") flags.BoolVar(&options.actionLeave, "leave", false, "Remove a node from builder instead of changing it") flags.BoolVar(&options.use, "use", false, "Set the current builder instance") + setBuilderStatusTimeoutFlag(flags, &options.timeout) // hide builder persistent flag for this command cobrautil.HideInheritedFlags(cmd, "builder") diff --git a/commands/diskusage.go b/commands/diskusage.go index ce8c6752e31d..5bcc82231f7c 100644 --- a/commands/diskusage.go +++ b/commands/diskusage.go @@ -65,6 +65,7 @@ type duOptions struct { filter opts.FilterOpt verbose bool format string + timeout time.Duration } func runDiskUsage(ctx context.Context, dockerCli command.Cli, opts duOptions) error { @@ -92,7 +93,13 @@ func runDiskUsage(ctx context.Context, dockerCli command.Cli, opts duOptions) er return err } - nodes, err := b.LoadNodes(ctx) + timeoutCtx, cancel := context.WithCancelCause(ctx) + if opts.timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, opts.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } + defer func() { cancel(errors.WithStack(context.Canceled)) }() + + nodes, err := b.LoadNodes(timeoutCtx) if err != nil { return err } @@ -197,6 +204,7 @@ func duCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.Var(&options.filter, "filter", "Provide filter values") flags.BoolVar(&options.verbose, "verbose", false, `Shorthand for "--format=pretty"`) flags.StringVar(&options.format, "format", "", "Format the output") + setBuilderStatusTimeoutFlag(flags, &options.timeout) return cmd } diff --git a/commands/inspect.go b/commands/inspect.go index 00031e44467e..9e891217aeb5 100644 --- a/commands/inspect.go +++ b/commands/inspect.go @@ -24,6 +24,7 @@ import ( type inspectOptions struct { bootstrap bool builder string + timeout time.Duration } func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) error { @@ -36,7 +37,9 @@ func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) e } timeoutCtx, cancel := context.WithCancelCause(ctx) - timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + if in.timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } defer func() { cancel(errors.WithStack(context.Canceled)) }() nodes, err := b.LoadNodes(timeoutCtx, builder.WithData()) @@ -188,6 +191,7 @@ func inspectCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags := cmd.Flags() flags.BoolVar(&options.bootstrap, "bootstrap", false, "Ensure builder has booted before inspecting") + setBuilderStatusTimeoutFlag(flags, &options.timeout) return cmd } diff --git a/commands/ls.go b/commands/ls.go index 847c4130a179..1791bda8d1df 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -40,6 +40,7 @@ const ( type lsOptions struct { format string noTrunc bool + timeout time.Duration } func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error { @@ -60,7 +61,9 @@ func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error { } timeoutCtx, cancel := context.WithCancelCause(ctx) - timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + if in.timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } defer func() { cancel(errors.WithStack(context.Canceled)) }() eg, _ := errgroup.WithContext(timeoutCtx) @@ -114,6 +117,7 @@ func lsCmd(dockerCli command.Cli) *cobra.Command { flags := cmd.Flags() flags.StringVar(&options.format, "format", formatter.TableFormatKey, "Format the output") flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") + setBuilderStatusTimeoutFlag(flags, &options.timeout) // hide builder persistent flag for this command cobrautil.HideInheritedFlags(cmd, "builder") diff --git a/commands/prune.go b/commands/prune.go index d18b9d914b9e..fd8293b82624 100644 --- a/commands/prune.go +++ b/commands/prune.go @@ -36,6 +36,7 @@ type pruneOptions struct { minFreeSpace opts.MemBytes force bool verbose bool + timeout time.Duration } const ( @@ -68,7 +69,13 @@ func runPrune(ctx context.Context, dockerCli command.Cli, opts pruneOptions) err return err } - nodes, err := b.LoadNodes(ctx) + timeoutCtx, cancel := context.WithCancelCause(ctx) + if opts.timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, opts.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } + defer func() { cancel(errors.WithStack(context.Canceled)) }() + + nodes, err := b.LoadNodes(timeoutCtx) if err != nil { return err } @@ -182,6 +189,7 @@ func pruneCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.Var(&options.maxUsedSpace, "max-used-space", "Maximum amount of disk space allowed to keep for cache") flags.BoolVar(&options.verbose, "verbose", false, "Provide a more verbose output") flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") + setBuilderStatusTimeoutFlag(flags, &options.timeout) flags.Var(&options.reservedSpace, "keep-storage", "Amount of disk space to keep for cache") flags.MarkDeprecated("keep-storage", "keep-storage flag has been changed to reserved-space") diff --git a/commands/rm.go b/commands/rm.go index 6f9cb000f4f8..f14c1d2500c6 100644 --- a/commands/rm.go +++ b/commands/rm.go @@ -21,6 +21,7 @@ type rmOptions struct { keepDaemon bool allInactive bool force bool + timeout time.Duration } const ( @@ -46,7 +47,13 @@ func runRm(ctx context.Context, dockerCli command.Cli, in rmOptions) error { return rmAllInactive(ctx, txn, dockerCli, in) } - eg, _ := errgroup.WithContext(ctx) + timeoutCtx, cancel := context.WithCancelCause(ctx) + if in.timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } + defer func() { cancel(errors.WithStack(context.Canceled)) }() + + eg, _ := errgroup.WithContext(timeoutCtx) for _, name := range in.builders { func(name string) { eg.Go(func() (err error) { @@ -67,7 +74,7 @@ func runRm(ctx context.Context, dockerCli command.Cli, in rmOptions) error { return err } - nodes, err := b.LoadNodes(ctx) + nodes, err := b.LoadNodes(timeoutCtx) if err != nil { return err } @@ -120,6 +127,7 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.BoolVar(&options.keepDaemon, "keep-daemon", false, "Keep the BuildKit daemon running") flags.BoolVar(&options.allInactive, "all-inactive", false, "Remove all inactive builders") flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") + setBuilderStatusTimeoutFlag(flags, &options.timeout) return cmd } @@ -152,7 +160,9 @@ func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, i } timeoutCtx, cancel := context.WithCancelCause(ctx) - timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + if in.timeout > 0 { + timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet // no need to manually cancel this context as we already rely on parent + } defer func() { cancel(errors.WithStack(context.Canceled)) }() eg, _ := errgroup.WithContext(timeoutCtx) diff --git a/commands/root.go b/commands/root.go index 1c36eb40873a..ee658bbcbf74 100644 --- a/commands/root.go +++ b/commands/root.go @@ -3,6 +3,7 @@ package commands import ( "fmt" "os" + "time" historycmd "github.com/docker/buildx/commands/history" imagetoolscmd "github.com/docker/buildx/commands/imagetools" @@ -142,3 +143,7 @@ func rootFlags(options *rootOptions, flags *pflag.FlagSet) { flags.StringVar(&options.builder, "builder", os.Getenv("BUILDX_BUILDER"), "Override the configured builder instance") flags.BoolVarP(&options.debug, "debug", "D", debug.IsEnabled(), "Enable debug logging") } + +func setBuilderStatusTimeoutFlag(flags *pflag.FlagSet, target *time.Duration) { + flags.DurationVar(target, "timeout", 20*time.Second, "Override the default timeout for loading builder status") +} diff --git a/docs/reference/buildx_create.md b/docs/reference/buildx_create.md index 96d71b29afce..0c8d9f0ea57f 100644 --- a/docs/reference/buildx_create.md +++ b/docs/reference/buildx_create.md @@ -22,6 +22,7 @@ Create a new builder instance | [`--name`](#name) | `string` | | Builder instance name | | [`--node`](#node) | `string` | | Create/modify node with given name | | [`--platform`](#platform) | `stringArray` | | Fixed platforms for current node | +| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status | | [`--use`](#use) | `bool` | | Set the current builder instance | diff --git a/docs/reference/buildx_du.md b/docs/reference/buildx_du.md index 999d2561fb10..184a16ba0c1b 100644 --- a/docs/reference/buildx_du.md +++ b/docs/reference/buildx_du.md @@ -9,13 +9,14 @@ Disk usage ### Options -| Name | Type | Default | Description | -|:------------------------|:---------|:--------|:-----------------------------------------| -| [`--builder`](#builder) | `string` | | Override the configured builder instance | -| `-D`, `--debug` | `bool` | | Enable debug logging | -| [`--filter`](#filter) | `filter` | | Provide filter values | -| [`--format`](#format) | `string` | | Format the output | -| [`--verbose`](#verbose) | `bool` | | Shorthand for `--format=pretty` | +| Name | Type | Default | Description | +|:------------------------|:-----------|:--------|:--------------------------------------------------------| +| [`--builder`](#builder) | `string` | | Override the configured builder instance | +| `-D`, `--debug` | `bool` | | Enable debug logging | +| [`--filter`](#filter) | `filter` | | Provide filter values | +| [`--format`](#format) | `string` | | Format the output | +| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status | +| [`--verbose`](#verbose) | `bool` | | Shorthand for `--format=pretty` | diff --git a/docs/reference/buildx_inspect.md b/docs/reference/buildx_inspect.md index 02847e8755b1..eae809f494b6 100644 --- a/docs/reference/buildx_inspect.md +++ b/docs/reference/buildx_inspect.md @@ -9,11 +9,12 @@ Inspect current builder instance ### Options -| Name | Type | Default | Description | -|:----------------------------|:---------|:--------|:--------------------------------------------| -| [`--bootstrap`](#bootstrap) | `bool` | | Ensure builder has booted before inspecting | -| [`--builder`](#builder) | `string` | | Override the configured builder instance | -| `-D`, `--debug` | `bool` | | Enable debug logging | +| Name | Type | Default | Description | +|:----------------------------|:-----------|:--------|:--------------------------------------------------------| +| [`--bootstrap`](#bootstrap) | `bool` | | Ensure builder has booted before inspecting | +| [`--builder`](#builder) | `string` | | Override the configured builder instance | +| `-D`, `--debug` | `bool` | | Enable debug logging | +| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status | diff --git a/docs/reference/buildx_ls.md b/docs/reference/buildx_ls.md index 1b0d89a0e9cc..f437c30ed507 100644 --- a/docs/reference/buildx_ls.md +++ b/docs/reference/buildx_ls.md @@ -9,11 +9,12 @@ List builder instances ### Options -| Name | Type | Default | Description | -|:----------------------|:---------|:--------|:----------------------| -| `-D`, `--debug` | `bool` | | Enable debug logging | -| [`--format`](#format) | `string` | `table` | Format the output | -| `--no-trunc` | `bool` | | Don't truncate output | +| Name | Type | Default | Description | +|:----------------------|:-----------|:--------|:--------------------------------------------------------| +| `-D`, `--debug` | `bool` | | Enable debug logging | +| [`--format`](#format) | `string` | `table` | Format the output | +| `--no-trunc` | `bool` | | Don't truncate output | +| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status | diff --git a/docs/reference/buildx_prune.md b/docs/reference/buildx_prune.md index 242a879a658c..483b24f65287 100644 --- a/docs/reference/buildx_prune.md +++ b/docs/reference/buildx_prune.md @@ -9,17 +9,18 @@ Remove build cache ### Options -| Name | Type | Default | Description | -|:--------------------------------------|:---------|:--------|:-------------------------------------------------------| -| [`-a`](#all), [`--all`](#all) | `bool` | | Include internal/frontend images | -| [`--builder`](#builder) | `string` | | Override the configured builder instance | -| `-D`, `--debug` | `bool` | | Enable debug logging | -| [`--filter`](#filter) | `filter` | | Provide filter values | -| `-f`, `--force` | `bool` | | Do not prompt for confirmation | -| [`--max-used-space`](#max-used-space) | `bytes` | `0` | Maximum amount of disk space allowed to keep for cache | -| [`--min-free-space`](#min-free-space) | `bytes` | `0` | Target amount of free disk space after pruning | -| [`--reserved-space`](#reserved-space) | `bytes` | `0` | Amount of disk space always allowed to keep for cache | -| `--verbose` | `bool` | | Provide a more verbose output | +| Name | Type | Default | Description | +|:--------------------------------------|:-----------|:--------|:--------------------------------------------------------| +| [`-a`](#all), [`--all`](#all) | `bool` | | Include internal/frontend images | +| [`--builder`](#builder) | `string` | | Override the configured builder instance | +| `-D`, `--debug` | `bool` | | Enable debug logging | +| [`--filter`](#filter) | `filter` | | Provide filter values | +| `-f`, `--force` | `bool` | | Do not prompt for confirmation | +| [`--max-used-space`](#max-used-space) | `bytes` | `0` | Maximum amount of disk space allowed to keep for cache | +| [`--min-free-space`](#min-free-space) | `bytes` | `0` | Target amount of free disk space after pruning | +| [`--reserved-space`](#reserved-space) | `bytes` | `0` | Amount of disk space always allowed to keep for cache | +| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status | +| `--verbose` | `bool` | | Provide a more verbose output | diff --git a/docs/reference/buildx_rm.md b/docs/reference/buildx_rm.md index 996bacd57daf..4d64e3387c92 100644 --- a/docs/reference/buildx_rm.md +++ b/docs/reference/buildx_rm.md @@ -9,14 +9,15 @@ Remove one or more builder instances ### Options -| Name | Type | Default | Description | -|:------------------------------------|:---------|:--------|:-----------------------------------------| -| [`--all-inactive`](#all-inactive) | `bool` | | Remove all inactive builders | -| [`--builder`](#builder) | `string` | | Override the configured builder instance | -| `-D`, `--debug` | `bool` | | Enable debug logging | -| [`-f`](#force), [`--force`](#force) | `bool` | | Do not prompt for confirmation | -| [`--keep-daemon`](#keep-daemon) | `bool` | | Keep the BuildKit daemon running | -| [`--keep-state`](#keep-state) | `bool` | | Keep BuildKit state | +| Name | Type | Default | Description | +|:------------------------------------|:-----------|:--------|:--------------------------------------------------------| +| [`--all-inactive`](#all-inactive) | `bool` | | Remove all inactive builders | +| [`--builder`](#builder) | `string` | | Override the configured builder instance | +| `-D`, `--debug` | `bool` | | Enable debug logging | +| [`-f`](#force), [`--force`](#force) | `bool` | | Do not prompt for confirmation | +| [`--keep-daemon`](#keep-daemon) | `bool` | | Keep the BuildKit daemon running | +| [`--keep-state`](#keep-state) | `bool` | | Keep BuildKit state | +| `--timeout` | `duration` | `20s` | Override the default timeout for loading builder status |