controller: followup refactoring on Build API

Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
pull/1671/head
Kohei Tokunaga 2 years ago
parent c5ce08bf3c
commit ccc9966600

@ -10,7 +10,6 @@ import (
"github.com/docker/buildx/bake" "github.com/docker/buildx/bake"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/util/buildflags" "github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/confutil" "github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil" "github.com/docker/buildx/util/dockerutil"
@ -29,7 +28,11 @@ type bakeOptions struct {
printOnly bool printOnly bool
sbom string sbom string
provenance string provenance string
controllerapi.CommonOptions
builder string
metadataFile string
exportPush bool
exportLoad bool
} }
func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags commonFlags) (err error) { func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags commonFlags) (err error) {
@ -64,12 +67,12 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com
} }
overrides := in.overrides overrides := in.overrides
if in.ExportPush { if in.exportPush {
if in.ExportLoad { if in.exportLoad {
return errors.Errorf("push and load may not be set together at the moment") return errors.Errorf("push and load may not be set together at the moment")
} }
overrides = append(overrides, "*.push=true") overrides = append(overrides, "*.push=true")
} else if in.ExportLoad { } else if in.exportLoad {
overrides = append(overrides, "*.output=type=docker") overrides = append(overrides, "*.output=type=docker")
} }
if cFlags.noCache != nil { if cFlags.noCache != nil {
@ -97,7 +100,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com
// instance only needed for reading remote bake files or building // instance only needed for reading remote bake files or building
if url != "" || !in.printOnly { if url != "" || !in.printOnly {
b, err := builder.New(dockerCli, b, err := builder.New(dockerCli,
builder.WithName(in.Builder), builder.WithName(in.builder),
builder.WithContextPathHash(contextPathHash), builder.WithContextPathHash(contextPathHash),
) )
if err != nil { if err != nil {
@ -180,12 +183,12 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com
return wrapBuildError(err, true) return wrapBuildError(err, true)
} }
if len(in.MetadataFile) > 0 { if len(in.metadataFile) > 0 {
dt := make(map[string]interface{}) dt := make(map[string]interface{})
for t, r := range resp { for t, r := range resp {
dt[t] = decodeExporterResponse(r.ExporterResponse) dt[t] = decodeExporterResponse(r.ExporterResponse)
} }
if err := writeMetadataFile(in.MetadataFile, dt); err != nil { if err := writeMetadataFile(in.metadataFile, dt); err != nil {
return err return err
} }
} }
@ -209,8 +212,8 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
if !cmd.Flags().Lookup("pull").Changed { if !cmd.Flags().Lookup("pull").Changed {
cFlags.pull = nil cFlags.pull = nil
} }
options.Builder = rootOpts.builder options.builder = rootOpts.builder
options.MetadataFile = cFlags.metadataFile options.metadataFile = cFlags.metadataFile
// Other common flags (noCache, pull and progress) are processed in runBake function. // Other common flags (noCache, pull and progress) are processed in runBake function.
return runBake(dockerCli, args, options, cFlags) return runBake(dockerCli, args, options, cFlags)
}, },
@ -219,9 +222,9 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Build definition file") flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Build definition file")
flags.BoolVar(&options.ExportLoad, "load", false, `Shorthand for "--set=*.output=type=docker"`) flags.BoolVar(&options.exportLoad, "load", false, `Shorthand for "--set=*.output=type=docker"`)
flags.BoolVar(&options.printOnly, "print", false, "Print the options without building") flags.BoolVar(&options.printOnly, "print", false, "Print the options without building")
flags.BoolVar(&options.ExportPush, "push", false, `Shorthand for "--set=*.output=type=registry"`) flags.BoolVar(&options.exportPush, "push", false, `Shorthand for "--set=*.output=type=registry"`)
flags.StringVar(&options.sbom, "sbom", "", `Shorthand for "--set=*.attest=type=sbom"`) flags.StringVar(&options.sbom, "sbom", "", `Shorthand for "--set=*.attest=type=sbom"`)
flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--set=*.attest=type=provenance"`) flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--set=*.attest=type=provenance"`)
flags.StringArrayVar(&options.overrides, "set", nil, `Override target value (e.g., "targetpattern.key=value")`) flags.StringArrayVar(&options.overrides, "set", nil, `Override target value (e.g., "targetpattern.key=value")`)

@ -14,6 +14,7 @@ import (
"strings" "strings"
"github.com/containerd/console" "github.com/containerd/console"
"github.com/docker/buildx/build"
"github.com/docker/buildx/controller" "github.com/docker/buildx/controller"
cbuild "github.com/docker/buildx/controller/build" cbuild "github.com/docker/buildx/controller/build"
"github.com/docker/buildx/controller/control" "github.com/docker/buildx/controller/control"
@ -35,6 +36,7 @@ import (
"github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/util/appcontext" "github.com/moby/buildkit/util/appcontext"
"github.com/moby/buildkit/util/grpcerrors" "github.com/moby/buildkit/util/grpcerrors"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -75,7 +77,13 @@ type buildOptions struct {
progress string progress string
quiet bool quiet bool
controllerapi.CommonOptions builder string
metadataFile string
noCache bool
pull bool
exportPush bool
exportLoad bool
control.ControlOptions control.ControlOptions
} }
@ -97,7 +105,12 @@ func (o *buildOptions) toControllerOptions() (controllerapi.BuildOptions, error)
Tags: o.tags, Tags: o.tags,
Target: o.target, Target: o.target,
Ulimits: dockerUlimitToControllerUlimit(o.ulimits), Ulimits: dockerUlimitToControllerUlimit(o.ulimits),
Opts: &o.CommonOptions, Builder: o.builder,
MetadataFile: o.metadataFile,
NoCache: o.noCache,
Pull: o.pull,
ExportPush: o.exportPush,
ExportLoad: o.exportLoad,
} }
inAttests := append([]string{}, o.attests...) inAttests := append([]string{}, o.attests...)
@ -179,7 +192,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) error {
if err != nil { if err != nil {
return err return err
} }
progress, err := in.toProgress() progressMode, err := in.toProgress()
if err != nil { if err != nil {
return err return err
} }
@ -190,7 +203,20 @@ func runBuild(dockerCli command.Cli, in buildOptions) error {
return errors.Wrap(err, "removing image ID file") return errors.Wrap(err, "removing image ID file")
} }
} }
resp, _, err := cbuild.RunBuild(ctx, dockerCli, opts, os.Stdin, progress, nil) resp, _, err := cbuild.RunBuild(ctx, dockerCli, opts, os.Stdin, cbuild.ProgressConfig{
Printer: func(ctx2 context.Context, ng *store.NodeGroup) (*progress.Printer, error) {
return progress.NewPrinter(ctx2, os.Stderr, os.Stderr, progressMode, progressui.WithDesc(
fmt.Sprintf("building with %q instance using %s driver", ng.Name, ng.Driver),
fmt.Sprintf("%s:%s", ng.Driver, ng.Name),
))
},
PrintWarningsFunc: func(warnings []client.VertexWarning) {
cbuild.PrintWarnings(os.Stderr, warnings, progressMode)
},
PrintResultFunc: func(f *build.PrintFunc, res map[string]string) error {
return cbuild.PrintResult(os.Stdout, f, res)
},
})
if err != nil { if err != nil {
return err return err
} }
@ -218,15 +244,15 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
Args: cli.ExactArgs(1), Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
options.contextPath = args[0] options.contextPath = args[0]
options.Builder = rootOpts.builder options.builder = rootOpts.builder
options.MetadataFile = cFlags.metadataFile options.metadataFile = cFlags.metadataFile
options.NoCache = false options.noCache = false
if cFlags.noCache != nil { if cFlags.noCache != nil {
options.NoCache = *cFlags.noCache options.noCache = *cFlags.noCache
} }
options.Pull = false options.pull = false
if cFlags.pull != nil { if cFlags.pull != nil {
options.Pull = *cFlags.pull options.pull = *cFlags.pull
} }
options.progress = cFlags.progress options.progress = cFlags.progress
cmd.Flags().VisitAll(checkWarnedFlags) cmd.Flags().VisitAll(checkWarnedFlags)
@ -267,7 +293,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.StringArrayVar(&options.labels, "label", []string{}, "Set metadata for an image") flags.StringArrayVar(&options.labels, "label", []string{}, "Set metadata for an image")
flags.BoolVar(&options.ExportLoad, "load", false, `Shorthand for "--output=type=docker"`) flags.BoolVar(&options.exportLoad, "load", false, `Shorthand for "--output=type=docker"`)
flags.StringVar(&options.networkMode, "network", "default", `Set the networking mode for the "RUN" instructions during build`) flags.StringVar(&options.networkMode, "network", "default", `Set the networking mode for the "RUN" instructions during build`)
@ -281,7 +307,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.StringVar(&options.printFunc, "print", "", "Print result of information request (e.g., outline, targets) [experimental]") flags.StringVar(&options.printFunc, "print", "", "Print result of information request (e.g., outline, targets) [experimental]")
} }
flags.BoolVar(&options.ExportPush, "push", false, `Shorthand for "--output=type=registry"`) flags.BoolVar(&options.exportPush, "push", false, `Shorthand for "--output=type=registry"`)
flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the build output and print image ID on success") flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the build output and print image ID on success")
@ -523,7 +549,7 @@ func launchControllerAndRunBuild(dockerCli command.Cli, options buildOptions) er
return err return err
} }
opts = *optsP opts = *optsP
ref, resp, err := c.Build(ctx, opts, pr, os.Stdout, os.Stderr, progress) ref, resp, err := control.Build(ctx, c, opts, pr, os.Stdout, os.Stderr, progress)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to build") // TODO: allow invoke even on error return errors.Wrapf(err, "failed to build") // TODO: allow invoke even on error
} }
@ -805,8 +831,8 @@ func resolvePaths(options *controllerapi.BuildOptions) (_ *controllerapi.BuildOp
} }
options.SSH = ssh options.SSH = ssh
if options.Opts != nil && options.Opts.MetadataFile != "" { if options.MetadataFile != "" {
options.Opts.MetadataFile, err = filepath.Abs(options.Opts.MetadataFile) options.MetadataFile, err = filepath.Abs(options.MetadataFile)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -228,14 +228,10 @@ func TestResolvePaths(t *testing.T) {
{ {
name: "metadatafile", name: "metadatafile",
options: controllerapi.BuildOptions{ options: controllerapi.BuildOptions{
Opts: &controllerapi.CommonOptions{ MetadataFile: "test1",
MetadataFile: "test1",
},
}, },
want: controllerapi.BuildOptions{ want: controllerapi.BuildOptions{
Opts: &controllerapi.CommonOptions{ MetadataFile: filepath.Join(tmpwd, "test1"),
MetadataFile: filepath.Join(tmpwd, "test1"),
},
}, },
}, },
} }

@ -1,12 +1,10 @@
package build package build
import ( import (
"bytes"
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/csv" "encoding/csv"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
@ -30,19 +28,23 @@ import (
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/session/auth/authprovider" "github.com/moby/buildkit/session/auth/authprovider"
"github.com/moby/buildkit/solver/errdefs"
"github.com/moby/buildkit/util/grpcerrors" "github.com/moby/buildkit/util/grpcerrors"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/morikuni/aec"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
) )
const defaultTargetName = "default" const defaultTargetName = "default"
func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.BuildOptions, inStream io.Reader, progressMode string, statusChan chan *client.SolveStatus) (*client.SolveResponse, *build.ResultContext, error) { // ProgressConfig is configuration about how the progress information is printed.
if in.Opts.NoCache && len(in.NoCacheFilter) > 0 { type ProgressConfig struct {
Printer func(ctx context.Context, ng *store.NodeGroup) (*progress.Printer, error)
PrintWarningsFunc func(warnings []client.VertexWarning)
PrintResultFunc func(f *build.PrintFunc, res map[string]string) error
}
// RunBuild builds the specified build with providing the build status information through ProgressConfig.
func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.BuildOptions, inStream io.Reader, progressConfig ProgressConfig) (*client.SolveResponse, *build.ResultContext, error) {
if in.NoCache && len(in.NoCacheFilter) > 0 {
return nil, nil, errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together") return nil, nil, errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together")
} }
@ -67,9 +69,9 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
ExtraHosts: in.ExtraHosts, ExtraHosts: in.ExtraHosts,
Labels: in.Labels, Labels: in.Labels,
NetworkMode: in.NetworkMode, NetworkMode: in.NetworkMode,
NoCache: in.Opts.NoCache, NoCache: in.NoCache,
NoCacheFilter: in.NoCacheFilter, NoCacheFilter: in.NoCacheFilter,
Pull: in.Opts.Pull, Pull: in.Pull,
ShmSize: dockeropts.MemBytes(in.ShmSize), ShmSize: dockeropts.MemBytes(in.ShmSize),
Tags: in.Tags, Tags: in.Tags,
Target: in.Target, Target: in.Target,
@ -106,8 +108,8 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if in.Opts.ExportPush { if in.ExportPush {
if in.Opts.ExportLoad { if in.ExportLoad {
return nil, nil, errors.Errorf("push and load may not be set together at the moment") return nil, nil, errors.Errorf("push and load may not be set together at the moment")
} }
if len(outputs) == 0 { if len(outputs) == 0 {
@ -126,7 +128,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
} }
} }
} }
if in.Opts.ExportLoad { if in.ExportLoad {
if len(outputs) == 0 { if len(outputs) == 0 {
outputs = []client.ExportEntry{{ outputs = []client.ExportEntry{{
Type: "docker", Type: "docker",
@ -160,7 +162,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
} }
b, err := builder.New(dockerCli, b, err := builder.New(dockerCli,
builder.WithName(in.Opts.Builder), builder.WithName(in.Builder),
builder.WithContextPathHash(contextPathHash), builder.WithContextPathHash(contextPathHash),
) )
if err != nil { if err != nil {
@ -174,7 +176,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
return nil, nil, err return nil, nil, err
} }
resp, res, err := buildTargets(ctx, dockerCli, b.NodeGroup, nodes, map[string]build.Options{defaultTargetName: opts}, progressMode, in.Opts.MetadataFile, statusChan) resp, res, err := buildTargets(ctx, dockerCli, b.NodeGroup, nodes, map[string]build.Options{defaultTargetName: opts}, progressConfig, in.MetadataFile)
err = wrapBuildError(err, false) err = wrapBuildError(err, false)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -182,14 +184,11 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
return resp, res, nil return resp, res, nil
} }
func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, nodes []builder.Node, opts map[string]build.Options, progressMode string, metadataFile string, statusChan chan *client.SolveStatus) (*client.SolveResponse, *build.ResultContext, error) { func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGroup, nodes []builder.Node, opts map[string]build.Options, progressConfig ProgressConfig, metadataFile string) (*client.SolveResponse, *build.ResultContext, error) {
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
printer, err := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, progressMode, progressui.WithDesc( printer, err := progressConfig.Printer(ctx2, ng)
fmt.Sprintf("building with %q instance using %s driver", ng.Name, ng.Driver),
fmt.Sprintf("%s:%s", ng.Driver, ng.Name),
))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -197,7 +196,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGrou
var res *build.ResultContext var res *build.ResultContext
var mu sync.Mutex var mu sync.Mutex
var idx int var idx int
resp, err := build.BuildWithResultHandler(ctx, nodes, opts, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), progress.Tee(printer, statusChan), func(driverIndex int, gotRes *build.ResultContext) { resp, err := build.BuildWithResultHandler(ctx, nodes, opts, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), printer, func(driverIndex int, gotRes *build.ResultContext) {
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
if res == nil || driverIndex < idx { if res == nil || driverIndex < idx {
@ -218,11 +217,13 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGrou
} }
} }
printWarnings(os.Stderr, printer.Warnings(), progressMode) if f := progressConfig.PrintWarningsFunc; f != nil {
f(printer.Warnings())
}
for k := range resp { for k := range resp {
if opts[k].PrintFunc != nil { if opts[k].PrintFunc != nil {
if err := printResult(opts[k].PrintFunc, resp[k].ExporterResponse); err != nil { if err := progressConfig.PrintResultFunc(opts[k].PrintFunc, resp[k].ExporterResponse); err != nil {
return nil, nil, err return nil, nil, err
} }
} }
@ -231,46 +232,6 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGrou
return resp[defaultTargetName], res, err return resp[defaultTargetName], res, err
} }
func printWarnings(w io.Writer, warnings []client.VertexWarning, mode string) {
if len(warnings) == 0 || mode == progress.PrinterModeQuiet {
return
}
fmt.Fprintf(w, "\n ")
sb := &bytes.Buffer{}
if len(warnings) == 1 {
fmt.Fprintf(sb, "1 warning found")
} else {
fmt.Fprintf(sb, "%d warnings found", len(warnings))
}
if logrus.GetLevel() < logrus.DebugLevel {
fmt.Fprintf(sb, " (use --debug to expand)")
}
fmt.Fprintf(sb, ":\n")
fmt.Fprint(w, aec.Apply(sb.String(), aec.YellowF))
for _, warn := range warnings {
fmt.Fprintf(w, " - %s\n", warn.Short)
if logrus.GetLevel() < logrus.DebugLevel {
continue
}
for _, d := range warn.Detail {
fmt.Fprintf(w, "%s\n", d)
}
if warn.URL != "" {
fmt.Fprintf(w, "More info: %s\n", warn.URL)
}
if warn.SourceInfo != nil && warn.Range != nil {
src := errdefs.Source{
Info: warn.SourceInfo,
Ranges: warn.Range,
}
src.Print(w)
}
fmt.Fprintf(w, "\n")
}
}
func parsePrintFunc(str string) (*build.PrintFunc, error) { func parsePrintFunc(str string) (*build.PrintFunc, error) {
if str == "" { if str == "" {
return nil, nil return nil, nil

@ -1,29 +1,35 @@
package build package build
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"log" "log"
"os"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
"github.com/docker/buildx/util/progress"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/moby/buildkit/client"
"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"
"github.com/moby/buildkit/solver/errdefs"
"github.com/morikuni/aec"
"github.com/sirupsen/logrus"
) )
func printResult(f *build.PrintFunc, res map[string]string) error { // PrintResult writes the result information to the specified writer.
func PrintResult(w io.Writer, f *build.PrintFunc, res map[string]string) error {
switch f.Name { switch f.Name {
case "outline": case "outline":
return printValue(outline.PrintOutline, outline.SubrequestsOutlineDefinition.Version, f.Format, res) return printValue(outline.PrintOutline, outline.SubrequestsOutlineDefinition.Version, f.Format, res, w)
case "targets": case "targets":
return printValue(targets.PrintTargets, targets.SubrequestsTargetsDefinition.Version, f.Format, res) return printValue(targets.PrintTargets, targets.SubrequestsTargetsDefinition.Version, f.Format, res, w)
case "subrequests.describe": case "subrequests.describe":
return printValue(subrequests.PrintDescribe, subrequests.SubrequestsDescribeDefinition.Version, f.Format, res) return printValue(subrequests.PrintDescribe, subrequests.SubrequestsDescribeDefinition.Version, f.Format, res, w)
default: default:
if dt, ok := res["result.txt"]; ok { if dt, ok := res["result.txt"]; ok {
fmt.Print(dt) fmt.Fprint(w, dt)
} else { } else {
log.Printf("%s %+v", f, res) log.Printf("%s %+v", f, res)
} }
@ -33,16 +39,57 @@ func printResult(f *build.PrintFunc, res map[string]string) error {
type printFunc func([]byte, io.Writer) error type printFunc func([]byte, io.Writer) error
func printValue(printer printFunc, version string, format string, res map[string]string) error { func printValue(printer printFunc, version string, format string, res map[string]string, w io.Writer) error {
if format == "json" { if format == "json" {
fmt.Fprintln(os.Stdout, res["result.json"]) fmt.Fprintln(w, res["result.json"])
return nil return nil
} }
if res["version"] != "" && versions.LessThan(version, res["version"]) && res["result.txt"] != "" { if res["version"] != "" && versions.LessThan(version, res["version"]) && res["result.txt"] != "" {
// structure is too new and we don't know how to print it // structure is too new and we don't know how to print it
fmt.Fprint(os.Stdout, res["result.txt"]) fmt.Fprint(w, res["result.txt"])
return nil return nil
} }
return printer([]byte(res["result.json"]), os.Stdout) return printer([]byte(res["result.json"]), w)
}
// PrintWarnings writes the warning information to the specified writer.
func PrintWarnings(w io.Writer, warnings []client.VertexWarning, mode string) {
if len(warnings) == 0 || mode == progress.PrinterModeQuiet {
return
}
fmt.Fprintf(w, "\n ")
sb := &bytes.Buffer{}
if len(warnings) == 1 {
fmt.Fprintf(sb, "1 warning found")
} else {
fmt.Fprintf(sb, "%d warnings found", len(warnings))
}
if logrus.GetLevel() < logrus.DebugLevel {
fmt.Fprintf(sb, " (use --debug to expand)")
}
fmt.Fprintf(sb, ":\n")
fmt.Fprint(w, aec.Apply(sb.String(), aec.YellowF))
for _, warn := range warnings {
fmt.Fprintf(w, " - %s\n", warn.Short)
if logrus.GetLevel() < logrus.DebugLevel {
continue
}
for _, d := range warn.Detail {
fmt.Fprintf(w, "%s\n", d)
}
if warn.URL != "" {
fmt.Fprintf(w, "More info: %s\n", warn.URL)
}
if warn.SourceInfo != nil && warn.Range != nil {
src := errdefs.Source{
Info: warn.SourceInfo,
Ranges: warn.Range,
}
src.Print(w)
}
fmt.Fprintf(w, "\n")
}
} }

@ -2,15 +2,25 @@ package control
import ( import (
"context" "context"
"fmt"
"io" "io"
"os"
"github.com/containerd/console" "github.com/containerd/console"
"github.com/docker/buildx/build"
cbuild "github.com/docker/buildx/controller/build"
controllerapi "github.com/docker/buildx/controller/pb" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/store"
"github.com/docker/buildx/util/progress"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
) )
type BuildxController interface { type BuildxController interface {
Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (ref string, resp *client.SolveResponse, err error) Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, statusChan chan *controllerapi.StatusResponse) (ref string, resp *client.SolveResponse, err error)
// Invoke starts an IO session into the specified process. // Invoke starts an IO session into the specified process.
// If pid doesn't matche to any running processes, it starts a new process with the specified config. // If pid doesn't matche to any running processes, it starts a new process with the specified config.
// If there is no container running or InvokeConfig.Rollback is speicfied, the process will start in a newly created container. // If there is no container running or InvokeConfig.Rollback is speicfied, the process will start in a newly created container.
@ -29,3 +39,205 @@ type ControlOptions struct {
Root string Root string
Detach bool Detach bool
} }
// Build is a helper function that builds the build and prints the status using the controller.
func Build(ctx context.Context, c BuildxController, options controllerapi.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (ref string, resp *client.SolveResponse, err error) {
pwCh := make(chan *progress.Printer)
statusChan := make(chan *controllerapi.StatusResponse)
statusDone := make(chan struct{})
eg, egCtx := errgroup.WithContext(ctx)
eg.Go(func() error {
defer close(statusChan)
var err error
ref, resp, err = c.Build(egCtx, options, in, statusChan)
return err
})
var resultInfo []*controllerapi.ResultInfoMessage
eg.Go(func() error {
defer close(statusDone)
var pw *progress.Printer
for s := range statusChan {
st := s
switch m := st.GetStatus().(type) {
case *controllerapi.StatusResponse_NodeInfo:
if pw != nil {
return errors.Errorf("node info is already registered")
}
ng := m.NodeInfo
pw, err = progress.NewPrinter(context.TODO(), w, out, progressMode, progressui.WithDesc(
fmt.Sprintf("building with %q instance using %s driver", ng.Name, ng.Driver),
fmt.Sprintf("%s:%s", ng.Driver, ng.Name),
))
if err != nil {
return err
}
pwCh <- pw
case *controllerapi.StatusResponse_SolveStatus:
if pw != nil {
pw.Write(toSolveStatus(m.SolveStatus))
}
case *controllerapi.StatusResponse_ResultInfo:
resultInfo = append(resultInfo, m.ResultInfo)
}
}
return nil
})
eg.Go(func() error {
pw := <-pwCh
<-statusDone
if err := pw.Wait(); err != nil {
return err
}
cbuild.PrintWarnings(w, pw.Warnings(), progressMode)
return nil
})
if err := eg.Wait(); err != nil {
return ref, resp, err
}
for _, ri := range resultInfo {
cbuild.PrintResult(w, &build.PrintFunc{Name: ri.Name, Format: ri.Format}, ri.Result)
}
return ref, resp, nil
}
// ForwardProgress creates a progress printer backed by Status API.
func ForwardProgress(statusChan chan *controllerapi.StatusResponse) cbuild.ProgressConfig {
return cbuild.ProgressConfig{
Printer: func(ctx context.Context, ng *store.NodeGroup) (*progress.Printer, error) {
statusChan <- &controllerapi.StatusResponse{
Status: &controllerapi.StatusResponse_NodeInfo{
NodeInfo: &controllerapi.NodeInfoMessage{Name: ng.Name, Driver: ng.Driver},
},
}
pw, err := progress.NewPrinter(ctx, io.Discard, os.Stderr, "quiet")
if err != nil {
return nil, err
}
return progress.Tee(pw, forwardStatus(statusChan)), nil
},
PrintResultFunc: func(f *build.PrintFunc, res map[string]string) error {
statusChan <- &controllerapi.StatusResponse{
Status: &controllerapi.StatusResponse_ResultInfo{
ResultInfo: &controllerapi.ResultInfoMessage{
Result: res,
Name: f.Name,
Format: f.Format,
},
},
}
return nil
},
// PrintWarningsFunc: printed on the client side
}
}
func forwardStatus(statusChan chan *controllerapi.StatusResponse) chan *client.SolveStatus {
ch := make(chan *client.SolveStatus)
go func() {
for st := range ch {
st2 := toControlStatus(st)
statusChan <- &controllerapi.StatusResponse{
Status: &controllerapi.StatusResponse_SolveStatus{
SolveStatus: st2,
},
}
}
}()
return ch
}
func toControlStatus(s *client.SolveStatus) *controllerapi.SolveStatusMessage {
resp := controllerapi.SolveStatusMessage{}
for _, v := range s.Vertexes {
resp.Vertexes = append(resp.Vertexes, &controlapi.Vertex{
Digest: v.Digest,
Inputs: v.Inputs,
Name: v.Name,
Started: v.Started,
Completed: v.Completed,
Error: v.Error,
Cached: v.Cached,
ProgressGroup: v.ProgressGroup,
})
}
for _, v := range s.Statuses {
resp.Statuses = append(resp.Statuses, &controlapi.VertexStatus{
ID: v.ID,
Vertex: v.Vertex,
Name: v.Name,
Total: v.Total,
Current: v.Current,
Timestamp: v.Timestamp,
Started: v.Started,
Completed: v.Completed,
})
}
for _, v := range s.Logs {
resp.Logs = append(resp.Logs, &controlapi.VertexLog{
Vertex: v.Vertex,
Stream: int64(v.Stream),
Msg: v.Data,
Timestamp: v.Timestamp,
})
}
for _, v := range s.Warnings {
resp.Warnings = append(resp.Warnings, &controlapi.VertexWarning{
Vertex: v.Vertex,
Level: int64(v.Level),
Short: v.Short,
Detail: v.Detail,
Url: v.URL,
Info: v.SourceInfo,
Ranges: v.Range,
})
}
return &resp
}
func toSolveStatus(resp *controllerapi.SolveStatusMessage) *client.SolveStatus {
s := client.SolveStatus{}
for _, v := range resp.Vertexes {
s.Vertexes = append(s.Vertexes, &client.Vertex{
Digest: v.Digest,
Inputs: v.Inputs,
Name: v.Name,
Started: v.Started,
Completed: v.Completed,
Error: v.Error,
Cached: v.Cached,
ProgressGroup: v.ProgressGroup,
})
}
for _, v := range resp.Statuses {
s.Statuses = append(s.Statuses, &client.VertexStatus{
ID: v.ID,
Vertex: v.Vertex,
Name: v.Name,
Total: v.Total,
Current: v.Current,
Timestamp: v.Timestamp,
Started: v.Started,
Completed: v.Completed,
})
}
for _, v := range resp.Logs {
s.Logs = append(s.Logs, &client.VertexLog{
Vertex: v.Vertex,
Stream: int(v.Stream),
Data: v.Msg,
Timestamp: v.Timestamp,
})
}
for _, v := range resp.Warnings {
s.Warnings = append(s.Warnings, &client.VertexWarning{
Vertex: v.Vertex,
Level: int(v.Level),
Short: v.Short,
Detail: v.Detail,
URL: v.Url,
SourceInfo: v.Info,
Range: v.Ranges,
})
}
return &s
}

@ -5,7 +5,6 @@ import (
"io" "io"
"sync/atomic" "sync/atomic"
"github.com/containerd/console"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
cbuild "github.com/docker/buildx/controller/build" cbuild "github.com/docker/buildx/controller/build"
"github.com/docker/buildx/controller/control" "github.com/docker/buildx/controller/control"
@ -34,13 +33,13 @@ type localController struct {
buildOnGoing atomic.Bool buildOnGoing atomic.Bool
} }
func (b *localController) Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (string, *client.SolveResponse, error) { func (b *localController) Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, statusChan chan *controllerapi.StatusResponse) (string, *client.SolveResponse, error) {
if !b.buildOnGoing.CompareAndSwap(false, true) { if !b.buildOnGoing.CompareAndSwap(false, true) {
return "", nil, errors.New("build ongoing") return "", nil, errors.New("build ongoing")
} }
defer b.buildOnGoing.Store(false) defer b.buildOnGoing.Store(false)
resp, res, err := cbuild.RunBuild(ctx, b.dockerCli, options, in, progressMode, nil) resp, res, err := cbuild.RunBuild(ctx, b.dockerCli, options, in, control.ForwardProgress(statusChan))
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }

@ -292,7 +292,12 @@ type BuildOptions struct {
Tags []string `protobuf:"bytes,20,rep,name=Tags,proto3" json:"Tags,omitempty"` Tags []string `protobuf:"bytes,20,rep,name=Tags,proto3" json:"Tags,omitempty"`
Target string `protobuf:"bytes,21,opt,name=Target,proto3" json:"Target,omitempty"` Target string `protobuf:"bytes,21,opt,name=Target,proto3" json:"Target,omitempty"`
Ulimits *UlimitOpt `protobuf:"bytes,22,opt,name=Ulimits,proto3" json:"Ulimits,omitempty"` Ulimits *UlimitOpt `protobuf:"bytes,22,opt,name=Ulimits,proto3" json:"Ulimits,omitempty"`
Opts *CommonOptions `protobuf:"bytes,24,opt,name=Opts,proto3" json:"Opts,omitempty"` Builder string `protobuf:"bytes,23,opt,name=Builder,proto3" json:"Builder,omitempty"`
MetadataFile string `protobuf:"bytes,24,opt,name=MetadataFile,proto3" json:"MetadataFile,omitempty"`
NoCache bool `protobuf:"varint,25,opt,name=NoCache,proto3" json:"NoCache,omitempty"`
Pull bool `protobuf:"varint,26,opt,name=Pull,proto3" json:"Pull,omitempty"`
ExportPush bool `protobuf:"varint,27,opt,name=ExportPush,proto3" json:"ExportPush,omitempty"`
ExportLoad bool `protobuf:"varint,28,opt,name=ExportLoad,proto3" json:"ExportLoad,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -476,11 +481,46 @@ func (m *BuildOptions) GetUlimits() *UlimitOpt {
return nil return nil
} }
func (m *BuildOptions) GetOpts() *CommonOptions { func (m *BuildOptions) GetBuilder() string {
if m != nil { if m != nil {
return m.Opts return m.Builder
} }
return nil return ""
}
func (m *BuildOptions) GetMetadataFile() string {
if m != nil {
return m.MetadataFile
}
return ""
}
func (m *BuildOptions) GetNoCache() bool {
if m != nil {
return m.NoCache
}
return false
}
func (m *BuildOptions) GetPull() bool {
if m != nil {
return m.Pull
}
return false
}
func (m *BuildOptions) GetExportPush() bool {
if m != nil {
return m.ExportPush
}
return false
}
func (m *BuildOptions) GetExportLoad() bool {
if m != nil {
return m.ExportLoad
}
return false
} }
type ExportEntry struct { type ExportEntry struct {
@ -829,85 +869,6 @@ func (m *Ulimit) GetSoft() int64 {
return 0 return 0
} }
type CommonOptions struct {
Builder string `protobuf:"bytes,1,opt,name=Builder,proto3" json:"Builder,omitempty"`
MetadataFile string `protobuf:"bytes,2,opt,name=MetadataFile,proto3" json:"MetadataFile,omitempty"`
NoCache bool `protobuf:"varint,3,opt,name=NoCache,proto3" json:"NoCache,omitempty"`
// string Progress: no progress view on server side
Pull bool `protobuf:"varint,4,opt,name=Pull,proto3" json:"Pull,omitempty"`
ExportPush bool `protobuf:"varint,5,opt,name=ExportPush,proto3" json:"ExportPush,omitempty"`
ExportLoad bool `protobuf:"varint,6,opt,name=ExportLoad,proto3" json:"ExportLoad,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CommonOptions) Reset() { *m = CommonOptions{} }
func (m *CommonOptions) String() string { return proto.CompactTextString(m) }
func (*CommonOptions) ProtoMessage() {}
func (*CommonOptions) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{14}
}
func (m *CommonOptions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CommonOptions.Unmarshal(m, b)
}
func (m *CommonOptions) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CommonOptions.Marshal(b, m, deterministic)
}
func (m *CommonOptions) XXX_Merge(src proto.Message) {
xxx_messageInfo_CommonOptions.Merge(m, src)
}
func (m *CommonOptions) XXX_Size() int {
return xxx_messageInfo_CommonOptions.Size(m)
}
func (m *CommonOptions) XXX_DiscardUnknown() {
xxx_messageInfo_CommonOptions.DiscardUnknown(m)
}
var xxx_messageInfo_CommonOptions proto.InternalMessageInfo
func (m *CommonOptions) GetBuilder() string {
if m != nil {
return m.Builder
}
return ""
}
func (m *CommonOptions) GetMetadataFile() string {
if m != nil {
return m.MetadataFile
}
return ""
}
func (m *CommonOptions) GetNoCache() bool {
if m != nil {
return m.NoCache
}
return false
}
func (m *CommonOptions) GetPull() bool {
if m != nil {
return m.Pull
}
return false
}
func (m *CommonOptions) GetExportPush() bool {
if m != nil {
return m.ExportPush
}
return false
}
func (m *CommonOptions) GetExportLoad() bool {
if m != nil {
return m.ExportLoad
}
return false
}
type BuildResponse struct { type BuildResponse struct {
ExporterResponse map[string]string `protobuf:"bytes,1,rep,name=ExporterResponse,proto3" json:"ExporterResponse,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` ExporterResponse map[string]string `protobuf:"bytes,1,rep,name=ExporterResponse,proto3" json:"ExporterResponse,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -919,7 +880,7 @@ func (m *BuildResponse) Reset() { *m = BuildResponse{} }
func (m *BuildResponse) String() string { return proto.CompactTextString(m) } func (m *BuildResponse) String() string { return proto.CompactTextString(m) }
func (*BuildResponse) ProtoMessage() {} func (*BuildResponse) ProtoMessage() {}
func (*BuildResponse) Descriptor() ([]byte, []int) { func (*BuildResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{15} return fileDescriptor_ed7f10298fa1d90f, []int{14}
} }
func (m *BuildResponse) XXX_Unmarshal(b []byte) error { func (m *BuildResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BuildResponse.Unmarshal(m, b) return xxx_messageInfo_BuildResponse.Unmarshal(m, b)
@ -957,7 +918,7 @@ func (m *DisconnectRequest) Reset() { *m = DisconnectRequest{} }
func (m *DisconnectRequest) String() string { return proto.CompactTextString(m) } func (m *DisconnectRequest) String() string { return proto.CompactTextString(m) }
func (*DisconnectRequest) ProtoMessage() {} func (*DisconnectRequest) ProtoMessage() {}
func (*DisconnectRequest) Descriptor() ([]byte, []int) { func (*DisconnectRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{16} return fileDescriptor_ed7f10298fa1d90f, []int{15}
} }
func (m *DisconnectRequest) XXX_Unmarshal(b []byte) error { func (m *DisconnectRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DisconnectRequest.Unmarshal(m, b) return xxx_messageInfo_DisconnectRequest.Unmarshal(m, b)
@ -994,7 +955,7 @@ func (m *DisconnectResponse) Reset() { *m = DisconnectResponse{} }
func (m *DisconnectResponse) String() string { return proto.CompactTextString(m) } func (m *DisconnectResponse) String() string { return proto.CompactTextString(m) }
func (*DisconnectResponse) ProtoMessage() {} func (*DisconnectResponse) ProtoMessage() {}
func (*DisconnectResponse) Descriptor() ([]byte, []int) { func (*DisconnectResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{17} return fileDescriptor_ed7f10298fa1d90f, []int{16}
} }
func (m *DisconnectResponse) XXX_Unmarshal(b []byte) error { func (m *DisconnectResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DisconnectResponse.Unmarshal(m, b) return xxx_messageInfo_DisconnectResponse.Unmarshal(m, b)
@ -1025,7 +986,7 @@ func (m *ListRequest) Reset() { *m = ListRequest{} }
func (m *ListRequest) String() string { return proto.CompactTextString(m) } func (m *ListRequest) String() string { return proto.CompactTextString(m) }
func (*ListRequest) ProtoMessage() {} func (*ListRequest) ProtoMessage() {}
func (*ListRequest) Descriptor() ([]byte, []int) { func (*ListRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{18} return fileDescriptor_ed7f10298fa1d90f, []int{17}
} }
func (m *ListRequest) XXX_Unmarshal(b []byte) error { func (m *ListRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListRequest.Unmarshal(m, b) return xxx_messageInfo_ListRequest.Unmarshal(m, b)
@ -1063,7 +1024,7 @@ func (m *ListResponse) Reset() { *m = ListResponse{} }
func (m *ListResponse) String() string { return proto.CompactTextString(m) } func (m *ListResponse) String() string { return proto.CompactTextString(m) }
func (*ListResponse) ProtoMessage() {} func (*ListResponse) ProtoMessage() {}
func (*ListResponse) Descriptor() ([]byte, []int) { func (*ListResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{19} return fileDescriptor_ed7f10298fa1d90f, []int{18}
} }
func (m *ListResponse) XXX_Unmarshal(b []byte) error { func (m *ListResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListResponse.Unmarshal(m, b) return xxx_messageInfo_ListResponse.Unmarshal(m, b)
@ -1104,7 +1065,7 @@ func (m *InputMessage) Reset() { *m = InputMessage{} }
func (m *InputMessage) String() string { return proto.CompactTextString(m) } func (m *InputMessage) String() string { return proto.CompactTextString(m) }
func (*InputMessage) ProtoMessage() {} func (*InputMessage) ProtoMessage() {}
func (*InputMessage) Descriptor() ([]byte, []int) { func (*InputMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{20} return fileDescriptor_ed7f10298fa1d90f, []int{19}
} }
func (m *InputMessage) XXX_Unmarshal(b []byte) error { func (m *InputMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InputMessage.Unmarshal(m, b) return xxx_messageInfo_InputMessage.Unmarshal(m, b)
@ -1178,7 +1139,7 @@ func (m *InputInitMessage) Reset() { *m = InputInitMessage{} }
func (m *InputInitMessage) String() string { return proto.CompactTextString(m) } func (m *InputInitMessage) String() string { return proto.CompactTextString(m) }
func (*InputInitMessage) ProtoMessage() {} func (*InputInitMessage) ProtoMessage() {}
func (*InputInitMessage) Descriptor() ([]byte, []int) { func (*InputInitMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{21} return fileDescriptor_ed7f10298fa1d90f, []int{20}
} }
func (m *InputInitMessage) XXX_Unmarshal(b []byte) error { func (m *InputInitMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InputInitMessage.Unmarshal(m, b) return xxx_messageInfo_InputInitMessage.Unmarshal(m, b)
@ -1217,7 +1178,7 @@ func (m *DataMessage) Reset() { *m = DataMessage{} }
func (m *DataMessage) String() string { return proto.CompactTextString(m) } func (m *DataMessage) String() string { return proto.CompactTextString(m) }
func (*DataMessage) ProtoMessage() {} func (*DataMessage) ProtoMessage() {}
func (*DataMessage) Descriptor() ([]byte, []int) { func (*DataMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{22} return fileDescriptor_ed7f10298fa1d90f, []int{21}
} }
func (m *DataMessage) XXX_Unmarshal(b []byte) error { func (m *DataMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DataMessage.Unmarshal(m, b) return xxx_messageInfo_DataMessage.Unmarshal(m, b)
@ -1261,7 +1222,7 @@ func (m *InputResponse) Reset() { *m = InputResponse{} }
func (m *InputResponse) String() string { return proto.CompactTextString(m) } func (m *InputResponse) String() string { return proto.CompactTextString(m) }
func (*InputResponse) ProtoMessage() {} func (*InputResponse) ProtoMessage() {}
func (*InputResponse) Descriptor() ([]byte, []int) { func (*InputResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{23} return fileDescriptor_ed7f10298fa1d90f, []int{22}
} }
func (m *InputResponse) XXX_Unmarshal(b []byte) error { func (m *InputResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InputResponse.Unmarshal(m, b) return xxx_messageInfo_InputResponse.Unmarshal(m, b)
@ -1297,7 +1258,7 @@ func (m *Message) Reset() { *m = Message{} }
func (m *Message) String() string { return proto.CompactTextString(m) } func (m *Message) String() string { return proto.CompactTextString(m) }
func (*Message) ProtoMessage() {} func (*Message) ProtoMessage() {}
func (*Message) Descriptor() ([]byte, []int) { func (*Message) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{24} return fileDescriptor_ed7f10298fa1d90f, []int{23}
} }
func (m *Message) XXX_Unmarshal(b []byte) error { func (m *Message) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Message.Unmarshal(m, b) return xxx_messageInfo_Message.Unmarshal(m, b)
@ -1399,7 +1360,7 @@ func (m *InitMessage) Reset() { *m = InitMessage{} }
func (m *InitMessage) String() string { return proto.CompactTextString(m) } func (m *InitMessage) String() string { return proto.CompactTextString(m) }
func (*InitMessage) ProtoMessage() {} func (*InitMessage) ProtoMessage() {}
func (*InitMessage) Descriptor() ([]byte, []int) { func (*InitMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{25} return fileDescriptor_ed7f10298fa1d90f, []int{24}
} }
func (m *InitMessage) XXX_Unmarshal(b []byte) error { func (m *InitMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InitMessage.Unmarshal(m, b) return xxx_messageInfo_InitMessage.Unmarshal(m, b)
@ -1459,7 +1420,7 @@ func (m *InvokeConfig) Reset() { *m = InvokeConfig{} }
func (m *InvokeConfig) String() string { return proto.CompactTextString(m) } func (m *InvokeConfig) String() string { return proto.CompactTextString(m) }
func (*InvokeConfig) ProtoMessage() {} func (*InvokeConfig) ProtoMessage() {}
func (*InvokeConfig) Descriptor() ([]byte, []int) { func (*InvokeConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{26} return fileDescriptor_ed7f10298fa1d90f, []int{25}
} }
func (m *InvokeConfig) XXX_Unmarshal(b []byte) error { func (m *InvokeConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InvokeConfig.Unmarshal(m, b) return xxx_messageInfo_InvokeConfig.Unmarshal(m, b)
@ -1555,7 +1516,7 @@ func (m *FdMessage) Reset() { *m = FdMessage{} }
func (m *FdMessage) String() string { return proto.CompactTextString(m) } func (m *FdMessage) String() string { return proto.CompactTextString(m) }
func (*FdMessage) ProtoMessage() {} func (*FdMessage) ProtoMessage() {}
func (*FdMessage) Descriptor() ([]byte, []int) { func (*FdMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{27} return fileDescriptor_ed7f10298fa1d90f, []int{26}
} }
func (m *FdMessage) XXX_Unmarshal(b []byte) error { func (m *FdMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FdMessage.Unmarshal(m, b) return xxx_messageInfo_FdMessage.Unmarshal(m, b)
@ -1608,7 +1569,7 @@ func (m *ResizeMessage) Reset() { *m = ResizeMessage{} }
func (m *ResizeMessage) String() string { return proto.CompactTextString(m) } func (m *ResizeMessage) String() string { return proto.CompactTextString(m) }
func (*ResizeMessage) ProtoMessage() {} func (*ResizeMessage) ProtoMessage() {}
func (*ResizeMessage) Descriptor() ([]byte, []int) { func (*ResizeMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{28} return fileDescriptor_ed7f10298fa1d90f, []int{27}
} }
func (m *ResizeMessage) XXX_Unmarshal(b []byte) error { func (m *ResizeMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ResizeMessage.Unmarshal(m, b) return xxx_messageInfo_ResizeMessage.Unmarshal(m, b)
@ -1655,7 +1616,7 @@ func (m *SignalMessage) Reset() { *m = SignalMessage{} }
func (m *SignalMessage) String() string { return proto.CompactTextString(m) } func (m *SignalMessage) String() string { return proto.CompactTextString(m) }
func (*SignalMessage) ProtoMessage() {} func (*SignalMessage) ProtoMessage() {}
func (*SignalMessage) Descriptor() ([]byte, []int) { func (*SignalMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{29} return fileDescriptor_ed7f10298fa1d90f, []int{28}
} }
func (m *SignalMessage) XXX_Unmarshal(b []byte) error { func (m *SignalMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SignalMessage.Unmarshal(m, b) return xxx_messageInfo_SignalMessage.Unmarshal(m, b)
@ -1693,7 +1654,7 @@ func (m *StatusRequest) Reset() { *m = StatusRequest{} }
func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) ProtoMessage() {}
func (*StatusRequest) Descriptor() ([]byte, []int) { func (*StatusRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{30} return fileDescriptor_ed7f10298fa1d90f, []int{29}
} }
func (m *StatusRequest) XXX_Unmarshal(b []byte) error { func (m *StatusRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusRequest.Unmarshal(m, b) return xxx_messageInfo_StatusRequest.Unmarshal(m, b)
@ -1721,20 +1682,22 @@ func (m *StatusRequest) GetRef() string {
} }
type StatusResponse struct { type StatusResponse struct {
Vertexes []*control.Vertex `protobuf:"bytes,1,rep,name=vertexes,proto3" json:"vertexes,omitempty"` // Types that are valid to be assigned to Status:
Statuses []*control.VertexStatus `protobuf:"bytes,2,rep,name=statuses,proto3" json:"statuses,omitempty"` //
Logs []*control.VertexLog `protobuf:"bytes,3,rep,name=logs,proto3" json:"logs,omitempty"` // *StatusResponse_SolveStatus
Warnings []*control.VertexWarning `protobuf:"bytes,4,rep,name=warnings,proto3" json:"warnings,omitempty"` // *StatusResponse_NodeInfo
XXX_NoUnkeyedLiteral struct{} `json:"-"` // *StatusResponse_ResultInfo
XXX_unrecognized []byte `json:"-"` Status isStatusResponse_Status `protobuf_oneof:"Status"`
XXX_sizecache int32 `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) Reset() { *m = StatusResponse{} }
func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) ProtoMessage() {}
func (*StatusResponse) Descriptor() ([]byte, []int) { func (*StatusResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{31} return fileDescriptor_ed7f10298fa1d90f, []int{30}
} }
func (m *StatusResponse) XXX_Unmarshal(b []byte) error { func (m *StatusResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusResponse.Unmarshal(m, b) return xxx_messageInfo_StatusResponse.Unmarshal(m, b)
@ -1754,34 +1717,223 @@ func (m *StatusResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_StatusResponse proto.InternalMessageInfo var xxx_messageInfo_StatusResponse proto.InternalMessageInfo
func (m *StatusResponse) GetVertexes() []*control.Vertex { type isStatusResponse_Status interface {
isStatusResponse_Status()
}
type StatusResponse_SolveStatus struct {
SolveStatus *SolveStatusMessage `protobuf:"bytes,1,opt,name=SolveStatus,proto3,oneof" json:"SolveStatus,omitempty"`
}
type StatusResponse_NodeInfo struct {
NodeInfo *NodeInfoMessage `protobuf:"bytes,2,opt,name=NodeInfo,proto3,oneof" json:"NodeInfo,omitempty"`
}
type StatusResponse_ResultInfo struct {
ResultInfo *ResultInfoMessage `protobuf:"bytes,3,opt,name=ResultInfo,proto3,oneof" json:"ResultInfo,omitempty"`
}
func (*StatusResponse_SolveStatus) isStatusResponse_Status() {}
func (*StatusResponse_NodeInfo) isStatusResponse_Status() {}
func (*StatusResponse_ResultInfo) isStatusResponse_Status() {}
func (m *StatusResponse) GetStatus() isStatusResponse_Status {
if m != nil {
return m.Status
}
return nil
}
func (m *StatusResponse) GetSolveStatus() *SolveStatusMessage {
if x, ok := m.GetStatus().(*StatusResponse_SolveStatus); ok {
return x.SolveStatus
}
return nil
}
func (m *StatusResponse) GetNodeInfo() *NodeInfoMessage {
if x, ok := m.GetStatus().(*StatusResponse_NodeInfo); ok {
return x.NodeInfo
}
return nil
}
func (m *StatusResponse) GetResultInfo() *ResultInfoMessage {
if x, ok := m.GetStatus().(*StatusResponse_ResultInfo); ok {
return x.ResultInfo
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*StatusResponse) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*StatusResponse_SolveStatus)(nil),
(*StatusResponse_NodeInfo)(nil),
(*StatusResponse_ResultInfo)(nil),
}
}
type SolveStatusMessage struct {
Vertexes []*control.Vertex `protobuf:"bytes,1,rep,name=vertexes,proto3" json:"vertexes,omitempty"`
Statuses []*control.VertexStatus `protobuf:"bytes,2,rep,name=statuses,proto3" json:"statuses,omitempty"`
Logs []*control.VertexLog `protobuf:"bytes,3,rep,name=logs,proto3" json:"logs,omitempty"`
Warnings []*control.VertexWarning `protobuf:"bytes,4,rep,name=warnings,proto3" json:"warnings,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SolveStatusMessage) Reset() { *m = SolveStatusMessage{} }
func (m *SolveStatusMessage) String() string { return proto.CompactTextString(m) }
func (*SolveStatusMessage) ProtoMessage() {}
func (*SolveStatusMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{31}
}
func (m *SolveStatusMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SolveStatusMessage.Unmarshal(m, b)
}
func (m *SolveStatusMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SolveStatusMessage.Marshal(b, m, deterministic)
}
func (m *SolveStatusMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_SolveStatusMessage.Merge(m, src)
}
func (m *SolveStatusMessage) XXX_Size() int {
return xxx_messageInfo_SolveStatusMessage.Size(m)
}
func (m *SolveStatusMessage) XXX_DiscardUnknown() {
xxx_messageInfo_SolveStatusMessage.DiscardUnknown(m)
}
var xxx_messageInfo_SolveStatusMessage proto.InternalMessageInfo
func (m *SolveStatusMessage) GetVertexes() []*control.Vertex {
if m != nil { if m != nil {
return m.Vertexes return m.Vertexes
} }
return nil return nil
} }
func (m *StatusResponse) GetStatuses() []*control.VertexStatus { func (m *SolveStatusMessage) GetStatuses() []*control.VertexStatus {
if m != nil { if m != nil {
return m.Statuses return m.Statuses
} }
return nil return nil
} }
func (m *StatusResponse) GetLogs() []*control.VertexLog { func (m *SolveStatusMessage) GetLogs() []*control.VertexLog {
if m != nil { if m != nil {
return m.Logs return m.Logs
} }
return nil return nil
} }
func (m *StatusResponse) GetWarnings() []*control.VertexWarning { func (m *SolveStatusMessage) GetWarnings() []*control.VertexWarning {
if m != nil { if m != nil {
return m.Warnings return m.Warnings
} }
return nil return nil
} }
type NodeInfoMessage struct {
Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
Driver string `protobuf:"bytes,2,opt,name=Driver,proto3" json:"Driver,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *NodeInfoMessage) Reset() { *m = NodeInfoMessage{} }
func (m *NodeInfoMessage) String() string { return proto.CompactTextString(m) }
func (*NodeInfoMessage) ProtoMessage() {}
func (*NodeInfoMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{32}
}
func (m *NodeInfoMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_NodeInfoMessage.Unmarshal(m, b)
}
func (m *NodeInfoMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_NodeInfoMessage.Marshal(b, m, deterministic)
}
func (m *NodeInfoMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_NodeInfoMessage.Merge(m, src)
}
func (m *NodeInfoMessage) XXX_Size() int {
return xxx_messageInfo_NodeInfoMessage.Size(m)
}
func (m *NodeInfoMessage) XXX_DiscardUnknown() {
xxx_messageInfo_NodeInfoMessage.DiscardUnknown(m)
}
var xxx_messageInfo_NodeInfoMessage proto.InternalMessageInfo
func (m *NodeInfoMessage) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *NodeInfoMessage) GetDriver() string {
if m != nil {
return m.Driver
}
return ""
}
type ResultInfoMessage struct {
Result map[string]string `protobuf:"bytes,1,rep,name=Result,proto3" json:"Result,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
Format string `protobuf:"bytes,3,opt,name=Format,proto3" json:"Format,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ResultInfoMessage) Reset() { *m = ResultInfoMessage{} }
func (m *ResultInfoMessage) String() string { return proto.CompactTextString(m) }
func (*ResultInfoMessage) ProtoMessage() {}
func (*ResultInfoMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{33}
}
func (m *ResultInfoMessage) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ResultInfoMessage.Unmarshal(m, b)
}
func (m *ResultInfoMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ResultInfoMessage.Marshal(b, m, deterministic)
}
func (m *ResultInfoMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_ResultInfoMessage.Merge(m, src)
}
func (m *ResultInfoMessage) XXX_Size() int {
return xxx_messageInfo_ResultInfoMessage.Size(m)
}
func (m *ResultInfoMessage) XXX_DiscardUnknown() {
xxx_messageInfo_ResultInfoMessage.DiscardUnknown(m)
}
var xxx_messageInfo_ResultInfoMessage proto.InternalMessageInfo
func (m *ResultInfoMessage) GetResult() map[string]string {
if m != nil {
return m.Result
}
return nil
}
func (m *ResultInfoMessage) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *ResultInfoMessage) GetFormat() string {
if m != nil {
return m.Format
}
return ""
}
type InfoRequest struct { type InfoRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
@ -1792,7 +1944,7 @@ func (m *InfoRequest) Reset() { *m = InfoRequest{} }
func (m *InfoRequest) String() string { return proto.CompactTextString(m) } func (m *InfoRequest) String() string { return proto.CompactTextString(m) }
func (*InfoRequest) ProtoMessage() {} func (*InfoRequest) ProtoMessage() {}
func (*InfoRequest) Descriptor() ([]byte, []int) { func (*InfoRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{32} return fileDescriptor_ed7f10298fa1d90f, []int{34}
} }
func (m *InfoRequest) XXX_Unmarshal(b []byte) error { func (m *InfoRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InfoRequest.Unmarshal(m, b) return xxx_messageInfo_InfoRequest.Unmarshal(m, b)
@ -1823,7 +1975,7 @@ func (m *InfoResponse) Reset() { *m = InfoResponse{} }
func (m *InfoResponse) String() string { return proto.CompactTextString(m) } func (m *InfoResponse) String() string { return proto.CompactTextString(m) }
func (*InfoResponse) ProtoMessage() {} func (*InfoResponse) ProtoMessage() {}
func (*InfoResponse) Descriptor() ([]byte, []int) { func (*InfoResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{33} return fileDescriptor_ed7f10298fa1d90f, []int{35}
} }
func (m *InfoResponse) XXX_Unmarshal(b []byte) error { func (m *InfoResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InfoResponse.Unmarshal(m, b) return xxx_messageInfo_InfoResponse.Unmarshal(m, b)
@ -1863,7 +2015,7 @@ func (m *BuildxVersion) Reset() { *m = BuildxVersion{} }
func (m *BuildxVersion) String() string { return proto.CompactTextString(m) } func (m *BuildxVersion) String() string { return proto.CompactTextString(m) }
func (*BuildxVersion) ProtoMessage() {} func (*BuildxVersion) ProtoMessage() {}
func (*BuildxVersion) Descriptor() ([]byte, []int) { func (*BuildxVersion) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{34} return fileDescriptor_ed7f10298fa1d90f, []int{36}
} }
func (m *BuildxVersion) XXX_Unmarshal(b []byte) error { func (m *BuildxVersion) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BuildxVersion.Unmarshal(m, b) return xxx_messageInfo_BuildxVersion.Unmarshal(m, b)
@ -1925,7 +2077,6 @@ func init() {
proto.RegisterType((*UlimitOpt)(nil), "buildx.controller.v1.UlimitOpt") proto.RegisterType((*UlimitOpt)(nil), "buildx.controller.v1.UlimitOpt")
proto.RegisterMapType((map[string]*Ulimit)(nil), "buildx.controller.v1.UlimitOpt.ValuesEntry") proto.RegisterMapType((map[string]*Ulimit)(nil), "buildx.controller.v1.UlimitOpt.ValuesEntry")
proto.RegisterType((*Ulimit)(nil), "buildx.controller.v1.Ulimit") proto.RegisterType((*Ulimit)(nil), "buildx.controller.v1.Ulimit")
proto.RegisterType((*CommonOptions)(nil), "buildx.controller.v1.CommonOptions")
proto.RegisterType((*BuildResponse)(nil), "buildx.controller.v1.BuildResponse") proto.RegisterType((*BuildResponse)(nil), "buildx.controller.v1.BuildResponse")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.BuildResponse.ExporterResponseEntry") proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.BuildResponse.ExporterResponseEntry")
proto.RegisterType((*DisconnectRequest)(nil), "buildx.controller.v1.DisconnectRequest") proto.RegisterType((*DisconnectRequest)(nil), "buildx.controller.v1.DisconnectRequest")
@ -1944,6 +2095,10 @@ func init() {
proto.RegisterType((*SignalMessage)(nil), "buildx.controller.v1.SignalMessage") proto.RegisterType((*SignalMessage)(nil), "buildx.controller.v1.SignalMessage")
proto.RegisterType((*StatusRequest)(nil), "buildx.controller.v1.StatusRequest") proto.RegisterType((*StatusRequest)(nil), "buildx.controller.v1.StatusRequest")
proto.RegisterType((*StatusResponse)(nil), "buildx.controller.v1.StatusResponse") proto.RegisterType((*StatusResponse)(nil), "buildx.controller.v1.StatusResponse")
proto.RegisterType((*SolveStatusMessage)(nil), "buildx.controller.v1.SolveStatusMessage")
proto.RegisterType((*NodeInfoMessage)(nil), "buildx.controller.v1.NodeInfoMessage")
proto.RegisterType((*ResultInfoMessage)(nil), "buildx.controller.v1.ResultInfoMessage")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.ResultInfoMessage.ResultEntry")
proto.RegisterType((*InfoRequest)(nil), "buildx.controller.v1.InfoRequest") proto.RegisterType((*InfoRequest)(nil), "buildx.controller.v1.InfoRequest")
proto.RegisterType((*InfoResponse)(nil), "buildx.controller.v1.InfoResponse") proto.RegisterType((*InfoResponse)(nil), "buildx.controller.v1.InfoResponse")
proto.RegisterType((*BuildxVersion)(nil), "buildx.controller.v1.BuildxVersion") proto.RegisterType((*BuildxVersion)(nil), "buildx.controller.v1.BuildxVersion")
@ -1952,119 +2107,127 @@ func init() {
func init() { proto.RegisterFile("controller.proto", fileDescriptor_ed7f10298fa1d90f) } func init() { proto.RegisterFile("controller.proto", fileDescriptor_ed7f10298fa1d90f) }
var fileDescriptor_ed7f10298fa1d90f = []byte{ var fileDescriptor_ed7f10298fa1d90f = []byte{
// 1790 bytes of a gzipped FileDescriptorProto // 1915 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x6e, 0x23, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x72, 0x1b, 0xc7,
0x11, 0xce, 0x90, 0x14, 0x7f, 0x8a, 0xa2, 0xac, 0xed, 0x68, 0x8d, 0x31, 0xed, 0x78, 0xb5, 0xb3, 0x11, 0xce, 0x02, 0x20, 0x7e, 0x1a, 0x04, 0x4d, 0x4d, 0x28, 0x65, 0x04, 0x29, 0x16, 0xb5, 0x92,
0x1b, 0x87, 0xc8, 0x06, 0x94, 0x2d, 0xc7, 0x59, 0xaf, 0x77, 0x03, 0x44, 0xa2, 0x44, 0x48, 0xc6, 0x6d, 0x54, 0x94, 0x02, 0x6d, 0x2a, 0x8e, 0x2c, 0x4b, 0xae, 0x0a, 0x09, 0x12, 0x45, 0x3a, 0x24,
0xea, 0x07, 0x4d, 0xed, 0x1a, 0x49, 0x80, 0x18, 0x43, 0xb2, 0x45, 0x0d, 0x38, 0x9c, 0x66, 0xa6, 0xc5, 0x5a, 0x50, 0x72, 0x25, 0xa9, 0x8a, 0x6b, 0x01, 0x0c, 0xc1, 0x2d, 0x2c, 0x76, 0x90, 0x9d,
0x9b, 0x94, 0x98, 0x53, 0x2e, 0xbe, 0xe6, 0x3d, 0x82, 0x5c, 0x73, 0xcb, 0x29, 0xef, 0x90, 0x07, 0x01, 0x48, 0xe4, 0x94, 0x4b, 0xae, 0x79, 0x8f, 0x54, 0xae, 0xb9, 0xe5, 0x94, 0x53, 0x5e, 0x20,
0xc9, 0x23, 0x04, 0x5d, 0xdd, 0x33, 0x9c, 0x11, 0x39, 0x94, 0x14, 0x9f, 0xd8, 0x55, 0xf3, 0x55, 0x8f, 0x92, 0x83, 0x8f, 0xa9, 0xe9, 0x99, 0x5d, 0x2c, 0x08, 0x2c, 0x48, 0x26, 0x27, 0x4c, 0xf7,
0x55, 0x57, 0x75, 0xfd, 0x74, 0x13, 0x36, 0x7b, 0x3c, 0x90, 0x21, 0xf7, 0x7d, 0x16, 0x36, 0xc7, 0x7e, 0x5f, 0x4f, 0x77, 0x6f, 0x4f, 0x4f, 0x2f, 0x60, 0xbd, 0xc3, 0x03, 0x19, 0x72, 0xdf, 0x67,
0x21, 0x97, 0x9c, 0x6c, 0x75, 0x27, 0x9e, 0xdf, 0xbf, 0x69, 0x26, 0x3e, 0x4c, 0xbf, 0xa8, 0xbf, 0x61, 0x7d, 0x18, 0x72, 0xc9, 0xc9, 0x46, 0x7b, 0xe4, 0xf9, 0xdd, 0xab, 0x7a, 0xe2, 0xc1, 0xf8,
0x1e, 0x78, 0xf2, 0x6a, 0xd2, 0x6d, 0xf6, 0xf8, 0x68, 0x67, 0xc4, 0xbb, 0xb3, 0x1d, 0x44, 0x0d, 0x8b, 0xea, 0x9b, 0x9e, 0x27, 0x2f, 0x46, 0xed, 0x7a, 0x87, 0x0f, 0xb6, 0x06, 0xbc, 0x3d, 0xd9,
0x3d, 0xb9, 0xe3, 0x8e, 0xbd, 0x1d, 0xc1, 0xc2, 0xa9, 0xd7, 0x63, 0x62, 0xc7, 0x08, 0x45, 0xbf, 0x42, 0x54, 0xdf, 0x93, 0x5b, 0xee, 0xd0, 0xdb, 0x12, 0x2c, 0x1c, 0x7b, 0x1d, 0x26, 0xb6, 0x0c,
0x5a, 0xa5, 0xd3, 0x80, 0xad, 0xb7, 0x9e, 0x90, 0xe7, 0x21, 0xef, 0x31, 0x21, 0x98, 0xa0, 0xec, 0x29, 0xfa, 0xd5, 0x26, 0xed, 0x1a, 0x6c, 0x1c, 0x79, 0x42, 0x9e, 0x86, 0xbc, 0xc3, 0x84, 0x60,
0xcf, 0x13, 0x26, 0x24, 0xd9, 0x84, 0x3c, 0x65, 0x97, 0xb6, 0xb5, 0x6d, 0x35, 0x2a, 0x54, 0x2d, 0xc2, 0x61, 0x7f, 0x18, 0x31, 0x21, 0xc9, 0x3a, 0x64, 0x1d, 0x76, 0x4e, 0xad, 0x4d, 0xab, 0x56,
0x9d, 0x73, 0x78, 0x7c, 0x0b, 0x29, 0xc6, 0x3c, 0x10, 0x8c, 0xbc, 0x84, 0xb5, 0xe3, 0xe0, 0x92, 0x72, 0xd4, 0xd2, 0x3e, 0x85, 0xfb, 0xd7, 0x90, 0x62, 0xc8, 0x03, 0xc1, 0xc8, 0x2b, 0x58, 0x39,
0x0b, 0xdb, 0xda, 0xce, 0x37, 0xaa, 0xbb, 0x4f, 0x9b, 0xcb, 0x76, 0xd9, 0x34, 0x72, 0x0a, 0x49, 0x0c, 0xce, 0xb9, 0xa0, 0xd6, 0x66, 0xb6, 0x56, 0xde, 0x7e, 0x5a, 0x5f, 0xe4, 0x65, 0xdd, 0xf0,
0x35, 0xde, 0x11, 0x50, 0x4d, 0x70, 0xc9, 0x27, 0x50, 0x89, 0xc8, 0x03, 0x63, 0x78, 0xce, 0x20, 0x14, 0xd2, 0xd1, 0x78, 0x5b, 0x40, 0x39, 0xa1, 0x25, 0x8f, 0xa1, 0x14, 0x89, 0x7b, 0x66, 0xe3,
0x6d, 0x58, 0x3f, 0x0e, 0xa6, 0x7c, 0xc8, 0x5a, 0x3c, 0xb8, 0xf4, 0x06, 0x76, 0x6e, 0xdb, 0x6a, 0xa9, 0x82, 0x34, 0x61, 0xf5, 0x30, 0x18, 0xf3, 0x3e, 0x6b, 0xf0, 0xe0, 0xdc, 0xeb, 0xd1, 0xcc,
0x54, 0x77, 0x9d, 0xe5, 0xc6, 0x92, 0x48, 0x9a, 0x92, 0x73, 0xbe, 0x05, 0xfb, 0xc0, 0x13, 0x3d, 0xa6, 0x55, 0x2b, 0x6f, 0xdb, 0x8b, 0x37, 0x4b, 0x22, 0x9d, 0x19, 0x9e, 0xfd, 0x2d, 0xd0, 0x3d,
0x1e, 0x04, 0xac, 0x17, 0x39, 0x93, 0xe9, 0x74, 0x7a, 0x4f, 0xb9, 0x5b, 0x7b, 0x72, 0x3e, 0x86, 0x4f, 0x74, 0x78, 0x10, 0xb0, 0x4e, 0x14, 0x4c, 0x6a, 0xd0, 0xb3, 0x3e, 0x65, 0xae, 0xf9, 0x64,
0x8f, 0x96, 0xe8, 0xd2, 0x61, 0x71, 0xfe, 0x04, 0xeb, 0xfb, 0x6a, 0x6f, 0xd9, 0xca, 0xdf, 0x40, 0x3f, 0x82, 0x87, 0x0b, 0x6c, 0xe9, 0xb4, 0xd8, 0xbf, 0x87, 0xd5, 0x5d, 0xe5, 0x5b, 0xba, 0xf1,
0xe9, 0x6c, 0x2c, 0x3d, 0x1e, 0x88, 0xd5, 0xde, 0xa0, 0x1a, 0x83, 0xa4, 0x91, 0x88, 0xf3, 0x03, 0xb7, 0x50, 0x78, 0x37, 0x94, 0x1e, 0x0f, 0xc4, 0xf2, 0x68, 0xd0, 0x8c, 0x41, 0x3a, 0x11, 0xc5,
0x18, 0x03, 0x86, 0x41, 0xb6, 0xa1, 0xda, 0xe2, 0x81, 0x64, 0x37, 0xf2, 0xdc, 0x95, 0x57, 0xc6, 0xfe, 0x01, 0xcc, 0x06, 0x46, 0x41, 0x36, 0xa1, 0xdc, 0xe0, 0x81, 0x64, 0x57, 0xf2, 0xd4, 0x95,
0x50, 0x92, 0x45, 0x3e, 0x83, 0x8d, 0x03, 0xde, 0x1b, 0xb2, 0xf0, 0xd2, 0xf3, 0xd9, 0xa9, 0x3b, 0x17, 0x66, 0xa3, 0xa4, 0x8a, 0x7c, 0x0a, 0x6b, 0x7b, 0xbc, 0xd3, 0x67, 0xe1, 0xb9, 0xe7, 0xb3,
0x62, 0xc6, 0xa5, 0x5b, 0x5c, 0xed, 0xb5, 0x17, 0xc8, 0xf6, 0x24, 0xe8, 0xd9, 0xf9, 0xc8, 0x6b, 0x13, 0x77, 0xc0, 0x4c, 0x48, 0xd7, 0xb4, 0x3a, 0x6a, 0x2f, 0x90, 0xcd, 0x51, 0xd0, 0xa1, 0xd9,
0xc3, 0x20, 0x7f, 0x84, 0x9a, 0x42, 0xf5, 0x8d, 0x66, 0x61, 0x17, 0xf0, 0xdc, 0xbf, 0xba, 0x7b, 0x28, 0x6a, 0xa3, 0x20, 0xbf, 0x83, 0x8a, 0x42, 0x75, 0x8d, 0x65, 0x41, 0x73, 0xf8, 0xde, 0xbf,
0xf3, 0xcd, 0x94, 0xdc, 0x61, 0x20, 0xc3, 0x19, 0x4d, 0xeb, 0x22, 0x5b, 0xb0, 0xb6, 0xe7, 0xfb, 0xbc, 0xd9, 0xf9, 0xfa, 0x0c, 0x6f, 0x3f, 0x90, 0xe1, 0xc4, 0x99, 0xb5, 0x45, 0x36, 0x60, 0x65,
0xfc, 0xda, 0x5e, 0xdb, 0xce, 0x37, 0x2a, 0x54, 0x13, 0xe4, 0x37, 0x50, 0xda, 0x93, 0x92, 0x09, 0xc7, 0xf7, 0xf9, 0x25, 0x5d, 0xd9, 0xcc, 0xd6, 0x4a, 0x8e, 0x16, 0xc8, 0x2f, 0xa1, 0xb0, 0x23,
0x29, 0xec, 0x22, 0x1a, 0xfb, 0x64, 0xb9, 0x31, 0x0d, 0xa2, 0x11, 0x98, 0x9c, 0x41, 0x05, 0xed, 0x25, 0x13, 0x52, 0xd0, 0x3c, 0x6e, 0xf6, 0x78, 0xf1, 0x66, 0x1a, 0xe4, 0x44, 0x60, 0xf2, 0x0e,
0xef, 0x85, 0x03, 0x61, 0x97, 0x50, 0xf2, 0x8b, 0x7b, 0x6c, 0x33, 0x96, 0xd1, 0x5b, 0x9c, 0xeb, 0x4a, 0xb8, 0xff, 0x4e, 0xd8, 0x13, 0xb4, 0x80, 0xcc, 0x2f, 0x6e, 0xe1, 0x66, 0xcc, 0xd1, 0x2e,
0x20, 0x87, 0x50, 0x69, 0xb9, 0xbd, 0x2b, 0xd6, 0x0e, 0xf9, 0xc8, 0x2e, 0xa3, 0xc2, 0x5f, 0x2c, 0x4e, 0x6d, 0x90, 0x7d, 0x28, 0x35, 0xdc, 0xce, 0x05, 0x6b, 0x86, 0x7c, 0x40, 0x8b, 0x68, 0xf0,
0x57, 0x88, 0x30, 0xa3, 0xd0, 0xa8, 0x89, 0x25, 0xc9, 0x1e, 0x94, 0x90, 0xb8, 0xe0, 0x76, 0xe5, 0xb3, 0xc5, 0x06, 0x11, 0x66, 0x0c, 0x1a, 0x33, 0x31, 0x93, 0xec, 0x40, 0x01, 0x85, 0x33, 0x4e,
0x61, 0x4a, 0x22, 0x39, 0xe2, 0xc0, 0x7a, 0x6b, 0x10, 0xf2, 0xc9, 0xf8, 0xdc, 0x0d, 0x59, 0x20, 0x4b, 0x77, 0x33, 0x12, 0xf1, 0x88, 0x0d, 0xab, 0x8d, 0x5e, 0xc8, 0x47, 0xc3, 0x53, 0x37, 0x64,
0x6d, 0xc0, 0x63, 0x4a, 0xf1, 0xc8, 0x6b, 0x28, 0x1d, 0xde, 0x8c, 0x79, 0x28, 0x85, 0x5d, 0x5d, 0x81, 0xa4, 0x80, 0xaf, 0x69, 0x46, 0x47, 0xde, 0x40, 0x61, 0xff, 0x6a, 0xc8, 0x43, 0x29, 0x68,
0x55, 0x9b, 0x1a, 0x64, 0x0c, 0x18, 0x09, 0xf2, 0x29, 0xc0, 0xe1, 0x8d, 0x0c, 0xdd, 0x23, 0xae, 0x79, 0xd9, 0xd9, 0xd4, 0x20, 0xb3, 0x81, 0x61, 0x90, 0x8f, 0x01, 0xf6, 0xaf, 0x64, 0xe8, 0x1e,
0xc2, 0xbe, 0x8e, 0xc7, 0x91, 0xe0, 0x90, 0x36, 0x14, 0xdf, 0xba, 0x5d, 0xe6, 0x0b, 0xbb, 0x86, 0x70, 0x95, 0xf6, 0x55, 0x7c, 0x1d, 0x09, 0x0d, 0x69, 0x42, 0xfe, 0xc8, 0x6d, 0x33, 0x5f, 0xd0,
0xba, 0x9b, 0xf7, 0x08, 0xac, 0x16, 0xd0, 0x86, 0x8c, 0xb4, 0x4a, 0xdb, 0x53, 0x26, 0xaf, 0x79, 0x0a, 0xda, 0xae, 0xdf, 0x22, 0xb1, 0x9a, 0xa0, 0x37, 0x32, 0x6c, 0x55, 0xb6, 0x27, 0x4c, 0x5e,
0x38, 0x3c, 0xe1, 0x7d, 0x66, 0x6f, 0xe8, 0xb4, 0x4d, 0xb0, 0xc8, 0x73, 0xa8, 0x9d, 0x72, 0x1d, 0xf2, 0xb0, 0x7f, 0xcc, 0xbb, 0x8c, 0xae, 0xe9, 0xb2, 0x4d, 0xa8, 0xc8, 0x73, 0xa8, 0x9c, 0x70,
0x3c, 0xcf, 0x97, 0x2c, 0xb4, 0x3f, 0xc0, 0xcd, 0xa4, 0x99, 0x98, 0xb4, 0xbe, 0x2b, 0x2f, 0x79, 0x9d, 0x3c, 0xcf, 0x97, 0x2c, 0xa4, 0x1f, 0xa1, 0x33, 0xb3, 0x4a, 0x2c, 0x5a, 0xdf, 0x95, 0xe7,
0x38, 0x12, 0xf6, 0x26, 0x22, 0xe6, 0x0c, 0x95, 0x41, 0x1d, 0xd6, 0x0b, 0x99, 0x14, 0xf6, 0xa3, 0x3c, 0x1c, 0x08, 0xba, 0x8e, 0x88, 0xa9, 0x42, 0x55, 0x50, 0x8b, 0x75, 0x42, 0x26, 0x05, 0xbd,
0x55, 0x19, 0xa4, 0x41, 0x34, 0x02, 0x13, 0x1b, 0x4a, 0x9d, 0xab, 0x51, 0xc7, 0xfb, 0x0b, 0xb3, 0xb7, 0xac, 0x82, 0x34, 0xc8, 0x89, 0xc0, 0x84, 0x42, 0xa1, 0x75, 0x31, 0x68, 0x79, 0x7f, 0x64,
0xc9, 0xb6, 0xd5, 0xc8, 0xd3, 0x88, 0x24, 0x2f, 0x20, 0xdf, 0xe9, 0x1c, 0xd9, 0x3f, 0x45, 0x6d, 0x94, 0x6c, 0x5a, 0xb5, 0xac, 0x13, 0x89, 0xe4, 0x05, 0x64, 0x5b, 0xad, 0x03, 0xfa, 0x63, 0xb4,
0x1f, 0x65, 0x68, 0xeb, 0x1c, 0x51, 0x85, 0x22, 0x04, 0x0a, 0x17, 0xee, 0x40, 0xd8, 0x5b, 0xb8, 0xf6, 0x30, 0xc5, 0x5a, 0xeb, 0xc0, 0x51, 0x28, 0x42, 0x20, 0x77, 0xe6, 0xf6, 0x04, 0xdd, 0x40,
0x2f, 0x5c, 0x93, 0x0f, 0xa1, 0x78, 0xe1, 0x86, 0x03, 0x26, 0xed, 0xc7, 0xe8, 0xb3, 0xa1, 0xc8, 0xbf, 0x70, 0x4d, 0x1e, 0x40, 0xfe, 0xcc, 0x0d, 0x7b, 0x4c, 0xd2, 0xfb, 0x18, 0xb3, 0x91, 0xc8,
0x2b, 0x28, 0xbd, 0xf3, 0xbd, 0x91, 0x27, 0x85, 0xfd, 0x21, 0xb6, 0x85, 0x27, 0xcb, 0x95, 0x6b, 0x6b, 0x28, 0xbc, 0xf7, 0xbd, 0x81, 0x27, 0x05, 0x7d, 0x80, 0x6d, 0xe1, 0xc9, 0x62, 0xe3, 0x1a,
0xd0, 0xd9, 0x58, 0xd2, 0x08, 0x4f, 0x5e, 0x42, 0xe1, 0x6c, 0x2c, 0x85, 0x6d, 0xa3, 0xdc, 0xb3, 0xf4, 0x6e, 0x28, 0x9d, 0x08, 0xaf, 0xbc, 0xc5, 0x7c, 0xb3, 0x90, 0xfe, 0x04, 0x6d, 0x46, 0xa2,
0x8c, 0xa4, 0xe2, 0xa3, 0x11, 0x0f, 0xa2, 0x7e, 0x82, 0x02, 0xf5, 0xdf, 0x01, 0x59, 0xac, 0x4d, 0x2a, 0x97, 0x63, 0x26, 0xdd, 0xae, 0x2b, 0xdd, 0xa6, 0xe7, 0x33, 0x4a, 0x75, 0xb9, 0x24, 0x75,
0xd5, 0xb2, 0x86, 0x6c, 0x16, 0xb5, 0xac, 0x21, 0x9b, 0xa9, 0xf2, 0x9c, 0xba, 0xfe, 0x24, 0x6a, 0x8a, 0x6d, 0x52, 0x4a, 0x1f, 0x6e, 0x5a, 0xb5, 0xa2, 0x13, 0x89, 0xca, 0xfd, 0xd3, 0x91, 0xef,
0x1c, 0x9a, 0xf8, 0x26, 0xf7, 0xb5, 0x55, 0x7f, 0x03, 0x1b, 0xe9, 0xb2, 0x79, 0x90, 0xf4, 0x2b, 0xd3, 0x2a, 0xaa, 0x71, 0xad, 0xeb, 0x43, 0x95, 0xca, 0xe9, 0x48, 0x5c, 0xd0, 0x47, 0xf8, 0x24,
0xa8, 0x26, 0x72, 0xe3, 0x21, 0xa2, 0xce, 0xbf, 0x2d, 0xa8, 0x26, 0x12, 0x18, 0x43, 0x3d, 0x1b, 0xa1, 0x99, 0x3e, 0x3f, 0xe2, 0x6e, 0x97, 0x3e, 0x4e, 0x3e, 0x57, 0x9a, 0xea, 0xaf, 0x80, 0xcc,
0x33, 0x23, 0x8c, 0x6b, 0xb2, 0x0f, 0x6b, 0x7b, 0x52, 0x86, 0xaa, 0xcf, 0xaa, 0xd3, 0xfa, 0xd5, 0xb7, 0x03, 0xd5, 0x25, 0xfb, 0x6c, 0x12, 0x75, 0xc9, 0x3e, 0x9b, 0xa8, 0x8e, 0x30, 0x76, 0xfd,
0x9d, 0x65, 0xd0, 0x44, 0xb8, 0x4e, 0x54, 0x2d, 0xaa, 0xf2, 0xf4, 0x80, 0x09, 0xe9, 0x05, 0xae, 0x51, 0xd4, 0xab, 0xb4, 0xf0, 0x75, 0xe6, 0x2b, 0xab, 0xfa, 0x16, 0xd6, 0x66, 0x4f, 0xea, 0x9d,
0x0a, 0x9c, 0x69, 0x8b, 0x49, 0x56, 0xfd, 0x6b, 0x80, 0xb9, 0xd8, 0x83, 0x7c, 0xf8, 0x87, 0x05, 0xd8, 0xaf, 0xa1, 0x9c, 0x28, 0xc7, 0xbb, 0x50, 0xed, 0x7f, 0x5a, 0x50, 0x4e, 0x9c, 0x19, 0x7c,
0x8f, 0x16, 0x6a, 0x7d, 0xa9, 0x27, 0x47, 0x69, 0x4f, 0x76, 0xef, 0xd9, 0x37, 0x16, 0xfd, 0xf9, 0xbb, 0x93, 0x21, 0x33, 0x64, 0x5c, 0x93, 0x5d, 0x58, 0xd9, 0x91, 0x32, 0x54, 0xad, 0x5d, 0x15,
0x11, 0xbb, 0x3d, 0x85, 0xa2, 0x6e, 0xb0, 0x4b, 0x77, 0x58, 0x87, 0xf2, 0x81, 0x27, 0xdc, 0xae, 0xc8, 0xcf, 0x6f, 0x3c, 0x79, 0x75, 0x84, 0xeb, 0xb3, 0xa1, 0xa9, 0xea, 0x68, 0xec, 0x31, 0x21,
0xcf, 0xfa, 0x28, 0x5a, 0xa6, 0x31, 0x8d, 0xdd, 0x1d, 0x77, 0xaf, 0xa3, 0xa7, 0x09, 0x47, 0x57, 0xbd, 0xc0, 0x55, 0xc7, 0xc7, 0x74, 0xe2, 0xa4, 0xaa, 0xfa, 0x15, 0xc0, 0x94, 0x76, 0xa7, 0x18,
0x12, 0xd9, 0x80, 0x5c, 0x3c, 0xf8, 0x73, 0xc7, 0x07, 0x0a, 0xac, 0xa6, 0x96, 0x76, 0xb5, 0x42, 0xfe, 0x66, 0xc1, 0xbd, 0xb9, 0xf6, 0xb2, 0x30, 0x92, 0x83, 0xd9, 0x48, 0xb6, 0x6f, 0xd9, 0xaa,
0x35, 0xe1, 0xb4, 0xa1, 0xa8, 0x6b, 0x73, 0x01, 0x5f, 0x87, 0x72, 0xdb, 0xf3, 0x19, 0x0e, 0x3f, 0xe6, 0xe3, 0xf9, 0x3f, 0xbc, 0x3d, 0x81, 0xbc, 0xee, 0xe9, 0x0b, 0x3d, 0xac, 0x42, 0x71, 0xcf,
0xbd, 0xe7, 0x98, 0x56, 0xee, 0x1d, 0x06, 0x53, 0x63, 0x56, 0x2d, 0x9d, 0xbf, 0x5b, 0x50, 0x89, 0x13, 0x6e, 0xdb, 0x67, 0x5d, 0xa4, 0x16, 0x9d, 0x58, 0xc6, 0x0b, 0x05, 0xbd, 0xd7, 0xd9, 0xd3,
0x2b, 0x88, 0xb4, 0xa0, 0x88, 0xfe, 0x45, 0x97, 0x98, 0x17, 0x77, 0x94, 0x5c, 0xf3, 0x3d, 0xa2, 0x82, 0xad, 0x0f, 0x2f, 0x59, 0x83, 0x4c, 0x3c, 0x6b, 0x64, 0x0e, 0xf7, 0x14, 0x58, 0x5d, 0x94,
0x4d, 0x27, 0xd3, 0xa2, 0xf5, 0xef, 0xa0, 0x9a, 0x60, 0x2f, 0x09, 0xe9, 0x6e, 0x32, 0xa4, 0x99, 0x3a, 0xd4, 0x92, 0xa3, 0x05, 0xbb, 0x09, 0x79, 0xdd, 0x0e, 0xe6, 0xf0, 0x55, 0x28, 0xaa, 0x93,
0x2d, 0x48, 0x1b, 0x49, 0x06, 0xfc, 0x00, 0x8a, 0x9a, 0xa9, 0x02, 0x8e, 0x73, 0xdb, 0x04, 0x1c, 0x83, 0xf7, 0xad, 0xf6, 0x39, 0x96, 0x55, 0x78, 0xfb, 0xc1, 0xd8, 0x6c, 0xab, 0x96, 0xf6, 0x5f,
0xa7, 0x35, 0x81, 0xc2, 0x91, 0x1b, 0xea, 0x60, 0xe7, 0x29, 0xae, 0x15, 0xaf, 0xc3, 0x2f, 0x25, 0x2d, 0x28, 0xc5, 0x87, 0x96, 0x34, 0x20, 0x8f, 0xf1, 0x45, 0x73, 0xd3, 0x8b, 0x1b, 0x4e, 0x79,
0x3a, 0x9c, 0xa7, 0xb8, 0x76, 0xfe, 0x65, 0x41, 0x2d, 0x55, 0xfb, 0xaa, 0xb9, 0x61, 0xcd, 0xb2, 0xfd, 0x03, 0xa2, 0x4d, 0xf3, 0xd4, 0xd4, 0xea, 0x77, 0x50, 0x4e, 0xa8, 0x17, 0xa4, 0x74, 0x3b,
0xd0, 0x28, 0x8c, 0x48, 0x35, 0x5d, 0x4e, 0x98, 0x74, 0xfb, 0xae, 0x74, 0x55, 0x0c, 0x4d, 0x3c, 0x99, 0xd2, 0xd4, 0xae, 0xa7, 0x37, 0x49, 0x26, 0x7c, 0x0f, 0xf2, 0x5a, 0xa9, 0x12, 0x8e, 0xa3,
0x53, 0x3c, 0x25, 0x6d, 0x3a, 0x30, 0x9a, 0x29, 0xd3, 0x88, 0x54, 0xd6, 0xcf, 0x27, 0xbe, 0x6f, 0x82, 0x49, 0x38, 0x0e, 0x08, 0x04, 0x72, 0x07, 0x6e, 0xa8, 0x93, 0x9d, 0x75, 0x70, 0xad, 0x74,
0x17, 0x90, 0x8d, 0x6b, 0x3d, 0x4e, 0x54, 0x7d, 0x9d, 0x4f, 0xc4, 0x95, 0xbd, 0x86, 0x5f, 0x12, 0x2d, 0x7e, 0x2e, 0x31, 0xe0, 0xac, 0x83, 0x6b, 0xfb, 0x1f, 0x16, 0x54, 0xcc, 0x10, 0x64, 0x86,
0x9c, 0xf9, 0xf7, 0xb7, 0xdc, 0xed, 0xdb, 0xc5, 0xe4, 0x77, 0xc5, 0xc1, 0xdd, 0x9b, 0xfb, 0x94, 0x45, 0x06, 0xeb, 0xba, 0xe6, 0x59, 0x18, 0xe9, 0x4c, 0xfc, 0xaf, 0x97, 0xdc, 0x1f, 0x11, 0xb4,
0xb9, 0x77, 0x32, 0xd8, 0xd4, 0xdf, 0x59, 0x18, 0xf1, 0xcc, 0xe9, 0xbd, 0x5a, 0x31, 0x8a, 0x22, 0x7e, 0x9d, 0xab, 0xb3, 0x31, 0x67, 0xb2, 0xda, 0x80, 0xfb, 0x0b, 0xa1, 0x77, 0x2a, 0xba, 0x4f,
0x68, 0xf3, 0xb6, 0xac, 0x3e, 0xcb, 0x05, 0x95, 0xf5, 0x16, 0x3c, 0x5e, 0x0a, 0x7d, 0x50, 0xc9, 0xe0, 0xde, 0x74, 0xbc, 0x4b, 0x1f, 0x8c, 0x37, 0x80, 0x24, 0x61, 0x66, 0xfc, 0x7b, 0x02, 0x65,
0xfc, 0x1c, 0x1e, 0xcd, 0x6f, 0x8a, 0xd9, 0x77, 0xec, 0x2d, 0x20, 0x49, 0x98, 0xb9, 0x49, 0x3e, 0x35, 0x2e, 0xa7, 0xd3, 0x6c, 0x58, 0xd5, 0x00, 0x93, 0x19, 0x02, 0xb9, 0x3e, 0x9b, 0xe8, 0x6a,
0x81, 0xaa, 0xba, 0x79, 0x67, 0x8b, 0x39, 0xb0, 0xae, 0x01, 0x26, 0x32, 0x04, 0x0a, 0x43, 0x36, 0x28, 0x39, 0xb8, 0xb6, 0xff, 0x62, 0xa9, 0xa9, 0x77, 0x38, 0x92, 0xc7, 0x4c, 0x08, 0xb7, 0xc7,
0xd3, 0xb9, 0x5c, 0xa1, 0xb8, 0x76, 0xfe, 0x66, 0xa9, 0x0b, 0xf4, 0x78, 0x22, 0x4f, 0x98, 0x10, 0xc8, 0x5b, 0xc8, 0x1d, 0x06, 0x9e, 0x44, 0x3b, 0xe5, 0xed, 0x4f, 0xd3, 0xa6, 0xdf, 0xe1, 0x48,
0xee, 0x80, 0x91, 0x37, 0x50, 0x38, 0x0e, 0x3c, 0x89, 0x7a, 0xaa, 0xbb, 0x9f, 0x65, 0x5d, 0xa4, 0x2a, 0x98, 0x61, 0x1d, 0xfc, 0xc8, 0x41, 0x16, 0x79, 0x05, 0xb9, 0x3d, 0x57, 0xba, 0xa6, 0x16,
0xc7, 0x13, 0xa9, 0x60, 0x46, 0xea, 0xe8, 0x27, 0x14, 0xa5, 0xd4, 0xa4, 0x39, 0x70, 0xa5, 0x6b, 0x52, 0x86, 0x01, 0x85, 0x48, 0x10, 0x95, 0xb8, 0x5b, 0x50, 0x23, 0xfe, 0x70, 0x24, 0xed, 0xe7,
0x32, 0x39, 0xe3, 0x5e, 0xa1, 0x10, 0x09, 0x41, 0x45, 0xee, 0x97, 0xd4, 0x6b, 0x61, 0x3c, 0x91, 0xb0, 0x7e, 0xdd, 0xfa, 0x82, 0xd0, 0x5e, 0x42, 0x39, 0x61, 0x05, 0x4f, 0xc2, 0xbb, 0x26, 0x02,
0xce, 0x73, 0xd8, 0xbc, 0xad, 0x7d, 0x89, 0x6b, 0x5f, 0x42, 0x35, 0xa1, 0x05, 0xeb, 0xf8, 0xac, 0x8a, 0x8e, 0x5a, 0xaa, 0x58, 0x63, 0x47, 0x56, 0xf5, 0x1e, 0xf6, 0x47, 0x50, 0x41, 0xd3, 0x71,
0x8d, 0x80, 0x32, 0x55, 0x4b, 0xe5, 0x6b, 0xbc, 0x91, 0x75, 0x6d, 0xc3, 0xf9, 0x00, 0x6a, 0xa8, 0x06, 0xff, 0x94, 0x81, 0x42, 0x64, 0xe2, 0xd5, 0x4c, 0xdc, 0x4f, 0xd3, 0xe2, 0x9e, 0x0f, 0xf9,
0x3a, 0x8e, 0xe0, 0x5f, 0x73, 0x50, 0x8a, 0x54, 0xbc, 0x4c, 0xf9, 0xfd, 0x34, 0xcb, 0xef, 0x45, 0x4b, 0xc8, 0xe1, 0x7d, 0x97, 0x59, 0x76, 0x93, 0x36, 0xbb, 0x09, 0x1a, 0x5e, 0x85, 0xdf, 0x40,
0x97, 0xbf, 0x82, 0x42, 0x5c, 0x0b, 0x99, 0x43, 0xb9, 0xdd, 0x4f, 0x88, 0x61, 0x99, 0xfc, 0x16, 0xde, 0x61, 0x42, 0xdd, 0xfa, 0x59, 0x24, 0x3e, 0x5b, 0x4c, 0xd4, 0x98, 0x29, 0xd9, 0x90, 0x14,
0x8a, 0x94, 0x09, 0x75, 0x81, 0xc8, 0xaf, 0x9a, 0xca, 0x1a, 0x33, 0x17, 0x36, 0x42, 0x4a, 0xbc, 0xbd, 0xe5, 0xf5, 0x02, 0xd7, 0xa7, 0xb9, 0x65, 0x74, 0x8d, 0x49, 0xd0, 0xb5, 0x62, 0x9a, 0xee,
0xe3, 0x0d, 0x02, 0x57, 0x57, 0x53, 0xa6, 0xb8, 0xc6, 0x24, 0xc4, 0x35, 0x63, 0x1e, 0xee, 0x1f, 0x3f, 0x5b, 0x50, 0x5e, 0x9a, 0xea, 0xe5, 0x1f, 0x28, 0x73, 0x1f, 0x4d, 0xd9, 0xff, 0xf1, 0xa3,
0x2c, 0xa8, 0xae, 0x0c, 0xf5, 0xea, 0xb7, 0xce, 0xc2, 0xfb, 0x2b, 0xff, 0x7f, 0xbe, 0xbf, 0xfe, 0xe9, 0xdf, 0xd6, 0xac, 0x21, 0xbc, 0xdc, 0xd5, 0x79, 0x1a, 0x72, 0x2f, 0x90, 0xa6, 0x64, 0x13,
0x63, 0xa5, 0x15, 0x61, 0xe1, 0xab, 0x7a, 0x1a, 0x73, 0x2f, 0x90, 0x26, 0x65, 0x13, 0x1c, 0xb5, 0x1a, 0xe5, 0x68, 0x63, 0xd0, 0x35, 0x6d, 0x54, 0x2d, 0xa7, 0xed, 0x30, 0x6b, 0xda, 0xa1, 0x2a,
0xd1, 0xd6, 0xa8, 0x6f, 0x86, 0x80, 0x5a, 0xce, 0x9b, 0x79, 0xde, 0x34, 0x73, 0x95, 0x04, 0xef, 0x82, 0xf7, 0x82, 0x85, 0x98, 0xa2, 0x92, 0x83, 0x6b, 0x35, 0x13, 0x9d, 0x70, 0xd4, 0xae, 0x60,
0x04, 0x0b, 0x31, 0x44, 0x15, 0x8a, 0x6b, 0x75, 0xbd, 0x3a, 0xe5, 0xc8, 0xd5, 0xcd, 0xc6, 0x50, 0xb5, 0x18, 0x09, 0xed, 0x5d, 0x76, 0x69, 0x5e, 0x07, 0xde, 0xb8, 0xc4, 0xbe, 0x7e, 0xc2, 0x95,
0xa8, 0xef, 0x5a, 0x77, 0x18, 0xa5, 0xef, 0x1a, 0xa7, 0xd2, 0x29, 0x57, 0xbc, 0x12, 0x02, 0x35, 0xae, 0x80, 0x40, 0x2d, 0x28, 0xdc, 0x99, 0x9c, 0xd0, 0xa2, 0x2e, 0xb5, 0x33, 0x39, 0x51, 0x2d,
0xa1, 0x70, 0x17, 0x72, 0x66, 0x97, 0x75, 0xaa, 0x5d, 0xc8, 0x99, 0x1a, 0x30, 0x94, 0xfb, 0x7e, 0xda, 0xe1, 0xbe, 0xdf, 0x76, 0x3b, 0x7d, 0x5a, 0xd2, 0x77, 0x43, 0x24, 0xdb, 0x3b, 0x50, 0x8a,
0xd7, 0xed, 0x0d, 0xed, 0x8a, 0x9e, 0x6c, 0x11, 0xed, 0xec, 0x41, 0x25, 0x3e, 0x7a, 0x35, 0x99, 0x5f, 0xbd, 0xea, 0xed, 0xcd, 0x2e, 0xa6, 0xb6, 0xe2, 0x64, 0x9a, 0xdd, 0xa8, 0x6a, 0x33, 0xf3,
0xda, 0x7d, 0x0c, 0x6d, 0x8d, 0xe6, 0xda, 0xfd, 0x28, 0x6b, 0x73, 0x8b, 0x59, 0x9b, 0x4f, 0x64, 0x55, 0x9b, 0x4d, 0x54, 0xed, 0x2b, 0xa8, 0xcc, 0x14, 0x81, 0x02, 0x39, 0xfc, 0x52, 0x18, 0x43,
0xed, 0x4b, 0xa8, 0xa5, 0x92, 0x40, 0x81, 0x28, 0xbf, 0x16, 0x46, 0x11, 0xae, 0x15, 0xaf, 0xc5, 0xb8, 0x56, 0xba, 0x06, 0xf7, 0xf5, 0x57, 0x5e, 0xc5, 0xc1, 0xb5, 0xfd, 0x0c, 0x2a, 0x33, 0xaf,
0x7d, 0xfd, 0x60, 0xac, 0x51, 0x5c, 0x3b, 0xcf, 0xa0, 0x96, 0x3a, 0xfe, 0x65, 0x53, 0xc2, 0x79, 0x7f, 0x51, 0x9f, 0xb5, 0x9f, 0x42, 0xa5, 0x25, 0x5d, 0x39, 0x5a, 0xf2, 0x59, 0xfe, 0x83, 0x05,
0x0a, 0xb5, 0x8e, 0x74, 0xe5, 0x64, 0xc5, 0x0b, 0xff, 0xbf, 0x16, 0x6c, 0x44, 0x18, 0xd3, 0x49, 0x6b, 0x11, 0xc6, 0x74, 0x92, 0x23, 0x28, 0xb7, 0xb8, 0x3f, 0x66, 0x5a, 0x6d, 0xce, 0x4c, 0x2d,
0x7e, 0x0d, 0xe5, 0x29, 0x0b, 0x25, 0xbb, 0x89, 0x27, 0xa3, 0xdd, 0x1c, 0xf1, 0xee, 0xac, 0x19, 0xa5, 0x04, 0xa7, 0xc0, 0x69, 0x1d, 0x26, 0xe9, 0xa4, 0x01, 0xc5, 0x13, 0xde, 0x65, 0xea, 0x13,
0xfd, 0xc7, 0xa0, 0x4e, 0xfb, 0x3d, 0x22, 0x68, 0x8c, 0x24, 0xdf, 0x40, 0x59, 0xa0, 0x1e, 0x16, 0xdd, 0x9c, 0xa2, 0x4f, 0x16, 0x9b, 0x8a, 0x50, 0x53, 0x3b, 0x31, 0x91, 0x1c, 0x02, 0x38, 0x4c,
0xdd, 0x53, 0x3e, 0xcd, 0x92, 0x32, 0xf6, 0x62, 0x3c, 0xd9, 0x81, 0x82, 0xcf, 0x07, 0x02, 0x4f, 0x8c, 0x7c, 0x89, 0x66, 0x74, 0x19, 0x7e, 0x96, 0x7a, 0xa6, 0x0c, 0x6e, 0x6a, 0x28, 0x41, 0xde,
0xb7, 0xba, 0xfb, 0x71, 0x96, 0xdc, 0x5b, 0x3e, 0xa0, 0x08, 0x24, 0xaf, 0xa1, 0x7c, 0xed, 0x86, 0x2d, 0x42, 0x5e, 0x7b, 0x66, 0xff, 0xc7, 0x02, 0x32, 0xef, 0x3f, 0xf9, 0x05, 0x14, 0xc7, 0x2c,
0x81, 0x17, 0x0c, 0xa2, 0x97, 0xe8, 0x93, 0x2c, 0xa1, 0xef, 0x34, 0x8e, 0xc6, 0x02, 0x4e, 0x4d, 0x94, 0xec, 0x2a, 0xbe, 0x5a, 0x69, 0x7d, 0xc0, 0xdb, 0x93, 0x7a, 0xf4, 0xbf, 0x88, 0xda, 0xe5,
0x15, 0xc5, 0x25, 0x37, 0x31, 0x71, 0x7e, 0xaf, 0x72, 0x53, 0x91, 0xc6, 0xfd, 0x63, 0xa8, 0xe9, 0x03, 0x22, 0x9c, 0x18, 0x49, 0xbe, 0x86, 0xa2, 0x40, 0x33, 0x2c, 0x1a, 0x74, 0x3e, 0x4e, 0x63,
0xfc, 0x7e, 0xcf, 0x42, 0xa1, 0x6e, 0x7d, 0xd6, 0xaa, 0x1a, 0xdc, 0x4f, 0x42, 0x69, 0x5a, 0xd2, 0x99, 0x74, 0xc7, 0x78, 0xb2, 0x05, 0x39, 0x9f, 0xf7, 0x04, 0x16, 0x77, 0x79, 0xfb, 0x51, 0x1a,
0xf9, 0xde, 0x8c, 0xaf, 0x88, 0xa1, 0xc6, 0xe7, 0xd8, 0xed, 0x0d, 0xdd, 0x41, 0x74, 0x4e, 0x11, 0xef, 0x88, 0xf7, 0x1c, 0x04, 0x92, 0x37, 0x50, 0xbc, 0x74, 0xc3, 0xc0, 0x0b, 0x7a, 0xd1, 0xd7,
0xa9, 0xbe, 0x4c, 0x8d, 0x3d, 0x5d, 0x86, 0x11, 0xa9, 0x32, 0x30, 0x64, 0x53, 0x4f, 0xcc, 0x2f, 0xf3, 0x93, 0x34, 0xd2, 0x77, 0x1a, 0xe7, 0xc4, 0x04, 0xfb, 0x1b, 0xf8, 0xe8, 0x5a, 0xaa, 0x17,
0xa0, 0x31, 0xbd, 0xfb, 0xcf, 0x22, 0x40, 0x2b, 0xde, 0x0f, 0x39, 0x87, 0x35, 0xb4, 0x47, 0x9c, 0xde, 0xd1, 0x0f, 0x20, 0xbf, 0x17, 0x7a, 0x63, 0x16, 0x9a, 0xb6, 0x60, 0x24, 0xfb, 0x5f, 0x16,
0x95, 0xc3, 0x10, 0xfd, 0xae, 0x3f, 0xbb, 0xc7, 0xc0, 0x24, 0xef, 0xa0, 0xa8, 0x4f, 0x8b, 0x64, 0xdc, 0x9b, 0xcb, 0x31, 0xf9, 0x35, 0x36, 0xbc, 0x91, 0x2f, 0x4d, 0xca, 0x5e, 0xde, 0xf2, 0xe5,
0xf5, 0xa0, 0x64, 0x7e, 0xd5, 0x9f, 0xaf, 0x06, 0x69, 0xa5, 0x9f, 0x5b, 0x84, 0x9a, 0x0e, 0x45, 0x18, 0x8d, 0x99, 0x4a, 0xb4, 0x10, 0xbb, 0x93, 0x99, 0x75, 0xa7, 0xc9, 0xc3, 0x81, 0x2b, 0xcd,
0x9c, 0x15, 0x23, 0xc8, 0x64, 0x76, 0xd6, 0x46, 0x53, 0xdd, 0xbe, 0x61, 0x91, 0x6f, 0xa1, 0xa8, 0x44, 0x64, 0x24, 0x35, 0x86, 0x27, 0x4c, 0xdc, 0xe9, 0x7e, 0xae, 0xa8, 0xe6, 0x78, 0xce, 0xcd,
0x7b, 0x0c, 0xf9, 0xd9, 0x72, 0x81, 0x48, 0xdf, 0xea, 0xcf, 0x0d, 0xeb, 0x73, 0x8b, 0x9c, 0x40, 0xd9, 0xb0, 0x7f, 0xa3, 0x7a, 0x94, 0x12, 0xcd, 0x31, 0x38, 0x84, 0x8a, 0x8e, 0xe1, 0x03, 0x0b,
0x41, 0x0d, 0x57, 0x92, 0x31, 0x29, 0x12, 0x93, 0xb9, 0xee, 0xac, 0x82, 0x98, 0x28, 0x7e, 0x0f, 0x85, 0x9a, 0x9f, 0xad, 0x65, 0xbd, 0x78, 0x37, 0x09, 0x75, 0x66, 0x99, 0xf6, 0xf7, 0x66, 0x8c,
0x30, 0x1f, 0xf1, 0x24, 0xe3, 0xdd, 0xbf, 0x70, 0x57, 0xa8, 0x37, 0xee, 0x06, 0x1a, 0x03, 0x27, 0x89, 0x14, 0xea, 0x53, 0x69, 0xe8, 0x76, 0xfa, 0x6e, 0x2f, 0xca, 0x79, 0x24, 0xaa, 0x27, 0x63,
0x6a, 0xbe, 0x5d, 0x72, 0x92, 0x39, 0xd9, 0xe2, 0x74, 0xaf, 0x3b, 0xab, 0x20, 0x46, 0xdd, 0x15, 0xb3, 0x9f, 0x76, 0x38, 0x12, 0x55, 0x27, 0x0a, 0xd9, 0xd8, 0x13, 0xd3, 0x51, 0x3e, 0x96, 0xb7,
0xd4, 0x52, 0x7f, 0xfb, 0x91, 0x5f, 0x66, 0x3b, 0x79, 0xfb, 0x5f, 0xc4, 0xfa, 0x8b, 0x7b, 0x61, 0xff, 0x9e, 0x07, 0x68, 0xc4, 0xfe, 0x90, 0x53, 0x58, 0xc1, 0xfd, 0x88, 0xbd, 0x74, 0x28, 0xc2,
0x8d, 0x25, 0x99, 0xbc, 0x23, 0x99, 0xcf, 0xa4, 0x79, 0x97, 0xdf, 0xe9, 0xbf, 0xf0, 0xea, 0x3b, 0xb8, 0xab, 0xcf, 0x6e, 0x31, 0x38, 0x91, 0xf7, 0xd1, 0xa9, 0x21, 0x69, 0x77, 0x51, 0xb2, 0xcf,
0xf7, 0xc6, 0x6b, 0xab, 0xfb, 0x85, 0x3f, 0xe4, 0xc6, 0xdd, 0x6e, 0x11, 0xff, 0x0d, 0xfd, 0xf2, 0x54, 0x9f, 0x2f, 0x07, 0x69, 0xa3, 0x9f, 0x5b, 0xc4, 0x31, 0x37, 0x15, 0xb1, 0x97, 0x8c, 0x22,
0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x41, 0x5d, 0x93, 0xf2, 0x74, 0x15, 0x00, 0x00, 0xa6, 0x54, 0xd2, 0x1c, 0x9d, 0xb9, 0xf5, 0x6b, 0x16, 0xf9, 0x16, 0xf2, 0xfa, 0xae, 0x21, 0x3f,
0x5d, 0x4c, 0x88, 0xec, 0x2d, 0x7f, 0x5c, 0xb3, 0x3e, 0xb7, 0xc8, 0x31, 0xe4, 0xd4, 0x90, 0x45,
0x52, 0x26, 0x86, 0xc4, 0x84, 0x56, 0xb5, 0x97, 0x41, 0x4c, 0x16, 0xbf, 0x07, 0x98, 0x8e, 0x7a,
0x24, 0xa5, 0x81, 0xcd, 0xcd, 0x8c, 0xd5, 0xda, 0xcd, 0x40, 0xb3, 0xc1, 0xb1, 0x9a, 0x73, 0xce,
0x39, 0x49, 0x9d, 0x70, 0xe2, 0x72, 0xaf, 0xda, 0xcb, 0x20, 0xc6, 0xdc, 0x05, 0x54, 0x66, 0xfe,
0xb3, 0x25, 0x3f, 0x4b, 0x0f, 0xf2, 0xfa, 0x5f, 0xc0, 0xd5, 0x17, 0xb7, 0xc2, 0x9a, 0x9d, 0x64,
0x72, 0x56, 0x36, 0x8f, 0x49, 0xfd, 0xa6, 0xb8, 0x67, 0xff, 0x7f, 0xad, 0x6e, 0xdd, 0x1a, 0xaf,
0x77, 0xdd, 0xcd, 0xfd, 0x36, 0x33, 0x6c, 0xb7, 0xf3, 0xf8, 0x57, 0xf6, 0xcb, 0xff, 0x06, 0x00,
0x00, 0xff, 0xff, 0x62, 0xe5, 0x06, 0x57, 0x31, 0x17, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

@ -69,7 +69,12 @@ message BuildOptions {
string Target = 21; string Target = 21;
UlimitOpt Ulimits = 22; UlimitOpt Ulimits = 22;
CommonOptions Opts = 24; string Builder = 23;
string MetadataFile = 24;
bool NoCache = 25;
bool Pull = 26;
bool ExportPush = 27;
bool ExportLoad = 28;
} }
message ExportEntry { message ExportEntry {
@ -110,16 +115,6 @@ message Ulimit {
int64 Soft = 3; int64 Soft = 3;
} }
message CommonOptions {
string Builder = 1;
string MetadataFile = 2;
bool NoCache = 3;
// string Progress: no progress view on server side
bool Pull = 4;
bool ExportPush = 5;
bool ExportLoad = 6;
}
message BuildResponse { message BuildResponse {
map<string, string> ExporterResponse = 1; map<string, string> ExporterResponse = 1;
} }
@ -214,12 +209,31 @@ message StatusRequest {
} }
message StatusResponse { message StatusResponse {
oneof Status {
SolveStatusMessage SolveStatus = 1;
NodeInfoMessage NodeInfo = 2;
ResultInfoMessage ResultInfo = 3;
}
}
message SolveStatusMessage {
repeated moby.buildkit.v1.Vertex vertexes = 1; repeated moby.buildkit.v1.Vertex vertexes = 1;
repeated moby.buildkit.v1.VertexStatus statuses = 2; repeated moby.buildkit.v1.VertexStatus statuses = 2;
repeated moby.buildkit.v1.VertexLog logs = 3; repeated moby.buildkit.v1.VertexLog logs = 3;
repeated moby.buildkit.v1.VertexWarning warnings = 4; repeated moby.buildkit.v1.VertexWarning warnings = 4;
} }
message NodeInfoMessage {
string Name = 1;
string Driver = 2;
}
message ResultInfoMessage {
map<string, string> Result = 1;
string Name = 2;
string Format = 3;
}
message InfoRequest {} message InfoRequest {}
message InfoResponse { message InfoResponse {

@ -6,11 +6,9 @@ import (
"sync" "sync"
"time" "time"
"github.com/containerd/console"
"github.com/containerd/containerd/defaults" "github.com/containerd/containerd/defaults"
"github.com/containerd/containerd/pkg/dialer" "github.com/containerd/containerd/pkg/dialer"
"github.com/docker/buildx/controller/pb" "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/util/progress"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -104,38 +102,13 @@ func (c *Client) Invoke(ctx context.Context, ref string, pid string, invokeConfi
}) })
} }
func (c *Client) Build(ctx context.Context, options pb.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (string, *client.SolveResponse, error) { func (c *Client) Build(ctx context.Context, options pb.BuildOptions, in io.ReadCloser, statusChan chan *pb.StatusResponse) (string, *client.SolveResponse, error) {
ref := identity.NewID() ref := identity.NewID()
pw, err := progress.NewPrinter(context.TODO(), w, out, progressMode) resp, err := c.build(ctx, ref, options, in, statusChan)
if err != nil { return ref, resp, err
return "", nil, err
}
statusChan := make(chan *client.SolveStatus)
statusDone := make(chan struct{})
eg, egCtx := errgroup.WithContext(ctx)
var resp *client.SolveResponse
eg.Go(func() error {
defer close(statusChan)
var err error
resp, err = c.build(egCtx, ref, options, in, statusChan)
return err
})
eg.Go(func() error {
defer close(statusDone)
for s := range statusChan {
st := s
pw.Write(st)
}
return nil
})
eg.Go(func() error {
<-statusDone
return pw.Wait()
})
return ref, resp, eg.Wait()
} }
func (c *Client) build(ctx context.Context, ref string, options pb.BuildOptions, in io.ReadCloser, statusChan chan *client.SolveStatus) (*client.SolveResponse, error) { func (c *Client) build(ctx context.Context, ref string, options pb.BuildOptions, in io.ReadCloser, statusChan chan *pb.StatusResponse) (*client.SolveResponse, error) {
eg, egCtx := errgroup.WithContext(ctx) eg, egCtx := errgroup.WithContext(ctx)
done := make(chan struct{}) done := make(chan struct{})
@ -170,51 +143,7 @@ func (c *Client) build(ctx context.Context, ref string, options pb.BuildOptions,
} }
return errors.Wrap(err, "failed to receive status") return errors.Wrap(err, "failed to receive status")
} }
s := client.SolveStatus{} statusChan <- resp
for _, v := range resp.Vertexes {
s.Vertexes = append(s.Vertexes, &client.Vertex{
Digest: v.Digest,
Inputs: v.Inputs,
Name: v.Name,
Started: v.Started,
Completed: v.Completed,
Error: v.Error,
Cached: v.Cached,
ProgressGroup: v.ProgressGroup,
})
}
for _, v := range resp.Statuses {
s.Statuses = append(s.Statuses, &client.VertexStatus{
ID: v.ID,
Vertex: v.Vertex,
Name: v.Name,
Total: v.Total,
Current: v.Current,
Timestamp: v.Timestamp,
Started: v.Started,
Completed: v.Completed,
})
}
for _, v := range resp.Logs {
s.Logs = append(s.Logs, &client.VertexLog{
Vertex: v.Vertex,
Stream: int(v.Stream),
Data: v.Msg,
Timestamp: v.Timestamp,
})
}
for _, v := range resp.Warnings {
s.Warnings = append(s.Warnings, &client.VertexWarning{
Vertex: v.Vertex,
Level: int(v.Level),
Short: v.Short,
Detail: v.Detail,
URL: v.Url,
SourceInfo: v.Info,
Range: v.Ranges,
})
}
statusChan <- &s
} }
}) })
if in != nil { if in != nil {

@ -141,8 +141,8 @@ func serveCmd(dockerCli command.Cli) *cobra.Command {
}() }()
// prepare server // prepare server
b := NewServer(func(ctx context.Context, options *controllerapi.BuildOptions, stdin io.Reader, statusChan chan *client.SolveStatus) (*client.SolveResponse, *build.ResultContext, error) { b := NewServer(func(ctx context.Context, options *controllerapi.BuildOptions, stdin io.Reader, statusChan chan *controllerapi.StatusResponse) (*client.SolveResponse, *build.ResultContext, error) {
return cbuild.RunBuild(ctx, dockerCli, *options, stdin, "quiet", statusChan) return cbuild.RunBuild(ctx, dockerCli, *options, stdin, control.ForwardProgress(statusChan))
}) })
defer b.Close() defer b.Close()

@ -12,13 +12,12 @@ import (
"github.com/docker/buildx/controller/processes" "github.com/docker/buildx/controller/processes"
"github.com/docker/buildx/util/ioset" "github.com/docker/buildx/util/ioset"
"github.com/docker/buildx/version" "github.com/docker/buildx/version"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
type BuildFunc func(ctx context.Context, options *pb.BuildOptions, stdin io.Reader, statusChan chan *client.SolveStatus) (resp *client.SolveResponse, res *build.ResultContext, err error) type BuildFunc func(ctx context.Context, options *pb.BuildOptions, stdin io.Reader, statusChan chan *pb.StatusResponse) (resp *client.SolveResponse, res *build.ResultContext, err error)
func NewServer(buildFunc BuildFunc) *Server { func NewServer(buildFunc BuildFunc) *Server {
return &Server{ return &Server{
@ -34,7 +33,7 @@ type Server struct {
type session struct { type session struct {
buildOnGoing atomic.Bool buildOnGoing atomic.Bool
statusChan chan *client.SolveStatus statusChan chan *pb.StatusResponse
cancelBuild func() cancelBuild func()
inputPipe *io.PipeWriter inputPipe *io.PipeWriter
@ -156,7 +155,7 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
s.buildOnGoing.Store(true) s.buildOnGoing.Store(true)
} }
s.processes = processes.NewManager() s.processes = processes.NewManager()
statusChan := make(chan *client.SolveStatus) statusChan := make(chan *pb.StatusResponse)
s.statusChan = statusChan s.statusChan = statusChan
inR, inW := io.Pipe() inR, inW := io.Pipe()
defer inR.Close() defer inR.Close()
@ -204,7 +203,7 @@ func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer
} }
// Wait and get status channel prepared by Build() // Wait and get status channel prepared by Build()
var statusChan <-chan *client.SolveStatus var statusChan <-chan *pb.StatusResponse
for { for {
// TODO: timeout? // TODO: timeout?
m.sessionMu.Lock() m.sessionMu.Lock()
@ -223,7 +222,7 @@ func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer
if ss == nil { if ss == nil {
break break
} }
cs := toControlStatus(ss) cs := ss
if err := stream.Send(cs); err != nil { if err := stream.Send(cs); err != nil {
return err return err
} }
@ -404,51 +403,3 @@ func (m *Server) Invoke(srv pb.Controller_InvokeServer) error {
return eg.Wait() return eg.Wait()
} }
func toControlStatus(s *client.SolveStatus) *pb.StatusResponse {
resp := pb.StatusResponse{}
for _, v := range s.Vertexes {
resp.Vertexes = append(resp.Vertexes, &controlapi.Vertex{
Digest: v.Digest,
Inputs: v.Inputs,
Name: v.Name,
Started: v.Started,
Completed: v.Completed,
Error: v.Error,
Cached: v.Cached,
ProgressGroup: v.ProgressGroup,
})
}
for _, v := range s.Statuses {
resp.Statuses = append(resp.Statuses, &controlapi.VertexStatus{
ID: v.ID,
Vertex: v.Vertex,
Name: v.Name,
Total: v.Total,
Current: v.Current,
Timestamp: v.Timestamp,
Started: v.Started,
Completed: v.Completed,
})
}
for _, v := range s.Logs {
resp.Logs = append(resp.Logs, &controlapi.VertexLog{
Vertex: v.Vertex,
Stream: int64(v.Stream),
Msg: v.Data,
Timestamp: v.Timestamp,
})
}
for _, v := range s.Warnings {
resp.Warnings = append(resp.Warnings, &controlapi.VertexWarning{
Vertex: v.Vertex,
Level: int64(v.Level),
Short: v.Short,
Detail: v.Detail,
Url: v.URL,
Info: v.SourceInfo,
Ranges: v.Range,
})
}
return &resp
}

@ -125,7 +125,7 @@ func RunMonitor(ctx context.Context, curRef string, options controllerapi.BuildO
fmt.Println("disconnect error", err) fmt.Println("disconnect error", err)
} }
} }
ref, _, err := c.Build(ctx, options, nil, stdout, stderr, progressMode) // TODO: support stdin, hold build ref ref, _, err := control.Build(ctx, c, options, nil, stdout, stderr, progressMode) // TODO: support stdin if needed
if err != nil { if err != nil {
fmt.Printf("failed to reload: %v\n", err) fmt.Printf("failed to reload: %v\n", err)
} else { } else {

@ -69,23 +69,18 @@ func NewChannel(w Writer) (chan *client.SolveStatus, chan struct{}) {
return ch, done return ch, done
} }
type tee struct { func Tee(w *Printer, ch chan *client.SolveStatus) *Printer {
Writer wStatus := make(chan *client.SolveStatus)
ch chan *client.SolveStatus orgStatus := w.status
} w.status = wStatus
go func() {
func (t *tee) Write(v *client.SolveStatus) { defer close(orgStatus)
v2 := *v for st := range wStatus {
t.ch <- &v2 st := st
t.Writer.Write(v) st2 := *st
} ch <- &st2
orgStatus <- st
func Tee(w Writer, ch chan *client.SolveStatus) Writer { }
if ch == nil { }()
return w return w
}
return &tee{
Writer: w,
ch: ch,
}
} }

Loading…
Cancel
Save