Introduce a client interface, to abstract from buildkit client.

This will allow further enhancement like caching remote driver responses.

Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
This commit is contained in:
Silvin Lubecki 2023-08-08 14:44:42 +02:00
parent 561a4330cf
commit 2aa6d52b06
9 changed files with 36 additions and 17 deletions

View File

@ -164,8 +164,8 @@ func allIndexes(l int) []int {
return out return out
} }
func ensureBooted(ctx context.Context, nodes []builder.Node, idxs []int, pw progress.Writer) ([]*client.Client, error) { func ensureBooted(ctx context.Context, nodes []builder.Node, idxs []int, pw progress.Writer) ([]driver.Client, error) {
clients := make([]*client.Client, len(nodes)) clients := make([]driver.Client, len(nodes))
baseCtx := ctx baseCtx := ctx
eg, ctx := errgroup.WithContext(ctx) eg, ctx := errgroup.WithContext(ctx)
@ -214,7 +214,7 @@ func splitToDriverPairs(availablePlatforms map[string]int, opt map[string]Option
return m return m
} }
func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []driver.Client, error) {
dps, clients, err := resolveDriversBase(ctx, nodes, opt, pw) dps, clients, err := resolveDriversBase(ctx, nodes, opt, pw)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -230,7 +230,7 @@ func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Op
continue continue
} }
func(i int, c *client.Client) { func(i int, c driver.Client) {
eg.Go(func() error { eg.Go(func() error {
clients[i].Build(ctx, client.SolveOpt{ clients[i].Build(ctx, client.SolveOpt{
Internal: true, Internal: true,
@ -257,7 +257,7 @@ func resolveDrivers(ctx context.Context, nodes []builder.Node, opt map[string]Op
return dps, clients, nil return dps, clients, nil
} }
func resolveDriversBase(ctx context.Context, nodes []builder.Node, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []*client.Client, error) { func resolveDriversBase(ctx context.Context, nodes []builder.Node, opt map[string]Options, pw progress.Writer) (map[string][]driverPair, []driver.Client, error) {
availablePlatforms := map[string]int{} availablePlatforms := map[string]int{}
for i, node := range nodes { for i, node := range nodes {
for _, p := range node.Platforms { for _, p := range node.Platforms {

View File

@ -8,6 +8,7 @@ import (
"sync" "sync"
controllerapi "github.com/docker/buildx/controller/pb" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/driver"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/exporter/containerimage/exptypes"
gateway "github.com/moby/buildkit/frontend/gateway/client" gateway "github.com/moby/buildkit/frontend/gateway/client"
@ -28,7 +29,7 @@ import (
// failures and successes. // failures and successes.
// //
// If the returned ResultHandle is not nil, the caller must call Done() on it. // If the returned ResultHandle is not nil, the caller must call Done() on it.
func NewResultHandle(ctx context.Context, cc *client.Client, opt client.SolveOpt, product string, buildFunc gateway.BuildFunc, ch chan *client.SolveStatus) (*ResultHandle, *client.SolveResponse, error) { func NewResultHandle(ctx context.Context, cc driver.Client, opt client.SolveOpt, product string, buildFunc gateway.BuildFunc, ch chan *client.SolveStatus) (*ResultHandle, *client.SolveResponse, error) {
// Create a new context to wrap the original, and cancel it when the // Create a new context to wrap the original, and cancel it when the
// caller-provided context is cancelled. // caller-provided context is cancelled.
// //

20
driver/client.go Normal file
View File

@ -0,0 +1,20 @@
package driver
import (
"context"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/client"
gateway "github.com/moby/buildkit/frontend/gateway/client"
)
type Client interface {
Build(ctx context.Context, opt client.SolveOpt, product string, buildFunc gateway.BuildFunc, statusChan chan *client.SolveStatus) (*client.SolveResponse, error)
ListWorkers(ctx context.Context, opts ...client.ListWorkersOption) ([]*client.WorkerInfo, error)
Info(ctx context.Context) (*client.Info, error)
DiskUsage(ctx context.Context, opts ...client.DiskUsageOption) ([]*client.UsageInfo, error)
Prune(ctx context.Context, ch chan client.UsageInfo, opts ...client.PruneOption) error
ControlClient() controlapi.ControlClient
Close() error
Wait(ctx context.Context) error
}

View File

@ -359,7 +359,7 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
return nil return nil
} }
func (d *Driver) Client(ctx context.Context) (*client.Client, error) { func (d *Driver) Client(ctx context.Context) (driver.Client, error) {
_, conn, err := d.exec(ctx, []string{"buildctl", "dial-stdio"}) _, conn, err := d.exec(ctx, []string{"buildctl", "dial-stdio"})
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -51,7 +51,7 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
return nil return nil
} }
func (d *Driver) Client(ctx context.Context) (*client.Client, error) { func (d *Driver) Client(ctx context.Context) (driver.Client, error) {
opts := []client.ClientOpt{ opts := []client.ClientOpt{
client.WithContextDialer(func(context.Context, string) (net.Conn, error) { client.WithContextDialer(func(context.Context, string) (net.Conn, error) {
return d.DockerAPI.DialHijack(ctx, "/grpc", "h2c", nil) return d.DockerAPI.DialHijack(ctx, "/grpc", "h2c", nil)

View File

@ -8,7 +8,6 @@ import (
"github.com/docker/buildx/util/progress" "github.com/docker/buildx/util/progress"
clitypes "github.com/docker/cli/cli/config/types" clitypes "github.com/docker/cli/cli/config/types"
controlapi "github.com/moby/buildkit/api/services/control" controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/client"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -58,13 +57,13 @@ type Driver interface {
Version(context.Context) (string, error) Version(context.Context) (string, error)
Stop(ctx context.Context, force bool) error Stop(ctx context.Context, force bool) error
Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error
Client(ctx context.Context) (*client.Client, error) Client(ctx context.Context) (Client, error)
Features(ctx context.Context) map[Feature]bool Features(ctx context.Context) map[Feature]bool
IsMobyDriver() bool IsMobyDriver() bool
Config() InitConfig Config() InitConfig
} }
func Boot(ctx, clientContext context.Context, d *DriverHandle, pw progress.Writer) (*client.Client, error) { func Boot(ctx, clientContext context.Context, d *DriverHandle, pw progress.Writer) (Client, error) {
try := 0 try := 0
for { for {
info, err := d.Info(ctx) info, err := d.Info(ctx)
@ -92,7 +91,7 @@ func Boot(ctx, clientContext context.Context, d *DriverHandle, pw progress.Write
} }
} }
func historyAPISupported(ctx context.Context, c *client.Client) bool { func historyAPISupported(ctx context.Context, c Client) bool {
cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{ cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{
ActiveOnly: true, ActiveOnly: true,
Ref: "buildx-test-history-api-feature", // dummy ref to check if the server supports the API Ref: "buildx-test-history-api-feature", // dummy ref to check if the server supports the API

View File

@ -189,7 +189,7 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
return nil return nil
} }
func (d *Driver) Client(ctx context.Context) (*client.Client, error) { func (d *Driver) Client(ctx context.Context) (driver.Client, error) {
restClient := d.clientset.CoreV1().RESTClient() restClient := d.clientset.CoreV1().RESTClient()
restClientConfig, err := d.KubeClientConfig.ClientConfig() restClientConfig, err := d.KubeClientConfig.ClientConfig()
if err != nil { if err != nil {

View File

@ -9,7 +9,6 @@ import (
"sync" "sync"
dockerclient "github.com/docker/docker/client" dockerclient "github.com/docker/docker/client"
"github.com/moby/buildkit/client"
specs "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
@ -147,7 +146,7 @@ func GetFactories(instanceRequired bool) []Factory {
type DriverHandle struct { type DriverHandle struct {
Driver Driver
client *client.Client client Client
err error err error
once sync.Once once sync.Once
featuresOnce sync.Once featuresOnce sync.Once
@ -159,7 +158,7 @@ type DriverHandle struct {
hostGatewayIPErr error hostGatewayIPErr error
} }
func (d *DriverHandle) Client(ctx context.Context) (*client.Client, error) { func (d *DriverHandle) Client(ctx context.Context) (Client, error) {
d.once.Do(func() { d.once.Do(func() {
d.client, d.err = d.Driver.Client(ctx) d.client, d.err = d.Driver.Client(ctx)
}) })

View File

@ -61,7 +61,7 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
return nil return nil
} }
func (d *Driver) Client(ctx context.Context) (*client.Client, error) { func (d *Driver) Client(ctx context.Context) (driver.Client, error) {
opts := []client.ClientOpt{} opts := []client.ClientOpt{}
exp, err := detect.Exporter() exp, err := detect.Exporter()