solver: simplify solver public api

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
docker-18.09
Tonis Tiigi 2017-10-04 22:31:18 -07:00
parent 7d0fea5b60
commit 23a114a977
6 changed files with 102 additions and 74 deletions

View File

@ -45,6 +45,7 @@ func NewController(opt Opt) (*Controller, error) {
Worker: opt.Worker,
InstructionCache: opt.InstructionCache,
ImageSource: opt.ImageSource,
Frontends: opt.Frontends,
}),
}
return c, nil
@ -105,7 +106,12 @@ func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*
}
}
if err := c.solver.Solve(ctx, req.Ref, frontend, req.Definition, expi, req.FrontendAttrs, c.opt.Frontends); err != nil {
if err := c.solver.Solve(ctx, req.Ref, solver.SolveRequest{
Frontend: frontend,
Definition: req.Definition,
Exporter: expi,
FrontendOpt: req.FrontendAttrs,
}); err != nil {
return nil, err
}
return &controlapi.SolveResponse{}, nil

View File

@ -53,7 +53,9 @@ func (f *dfFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBr
return nil, nil, err
}
ref, _, err := llbBridge.Solve(ctx, def.ToPB(), "", nil)
ref, _, err := llbBridge.Solve(ctx, frontend.SolveRequest{
Definition: def.ToPB(),
})
if err != nil {
return nil, nil, err
}
@ -112,7 +114,9 @@ func (f *dfFrontend) Solve(ctx context.Context, llbBridge frontend.FrontendLLBBr
if err != nil {
return nil, nil, err
}
retRef, _, err = llbBridge.Solve(ctx, def.ToPB(), "", nil)
retRef, _, err = llbBridge.Solve(ctx, frontend.SolveRequest{
Definition: def.ToPB(),
})
if err != nil {
return nil, nil, err
}

View File

@ -15,7 +15,13 @@ type Frontend interface {
}
type FrontendLLBBridge interface {
Solve(ctx context.Context, def *pb.Definition, frontend string, opts map[string]string) (cache.ImmutableRef, map[string][]byte, error)
Solve(ctx context.Context, req SolveRequest) (cache.ImmutableRef, map[string][]byte, error)
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
Exec(ctx context.Context, meta worker.Meta, rootfs cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
}
type SolveRequest struct {
Definition *pb.Definition
Frontend string
FrontendOpt map[string]string
}

View File

@ -67,7 +67,11 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
var rootFS cache.ImmutableRef
if isDevel {
ref, exp, err := llbBridge.Solve(session.NewContext(ctx, "gateway:"+sid), nil, source, filterPrefix(opts, "gateway-"))
ref, exp, err := llbBridge.Solve(session.NewContext(ctx, "gateway:"+sid),
frontend.SolveRequest{
Frontend: source,
FrontendOpt: filterPrefix(opts, "gateway-"),
})
if err != nil {
return nil, nil, err
}
@ -105,7 +109,9 @@ func (gf *gatewayFrontend) Solve(ctx context.Context, llbBridge frontend.Fronten
return nil, nil, err
}
ref, _, err := llbBridge.Solve(ctx, def.ToPB(), "", nil)
ref, _, err := llbBridge.Solve(ctx, frontend.SolveRequest{
Definition: def.ToPB(),
})
if err != nil {
return nil, nil, err
}
@ -240,7 +246,10 @@ func (lbf *llbBrideForwarder) ResolveImageConfig(ctx context.Context, req *pb.Re
}
func (lbf *llbBrideForwarder) Solve(ctx context.Context, req *pb.SolveRequest) (*pb.SolveResponse, error) {
ref, expResp, err := lbf.llbBridge.Solve(ctx, req.Definition, req.Frontend, nil)
ref, expResp, err := lbf.llbBridge.Solve(ctx, frontend.SolveRequest{
Definition: req.Definition,
Frontend: req.Frontend,
})
if err != nil {
return nil, err
}

View File

@ -11,7 +11,6 @@ import (
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/exporter"
"github.com/moby/buildkit/frontend"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/source"
"github.com/moby/buildkit/util/bgfunc"
@ -26,10 +25,11 @@ import (
type LLBOpt struct {
SourceManager *source.Manager
CacheManager cache.Manager // TODO: this shouldn't be needed before instruction cache
CacheManager cache.Manager
Worker worker.Worker
InstructionCache InstructionCache
ImageSource source.Source
Frontends map[string]frontend.Frontend // used by nested invocations
}
func NewLLBSolver(opt LLBOpt) *Solver {
@ -45,7 +45,7 @@ func NewLLBSolver(opt LLBOpt) *Solver {
default:
return nil, nil
}
}, opt.InstructionCache, opt.ImageSource, opt.Worker, opt.CacheManager)
}, opt.InstructionCache, opt.ImageSource, opt.Worker, opt.CacheManager, opt.Frontends)
return s
}
@ -79,46 +79,55 @@ type Solver struct {
imageSource source.Source
worker worker.Worker
cm cache.Manager // TODO: remove with immutableRef.New()
frontends map[string]frontend.Frontend
}
func New(resolve ResolveOpFunc, cache InstructionCache, imageSource source.Source, worker worker.Worker, cm cache.Manager) *Solver {
return &Solver{resolve: resolve, jobs: newJobList(), cache: cache, imageSource: imageSource, worker: worker, cm: cm}
func New(resolve ResolveOpFunc, cache InstructionCache, imageSource source.Source, worker worker.Worker, cm cache.Manager, f map[string]frontend.Frontend) *Solver {
return &Solver{resolve: resolve, jobs: newJobList(), cache: cache, imageSource: imageSource, worker: worker, cm: cm, frontends: f}
}
func (s *Solver) Solve(ctx context.Context, id string, f frontend.Frontend, def *pb.Definition, exp exporter.ExporterInstance, frontendOpt map[string]string, allFrontends map[string]frontend.Frontend) error {
type SolveRequest struct {
Definition *pb.Definition
Frontend frontend.Frontend
Exporter exporter.ExporterInstance
FrontendOpt map[string]string
}
func (s *Solver) solve(ctx context.Context, j *job, req SolveRequest) (Reference, map[string][]byte, error) {
if req.Definition == nil {
if req.Frontend == nil {
return nil, nil, errors.Errorf("invalid request: no definition nor frontend")
}
return req.Frontend.Solve(ctx, s.llbBridge(j), req.FrontendOpt)
}
inp, err := j.load(req.Definition, s.resolve)
if err != nil {
return nil, nil, err
}
ref, err := j.getRef(ctx, inp.Vertex.(*vertex), inp.Index)
return ref, nil, err
}
func (s *Solver) llbBridge(j *job) *llbBridge {
return &llbBridge{job: j, Solver: s, resolveImageConfig: s.imageSource.(resolveImageConfig)}
}
func (s *Solver) Solve(ctx context.Context, id string, req SolveRequest) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
pr, ctx, closeProgressWriter := progress.NewContext(ctx)
defer closeProgressWriter()
// register a build job. vertex needs to be loaded to a job to run
ctx, j, err := s.jobs.new(ctx, id, pr, s.cache)
if err != nil {
return err
}
var ref Reference
var exporterOpt map[string][]byte
if def != nil {
var inp *Input
inp, err = j.load(def, s.resolve)
if err != nil {
j.discard()
return err
}
ref, err = j.getRef(ctx, inp.Vertex.(*vertex), inp.Index)
} else {
ref, exporterOpt, err = f.Solve(ctx, &llbBridge{
worker: s.worker,
job: j,
cm: s.cm,
resolveOp: s.resolve,
resolveImageConfig: s.imageSource.(resolveImageConfig),
allFrontends: allFrontends,
}, frontendOpt)
}
j.discard()
ref, exporterOpt, err := s.solve(ctx, j, req)
defer j.discard()
if err != nil {
return err
}
@ -135,19 +144,10 @@ func (s *Solver) Solve(ctx context.Context, id string, f frontend.Frontend, def
return err
}
if exp != nil {
v := client.Vertex{
Digest: digest.FromBytes([]byte(identity.NewID())),
Name: exp.Name(),
}
notifyStarted(ctx, &v)
pw, _, ctx := progress.FromContext(ctx, progress.WithMetadata("vertex", v.Digest))
defer pw.Close()
err := exp.Export(ctx, immutable, exporterOpt)
notifyCompleted(ctx, &v, err)
if err != nil {
return err
}
if exp := req.Exporter; exp != nil {
return inVertexContext(ctx, exp.Name(), func(ctx context.Context) error {
return exp.Export(ctx, immutable, exporterOpt)
})
}
return err
}
@ -571,39 +571,29 @@ type VertexResult struct {
// llbBridge is an helper used by frontends
type llbBridge struct {
*Solver
job *job
resolveImageConfig
job *job
resolveOp ResolveOpFunc
worker worker.Worker
allFrontends map[string]frontend.Frontend
cm cache.Manager
}
type resolveImageConfig interface {
ResolveImageConfig(ctx context.Context, ref string) (digest.Digest, []byte, error)
}
func (s *llbBridge) Solve(ctx context.Context, def *pb.Definition, frontend string, opts map[string]string) (cache.ImmutableRef, map[string][]byte, error) {
if def == nil {
f, ok := s.allFrontends[frontend]
func (s *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest) (cache.ImmutableRef, map[string][]byte, error) {
var f frontend.Frontend
if req.Frontend != "" {
var ok bool
f, ok = s.frontends[req.Frontend]
if !ok {
return nil, nil, errors.Errorf("invalid frontend: %s", frontend)
return nil, nil, errors.Errorf("invalid frontend: %s", req.Frontend)
}
ref, exporterOpt, err := f.Solve(ctx, s, opts)
if err != nil {
return nil, nil, err
}
immutable, ok := toImmutableRef(ref)
if !ok {
return nil, nil, errors.Errorf("invalid reference for exporting: %T", ref)
}
return immutable, exporterOpt, nil
}
inp, err := s.job.load(def, s.resolveOp)
if err != nil {
return nil, nil, err
}
ref, err := s.job.getRef(ctx, inp.Vertex.(*vertex), inp.Index)
ref, exp, err := s.solve(ctx, s.job, SolveRequest{
Definition: req.Definition,
Frontend: f,
FrontendOpt: req.FrontendOpt,
})
if err != nil {
return nil, nil, err
}
@ -611,8 +601,7 @@ func (s *llbBridge) Solve(ctx context.Context, def *pb.Definition, frontend stri
if !ok {
return nil, nil, errors.Errorf("invalid reference for exporting: %T", ref)
}
return immutable, nil, nil
return immutable, exp, nil
}
func (s *llbBridge) Exec(ctx context.Context, meta worker.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error {

View File

@ -1,13 +1,14 @@
package solver
import (
"context"
"sync"
"time"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/progress"
digest "github.com/opencontainers/go-digest"
"golang.org/x/net/context"
)
// Vertex is one node in the build graph
@ -112,3 +113,16 @@ func notifyCompleted(ctx context.Context, v *client.Vertex, err error) {
}
pw.Write(v.Digest.String(), *v)
}
func inVertexContext(ctx context.Context, name string, f func(ctx context.Context) error) error {
v := client.Vertex{
Digest: digest.FromBytes([]byte(identity.NewID())),
Name: name,
}
pw, _, ctx := progress.FromContext(ctx, progress.WithMetadata("vertex", v.Digest))
notifyStarted(ctx, &v)
defer pw.Close()
err := f(ctx)
notifyCompleted(ctx, &v, err)
return err
}