mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 09:17:49 +08:00

This refactors the driver handle to initialize the tracer delegate inside of the driver handle instead of the individual plugins. This provides more uniformity to how the tracer delegate is created by allowing the driver handle to pass additional client options to the drivers when they create the client. It also avoids creating the tracer delegate client multiple times because the driver handle will only initialize the client once. This prevents some drivers, like the remote driver, from accidentally registering multiple clients as tracer delegates. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
130 lines
2.9 KiB
Go
130 lines
2.9 KiB
Go
package driver
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/docker/buildx/store"
|
|
"github.com/docker/buildx/util/progress"
|
|
clitypes "github.com/docker/cli/cli/config/types"
|
|
controlapi "github.com/moby/buildkit/api/services/control"
|
|
"github.com/moby/buildkit/client"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var ErrNotRunning = errors.Errorf("driver not running")
|
|
var ErrNotConnecting = errors.Errorf("driver not connecting")
|
|
|
|
type Status int
|
|
|
|
const (
|
|
Inactive Status = iota
|
|
Starting
|
|
Running
|
|
Stopping
|
|
Stopped
|
|
)
|
|
|
|
func (s Status) String() string {
|
|
switch s {
|
|
case Inactive:
|
|
return "inactive"
|
|
case Starting:
|
|
return "starting"
|
|
case Running:
|
|
return "running"
|
|
case Stopping:
|
|
return "stopping"
|
|
case Stopped:
|
|
return "stopped"
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
type Info struct {
|
|
Status Status
|
|
// DynamicNodes must be empty if the actual nodes are statically listed in the store
|
|
DynamicNodes []store.Node
|
|
}
|
|
|
|
type Auth interface {
|
|
GetAuthConfig(registryHostname string) (clitypes.AuthConfig, error)
|
|
}
|
|
|
|
type Driver interface {
|
|
Factory() Factory
|
|
Bootstrap(context.Context, progress.Logger) error
|
|
Info(context.Context) (*Info, error)
|
|
Version(context.Context) (string, error)
|
|
Stop(ctx context.Context, force bool) error
|
|
Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error
|
|
Dial(ctx context.Context) (net.Conn, error)
|
|
Client(ctx context.Context, opts ...client.ClientOpt) (*client.Client, error)
|
|
Features(ctx context.Context) map[Feature]bool
|
|
HostGatewayIP(ctx context.Context) (net.IP, error)
|
|
IsMobyDriver() bool
|
|
Config() InitConfig
|
|
}
|
|
|
|
const builderNamePrefix = "buildx_buildkit_"
|
|
|
|
func BuilderName(name string) string {
|
|
return builderNamePrefix + name
|
|
}
|
|
|
|
func ParseBuilderName(name string) (string, error) {
|
|
if !strings.HasPrefix(name, builderNamePrefix) {
|
|
return "", errors.Errorf("invalid builder name %q, must have %q prefix", name, builderNamePrefix)
|
|
}
|
|
return strings.TrimPrefix(name, builderNamePrefix), nil
|
|
}
|
|
|
|
func Boot(ctx, clientContext context.Context, d *DriverHandle, pw progress.Writer) (*client.Client, error) {
|
|
try := 0
|
|
for {
|
|
info, err := d.Info(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
try++
|
|
if info.Status != Running {
|
|
if try > 2 {
|
|
return nil, errors.Errorf("failed to bootstrap %T driver in attempts", d)
|
|
}
|
|
if err := d.Bootstrap(ctx, pw.Write); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
c, err := d.Client(clientContext)
|
|
if err != nil {
|
|
if errors.Cause(err) == ErrNotRunning && try <= 2 {
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
return c, nil
|
|
}
|
|
}
|
|
|
|
func historyAPISupported(ctx context.Context, c *client.Client) bool {
|
|
cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{
|
|
ActiveOnly: true,
|
|
Ref: "buildx-test-history-api-feature", // dummy ref to check if the server supports the API
|
|
EarlyExit: true,
|
|
})
|
|
if err != nil {
|
|
return false
|
|
}
|
|
for {
|
|
_, err := cl.Recv()
|
|
if errors.Is(err, io.EOF) {
|
|
return true
|
|
} else if err != nil {
|
|
return false
|
|
}
|
|
}
|
|
}
|