add timeout parameter to cli and driver

Signed-off-by: avoidik <avoidik@gmail.com>
Signed-off-by: Viacheslav Vasilyev <avoidik@gmail.com>
This commit is contained in:
avoidik 2024-07-10 15:25:03 +01:00 committed by Camden Narzt
parent 6df3a09284
commit b1c75354e9
No known key found for this signature in database
GPG Key ID: E349304DE45D816B
13 changed files with 54 additions and 18 deletions

View File

@ -344,6 +344,7 @@ type CreateOpts struct {
Use bool Use bool
Endpoint string Endpoint string
Append bool Append bool
Timeout time.Duration
} }
func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts CreateOpts) (*Builder, error) { func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts CreateOpts) (*Builder, error) {
@ -524,7 +525,7 @@ func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts Cre
} }
cancelCtx, cancel := context.WithCancelCause(ctx) cancelCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent timeoutCtx, _ := context.WithTimeoutCause(cancelCtx, opts.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }() defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx, WithData()) nodes, err := b.LoadNodes(timeoutCtx, WithData())

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"time"
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
"github.com/docker/buildx/driver" "github.com/docker/buildx/driver"
@ -27,6 +28,7 @@ type createOptions struct {
buildkitdFlags string buildkitdFlags string
buildkitdConfigFile string buildkitdConfigFile string
bootstrap bool bootstrap bool
timeout time.Duration
// upgrade bool // perform upgrade of the driver // 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, Use: in.use,
Endpoint: ep, Endpoint: ep,
Append: in.actionAppend, Append: in.actionAppend,
Timeout: in.timeout,
}) })
if err != nil { if err != nil {
return err return err
@ -80,7 +83,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
return nil return nil
} }
func createCmd(dockerCli command.Cli) *cobra.Command { func createCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
var options createOptions var options createOptions
var drivers bytes.Buffer var drivers bytes.Buffer
@ -96,6 +99,7 @@ func createCmd(dockerCli command.Cli) *cobra.Command {
Short: "Create a new builder instance", Short: "Create a new builder instance",
Args: cli.RequiresMaxArgs(1), Args: cli.RequiresMaxArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
options.timeout = rootOpts.timeout
return runCreate(cmd.Context(), dockerCli, options, args) return runCreate(cmd.Context(), dockerCli, options, args)
}, },
ValidArgsFunction: completion.Disable, ValidArgsFunction: completion.Disable,

View File

@ -24,6 +24,7 @@ import (
type inspectOptions struct { type inspectOptions struct {
bootstrap bool bootstrap bool
builder string builder string
timeout time.Duration
} }
func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) error { func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) error {
@ -36,7 +37,7 @@ func runInspect(ctx context.Context, dockerCli command.Cli, in inspectOptions) e
} }
timeoutCtx, cancel := context.WithCancelCause(ctx) timeoutCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }() defer func() { cancel(errors.WithStack(context.Canceled)) }()
nodes, err := b.LoadNodes(timeoutCtx, builder.WithData()) nodes, err := b.LoadNodes(timeoutCtx, builder.WithData())
@ -180,6 +181,7 @@ func inspectCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
if len(args) > 0 { if len(args) > 0 {
options.builder = args[0] options.builder = args[0]
} }
options.timeout = rootOpts.timeout
return runInspect(cmd.Context(), dockerCli, options) return runInspect(cmd.Context(), dockerCli, options)
}, },
ValidArgsFunction: completion.BuilderNames(dockerCli), ValidArgsFunction: completion.BuilderNames(dockerCli),

View File

@ -40,6 +40,7 @@ const (
type lsOptions struct { type lsOptions struct {
format string format string
noTrunc bool noTrunc bool
timeout time.Duration
} }
func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error { func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error {
@ -60,7 +61,7 @@ func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error {
} }
timeoutCtx, cancel := context.WithCancelCause(ctx) timeoutCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }() defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx) eg, _ := errgroup.WithContext(timeoutCtx)
@ -97,7 +98,7 @@ func runLs(ctx context.Context, dockerCli command.Cli, in lsOptions) error {
return nil return nil
} }
func lsCmd(dockerCli command.Cli) *cobra.Command { func lsCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
var options lsOptions var options lsOptions
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -105,6 +106,7 @@ func lsCmd(dockerCli command.Cli) *cobra.Command {
Short: "List builder instances", Short: "List builder instances",
Args: cli.ExactArgs(0), Args: cli.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
options.timeout = rootOpts.timeout
return runLs(cmd.Context(), dockerCli, options) return runLs(cmd.Context(), dockerCli, options)
}, },
ValidArgsFunction: completion.Disable, ValidArgsFunction: completion.Disable,

View File

