Skip to content

Commit 0bddd4c

Browse files
committed
builder: add graceful cancellation endpoint
Signed-off-by: Tonis Tiigi <[email protected]>
1 parent 22f7cae commit 0bddd4c

9 files changed

Lines changed: 71 additions & 2 deletions

File tree

api/server/backend/build/backend.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
7979
}
8080
}
8181

82-
stdout := config.ProgressWriter.StdoutFormatter
83-
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
82+
if !useBuildKit {
83+
stdout := config.ProgressWriter.StdoutFormatter
84+
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
85+
}
8486
err = tagger.TagImages(image.ID(imageID))
8587
return imageID, err
8688
}
@@ -94,6 +96,10 @@ func (b *Backend) PruneCache(ctx context.Context) (*types.BuildCachePruneReport,
9496
return &types.BuildCachePruneReport{SpaceReclaimed: size}, nil
9597
}
9698

99+
func (b *Backend) Cancel(ctx context.Context, id string) error {
100+
return b.buildkit.Cancel(ctx, id)
101+
}
102+
97103
func squashBuild(build *builder.Result, imageComponent ImageComponent) (string, error) {
98104
var fromID string
99105
if build.FromImage != nil {

api/server/router/build/backend.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ type Backend interface {
1515

1616
// Prune build cache
1717
PruneCache(context.Context) (*types.BuildCachePruneReport, error)
18+
19+
Cancel(context.Context, string) error
1820
}
1921

2022
type experimentalProvider interface {

api/server/router/build/build.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ func (r *buildRouter) initRoutes() {
2525
r.routes = []router.Route{
2626
router.NewPostRoute("/build", r.postBuild, router.WithCancel),
2727
router.NewPostRoute("/build/prune", r.postPrune, router.WithCancel),
28+
router.NewPostRoute("/build/cancel", r.postCancel),
2829
}
2930
}

api/server/router/build/build_routes.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
145145
options.CacheFrom = cacheFrom
146146
}
147147
options.SessionID = r.FormValue("session")
148+
options.BuildID = r.FormValue("buildid")
148149

149150
return options, nil
150151
}
@@ -157,6 +158,17 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
157158
return httputils.WriteJSON(w, http.StatusOK, report)
158159
}
159160

161+
func (br *buildRouter) postCancel(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
162+
w.Header().Set("Content-Type", "application/json")
163+
164+
id := r.FormValue("id")
165+
if id == "" {
166+
return errors.Errorf("build ID not provided")
167+
}
168+
169+
return br.backend.Cancel(ctx, id)
170+
}
171+
160172
func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
161173
var (
162174
notVerboseBuffer = bytes.NewBuffer(nil)

api/types/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ type ImageBuildOptions struct {
181181
Target string
182182
SessionID string
183183
Platform string
184+
BuildID string
184185
}
185186

186187
// ImageBuildResponse holds information

builder/builder-next/builder.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ type Opt struct {
5959
type Builder struct {
6060
controller *control.Controller
6161
results *results
62+
63+
mu sync.Mutex
64+
jobs map[string]func()
6265
}
6366

6467
func New(opt Opt) (*Builder, error) {
@@ -71,11 +74,30 @@ func New(opt Opt) (*Builder, error) {
7174
b := &Builder{
7275
controller: c,
7376
results: results,
77+
jobs: map[string]func(){},
7478
}
7579
return b, nil
7680
}
7781

82+
func (b *Builder) Cancel(ctx context.Context, id string) error {
83+
b.mu.Lock()
84+
if cancel, ok := b.jobs[id]; ok {
85+
cancel()
86+
}
87+
b.mu.Unlock()
88+
return nil
89+
}
90+
7891
func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.Result, error) {
92+
if buildID := opt.Options.BuildID; buildID != "" {
93+
b.mu.Lock()
94+
ctx, b.jobs[buildID] = context.WithCancel(ctx)
95+
b.mu.Unlock()
96+
defer func() {
97+
delete(b.jobs, buildID)
98+
}()
99+
}
100+
79101
id := identity.NewID()
80102

81103
attrs := map[string]string{

client/build_cancel.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package client // import "github.com/docker/docker/client"
2+
3+
import (
4+
"net/url"
5+
6+
"golang.org/x/net/context"
7+
)
8+
9+
// BuildCancel requests the daemon to cancel ongoing build request
10+
func (cli *Client) BuildCancel(ctx context.Context, id string) error {
11+
query := url.Values{}
12+
query.Set("id", id)
13+
14+
serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
15+
if err != nil {
16+
return err
17+
}
18+
defer ensureReaderClosed(serverResp)
19+
20+
return nil
21+
}

client/image_build.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,8 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
133133
if options.Platform != "" {
134134
query.Set("platform", strings.ToLower(options.Platform))
135135
}
136+
if options.BuildID != "" {
137+
query.Set("buildid", options.BuildID)
138+
}
136139
return query, nil
137140
}

client/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ type DistributionAPIClient interface {
8686
type ImageAPIClient interface {
8787
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
8888
BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error)
89+
BuildCancel(ctx context.Context, id string) error
8990
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
9091
ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
9192
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)

0 commit comments

Comments
 (0)