errdefs: attach source to an error

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2020-04-21 21:40:44 -07:00
parent cce301badd
commit abbda4e941
4 changed files with 81 additions and 2 deletions

View File

@@ -304,6 +304,10 @@ func buildAction(clicontext *cli.Context) error {
if errors.As(err, &ve) {
log.Printf("error-vertex: %s", ve.Digest)
}
for _, s := range errdefs.Sources(err) {
log.Printf("source: %+v", s)
}
}
return err

View File

@@ -19,8 +19,10 @@ import (
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
"github.com/moby/buildkit/frontend/dockerfile/parser"
"github.com/moby/buildkit/frontend/gateway/client"
gwpb "github.com/moby/buildkit/frontend/gateway/pb"
"github.com/moby/buildkit/solver/errdefs"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/apicaps"
specs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -132,9 +134,11 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
var buildContext *llb.State
isNotLocalContext := false
isNotLocalDockerfile := false
if st, ok := detectGitContext(opts[localNameContext], opts[keyContextKeepGitDir]); ok {
if !forceLocalDockerfile {
src = *st
isNotLocalDockerfile = true
}
buildContext = st
} else if httpPrefix.MatchString(opts[localNameContext]) {
@@ -184,6 +188,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
bc := unpack.AddMount("/out", llb.Scratch())
if !forceLocalDockerfile {
src = bc
isNotLocalDockerfile = true
}
buildContext = &bc
}
@@ -191,6 +196,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
filename = "context"
if !forceLocalDockerfile {
src = httpContext
isNotLocalDockerfile = true
}
buildContext = &httpContext
isNotLocalContext = true
@@ -205,6 +211,7 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
inputDockerfile, ok := inputs[DefaultLocalNameDockerfile]
if ok {
src = inputDockerfile
isNotLocalDockerfile = true
}
}
@@ -338,7 +345,16 @@ func Build(ctx context.Context, c client.Client) (*client.Result, error) {
for i, tp := range targetPlatforms {
func(i int, tp *specs.Platform) {
eg.Go(func() error {
eg.Go(func() (err error) {
defer func() {
var el *parser.ErrorLocation
if errors.As(err, &el) {
if isNotLocalDockerfile {
localNameDockerfile = ""
}
err = wrapSource(err, dtDockerfile, filename, localNameDockerfile, el.Ranges)
}
}()
st, img, err := dockerfile2llb.Dockerfile2LLB(ctx, dtDockerfile, dockerfile2llb.ConvertOpt{
Target: opts[keyTarget],
MetaResolver: c,
@@ -639,3 +655,25 @@ func scopeToSubDir(c *llb.State, fileop bool, dir string) *llb.State {
bc := unpack.AddMount("/out", llb.Scratch())
return &bc
}
func wrapSource(err error, dt []byte, filename, local string, locations []parser.Range) error {
s := errdefs.Source{
Data: dt,
Filename: filename,
Local: local,
Locations: make([]*errdefs.Range, 0, len(locations)),
}
for _, l := range locations {
s.Locations = append(s.Locations, &errdefs.Range{
Start: &errdefs.Position{
Line: int32(l.Start.Line),
Character: int32(l.Start.Character),
},
End: &errdefs.Position{
Line: int32(l.End.Line),
Character: int32(l.End.Character),
},
})
}
return errdefs.WithSource(err, s)
}

View File

@@ -30,6 +30,10 @@ func ToGRPC(err error) error {
details = append(details, st)
}
for _, st := range Sources(err) {
details = append(details, st)
}
var ve *VertexError
if errors.As(err, &ve) {
details = append(details, &ve.Vertex)
@@ -111,7 +115,7 @@ func FromGRPC(err error) error {
continue
}
switch detail.Message.(type) {
case *Stack, *Vertex:
case *Stack, *Vertex, *Source:
details = append(details, detail.Message)
default:
n.Details = append(n.Details, d)
@@ -128,6 +132,10 @@ func FromGRPC(err error) error {
}
case *Vertex:
err = WrapVertex(err, digest.Digest(v.Digest))
case *Source:
if v != nil {
err = WithSource(err, *v)
}
}
}

29
solver/errdefs/source.go Normal file
View File

@@ -0,0 +1,29 @@
package errdefs
import "github.com/pkg/errors"
func WithSource(err error, src Source) error {
if err == nil {
return nil
}
return &ErrorSource{Source: src, error: err}
}
type ErrorSource struct {
Source
error
}
func (e *ErrorSource) Unwrap() error {
return e.error
}
func Sources(err error) []*Source {
var out []*Source
var es *ErrorSource
if errors.As(err, &es) {
out = Sources(es.Unwrap())
out = append(out, &es.Source)
}
return out
}