diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index 26b019df42d1..d591f0a1ff4b 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -16,6 +16,7 @@ import ( "github.com/moby/buildkit/frontend/dockerui" "github.com/moby/buildkit/frontend/gateway/client" gwpb "github.com/moby/buildkit/frontend/gateway/pb" + "github.com/moby/buildkit/frontend/subrequests/convertllb" "github.com/moby/buildkit/frontend/subrequests/lint" "github.com/moby/buildkit/frontend/subrequests/outline" "github.com/moby/buildkit/frontend/subrequests/targets" @@ -96,6 +97,9 @@ func Build(ctx context.Context, c client.Client) (_ *client.Result, err error) { Lint: func(ctx context.Context) (*lint.LintResults, error) { return dockerfile2llb.DockerfileLint(ctx, src.Data, convertOpt) }, + ConvertLLB: func(ctx context.Context) (*convertllb.Result, error) { + return dockerfile2llb.DockerfileConvertLLB(ctx, src.Data, convertOpt) + }, }); err != nil { return nil, err } else if ok { diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index 665bdb399fe5..9adf0171ae29 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -30,6 +30,7 @@ import ( "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/moby/buildkit/frontend/dockerfile/shell" "github.com/moby/buildkit/frontend/dockerui" + "github.com/moby/buildkit/frontend/subrequests/convertllb" "github.com/moby/buildkit/frontend/subrequests/lint" "github.com/moby/buildkit/frontend/subrequests/outline" "github.com/moby/buildkit/frontend/subrequests/targets" @@ -123,6 +124,14 @@ func Dockerfile2Outline(ctx context.Context, dt []byte, opt ConvertOpt) (*outlin return &o, nil } +func DockerfileConvertLLB(ctx context.Context, dt []byte, opt ConvertOpt) (*convertllb.Result, error) { + ds, err := toDispatchState(ctx, dt, opt) + if err != nil { + return nil, err + } + return ds.ConvertLLB(ctx) +} + func DockerfileLint(ctx context.Context, dt []byte, opt ConvertOpt) (*lint.LintResults, error) { results := &lint.LintResults{} sourceIndex := results.AddSource(opt.SourceMap) @@ -1223,7 +1232,7 @@ func dispatchRun(d *dispatchState, c *instructions.RunCommand, proxy *llb.ProxyE // Run command can potentially access any file. Mark the full filesystem as used. d.paths["/"] = struct{}{} - var args = c.CmdLine + args := c.CmdLine if len(c.Files) > 0 { if len(args) != 1 || !c.PrependShell { return errors.Errorf("parsing produced an invalid run command: %v", args) @@ -1760,7 +1769,7 @@ func dispatchOnbuild(d *dispatchState, c *instructions.OnbuildCommand) error { func dispatchCmd(d *dispatchState, c *instructions.CmdCommand, lint *linter.Linter) error { validateUsedOnce(c, &d.cmd, lint) - var args = c.CmdLine + args := c.CmdLine if c.PrependShell { if len(d.image.Config.Shell) == 0 { msg := linter.RuleJSONArgsRecommended.Format(c.Name()) @@ -1776,7 +1785,7 @@ func dispatchCmd(d *dispatchState, c *instructions.CmdCommand, lint *linter.Lint func dispatchEntrypoint(d *dispatchState, c *instructions.EntrypointCommand, lint *linter.Linter) error { validateUsedOnce(c, &d.entrypoint, lint) - var args = c.CmdLine + args := c.CmdLine if c.PrependShell { if len(d.image.Config.Shell) == 0 { msg := linter.RuleJSONArgsRecommended.Format(c.Name()) diff --git a/frontend/dockerfile/dockerfile2llb/convertllb.go b/frontend/dockerfile/dockerfile2llb/convertllb.go new file mode 100644 index 000000000000..93cf02e1bb08 --- /dev/null +++ b/frontend/dockerfile/dockerfile2llb/convertllb.go @@ -0,0 +1,32 @@ +package dockerfile2llb + +import ( + "context" + + "github.com/moby/buildkit/frontend/subrequests/convertllb" + "github.com/moby/buildkit/solver/pb" + digest "github.com/opencontainers/go-digest" +) + +func (ds *dispatchState) ConvertLLB(ctx context.Context) (*convertllb.Result, error) { + def, err := ds.state.Marshal(ctx) + if err != nil { + return nil, err + } + + res := &convertllb.Result{ + Def: make(map[digest.Digest]*pb.Op, len(def.Def)), + Metadata: def.Metadata, + Source: def.Source, + } + for _, dt := range def.Def { + var op pb.Op + if err := op.UnmarshalVT(dt); err != nil { + return nil, err + } + + dgst := digest.FromBytes(dt) + res.Def[dgst] = &op + } + return res, nil +} diff --git a/frontend/dockerui/requests.go b/frontend/dockerui/requests.go index 9b84c52c07b3..08dd748e7356 100644 --- a/frontend/dockerui/requests.go +++ b/frontend/dockerui/requests.go @@ -7,6 +7,7 @@ import ( "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/frontend/subrequests/convertllb" "github.com/moby/buildkit/frontend/subrequests/lint" "github.com/moby/buildkit/frontend/subrequests/outline" "github.com/moby/buildkit/frontend/subrequests/targets" @@ -21,6 +22,7 @@ type RequestHandler struct { Outline func(context.Context) (*outline.Outline, error) ListTargets func(context.Context) (*targets.List, error) Lint func(context.Context) (*lint.LintResults, error) + ConvertLLB func(context.Context) (*convertllb.Result, error) AllowOther bool } @@ -69,6 +71,16 @@ func (bc *Client) HandleSubrequest(ctx context.Context, h RequestHandler) (*clie res, err := warnings.ToResult(nil) return res, true, err } + case convertllb.SubrequestConvertLLBDefinition.Name: + if f := h.ConvertLLB; f != nil { + result, err := f(ctx) + if err != nil { + return nil, false, err + } + + res, err := result.ToResult() + return res, true, err + } } if h.AllowOther { return nil, false, nil diff --git a/frontend/subrequests/convertllb/convertllb.go b/frontend/subrequests/convertllb/convertllb.go new file mode 100644 index 000000000000..5888a7abdb1c --- /dev/null +++ b/frontend/subrequests/convertllb/convertllb.go @@ -0,0 +1,67 @@ +package convertllb + +import ( + "encoding/json" + + "github.com/moby/buildkit/client/llb" + "github.com/moby/buildkit/frontend/gateway/client" + "github.com/moby/buildkit/frontend/subrequests" + "github.com/moby/buildkit/solver/pb" + digest "github.com/opencontainers/go-digest" + "google.golang.org/protobuf/encoding/protojson" +) + +const RequestConvertLLB = "frontend.convertllb" + +var SubrequestConvertLLBDefinition = subrequests.Request{ + Name: RequestConvertLLB, + Version: "0.1.0", + Type: subrequests.TypeRPC, + Description: "Convert Dockerfile to LLB", + Opts: []subrequests.Named{}, + Metadata: []subrequests.Named{ + {Name: "result.json"}, + }, +} + +type Result struct { + Def map[digest.Digest]*pb.Op `json:"def"` + Metadata map[digest.Digest]llb.OpMetadata `json:"metadata"` + Source *pb.Source `json:"source"` +} + +func (result *Result) ToResult() (*client.Result, error) { + res := client.NewResult() + dt, err := json.MarshalIndent(result, "", " ") + if err != nil { + return nil, err + } + res.AddMeta("result.json", dt) + + res.AddMeta("version", []byte(SubrequestConvertLLBDefinition.Version)) + return res, nil +} + +func (result *Result) MarshalJSON() ([]byte, error) { + var jsonResult struct { + Def map[digest.Digest]json.RawMessage `json:"def"` + Metadata map[digest.Digest]llb.OpMetadata `json:"metadata"` + Source json.RawMessage `json:"source"` + } + jsonResult.Def = make(map[digest.Digest]json.RawMessage, len(result.Def)) + for dgst, op := range result.Def { + dt, err := protojson.Marshal(op) + if err != nil { + return nil, err + } + jsonResult.Def[dgst] = dt + } + jsonResult.Metadata = result.Metadata + + src, err := protojson.Marshal(result.Source) + if err != nil { + return nil, err + } + jsonResult.Source = src + return json.Marshal(&jsonResult) +}