Skip to content

Commit

Permalink
build: sublogger to show docker load progress output
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <[email protected]>
  • Loading branch information
crazy-max committed Sep 11, 2023
1 parent 42a0f3d commit 363db3d
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 38 deletions.
10 changes: 3 additions & 7 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,9 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
return nil, nil, err
}
defers = append(defers, cancel)
opt.Exports[i].Output = wrapWriteCloser(w)
opt.Exports[i].Output = func(_ map[string]string) (io.WriteCloser, error) {
return w, nil
}
}
} else if !nodeDriver.Features(ctx)[driver.DockerExporter] {
return nil, nil, notSupported(nodeDriver, driver.DockerExporter)
Expand Down Expand Up @@ -1607,12 +1609,6 @@ func handleLowercaseDockerfile(dir, p string) string {
return p
}

func wrapWriteCloser(wc io.WriteCloser) func(map[string]string) (io.WriteCloser, error) {
return func(map[string]string) (io.WriteCloser, error) {
return wc, nil
}
}

var nodeIdentifierMu sync.Mutex

func tryNodeIdentifier(configDir string) (out string) {
Expand Down
6 changes: 4 additions & 2 deletions util/dockerutil/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ func (c *Client) LoadImage(ctx context.Context, name string, status progress.Wri
return
}

prog := progress.WithPrefix(status, "", false)
if err := fromReader(prog, "importing to docker", resp.Body); err != nil {
status = progress.ResetTime(status)
if err := progress.Wrap("importing to docker", status.Write, func(l progress.SubLogger) error {
return fromReader(l, resp.Body)
}); err != nil {
handleErr(err)
}
},
Expand Down
90 changes: 61 additions & 29 deletions util/dockerutil/progress.go
Original file line number Diff line number Diff line change
@@ -1,47 +1,79 @@
package dockerutil

import (
"errors"
"encoding/json"
"io"
"time"

"github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity"
"github.com/opencontainers/go-digest"
)

func fromReader(w progress.Writer, name string, rc io.ReadCloser) error {
dgst := digest.FromBytes([]byte(identity.NewID()))
tm := time.Now()
const minProgressDelta = 0.50 // %

vtx := client.Vertex{
Digest: dgst,
Name: name,
Started: &tm,
}
func fromReader(l progress.SubLogger, rc io.ReadCloser) error {
started := map[string]client.VertexStatus{}

w.Write(&client.SolveStatus{
Vertexes: []*client.Vertex{&vtx},
})
defer func() {
for _, st := range started {
st := st
if st.Completed == nil {
now := time.Now()
st.Completed = &now
l.SetStatus(&st)
}
}
}()

err := jsonmessage.DisplayJSONMessagesToStream(rc, streams.NewOut(io.Discard), nil)
if err != nil {
if jerr, ok := err.(*jsonmessage.JSONError); ok {
err = errors.New(jerr.Message)
dec := json.NewDecoder(rc)
var parsedErr error
var jm jsonmessage.JSONMessage
for {
if err := dec.Decode(&jm); err != nil {
if parsedErr != nil {
return parsedErr
}
if err == io.EOF {
break
}
return err
}
if jm.Error != nil {
parsedErr = jm.Error
}
if jm.ID == "" {
continue
}
id := "loading layer " + jm.ID
st, ok := started[id]
if !ok {
if jm.Progress != nil {
now := time.Now()
st = client.VertexStatus{
ID: id,
Started: &now,
}
} else {
continue
}
}
st.Timestamp = time.Now()
var progressDelta float64
if jm.Progress != nil && jm.Progress.Total > 0 {
progressDelta = float64(jm.Progress.Current-st.Current) / float64(jm.Progress.Total)
}
if jm.Progress != nil && jm.Status == "Loading layer" && (st.Current == 0 || progressDelta >= minProgressDelta) {
st.Current = jm.Progress.Current
st.Total = jm.Progress.Total
}
if jm.Error != nil {
now := time.Now()
st.Completed = &now
}
started[id] = st
l.SetStatus(&st)
}

tm2 := time.Now()
vtx2 := vtx
vtx2.Completed = &tm2
if err != nil {
vtx2.Error = err.Error()
}
w.Write(&client.SolveStatus{
Vertexes: []*client.Vertex{&vtx2},
})
return err
return nil
}

0 comments on commit 363db3d

Please sign in to comment.