Add Solve API for performing a build on a build definition
This commit adds Solve API to the controller. This receives a build definition, performs that build using ResultHandler held by that session. After Solve completes, the client can debug the result using other APIs including Invoke. Note that the ResultHandle provided by Solve overwrites the ResultHandle previously stored in that session (possibly generated by the past Build or Solve API call). Using this API, user can perform build-and-debugging loop on the same session. Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"sync"
|
||||
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
||||
@@ -93,6 +94,8 @@ func NewResultHandle(ctx context.Context, cc *client.Client, opt client.SolveOpt
|
||||
if res != nil && err == nil {
|
||||
if noEval {
|
||||
respHandle = &ResultHandle{
|
||||
client: cc,
|
||||
solveOpt: opt,
|
||||
done: make(chan struct{}),
|
||||
gwClient: c,
|
||||
gwCtx: ctx,
|
||||
@@ -127,6 +130,8 @@ func NewResultHandle(ctx context.Context, cc *client.Client, opt client.SolveOpt
|
||||
var se *errdefs.SolveError
|
||||
if errors.As(err, &se) {
|
||||
respHandle = &ResultHandle{
|
||||
client: cc,
|
||||
solveOpt: opt,
|
||||
done: make(chan struct{}),
|
||||
solveErr: se,
|
||||
gwClient: c,
|
||||
@@ -183,6 +188,8 @@ func NewResultHandle(ctx context.Context, cc *client.Client, opt client.SolveOpt
|
||||
return nil, errors.Wrap(err, "inconsistent solve result")
|
||||
}
|
||||
respHandle = &ResultHandle{
|
||||
client: cc,
|
||||
solveOpt: opt,
|
||||
done: make(chan struct{}),
|
||||
res: res,
|
||||
gwClient: c,
|
||||
@@ -265,8 +272,27 @@ func evalDefinition(ctx context.Context, c gateway.Client, defs *result.Result[*
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func SolveWithResultHandler(ctx context.Context, product string, resultCtx *ResultHandle, target *pb.Definition, pw progress.Writer) (*ResultHandle, error) {
|
||||
opt := resultCtx.solveOpt
|
||||
opt.Ref = ""
|
||||
opt.Exports = nil
|
||||
opt.CacheExports = nil
|
||||
ch, done := progress.NewChannel(pw)
|
||||
defer func() { <-done }()
|
||||
h, _, err := NewResultHandle(ctx, resultCtx.client, opt, product, func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
|
||||
return c.Solve(ctx, gateway.SolveRequest{
|
||||
Evaluate: true,
|
||||
Definition: target,
|
||||
})
|
||||
}, ch, false)
|
||||
return h, err
|
||||
}
|
||||
|
||||
// ResultHandle is a build result with the client that built it.
|
||||
type ResultHandle struct {
|
||||
client *client.Client
|
||||
solveOpt client.SolveOpt
|
||||
|
||||
res *gateway.Result
|
||||
solveErr *errdefs.SolveError
|
||||
|
||||
@@ -295,6 +321,10 @@ func (r *ResultHandle) Done() {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *ResultHandle) SolveError() *errdefs.SolveError {
|
||||
return r.solveErr
|
||||
}
|
||||
|
||||
func (r *ResultHandle) registerCleanup(f func()) {
|
||||
r.cleanupsMu.Lock()
|
||||
r.cleanups = append(r.cleanups, f)
|
||||
|
||||
Reference in New Issue
Block a user