mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	Merge pull request #1846 from crazy-max/history-capability
driver: check history capability
This commit is contained in:
		@@ -389,7 +389,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, e := range opt.CacheTo {
 | 
			
		||||
		if e.Type != "inline" && !nodeDriver.Features()[driver.CacheExport] {
 | 
			
		||||
		if e.Type != "inline" && !nodeDriver.Features(ctx)[driver.CacheExport] {
 | 
			
		||||
			return nil, nil, notSupported(nodeDriver, driver.CacheExport)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -527,7 +527,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
 | 
			
		||||
 | 
			
		||||
	// set up exporters
 | 
			
		||||
	for i, e := range opt.Exports {
 | 
			
		||||
		if e.Type == "oci" && !nodeDriver.Features()[driver.OCIExporter] {
 | 
			
		||||
		if e.Type == "oci" && !nodeDriver.Features(ctx)[driver.OCIExporter] {
 | 
			
		||||
			return nil, nil, notSupported(nodeDriver, driver.OCIExporter)
 | 
			
		||||
		}
 | 
			
		||||
		if e.Type == "docker" {
 | 
			
		||||
@@ -545,7 +545,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
 | 
			
		||||
					defers = append(defers, cancel)
 | 
			
		||||
					opt.Exports[i].Output = wrapWriteCloser(w)
 | 
			
		||||
				}
 | 
			
		||||
			} else if !nodeDriver.Features()[driver.DockerExporter] {
 | 
			
		||||
			} else if !nodeDriver.Features(ctx)[driver.DockerExporter] {
 | 
			
		||||
				return nil, nil, notSupported(nodeDriver, driver.DockerExporter)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -614,7 +614,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
 | 
			
		||||
		for i, p := range opt.Platforms {
 | 
			
		||||
			pp[i] = platforms.Format(p)
 | 
			
		||||
		}
 | 
			
		||||
		if len(pp) > 1 && !nodeDriver.Features()[driver.MultiPlatform] {
 | 
			
		||||
		if len(pp) > 1 && !nodeDriver.Features(ctx)[driver.MultiPlatform] {
 | 
			
		||||
			return nil, nil, notSupported(nodeDriver, driver.MultiPlatform)
 | 
			
		||||
		}
 | 
			
		||||
		so.FrontendAttrs["platform"] = strings.Join(pp, ",")
 | 
			
		||||
 
 | 
			
		||||
@@ -387,13 +387,19 @@ func (d *Driver) Factory() driver.Factory {
 | 
			
		||||
	return d.factory
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Driver) Features() map[driver.Feature]bool {
 | 
			
		||||
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
 | 
			
		||||
	var historyAPI bool
 | 
			
		||||
	c, err := d.Client(ctx)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		historyAPI = driver.HistoryAPISupported(ctx, c)
 | 
			
		||||
		c.Close()
 | 
			
		||||
	}
 | 
			
		||||
	return map[driver.Feature]bool{
 | 
			
		||||
		driver.OCIExporter:    true,
 | 
			
		||||
		driver.DockerExporter: true,
 | 
			
		||||
 | 
			
		||||
		driver.CacheExport:   true,
 | 
			
		||||
		driver.MultiPlatform: true,
 | 
			
		||||
		driver.CacheExport:    true,
 | 
			
		||||
		driver.MultiPlatform:  true,
 | 
			
		||||
		driver.HistoryAPI:     historyAPI,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -58,9 +58,9 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) {
 | 
			
		||||
	}))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Driver) Features() map[driver.Feature]bool {
 | 
			
		||||
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
 | 
			
		||||
	var useContainerdSnapshotter bool
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
	var historyAPI bool
 | 
			
		||||
	c, err := d.Client(ctx)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		workers, _ := c.ListWorkers(ctx)
 | 
			
		||||
@@ -69,6 +69,7 @@ func (d *Driver) Features() map[driver.Feature]bool {
 | 
			
		||||
				useContainerdSnapshotter = true
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		historyAPI = driver.HistoryAPISupported(ctx, c)
 | 
			
		||||
		c.Close()
 | 
			
		||||
	}
 | 
			
		||||
	return map[driver.Feature]bool{
 | 
			
		||||
@@ -76,6 +77,7 @@ func (d *Driver) Features() map[driver.Feature]bool {
 | 
			
		||||
		driver.DockerExporter: useContainerdSnapshotter,
 | 
			
		||||
		driver.CacheExport:    useContainerdSnapshotter,
 | 
			
		||||
		driver.MultiPlatform:  useContainerdSnapshotter,
 | 
			
		||||
		driver.HistoryAPI:     historyAPI,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,11 @@ import (
 | 
			
		||||
	"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/moby/buildkit/util/grpcerrors"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"google.golang.org/grpc/codes"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var ErrNotRunning = errors.Errorf("driver not running")
 | 
			
		||||
@@ -57,7 +60,7 @@ type Driver interface {
 | 
			
		||||
	Stop(ctx context.Context, force bool) error
 | 
			
		||||
	Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error
 | 
			
		||||
	Client(ctx context.Context) (*client.Client, error)
 | 
			
		||||
	Features() map[Feature]bool
 | 
			
		||||
	Features(ctx context.Context) map[Feature]bool
 | 
			
		||||
	IsMobyDriver() bool
 | 
			
		||||
	Config() InitConfig
 | 
			
		||||
}
 | 
			
		||||
@@ -89,3 +92,26 @@ func Boot(ctx, clientContext context.Context, d Driver, pw progress.Writer) (*cl
 | 
			
		||||
		return c, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func HistoryAPISupported(ctx context.Context, c *client.Client) (res bool) {
 | 
			
		||||
	res = true
 | 
			
		||||
	checkErrF := func(err error) {
 | 
			
		||||
		if s, ok := grpcerrors.AsGRPCStatus(err); ok {
 | 
			
		||||
			if s.Code() == codes.Unimplemented {
 | 
			
		||||
				res = false
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{
 | 
			
		||||
		ActiveOnly: true,
 | 
			
		||||
		Ref:        "buildx-dummy-ref", // dummy ref to check if the server supports the API
 | 
			
		||||
		EarlyExit:  true,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		checkErrF(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	_, err = cl.Recv()
 | 
			
		||||
	checkErrF(err)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,3 +7,5 @@ const DockerExporter Feature = "Docker exporter"
 | 
			
		||||
 | 
			
		||||
const CacheExport Feature = "cache export"
 | 
			
		||||
const MultiPlatform Feature = "multiple platforms"
 | 
			
		||||
 | 
			
		||||
const HistoryAPI Feature = "history api"
 | 
			
		||||
 
 | 
			
		||||
@@ -228,12 +228,18 @@ func (d *Driver) Factory() driver.Factory {
 | 
			
		||||
	return d.factory
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Driver) Features() map[driver.Feature]bool {
 | 
			
		||||
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
 | 
			
		||||
	var historyAPI bool
 | 
			
		||||
	c, err := d.Client(ctx)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		historyAPI = driver.HistoryAPISupported(ctx, c)
 | 
			
		||||
		c.Close()
 | 
			
		||||
	}
 | 
			
		||||
	return map[driver.Feature]bool{
 | 
			
		||||
		driver.OCIExporter:    true,
 | 
			
		||||
		driver.DockerExporter: d.DockerAPI != nil,
 | 
			
		||||
 | 
			
		||||
		driver.CacheExport:   true,
 | 
			
		||||
		driver.MultiPlatform: true, // Untested (needs multiple Driver instances)
 | 
			
		||||
		driver.CacheExport:    true,
 | 
			
		||||
		driver.MultiPlatform:  true, // Untested (needs multiple Driver instances)
 | 
			
		||||
		driver.HistoryAPI:     historyAPI,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -147,9 +147,11 @@ func GetFactories(instanceRequired bool) []Factory {
 | 
			
		||||
 | 
			
		||||
type cachedDriver struct {
 | 
			
		||||
	Driver
 | 
			
		||||
	client *client.Client
 | 
			
		||||
	err    error
 | 
			
		||||
	once   sync.Once
 | 
			
		||||
	client       *client.Client
 | 
			
		||||
	err          error
 | 
			
		||||
	once         sync.Once
 | 
			
		||||
	featuresOnce sync.Once
 | 
			
		||||
	features     map[Feature]bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *cachedDriver) Client(ctx context.Context) (*client.Client, error) {
 | 
			
		||||
@@ -158,3 +160,10 @@ func (d *cachedDriver) Client(ctx context.Context) (*client.Client, error) {
 | 
			
		||||
	})
 | 
			
		||||
	return d.client, d.err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *cachedDriver) Features(ctx context.Context) map[Feature]bool {
 | 
			
		||||
	d.featuresOnce.Do(func() {
 | 
			
		||||
		d.features = d.Driver.Features(ctx)
 | 
			
		||||
	})
 | 
			
		||||
	return d.features
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -87,12 +87,19 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) {
 | 
			
		||||
	return client.New(ctx, d.InitConfig.EndpointAddr, opts...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Driver) Features() map[driver.Feature]bool {
 | 
			
		||||
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
 | 
			
		||||
	var historyAPI bool
 | 
			
		||||
	c, err := d.Client(ctx)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		historyAPI = driver.HistoryAPISupported(ctx, c)
 | 
			
		||||
		c.Close()
 | 
			
		||||
	}
 | 
			
		||||
	return map[driver.Feature]bool{
 | 
			
		||||
		driver.OCIExporter:    true,
 | 
			
		||||
		driver.DockerExporter: true,
 | 
			
		||||
		driver.CacheExport:    true,
 | 
			
		||||
		driver.MultiPlatform:  true,
 | 
			
		||||
		driver.HistoryAPI:     historyAPI,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user