builder: add graceful cancellation endpoint

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2018-04-19 11:08:33 -07:00
parent 22f7caee03
commit 0bddd4ccfe
9 changed files with 71 additions and 2 deletions

View File

@ -79,8 +79,10 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
}
}
if !useBuildKit {
stdout := config.ProgressWriter.StdoutFormatter
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
}
err = tagger.TagImages(image.ID(imageID))
return imageID, err
}
@ -94,6 +96,10 @@ func (b *Backend) PruneCache(ctx context.Context) (*types.BuildCachePruneReport,
return &types.BuildCachePruneReport{SpaceReclaimed: size}, nil
}
func (b *Backend) Cancel(ctx context.Context, id string) error {
return b.buildkit.Cancel(ctx, id)
}
func squashBuild(build *builder.Result, imageComponent ImageComponent) (string, error) {
var fromID string
if build.FromImage != nil {

View File

@ -15,6 +15,8 @@ type Backend interface {
// Prune build cache
PruneCache(context.Context) (*types.BuildCachePruneReport, error)
Cancel(context.Context, string) error
}
type experimentalProvider interface {

View File

@ -25,5 +25,6 @@ func (r *buildRouter) initRoutes() {
r.routes = []router.Route{
router.NewPostRoute("/build", r.postBuild, router.WithCancel),
router.NewPostRoute("/build/prune", r.postPrune, router.WithCancel),
router.NewPostRoute("/build/cancel", r.postCancel),
}
}

View File

@ -145,6 +145,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
options.CacheFrom = cacheFrom
}
options.SessionID = r.FormValue("session")
options.BuildID = r.FormValue("buildid")
return options, nil
}
@ -157,6 +158,17 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
return httputils.WriteJSON(w, http.StatusOK, report)
}
func (br *buildRouter) postCancel(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
w.Header().Set("Content-Type", "application/json")
id := r.FormValue("id")
if id == "" {
return errors.Errorf("build ID not provided")
}
return br.backend.Cancel(ctx, id)
}
func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
var (
notVerboseBuffer = bytes.NewBuffer(nil)

View File

@ -181,6 +181,7 @@ type ImageBuildOptions struct {
Target string
SessionID string
Platform string
BuildID string
}
// ImageBuildResponse holds information

View File

@ -59,6 +59,9 @@ type Opt struct {
type Builder struct {
controller *control.Controller
results *results
mu sync.Mutex
jobs map[string]func()
}
func New(opt Opt) (*Builder, error) {
@ -71,11 +74,30 @@ func New(opt Opt) (*Builder, error) {
b := &Builder{
controller: c,
results: results,
jobs: map[string]func(){},
}
return b, nil
}
func (b *Builder) Cancel(ctx context.Context, id string) error {
b.mu.Lock()
if cancel, ok := b.jobs[id]; ok {
cancel()
}
b.mu.Unlock()
return nil
}
func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.Result, error) {
if buildID := opt.Options.BuildID; buildID != "" {
b.mu.Lock()
ctx, b.jobs[buildID] = context.WithCancel(ctx)
b.mu.Unlock()
defer func() {
delete(b.jobs, buildID)
}()
}
id := identity.NewID()
attrs := map[string]string{

21
client/build_cancel.go Normal file
View File

@ -0,0 +1,21 @@
package client // import "github.com/docker/docker/client"
import (
"net/url"
"golang.org/x/net/context"
)
// BuildCancel requests the daemon to cancel ongoing build request
func (cli *Client) BuildCancel(ctx context.Context, id string) error {
query := url.Values{}
query.Set("id", id)
serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
if err != nil {
return err
}
defer ensureReaderClosed(serverResp)
return nil
}

View File

@ -133,5 +133,8 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
if options.BuildID != "" {
query.Set("buildid", options.BuildID)
}
return query, nil
}

View File

@ -86,6 +86,7 @@ type DistributionAPIClient interface {
type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error)
BuildCancel(ctx context.Context, id string) error
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)