@ -21,6 +21,7 @@ type rmOptions struct {
keepDaemon bool keepDaemon bool
allInactive bool allInactive bool
force bool force bool
timeout time.Duration
} }
const ( const (
@ -109,6 +110,7 @@ func rmCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
} }
options.builders = args options.builders = args
} }
options.timeout = rootOpts.timeout
return runRm(cmd.Context(), dockerCli, options) return runRm(cmd.Context(), dockerCli, options)
}, },
ValidArgsFunction: completion.BuilderNames(dockerCli), ValidArgsFunction: completion.BuilderNames(dockerCli),
@ -151,7 +153,7 @@ func rmAllInactive(ctx context.Context, txn *store.Txn, dockerCli command.Cli, i
} }
timeoutCtx, cancel := context.WithCancelCause(ctx) timeoutCtx, cancel := context.WithCancelCause(ctx)
timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent timeoutCtx, _ = context.WithTimeoutCause(timeoutCtx, in.timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }() defer func() { cancel(errors.WithStack(context.Canceled)) }()
eg, _ := errgroup.WithContext(timeoutCtx) eg, _ := errgroup.WithContext(timeoutCtx)

View File

@ -3,6 +3,7 @@ package commands
import ( import (
"fmt" "fmt"
"os" "os"
"time"
debugcmd "github.com/docker/buildx/commands/debug" debugcmd "github.com/docker/buildx/commands/debug"
historycmd "github.com/docker/buildx/commands/history" historycmd "github.com/docker/buildx/commands/history"
@ -22,6 +23,8 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
const defaultTimeoutCli = 20 * time.Second
func NewRootCmd(name string, isPlugin bool, dockerCli *command.DockerCli) *cobra.Command { func NewRootCmd(name string, isPlugin bool, dockerCli *command.DockerCli) *cobra.Command {
var opt rootOptions var opt rootOptions
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -96,6 +99,7 @@ func NewRootCmd(name string, isPlugin bool, dockerCli *command.DockerCli) *cobra
type rootOptions struct { type rootOptions struct {
builder string builder string
debug bool debug bool
timeout time.Duration
} }
func addCommands(cmd *cobra.Command, opts *rootOptions, dockerCli command.Cli) { func addCommands(cmd *cobra.Command, opts *rootOptions, dockerCli command.Cli) {
@ -104,10 +108,10 @@ func addCommands(cmd *cobra.Command, opts *rootOptions, dockerCli command.Cli) {
cmd.AddCommand( cmd.AddCommand(
buildCmd(dockerCli, opts, nil), buildCmd(dockerCli, opts, nil),
bakeCmd(dockerCli, opts), bakeCmd(dockerCli, opts),
createCmd(dockerCli), createCmd(dockerCli, opts),
dialStdioCmd(dockerCli, opts), dialStdioCmd(dockerCli, opts),
rmCmd(dockerCli, opts), rmCmd(dockerCli, opts),
lsCmd(dockerCli), lsCmd(dockerCli, opts),
useCmd(dockerCli, opts), useCmd(dockerCli, opts),
inspectCmd(dockerCli, opts), inspectCmd(dockerCli, opts),
stopCmd(dockerCli, opts), stopCmd(dockerCli, opts),
@ -134,4 +138,14 @@ func addCommands(cmd *cobra.Command, opts *rootOptions, dockerCli command.Cli) {
func rootFlags(options *rootOptions, flags *pflag.FlagSet) { func rootFlags(options *rootOptions, flags *pflag.FlagSet) {
flags.StringVar(&options.builder, "builder", os.Getenv("BUILDX_BUILDER"), "Override the configured builder instance") 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") flags.BoolVarP(&options.debug, "debug", "D", debug.IsEnabled(), "Enable debug logging")
var timeoutDuration = defaultTimeoutCli
if value, ok := os.LookupEnv("BUILDX_TIMEOUT"); ok {
var err error
timeoutDuration, err = time.ParseDuration(value)
if err != nil {
timeoutDuration = defaultTimeoutCli
}
}
flags.DurationVar(&options.timeout, "timeout", timeoutDuration, "Override the default global timeout (20 seconds)")
} }

View File

@ -3,6 +3,7 @@ package control
import ( import (
"context" "context"
"io" "io"
"time"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
cbuild "github.com/docker/buildx/controller/build" cbuild "github.com/docker/buildx/controller/build"
@ -24,3 +25,7 @@ type BuildxController interface {
DisconnectProcess(ctx context.Context, pid string) error DisconnectProcess(ctx context.Context, pid string) error
Inspect(ctx context.Context) *cbuild.Options Inspect(ctx context.Context) *cbuild.Options
} }
type ControlOptions struct {
Timeout time.Duration
}

View File

@ -217,7 +217,7 @@ func (d *Driver) wait(ctx context.Context, l progress.SubLogger) error {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return context.Cause(ctx) return context.Cause(ctx)
case <-time.After(time.Duration(try*120) * time.Millisecond): case <-time.After(d.Timeout / time.Microsecond):
try++ try++
continue continue
} }

View File

@ -52,7 +52,6 @@ type Driver struct {
configMapClient clientcorev1.ConfigMapInterface configMapClient clientcorev1.ConfigMapInterface
podChooser podchooser.PodChooser podChooser podchooser.PodChooser
defaultLoad bool defaultLoad bool
timeout time.Duration
} }
func (d *Driver) IsMobyDriver() bool { func (d *Driver) IsMobyDriver() bool {
@ -91,7 +90,7 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
} }
} }
return sub.Wrap( return sub.Wrap(
fmt.Sprintf("waiting for %d pods to be ready, timeout: %s", d.minReplicas, units.HumanDuration(d.timeout)), fmt.Sprintf("waiting for %d pods to be ready, timeout: %s", d.minReplicas, units.HumanDuration(d.Timeout)),
func() error { func() error {
return d.wait(ctx) return d.wait(ctx)
}) })
@ -105,8 +104,8 @@ func (d *Driver) wait(ctx context.Context) error {
depl *appsv1.Deployment depl *appsv1.Deployment
) )
timeoutChan := time.After(d.timeout) timeoutChan := time.After(d.Timeout)
ticker := time.NewTicker(100 * time.Millisecond) ticker := time.NewTicker(d.Timeout / time.Microsecond)
defer ticker.Stop() defer ticker.Stop()
for { for {

View File

@ -23,7 +23,6 @@ import (
const ( const (
prioritySupported = 40 prioritySupported = 40
priorityUnsupported = 80 priorityUnsupported = 80
defaultTimeout = 120 * time.Second
) )
type ClientConfig interface { type ClientConfig interface {
@ -134,7 +133,7 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
} }
d.defaultLoad = defaultLoad d.defaultLoad = defaultLoad
d.timeout = timeout d.Timeout = timeout
d.deployment, d.configMaps, err = manifest.NewDeployment(deploymentOpt) d.deployment, d.configMaps, err = manifest.NewDeployment(deploymentOpt)
if err != nil { if err != nil {
@ -175,7 +174,7 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg
} }
defaultLoad := false defaultLoad := false
timeout := defaultTimeout timeout := cfg.Timeout
deploymentOpt.Qemu.Image = bkimage.QemuImage deploymentOpt.Qemu.Image = bkimage.QemuImage

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"sort" "sort"
"sync" "sync"
"time"
"github.com/docker/cli/cli/context/store" "github.com/docker/cli/cli/context/store"
dockerclient "github.com/docker/docker/client" dockerclient "github.com/docker/docker/client"
@ -38,6 +39,7 @@ type InitConfig struct {
Platforms []specs.Platform Platforms []specs.Platform
ContextPathHash string ContextPathHash string
DialMeta map[string][]string DialMeta map[string][]string
Timeout time.Duration
} }
var drivers map[string]Factory var drivers map[string]Factory

View File

@ -8,7 +8,6 @@ import (
"os" "os"
"strings" "strings"
"sync" "sync"
"time"
"github.com/docker/buildx/driver" "github.com/docker/buildx/driver"
util "github.com/docker/buildx/driver/remote/util" util "github.com/docker/buildx/driver/remote/util"
@ -48,7 +47,7 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error {
} }
return progress.Wrap("[internal] waiting for connection", l, func(_ progress.SubLogger) error { return progress.Wrap("[internal] waiting for connection", l, func(_ progress.SubLogger) error {
cancelCtx, cancel := context.WithCancelCause(ctx) cancelCtx, cancel := context.WithCancelCause(ctx)
ctx, _ := context.WithTimeoutCause(cancelCtx, 20*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent ctx, _ := context.WithTimeoutCause(cancelCtx, d.Timeout, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
defer func() { cancel(errors.WithStack(context.Canceled)) }() defer func() { cancel(errors.WithStack(context.Canceled)) }()
return c.Wait(ctx) return c.Wait(ctx)
}) })

View File

@ -6,6 +6,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/docker/buildx/driver" "github.com/docker/buildx/driver"
util "github.com/docker/buildx/driver/remote/util" util "github.com/docker/buildx/driver/remote/util"
@ -87,6 +88,12 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver
return nil, err return nil, err
} }
d.defaultLoad = parsed d.defaultLoad = parsed
case "timeout":
parsed, err := time.ParseDuration(v)
if err != nil {
return nil, err
}
d.Timeout = parsed
default: default:
return nil, errors.Errorf("invalid driver option %s for remote driver", k) return nil, errors.Errorf("invalid driver option %s for remote driver", k)
} }