Browse code

builder: return image ID in API when using buildkit

Signed-off-by: Tibor Vass <tibor@docker.com>

Tibor Vass authored on 2018/06/12 03:48:42
Showing 6 changed files
... ...
@@ -73,7 +73,7 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
73 73
 			return "", err
74 74
 		}
75 75
 		if config.ProgressWriter.AuxFormatter != nil {
76
-			if err = config.ProgressWriter.AuxFormatter.Emit(types.BuildResult{ID: imageID}); err != nil {
76
+			if err = config.ProgressWriter.AuxFormatter.Emit("moby.image.id", types.BuildResult{ID: imageID}); err != nil {
77 77
 				return "", err
78 78
 			}
79 79
 		}
... ...
@@ -243,6 +243,10 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
243 243
 		return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
244 244
 	}
245 245
 
246
+	if buildOptions.Version == types.BuilderBuildKit && !br.daemon.HasExperimental() {
247
+		return errdefs.InvalidParameter(errors.New("buildkit is only supported with experimental mode"))
248
+	}
249
+
246 250
 	out := io.Writer(output)
247 251
 	if buildOptions.SuppressOutput {
248 252
 		out = notVerboseBuffer
... ...
@@ -255,10 +259,6 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
255 255
 		return progress.NewProgressReader(in, progressOutput, r.ContentLength, "Downloading context", buildOptions.RemoteContext)
256 256
 	}
257 257
 
258
-	if buildOptions.Version == types.BuilderBuildKit && !br.daemon.HasExperimental() {
259
-		return errdefs.InvalidParameter(errors.New("buildkit is only supported with experimental mode"))
260
-	}
261
-
262 258
 	wantAux := versions.GreaterThanOrEqualTo(version, "1.30")
263 259
 
264 260
 	imgID, err := br.backend.Build(ctx, backend.BuildConfig{
... ...
@@ -2,7 +2,6 @@ package buildkit
2 2
 
3 3
 import (
4 4
 	"context"
5
-	"encoding/json"
6 5
 	"io"
7 6
 	"strings"
8 7
 	"sync"
... ...
@@ -14,7 +13,7 @@ import (
14 14
 	"github.com/docker/docker/api/types/backend"
15 15
 	"github.com/docker/docker/builder"
16 16
 	"github.com/docker/docker/daemon/images"
17
-	"github.com/docker/docker/pkg/jsonmessage"
17
+	"github.com/docker/docker/pkg/streamformatter"
18 18
 	controlapi "github.com/moby/buildkit/api/services/control"
19 19
 	"github.com/moby/buildkit/control"
20 20
 	"github.com/moby/buildkit/identity"
... ...
@@ -228,6 +227,8 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
228 228
 		Session:       opt.Options.SessionID,
229 229
 	}
230 230
 
231
+	aux := streamformatter.AuxFormatter{opt.ProgressWriter.Output}
232
+
231 233
 	eg, ctx := errgroup.WithContext(ctx)
232 234
 
233 235
 	eg.Go(func() error {
... ...
@@ -240,7 +241,7 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
240 240
 			return errors.Errorf("missing image id")
241 241
 		}
242 242
 		out.ImageID = id
243
-		return nil
243
+		return aux.Emit("moby.image.id", types.BuildResult{ID: id})
244 244
 	})
245 245
 
246 246
 	ch := make(chan *controlapi.StatusResponse)
... ...
@@ -258,25 +259,9 @@ func (b *Builder) Build(ctx context.Context, opt backend.BuildConfig) (*builder.
258 258
 			if err != nil {
259 259
 				return err
260 260
 			}
261
-
262
-			auxJSONBytes, err := json.Marshal(dt)
263
-			if err != nil {
261
+			if err := aux.Emit("moby.buildkit.trace", dt); err != nil {
264 262
 				return err
265 263
 			}
266
-			auxJSON := new(json.RawMessage)
267
-			*auxJSON = auxJSONBytes
268
-			msgJSON, err := json.Marshal(&jsonmessage.JSONMessage{ID: "moby.buildkit.trace", Aux: auxJSON})
269
-			if err != nil {
270
-				return err
271
-			}
272
-			msgJSON = append(msgJSON, []byte("\r\n")...)
273
-			n, err := opt.ProgressWriter.Output.Write(msgJSON)
274
-			if err != nil {
275
-				return err
276
-			}
277
-			if n != len(msgJSON) {
278
-				return io.ErrShortWrite
279
-			}
280 264
 		}
281 265
 		return nil
282 266
 	})
... ...
@@ -257,7 +257,7 @@ func emitImageID(aux *streamformatter.AuxFormatter, state *dispatchState) error
257 257
 	if aux == nil || state.imageID == "" {
258 258
 		return nil
259 259
 	}
260
-	return aux.Emit(types.BuildResult{ID: state.imageID})
260
+	return aux.Emit("", types.BuildResult{ID: state.imageID})
261 261
 }
262 262
 
263 263
 func processMetaArg(meta instructions.ArgCommand, shlex *shell.Lex, args *BuildArgs) error {
... ...
@@ -139,14 +139,14 @@ type AuxFormatter struct {
139 139
 }
140 140
 
141 141
 // Emit emits the given interface as an aux progress message
142
-func (sf *AuxFormatter) Emit(aux interface{}) error {
142
+func (sf *AuxFormatter) Emit(id string, aux interface{}) error {
143 143
 	auxJSONBytes, err := json.Marshal(aux)
144 144
 	if err != nil {
145 145
 		return err
146 146
 	}
147 147
 	auxJSON := new(json.RawMessage)
148 148
 	*auxJSON = auxJSONBytes
149
-	msgJSON, err := json.Marshal(&jsonmessage.JSONMessage{Aux: auxJSON})
149
+	msgJSON, err := json.Marshal(&jsonmessage.JSONMessage{ID: id, Aux: auxJSON})
150 150
 	if err != nil {
151 151
 		return err
152 152
 	}
... ...
@@ -106,7 +106,7 @@ func TestAuxFormatterEmit(t *testing.T) {
106 106
 	sampleAux := &struct {
107 107
 		Data string
108 108
 	}{"Additional data"}
109
-	err := aux.Emit(sampleAux)
109
+	err := aux.Emit("", sampleAux)
110 110
 	assert.NilError(t, err)
111 111
 	assert.Check(t, is.Equal(`{"aux":{"Data":"Additional data"}}`+streamNewline, b.String()))
112 112
 }