mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-13 06:57:09 +08:00
build: add docker output for non-moby drivers
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/docker/distribution/reference"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/urlutil"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/session"
|
||||
@ -61,6 +62,10 @@ type DriverInfo struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type DockerAPI interface {
|
||||
DockerAPI(name string) (dockerclient.APIClient, error)
|
||||
}
|
||||
|
||||
func getFirstDriver(drivers []DriverInfo) (driver.Driver, error) {
|
||||
err := errors.Errorf("no drivers found")
|
||||
for _, di := range drivers {
|
||||
@ -74,7 +79,7 @@ func getFirstDriver(drivers []DriverInfo) (driver.Driver, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw progress.Writer) (map[string]*client.SolveResponse, error) {
|
||||
func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, docker DockerAPI, pw progress.Writer) (map[string]*client.SolveResponse, error) {
|
||||
if len(drivers) == 0 {
|
||||
return nil, errors.Errorf("driver required for build")
|
||||
}
|
||||
@ -83,7 +88,6 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw
|
||||
return nil, errors.Errorf("multiple drivers currently not supported")
|
||||
}
|
||||
|
||||
pwOld := pw
|
||||
d, err := getFirstDriver(drivers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -91,10 +95,10 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw
|
||||
_, isDefaultMobyDriver := d.(interface {
|
||||
IsDefaultMobyDriver()
|
||||
})
|
||||
c, pw, err := driver.Boot(ctx, d, pw)
|
||||
c, err := driver.Boot(ctx, d, pw)
|
||||
if err != nil {
|
||||
close(pwOld.Status())
|
||||
<-pwOld.Done()
|
||||
close(pw.Status())
|
||||
<-pw.Done()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -173,10 +177,16 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw
|
||||
}
|
||||
if e.Type == "docker" {
|
||||
if e.Output == nil {
|
||||
if !isDefaultMobyDriver {
|
||||
return nil, errors.Errorf("loading to docker currently not implemented, specify dest file or -")
|
||||
if isDefaultMobyDriver {
|
||||
e.Type = "image"
|
||||
} else {
|
||||
w, cancel, err := newDockerLoader(ctx, docker, e.Attrs["context"], mw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cancel()
|
||||
opt.Exports[i].Output = w
|
||||
}
|
||||
e.Type = "image"
|
||||
} else if !d.Features()[driver.DockerExporter] {
|
||||
return nil, notSupported(d, driver.DockerExporter)
|
||||
}
|
||||
@ -245,6 +255,7 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, pw
|
||||
|
||||
var statusCh chan *client.SolveStatus
|
||||
if pw != nil {
|
||||
pw = progress.ResetTime(pw)
|
||||
statusCh = pw.Status()
|
||||
eg.Go(func() error {
|
||||
<-pw.Done()
|
||||
@ -380,5 +391,54 @@ func LoadInputs(inp Inputs, target *client.SolveOpt) (func(), error) {
|
||||
}
|
||||
|
||||
func notSupported(d driver.Driver, f driver.Feature) error {
|
||||
return errors.Errorf("%s feature is currently not supported for %s driver. Please switch to a different driver (eg. \"docker buildx new\")", f, d.Factory().Name())
|
||||
return errors.Errorf("%s feature is currently not supported for %s driver. Please switch to a different driver (eg. \"docker buildx create\")", f, d.Factory().Name())
|
||||
}
|
||||
|
||||
func newDockerLoader(ctx context.Context, d DockerAPI, name string, mw *progress.MultiWriter) (io.WriteCloser, func(), error) {
|
||||
c, err := d.DockerAPI(name)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pr, pw := io.Pipe()
|
||||
started := make(chan struct{})
|
||||
w := &waitingWriter{
|
||||
PipeWriter: pw,
|
||||
f: func() {
|
||||
resp, err := c.ImageLoad(ctx, pr, false)
|
||||
if err != nil {
|
||||
pr.CloseWithError(err)
|
||||
return
|
||||
}
|
||||
prog := mw.WithPrefix("", false)
|
||||
close(started)
|
||||
progress.FromReader(prog, "importing to docker", resp.Body)
|
||||
},
|
||||
started: started,
|
||||
}
|
||||
return w, func() {
|
||||
pr.Close()
|
||||
}, nil
|
||||
}
|
||||
|
||||
type waitingWriter struct {
|
||||
*io.PipeWriter
|
||||
f func()
|
||||
once sync.Once
|
||||
mu sync.Mutex
|
||||
err error
|
||||
started chan struct{}
|
||||
}
|
||||
|
||||
func (w *waitingWriter) Write(dt []byte) (int, error) {
|
||||
w.once.Do(func() {
|
||||
go w.f()
|
||||
})
|
||||
return w.PipeWriter.Write(dt)
|
||||
}
|
||||
|
||||
func (w *waitingWriter) Close() error {
|
||||
err := w.PipeWriter.Close()
|
||||
<-w.started
|
||||
return err
|
||||
}
|
||||
|
Reference in New Issue
Block a user