feat: improve docker build and push output (#1364)

Signed-off-by: Matej Vasek <mvasek@redhat.com>

Signed-off-by: Matej Vasek <mvasek@redhat.com>
This commit is contained in:
Matej Vasek 2022-10-21 16:10:17 +02:00 committed by GitHub
parent fe81e235d3
commit cc063f79fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 81 deletions

View File

@ -17,11 +17,13 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/daemon"
"github.com/google/go-containerregistry/pkg/v1/remote"
"golang.org/x/term"
)
type Opt func(*Pusher)
@ -176,34 +178,19 @@ func (n *Pusher) daemonPush(ctx context.Context, f fn.Function, credentials Cred
var outBuff bytes.Buffer
output = io.MultiWriter(&outBuff, output)
decoder := json.NewDecoder(r)
li := logItem{}
for {
err = decoder.Decode(&li)
if err != nil {
if errors.Is(err, io.EOF) {
err = nil
}
break
}
if li.Error != "" {
return "", errors.New(li.ErrorDetail.Message)
}
if li.Id != "" {
fmt.Fprintf(output, "%s: ", li.Id)
}
var percent int
if li.ProgressDetail.Total == 0 {
percent = 100
} else {
percent = (li.ProgressDetail.Current * 100) / li.ProgressDetail.Total
}
fmt.Fprintf(output, "%s (%d%%)\n", li.Status, percent)
var isTerminal bool
var fd uintptr
if outF, ok := output.(*os.File); ok {
fd = outF.Fd()
isTerminal = term.IsTerminal(int(outF.Fd()))
}
digest = ParseDigest(outBuff.String())
err = jsonmessage.DisplayJSONMessagesStream(r, output, fd, isTerminal, nil)
if err != nil {
return "", err
}
return digest, nil
return ParseDigest(outBuff.String()), nil
}
var digestRE = regexp.MustCompile(`digest:\s+(sha256:\w{64})`)
@ -219,24 +206,6 @@ func ParseDigest(output string) string {
return ""
}
type errorDetail struct {
Message string `json:"message"`
}
type progressDetail struct {
Current int `json:"current"`
Total int `json:"total"`
}
type logItem struct {
Id string `json:"id"`
Status string `json:"status"`
Error string `json:"error"`
ErrorDetail errorDetail `json:"errorDetail"`
Progress string `json:"progress"`
ProgressDetail progressDetail `json:"progressDetail"`
}
func (n *Pusher) push(ctx context.Context, f fn.Function, credentials Credentials, output io.Writer) (digest string, err error) {
auth := &authn.Basic{
Username: credentials.Username,

View File

@ -3,7 +3,6 @@ package s2i
import (
"archive/tar"
"context"
"encoding/json"
"errors"
"fmt"
"io"
@ -15,6 +14,7 @@ import (
"github.com/docker/docker/api/types"
dockerClient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
@ -24,6 +24,7 @@ import (
"github.com/openshift/source-to-image/pkg/build/strategies"
s2idocker "github.com/openshift/source-to-image/pkg/docker"
"github.com/openshift/source-to-image/pkg/scm/git"
"golang.org/x/term"
fn "knative.dev/func"
"knative.dev/func/builders"
@ -281,45 +282,14 @@ func (b *Builder) Build(ctx context.Context, f fn.Function) (err error) {
out = os.Stderr
}
errMsg, err := parseBuildResponse(resp.Body, out)
if err != nil {
return fmt.Errorf("cannot parse response body: %w", err)
}
if errMsg != "" {
return fmt.Errorf("cannot build the app: %s", errMsg)
var isTerminal bool
var fd uintptr
if outF, ok := out.(*os.File); ok {
fd = outF.Fd()
isTerminal = term.IsTerminal(int(outF.Fd()))
}
return nil
}
func parseBuildResponse(r io.Reader, w io.Writer) (errorMessage string, err error) {
obj := struct {
ErrorDetail struct {
Message string `json:"message"`
} `json:"errorDetail"`
Stream string `json:"stream"`
}{}
d := json.NewDecoder(r)
for {
err = d.Decode(&obj)
if err != nil {
if errors.Is(err, io.EOF) {
break
}
return "", err
}
if obj.ErrorDetail.Message != "" {
errorMessage = obj.ErrorDetail.Message
return errorMessage, nil
}
if obj.Stream != "" {
_, err = w.Write([]byte(obj.Stream))
if err != nil {
return "", err
}
}
}
return "", nil
return jsonmessage.DisplayJSONMessagesStream(resp.Body, out, fd, isTerminal, nil)
}
func s2iScriptURL(ctx context.Context, cli DockerClient, image string) (string, error) {