mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
builder: add graceful cancellation endpoint
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
parent
22f7caee03
commit
0bddd4ccfe
9 changed files with 71 additions and 2 deletions
|
@ -79,8 +79,10 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
|
|||
}
|
||||
}
|
||||
|
||||
stdout := config.ProgressWriter.StdoutFormatter
|
||||
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
|
||||
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 {
|
||||
|
|
|
@ -15,6 +15,8 @@ type Backend interface {
|
|||
|
||||
// Prune build cache
|
||||
PruneCache(context.Context) (*types.BuildCachePruneReport, error)
|
||||
|
||||
Cancel(context.Context, string) error
|
||||
}
|
||||
|
||||
type experimentalProvider interface {
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -181,6 +181,7 @@ type ImageBuildOptions struct {
|
|||
Target string
|
||||
SessionID string
|
||||
Platform string
|
||||
BuildID string
|
||||
}
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
|
|
|
@ -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
21
client/build_cancel.go
Normal 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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue