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…
	
	Add table
		Add a link
		
	
		Reference in a new issue