mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			146 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			3.1 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"
 | 
						|
)
 | 
						|
 | 
						|
type ErrNotRunning struct{}
 | 
						|
 | 
						|
func (ErrNotRunning) Error() string {
 | 
						|
	return "driver not running"
 | 
						|
}
 | 
						|
 | 
						|
type ErrNotConnecting struct{}
 | 
						|
 | 
						|
func (ErrNotConnecting) Error() string {
 | 
						|
	return "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
 | 
						|
	logger := discardLogger
 | 
						|
	if pw != nil {
 | 
						|
		logger = pw.Write
 | 
						|
	}
 | 
						|
 | 
						|
	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, logger); err != nil {
 | 
						|
				return nil, err
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		c, err := d.Client(clientContext)
 | 
						|
		if err != nil {
 | 
						|
			if errors.Is(err, ErrNotRunning{}) && try <= 2 {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		return c, nil
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func discardLogger(*client.SolveStatus) {}
 | 
						|
 | 
						|
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
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |