From 4bd0ffd3fc4a4150272487fb5eaf4282b73b86ed Mon Sep 17 00:00:00 2001 From: Andrea Luzzardi Date: Thu, 25 Feb 2021 14:17:01 -0800 Subject: [PATCH] FetchContainer: Inject Docker image metadata into LLB Fixes #130 Signed-off-by: Andrea Luzzardi --- dagger/fs.go | 2 +- dagger/pipeline.go | 49 ++++++++++++++++++++++++++++++++++++++++++---- dagger/solver.go | 18 +++++++++++++++++ go.mod | 1 + stdlib/go/go.cue | 10 ++-------- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/dagger/fs.go b/dagger/fs.go index 44dc0a95..e158bf20 100644 --- a/dagger/fs.go +++ b/dagger/fs.go @@ -196,7 +196,7 @@ func bkCleanError(err error) error { noise := []string{ "executor failed running ", "buildkit-runc did not terminate successfully", - "rpc error: code = Unknown desc =", + "rpc error: code = Unknown desc = ", "failed to solve: ", } diff --git a/dagger/pipeline.go b/dagger/pipeline.go index 606c7b75..6b8784ab 100644 --- a/dagger/pipeline.go +++ b/dagger/pipeline.go @@ -7,6 +7,7 @@ import ( "fmt" "strings" + "github.com/docker/distribution/reference" "github.com/moby/buildkit/client/llb" dockerfilebuilder "github.com/moby/buildkit/frontend/dockerfile/builder" bkgw "github.com/moby/buildkit/frontend/gateway/client" @@ -484,17 +485,57 @@ func (p *Pipeline) Load(ctx context.Context, op *compiler.Value) error { } func (p *Pipeline) FetchContainer(ctx context.Context, op *compiler.Value) error { - ref, err := op.Get("ref").String() + rawRef, err := op.Get("ref").String() if err != nil { return err } - // FIXME: preserve docker image metadata - p.fs = p.fs.Set( - llb.Image(ref, llb.WithCustomName(p.vertexNamef("FetchContainer %s", ref))), + + ref, err := reference.ParseNormalizedNamed(rawRef) + if err != nil { + return fmt.Errorf("failed to parse ref %s: %w", rawRef, err) + } + // Add the default tag "latest" to a reference if it only has a repo name. + ref = reference.TagNameOnly(ref) + + state := llb.Image( + ref.String(), + llb.WithCustomName(p.vertexNamef("FetchContainer %s", rawRef)), ) + + // Load image metadata and convert to to LLB. + // FIXME: metadata MUST be injected back into the gateway result + // FIXME: there are unhandled sections of the image config + image, err := p.s.ResolveImageConfig(ctx, ref.String(), llb.ResolveImageConfigOpt{ + LogName: p.vertexNamef("load metadata for %s", ref.String()), + }) + if err != nil { + return err + } + + for _, env := range image.Config.Env { + k, v := parseKeyValue(env) + state = state.AddEnv(k, v) + } + if image.Config.WorkingDir != "" { + state = state.Dir(image.Config.WorkingDir) + } + if image.Config.User != "" { + state = state.User(image.Config.User) + } + p.fs = p.fs.Set(state) return nil } +func parseKeyValue(env string) (string, string) { + parts := strings.SplitN(env, "=", 2) + v := "" + if len(parts) > 1 { + v = parts[1] + } + + return parts[0], v +} + func (p *Pipeline) FetchGit(ctx context.Context, op *compiler.Value) error { remote, err := op.Get("remote").String() if err != nil { diff --git a/dagger/solver.go b/dagger/solver.go index c4e6ebf0..36799e83 100644 --- a/dagger/solver.go +++ b/dagger/solver.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" bkgw "github.com/moby/buildkit/frontend/gateway/client" bkpb "github.com/moby/buildkit/solver/pb" "github.com/opencontainers/go-digest" @@ -39,6 +40,23 @@ func (s Solver) SessionID() string { return s.c.BuildOpts().SessionID } +func (s Solver) ResolveImageConfig(ctx context.Context, ref string, opts llb.ResolveImageConfigOpt) (dockerfile2llb.Image, error) { + var image dockerfile2llb.Image + + // Load image metadata and convert to to LLB. + // Inspired by https://github.com/moby/buildkit/blob/master/frontend/dockerfile/dockerfile2llb/convert.go + // FIXME: this needs to handle platform + _, meta, err := s.c.ResolveImageConfig(ctx, ref, opts) + if err != nil { + return image, err + } + if err := json.Unmarshal(meta, &image); err != nil { + return image, err + } + + return image, nil +} + // Solve will block until the state is solved and returns a Reference. func (s Solver) SolveRequest(ctx context.Context, req bkgw.SolveRequest) (bkgw.Reference, error) { // call solve diff --git a/go.mod b/go.mod index a236722c..7833ce57 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( cuelang.org/go v0.3.0-beta.5 github.com/KromDaniel/jonson v0.0.0-20180630143114-d2f9c3c389db github.com/containerd/console v1.0.1 + github.com/docker/distribution v2.7.1+incompatible // indirect github.com/emicklei/proto v1.9.0 // indirect github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db diff --git a/stdlib/go/go.cue b/stdlib/go/go.cue index 416c7ee0..c9e5a029 100644 --- a/stdlib/go/go.cue +++ b/stdlib/go/go.cue @@ -24,14 +24,8 @@ import ( dagger.#Exec & { "args": ["go"] + args - env: env - env: CGO_ENABLED: "0" - // FIXME: this should come from the golang image. - // https://github.com/dagger/dagger/issues/130 - env: { - PATH: "/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - GOPATH: "/go" - } + "env": env + "env": CGO_ENABLED: "0" dir: "/src" mount: "/src": from: source