Merge pull request #1614 from jedevc/typed-controller-api

controller: strongly type the controller api
pull/1037/head
Justin Chadwell 2 years ago committed by GitHub
commit f3a4cd5176
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,6 +14,7 @@ import (
"github.com/docker/buildx/bake/hclparser" "github.com/docker/buildx/bake/hclparser"
"github.com/docker/buildx/build" "github.com/docker/buildx/build"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/util/buildflags" "github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/platformutil" "github.com/docker/buildx/util/platformutil"
"github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config"
@ -978,17 +979,24 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.Session = append(bo.Session, secrets) secretAttachment, err := controllerapi.CreateSecrets(secrets)
if err != nil {
return nil, err
}
bo.Session = append(bo.Session, secretAttachment)
sshSpecs := t.SSH sshSpecs, err := buildflags.ParseSSHSpecs(t.SSH)
if err != nil {
return nil, err
}
if len(sshSpecs) == 0 && buildflags.IsGitSSH(contextPath) { if len(sshSpecs) == 0 && buildflags.IsGitSSH(contextPath) {
sshSpecs = []string{"default"} sshSpecs = append(sshSpecs, &controllerapi.SSH{ID: "default"})
} }
ssh, err := buildflags.ParseSSHSpecs(sshSpecs) sshAttachment, err := controllerapi.CreateSSH(sshSpecs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.Session = append(bo.Session, ssh) bo.Session = append(bo.Session, sshAttachment)
if t.Target != nil { if t.Target != nil {
bo.Target = *t.Target bo.Target = *t.Target
@ -998,25 +1006,28 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.CacheFrom = cacheImports bo.CacheFrom = controllerapi.CreateCaches(cacheImports)
cacheExports, err := buildflags.ParseCacheEntry(t.CacheTo) cacheExports, err := buildflags.ParseCacheEntry(t.CacheTo)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.CacheTo = cacheExports bo.CacheTo = controllerapi.CreateCaches(cacheExports)
outputs, err := buildflags.ParseOutputs(t.Outputs) outputs, err := buildflags.ParseExports(t.Outputs)
if err != nil {
return nil, err
}
bo.Exports, err = controllerapi.CreateExports(outputs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.Exports = outputs
attests, err := buildflags.ParseAttests(t.Attest) attests, err := buildflags.ParseAttests(t.Attest)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bo.Attests = attests bo.Attests = controllerapi.CreateAttestations(attests)
return bo, nil return bo, nil
} }

@ -77,19 +77,19 @@ type Options struct {
CgroupParent string CgroupParent string
Exports []client.ExportEntry Exports []client.ExportEntry
ExtraHosts []string ExtraHosts []string
ImageIDFile string
Labels map[string]string Labels map[string]string
NetworkMode string NetworkMode string
NoCache bool NoCache bool
NoCacheFilter []string NoCacheFilter []string
Platforms []specs.Platform Platforms []specs.Platform
Pull bool Pull bool
Session []session.Attachable
ShmSize opts.MemBytes ShmSize opts.MemBytes
Tags []string Tags []string
Target string Target string
Ulimits *opts.UlimitOpt Ulimits *opts.UlimitOpt
Session []session.Attachable
// Linked marks this target as exclusively linked (not requested by the user). // Linked marks this target as exclusively linked (not requested by the user).
Linked bool Linked bool
PrintFunc *PrintFunc PrintFunc *PrintFunc
@ -375,13 +375,6 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
} }
}() }()
if opt.ImageIDFile != "" {
// Avoid leaving a stale file if we eventually fail
if err := os.Remove(opt.ImageIDFile); err != nil && !os.IsNotExist(err) {
return nil, nil, errors.Wrap(err, "removing image ID file")
}
}
// inline cache from build arg // inline cache from build arg
if v, ok := opt.BuildArgs["BUILDKIT_INLINE_CACHE"]; ok { if v, ok := opt.BuildArgs["BUILDKIT_INLINE_CACHE"]; ok {
if v, _ := strconv.ParseBool(v); v { if v, _ := strconv.ParseBool(v); v {
@ -462,11 +455,11 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
return nil, nil, errors.Errorf("attestations are not supported by the current buildkitd") return nil, nil, errors.Errorf("attestations are not supported by the current buildkitd")
} }
for k, v := range attests { for k, v := range attests {
so.FrontendAttrs[k] = v so.FrontendAttrs["attest:"+k] = v
} }
} }
if _, ok := opt.Attests["attest:provenance"]; !ok && supportsAttestations { if _, ok := opt.Attests["provenance"]; !ok && supportsAttestations {
const noAttestEnv = "BUILDX_NO_DEFAULT_ATTESTATIONS" const noAttestEnv = "BUILDX_NO_DEFAULT_ATTESTATIONS"
var noProv bool var noProv bool
if v, ok := os.LookupEnv(noAttestEnv); ok { if v, ok := os.LookupEnv(noAttestEnv); ok {
@ -530,9 +523,6 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
// set up exporters // set up exporters
for i, e := range opt.Exports { for i, e := range opt.Exports {
if (e.Type == "local" || e.Type == "tar") && opt.ImageIDFile != "" {
return nil, nil, errors.Errorf("local and tar exporters are incompatible with image ID file")
}
if e.Type == "oci" && !nodeDriver.Features()[driver.OCIExporter] { if e.Type == "oci" && !nodeDriver.Features()[driver.OCIExporter] {
return nil, nil, notSupported(nodeDriver, driver.OCIExporter) return nil, nil, notSupported(nodeDriver, driver.OCIExporter)
} }
@ -1154,13 +1144,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
resp[k] = res[0] resp[k] = res[0]
respMu.Unlock() respMu.Unlock()
if len(res) == 1 { if len(res) == 1 {
dgst := res[0].ExporterResponse[exptypes.ExporterImageDigestKey]
if v, ok := res[0].ExporterResponse[exptypes.ExporterImageConfigDigestKey]; ok {
dgst = v
}
if opt.ImageIDFile != "" {
return os.WriteFile(opt.ImageIDFile, []byte(dgst), 0644)
}
return nil return nil
} }
@ -1238,11 +1221,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
if err != nil { if err != nil {
return err return err
} }
if opt.ImageIDFile != "" {
if err := os.WriteFile(opt.ImageIDFile, []byte(desc.Digest), 0644); err != nil {
return err
}
}
itpush := imagetools.New(imageopt) itpush := imagetools.New(imageopt)
@ -1259,7 +1237,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
respMu.Lock() respMu.Lock()
resp[k] = &client.SolveResponse{ resp[k] = &client.SolveResponse{
ExporterResponse: map[string]string{ ExporterResponse: map[string]string{
"containerimage.digest": desc.Digest.String(), exptypes.ExporterImageDigestKey: desc.Digest.String(),
}, },
} }
respMu.Unlock() respMu.Unlock()

@ -24,9 +24,11 @@ import (
) )
type bakeOptions struct { type bakeOptions struct {
files []string files []string
overrides []string overrides []string
printOnly bool printOnly bool
sbom string
provenance string
controllerapi.CommonOptions controllerapi.CommonOptions
} }
@ -76,11 +78,11 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com
if cFlags.pull != nil { if cFlags.pull != nil {
overrides = append(overrides, fmt.Sprintf("*.pull=%t", *cFlags.pull)) overrides = append(overrides, fmt.Sprintf("*.pull=%t", *cFlags.pull))
} }
if in.SBOM != "" { if in.sbom != "" {
overrides = append(overrides, fmt.Sprintf("*.attest=%s", buildflags.CanonicalizeAttest("sbom", in.SBOM))) overrides = append(overrides, fmt.Sprintf("*.attest=%s", buildflags.CanonicalizeAttest("sbom", in.sbom)))
} }
if in.Provenance != "" { if in.provenance != "" {
overrides = append(overrides, fmt.Sprintf("*.attest=%s", buildflags.CanonicalizeAttest("provenance", in.Provenance))) overrides = append(overrides, fmt.Sprintf("*.attest=%s", buildflags.CanonicalizeAttest("provenance", in.provenance)))
} }
contextPathHash, _ := os.Getwd() contextPathHash, _ := os.Getwd()
@ -220,8 +222,8 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
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")`)
commonBuildFlags(&cFlags, flags) commonBuildFlags(&cFlags, flags)

@ -5,6 +5,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/csv" "encoding/csv"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"os" "os"
"runtime" "runtime"
@ -19,14 +20,17 @@ import (
"github.com/docker/buildx/monitor" "github.com/docker/buildx/monitor"
"github.com/docker/buildx/store" "github.com/docker/buildx/store"
"github.com/docker/buildx/store/storeutil" "github.com/docker/buildx/store/storeutil"
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/ioset" "github.com/docker/buildx/util/ioset"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing" "github.com/docker/buildx/util/tracing"
"github.com/docker/cli-docs-tool/annotation" "github.com/docker/cli-docs-tool/annotation"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
dockeropts "github.com/docker/cli/opts" dockeropts "github.com/docker/cli/opts"
"github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/ioutils"
"github.com/docker/go-units" "github.com/moby/buildkit/client"
"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/pkg/errors" "github.com/pkg/errors"
@ -37,12 +41,127 @@ import (
) )
type buildOptions struct { type buildOptions struct {
allow []string
buildArgs []string
cacheFrom []string
cacheTo []string
cgroupParent string
contextPath string
contexts []string
dockerfileName string
extraHosts []string
imageIDFile string
labels []string
networkMode string
noCacheFilter []string
outputs []string
platforms []string
printFunc string
secrets []string
shmSize dockeropts.MemBytes
ssh []string
tags []string
target string
ulimits *dockeropts.UlimitOpt
invoke string
attests []string
sbom string
provenance string
progress string progress string
invoke string quiet bool
controllerapi.BuildOptions
controllerapi.CommonOptions
control.ControlOptions control.ControlOptions
} }
func (o *buildOptions) toControllerOptions() (controllerapi.BuildOptions, error) {
var err error
opts := controllerapi.BuildOptions{
Allow: o.allow,
BuildArgs: listToMap(o.buildArgs, true),
CgroupParent: o.cgroupParent,
ContextPath: o.contextPath,
DockerfileName: o.dockerfileName,
ExtraHosts: o.extraHosts,
Labels: listToMap(o.labels, false),
NetworkMode: o.networkMode,
NoCacheFilter: o.noCacheFilter,
Platforms: o.platforms,
PrintFunc: o.printFunc,
ShmSize: int64(o.shmSize),
Tags: o.tags,
Target: o.target,
Ulimits: dockerUlimitToControllerUlimit(o.ulimits),
Opts: &o.CommonOptions,
}
inAttests := append([]string{}, o.attests...)
if o.provenance != "" {
inAttests = append(inAttests, buildflags.CanonicalizeAttest("provenance", o.provenance))
}
if o.sbom != "" {
inAttests = append(inAttests, buildflags.CanonicalizeAttest("sbom", o.sbom))
}
opts.Attests, err = buildflags.ParseAttests(inAttests)
if err != nil {
return controllerapi.BuildOptions{}, err
}
opts.NamedContexts, err = buildflags.ParseContextNames(o.contexts)
if err != nil {
return controllerapi.BuildOptions{}, err
}
opts.Exports, err = buildflags.ParseExports(o.outputs)
if err != nil {
return controllerapi.BuildOptions{}, err
}
for _, e := range opts.Exports {
if (e.Type == client.ExporterLocal || e.Type == client.ExporterTar) && o.imageIDFile != "" {
return controllerapi.BuildOptions{}, errors.Errorf("local and tar exporters are incompatible with image ID file")
}
}
opts.CacheFrom, err = buildflags.ParseCacheEntry(o.cacheFrom)
if err != nil {
return controllerapi.BuildOptions{}, err
}
opts.CacheTo, err = buildflags.ParseCacheEntry(o.cacheTo)
if err != nil {
return controllerapi.BuildOptions{}, err
}
opts.Secrets, err = buildflags.ParseSecretSpecs(o.secrets)
if err != nil {
return controllerapi.BuildOptions{}, err
}
opts.SSH, err = buildflags.ParseSSHSpecs(o.ssh)
if err != nil {
return controllerapi.BuildOptions{}, err
}
return opts, nil
}
func (o *buildOptions) toProgress() (string, error) {
switch o.progress {
case progress.PrinterModeAuto, progress.PrinterModeTty, progress.PrinterModePlain, progress.PrinterModeQuiet:
default:
return "", errors.Errorf("progress=%s is not a valid progress option", o.progress)
}
if o.quiet {
if o.progress != progress.PrinterModeAuto && o.progress != progress.PrinterModeQuiet {
return "", errors.Errorf("progress=%s and quiet cannot be used together", o.progress)
}
return progress.PrinterModeQuiet, nil
}
return o.progress, nil
}
func runBuild(dockerCli command.Cli, in buildOptions) error { func runBuild(dockerCli command.Cli, in buildOptions) error {
ctx := appcontext.Context() ctx := appcontext.Context()
@ -54,12 +173,40 @@ func runBuild(dockerCli command.Cli, in buildOptions) error {
end(err) end(err)
}() }()
_, err = cbuild.RunBuild(ctx, dockerCli, in.BuildOptions, os.Stdin, in.progress, nil) opts, err := in.toControllerOptions()
return err if err != nil {
return err
}
progress, err := in.toProgress()
if err != nil {
return err
}
// Avoid leaving a stale file if we eventually fail
if in.imageIDFile != "" {
if err := os.Remove(in.imageIDFile); err != nil && !os.IsNotExist(err) {
return errors.Wrap(err, "removing image ID file")
}
}
resp, _, err := cbuild.RunBuild(ctx, dockerCli, opts, os.Stdin, progress, nil)
if err != nil {
return err
}
if in.quiet {
fmt.Println(resp.ExporterResponse[exptypes.ExporterImageDigestKey])
}
if in.imageIDFile != "" {
dgst := resp.ExporterResponse[exptypes.ExporterImageDigestKey]
if v, ok := resp.ExporterResponse[exptypes.ExporterImageConfigDigestKey]; ok {
dgst = v
}
return os.WriteFile(in.imageIDFile, []byte(dgst), 0644)
}
return nil
} }
func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
options := newBuildOptions() options := buildOptions{}
cFlags := &commonFlags{} cFlags := &commonFlags{}
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -68,16 +215,16 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
Short: "Start a build", Short: "Start a build",
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.Opts.Builder = rootOpts.builder options.Builder = rootOpts.builder
options.Opts.MetadataFile = cFlags.metadataFile options.MetadataFile = cFlags.metadataFile
options.Opts.NoCache = false options.NoCache = false
if cFlags.noCache != nil { if cFlags.noCache != nil {
options.Opts.NoCache = *cFlags.noCache options.NoCache = *cFlags.noCache
} }
options.Opts.Pull = false options.Pull = false
if cFlags.pull != nil { if cFlags.pull != nil {
options.Opts.Pull = *cFlags.pull options.Pull = *cFlags.pull
} }
options.progress = cFlags.progress options.progress = cFlags.progress
cmd.Flags().VisitAll(checkWarnedFlags) cmd.Flags().VisitAll(checkWarnedFlags)
@ -95,64 +242,65 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringSliceVar(&options.ExtraHosts, "add-host", []string{}, `Add a custom host-to-IP mapping (format: "host:ip")`) flags.StringSliceVar(&options.extraHosts, "add-host", []string{}, `Add a custom host-to-IP mapping (format: "host:ip")`)
flags.SetAnnotation("add-host", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#add-host"}) flags.SetAnnotation("add-host", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#add-host"})
flags.StringSliceVar(&options.Allow, "allow", []string{}, `Allow extra privileged entitlement (e.g., "network.host", "security.insecure")`) flags.StringSliceVar(&options.allow, "allow", []string{}, `Allow extra privileged entitlement (e.g., "network.host", "security.insecure")`)
flags.StringArrayVar(&options.BuildArgs, "build-arg", []string{}, "Set build-time variables") flags.StringArrayVar(&options.buildArgs, "build-arg", []string{}, "Set build-time variables")
flags.StringArrayVar(&options.CacheFrom, "cache-from", []string{}, `External cache sources (e.g., "user/app:cache", "type=local,src=path/to/dir")`) flags.StringArrayVar(&options.cacheFrom, "cache-from", []string{}, `External cache sources (e.g., "user/app:cache", "type=local,src=path/to/dir")`)
flags.StringArrayVar(&options.CacheTo, "cache-to", []string{}, `Cache export destinations (e.g., "user/app:cache", "type=local,dest=path/to/dir")`) flags.StringArrayVar(&options.cacheTo, "cache-to", []string{}, `Cache export destinations (e.g., "user/app:cache", "type=local,dest=path/to/dir")`)
flags.StringVar(&options.CgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container") flags.StringVar(&options.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
flags.SetAnnotation("cgroup-parent", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#cgroup-parent"}) flags.SetAnnotation("cgroup-parent", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#cgroup-parent"})
flags.StringArrayVar(&options.Contexts, "build-context", []string{}, "Additional build contexts (e.g., name=path)") flags.StringArrayVar(&options.contexts, "build-context", []string{}, "Additional build contexts (e.g., name=path)")
flags.StringVarP(&options.DockerfileName, "file", "f", "", `Name of the Dockerfile (default: "PATH/Dockerfile")`) flags.StringVarP(&options.dockerfileName, "file", "f", "", `Name of the Dockerfile (default: "PATH/Dockerfile")`)
flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#file"}) flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#file"})
flags.StringVar(&options.ImageIDFile, "iidfile", "", "Write the image ID to the file") flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file")
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.Opts.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`)
flags.StringArrayVar(&options.NoCacheFilter, "no-cache-filter", []string{}, "Do not cache specified stages") flags.StringArrayVar(&options.noCacheFilter, "no-cache-filter", []string{}, "Do not cache specified stages")
flags.StringArrayVarP(&options.Outputs, "output", "o", []string{}, `Output destination (format: "type=local,dest=path")`) flags.StringArrayVarP(&options.outputs, "output", "o", []string{}, `Output destination (format: "type=local,dest=path")`)
flags.StringArrayVar(&options.Platforms, "platform", platformsDefault, "Set target platform for build") flags.StringArrayVar(&options.platforms, "platform", platformsDefault, "Set target platform for build")
if isExperimental() { if isExperimental() {
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.Opts.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")
flags.StringArrayVar(&options.Secrets, "secret", []string{}, `Secret to expose to the build (format: "id=mysecret[,src=/local/secret]")`) flags.StringArrayVar(&options.secrets, "secret", []string{}, `Secret to expose to the build (format: "id=mysecret[,src=/local/secret]")`)
flags.Var(newShmSize(&options), "shm-size", `Size of "/dev/shm"`) flags.Var(&options.shmSize, "shm-size", `Size of "/dev/shm"`)
flags.StringArrayVar(&options.SSH, "ssh", []string{}, `SSH agent socket or keys to expose to the build (format: "default|<id>[=<socket>|<key>[,<key>]]")`) flags.StringArrayVar(&options.ssh, "ssh", []string{}, `SSH agent socket or keys to expose to the build (format: "default|<id>[=<socket>|<key>[,<key>]]")`)
flags.StringArrayVarP(&options.Tags, "tag", "t", []string{}, `Name and optionally a tag (format: "name:tag")`) flags.StringArrayVarP(&options.tags, "tag", "t", []string{}, `Name and optionally a tag (format: "name:tag")`)
flags.SetAnnotation("tag", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#tag"}) flags.SetAnnotation("tag", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#tag"})
flags.StringVar(&options.Target, "target", "", "Set the target build stage to build") flags.StringVar(&options.target, "target", "", "Set the target build stage to build")
flags.SetAnnotation("target", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#target"}) flags.SetAnnotation("target", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#target"})
flags.Var(newUlimits(&options), "ulimit", "Ulimit options") options.ulimits = dockeropts.NewUlimitOpt(nil)
flags.Var(options.ulimits, "ulimit", "Ulimit options")
flags.StringArrayVar(&options.Attests, "attest", []string{}, `Attestation parameters (format: "type=sbom,generator=image")`) flags.StringArrayVar(&options.attests, "attest", []string{}, `Attestation parameters (format: "type=sbom,generator=image")`)
flags.StringVar(&options.Opts.SBOM, "sbom", "", `Shorthand for "--attest=type=sbom"`) flags.StringVar(&options.sbom, "sbom", "", `Shorthand for "--attest=type=sbom"`)
flags.StringVar(&options.Opts.Provenance, "provenance", "", `Shortand for "--attest=type=provenance"`) flags.StringVar(&options.provenance, "provenance", "", `Shortand for "--attest=type=provenance"`)
if isExperimental() { if isExperimental() {
flags.StringVar(&options.invoke, "invoke", "", "Invoke a command after the build [experimental]") flags.StringVar(&options.invoke, "invoke", "", "Invoke a command after the build [experimental]")
@ -317,12 +465,7 @@ func updateLastActivity(dockerCli command.Cli, ng *store.NodeGroup) error {
func launchControllerAndRunBuild(dockerCli command.Cli, options buildOptions) error { func launchControllerAndRunBuild(dockerCli command.Cli, options buildOptions) error {
ctx := context.TODO() ctx := context.TODO()
if options.Quiet && options.progress != "auto" && options.progress != "quiet" { if options.invoke != "" && (options.dockerfileName == "-" || options.contextPath == "-") {
return errors.Errorf("progress=%s and quiet cannot be used together", options.progress)
} else if options.Quiet {
options.progress = "quiet"
}
if options.invoke != "" && (options.DockerfileName == "-" || options.ContextPath == "-") {
// stdin must be usable for monitor // stdin must be usable for monitor
return errors.Errorf("Dockerfile or context from stdin is not supported with invoke") return errors.Errorf("Dockerfile or context from stdin is not supported with invoke")
} }
@ -354,8 +497,24 @@ func launchControllerAndRunBuild(dockerCli command.Cli, options buildOptions) er
}) })
f.SetReader(os.Stdin) f.SetReader(os.Stdin)
opts, err := options.toControllerOptions()
if err != nil {
return err
}
progress, err := options.toProgress()
if err != nil {
return err
}
// Avoid leaving a stale file if we eventually fail
if options.imageIDFile != "" {
if err := os.Remove(options.imageIDFile); err != nil && !os.IsNotExist(err) {
return errors.Wrap(err, "removing image ID file")
}
}
// Start build // Start build
ref, err := c.Build(ctx, options.BuildOptions, pr, os.Stdout, os.Stderr, options.progress) ref, resp, err := c.Build(ctx, 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
} }
@ -366,6 +525,17 @@ func launchControllerAndRunBuild(dockerCli command.Cli, options buildOptions) er
logrus.Debug("failed to close stdin pipe reader") logrus.Debug("failed to close stdin pipe reader")
} }
if options.quiet {
fmt.Println(resp.ExporterResponse[exptypes.ExporterImageDigestKey])
}
if options.imageIDFile != "" {
dgst := resp.ExporterResponse[exptypes.ExporterImageDigestKey]
if v, ok := resp.ExporterResponse[exptypes.ExporterImageConfigDigestKey]; ok {
dgst = v
}
return os.WriteFile(options.imageIDFile, []byte(dgst), 0644)
}
// post-build operations // post-build operations
if options.invoke != "" { if options.invoke != "" {
pr2, pw2 := io.Pipe() pr2, pw2 := io.Pipe()
@ -380,7 +550,7 @@ func launchControllerAndRunBuild(dockerCli command.Cli, options buildOptions) er
} }
return errors.Errorf("failed to configure terminal: %v", err) return errors.Errorf("failed to configure terminal: %v", err)
} }
err = monitor.RunMonitor(ctx, ref, options.BuildOptions, invokeConfig, c, options.progress, pr2, os.Stdout, os.Stderr) err = monitor.RunMonitor(ctx, ref, opts, invokeConfig, c, options.progress, pr2, os.Stdout, os.Stderr)
con.Reset() con.Reset()
if err := pw2.Close(); err != nil { if err := pw2.Close(); err != nil {
logrus.Debug("failed to close monitor stdin pipe reader") logrus.Debug("failed to close monitor stdin pipe reader")
@ -445,75 +615,37 @@ func parseInvokeConfig(invoke string) (cfg controllerapi.ContainerConfig, err er
return cfg, nil return cfg, nil
} }
func newBuildOptions() buildOptions { func listToMap(values []string, defaultEnv bool) map[string]string {
return buildOptions{ result := make(map[string]string, len(values))
BuildOptions: controllerapi.BuildOptions{ for _, value := range values {
Opts: &controllerapi.CommonOptions{}, kv := strings.SplitN(value, "=", 2)
}, if len(kv) == 1 {
if defaultEnv {
v, ok := os.LookupEnv(kv[0])
if ok {
result[kv[0]] = v
}
} else {
result[kv[0]] = ""
}
} else {
result[kv[0]] = kv[1]
}
} }
return result
} }
func newUlimits(opt *buildOptions) *ulimits { func dockerUlimitToControllerUlimit(u *dockeropts.UlimitOpt) *controllerapi.UlimitOpt {
ul := make(map[string]*units.Ulimit) if u == nil {
return &ulimits{opt: opt, org: dockeropts.NewUlimitOpt(&ul)} return nil
}
type ulimits struct {
opt *buildOptions
org *dockeropts.UlimitOpt
}
func (u *ulimits) sync() {
du := &controllerapi.UlimitOpt{
Values: make(map[string]*controllerapi.Ulimit),
} }
for _, l := range u.org.GetList() { values := make(map[string]*controllerapi.Ulimit)
du.Values[l.Name] = &controllerapi.Ulimit{ for _, u := range u.GetList() {
Name: l.Name, values[u.Name] = &controllerapi.Ulimit{
Hard: l.Hard, Name: u.Name,
Soft: l.Soft, Hard: u.Hard,
Soft: u.Soft,
} }
} }
u.opt.Ulimits = du return &controllerapi.UlimitOpt{Values: values}
}
func (u *ulimits) String() string {
return u.org.String()
}
func (u *ulimits) Set(v string) error {
err := u.org.Set(v)
u.sync()
return err
}
func (u *ulimits) Type() string {
return u.org.Type()
}
func newShmSize(opt *buildOptions) *shmSize {
return &shmSize{opt: opt}
}
type shmSize struct {
opt *buildOptions
org dockeropts.MemBytes
}
func (s *shmSize) sync() {
s.opt.ShmSize = s.org.Value()
}
func (s *shmSize) String() string {
return s.org.String()
}
func (s *shmSize) Set(v string) error {
err := s.org.Set(v)
s.sync()
return err
}
func (s *shmSize) Type() string {
return s.org.Type()
} }

@ -26,7 +26,6 @@ import (
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config"
dockeropts "github.com/docker/cli/opts" dockeropts "github.com/docker/cli/opts"
"github.com/docker/distribution/reference"
"github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/ioutils"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
@ -42,25 +41,19 @@ import (
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) (res *build.ResultContext, err error) { 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) {
if in.Opts.NoCache && len(in.NoCacheFilter) > 0 { if in.Opts.NoCache && len(in.NoCacheFilter) > 0 {
return 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")
} }
if in.Quiet && progressMode != progress.PrinterModeAuto && progressMode != progress.PrinterModeQuiet { contexts := map[string]build.NamedContext{}
return nil, errors.Errorf("progress=%s and quiet cannot be used together", progressMode) for name, path := range in.NamedContexts {
} else if in.Quiet { contexts[name] = build.NamedContext{Path: path}
progressMode = "quiet"
}
contexts, err := parseContextNames(in.Contexts)
if err != nil {
return nil, err
} }
printFunc, err := parsePrintFunc(in.PrintFunc) printFunc, err := parsePrintFunc(in.PrintFunc)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
opts := build.Options{ opts := build.Options{
@ -70,10 +63,9 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
InStream: inStream, InStream: inStream,
NamedContexts: contexts, NamedContexts: contexts,
}, },
BuildArgs: listToMap(in.BuildArgs, true), BuildArgs: in.BuildArgs,
ExtraHosts: in.ExtraHosts, ExtraHosts: in.ExtraHosts,
ImageIDFile: in.ImageIDFile, Labels: in.Labels,
Labels: listToMap(in.Labels, false),
NetworkMode: in.NetworkMode, NetworkMode: in.NetworkMode,
NoCache: in.Opts.NoCache, NoCache: in.Opts.NoCache,
NoCacheFilter: in.NoCacheFilter, NoCacheFilter: in.NoCacheFilter,
@ -87,36 +79,36 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
platforms, err := platformutil.Parse(in.Platforms) platforms, err := platformutil.Parse(in.Platforms)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
opts.Platforms = platforms opts.Platforms = platforms
dockerConfig := config.LoadDefaultConfigFile(os.Stderr) dockerConfig := config.LoadDefaultConfigFile(os.Stderr)
opts.Session = append(opts.Session, authprovider.NewDockerAuthProvider(dockerConfig)) opts.Session = append(opts.Session, authprovider.NewDockerAuthProvider(dockerConfig))
secrets, err := buildflags.ParseSecretSpecs(in.Secrets) secrets, err := controllerapi.CreateSecrets(in.Secrets)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
opts.Session = append(opts.Session, secrets) opts.Session = append(opts.Session, secrets)
sshSpecs := in.SSH sshSpecs := in.SSH
if len(sshSpecs) == 0 && buildflags.IsGitSSH(in.ContextPath) { if len(sshSpecs) == 0 && buildflags.IsGitSSH(in.ContextPath) {
sshSpecs = []string{"default"} sshSpecs = append(sshSpecs, &controllerapi.SSH{ID: "default"})
} }
ssh, err := buildflags.ParseSSHSpecs(sshSpecs) ssh, err := controllerapi.CreateSSH(sshSpecs)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
opts.Session = append(opts.Session, ssh) opts.Session = append(opts.Session, ssh)
outputs, err := buildflags.ParseOutputs(in.Outputs) outputs, err := controllerapi.CreateExports(in.Exports)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if in.Opts.ExportPush { if in.Opts.ExportPush {
if in.Opts.ExportLoad { if in.Opts.ExportLoad {
return 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 {
outputs = []client.ExportEntry{{ outputs = []client.ExportEntry{{
@ -130,7 +122,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
case "image": case "image":
outputs[0].Attrs["push"] = "true" outputs[0].Attrs["push"] = "true"
default: default:
return nil, errors.Errorf("push and %q output can't be used together", outputs[0].Type) return nil, nil, errors.Errorf("push and %q output can't be used together", outputs[0].Type)
} }
} }
} }
@ -144,39 +136,20 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
switch outputs[0].Type { switch outputs[0].Type {
case "docker": case "docker":
default: default:
return nil, errors.Errorf("load and %q output can't be used together", outputs[0].Type) return nil, nil, errors.Errorf("load and %q output can't be used together", outputs[0].Type)
} }
} }
} }
opts.Exports = outputs opts.Exports = outputs
inAttests := append([]string{}, in.Attests...) opts.CacheFrom = controllerapi.CreateCaches(in.CacheFrom)
if in.Opts.Provenance != "" { opts.CacheTo = controllerapi.CreateCaches(in.CacheTo)
inAttests = append(inAttests, buildflags.CanonicalizeAttest("provenance", in.Opts.Provenance))
}
if in.Opts.SBOM != "" {
inAttests = append(inAttests, buildflags.CanonicalizeAttest("sbom", in.Opts.SBOM))
}
opts.Attests, err = buildflags.ParseAttests(inAttests)
if err != nil {
return nil, err
}
cacheImports, err := buildflags.ParseCacheEntry(in.CacheFrom)
if err != nil {
return nil, err
}
opts.CacheFrom = cacheImports
cacheExports, err := buildflags.ParseCacheEntry(in.CacheTo) opts.Attests = controllerapi.CreateAttestations(in.Attests)
if err != nil {
return nil, err
}
opts.CacheTo = cacheExports
allow, err := buildflags.ParseEntitlements(in.Allow) allow, err := buildflags.ParseEntitlements(in.Allow)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
opts.Allow = allow opts.Allow = allow
@ -191,29 +164,25 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
builder.WithContextPathHash(contextPathHash), builder.WithContextPathHash(contextPathHash),
) )
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if err = updateLastActivity(dockerCli, b.NodeGroup); err != nil { if err = updateLastActivity(dockerCli, b.NodeGroup); err != nil {
return nil, errors.Wrapf(err, "failed to update builder last activity time") return nil, nil, errors.Wrapf(err, "failed to update builder last activity time")
} }
nodes, err := b.LoadNodes(ctx, false) nodes, err := b.LoadNodes(ctx, false)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
imageID, 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}, progressMode, in.Opts.MetadataFile, statusChan)
err = wrapBuildError(err, false) err = wrapBuildError(err, false)
if err != nil { if err != nil {
return nil, err return nil, nil, err
}
if in.Quiet {
fmt.Println(imageID)
} }
return 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) (imageID string, res *build.ResultContext, err error) { 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) {
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
@ -222,9 +191,10 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGrou
fmt.Sprintf("%s:%s", ng.Driver, ng.Name), fmt.Sprintf("%s:%s", ng.Driver, ng.Name),
)) ))
if err != nil { if err != nil {
return "", nil, err return nil, nil, err
} }
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), progress.Tee(printer, statusChan), func(driverIndex int, gotRes *build.ResultContext) {
@ -239,12 +209,12 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGrou
err = err1 err = err1
} }
if err != nil { if err != nil {
return "", nil, err return nil, nil, err
} }
if len(metadataFile) > 0 && resp != nil { if len(metadataFile) > 0 && resp != nil {
if err := writeMetadataFile(metadataFile, decodeExporterResponse(resp[defaultTargetName].ExporterResponse)); err != nil { if err := writeMetadataFile(metadataFile, decodeExporterResponse(resp[defaultTargetName].ExporterResponse)); err != nil {
return "", nil, err return nil, nil, err
} }
} }
@ -253,12 +223,12 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, ng *store.NodeGrou
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 := printResult(opts[k].PrintFunc, resp[k].ExporterResponse); err != nil {
return "", nil, err return nil, nil, err
} }
} }
} }
return resp[defaultTargetName].ExporterResponse["containerimage.digest"], res, err return resp[defaultTargetName], res, err
} }
func printWarnings(w io.Writer, warnings []client.VertexWarning, mode string) { func printWarnings(w io.Writer, warnings []client.VertexWarning, mode string) {
@ -301,46 +271,6 @@ func printWarnings(w io.Writer, warnings []client.VertexWarning, mode string) {
} }
} }
func listToMap(values []string, defaultEnv bool) map[string]string {
result := make(map[string]string, len(values))
for _, value := range values {
kv := strings.SplitN(value, "=", 2)
if len(kv) == 1 {
if defaultEnv {
v, ok := os.LookupEnv(kv[0])
if ok {
result[kv[0]] = v
}
} else {
result[kv[0]] = ""
}
} else {
result[kv[0]] = kv[1]
}
}
return result
}
func parseContextNames(values []string) (map[string]build.NamedContext, error) {
if len(values) == 0 {
return nil, nil
}
result := make(map[string]build.NamedContext, len(values))
for _, value := range values {
kv := strings.SplitN(value, "=", 2)
if len(kv) != 2 {
return nil, errors.Errorf("invalid context value: %s, expected key=value", value)
}
named, err := reference.ParseNormalizedNamed(kv[0])
if err != nil {
return nil, errors.Wrapf(err, "invalid context name %s", kv[0])
}
name := strings.TrimSuffix(reference.FamiliarString(named), ":latest")
result[name] = build.NamedContext{Path: kv[1]}
}
return result, nil
}
func parsePrintFunc(str string) (*build.PrintFunc, error) { func parsePrintFunc(str string) (*build.PrintFunc, error) {
if str == "" { if str == "" {
return nil, nil return nil, nil

@ -6,14 +6,15 @@ import (
"github.com/containerd/console" "github.com/containerd/console"
controllerapi "github.com/docker/buildx/controller/pb" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/moby/buildkit/client"
) )
type BuildxController interface { type BuildxController interface {
Invoke(ctx context.Context, ref string, options controllerapi.ContainerConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error 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, w io.Writer, out console.File, progressMode string) (ref string, err error) Invoke(ctx context.Context, ref string, options controllerapi.ContainerConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) (err error)
Kill(ctx context.Context) error Kill(ctx context.Context) error
Close() error Close() error
List(ctx context.Context) (res []string, _ error) List(ctx context.Context) (refs []string, _ error)
Disconnect(ctx context.Context, ref string) error Disconnect(ctx context.Context, ref string) error
} }

@ -10,6 +10,7 @@ import (
"github.com/docker/buildx/controller/control" "github.com/docker/buildx/controller/control"
controllerapi "github.com/docker/buildx/controller/pb" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/moby/buildkit/client"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -26,6 +27,15 @@ type localController struct {
resultCtx *build.ResultContext resultCtx *build.ResultContext
} }
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) {
resp, res, err := cbuild.RunBuild(ctx, b.dockerCli, options, in, progressMode, nil)
if err != nil {
return "", nil, err
}
b.resultCtx = res
return b.ref, resp, nil
}
func (b *localController) Invoke(ctx context.Context, ref string, cfg controllerapi.ContainerConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error { func (b *localController) Invoke(ctx context.Context, ref string, cfg controllerapi.ContainerConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error {
if ref != b.ref { if ref != b.ref {
return errors.Errorf("unknown ref %q", ref) return errors.Errorf("unknown ref %q", ref)
@ -52,15 +62,6 @@ func (b *localController) Invoke(ctx context.Context, ref string, cfg controller
return build.Invoke(ctx, ccfg) return build.Invoke(ctx, ccfg)
} }
func (b *localController) Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (string, error) {
res, err := cbuild.RunBuild(ctx, b.dockerCli, options, in, progressMode, nil)
if err != nil {
return "", err
}
b.resultCtx = res
return b.ref, nil
}
func (b *localController) Kill(context.Context) error { func (b *localController) Kill(context.Context) error {
return nil // nop return nil // nop
} }

@ -0,0 +1,20 @@
package pb
func CreateAttestations(attests []*Attest) map[string]*string {
result := map[string]*string{}
for _, attest := range attests {
// ignore duplicates
if _, ok := result[attest.Type]; ok {
continue
}
if attest.Disabled {
result[attest.Type] = nil
continue
}
attrs := attest.Attrs
result[attest.Type] = &attrs
}
return result
}

@ -0,0 +1,21 @@
package pb
import "github.com/moby/buildkit/client"
func CreateCaches(entries []*CacheOptionsEntry) []client.CacheOptionsEntry {
var outs []client.CacheOptionsEntry
if len(entries) == 0 {
return nil
}
for _, entry := range entries {
out := client.CacheOptionsEntry{
Type: entry.Type,
Attrs: map[string]string{},
}
for k, v := range entry.Attrs {
out.Attrs[k] = v
}
outs = append(outs, out)
}
return outs
}

@ -72,35 +72,32 @@ func (m *BuildRequest) GetOptions() *BuildOptions {
} }
type BuildOptions struct { type BuildOptions struct {
ContextPath string `protobuf:"bytes,1,opt,name=ContextPath,proto3" json:"ContextPath,omitempty"` ContextPath string `protobuf:"bytes,1,opt,name=ContextPath,proto3" json:"ContextPath,omitempty"`
DockerfileName string `protobuf:"bytes,2,opt,name=DockerfileName,proto3" json:"DockerfileName,omitempty"` DockerfileName string `protobuf:"bytes,2,opt,name=DockerfileName,proto3" json:"DockerfileName,omitempty"`
PrintFunc string `protobuf:"bytes,3,opt,name=PrintFunc,proto3" json:"PrintFunc,omitempty"` PrintFunc string `protobuf:"bytes,3,opt,name=PrintFunc,proto3" json:"PrintFunc,omitempty"`
Allow []string `protobuf:"bytes,4,rep,name=Allow,proto3" json:"Allow,omitempty"` NamedContexts map[string]string `protobuf:"bytes,4,rep,name=NamedContexts,proto3" json:"NamedContexts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Attests []string `protobuf:"bytes,5,rep,name=Attests,proto3" json:"Attests,omitempty"` Allow []string `protobuf:"bytes,5,rep,name=Allow,proto3" json:"Allow,omitempty"`
BuildArgs []string `protobuf:"bytes,6,rep,name=BuildArgs,proto3" json:"BuildArgs,omitempty"` Attests []*Attest `protobuf:"bytes,6,rep,name=Attests,proto3" json:"Attests,omitempty"`
CacheFrom []string `protobuf:"bytes,7,rep,name=CacheFrom,proto3" json:"CacheFrom,omitempty"` BuildArgs map[string]string `protobuf:"bytes,7,rep,name=BuildArgs,proto3" json:"BuildArgs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
CacheTo []string `protobuf:"bytes,8,rep,name=CacheTo,proto3" json:"CacheTo,omitempty"` CacheFrom []*CacheOptionsEntry `protobuf:"bytes,8,rep,name=CacheFrom,proto3" json:"CacheFrom,omitempty"`
CgroupParent string `protobuf:"bytes,9,opt,name=CgroupParent,proto3" json:"CgroupParent,omitempty"` CacheTo []*CacheOptionsEntry `protobuf:"bytes,9,rep,name=CacheTo,proto3" json:"CacheTo,omitempty"`
Contexts []string `protobuf:"bytes,10,rep,name=Contexts,proto3" json:"Contexts,omitempty"` CgroupParent string `protobuf:"bytes,10,opt,name=CgroupParent,proto3" json:"CgroupParent,omitempty"`
ExtraHosts []string `protobuf:"bytes,11,rep,name=ExtraHosts,proto3" json:"ExtraHosts,omitempty"` Exports []*ExportEntry `protobuf:"bytes,11,rep,name=Exports,proto3" json:"Exports,omitempty"`
ImageIDFile string `protobuf:"bytes,12,opt,name=ImageIDFile,proto3" json:"ImageIDFile,omitempty"` ExtraHosts []string `protobuf:"bytes,12,rep,name=ExtraHosts,proto3" json:"ExtraHosts,omitempty"`
Labels []string `protobuf:"bytes,13,rep,name=Labels,proto3" json:"Labels,omitempty"` Labels map[string]string `protobuf:"bytes,13,rep,name=Labels,proto3" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
NetworkMode string `protobuf:"bytes,14,opt,name=NetworkMode,proto3" json:"NetworkMode,omitempty"` NetworkMode string `protobuf:"bytes,14,opt,name=NetworkMode,proto3" json:"NetworkMode,omitempty"`
NoCacheFilter []string `protobuf:"bytes,15,rep,name=NoCacheFilter,proto3" json:"NoCacheFilter,omitempty"` NoCacheFilter []string `protobuf:"bytes,15,rep,name=NoCacheFilter,proto3" json:"NoCacheFilter,omitempty"`
Outputs []string `protobuf:"bytes,16,rep,name=Outputs,proto3" json:"Outputs,omitempty"` Platforms []string `protobuf:"bytes,16,rep,name=Platforms,proto3" json:"Platforms,omitempty"`
Platforms []string `protobuf:"bytes,17,rep,name=Platforms,proto3" json:"Platforms,omitempty"` Secrets []*Secret `protobuf:"bytes,17,rep,name=Secrets,proto3" json:"Secrets,omitempty"`
Quiet bool `protobuf:"varint,18,opt,name=Quiet,proto3" json:"Quiet,omitempty"` ShmSize int64 `protobuf:"varint,18,opt,name=ShmSize,proto3" json:"ShmSize,omitempty"`
Secrets []string `protobuf:"bytes,19,rep,name=Secrets,proto3" json:"Secrets,omitempty"` SSH []*SSH `protobuf:"bytes,19,rep,name=SSH,proto3" json:"SSH,omitempty"`
ShmSize int64 `protobuf:"varint,20,opt,name=ShmSize,proto3" json:"ShmSize,omitempty"` Tags []string `protobuf:"bytes,20,rep,name=Tags,proto3" json:"Tags,omitempty"`
SSH []string `protobuf:"bytes,21,rep,name=SSH,proto3" json:"SSH,omitempty"` Target string `protobuf:"bytes,21,opt,name=Target,proto3" json:"Target,omitempty"`
Tags []string `protobuf:"bytes,22,rep,name=Tags,proto3" json:"Tags,omitempty"` Ulimits *UlimitOpt `protobuf:"bytes,22,opt,name=Ulimits,proto3" json:"Ulimits,omitempty"`
Target string `protobuf:"bytes,23,opt,name=Target,proto3" json:"Target,omitempty"` Opts *CommonOptions `protobuf:"bytes,24,opt,name=Opts,proto3" json:"Opts,omitempty"`
Ulimits *UlimitOpt `protobuf:"bytes,24,opt,name=Ulimits,proto3" json:"Ulimits,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
// string Invoke: provided via Invoke API XXX_unrecognized []byte `json:"-"`
Opts *CommonOptions `protobuf:"bytes,25,opt,name=Opts,proto3" json:"Opts,omitempty"` XXX_sizecache int32 `json:"-"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *BuildOptions) Reset() { *m = BuildOptions{} } func (m *BuildOptions) Reset() { *m = BuildOptions{} }
@ -148,6 +145,13 @@ func (m *BuildOptions) GetPrintFunc() string {
return "" return ""
} }
func (m *BuildOptions) GetNamedContexts() map[string]string {
if m != nil {
return m.NamedContexts
}
return nil
}
func (m *BuildOptions) GetAllow() []string { func (m *BuildOptions) GetAllow() []string {
if m != nil { if m != nil {
return m.Allow return m.Allow
@ -155,28 +159,28 @@ func (m *BuildOptions) GetAllow() []string {
return nil return nil
} }
func (m *BuildOptions) GetAttests() []string { func (m *BuildOptions) GetAttests() []*Attest {
if m != nil { if m != nil {
return m.Attests return m.Attests
} }
return nil return nil
} }
func (m *BuildOptions) GetBuildArgs() []string { func (m *BuildOptions) GetBuildArgs() map[string]string {
if m != nil { if m != nil {
return m.BuildArgs return m.BuildArgs
} }
return nil return nil
} }
func (m *BuildOptions) GetCacheFrom() []string { func (m *BuildOptions) GetCacheFrom() []*CacheOptionsEntry {
if m != nil { if m != nil {
return m.CacheFrom return m.CacheFrom
} }
return nil return nil
} }
func (m *BuildOptions) GetCacheTo() []string { func (m *BuildOptions) GetCacheTo() []*CacheOptionsEntry {
if m != nil { if m != nil {
return m.CacheTo return m.CacheTo
} }
@ -190,9 +194,9 @@ func (m *BuildOptions) GetCgroupParent() string {
return "" return ""
} }
func (m *BuildOptions) GetContexts() []string { func (m *BuildOptions) GetExports() []*ExportEntry {
if m != nil { if m != nil {
return m.Contexts return m.Exports
} }
return nil return nil
} }
@ -204,14 +208,7 @@ func (m *BuildOptions) GetExtraHosts() []string {
return nil return nil
} }
func (m *BuildOptions) GetImageIDFile() string { func (m *BuildOptions) GetLabels() map[string]string {
if m != nil {
return m.ImageIDFile
}
return ""
}
func (m *BuildOptions) GetLabels() []string {
if m != nil { if m != nil {
return m.Labels return m.Labels
} }
@ -232,13 +229,6 @@ func (m *BuildOptions) GetNoCacheFilter() []string {
return nil return nil
} }
func (m *BuildOptions) GetOutputs() []string {
if m != nil {
return m.Outputs
}
return nil
}
func (m *BuildOptions) GetPlatforms() []string { func (m *BuildOptions) GetPlatforms() []string {
if m != nil { if m != nil {
return m.Platforms return m.Platforms
@ -246,14 +236,7 @@ func (m *BuildOptions) GetPlatforms() []string {
return nil return nil
} }
func (m *BuildOptions) GetQuiet() bool { func (m *BuildOptions) GetSecrets() []*Secret {
if m != nil {
return m.Quiet
}
return false
}
func (m *BuildOptions) GetSecrets() []string {
if m != nil { if m != nil {
return m.Secrets return m.Secrets
} }
@ -267,7 +250,7 @@ func (m *BuildOptions) GetShmSize() int64 {
return 0 return 0
} }
func (m *BuildOptions) GetSSH() []string { func (m *BuildOptions) GetSSH() []*SSH {
if m != nil { if m != nil {
return m.SSH return m.SSH
} }
@ -302,6 +285,260 @@ func (m *BuildOptions) GetOpts() *CommonOptions {
return nil return nil
} }
type ExportEntry struct {
Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
Attrs map[string]string `protobuf:"bytes,2,rep,name=Attrs,proto3" json:"Attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Destination string `protobuf:"bytes,3,opt,name=Destination,proto3" json:"Destination,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ExportEntry) Reset() { *m = ExportEntry{} }
func (m *ExportEntry) String() string { return proto.CompactTextString(m) }
func (*ExportEntry) ProtoMessage() {}
func (*ExportEntry) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{2}
}
func (m *ExportEntry) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExportEntry.Unmarshal(m, b)
}
func (m *ExportEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ExportEntry.Marshal(b, m, deterministic)
}
func (m *ExportEntry) XXX_Merge(src proto.Message) {
xxx_messageInfo_ExportEntry.Merge(m, src)
}
func (m *ExportEntry) XXX_Size() int {
return xxx_messageInfo_ExportEntry.Size(m)
}
func (m *ExportEntry) XXX_DiscardUnknown() {
xxx_messageInfo_ExportEntry.DiscardUnknown(m)
}
var xxx_messageInfo_ExportEntry proto.InternalMessageInfo
func (m *ExportEntry) GetType() string {
if m != nil {
return m.Type
}
return ""
}
func (m *ExportEntry) GetAttrs() map[string]string {
if m != nil {
return m.Attrs
}
return nil
}
func (m *ExportEntry) GetDestination() string {
if m != nil {
return m.Destination
}
return ""
}
type CacheOptionsEntry struct {
Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
Attrs map[string]string `protobuf:"bytes,2,rep,name=Attrs,proto3" json:"Attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CacheOptionsEntry) Reset() { *m = CacheOptionsEntry{} }
func (m *CacheOptionsEntry) String() string { return proto.CompactTextString(m) }
func (*CacheOptionsEntry) ProtoMessage() {}
func (*CacheOptionsEntry) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{3}
}
func (m *CacheOptionsEntry) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CacheOptionsEntry.Unmarshal(m, b)
}
func (m *CacheOptionsEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CacheOptionsEntry.Marshal(b, m, deterministic)
}
func (m *CacheOptionsEntry) XXX_Merge(src proto.Message) {
xxx_messageInfo_CacheOptionsEntry.Merge(m, src)
}
func (m *CacheOptionsEntry) XXX_Size() int {
return xxx_messageInfo_CacheOptionsEntry.Size(m)
}
func (m *CacheOptionsEntry) XXX_DiscardUnknown() {
xxx_messageInfo_CacheOptionsEntry.DiscardUnknown(m)
}
var xxx_messageInfo_CacheOptionsEntry proto.InternalMessageInfo
func (m *CacheOptionsEntry) GetType() string {
if m != nil {
return m.Type
}
return ""
}
func (m *CacheOptionsEntry) GetAttrs() map[string]string {
if m != nil {
return m.Attrs
}
return nil
}
type Attest struct {
Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
Disabled bool `protobuf:"varint,2,opt,name=Disabled,proto3" json:"Disabled,omitempty"`
Attrs string `protobuf:"bytes,3,opt,name=Attrs,proto3" json:"Attrs,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Attest) Reset() { *m = Attest{} }
func (m *Attest) String() string { return proto.CompactTextString(m) }
func (*Attest) ProtoMessage() {}
func (*Attest) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{4}
}
func (m *Attest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Attest.Unmarshal(m, b)
}
func (m *Attest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Attest.Marshal(b, m, deterministic)
}
func (m *Attest) XXX_Merge(src proto.Message) {
xxx_messageInfo_Attest.Merge(m, src)
}
func (m *Attest) XXX_Size() int {
return xxx_messageInfo_Attest.Size(m)
}
func (m *Attest) XXX_DiscardUnknown() {
xxx_messageInfo_Attest.DiscardUnknown(m)
}
var xxx_messageInfo_Attest proto.InternalMessageInfo
func (m *Attest) GetType() string {
if m != nil {
return m.Type
}
return ""
}
func (m *Attest) GetDisabled() bool {
if m != nil {
return m.Disabled
}
return false
}
func (m *Attest) GetAttrs() string {
if m != nil {
return m.Attrs
}
return ""
}
type SSH struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Paths []string `protobuf:"bytes,2,rep,name=Paths,proto3" json:"Paths,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SSH) Reset() { *m = SSH{} }
func (m *SSH) String() string { return proto.CompactTextString(m) }
func (*SSH) ProtoMessage() {}
func (*SSH) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{5}
}
func (m *SSH) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SSH.Unmarshal(m, b)
}
func (m *SSH) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SSH.Marshal(b, m, deterministic)
}
func (m *SSH) XXX_Merge(src proto.Message) {
xxx_messageInfo_SSH.Merge(m, src)
}
func (m *SSH) XXX_Size() int {
return xxx_messageInfo_SSH.Size(m)
}
func (m *SSH) XXX_DiscardUnknown() {
xxx_messageInfo_SSH.DiscardUnknown(m)
}
var xxx_messageInfo_SSH proto.InternalMessageInfo
func (m *SSH) GetID() string {
if m != nil {
return m.ID
}
return ""
}
func (m *SSH) GetPaths() []string {
if m != nil {
return m.Paths
}
return nil
}
type Secret struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
FilePath string `protobuf:"bytes,2,opt,name=FilePath,proto3" json:"FilePath,omitempty"`
Env string `protobuf:"bytes,3,opt,name=Env,proto3" json:"Env,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Secret) Reset() { *m = Secret{} }
func (m *Secret) String() string { return proto.CompactTextString(m) }
func (*Secret) ProtoMessage() {}
func (*Secret) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{6}
}
func (m *Secret) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Secret.Unmarshal(m, b)
}
func (m *Secret) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Secret.Marshal(b, m, deterministic)
}
func (m *Secret) XXX_Merge(src proto.Message) {
xxx_messageInfo_Secret.Merge(m, src)
}
func (m *Secret) XXX_Size() int {
return xxx_messageInfo_Secret.Size(m)
}
func (m *Secret) XXX_DiscardUnknown() {
xxx_messageInfo_Secret.DiscardUnknown(m)
}
var xxx_messageInfo_Secret proto.InternalMessageInfo
func (m *Secret) GetID() string {
if m != nil {
return m.ID
}
return ""
}
func (m *Secret) GetFilePath() string {
if m != nil {
return m.FilePath
}
return ""
}
func (m *Secret) GetEnv() string {
if m != nil {
return m.Env
}
return ""
}
type UlimitOpt struct { type UlimitOpt struct {
Values map[string]*Ulimit `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Values map[string]*Ulimit `protobuf:"bytes,1,rep,name=values,proto3" json:"values,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:"-"`
@ -313,7 +550,7 @@ func (m *UlimitOpt) Reset() { *m = UlimitOpt{} }
func (m *UlimitOpt) String() string { return proto.CompactTextString(m) } func (m *UlimitOpt) String() string { return proto.CompactTextString(m) }
func (*UlimitOpt) ProtoMessage() {} func (*UlimitOpt) ProtoMessage() {}
func (*UlimitOpt) Descriptor() ([]byte, []int) { func (*UlimitOpt) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{2} return fileDescriptor_ed7f10298fa1d90f, []int{7}
} }
func (m *UlimitOpt) XXX_Unmarshal(b []byte) error { func (m *UlimitOpt) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UlimitOpt.Unmarshal(m, b) return xxx_messageInfo_UlimitOpt.Unmarshal(m, b)
@ -353,7 +590,7 @@ func (m *Ulimit) Reset() { *m = Ulimit{} }
func (m *Ulimit) String() string { return proto.CompactTextString(m) } func (m *Ulimit) String() string { return proto.CompactTextString(m) }
func (*Ulimit) ProtoMessage() {} func (*Ulimit) ProtoMessage() {}
func (*Ulimit) Descriptor() ([]byte, []int) { func (*Ulimit) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{3} return fileDescriptor_ed7f10298fa1d90f, []int{8}
} }
func (m *Ulimit) XXX_Unmarshal(b []byte) error { func (m *Ulimit) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Ulimit.Unmarshal(m, b) return xxx_messageInfo_Ulimit.Unmarshal(m, b)
@ -402,8 +639,6 @@ type CommonOptions struct {
Pull bool `protobuf:"varint,4,opt,name=Pull,proto3" json:"Pull,omitempty"` Pull bool `protobuf:"varint,4,opt,name=Pull,proto3" json:"Pull,omitempty"`
ExportPush bool `protobuf:"varint,5,opt,name=ExportPush,proto3" json:"ExportPush,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"` ExportLoad bool `protobuf:"varint,6,opt,name=ExportLoad,proto3" json:"ExportLoad,omitempty"`
SBOM string `protobuf:"bytes,7,opt,name=SBOM,proto3" json:"SBOM,omitempty"`
Provenance string `protobuf:"bytes,8,opt,name=Provenance,proto3" json:"Provenance,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:"-"`
@ -413,7 +648,7 @@ func (m *CommonOptions) Reset() { *m = CommonOptions{} }
func (m *CommonOptions) String() string { return proto.CompactTextString(m) } func (m *CommonOptions) String() string { return proto.CompactTextString(m) }
func (*CommonOptions) ProtoMessage() {} func (*CommonOptions) ProtoMessage() {}
func (*CommonOptions) Descriptor() ([]byte, []int) { func (*CommonOptions) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{4} return fileDescriptor_ed7f10298fa1d90f, []int{9}
} }
func (m *CommonOptions) XXX_Unmarshal(b []byte) error { func (m *CommonOptions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CommonOptions.Unmarshal(m, b) return xxx_messageInfo_CommonOptions.Unmarshal(m, b)
@ -475,31 +710,18 @@ func (m *CommonOptions) GetExportLoad() bool {
return false return false
} }
func (m *CommonOptions) GetSBOM() string {
if m != nil {
return m.SBOM
}
return ""
}
func (m *CommonOptions) GetProvenance() string {
if m != nil {
return m.Provenance
}
return ""
}
type BuildResponse struct { type BuildResponse struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"` 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_unrecognized []byte `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *BuildResponse) Reset() { *m = BuildResponse{} } 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{5} return fileDescriptor_ed7f10298fa1d90f, []int{10}
} }
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)
@ -519,6 +741,13 @@ func (m *BuildResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_BuildResponse proto.InternalMessageInfo var xxx_messageInfo_BuildResponse proto.InternalMessageInfo
func (m *BuildResponse) GetExporterResponse() map[string]string {
if m != nil {
return m.ExporterResponse
}
return nil
}
type DisconnectRequest struct { type DisconnectRequest struct {
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -530,7 +759,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{6} return fileDescriptor_ed7f10298fa1d90f, []int{11}
} }
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)
@ -567,7 +796,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{7} return fileDescriptor_ed7f10298fa1d90f, []int{12}
} }
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)
@ -598,7 +827,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{8} return fileDescriptor_ed7f10298fa1d90f, []int{13}
} }
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)
@ -636,7 +865,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{9} return fileDescriptor_ed7f10298fa1d90f, []int{14}
} }
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)
@ -677,7 +906,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{10} return fileDescriptor_ed7f10298fa1d90f, []int{15}
} }
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)
@ -751,7 +980,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{11} return fileDescriptor_ed7f10298fa1d90f, []int{16}
} }
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)
@ -790,7 +1019,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{12} return fileDescriptor_ed7f10298fa1d90f, []int{17}
} }
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)
@ -834,7 +1063,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{13} return fileDescriptor_ed7f10298fa1d90f, []int{18}
} }
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)
@ -870,7 +1099,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{14} return fileDescriptor_ed7f10298fa1d90f, []int{19}
} }
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)
@ -969,7 +1198,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{15} return fileDescriptor_ed7f10298fa1d90f, []int{20}
} }
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)
@ -1021,7 +1250,7 @@ func (m *ContainerConfig) Reset() { *m = ContainerConfig{} }
func (m *ContainerConfig) String() string { return proto.CompactTextString(m) } func (m *ContainerConfig) String() string { return proto.CompactTextString(m) }
func (*ContainerConfig) ProtoMessage() {} func (*ContainerConfig) ProtoMessage() {}
func (*ContainerConfig) Descriptor() ([]byte, []int) { func (*ContainerConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_ed7f10298fa1d90f, []int{16} return fileDescriptor_ed7f10298fa1d90f, []int{21}
} }
func (m *ContainerConfig) XXX_Unmarshal(b []byte) error { func (m *ContainerConfig) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ContainerConfig.Unmarshal(m, b) return xxx_messageInfo_ContainerConfig.Unmarshal(m, b)
@ -1110,7 +1339,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{17} return fileDescriptor_ed7f10298fa1d90f, []int{22}
} }
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)
@ -1163,7 +1392,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{18} return fileDescriptor_ed7f10298fa1d90f, []int{23}
} }
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)
@ -1210,7 +1439,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{19} return fileDescriptor_ed7f10298fa1d90f, []int{24}
} }
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)
@ -1248,7 +1477,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{20} return fileDescriptor_ed7f10298fa1d90f, []int{25}
} }
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)
@ -1289,7 +1518,7 @@ 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{21} return fileDescriptor_ed7f10298fa1d90f, []int{26}
} }
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)
@ -1347,7 +1576,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{22} return fileDescriptor_ed7f10298fa1d90f, []int{27}
} }
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)
@ -1378,7 +1607,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{23} return fileDescriptor_ed7f10298fa1d90f, []int{28}
} }
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)
@ -1418,7 +1647,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{24} return fileDescriptor_ed7f10298fa1d90f, []int{29}
} }
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)
@ -1462,11 +1691,22 @@ func (m *BuildxVersion) GetRevision() string {
func init() { func init() {
proto.RegisterType((*BuildRequest)(nil), "buildx.controller.v1.BuildRequest") proto.RegisterType((*BuildRequest)(nil), "buildx.controller.v1.BuildRequest")
proto.RegisterType((*BuildOptions)(nil), "buildx.controller.v1.BuildOptions") proto.RegisterType((*BuildOptions)(nil), "buildx.controller.v1.BuildOptions")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.BuildOptions.BuildArgsEntry")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.BuildOptions.LabelsEntry")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.BuildOptions.NamedContextsEntry")
proto.RegisterType((*ExportEntry)(nil), "buildx.controller.v1.ExportEntry")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.ExportEntry.AttrsEntry")
proto.RegisterType((*CacheOptionsEntry)(nil), "buildx.controller.v1.CacheOptionsEntry")
proto.RegisterMapType((map[string]string)(nil), "buildx.controller.v1.CacheOptionsEntry.AttrsEntry")
proto.RegisterType((*Attest)(nil), "buildx.controller.v1.Attest")
proto.RegisterType((*SSH)(nil), "buildx.controller.v1.SSH")
proto.RegisterType((*Secret)(nil), "buildx.controller.v1.Secret")
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((*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.RegisterType((*DisconnectRequest)(nil), "buildx.controller.v1.DisconnectRequest") proto.RegisterType((*DisconnectRequest)(nil), "buildx.controller.v1.DisconnectRequest")
proto.RegisterType((*DisconnectResponse)(nil), "buildx.controller.v1.DisconnectResponse") proto.RegisterType((*DisconnectResponse)(nil), "buildx.controller.v1.DisconnectResponse")
proto.RegisterType((*ListRequest)(nil), "buildx.controller.v1.ListRequest") proto.RegisterType((*ListRequest)(nil), "buildx.controller.v1.ListRequest")
@ -1491,97 +1731,111 @@ 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{
// 1436 bytes of a gzipped FileDescriptorProto // 1657 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x57, 0xdd, 0x52, 0x1b, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xdd, 0x6e, 0xdb, 0xc6,
0x12, 0x3e, 0x8b, 0x84, 0x7e, 0x5a, 0x08, 0xe3, 0x39, 0x1c, 0x9f, 0x39, 0x3a, 0x8e, 0x8d, 0x17, 0x12, 0x3e, 0x94, 0x64, 0xfd, 0x8c, 0x2c, 0xc7, 0xd9, 0xe3, 0x04, 0x3c, 0x3a, 0x39, 0x89, 0xc3,
0xdb, 0x51, 0x55, 0xaa, 0x84, 0x83, 0x93, 0x72, 0x62, 0x3b, 0x17, 0x20, 0xa0, 0x20, 0xc5, 0x5f, 0xfc, 0x1c, 0x01, 0x29, 0xe4, 0xc4, 0x69, 0x9a, 0xdf, 0x02, 0xb5, 0x25, 0x0b, 0x76, 0xe1, 0x3f,
0x16, 0x6c, 0x57, 0x72, 0x11, 0xd7, 0x22, 0x0d, 0x62, 0x4b, 0xab, 0x1d, 0x65, 0x67, 0x24, 0x20, 0x50, 0x4e, 0x82, 0xb6, 0x40, 0x03, 0x5a, 0x5a, 0xcb, 0x84, 0x28, 0xae, 0xca, 0x5d, 0xc9, 0x56,
0x57, 0x79, 0x82, 0x5c, 0xe4, 0x2d, 0xf2, 0x0c, 0x79, 0x8d, 0xbc, 0x47, 0xf2, 0x08, 0xa9, 0xee, 0xaf, 0x7a, 0xd3, 0xdb, 0xbe, 0x47, 0xd1, 0x47, 0xe8, 0x55, 0xdf, 0xa1, 0x0f, 0xd2, 0x47, 0x28,
0x99, 0x5d, 0x56, 0x58, 0x2b, 0x5f, 0x69, 0xfa, 0x9b, 0xef, 0xeb, 0x99, 0xee, 0xe9, 0xe9, 0x59, 0x76, 0x76, 0x49, 0x51, 0x96, 0x28, 0xdb, 0xe8, 0x95, 0x77, 0x86, 0xdf, 0x37, 0xb3, 0x3b, 0x3b,
0xc1, 0x52, 0x47, 0x46, 0x3a, 0x96, 0x61, 0x28, 0xe2, 0xd6, 0x30, 0x96, 0x5a, 0xb2, 0xe5, 0xb3, 0x3f, 0x2b, 0xc3, 0x72, 0x8b, 0xf9, 0x22, 0x60, 0x9e, 0x47, 0x83, 0x6a, 0x3f, 0x60, 0x82, 0x91,
0x51, 0x10, 0x76, 0xaf, 0x5a, 0x99, 0x89, 0xf1, 0xe7, 0x8d, 0x57, 0xbd, 0x40, 0x5f, 0x8c, 0xce, 0x95, 0xe3, 0x81, 0xeb, 0xb5, 0xcf, 0xab, 0xb1, 0x0f, 0xc3, 0x67, 0xe5, 0xb7, 0x1d, 0x57, 0x9c,
0x5a, 0x1d, 0x39, 0x58, 0x1b, 0xc8, 0xb3, 0xeb, 0x35, 0x62, 0xf5, 0x03, 0xbd, 0xe6, 0x0f, 0x83, 0x0e, 0x8e, 0xab, 0x2d, 0xd6, 0x5b, 0xeb, 0xb1, 0xe3, 0xd1, 0x1a, 0xa2, 0xba, 0xae, 0x58, 0x73,
0x35, 0x25, 0xe2, 0x71, 0xd0, 0x11, 0x6a, 0xcd, 0x8a, 0x92, 0x5f, 0xe3, 0xd2, 0xfd, 0x11, 0x16, 0xfa, 0xee, 0x1a, 0xa7, 0xc1, 0xd0, 0x6d, 0x51, 0xbe, 0xa6, 0x49, 0xe1, 0x5f, 0x65, 0xd2, 0xfa,
0x36, 0x91, 0xee, 0x89, 0x9f, 0x46, 0x42, 0x69, 0xb6, 0x04, 0x05, 0x4f, 0x9c, 0x73, 0x67, 0xc5, 0x1e, 0x16, 0x37, 0x25, 0xdc, 0xa6, 0x3f, 0x0c, 0x28, 0x17, 0x64, 0x19, 0xd2, 0x36, 0x3d, 0x31,
0x69, 0x56, 0x3d, 0x1c, 0xb2, 0xd7, 0x50, 0x3e, 0x1a, 0xea, 0x40, 0x46, 0x8a, 0xcf, 0xad, 0x38, 0x8d, 0x55, 0xa3, 0x52, 0xb0, 0xe5, 0x92, 0xbc, 0x83, 0xdc, 0x41, 0x5f, 0xb8, 0xcc, 0xe7, 0x66,
0xcd, 0xda, 0xba, 0xdb, 0x9a, 0xb6, 0x8d, 0x16, 0xb9, 0xb1, 0x4c, 0x2f, 0x91, 0xb8, 0xbf, 0x95, 0x6a, 0xd5, 0xa8, 0x14, 0xd7, 0xad, 0xea, 0xac, 0x6d, 0x54, 0xd1, 0x8c, 0x46, 0xda, 0x21, 0xc5,
0xec, 0x02, 0x16, 0x60, 0x2b, 0x50, 0x6b, 0xcb, 0x48, 0x8b, 0x2b, 0x7d, 0xec, 0xeb, 0x0b, 0xbb, 0xfa, 0x19, 0xb4, 0x03, 0xad, 0x20, 0xab, 0x50, 0xac, 0x31, 0x5f, 0xd0, 0x73, 0x71, 0xe8, 0x88,
0x50, 0x16, 0x62, 0x4f, 0x61, 0x71, 0x4b, 0x76, 0xfa, 0x22, 0x3e, 0x0f, 0x42, 0x71, 0xe8, 0x0f, 0x53, 0xed, 0x28, 0xae, 0x22, 0x8f, 0x61, 0xa9, 0xce, 0x5a, 0x5d, 0x1a, 0x9c, 0xb8, 0x1e, 0xdd,
0x04, 0xad, 0x5b, 0xf5, 0x6e, 0xa1, 0xec, 0x3e, 0x54, 0x8f, 0xe3, 0x20, 0xd2, 0x3b, 0xa3, 0xa8, 0x77, 0x7a, 0x14, 0xfd, 0x16, 0xec, 0x0b, 0x5a, 0x72, 0x07, 0x0a, 0x87, 0x81, 0xeb, 0x8b, 0xc6,
0xc3, 0x0b, 0x44, 0xb9, 0x01, 0xd8, 0x32, 0xcc, 0x6f, 0x84, 0xa1, 0xbc, 0xe4, 0xc5, 0x95, 0x42, 0xc0, 0x6f, 0x99, 0x69, 0x84, 0x8c, 0x15, 0xe4, 0x3b, 0x28, 0x49, 0x54, 0x5b, 0x5b, 0xe6, 0x66,
0xb3, 0xea, 0x19, 0x83, 0x71, 0x28, 0x6f, 0x68, 0x2d, 0x94, 0x56, 0x7c, 0x9e, 0xf0, 0xc4, 0x44, 0x66, 0x35, 0x5d, 0x29, 0xae, 0xbf, 0xb8, 0x7c, 0xf3, 0xd5, 0x09, 0xde, 0x96, 0x2f, 0x82, 0x91,
0x6f, 0xb4, 0xcf, 0x8d, 0xb8, 0xa7, 0x78, 0x89, 0xe6, 0x6e, 0x00, 0x9c, 0x6d, 0xfb, 0x9d, 0x0b, 0x3d, 0x69, 0x8b, 0xac, 0xc0, 0xc2, 0x86, 0xe7, 0xb1, 0x33, 0x73, 0x61, 0x35, 0x5d, 0x29, 0xd8,
0xb1, 0x13, 0xcb, 0x01, 0x2f, 0x9b, 0xd9, 0x14, 0x40, 0xaf, 0x64, 0x9c, 0x4a, 0x5e, 0x31, 0x5e, 0x4a, 0x20, 0x5f, 0x40, 0x6e, 0x43, 0x08, 0xca, 0x05, 0x37, 0xb3, 0xe8, 0xec, 0xce, 0x6c, 0x67,
0xad, 0xc9, 0x5c, 0x58, 0x68, 0xf7, 0x62, 0x39, 0x1a, 0x1e, 0xfb, 0xb1, 0x88, 0x34, 0xaf, 0xd2, 0x0a, 0x64, 0x87, 0x60, 0x72, 0x00, 0x05, 0xf4, 0xbf, 0x11, 0x74, 0xb8, 0x99, 0x43, 0xe6, 0xb3,
0x36, 0x27, 0x30, 0xd6, 0x80, 0x8a, 0x0d, 0x5f, 0x71, 0x20, 0x79, 0x6a, 0xb3, 0x07, 0x00, 0xdb, 0x2b, 0x6c, 0x33, 0xe2, 0xa8, 0x2d, 0x8e, 0x6d, 0x90, 0x2d, 0x28, 0xd4, 0x9c, 0xd6, 0x29, 0x6d,
0x57, 0x3a, 0xf6, 0x77, 0x25, 0x6e, 0xb9, 0x46, 0xb3, 0x19, 0x04, 0xb3, 0xb9, 0x37, 0xf0, 0x7b, 0x04, 0xac, 0x67, 0xe6, 0xd1, 0xe0, 0xff, 0x67, 0x1b, 0x44, 0x98, 0x36, 0xa8, 0xcd, 0x44, 0x4c,
0x62, 0x6f, 0x6b, 0x27, 0x08, 0x05, 0x5f, 0x30, 0xd9, 0xcc, 0x40, 0xec, 0x1e, 0x94, 0xf6, 0xfd, 0xb2, 0x01, 0x39, 0x14, 0x8e, 0x98, 0x59, 0xb8, 0x9e, 0x91, 0x90, 0x47, 0x2c, 0x58, 0xac, 0x75,
0x33, 0x11, 0x2a, 0x5e, 0x27, 0xb5, 0xb5, 0x50, 0x79, 0x28, 0xf4, 0xa5, 0x8c, 0xfb, 0x07, 0xb2, 0x02, 0x36, 0xe8, 0x1f, 0x3a, 0x01, 0xf5, 0x85, 0x09, 0x78, 0x4d, 0x13, 0x3a, 0xf2, 0x16, 0x72,
0x2b, 0xf8, 0xa2, 0x51, 0x66, 0x20, 0xf6, 0x18, 0xea, 0x87, 0xd2, 0x04, 0x19, 0x84, 0x5a, 0xc4, 0x5b, 0xe7, 0x7d, 0x16, 0x08, 0x6e, 0x16, 0xd1, 0xcd, 0xfd, 0xd9, 0x6e, 0x14, 0x48, 0x3b, 0xd0,
0xfc, 0x0e, 0x39, 0x98, 0x04, 0x31, 0xf6, 0xa3, 0x91, 0x1e, 0x8e, 0xb4, 0xe2, 0x4b, 0x26, 0x76, 0x0c, 0x72, 0x17, 0x60, 0xeb, 0x5c, 0x04, 0xce, 0x36, 0x93, 0x61, 0x5f, 0xc4, 0xeb, 0x88, 0x69,
0x6b, 0xd2, 0xf9, 0x84, 0xbe, 0x3e, 0x97, 0xf1, 0x40, 0xf1, 0xbb, 0x26, 0x67, 0x29, 0x80, 0xe7, 0x48, 0x03, 0xb2, 0xbb, 0xce, 0x31, 0xf5, 0xb8, 0x59, 0x42, 0xdb, 0xd5, 0x2b, 0x04, 0x56, 0x11,
0xf3, 0xdd, 0x28, 0x10, 0x9a, 0xb3, 0x15, 0xa7, 0x59, 0xf1, 0x8c, 0x81, 0xde, 0x4e, 0x44, 0x27, 0x94, 0x23, 0xcd, 0x96, 0x69, 0xbb, 0x4f, 0xc5, 0x19, 0x0b, 0xba, 0x7b, 0xac, 0x4d, 0xcd, 0x25,
0x16, 0x5a, 0xf1, 0x7f, 0x1b, 0x6f, 0xd6, 0xa4, 0x99, 0x8b, 0xc1, 0x49, 0xf0, 0xb3, 0xe0, 0xcb, 0x95, 0xb6, 0x31, 0x15, 0x79, 0x08, 0xa5, 0x7d, 0xa6, 0x82, 0xe7, 0x7a, 0x82, 0x06, 0xe6, 0x0d,
0x2b, 0x4e, 0xb3, 0xe0, 0x25, 0x26, 0x96, 0xec, 0xc9, 0xc9, 0x2e, 0xff, 0x0f, 0xf1, 0x71, 0xc8, 0xdc, 0xcc, 0xa4, 0x12, 0x93, 0xd6, 0x73, 0xc4, 0x09, 0x0b, 0x7a, 0xdc, 0x5c, 0x46, 0xc4, 0x58,
0x18, 0x14, 0x4f, 0xfd, 0x9e, 0xe2, 0xf7, 0x08, 0xa2, 0x31, 0xe6, 0xe1, 0xd4, 0x8f, 0x7b, 0x42, 0x21, 0x33, 0xa8, 0x49, 0x5b, 0x01, 0x15, 0xdc, 0xbc, 0x39, 0x2f, 0x83, 0x14, 0xc8, 0x0e, 0xc1,
0xf3, 0xff, 0x52, 0xa8, 0xd6, 0x62, 0x5f, 0x43, 0xf9, 0x4d, 0x18, 0x0c, 0x02, 0xad, 0x38, 0xa7, 0xc4, 0x84, 0x5c, 0xf3, 0xb4, 0xd7, 0x74, 0x7f, 0xa4, 0x26, 0x59, 0x35, 0x2a, 0x69, 0x3b, 0x14,
0xf2, 0x7e, 0x38, 0xbd, 0xbc, 0x0d, 0xe9, 0x68, 0xa8, 0xbd, 0x84, 0xcf, 0x5e, 0x40, 0xf1, 0x68, 0xc9, 0x13, 0x48, 0x37, 0x9b, 0xdb, 0xe6, 0xbf, 0xd1, 0xda, 0x7f, 0x12, 0xac, 0x35, 0xb7, 0x6d,
0xa8, 0x15, 0xff, 0x1f, 0xe9, 0x56, 0xa7, 0xeb, 0xda, 0x72, 0x30, 0x90, 0x51, 0x72, 0x2f, 0x48, 0x89, 0x22, 0x04, 0x32, 0x47, 0x4e, 0x87, 0x9b, 0x2b, 0xb8, 0x2f, 0x5c, 0x93, 0xdb, 0x90, 0x3d,
0xe0, 0xfe, 0xee, 0x40, 0x35, 0xf5, 0xc7, 0xda, 0x50, 0x1a, 0xfb, 0xe1, 0x48, 0x28, 0xee, 0xac, 0x72, 0x82, 0x0e, 0x15, 0xe6, 0x2d, 0x3c, 0xb3, 0x96, 0xc8, 0x6b, 0xc8, 0xbd, 0xf7, 0xdc, 0x9e,
0x14, 0x9a, 0xb5, 0xf5, 0xcf, 0x3e, 0xb2, 0x81, 0xd6, 0x5b, 0x62, 0x6f, 0x47, 0x3a, 0xbe, 0xf6, 0x2b, 0xb8, 0x79, 0x1b, 0xdb, 0xc2, 0xbd, 0xd9, 0xc6, 0x15, 0xe8, 0xa0, 0x2f, 0xec, 0x10, 0x4f,
0xac, 0xb4, 0xf1, 0x0e, 0x6a, 0x19, 0x18, 0x73, 0xd2, 0x17, 0xd7, 0xc9, 0x35, 0xee, 0x8b, 0x6b, 0x5e, 0x42, 0xe6, 0xa0, 0x2f, 0xb8, 0x69, 0x22, 0xef, 0x41, 0x42, 0x52, 0xb1, 0x5e, 0x8f, 0xf9,
0xb6, 0x0e, 0xf3, 0x44, 0xb5, 0x97, 0xf8, 0xfe, 0xac, 0x45, 0x3c, 0x43, 0x7d, 0x39, 0xf7, 0x95, 0x61, 0x3f, 0x41, 0x42, 0xf9, 0x2b, 0x20, 0xd3, 0xb5, 0x29, 0x5b, 0x56, 0x97, 0x8e, 0xc2, 0x96,
0xe3, 0x6e, 0x41, 0xc9, 0x80, 0x98, 0x55, 0xba, 0x8d, 0xc6, 0x29, 0x8d, 0x11, 0xdb, 0xf5, 0xe3, 0xd5, 0xa5, 0x23, 0x59, 0x9e, 0x43, 0xc7, 0x1b, 0x84, 0x8d, 0x43, 0x09, 0x6f, 0x52, 0xaf, 0x8c,
0x2e, 0x39, 0x2d, 0x78, 0x34, 0x46, 0xec, 0x44, 0x9e, 0x6b, 0xba, 0x92, 0x05, 0x8f, 0xc6, 0xee, 0xf2, 0x3b, 0x58, 0x9a, 0x2c, 0x9b, 0x6b, 0xb1, 0x5f, 0x43, 0x31, 0x96, 0x1b, 0xd7, 0xa1, 0x5a,
0x5f, 0x0e, 0xd4, 0x27, 0x32, 0x81, 0xe7, 0x49, 0xd7, 0x4b, 0xc4, 0xd6, 0x61, 0x62, 0xe2, 0x9d, 0x7f, 0x18, 0x50, 0x8c, 0x25, 0x30, 0x86, 0x7a, 0xd4, 0xa7, 0x9a, 0x8c, 0x6b, 0xb2, 0x09, 0x0b,
0x39, 0x10, 0xda, 0xef, 0xfa, 0xda, 0xa7, 0xa2, 0x36, 0xb7, 0x7f, 0x02, 0x43, 0xb5, 0x2d, 0x43, 0x1b, 0x42, 0x04, 0xb2, 0xcf, 0xca, 0xdb, 0xfa, 0xec, 0xd2, 0x32, 0xa8, 0x22, 0x5c, 0x25, 0xaa,
0x5a, 0xa6, 0xe2, 0x25, 0x26, 0xae, 0x7e, 0x3c, 0x0a, 0x43, 0x5e, 0x24, 0x98, 0xc6, 0xe6, 0x16, 0xa2, 0xca, 0x3c, 0xad, 0x53, 0x2e, 0x5c, 0xdf, 0x91, 0x81, 0xd3, 0x6d, 0x31, 0xae, 0x2a, 0xbf,
0x0d, 0x65, 0xac, 0x8f, 0x47, 0xea, 0x82, 0xcf, 0xd3, 0x4c, 0x06, 0xb9, 0x99, 0xdf, 0x97, 0x7e, 0x02, 0x18, 0xd3, 0xae, 0x75, 0x86, 0xdf, 0x0c, 0xb8, 0x39, 0x55, 0xeb, 0x33, 0x4f, 0xb2, 0x3d,
0x97, 0x97, 0xb2, 0xf3, 0x88, 0x50, 0x44, 0x9b, 0x47, 0x07, 0xbc, 0x6c, 0x22, 0xc7, 0x31, 0x6a, 0x79, 0x92, 0xf5, 0x2b, 0xf6, 0x8d, 0xe9, 0xf3, 0xfc, 0x83, 0xdd, 0xee, 0x43, 0x56, 0x35, 0xd8,
0x8e, 0x63, 0x39, 0x16, 0x91, 0x1f, 0x75, 0x04, 0xaf, 0xd0, 0x4c, 0x06, 0x71, 0xef, 0x40, 0xdd, 0x99, 0x3b, 0x2c, 0x43, 0xbe, 0xee, 0x72, 0xe7, 0xd8, 0xa3, 0x6d, 0xa4, 0xe6, 0xed, 0x48, 0xc6,
0x36, 0x56, 0x35, 0x94, 0x91, 0x12, 0xee, 0x13, 0xb8, 0xbb, 0x15, 0xa8, 0x8e, 0x8c, 0x22, 0xd1, 0xee, 0x8e, 0xbb, 0x57, 0xd1, 0x53, 0x82, 0xa5, 0x2a, 0x89, 0x2c, 0x41, 0x6a, 0xa7, 0xae, 0x4d,
0xd1, 0xb9, 0xed, 0xd6, 0x5d, 0x06, 0x96, 0xa5, 0x59, 0xf1, 0x43, 0xa8, 0xed, 0x07, 0x6a, 0x86, 0xa5, 0x76, 0xea, 0x12, 0x2c, 0xa7, 0x96, 0x3a, 0x6a, 0xc1, 0x56, 0x82, 0xd5, 0x80, 0xac, 0xaa,
0xcc, 0x85, 0x05, 0x43, 0x30, 0x02, 0xdc, 0x72, 0x5f, 0x5c, 0x9b, 0x92, 0xaa, 0x7a, 0x34, 0x76, 0xcd, 0x29, 0x7c, 0x19, 0xf2, 0x0d, 0xd7, 0xa3, 0x38, 0xfc, 0xd4, 0x9e, 0x23, 0x59, 0x1e, 0x6f,
0x7f, 0x75, 0x60, 0x61, 0x2f, 0x1a, 0x8e, 0xf4, 0x81, 0x50, 0xca, 0xef, 0x09, 0xf6, 0x1a, 0x8a, 0xcb, 0x1f, 0x6a, 0xb7, 0x72, 0x69, 0xfd, 0x6a, 0x40, 0x21, 0xaa, 0x20, 0x52, 0x83, 0x2c, 0x9e,
0x7b, 0x51, 0xa0, 0xc9, 0x4f, 0x6d, 0xfd, 0xe9, 0xf4, 0x92, 0x20, 0x05, 0xd2, 0xac, 0x6a, 0xf7, 0x8f, 0x9b, 0x06, 0xc6, 0xf5, 0xc9, 0x25, 0x25, 0x57, 0xfd, 0x80, 0x68, 0xdd, 0xc9, 0x14, 0xb5,
0x5f, 0x1e, 0xa9, 0xb0, 0xfc, 0xb7, 0x7c, 0xed, 0xdb, 0x82, 0x7a, 0x34, 0x5d, 0x8d, 0x8c, 0x8c, 0xfc, 0x11, 0x8a, 0x31, 0xf5, 0x8c, 0x90, 0xae, 0xc7, 0x43, 0x9a, 0xd8, 0x82, 0x94, 0x93, 0x78,
0x10, 0xcd, 0xcd, 0x32, 0xcc, 0x93, 0x53, 0xf7, 0x31, 0x2c, 0xdd, 0xf6, 0x3e, 0x25, 0xb4, 0xe7, 0xc0, 0xeb, 0x90, 0x55, 0x4a, 0x19, 0x70, 0x9c, 0xdb, 0x3a, 0xe0, 0x38, 0xad, 0x09, 0x64, 0xb6,
0x50, 0xcb, 0x78, 0x41, 0xc2, 0xf6, 0xd1, 0x0e, 0x11, 0x2a, 0x1e, 0x0e, 0x31, 0xd6, 0x74, 0x23, 0x9d, 0x40, 0x05, 0x3b, 0x6d, 0xe3, 0x5a, 0xea, 0x9a, 0xec, 0x44, 0xe0, 0x81, 0xd3, 0x36, 0xae,
0x0b, 0x66, 0x0d, 0x4c, 0x3f, 0xb9, 0x4e, 0x33, 0xf8, 0xcb, 0x1c, 0x94, 0x13, 0x17, 0x2f, 0x26, 0xad, 0xdf, 0x0d, 0x28, 0x4d, 0xd4, 0xbe, 0x6c, 0x6e, 0x58, 0xb3, 0x34, 0xd0, 0x06, 0x43, 0x51,
0xe2, 0x7e, 0x94, 0x17, 0xf7, 0x87, 0x21, 0x7f, 0x09, 0xc5, 0xb4, 0x24, 0x73, 0x3b, 0xc5, 0x4e, 0x4e, 0x97, 0x3d, 0x2a, 0x9c, 0xb6, 0x23, 0x1c, 0x19, 0x43, 0x1d, 0xcf, 0x09, 0x9d, 0x64, 0xeb,
0x37, 0x23, 0xa3, 0x6a, 0xfd, 0x06, 0x4a, 0x9e, 0x50, 0xd8, 0xba, 0x0a, 0xb3, 0x5a, 0x85, 0xe1, 0x0e, 0x8c, 0x6e, 0xf2, 0x76, 0x28, 0x4a, 0xef, 0x87, 0x03, 0xcf, 0x33, 0x33, 0xa8, 0xc6, 0xb5,
0xdc, 0x88, 0xad, 0x08, 0xe5, 0x27, 0x41, 0x2f, 0xf2, 0x4d, 0x51, 0xe7, 0xca, 0x0d, 0x27, 0x23, 0x1a, 0x27, 0xb2, 0xbe, 0x0e, 0x07, 0xfc, 0xd4, 0x5c, 0xc0, 0x2f, 0x31, 0xcd, 0xf8, 0xfb, 0x2e,
0x37, 0xc0, 0x4d, 0xba, 0x87, 0x50, 0x9b, 0x99, 0x69, 0x76, 0x04, 0x77, 0xf0, 0xe5, 0xf1, 0x83, 0x73, 0xda, 0x66, 0x36, 0xfe, 0x5d, 0x6a, 0x70, 0xf7, 0xfa, 0x3d, 0xc5, 0xfb, 0xcc, 0xe7, 0x94,
0x48, 0xc4, 0x6d, 0x19, 0x9d, 0x07, 0x3d, 0x1b, 0xe9, 0x93, 0xbc, 0xde, 0x36, 0x41, 0xf6, 0x6e, 0x50, 0x58, 0x56, 0xdf, 0x69, 0x10, 0xea, 0xf4, 0xed, 0xbd, 0x9e, 0x33, 0x8a, 0x42, 0x68, 0xf5,
0xab, 0xdd, 0x3f, 0x9c, 0x0f, 0x3c, 0xd2, 0x65, 0xc3, 0x1e, 0x35, 0x94, 0x41, 0xa4, 0x6d, 0x7d, 0x22, 0x57, 0xdd, 0xe5, 0x94, 0xc9, 0x72, 0x0d, 0x6e, 0xcd, 0x84, 0x5e, 0xab, 0x64, 0x1e, 0xc1,
0x66, 0x10, 0xdc, 0x56, 0x7b, 0x80, 0x1d, 0x85, 0xda, 0x79, 0x7b, 0xd0, 0xa5, 0x13, 0x8f, 0xc6, 0xcd, 0xba, 0xcb, 0x5b, 0xcc, 0xf7, 0x69, 0x4b, 0x24, 0xbe, 0x08, 0xad, 0x15, 0x20, 0x71, 0x98,
0xbc, 0x60, 0x90, 0xed, 0x68, 0x8c, 0x27, 0xfe, 0x46, 0x89, 0x98, 0xf2, 0x51, 0xf5, 0x68, 0x8c, 0xf2, 0x66, 0xdd, 0x83, 0xe2, 0xae, 0xcb, 0xe7, 0xd0, 0x2c, 0x58, 0x54, 0x00, 0x1d, 0x19, 0x02,
0x0d, 0xfe, 0x50, 0x12, 0x6a, 0x2e, 0xb8, 0xb5, 0xc8, 0xdf, 0xa5, 0xb9, 0xd5, 0xe8, 0xef, 0xb2, 0x99, 0x2e, 0x1d, 0xa9, 0x5c, 0x2e, 0xd8, 0xb8, 0xb6, 0x7e, 0x31, 0x60, 0x71, 0xc7, 0xef, 0x0f,
0x8b, 0x4f, 0xcf, 0xa1, 0x44, 0xac, 0x6c, 0x9e, 0x1e, 0x32, 0x90, 0x77, 0xaa, 0xaf, 0xe9, 0x26, 0xc4, 0x1e, 0xe5, 0xdc, 0xe9, 0x50, 0xf2, 0x0e, 0x32, 0x3b, 0xbe, 0x2b, 0xd0, 0x4e, 0x71, 0xfd,
0x57, 0x3c, 0x1c, 0xba, 0x1b, 0x50, 0x4d, 0xcf, 0x92, 0x2d, 0xc2, 0xdc, 0x4e, 0x97, 0x92, 0x55, 0xf1, 0xec, 0x90, 0x21, 0x43, 0xc2, 0x34, 0x6b, 0xfb, 0x5f, 0x36, 0xb2, 0xe4, 0xa4, 0xa9, 0x3b,
0xf7, 0xe6, 0x76, 0xba, 0x49, 0x19, 0xce, 0x7d, 0x58, 0x86, 0x85, 0x4c, 0x19, 0xbe, 0x80, 0xfa, 0xc2, 0xd1, 0x99, 0x9c, 0xf0, 0xae, 0x90, 0x88, 0x18, 0x51, 0x8a, 0x9b, 0x39, 0x58, 0x40, 0xa3,
0xc4, 0xa9, 0x22, 0xc9, 0x93, 0x97, 0xca, 0x3a, 0xa2, 0x31, 0x62, 0x6d, 0x19, 0x9a, 0xcf, 0xab, 0xd6, 0x43, 0x58, 0xbe, 0x68, 0x7d, 0xc6, 0xd1, 0x9e, 0x43, 0x31, 0x66, 0x05, 0xeb, 0xf8, 0xa0,
0xba, 0x47, 0x63, 0x77, 0x15, 0xea, 0x13, 0xe7, 0x39, 0xad, 0xfb, 0xba, 0x8f, 0xa0, 0x7e, 0xa2, 0x81, 0x80, 0xbc, 0x2d, 0x97, 0xf2, 0xac, 0xd1, 0x46, 0x16, 0x95, 0x0f, 0xeb, 0x06, 0x94, 0xd0,
0x7d, 0x3d, 0x52, 0xf9, 0x7d, 0xe1, 0x6f, 0x07, 0x16, 0x13, 0x8e, 0x6d, 0x0d, 0x5f, 0x40, 0x65, 0x74, 0x14, 0xc1, 0x9f, 0x52, 0x90, 0x0b, 0x4d, 0xbc, 0x9c, 0x38, 0xf7, 0xfd, 0xa4, 0x73, 0x4f,
0x2c, 0x62, 0x2d, 0xae, 0xd2, 0x17, 0x87, 0xb7, 0xf0, 0xbb, 0xb1, 0x95, 0x7c, 0x37, 0xe2, 0xd1, 0x1f, 0xf9, 0x05, 0x64, 0xa2, 0x5a, 0x48, 0x1c, 0xca, 0x8d, 0x76, 0x8c, 0x86, 0x65, 0xf2, 0x25,
0xbe, 0x25, 0x86, 0x97, 0x32, 0xd9, 0x4b, 0xa8, 0x28, 0xf2, 0x23, 0x14, 0x9d, 0x4d, 0x6d, 0xfd, 0x64, 0x6d, 0xca, 0xe5, 0x03, 0x22, 0x3d, 0x6f, 0x2a, 0x2b, 0xcc, 0x98, 0xac, 0x49, 0x92, 0xde,
0x41, 0x9e, 0xca, 0xae, 0x97, 0xf2, 0xd9, 0x1a, 0x14, 0x43, 0xd9, 0x53, 0x74, 0x82, 0xb5, 0xf5, 0x74, 0x3b, 0xbe, 0xa3, 0xaa, 0x29, 0x91, 0xae, 0x30, 0x31, 0xba, 0x52, 0x8c, 0xc3, 0xdd, 0x87,
0xff, 0xe7, 0xe9, 0xf6, 0x65, 0xcf, 0x23, 0x22, 0x7b, 0x05, 0x95, 0x4b, 0x3f, 0x8e, 0x82, 0xa8, 0xe2, 0xdc, 0x48, 0x93, 0x03, 0xb8, 0x21, 0xa7, 0xbf, 0xe3, 0xfa, 0x34, 0xa8, 0x31, 0xff, 0xc4,
0xa7, 0xe8, 0xfb, 0x0d, 0xef, 0x5a, 0x8e, 0xe8, 0x9d, 0xe1, 0x79, 0xa9, 0xc0, 0xad, 0x63, 0x99, 0xed, 0xe8, 0x93, 0x3e, 0x4a, 0x7a, 0x46, 0x4c, 0x80, 0xed, 0x8b, 0x6c, 0x59, 0xb1, 0x17, 0x75,
0x9f, 0x4b, 0x9b, 0x13, 0xf7, 0x7b, 0x6c, 0x7a, 0x68, 0xda, 0xf0, 0xf7, 0xa0, 0x6e, 0x8a, 0xf9, 0x58, 0xe5, 0xb2, 0x78, 0xfa, 0xcc, 0xf5, 0x85, 0xce, 0xcf, 0x98, 0x46, 0x6e, 0xab, 0xd6, 0x6b,
0xad, 0x88, 0x55, 0x20, 0x23, 0xdb, 0x05, 0x56, 0x67, 0x7c, 0xd5, 0x26, 0x54, 0x6f, 0x52, 0xe9, 0xeb, 0x8e, 0x2f, 0x97, 0xe3, 0xce, 0x9d, 0xd6, 0x9d, 0x5b, 0xde, 0xf8, 0x7b, 0x4e, 0x03, 0x8c,
0xbe, 0xb7, 0x3d, 0x3e, 0x01, 0xf0, 0x59, 0x1a, 0xfa, 0x9d, 0xbe, 0xdf, 0x4b, 0xce, 0x29, 0x31, 0x47, 0xc1, 0xc6, 0xb5, 0x7c, 0x4b, 0xed, 0x33, 0xd4, 0xaa, 0xce, 0xa2, 0x25, 0xb4, 0x77, 0xa6,
0x71, 0x66, 0x6c, 0xd7, 0x33, 0xef, 0x59, 0x62, 0xe2, 0xe7, 0x5f, 0x2c, 0xc6, 0x01, 0x4d, 0x99, 0xda, 0x89, 0xb4, 0x77, 0x86, 0x23, 0x68, 0x9f, 0x49, 0x5d, 0x0e, 0x81, 0x4a, 0x90, 0xb8, 0x23,
0xaf, 0xd8, 0xd4, 0x5e, 0xff, 0xb3, 0x08, 0xd0, 0x4e, 0xf7, 0xc3, 0x8e, 0x61, 0x9e, 0xd6, 0x63, 0x31, 0x32, 0xf3, 0x2a, 0xaf, 0x8e, 0xc4, 0xc8, 0xda, 0x80, 0x42, 0x74, 0x97, 0x72, 0xd4, 0x34,
0xb3, 0x3e, 0xc1, 0x6d, 0xdc, 0x8d, 0xd5, 0x99, 0x1c, 0x9b, 0x8c, 0x37, 0x50, 0x32, 0xa7, 0xc5, 0xda, 0x18, 0xac, 0x92, 0x9d, 0x6a, 0xb4, 0xc3, 0x34, 0x4c, 0x4d, 0xa7, 0x61, 0x3a, 0x96, 0x86,
0xf2, 0x9a, 0x4a, 0xb6, 0xbe, 0x1a, 0x8f, 0x67, 0x93, 0x8c, 0xd3, 0x67, 0x0e, 0xf3, 0x6c, 0xcb, 0x2f, 0xa1, 0x34, 0x71, 0xab, 0x12, 0x64, 0xb3, 0x33, 0xae, 0x0d, 0xe1, 0x5a, 0xea, 0x6a, 0xcc,
0xc9, 0xdb, 0x68, 0xf6, 0x15, 0xca, 0xdb, 0xe8, 0x44, 0xfb, 0x6e, 0x3a, 0xec, 0x5b, 0x28, 0xed, 0x53, 0xbf, 0x00, 0x4b, 0x36, 0xae, 0xad, 0x07, 0x50, 0x9a, 0xb8, 0xcf, 0x59, 0x6d, 0xdf, 0xba,
0x45, 0x63, 0xd9, 0x17, 0xec, 0x93, 0xe9, 0x82, 0xc4, 0xdf, 0xec, 0xe9, 0xa6, 0xf3, 0xcc, 0x61, 0x0f, 0xa5, 0xa6, 0x70, 0xc4, 0x80, 0x27, 0xf7, 0x85, 0xbf, 0x0c, 0x58, 0x0a, 0x31, 0xba, 0x35,
0x07, 0x50, 0xc4, 0xd7, 0x92, 0xe5, 0xb4, 0xfe, 0xcc, 0x53, 0xdb, 0x70, 0x67, 0x51, 0x6c, 0x16, 0x7c, 0x0e, 0xf9, 0x21, 0x0d, 0x04, 0x3d, 0x8f, 0x46, 0x9d, 0x59, 0x95, 0x3f, 0x6d, 0xab, 0xe1,
0xdf, 0x03, 0xdc, 0xbc, 0xd9, 0xec, 0xd3, 0x9c, 0x97, 0xf0, 0xf6, 0xe3, 0xdf, 0x68, 0x7e, 0x9c, 0x4f, 0x5b, 0x79, 0xb5, 0x1f, 0x10, 0x61, 0x47, 0x48, 0xf2, 0x06, 0xf2, 0x1c, 0xed, 0xd0, 0xf0,
0x68, 0x17, 0x38, 0xc0, 0x07, 0xeb, 0x5c, 0xb2, 0xdc, 0xa7, 0x2a, 0x2d, 0xf7, 0x86, 0x3b, 0x8b, 0xe1, 0x71, 0x37, 0x89, 0xa5, 0xfd, 0x45, 0x78, 0xb2, 0x06, 0x19, 0x8f, 0x75, 0x38, 0xde, 0x60,
0x62, 0xdc, 0x6d, 0x16, 0x7f, 0x98, 0x1b, 0x9e, 0x9d, 0x95, 0xe8, 0x1f, 0xe0, 0xf3, 0x7f, 0x02, 0x71, 0xfd, 0xbf, 0x49, 0xbc, 0x5d, 0xd6, 0xb1, 0x11, 0x48, 0xde, 0x42, 0xfe, 0xcc, 0x09, 0x7c,
0x00, 0x00, 0xff, 0xff, 0x10, 0xcd, 0x98, 0x21, 0x68, 0x0e, 0x00, 0x00, 0xd7, 0xef, 0x84, 0x3f, 0x2d, 0xef, 0x25, 0x91, 0x3e, 0x2a, 0x9c, 0x1d, 0x11, 0xac, 0x92, 0x4c,
0xf3, 0x13, 0xa6, 0x63, 0x62, 0x7d, 0x23, 0x9b, 0x9e, 0x14, 0xf5, 0xf1, 0x77, 0xa0, 0xa4, 0x92,
0xf9, 0x03, 0x0d, 0xb8, 0x7c, 0xc6, 0x19, 0xf3, 0x8a, 0x6a, 0x33, 0x0e, 0xb5, 0x27, 0x99, 0xd6,
0x27, 0x3d, 0x8f, 0x42, 0x85, 0x9c, 0x87, 0x7d, 0xa7, 0xd5, 0x75, 0x3a, 0xe1, 0x3d, 0x85, 0xa2,
0xfc, 0x32, 0xd4, 0xfe, 0xd4, 0x64, 0x08, 0x45, 0xf9, 0x66, 0x09, 0xe8, 0xd0, 0xe5, 0xe3, 0x17,
0x65, 0x24, 0xaf, 0xff, 0x99, 0x01, 0xa8, 0x45, 0xfb, 0x21, 0x87, 0xb0, 0x80, 0xfe, 0x88, 0x35,
0x77, 0xba, 0xe1, 0xb9, 0xcb, 0x0f, 0xae, 0x30, 0x01, 0xc9, 0x7b, 0xc8, 0xaa, 0xdb, 0x22, 0x49,
0x4d, 0x25, 0x9e, 0x5f, 0xe5, 0x87, 0xf3, 0x41, 0xca, 0xe8, 0x53, 0x83, 0xd8, 0xba, 0xe5, 0x24,
0x6d, 0x34, 0x3e, 0x85, 0x92, 0x36, 0x3a, 0xd1, 0xbe, 0x2b, 0x06, 0xf9, 0x1a, 0xb2, 0x3b, 0xfe,
0x90, 0x75, 0x29, 0xf9, 0xdf, 0x6c, 0x42, 0x68, 0x6f, 0xfe, 0xe7, 0x8a, 0xf1, 0xd4, 0x20, 0x7b,
0x90, 0x91, 0xd3, 0x92, 0x24, 0xb4, 0xfe, 0xd8, 0xa8, 0x2d, 0x5b, 0xf3, 0x20, 0x3a, 0x8a, 0x9f,
0x00, 0xc6, 0x33, 0x9b, 0x24, 0xfc, 0x90, 0x9f, 0x1a, 0xfe, 0xe5, 0xca, 0xe5, 0x40, 0xed, 0x60,
0x4f, 0x0e, 0xac, 0x13, 0x46, 0x12, 0x47, 0x55, 0x94, 0xee, 0x65, 0x6b, 0x1e, 0x44, 0x99, 0xdb,
0xcc, 0x7c, 0x9b, 0xea, 0x1f, 0x1f, 0x67, 0xf1, 0x9f, 0x54, 0xcf, 0xff, 0x0e, 0x00, 0x00, 0xff,
0xff, 0xf4, 0x2e, 0xaa, 0xc4, 0x0b, 0x13, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

@ -25,30 +25,56 @@ message BuildOptions {
string ContextPath = 1; string ContextPath = 1;
string DockerfileName = 2; string DockerfileName = 2;
string PrintFunc = 3; string PrintFunc = 3;
map<string, string> NamedContexts = 4;
repeated string Allow = 4;
repeated string Attests = 5; // TODO repeated string Allow = 5;
repeated string BuildArgs = 6; repeated Attest Attests = 6;
repeated string CacheFrom = 7; map<string, string> BuildArgs = 7;
repeated string CacheTo = 8; repeated CacheOptionsEntry CacheFrom = 8;
string CgroupParent = 9; repeated CacheOptionsEntry CacheTo = 9;
repeated string Contexts = 10; string CgroupParent = 10;
repeated string ExtraHosts = 11; repeated ExportEntry Exports = 11;
string ImageIDFile = 12; repeated string ExtraHosts = 12;
repeated string Labels = 13; map<string, string> Labels = 13;
string NetworkMode = 14; string NetworkMode = 14;
repeated string NoCacheFilter = 15; repeated string NoCacheFilter = 15;
repeated string Outputs = 16; repeated string Platforms = 16;
repeated string Platforms = 17; repeated Secret Secrets = 17;
bool Quiet = 18; int64 ShmSize = 18;
repeated string Secrets = 19; repeated SSH SSH = 19;
int64 ShmSize = 20; repeated string Tags = 20;
repeated string SSH = 21; string Target = 21;
repeated string Tags = 22; UlimitOpt Ulimits = 22;
string Target = 23;
UlimitOpt Ulimits = 24; CommonOptions Opts = 24;
// string Invoke: provided via Invoke API }
CommonOptions Opts = 25;
message ExportEntry {
string Type = 1;
map<string, string> Attrs = 2;
string Destination = 3;
}
message CacheOptionsEntry {
string Type = 1;
map<string, string> Attrs = 2;
}
message Attest {
string Type = 1;
bool Disabled = 2;
string Attrs = 3;
}
message SSH {
string ID = 1;
repeated string Paths = 2;
}
message Secret {
string ID = 1;
string FilePath = 2;
string Env = 3;
} }
message UlimitOpt { message UlimitOpt {
@ -69,11 +95,11 @@ message CommonOptions {
bool Pull = 4; bool Pull = 4;
bool ExportPush = 5; bool ExportPush = 5;
bool ExportLoad = 6; bool ExportLoad = 6;
string SBOM = 7; // TODO
string Provenance = 8; // TODO
} }
message BuildResponse {} message BuildResponse {
map<string, string> ExporterResponse = 1;
}
message DisconnectRequest { message DisconnectRequest {
string Ref = 1; string Ref = 1;

@ -1,66 +1,31 @@
package buildflags package pb
import ( import (
"encoding/csv"
"io" "io"
"os" "os"
"strconv" "strconv"
"strings"
"github.com/containerd/console" "github.com/containerd/console"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func ParseOutputs(inp []string) ([]client.ExportEntry, error) { func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, error) {
var outs []client.ExportEntry var outs []client.ExportEntry
if len(inp) == 0 { if len(entries) == 0 {
return nil, nil return nil, nil
} }
for _, s := range inp { for _, entry := range entries {
csvReader := csv.NewReader(strings.NewReader(s)) if entry.Type == "" {
fields, err := csvReader.Read() return nil, errors.Errorf("type is required for output")
if err != nil {
return nil, err
} }
out := client.ExportEntry{ out := client.ExportEntry{
Type: entry.Type,
Attrs: map[string]string{}, Attrs: map[string]string{},
} }
if len(fields) == 1 && fields[0] == s && !strings.HasPrefix(s, "type=") { for k, v := range entry.Attrs {
if s != "-" { out.Attrs[k] = v
outs = append(outs, client.ExportEntry{
Type: client.ExporterLocal,
OutputDir: s,
})
continue
}
out = client.ExportEntry{
Type: client.ExporterTar,
Attrs: map[string]string{
"dest": s,
},
}
}
if out.Type == "" {
for _, field := range fields {
parts := strings.SplitN(field, "=", 2)
if len(parts) != 2 {
return nil, errors.Errorf("invalid value %s", field)
}
key := strings.TrimSpace(strings.ToLower(parts[0]))
value := parts[1]
switch key {
case "type":
out.Type = value
default:
out.Attrs[key] = value
}
}
}
if out.Type == "" {
return nil, errors.Errorf("type is required for output")
} }
supportFile := false supportFile := false
@ -79,56 +44,49 @@ func ParseOutputs(inp []string) ([]client.ExportEntry, error) {
supportDir = !tar supportDir = !tar
case "registry": case "registry":
out.Type = client.ExporterImage out.Type = client.ExporterImage
if _, ok := out.Attrs["push"]; !ok {
out.Attrs["push"] = "true"
}
} }
dest, ok := out.Attrs["dest"]
if supportDir { if supportDir {
if !ok { if entry.Destination == "" {
return nil, errors.Errorf("dest is required for %s exporter", out.Type) return nil, errors.Errorf("dest is required for %s exporter", out.Type)
} }
if dest == "-" { if entry.Destination == "-" {
return nil, errors.Errorf("dest cannot be stdout for %s exporter", out.Type) return nil, errors.Errorf("dest cannot be stdout for %s exporter", out.Type)
} }
fi, err := os.Stat(dest) fi, err := os.Stat(entry.Destination)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "invalid destination directory: %s", dest) return nil, errors.Wrapf(err, "invalid destination directory: %s", entry.Destination)
} }
if err == nil && !fi.IsDir() { if err == nil && !fi.IsDir() {
return nil, errors.Errorf("destination directory %s is a file", dest) return nil, errors.Errorf("destination directory %s is a file", entry.Destination)
} }
out.OutputDir = dest out.OutputDir = entry.Destination
} }
if supportFile { if supportFile {
if !ok && out.Type != client.ExporterDocker { if entry.Destination == "" && out.Type != client.ExporterDocker {
dest = "-" entry.Destination = "-"
} }
if dest == "-" { if entry.Destination == "-" {
if _, err := console.ConsoleFromFile(os.Stdout); err == nil { if _, err := console.ConsoleFromFile(os.Stdout); err == nil {
return nil, errors.Errorf("dest file is required for %s exporter. refusing to write to console", out.Type) return nil, errors.Errorf("dest file is required for %s exporter. refusing to write to console", out.Type)
} }
out.Output = wrapWriteCloser(os.Stdout) out.Output = wrapWriteCloser(os.Stdout)
} else if dest != "" { } else if entry.Destination != "" {
fi, err := os.Stat(dest) fi, err := os.Stat(entry.Destination)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return nil, errors.Wrapf(err, "invalid destination file: %s", dest) return nil, errors.Wrapf(err, "invalid destination file: %s", entry.Destination)
} }
if err == nil && fi.IsDir() { if err == nil && fi.IsDir() {
return nil, errors.Errorf("destination file %s is a directory", dest) return nil, errors.Errorf("destination file %s is a directory", entry.Destination)
} }
f, err := os.Create(dest) f, err := os.Create(entry.Destination)
if err != nil { if err != nil {
return nil, errors.Errorf("failed to open %s", err) return nil, errors.Errorf("failed to open %s", err)
} }
out.Output = wrapWriteCloser(f) out.Output = wrapWriteCloser(f)
} }
} }
if supportFile || supportDir {
delete(out.Attrs, "dest")
}
outs = append(outs, out) outs = append(outs, out)
} }

@ -0,0 +1,22 @@
package pb
import (
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/secrets/secretsprovider"
)
func CreateSecrets(secrets []*Secret) (session.Attachable, error) {
fs := make([]secretsprovider.Source, 0, len(secrets))
for _, secret := range secrets {
fs = append(fs, secretsprovider.Source{
ID: secret.ID,
FilePath: secret.FilePath,
Env: secret.Env,
})
}
store, err := secretsprovider.NewStore(fs)
if err != nil {
return nil, err
}
return secretsprovider.NewSecretProvider(store), nil
}

@ -0,0 +1,18 @@
package pb
import (
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/sshforward/sshprovider"
)
func CreateSSH(ssh []*SSH) (session.Attachable, error) {
configs := make([]sshprovider.AgentConfig, 0, len(ssh))
for _, ssh := range ssh {
cfg := sshprovider.AgentConfig{
ID: ssh.ID,
Paths: append([]string{}, ssh.Paths...),
}
configs = append(configs, cfg)
}
return sshprovider.NewSSHAgentProvider(configs)
}

@ -91,18 +91,21 @@ func (c *Client) Invoke(ctx context.Context, ref string, containerConfig pb.Cont
}) })
} }
func (c *Client) Build(ctx context.Context, options pb.BuildOptions, in io.ReadCloser, w io.Writer, out console.File, progressMode string) (string, error) { 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) {
ref := identity.NewID() ref := identity.NewID()
pw, err := progress.NewPrinter(context.TODO(), w, out, progressMode) pw, err := progress.NewPrinter(context.TODO(), w, out, progressMode)
if err != nil { if err != nil {
return "", err return "", nil, err
} }
statusChan := make(chan *client.SolveStatus) statusChan := make(chan *client.SolveStatus)
statusDone := make(chan struct{}) statusDone := make(chan struct{})
eg, egCtx := errgroup.WithContext(ctx) eg, egCtx := errgroup.WithContext(ctx)
var resp *client.SolveResponse
eg.Go(func() error { eg.Go(func() error {
defer close(statusChan) defer close(statusChan)
return c.build(egCtx, ref, options, in, statusChan) var err error
resp, err = c.build(egCtx, ref, options, in, statusChan)
return err
}) })
eg.Go(func() error { eg.Go(func() error {
defer close(statusDone) defer close(statusDone)
@ -116,20 +119,27 @@ func (c *Client) Build(ctx context.Context, options pb.BuildOptions, in io.ReadC
<-statusDone <-statusDone
return pw.Wait() return pw.Wait()
}) })
return ref, eg.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) error { func (c *Client) build(ctx context.Context, ref string, options pb.BuildOptions, in io.ReadCloser, statusChan chan *client.SolveStatus) (*client.SolveResponse, error) {
eg, egCtx := errgroup.WithContext(ctx) eg, egCtx := errgroup.WithContext(ctx)
done := make(chan struct{}) done := make(chan struct{})
var resp *client.SolveResponse
eg.Go(func() error { eg.Go(func() error {
defer close(done) defer close(done)
if _, err := c.client().Build(egCtx, &pb.BuildRequest{ pbResp, err := c.client().Build(egCtx, &pb.BuildRequest{
Ref: ref, Ref: ref,
Options: &options, Options: &options,
}); err != nil { })
if err != nil {
return err return err
} }
resp = &client.SolveResponse{
ExporterResponse: pbResp.ExporterResponse,
}
return nil return nil
}) })
eg.Go(func() error { eg.Go(func() error {
@ -254,7 +264,7 @@ func (c *Client) build(ctx context.Context, ref string, options pb.BuildOptions,
return eg2.Wait() return eg2.Wait()
}) })
} }
return eg.Wait() return resp, eg.Wait()
} }
func (c *Client) client() pb.ControllerClient { func (c *Client) client() pb.ControllerClient {

@ -141,7 +141,7 @@ 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) (res *build.ResultContext, err error) { b := NewServer(func(ctx context.Context, options *controllerapi.BuildOptions, stdin io.Reader, statusChan chan *client.SolveStatus) (*client.SolveResponse, *build.ResultContext, error) {
return cbuild.RunBuild(ctx, dockerCli, *options, stdin, "quiet", statusChan) return cbuild.RunBuild(ctx, dockerCli, *options, stdin, "quiet", statusChan)
}) })
defer b.Close() defer b.Close()

