add formatting support to print function

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2022-08-05 00:25:39 -07:00
parent cab437adef
commit c834ba1389
3 changed files with 69 additions and 18 deletions

View File

@ -87,7 +87,12 @@ type Options struct {
// Linked marks this target as exclusively linked (not requested by the user). // Linked marks this target as exclusively linked (not requested by the user).
Linked bool Linked bool
PrintFunc string PrintFunc *PrintFunc
}
type PrintFunc struct {
Name string
Format string
} }
type Inputs struct { type Inputs struct {
@ -1050,13 +1055,13 @@ func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[s
var isFallback bool var isFallback bool
var origErr error var origErr error
for { for {
if opt.PrintFunc != "" { if opt.PrintFunc != nil {
if _, ok := req.FrontendOpt["frontend.caps"]; !ok { if _, ok := req.FrontendOpt["frontend.caps"]; !ok {
req.FrontendOpt["frontend.caps"] = "moby.buildkit.frontend.subrequests+forward" req.FrontendOpt["frontend.caps"] = "moby.buildkit.frontend.subrequests+forward"
} else { } else {
req.FrontendOpt["frontend.caps"] += ",moby.buildkit.frontend.subrequests+forward" req.FrontendOpt["frontend.caps"] += ",moby.buildkit.frontend.subrequests+forward"
} }
req.FrontendOpt["requestid"] = "frontend." + opt.PrintFunc req.FrontendOpt["requestid"] = "frontend." + opt.PrintFunc.Name
if isFallback { if isFallback {
req.FrontendOpt["build-arg:BUILDKIT_SYNTAX"] = printFallbackImage req.FrontendOpt["build-arg:BUILDKIT_SYNTAX"] = printFallbackImage
} }
@ -1086,7 +1091,7 @@ func BuildWithResultHandler(ctx context.Context, drivers []DriverInfo, opt map[s
} }
return nil, err return nil, err
} }
if opt.PrintFunc != "" { if opt.PrintFunc != nil {
printRes = res.Metadata printRes = res.Metadata
} }
results.Set(resultKey(dp.driverIndex, k), res) results.Set(resultKey(dp.driverIndex, k), res)
@ -1686,7 +1691,7 @@ func tryNodeIdentifier(configDir string) (out string) {
func noPrintFunc(opt map[string]Options) bool { func noPrintFunc(opt map[string]Options) bool {
for _, v := range opt { for _, v := range opt {
if v.PrintFunc != "" { if v.PrintFunc != nil {
return false return false
} }
} }

View File

@ -123,6 +123,11 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
return err return err
} }
printFunc, err := parsePrintFunc(in.printFunc)
if err != nil {
return err
}
opts := build.Options{ opts := build.Options{
Inputs: build.Inputs{ Inputs: build.Inputs{
ContextPath: in.contextPath, ContextPath: in.contextPath,
@ -142,7 +147,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
Tags: in.tags, Tags: in.tags,
Target: in.target, Target: in.target,
Ulimits: in.ulimits, Ulimits: in.ulimits,
PrintFunc: in.printFunc, PrintFunc: printFunc,
} }
platforms, err := platformutil.Parse(in.platforms) platforms, err := platformutil.Parse(in.platforms)
@ -310,7 +315,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu
printWarnings(os.Stderr, printer.Warnings(), progressMode) printWarnings(os.Stderr, printer.Warnings(), progressMode)
for k := range resp { for k := range resp {
if opts[k].PrintFunc != "" { if opts[k].PrintFunc != nil {
if err := printResult(opts[k].PrintFunc, resp[k].ExporterResponse); err != nil { if err := printResult(opts[k].PrintFunc, resp[k].ExporterResponse); err != nil {
return "", nil, err return "", nil, err
} }
@ -610,6 +615,34 @@ func parseContextNames(values []string) (map[string]build.NamedContext, error) {
return result, nil return result, nil
} }
func parsePrintFunc(str string) (*build.PrintFunc, error) {
if str == "" {
return nil, nil
}
csvReader := csv.NewReader(strings.NewReader(str))
fields, err := csvReader.Read()
if err != nil {
return nil, err
}
f := &build.PrintFunc{}
for _, field := range fields {
parts := strings.SplitN(field, "=", 2)
if len(parts) == 2 {
if parts[0] == "format" {
f.Format = parts[1]
} else {
return nil, errors.Errorf("invalid print field: %s", field)
}
} else {
if f.Name != "" {
return nil, errors.Errorf("invalid print value: %s", str)
}
f.Name = field
}
}
return f, nil
}
func writeMetadataFile(filename string, dt interface{}) error { func writeMetadataFile(filename string, dt interface{}) error {
b, err := json.MarshalIndent(dt, "", " ") b, err := json.MarshalIndent(dt, "", " ")
if err != nil { if err != nil {

View File

@ -2,28 +2,25 @@ package commands
import ( import (
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"github.com/docker/buildx/build"
"github.com/docker/docker/api/types/versions"
"github.com/moby/buildkit/frontend/subrequests" "github.com/moby/buildkit/frontend/subrequests"
"github.com/moby/buildkit/frontend/subrequests/outline" "github.com/moby/buildkit/frontend/subrequests/outline"
"github.com/moby/buildkit/frontend/subrequests/targets" "github.com/moby/buildkit/frontend/subrequests/targets"
) )
func printResult(f string, res map[string]string) error { func printResult(f *build.PrintFunc, res map[string]string) error {
switch f { switch f.Name {
case "outline": case "outline":
if err := outline.PrintOutline([]byte(res["result.json"]), os.Stdout); err != nil { return printValue(outline.PrintOutline, outline.SubrequestsOutlineDefinition.Version, f.Format, res)
return err
}
case "targets": case "targets":
if err := targets.PrintTargets([]byte(res["result.json"]), os.Stdout); err != nil { return printValue(targets.PrintTargets, targets.SubrequestsTargetsDefinition.Version, f.Format, res)
return err
}
case "subrequests.describe": case "subrequests.describe":
if err := subrequests.PrintDescribe([]byte(res["result.json"]), os.Stdout); err != nil { return printValue(subrequests.PrintDescribe, subrequests.SubrequestsDescribeDefinition.Version, f.Format, res)
return err
}
default: default:
if dt, ok := res["result.txt"]; ok { if dt, ok := res["result.txt"]; ok {
fmt.Print(dt) fmt.Print(dt)
@ -33,3 +30,19 @@ func printResult(f string, res map[string]string) error {
} }
return nil return nil
} }
type printFunc func([]byte, io.Writer) error
func printValue(printer printFunc, version string, format string, res map[string]string) error {
if format == "json" {
fmt.Fprintln(os.Stdout, res["result.json"])
return nil
}
if res["version"] != "" && versions.LessThan(version, res["version"]) && res["result.txt"] != "" {
// structure is too new and we don't know how to print it
fmt.Fprint(os.Stdout, res["result.txt"])
return nil
}
return printer([]byte(res["result.json"]), os.Stdout)
}