@ -17,7 +17,7 @@ import (
"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) (res *build.ResultContext, err error) type BuildFunc func(ctx context.Context, options *pb.BuildOptions, stdin io.Reader, statusChan chan *client.SolveStatus) (resp *client.SolveResponse, res *build.ResultContext, err error)
func NewServer(buildFunc BuildFunc) *Server { func NewServer(buildFunc BuildFunc) *Server {
return &Server{ return &Server{
@ -150,7 +150,7 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
// Build the specified request // Build the specified request
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
defer cancel() defer cancel()
res, err := m.buildFunc(ctx, req.Options, inR, statusChan) resp, res, err := m.buildFunc(ctx, req.Options, inR, statusChan)
m.sessionMu.Lock() m.sessionMu.Lock()
if s, ok := m.session[ref]; ok { if s, ok := m.session[ref]; ok {
s.result = res s.result = res
@ -162,7 +162,12 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
} }
m.sessionMu.Unlock() m.sessionMu.Unlock()
return &pb.BuildResponse{}, err if resp == nil {
resp = &client.SolveResponse{}
}
return &pb.BuildResponse{
ExporterResponse: resp.ExporterResponse,
}, err
} }
func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer) error { func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer) error {

@ -121,7 +121,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 := c.Build(ctx, options, nil, stdout, stderr, progressMode) // TODO: support stdin, hold build ref
if err != nil { if err != nil {
fmt.Printf("failed to reload: %v\n", err) fmt.Printf("failed to reload: %v\n", err)
} else { } else {

@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"strings" "strings"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -14,66 +15,66 @@ func CanonicalizeAttest(attestType string, in string) string {
return "" return ""
} }
if b, err := strconv.ParseBool(in); err == nil { if b, err := strconv.ParseBool(in); err == nil {
return fmt.Sprintf("type=%s,enabled=%t", attestType, b) return fmt.Sprintf("type=%s,disabled=%t", attestType, !b)
} }
return fmt.Sprintf("type=%s,%s", attestType, in) return fmt.Sprintf("type=%s,%s", attestType, in)
} }
func ParseAttests(in []string) (map[string]*string, error) { func ParseAttests(in []string) ([]*controllerapi.Attest, error) {
out := map[string]*string{} out := []*controllerapi.Attest{}
found := map[string]struct{}{}
for _, in := range in { for _, in := range in {
in := in in := in
attestType, enabled, err := parseAttest(in) attest, err := parseAttest(in)
if err != nil { if err != nil {
return nil, err return nil, err
} }
k := "attest:" + attestType if _, ok := found[attest.Type]; ok {
if _, ok := out[k]; ok { return nil, errors.Errorf("duplicate attestation field %s", attest.Type)
return nil, errors.Errorf("duplicate attestation field %s", attestType)
}
if enabled {
out[k] = &in
} else {
out[k] = nil
} }
found[attest.Type] = struct{}{}
out = append(out, attest)
} }
return out, nil return out, nil
} }
func parseAttest(in string) (string, bool, error) { func parseAttest(in string) (*controllerapi.Attest, error) {
if in == "" { if in == "" {
return "", false, nil return nil, nil
} }
csvReader := csv.NewReader(strings.NewReader(in)) csvReader := csv.NewReader(strings.NewReader(in))
fields, err := csvReader.Read() fields, err := csvReader.Read()
if err != nil { if err != nil {
return "", false, err return nil, err
} }
attestType := "" attest := controllerapi.Attest{
enabled := true Attrs: in,
}
for _, field := range fields { for _, field := range fields {
key, value, ok := strings.Cut(field, "=") key, value, ok := strings.Cut(field, "=")
if !ok { if !ok {
return "", false, errors.Errorf("invalid value %s", field) return nil, errors.Errorf("invalid value %s", field)
} }
key = strings.TrimSpace(strings.ToLower(key)) key = strings.TrimSpace(strings.ToLower(key))
switch key { switch key {
case "type": case "type":
attestType = value attest.Type = value
case "enabled": case "disabled":
enabled, err = strconv.ParseBool(value) disabled, err := strconv.ParseBool(value)
if err != nil { if err != nil {
return "", false, err return nil, errors.Wrapf(err, "invalid value %s", field)
} }
attest.Disabled = disabled
} }
} }
if attestType == "" { if attest.Type == "" {
return "", false, errors.Errorf("attestation type not specified") return nil, errors.Errorf("attestation type not specified")
} }
return attestType, enabled, nil return &attest, nil
} }

@ -7,12 +7,12 @@ import (
"strings" "strings"
awsconfig "github.com/aws/aws-sdk-go-v2/config" awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/moby/buildkit/client" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func ParseCacheEntry(in []string) ([]client.CacheOptionsEntry, error) { func ParseCacheEntry(in []string) ([]*controllerapi.CacheOptionsEntry, error) {
imports := make([]client.CacheOptionsEntry, 0, len(in)) outs := make([]*controllerapi.CacheOptionsEntry, 0, len(in))
for _, in := range in { for _, in := range in {
csvReader := csv.NewReader(strings.NewReader(in)) csvReader := csv.NewReader(strings.NewReader(in))
fields, err := csvReader.Read() fields, err := csvReader.Read()
@ -21,14 +21,15 @@ func ParseCacheEntry(in []string) ([]client.CacheOptionsEntry, error) {
} }
if isRefOnlyFormat(fields) { if isRefOnlyFormat(fields) {
for _, field := range fields { for _, field := range fields {
imports = append(imports, client.CacheOptionsEntry{ outs = append(outs, &controllerapi.CacheOptionsEntry{
Type: "registry", Type: "registry",
Attrs: map[string]string{"ref": field}, Attrs: map[string]string{"ref": field},
}) })
} }
continue continue
} }
im := client.CacheOptionsEntry{
out := controllerapi.CacheOptionsEntry{
Attrs: map[string]string{}, Attrs: map[string]string{},
} }
for _, field := range fields { for _, field := range fields {
@ -40,21 +41,21 @@ func ParseCacheEntry(in []string) ([]client.CacheOptionsEntry, error) {
value := parts[1] value := parts[1]
switch key { switch key {
case "type": case "type":
im.Type = value out.Type = value
default: default:
im.Attrs[key] = value out.Attrs[key] = value
} }
} }
if im.Type == "" { if out.Type == "" {
return nil, errors.Errorf("type required form> %q", in) return nil, errors.Errorf("type required form> %q", in)
} }
if !addGithubToken(&im) { if !addGithubToken(&out) {
continue continue
} }
addAwsCredentials(&im) addAwsCredentials(&out)
imports = append(imports, im) outs = append(outs, &out)
} }
return imports, nil return outs, nil
} }
func isRefOnlyFormat(in []string) bool { func isRefOnlyFormat(in []string) bool {
@ -66,7 +67,7 @@ func isRefOnlyFormat(in []string) bool {
return true return true
} }
func addGithubToken(ci *client.CacheOptionsEntry) bool { func addGithubToken(ci *controllerapi.CacheOptionsEntry) bool {
if ci.Type != "gha" { if ci.Type != "gha" {
return true return true
} }
@ -83,7 +84,7 @@ func addGithubToken(ci *client.CacheOptionsEntry) bool {
return ci.Attrs["token"] != "" && ci.Attrs["url"] != "" return ci.Attrs["token"] != "" && ci.Attrs["url"] != ""
} }
func addAwsCredentials(ci *client.CacheOptionsEntry) { func addAwsCredentials(ci *controllerapi.CacheOptionsEntry) {
if ci.Type != "s3" { if ci.Type != "s3" {
return return
} }

@ -0,0 +1,28 @@
package buildflags
import (
"strings"
"github.com/docker/distribution/reference"
"github.com/pkg/errors"
)
func ParseContextNames(values []string) (map[string]string, error) {
if len(values) == 0 {
return nil, nil
}
result := make(map[string]string, len(values))
for _, value := range values {
kv := strings.SplitN(value, "=", 2)
if len(kv) != 2 {
return nil, errors.Errorf("invalid context value: %s, expected key=value", value)
}
named, err := reference.ParseNormalizedNamed(kv[0])
if err != nil {
return nil, errors.Wrapf(err, "invalid context name %s", kv[0])
}
name := strings.TrimSuffix(reference.FamiliarString(named), ":latest")
result[name] = kv[1]
}
return result, nil
}

@ -0,0 +1,76 @@
package buildflags
import (
"encoding/csv"
"strings"
controllerapi "github.com/docker/buildx/controller/pb"
"github.com/moby/buildkit/client"
"github.com/pkg/errors"
)
func ParseExports(inp []string) ([]*controllerapi.ExportEntry, error) {
var outs []*controllerapi.ExportEntry
if len(inp) == 0 {
return nil, nil
}
for _, s := range inp {
csvReader := csv.NewReader(strings.NewReader(s))
fields, err := csvReader.Read()
if err != nil {
return nil, err
}
out := controllerapi.ExportEntry{
Attrs: map[string]string{},
}
if len(fields) == 1 && fields[0] == s && !strings.HasPrefix(s, "type=") {
if s != "-" {
outs = append(outs, &controllerapi.ExportEntry{
Type: client.ExporterLocal,
Destination: s,
})
continue
}
out = controllerapi.ExportEntry{
Type: client.ExporterTar,
Destination: s,
}
}
if out.Type == "" {
for _, field := range fields {
parts := strings.SplitN(field, "=", 2)
if len(parts) != 2 {
return nil, errors.Errorf("invalid value %s", field)
}
key := strings.TrimSpace(strings.ToLower(parts[0]))
value := parts[1]
switch key {
case "type":
out.Type = value
default:
out.Attrs[key] = value
}
}
}
if out.Type == "" {
return nil, errors.Errorf("type is required for output")
}
if out.Type == "registry" {
out.Type = client.ExporterImage
if _, ok := out.Attrs["push"]; !ok {
out.Attrs["push"] = "true"
}
}
if dest, ok := out.Attrs["dest"]; ok {
out.Destination = dest
delete(out.Attrs, "dest")
}
outs = append(outs, &out)
}
return outs, nil
}

@ -4,35 +4,30 @@ import (
"encoding/csv" "encoding/csv"
"strings" "strings"
"github.com/moby/buildkit/session" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/moby/buildkit/session/secrets/secretsprovider"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func ParseSecretSpecs(sl []string) (session.Attachable, error) { func ParseSecretSpecs(sl []string) ([]*controllerapi.Secret, error) {
fs := make([]secretsprovider.Source, 0, len(sl)) fs := make([]*controllerapi.Secret, 0, len(sl))
for _, v := range sl { for _, v := range sl {
s, err := parseSecret(v) s, err := parseSecret(v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fs = append(fs, *s) fs = append(fs, s)
} }
store, err := secretsprovider.NewStore(fs) return fs, nil
if err != nil {
return nil, err
}
return secretsprovider.NewSecretProvider(store), nil
} }
func parseSecret(value string) (*secretsprovider.Source, error) { func parseSecret(value string) (*controllerapi.Secret, error) {
csvReader := csv.NewReader(strings.NewReader(value)) csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read() fields, err := csvReader.Read()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to parse csv secret") return nil, errors.Wrap(err, "failed to parse csv secret")
} }
fs := secretsprovider.Source{} fs := controllerapi.Secret{}
var typ string var typ string
for _, field := range fields { for _, field := range fields {

@ -3,32 +3,27 @@ package buildflags
import ( import (
"strings" "strings"
"github.com/moby/buildkit/session" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/moby/buildkit/session/sshforward/sshprovider"
"github.com/moby/buildkit/util/gitutil" "github.com/moby/buildkit/util/gitutil"
) )
func ParseSSHSpecs(sl []string) (session.Attachable, error) { func ParseSSHSpecs(sl []string) ([]*controllerapi.SSH, error) {
configs := make([]sshprovider.AgentConfig, 0, len(sl)) var outs []*controllerapi.SSH
for _, v := range sl { if len(sl) == 0 {
c, err := parseSSH(v) return nil, nil
if err != nil {
return nil, err
}
configs = append(configs, *c)
} }
return sshprovider.NewSSHAgentProvider(configs)
}
func parseSSH(value string) (*sshprovider.AgentConfig, error) { for _, s := range sl {
parts := strings.SplitN(value, "=", 2) parts := strings.SplitN(s, "=", 2)
cfg := sshprovider.AgentConfig{ out := controllerapi.SSH{
ID: parts[0], ID: parts[0],
} }
if len(parts) > 1 { if len(parts) > 1 {
cfg.Paths = strings.Split(parts[1], ",") out.Paths = strings.Split(parts[1], ",")
}
outs = append(outs, &out)
} }
return &cfg, nil return outs, nil
} }
// IsGitSSH returns true if the given repo URL is accessed over ssh // IsGitSSH returns true if the given repo URL is accessed over ssh

Loading…
Cancel
Save