Compare commits

...

34 Commits

Author SHA1 Message Date
Tõnis Tiigi
9b0575b589 Merge pull request #2766 from tonistiigi/prune-caps-detection
prune: detect if buildkit supports newer storage filters
2024-10-29 13:55:29 -07:00
Tonis Tiigi
9f3a578149 prune: detect if buildkit supports newer storage filters
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-10-29 13:18:04 -07:00
CrazyMax
14b31d8b77 Merge pull request #2765 from crazy-max/ci-fix-content-read
ci: keep contents read permissions in jobs
2024-10-29 19:04:45 +01:00
CrazyMax
e26911f403 ci: keep contents read permissions in jobs
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-29 18:48:42 +01:00
Tõnis Tiigi
cd8d61a9d7 Merge pull request #2763 from neumantm/feat/listWithoutBuilder
Skip Builder Init For Bake List Flags
2024-10-29 10:20:58 -07:00
Tõnis Tiigi
3a56161d03 Merge pull request #2761 from crazy-max/fix-workflow-perms
ci: fix workflow permissions
2024-10-29 10:19:04 -07:00
Tim Neumann
0fd935b0ca Skip Builder Init For Bake List Flags
Add the flags --list-targets and --list-variables to the cases
where initializing the builder can be skipped.

This allows the listing of targets and variables
when no builder is available.

Resolves: docker/buildx#2755
Signed-off-by: Tim Neumann <git@neumann-tim.de>
2024-10-29 10:34:20 +01:00
CrazyMax
704b2cc52d Merge pull request #2760 from tonistiigi/update-compose-v2.4.1
vendor: update compose to v2.4.1
2024-10-29 10:28:24 +01:00
CrazyMax
6b2dc8ce56 ci: fix workflow permissions
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-29 09:48:47 +01:00
Tonis Tiigi
a585faf3d2 vendor: update compose to v2.4.1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-10-28 17:26:28 -07:00
Tõnis Tiigi
181348397c Merge pull request #2742 from tonistiigi/otel-build
build: add OTEL span around build function
2024-10-28 16:16:08 -07:00
Tõnis Tiigi
ad371e428e Merge pull request #2759 from tonistiigi/vendor-buildkit-v0.17.0-rc2
vendor: update buildkit to v0.17.0-rc2
2024-10-28 16:15:19 -07:00
Tonis Tiigi
f35dae3726 build: add OTEL span around build function
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-10-28 15:53:22 -07:00
Tonis Tiigi
6fcc6853d9 vendor: update buildkit to v0.17.0-rc2
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2024-10-28 15:39:50 -07:00
Tõnis Tiigi
202c390fca Merge pull request #2722 from crazy-max/test-details-link-exp
build: fix build details link in experimental mode
2024-10-28 10:03:10 -07:00
Tõnis Tiigi
2bdf451b68 Merge pull request #2754 from crazy-max/call-localstate
build: don't generate local state for subrequests
2024-10-25 11:06:22 -07:00
CrazyMax
658ed584c7 Merge pull request #2746 from jsternberg/buildx-profiles
pprof: take cpu and memory profiles by setting environment variables
2024-10-25 15:52:35 +02:00
CrazyMax
886ae21e93 build: don't generate local state for subrequests
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-25 11:06:25 +02:00
Jonathan A. Sternberg
cf7a9aa084 pprof: take cpu and memory profiles by setting environment variables
When run in standalone mode, the environment variables
`DOCKER_BUILDX_CPU_PROFILE` and `DOCKER_BUILDX_MEM_PROFILE` will cause
profiles to be written by the CLI.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2024-10-24 09:56:27 -05:00
CrazyMax
eb15c667b9 controller: rename ref to sessionID and set buildRef back to ref
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-24 15:37:18 +02:00
CrazyMax
1060328a96 build: fix build details link in experimental mode
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-23 20:31:17 +02:00
Tõnis Tiigi
746eadd16e Merge pull request #2745 from crazy-max/detect-sudo
config: fix file/folder ownership
2024-10-23 10:04:38 -07:00
CrazyMax
f89f861999 config: fix file/folder ownership
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-23 18:23:14 +02:00
Tõnis Tiigi
08a973a148 Merge pull request #2741 from crazy-max/cli-fix-unknown-command
cli: error out on unknown command
2024-10-23 08:47:44 -07:00
CrazyMax
cc286e2ef5 cli: error out on unknown command
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2024-10-18 14:04:16 +02:00
CrazyMax
9f0ebd2643 Merge pull request #2744 from dvdksn/bake-docs-pull-bool
docs: bake pull attr is a boolean
2024-10-17 10:36:10 +02:00
David Karlsson
680cdf1179 docs: bake pull attr is a boolean
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-17 10:26:29 +02:00
Tõnis Tiigi
8d32cabc22 Merge pull request #2740 from dvdksn/src-attr-secret-env
docs: clarify options for secret types (file, env)
2024-10-16 12:20:58 -07:00
David Karlsson
239930c998 chore: fix FromAsCasing in Dockerfile example
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-16 15:58:34 +02:00
David Karlsson
8d7f69883f docs: clarify options for secret types (file, env)
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-10-16 15:57:58 +02:00
Tõnis Tiigi
1de332530f Merge pull request #2729 from thaJeztah/touchup_security
touch-up security policy
2024-10-10 09:57:55 -07:00
CrazyMax
65c4756473 Merge pull request #2728 from thaJeztah/gha_permissions
gha: set default permissions to "contents: read"
2024-10-09 09:43:33 +02:00
Sebastiaan van Stijn
1ce3e6a221 touch-up security policy
Touch-up the security policy to make the OpenSSF scorecard
slightly happier;
https://securityscorecards.dev/viewer/?uri=github.com/docker/buildx

    Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-09 01:22:26 +02:00
Sebastiaan van Stijn
b1a13bb740 gha: set default permissions to "contents: read"
make the OpenSSF scorecard slightly happier;
https://securityscorecards.dev/viewer/?uri=github.com/docker/buildx

    Warn: no topLevel permission defined: .github/workflows/build.yml:1
    Warn: topLevel 'security-events' permission set to 'write': .github/workflows/codeql.yml:13
    Warn: no topLevel permission defined: .github/workflows/docs-release.yml:1
    Warn: no topLevel permission defined: .github/workflows/docs-upstream.yml:1
    Warn: no topLevel permission defined: .github/workflows/e2e.yml:1
    Warn: no topLevel permission defined: .github/workflows/labeler.yml:1
    Warn: no topLevel permission defined: .github/workflows/validate.yml:1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-09 01:07:18 +02:00
284 changed files with 7881 additions and 6315 deletions

50
.github/SECURITY.md vendored
View File

@@ -1,12 +1,44 @@
# Reporting security issues # Security Policy
The project maintainers take security seriously. If you discover a security The maintainers of Docker Buildx take security seriously. If you discover
issue, please bring it to their attention right away! a security issue, please bring it to their attention right away!
**Please _DO NOT_ file a public issue**, instead send your report privately to ## Reporting a Vulnerability
[security@docker.com](mailto:security@docker.com).
Security reports are greatly appreciated, and we will publicly thank you for it. Please **DO NOT** file a public issue, instead send your report privately
We also like to send gifts&mdash;if you're into schwag, make sure to let to [security@docker.com](mailto:security@docker.com).
us know. We currently do not offer a paid security bounty program, but are not
ruling it out in the future. Reporter(s) can expect a response within 72 hours, acknowledging the issue was
received.
## Review Process
After receiving the report, an initial triage and technical analysis is
performed to confirm the report and determine its scope. We may request
additional information in this stage of the process.
Once a reviewer has confirmed the relevance of the report, a draft security
advisory will be created on GitHub. The draft advisory will be used to discuss
the issue with maintainers, the reporter(s), and where applicable, other
affected parties under embargo.
If the vulnerability is accepted, a timeline for developing a patch, public
disclosure, and patch release will be determined. If there is an embargo period
on public disclosure before the patch release, the reporter(s) are expected to
participate in the discussion of the timeline and abide by agreed upon dates
for public disclosure.
## Accreditation
Security reports are greatly appreciated and we will publicly thank you,
although we will keep your name confidential if you request it. We also like to
send gifts - if you're into swag, make sure to let us know. We do not currently
offer a paid security bounty program at this time.
## Supported Versions
Once a new feature release is cut, support for the previous feature release is
discontinued. An exception may be made for urgent security releases that occur
shortly after a new feature release. Buildx does not offer LTS (Long-Term Support)
releases. Refer to the [Support Policy](https://github.com/docker/buildx/blob/master/PROJECT.md#support-policy)
for further details.

View File

@@ -1,5 +1,14 @@
name: build name: build
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
@@ -218,10 +227,10 @@ jobs:
govulncheck: govulncheck:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
permissions: permissions:
# same as global permission
contents: read
# required to write sarif report # required to write sarif report
security-events: write security-events: write
# required to check out the repository
contents: read
steps: steps:
- -
name: Checkout name: Checkout
@@ -365,6 +374,8 @@ jobs:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
if: ${{ github.ref == 'refs/heads/master' && github.repository == 'docker/buildx' }} if: ${{ github.ref == 'refs/heads/master' && github.repository == 'docker/buildx' }}
permissions: permissions:
# same as global permission
contents: read
# required to write sarif report # required to write sarif report
security-events: write security-events: write
needs: needs:
@@ -395,6 +406,9 @@ jobs:
release: release:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
permissions:
# required to create GitHub release
contents: write
needs: needs:
- test-integration - test-integration
- test-unit - test-unit

View File

@@ -1,5 +1,14 @@
name: codeql name: codeql
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
on: on:
push: push:
branches: branches:
@@ -7,17 +16,16 @@ on:
- 'v[0-9]*' - 'v[0-9]*'
pull_request: pull_request:
permissions:
actions: read
contents: read
security-events: write
env: env:
GO_VERSION: "1.22" GO_VERSION: "1.22"
jobs: jobs:
codeql: codeql:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
permissions:
contents: read
actions: read
security-events: write
steps: steps:
- -
name: Checkout name: Checkout

View File

@@ -1,5 +1,14 @@
name: docs-release name: docs-release
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@@ -14,6 +23,9 @@ jobs:
open-pr: open-pr:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
if: ${{ (github.event.release.prerelease != true || github.event.inputs.tag != '') && github.repository == 'docker/buildx' }} if: ${{ (github.event.release.prerelease != true || github.event.inputs.tag != '') && github.repository == 'docker/buildx' }}
permissions:
contents: write
pull-requests: write
steps: steps:
- -
name: Checkout docs repo name: Checkout docs repo

View File

@@ -3,6 +3,15 @@
# https://github.com/docker/docker.github.io/blob/98c7c9535063ae4cd2cd0a31478a21d16d2f07a3/docker-bake.hcl#L34-L36 # https://github.com/docker/docker.github.io/blob/98c7c9535063ae4cd2cd0a31478a21d16d2f07a3/docker-bake.hcl#L34-L36
name: docs-upstream name: docs-upstream
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -1,5 +1,14 @@
name: e2e name: e2e
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -1,5 +1,14 @@
name: labeler name: labeler
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
@@ -9,10 +18,12 @@ on:
jobs: jobs:
labeler: labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# same as global permission
contents: read
# required for writing labels
pull-requests: write
steps: steps:
- -
name: Run name: Run

View File

@@ -1,5 +1,14 @@
name: validate name: validate
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true

View File

@@ -151,11 +151,11 @@ func toRepoOnly(in string) (string, error) {
return strings.Join(out, ","), nil return strings.Join(out, ","), nil
} }
func Build(ctx context.Context, nodes []builder.Node, opts map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer) (resp map[string]*client.SolveResponse, err error) { func Build(ctx context.Context, nodes []builder.Node, opts map[string]Options, docker *dockerutil.Client, cfg *confutil.Config, w progress.Writer) (resp map[string]*client.SolveResponse, err error) {
return BuildWithResultHandler(ctx, nodes, opts, docker, configDir, w, nil) return BuildWithResultHandler(ctx, nodes, opts, docker, cfg, w, nil)
} }
func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[string]Options, docker *dockerutil.Client, configDir string, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultHandle)) (resp map[string]*client.SolveResponse, err error) { func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[string]Options, docker *dockerutil.Client, cfg *confutil.Config, w progress.Writer, resultHandleFunc func(driverIndex int, rCtx *ResultHandle)) (resp map[string]*client.SolveResponse, err error) {
if len(nodes) == 0 { if len(nodes) == 0 {
return nil, errors.Errorf("driver required for build") return nil, errors.Errorf("driver required for build")
} }
@@ -234,12 +234,12 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
return nil, err return nil, err
} }
localOpt := opt localOpt := opt
so, release, err := toSolveOpt(ctx, np.Node(), multiDriver, &localOpt, gatewayOpts, configDir, w, docker) so, release, err := toSolveOpt(ctx, np.Node(), multiDriver, &localOpt, gatewayOpts, cfg, w, docker)
opts[k] = localOpt opts[k] = localOpt
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := saveLocalState(so, k, opt, np.Node(), configDir); err != nil { if err := saveLocalState(so, k, opt, np.Node(), cfg); err != nil {
return nil, err return nil, err
} }
addGitAttrs(so) addGitAttrs(so)
@@ -500,7 +500,9 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
resultHandle, rr, err = NewResultHandle(ctx, cc, *so, "buildx", buildFunc, ch) resultHandle, rr, err = NewResultHandle(ctx, cc, *so, "buildx", buildFunc, ch)
resultHandleFunc(dp.driverIndex, resultHandle) resultHandleFunc(dp.driverIndex, resultHandle)
} else { } else {
span, ctx := tracing.StartSpan(ctx, "build")
rr, err = c.Build(ctx, *so, "buildx", buildFunc, ch) rr, err = c.Build(ctx, *so, "buildx", buildFunc, ch)
tracing.FinishWithError(span, err)
} }
if !so.Internal && desktop.BuildBackendEnabled() && node.Driver.HistoryAPISupported(ctx) { if !so.Internal && desktop.BuildBackendEnabled() && node.Driver.HistoryAPISupported(ctx) {
if err != nil { if err != nil {

View File

@@ -5,12 +5,13 @@ import (
"github.com/docker/buildx/builder" "github.com/docker/buildx/builder"
"github.com/docker/buildx/localstate" "github.com/docker/buildx/localstate"
"github.com/docker/buildx/util/confutil"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
) )
func saveLocalState(so *client.SolveOpt, target string, opts Options, node builder.Node, configDir string) error { func saveLocalState(so *client.SolveOpt, target string, opts Options, node builder.Node, cfg *confutil.Config) error {
var err error var err error
if so.Ref == "" { if so.Ref == "" || opts.CallFunc != nil {
return nil return nil
} }
lp := opts.Inputs.ContextPath lp := opts.Inputs.ContextPath
@@ -30,7 +31,7 @@ func saveLocalState(so *client.SolveOpt, target string, opts Options, node build
if lp == "" && dp == "" { if lp == "" && dp == "" {
return nil return nil
} }
l, err := localstate.New(configDir) l, err := localstate.New(cfg)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -35,7 +35,7 @@ import (
"github.com/tonistiigi/fsutil" "github.com/tonistiigi/fsutil"
) )
func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *Options, bopts gateway.BuildOpts, configDir string, pw progress.Writer, docker *dockerutil.Client) (_ *client.SolveOpt, release func(), err error) { func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *Options, bopts gateway.BuildOpts, cfg *confutil.Config, pw progress.Writer, docker *dockerutil.Client) (_ *client.SolveOpt, release func(), err error) {
nodeDriver := node.Driver nodeDriver := node.Driver
defers := make([]func(), 0, 2) defers := make([]func(), 0, 2)
releaseF := func() { releaseF := func() {
@@ -271,7 +271,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *O
// add node identifier to shared key if one was specified // add node identifier to shared key if one was specified
if so.SharedKey != "" { if so.SharedKey != "" {
so.SharedKey += ":" + confutil.TryNodeIdentifier(configDir) so.SharedKey += ":" + cfg.TryNodeIdentifier()
} }
if opt.Pull { if opt.Pull {

View File

@@ -439,7 +439,7 @@ func Create(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts Cre
if buildkitdConfigFile == "" { if buildkitdConfigFile == "" {
// if buildkit daemon config is not provided, check if the default one // if buildkit daemon config is not provided, check if the default one
// is available and use it // is available and use it
if f, ok := confutil.DefaultConfigFile(dockerCli); ok { if f, ok := confutil.NewConfig(dockerCli).BuildKitConfigFile(); ok {
buildkitdConfigFile = f buildkitdConfigFile = f
} }
} }
@@ -584,7 +584,7 @@ func Leave(ctx context.Context, txn *store.Txn, dockerCli command.Cli, opts Leav
return err return err
} }
ls, err := localstate.New(confutil.ConfigDir(dockerCli)) ls, err := localstate.New(confutil.NewConfig(dockerCli))
if err != nil { if err != nil {
return err return err
} }

75
cmd/buildx/debug.go Normal file
View File

@@ -0,0 +1,75 @@
package main
import (
"context"
"os"
"runtime"
"runtime/pprof"
"github.com/moby/buildkit/util/bklog"
"github.com/sirupsen/logrus"
)
func setupDebugProfiles(ctx context.Context) (stop func()) {
var stopFuncs []func()
if fn := setupCPUProfile(ctx); fn != nil {
stopFuncs = append(stopFuncs, fn)
}
if fn := setupHeapProfile(ctx); fn != nil {
stopFuncs = append(stopFuncs, fn)
}
return func() {
for _, fn := range stopFuncs {
fn()
}
}
}
func setupCPUProfile(ctx context.Context) (stop func()) {
if cpuProfile := os.Getenv("BUILDX_CPU_PROFILE"); cpuProfile != "" {
f, err := os.Create(cpuProfile)
if err != nil {
bklog.G(ctx).Warn("could not create cpu profile", logrus.WithError(err))
return nil
}
if err := pprof.StartCPUProfile(f); err != nil {
bklog.G(ctx).Warn("could not start cpu profile", logrus.WithError(err))
_ = f.Close()
return nil
}
return func() {
pprof.StopCPUProfile()
if err := f.Close(); err != nil {
bklog.G(ctx).Warn("could not close file for cpu profile", logrus.WithError(err))
}
}
}
return nil
}
func setupHeapProfile(ctx context.Context) (stop func()) {
if heapProfile := os.Getenv("BUILDX_MEM_PROFILE"); heapProfile != "" {
// Memory profile is only created on stop.
return func() {
f, err := os.Create(heapProfile)
if err != nil {
bklog.G(ctx).Warn("could not create memory profile", logrus.WithError(err))
return
}
// get up-to-date statistics
runtime.GC()
if err := pprof.WriteHeapProfile(f); err != nil {
bklog.G(ctx).Warn("could not write memory profile", logrus.WithError(err))
}
if err := f.Close(); err != nil {
bklog.G(ctx).Warn("could not close file for memory profile", logrus.WithError(err))
}
}
}
return nil
}

View File

@@ -6,6 +6,7 @@ import (
"os" "os"
"github.com/docker/buildx/commands" "github.com/docker/buildx/commands"
controllererrors "github.com/docker/buildx/controller/errdefs"
"github.com/docker/buildx/util/desktop" "github.com/docker/buildx/util/desktop"
"github.com/docker/buildx/version" "github.com/docker/buildx/version"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
@@ -16,6 +17,7 @@ import (
cliflags "github.com/docker/cli/cli/flags" cliflags "github.com/docker/cli/cli/flags"
"github.com/moby/buildkit/solver/errdefs" "github.com/moby/buildkit/solver/errdefs"
"github.com/moby/buildkit/util/stack" "github.com/moby/buildkit/util/stack"
"github.com/pkg/errors"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
//nolint:staticcheck // vendored dependencies may still use this //nolint:staticcheck // vendored dependencies may still use this
@@ -73,6 +75,16 @@ func runPlugin(cmd *command.DockerCli) error {
}) })
} }
func run(cmd *command.DockerCli) error {
stopProfiles := setupDebugProfiles(context.TODO())
defer stopProfiles()
if plugin.RunningStandalone() {
return runStandalone(cmd)
}
return runPlugin(cmd)
}
func main() { func main() {
cmd, err := command.NewDockerCli() cmd, err := command.NewDockerCli()
if err != nil { if err != nil {
@@ -80,15 +92,11 @@ func main() {
os.Exit(1) os.Exit(1)
} }
if plugin.RunningStandalone() { if err = run(cmd); err == nil {
err = runStandalone(cmd)
} else {
err = runPlugin(cmd)
}
if err == nil {
return return
} }
// Check the error from the run function above.
if sterr, ok := err.(cli.StatusError); ok { if sterr, ok := err.(cli.StatusError); ok {
if sterr.Status != "" { if sterr.Status != "" {
fmt.Fprintln(cmd.Err(), sterr.Status) fmt.Fprintln(cmd.Err(), sterr.Status)
@@ -109,8 +117,15 @@ func main() {
} else { } else {
fmt.Fprintf(cmd.Err(), "ERROR: %v\n", err) fmt.Fprintf(cmd.Err(), "ERROR: %v\n", err)
} }
if ebr, ok := err.(*desktop.ErrorWithBuildRef); ok {
var ebr *desktop.ErrorWithBuildRef
if errors.As(err, &ebr) {
ebr.Print(cmd.Err()) ebr.Print(cmd.Err())
} else {
var be *controllererrors.BuildError
if errors.As(err, &be) {
be.PrintBuildDetails(cmd.Err())
}
} }
os.Exit(1) os.Exit(1)

View File

@@ -116,7 +116,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
// instance only needed for reading remote bake files or building // instance only needed for reading remote bake files or building
var driverType string var driverType string
if url != "" || !in.printOnly { if url != "" || !(in.printOnly || in.listTargets || in.listVars) {
b, err := builder.New(dockerCli, b, err := builder.New(dockerCli,
builder.WithName(in.builder), builder.WithName(in.builder),
builder.WithContextPathHash(contextPathHash), builder.WithContextPathHash(contextPathHash),
@@ -265,7 +265,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
} }
done := timeBuildCommand(mp, attributes) done := timeBuildCommand(mp, attributes)
resp, retErr := build.Build(ctx, nodes, bo, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), printer) resp, retErr := build.Build(ctx, nodes, bo, dockerutil.NewClient(dockerCli), confutil.NewConfig(dockerCli), printer)
if err := printer.Wait(); retErr == nil { if err := printer.Wait(); retErr == nil {
retErr = err retErr = err
} }
@@ -464,13 +464,19 @@ func saveLocalStateGroup(dockerCli command.Cli, in bakeOptions, targets []string
groupRef := identity.NewID() groupRef := identity.NewID()
refs := make([]string, 0, len(bo)) refs := make([]string, 0, len(bo))
for k, b := range bo { for k, b := range bo {
if b.CallFunc != nil {
continue
}
b.Ref = identity.NewID() b.Ref = identity.NewID()
b.GroupRef = groupRef b.GroupRef = groupRef
b.ProvenanceResponseMode = prm b.ProvenanceResponseMode = prm
refs = append(refs, b.Ref) refs = append(refs, b.Ref)
bo[k] = b bo[k] = b
} }
l, err := localstate.New(confutil.ConfigDir(dockerCli)) if len(refs) == 0 {
return nil
}
l, err := localstate.New(confutil.NewConfig(dockerCli))
if err != nil { if err != nil {
return err return err
} }
@@ -621,7 +627,7 @@ func bakeMetricAttributes(dockerCli command.Cli, driverType, url, cmdContext str
commandNameAttribute.String("bake"), commandNameAttribute.String("bake"),
attribute.Stringer(string(commandOptionsHash), &bakeOptionsHash{ attribute.Stringer(string(commandOptionsHash), &bakeOptionsHash{
bakeOptions: options, bakeOptions: options,
configDir: confutil.ConfigDir(dockerCli), cfg: confutil.NewConfig(dockerCli),
url: url, url: url,
cmdContext: cmdContext, cmdContext: cmdContext,
targets: targets, targets: targets,
@@ -633,7 +639,7 @@ func bakeMetricAttributes(dockerCli command.Cli, driverType, url, cmdContext str
type bakeOptionsHash struct { type bakeOptionsHash struct {
*bakeOptions *bakeOptions
configDir string cfg *confutil.Config
url string url string
cmdContext string cmdContext string
targets []string targets []string
@@ -657,7 +663,7 @@ func (o *bakeOptionsHash) String() string {
joinedFiles := strings.Join(files, ",") joinedFiles := strings.Join(files, ",")
joinedTargets := strings.Join(targets, ",") joinedTargets := strings.Join(targets, ",")
salt := confutil.TryNodeIdentifier(o.configDir) salt := o.cfg.TryNodeIdentifier()
h := sha256.New() h := sha256.New()
for _, s := range []string{url, cmdContext, joinedFiles, joinedTargets, salt} { for _, s := range []string{url, cmdContext, joinedFiles, joinedTargets, salt} {

View File

@@ -238,7 +238,7 @@ func buildMetricAttributes(dockerCli command.Cli, driverType string, options *bu
commandNameAttribute.String("build"), commandNameAttribute.String("build"),
attribute.Stringer(string(commandOptionsHash), &buildOptionsHash{ attribute.Stringer(string(commandOptionsHash), &buildOptionsHash{
buildOptions: options, buildOptions: options,
configDir: confutil.ConfigDir(dockerCli), cfg: confutil.NewConfig(dockerCli),
}), }),
driverNameAttribute.String(options.builder), driverNameAttribute.String(options.builder),
driverTypeAttribute.String(driverType), driverTypeAttribute.String(driverType),
@@ -250,7 +250,7 @@ func buildMetricAttributes(dockerCli command.Cli, driverType string, options *bu
// the fmt.Stringer interface. // the fmt.Stringer interface.
type buildOptionsHash struct { type buildOptionsHash struct {
*buildOptions *buildOptions
configDir string cfg *confutil.Config
result string result string
resultOnce sync.Once resultOnce sync.Once
} }
@@ -267,7 +267,7 @@ func (o *buildOptionsHash) String() string {
if contextPath != "-" && osutil.IsLocalDir(contextPath) { if contextPath != "-" && osutil.IsLocalDir(contextPath) {
contextPath = osutil.ToAbs(contextPath) contextPath = osutil.ToAbs(contextPath)
} }
salt := confutil.TryNodeIdentifier(o.configDir) salt := o.cfg.TryNodeIdentifier()
h := sha256.New() h := sha256.New()
for _, s := range []string{target, contextPath, dockerfile, salt} { for _, s := range []string{target, contextPath, dockerfile, salt} {

View File

@@ -10,11 +10,12 @@ type RootOptions struct {
Builder *string Builder *string
} }
func RootCmd(dockerCli command.Cli, opts RootOptions) *cobra.Command { func RootCmd(rootcmd *cobra.Command, dockerCli command.Cli, opts RootOptions) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "imagetools", Use: "imagetools",
Short: "Commands to work on images in registry", Short: "Commands to work on images in registry",
ValidArgsFunction: completion.Disable, ValidArgsFunction: completion.Disable,
RunE: rootcmd.RunE,
} }
cmd.AddCommand( cmd.AddCommand(

View File

@@ -16,6 +16,9 @@ import (
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
gateway "github.com/moby/buildkit/frontend/gateway/client"
pb "github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/apicaps"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@@ -107,6 +110,17 @@ func runPrune(ctx context.Context, dockerCli command.Cli, opts pruneOptions) err
if err != nil { if err != nil {
return err return err
} }
// check if the client supports newer prune options
if opts.maxUsedSpace.Value() != 0 || opts.minFreeSpace.Value() != 0 {
caps, err := loadLLBCaps(ctx, c)
if err != nil {
return errors.Wrap(err, "failed to load buildkit capabilities for prune")
}
if caps.Supports(pb.CapGCFreeSpaceFilter) != nil {
return errors.New("buildkit v0.17.0+ is required for max-used-space and min-free-space filters")
}
}
popts := []client.PruneOption{ popts := []client.PruneOption{
client.WithKeepOpt(pi.KeepDuration, opts.reservedSpace.Value(), opts.maxUsedSpace.Value(), opts.minFreeSpace.Value()), client.WithKeepOpt(pi.KeepDuration, opts.reservedSpace.Value(), opts.maxUsedSpace.Value(), opts.minFreeSpace.Value()),
client.WithFilter(pi.Filter), client.WithFilter(pi.Filter),
@@ -133,6 +147,17 @@ func runPrune(ctx context.Context, dockerCli command.Cli, opts pruneOptions) err
return nil return nil
} }
func loadLLBCaps(ctx context.Context, c *client.Client) (apicaps.CapSet, error) {
var caps apicaps.CapSet
_, err := c.Build(ctx, client.SolveOpt{
Internal: true,
}, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
caps = c.BuildOpts().LLBCaps
return nil, nil
}, nil)
return caps, err
}
func pruneCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { func pruneCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
options := pruneOptions{filter: opts.NewFilterOpt()} options := pruneOptions{filter: opts.NewFilterOpt()}

View File

@@ -1,6 +1,7 @@
package commands package commands
import ( import (
"fmt"
"os" "os"
debugcmd "github.com/docker/buildx/commands/debug" debugcmd "github.com/docker/buildx/commands/debug"
@@ -36,13 +37,22 @@ func NewRootCmd(name string, isPlugin bool, dockerCli command.Cli) *cobra.Comman
if opt.debug { if opt.debug {
debug.Enable() debug.Enable()
} }
cmd.SetContext(appcontext.Context()) cmd.SetContext(appcontext.Context())
if !isPlugin { if !isPlugin {
return nil return nil
} }
return plugin.PersistentPreRunE(cmd, args) return plugin.PersistentPreRunE(cmd, args)
}, },
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return cmd.Help()
}
_ = cmd.Help()
return cli.StatusError{
StatusCode: 1,
Status: fmt.Sprintf("ERROR: unknown command: %q", args[0]),
}
},
} }
if !isPlugin { if !isPlugin {
// match plugin behavior for standalone mode // match plugin behavior for standalone mode
@@ -95,7 +105,7 @@ func addCommands(cmd *cobra.Command, opts *rootOptions, dockerCli command.Cli) {
versionCmd(dockerCli), versionCmd(dockerCli),
pruneCmd(dockerCli, opts), pruneCmd(dockerCli, opts),
duCmd(dockerCli, opts), duCmd(dockerCli, opts),
imagetoolscmd.RootCmd(dockerCli, imagetoolscmd.RootOptions{Builder: &opts.builder}), imagetoolscmd.RootCmd(cmd, dockerCli, imagetoolscmd.RootOptions{Builder: &opts.builder}),
) )
if confutil.IsExperimental() { if confutil.IsExperimental() {
cmd.AddCommand(debugcmd.RootCmd(dockerCli, cmd.AddCommand(debugcmd.RootCmd(dockerCli,

View File

@@ -214,7 +214,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, nodes []builder.No
if generateResult { if generateResult {
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, func(driverIndex int, gotRes *build.ResultHandle) { resp, err = build.BuildWithResultHandler(ctx, nodes, opts, dockerutil.NewClient(dockerCli), confutil.NewConfig(dockerCli), progress, func(driverIndex int, gotRes *build.ResultHandle) {
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
if res == nil || driverIndex < idx { if res == nil || driverIndex < idx {
@@ -222,7 +222,7 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, nodes []builder.No
} }
}) })
} else { } else {
resp, err = build.Build(ctx, nodes, opts, dockerutil.NewClient(dockerCli), confutil.ConfigDir(dockerCli), progress) resp, err = build.Build(ctx, nodes, opts, dockerutil.NewClient(dockerCli), confutil.NewConfig(dockerCli), progress)
} }
if err != nil { if err != nil {
return nil, res, err return nil, res, err

View File

@@ -1,7 +1,10 @@
package errdefs package errdefs
import ( import (
"io"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
"github.com/docker/buildx/util/desktop"
"github.com/moby/buildkit/util/grpcerrors" "github.com/moby/buildkit/util/grpcerrors"
) )
@@ -22,11 +25,22 @@ func (e *BuildError) ToProto() grpcerrors.TypedErrorProto {
return e.Build return e.Build
} }
func WrapBuild(err error, ref string) error { func (e *BuildError) PrintBuildDetails(w io.Writer) error {
if e.Ref == "" {
return nil
}
ebr := &desktop.ErrorWithBuildRef{
Ref: e.Ref,
Err: e.error,
}
return ebr.Print(w)
}
func WrapBuild(err error, sessionID string, ref string) error {
if err == nil { if err == nil {
return nil return nil
} }
return &BuildError{Build: &Build{Ref: ref}, error: err} return &BuildError{Build: &Build{SessionID: sessionID, Ref: ref}, error: err}
} }
func (b *Build) WrapError(err error) error { func (b *Build) WrapError(err error) error {

View File

@@ -25,7 +25,8 @@ type Build struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
Ref string `protobuf:"bytes,2,opt,name=Ref,proto3" json:"Ref,omitempty"`
} }
func (x *Build) Reset() { func (x *Build) Reset() {
@@ -60,6 +61,13 @@ func (*Build) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescGZIP(), []int{0} return file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescGZIP(), []int{0}
} }
func (x *Build) GetSessionID() string {
if x != nil {
return x.SessionID
}
return ""
}
func (x *Build) GetRef() string { func (x *Build) GetRef() string {
if x != nil { if x != nil {
return x.Ref return x.Ref
@@ -75,12 +83,14 @@ var file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDesc = []b
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x65, 0x72, 0x72, 0x64, 0x65, 0x66, 0x73, 0x2f, 0x65, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x65, 0x72, 0x72, 0x64, 0x65, 0x66, 0x73, 0x2f, 0x65, 0x72,
0x72, 0x64, 0x65, 0x66, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x64, 0x6f, 0x63, 0x72, 0x64, 0x65, 0x66, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x64, 0x6f, 0x63,
0x6b, 0x65, 0x72, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x65, 0x72, 0x72, 0x64, 0x65, 0x6b, 0x65, 0x72, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x65, 0x72, 0x72, 0x64, 0x65,
0x66, 0x73, 0x22, 0x19, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x66, 0x73, 0x22, 0x37, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x53,
0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x42, 0x2d, 0x5a, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66,
0x65, 0x72, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x42, 0x2d, 0x5a, 0x2b, 0x67,
0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x65, 0x72, 0x72, 0x64, 0x65, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72,
0x6f, 0x74, 0x6f, 0x33, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2f, 0x65, 0x72, 0x72, 0x64, 0x65, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
} }
var ( var (

View File

@@ -5,5 +5,6 @@ package docker.buildx.errdefs;
option go_package = "github.com/docker/buildx/controller/errdefs"; option go_package = "github.com/docker/buildx/controller/errdefs";
message Build { message Build {
string Ref = 1; string SessionID = 1;
string Ref = 2;
} }

View File

@@ -24,6 +24,7 @@ func (m *Build) CloneVT() *Build {
return (*Build)(nil) return (*Build)(nil)
} }
r := new(Build) r := new(Build)
r.SessionID = m.SessionID
r.Ref = m.Ref r.Ref = m.Ref
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
@@ -42,6 +43,9 @@ func (this *Build) EqualVT(that *Build) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.SessionID != that.SessionID {
return false
}
if this.Ref != that.Ref { if this.Ref != that.Ref {
return false return false
} }
@@ -90,6 +94,13 @@ func (m *Build) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.Ref)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref)))
i-- i--
dAtA[i] = 0x12
}
if len(m.SessionID) > 0 {
i -= len(m.SessionID)
copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
return len(dAtA) - i, nil return len(dAtA) - i, nil
@@ -101,6 +112,10 @@ func (m *Build) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.SessionID)
if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
}
l = len(m.Ref) l = len(m.Ref)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
@@ -139,6 +154,38 @@ func (m *Build) UnmarshalVT(dAtA []byte) error {
} }
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return protohelpers.ErrIntOverflow
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return protohelpers.ErrInvalidLength
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return protohelpers.ErrInvalidLength
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType)
} }

View File

@@ -11,6 +11,7 @@ import (
controllererrors "github.com/docker/buildx/controller/errdefs" controllererrors "github.com/docker/buildx/controller/errdefs"
controllerapi "github.com/docker/buildx/controller/pb" controllerapi "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/controller/processes" "github.com/docker/buildx/controller/processes"
"github.com/docker/buildx/util/desktop"
"github.com/docker/buildx/util/ioset" "github.com/docker/buildx/util/ioset"
"github.com/docker/buildx/util/progress" "github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
@@ -21,7 +22,7 @@ import (
func NewLocalBuildxController(ctx context.Context, dockerCli command.Cli, logger progress.SubLogger) control.BuildxController { func NewLocalBuildxController(ctx context.Context, dockerCli command.Cli, logger progress.SubLogger) control.BuildxController {
return &localController{ return &localController{
dockerCli: dockerCli, dockerCli: dockerCli,
ref: "local", sessionID: "local",
processes: processes.NewManager(), processes: processes.NewManager(),
} }
} }
@@ -35,7 +36,7 @@ type buildConfig struct {
type localController struct { type localController struct {
dockerCli command.Cli dockerCli command.Cli
ref string sessionID string
buildConfig buildConfig buildConfig buildConfig
processes *processes.Manager processes *processes.Manager
@@ -56,25 +57,30 @@ func (b *localController) Build(ctx context.Context, options *controllerapi.Buil
buildOptions: options, buildOptions: options,
} }
if buildErr != nil { if buildErr != nil {
buildErr = controllererrors.WrapBuild(buildErr, b.ref) var ref string
var ebr *desktop.ErrorWithBuildRef
if errors.As(buildErr, &ebr) {
ref = ebr.Ref
}
buildErr = controllererrors.WrapBuild(buildErr, b.sessionID, ref)
} }
} }
if buildErr != nil { if buildErr != nil {
return "", nil, nil, buildErr return "", nil, nil, buildErr
} }
return b.ref, resp, dockerfileMappings, nil return b.sessionID, resp, dockerfileMappings, nil
} }
func (b *localController) ListProcesses(ctx context.Context, ref string) (infos []*controllerapi.ProcessInfo, retErr error) { func (b *localController) ListProcesses(ctx context.Context, sessionID string) (infos []*controllerapi.ProcessInfo, retErr error) {
if ref != b.ref { if sessionID != b.sessionID {
return nil, errors.Errorf("unknown ref %q", ref) return nil, errors.Errorf("unknown session ID %q", sessionID)
} }
return b.processes.ListProcesses(), nil return b.processes.ListProcesses(), nil
} }
func (b *localController) DisconnectProcess(ctx context.Context, ref, pid string) error { func (b *localController) DisconnectProcess(ctx context.Context, sessionID, pid string) error {
if ref != b.ref { if sessionID != b.sessionID {
return errors.Errorf("unknown ref %q", ref) return errors.Errorf("unknown session ID %q", sessionID)
} }
return b.processes.DeleteProcess(pid) return b.processes.DeleteProcess(pid)
} }
@@ -83,9 +89,9 @@ func (b *localController) cancelRunningProcesses() {
b.processes.CancelRunningProcesses() b.processes.CancelRunningProcesses()
} }
func (b *localController) Invoke(ctx context.Context, ref string, pid string, cfg *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error { func (b *localController) Invoke(ctx context.Context, sessionID string, pid string, cfg *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error {
if ref != b.ref { if sessionID != b.sessionID {
return errors.Errorf("unknown ref %q", ref) return errors.Errorf("unknown session ID %q", sessionID)
} }
proc, ok := b.processes.Get(pid) proc, ok := b.processes.Get(pid)
@@ -130,7 +136,7 @@ func (b *localController) Close() error {
} }
func (b *localController) List(ctx context.Context) (res []string, _ error) { func (b *localController) List(ctx context.Context) (res []string, _ error) {
return []string{b.ref}, nil return []string{b.sessionID}, nil
} }
func (b *localController) Disconnect(ctx context.Context, key string) error { func (b *localController) Disconnect(ctx context.Context, key string) error {
@@ -138,9 +144,9 @@ func (b *localController) Disconnect(ctx context.Context, key string) error {
return nil return nil
} }
func (b *localController) Inspect(ctx context.Context, ref string) (*controllerapi.InspectResponse, error) { func (b *localController) Inspect(ctx context.Context, sessionID string) (*controllerapi.InspectResponse, error) {
if ref != b.ref { if sessionID != b.sessionID {
return nil, errors.Errorf("unknown ref %q", ref) return nil, errors.Errorf("unknown session ID %q", sessionID)
} }
return &controllerapi.InspectResponse{Options: b.buildConfig.buildOptions}, nil return &controllerapi.InspectResponse{Options: b.buildConfig.buildOptions}, nil
} }

View File

@@ -27,7 +27,7 @@ type ListProcessesRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
} }
func (x *ListProcessesRequest) Reset() { func (x *ListProcessesRequest) Reset() {
@@ -62,9 +62,9 @@ func (*ListProcessesRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{0} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{0}
} }
func (x *ListProcessesRequest) GetRef() string { func (x *ListProcessesRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -176,7 +176,7 @@ type DisconnectProcessRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
ProcessID string `protobuf:"bytes,2,opt,name=ProcessID,proto3" json:"ProcessID,omitempty"` ProcessID string `protobuf:"bytes,2,opt,name=ProcessID,proto3" json:"ProcessID,omitempty"`
} }
@@ -212,9 +212,9 @@ func (*DisconnectProcessRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{3} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{3}
} }
func (x *DisconnectProcessRequest) GetRef() string { func (x *DisconnectProcessRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -269,8 +269,8 @@ type BuildRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
Options *BuildOptions `protobuf:"bytes,2,opt,name=Options,proto3" json:"Options,omitempty"` Options *BuildOptions `protobuf:"bytes,2,opt,name=Options,proto3" json:"Options,omitempty"`
} }
func (x *BuildRequest) Reset() { func (x *BuildRequest) Reset() {
@@ -305,9 +305,9 @@ func (*BuildRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{5} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{5}
} }
func (x *BuildRequest) GetRef() string { func (x *BuildRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -981,7 +981,7 @@ type InspectRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
} }
func (x *InspectRequest) Reset() { func (x *InspectRequest) Reset() {
@@ -1016,9 +1016,9 @@ func (*InspectRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{13} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{13}
} }
func (x *InspectRequest) GetRef() string { func (x *InspectRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -1232,7 +1232,7 @@ type DisconnectRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
} }
func (x *DisconnectRequest) Reset() { func (x *DisconnectRequest) Reset() {
@@ -1267,9 +1267,9 @@ func (*DisconnectRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{18} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{18}
} }
func (x *DisconnectRequest) GetRef() string { func (x *DisconnectRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -1317,7 +1317,7 @@ type ListRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
} }
func (x *ListRequest) Reset() { func (x *ListRequest) Reset() {
@@ -1352,9 +1352,9 @@ func (*ListRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{20} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{20}
} }
func (x *ListRequest) GetRef() string { func (x *ListRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -1492,7 +1492,7 @@ type InputInitMessage struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
} }
func (x *InputInitMessage) Reset() { func (x *InputInitMessage) Reset() {
@@ -1527,9 +1527,9 @@ func (*InputInitMessage) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{23} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{23}
} }
func (x *InputInitMessage) GetRef() string { func (x *InputInitMessage) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -1745,7 +1745,7 @@ type InitMessage struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
// If ProcessID already exists in the server, it tries to connect to it // If ProcessID already exists in the server, it tries to connect to it
// instead of invoking the new one. In this case, InvokeConfig will be ignored. // instead of invoking the new one. In this case, InvokeConfig will be ignored.
ProcessID string `protobuf:"bytes,2,opt,name=ProcessID,proto3" json:"ProcessID,omitempty"` ProcessID string `protobuf:"bytes,2,opt,name=ProcessID,proto3" json:"ProcessID,omitempty"`
@@ -1784,9 +1784,9 @@ func (*InitMessage) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{27} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{27}
} }
func (x *InitMessage) GetRef() string { func (x *InitMessage) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -2104,7 +2104,7 @@ type StatusRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"` SessionID string `protobuf:"bytes,1,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
} }
func (x *StatusRequest) Reset() { func (x *StatusRequest) Reset() {
@@ -2139,9 +2139,9 @@ func (*StatusRequest) Descriptor() ([]byte, []int) {
return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{32} return file_github_com_docker_buildx_controller_pb_controller_proto_rawDescGZIP(), []int{32}
} }
func (x *StatusRequest) GetRef() string { func (x *StatusRequest) GetSessionID() string {
if x != nil { if x != nil {
return x.Ref return x.SessionID
} }
return "" return ""
} }
@@ -2380,178 +2380,181 @@ var file_github_com_docker_buildx_controller_pb_controller_proto_rawDesc = []byt
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75,
0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x6f, 0x6c, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x6f, 0x6c,
0x69, 0x63, 0x79, 0x2f, 0x70, 0x62, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72, 0x69, 0x63, 0x79, 0x2f, 0x70, 0x62, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x28, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x6f, 0x74, 0x6f, 0x22, 0x34, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65,
0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x53,
0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x22, 0x50, 0x0a, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x15, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x50, 0x0a, 0x15, 0x4c, 0x69, 0x73,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x22, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
0x73, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x49, 0x6e, 0x66, 0x6f, 0x73, 0x22, 0x73, 0x0a, 0x0b, 0x50,
0x0a, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72,
0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x12, 0x46, 0x0a, 0x0c, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50,
0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x12, 0x46, 0x0a, 0x0c, 0x49, 0x6e, 0x76, 0x6f,
0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6f, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66,
0x6e, 0x66, 0x69, 0x67, 0x22, 0x4a, 0x0a, 0x18, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x69, 0x67, 0x52, 0x0c, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x63, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x56, 0x0a, 0x18, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72,
0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
0x65, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x18, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72,
0x22, 0x1b, 0x0a, 0x19, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50,
0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5e, 0x0a, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x22, 0x1b, 0x0a, 0x19, 0x44, 0x69, 0x73, 0x63,
0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73,
0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x12, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6a, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65,
0x3c, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x6e, 0x49, 0x44, 0x12, 0x3c, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02,
0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xc5, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f,
0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x20, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c,
0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0xc5, 0x0c, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
0x12, 0x26, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6e, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x50, 0x61, 0x74,
0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69,
0x46, 0x75, 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x44, 0x6f,
0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x63, 0x6b, 0x65, 0x72, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x08,
0x31, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x52, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x43, 0x61, 0x6c, 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e,
0x46, 0x75, 0x6e, 0x63, 0x12, 0x5b, 0x0a, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x74, 0x65, 0x78, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x62, 0x75, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x52, 0x08,
0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x12, 0x5b, 0x0a, 0x0d, 0x4e, 0x61, 0x6d, 0x65,
0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x4e, 0x61, 0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x35, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x72, 0x79, 0x52, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69,
0x73, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x6f, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
0x52, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x36, 0x0a, 0x07, 0x41, 0x74, 0x74, 0x65, 0x73, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e,
0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x74, 0x65, 0x78, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x18, 0x05,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x12, 0x36, 0x0a, 0x07, 0x41,
0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x07, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x73, 0x12, 0x74, 0x74, 0x65, 0x73, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62,
0x4f, 0x0a, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x28, 0x0b, 0x32, 0x31, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x52, 0x07, 0x41, 0x74, 0x74, 0x65,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x73, 0x74, 0x73, 0x12, 0x4f, 0x0a, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x73,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x73, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75,
0x12, 0x45, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x18, 0x08, 0x20, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64,
0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x72, 0x6f,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x43, 0x61, 0x6d, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78,
0x63, 0x68, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x41, 0x0a, 0x07, 0x43, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43,
0x54, 0x6f, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x41, 0x0a, 0x07, 0x43,
0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x68, 0x65, 0x54, 0x6f, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x62,
0x79, 0x52, 0x07, 0x43, 0x61, 0x63, 0x68, 0x65, 0x54, 0x6f, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x67, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x72, 0x6f, 0x75, 0x70, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x52, 0x0c, 0x43, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x3b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x43, 0x61, 0x63, 0x68, 0x65, 0x54, 0x6f, 0x12, 0x22,
0x0a, 0x07, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x0c, 0x43, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x0a,
0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x61, 0x72, 0x65,
0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x74, 0x6e, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x0b, 0x20,
0x72, 0x79, 0x52, 0x07, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e,
0x78, 0x74, 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72,
0x0a, 0x45, 0x78, 0x74, 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x46, 0x0a, 0x06, 0x4c, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12,
0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x62, 0x75, 0x1e, 0x0a, 0x0a, 0x45, 0x78, 0x74, 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x0c, 0x20,
0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x45, 0x78, 0x74, 0x72, 0x61, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12,
0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x46, 0x0a, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x4c, 0x61, 0x62, 0x2e, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x65, 0x6c, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x6f, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69,
0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x4e, 0x6f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f,
0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x4e, 0x6f, 0x72, 0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4e, 0x65,
0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x4e, 0x6f, 0x43,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x68, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x09,
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x12, 0x36, 0x0a, 0x07, 0x53, 0x65, 0x63, 0x52, 0x0d, 0x4e, 0x6f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12,
0x72, 0x65, 0x74, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x75, 0x69, 0x1c, 0x0a, 0x09, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x18, 0x10, 0x20, 0x03,
0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x28, 0x09, 0x52, 0x09, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x12, 0x36, 0x0a,
0x31, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x07, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x07, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c,
0x73, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x12, 0x20, 0x01, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x28, 0x03, 0x52, 0x07, 0x53, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x53, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x07, 0x53, 0x65,
0x53, 0x48, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x53, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x12,
0x53, 0x53, 0x48, 0x52, 0x03, 0x53, 0x53, 0x48, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x2b, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x62,
0x18, 0x14, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x54, 0x61, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x53, 0x48, 0x52, 0x03, 0x53, 0x53, 0x48, 0x12, 0x12, 0x0a, 0x04,
0x72, 0x67, 0x65, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x54, 0x61, 0x67, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73,
0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09,
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6c, 0x69, 0x52, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x55, 0x6c, 0x69, 0x6d,
0x6d, 0x69, 0x74, 0x4f, 0x70, 0x74, 0x52, 0x07, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x12, 0x69, 0x74, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x75, 0x69, 0x6c,
0x18, 0x0a, 0x07, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x52, 0x07, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4e, 0x6f, 0x43, 0x2e, 0x55, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x4f, 0x70, 0x74, 0x52, 0x07, 0x55, 0x6c, 0x69, 0x6d,
0x61, 0x63, 0x68, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x4e, 0x6f, 0x43, 0x61, 0x69, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x18, 0x17,
0x63, 0x68, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x75, 0x6c, 0x6c, 0x18, 0x19, 0x20, 0x01, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a,
0x08, 0x52, 0x04, 0x50, 0x75, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x07, 0x4e, 0x6f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
0x74, 0x50, 0x75, 0x73, 0x68, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x45, 0x78, 0x70, 0x4e, 0x6f, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x75, 0x6c, 0x6c, 0x18,
0x6f, 0x72, 0x74, 0x50, 0x75, 0x73, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x50, 0x75, 0x6c, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x45,
0x74, 0x4c, 0x6f, 0x61, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x45, 0x78, 0x70, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x75, 0x73, 0x68, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52,
0x6f, 0x72, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x12, 0x49, 0x0a, 0x0c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x75, 0x73, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x45,
0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52,
0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x12, 0x49, 0x0a, 0x0c, 0x53,
0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x1c, 0x20, 0x01, 0x28,
0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x0b, 0x32, 0x25, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69,
0x63, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x70, 0x6f, 0x6c, 0x69, 0x63,
0x03, 0x52, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x66, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x66, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x1d, 0x20,
0x12, 0x20, 0x0a, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x12, 0x1a, 0x0a, 0x08, 0x47, 0x72, 0x6f, 0x75,
0x1f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x70, 0x52, 0x65, 0x66, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x47, 0x72, 0x6f, 0x75,
0x6e, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x70, 0x52, 0x65, 0x66, 0x12, 0x20, 0x0a, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x20, 0x20, 0x01, 0x6f, 0x6e, 0x73, 0x18, 0x1f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
0x28, 0x09, 0x52, 0x16, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x1a, 0x40, 0x0a, 0x12, 0x4e, 0x61, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x6f, 0x64, 0x65,
0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x1a, 0x40,
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0a, 0x12, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x45,
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3c, 0x0a, 0x0e, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x3c, 0x0a, 0x0e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x41, 0x72, 0x67, 0x73, 0x45, 0x6e, 0x74,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc1, 0x01, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x42, 0x0a, 0x05, 0x41, 0x74, 0x74,
0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, 0x20, 0x0a,
0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a,
0x38, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xab, 0x01, 0x0a, 0x11, 0x43, 0x61, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc1, 0x01, 0x0a, 0x0b, 0x45, 0x78,
0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70,
0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x42, 0x0a,
0x79, 0x70, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x62,
0x28, 0x0b, 0x32, 0x32, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x41, 0x74, 0x74, 0x72,
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x1a, 0x38, 0x0a, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x69, 0x6f, 0x6e, 0x1a, 0x38, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4e, 0x0a, 0x06, 0x41, 0x74, 0x74, 0x65, 0x73, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x74, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xab, 0x01,
0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x11, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x64, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x48, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73,
0x52, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x22, 0x2b, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x12, 0x0e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e,
0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x14, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61,
0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x50, 0x63, 0x68, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x2e,
0x61, 0x74, 0x68, 0x73, 0x22, 0x46, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x0e, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x41, 0x74, 0x74, 0x72,
0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x1a, 0x73, 0x1a, 0x38, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x45, 0x6e, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x76, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x45, 0x6e, 0x76, 0x22, 0x5a, 0x0a, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4e, 0x0a, 0x06, 0x41,
0x43, 0x61, 0x6c, 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x74, 0x74, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x69, 0x73,
0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x6f, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x44, 0x69, 0x73,
0x72, 0x6d, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x18, 0x03,
0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, 0x67, 0x6e, 0x6f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x22, 0x2b, 0x0a, 0x03, 0x53,
0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x22, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x70, 0x53, 0x48, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x22, 0x4f, 0x0a, 0x0f, 0x09, 0x52, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0x46, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72,
0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x10,
0x0a, 0x03, 0x45, 0x6e, 0x76, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x45, 0x6e, 0x76,
0x22, 0x5a, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x46, 0x75, 0x6e, 0x63, 0x12, 0x12, 0x0a, 0x04,
0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x16, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x67, 0x6e, 0x6f,
0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c,
0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2e, 0x0a, 0x0e,
0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x4f, 0x0a, 0x0f,
0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x3c, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x3c, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
@@ -2583,50 +2586,53 @@ var file_github_com_docker_buildx_controller_pb_controller_proto_rawDesc = []byt
0x72, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x72, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x25, 0x0a, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x31, 0x0a,
0x11, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x11, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18,
0x03, 0x52, 0x65, 0x66, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44,
0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x0a, 0x0b, 0x4c, 0x69, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65,
0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x22, 0x22, 0x0a, 0x0c, 0x4c, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x6e, 0x49, 0x44, 0x22, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x8e, 0x01, 0x0a, 0x0c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
0x12, 0x3c, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x09, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x0c, 0x49, 0x6e, 0x70, 0x75,
0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x37,
0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62,
0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48,
0x00, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x42, 0x07, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74,
0x22, 0x24, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x22, 0x33, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x45, 0x4f, 0x46, 0x18, 0x01, 0x20, 0x01,
0x28, 0x08, 0x52, 0x03, 0x45, 0x4f, 0x46, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x22, 0x0f, 0x0a, 0x0d, 0x49,
0x6e, 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x80, 0x02, 0x0a,
0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e,
0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x04, 0x49, 0x6e, 0x69, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00,
0x74, 0x12, 0x35, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x52, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x02,
0x1f, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f,
0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61,
0x48, 0x00, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x69, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x42,
0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x07, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x30, 0x0a, 0x10, 0x49, 0x6e, 0x70, 0x75,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09,
0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x33, 0x0a, 0x0b, 0x44, 0x61,
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x45, 0x4f, 0x46,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x45, 0x4f, 0x46, 0x12, 0x12, 0x0a, 0x04, 0x44,
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x06, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x22,
0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x85, 0x01, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x80, 0x02, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x04,
0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x62, 0x75, 0x69,
0x66, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x18, 0x02, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76,
0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52,
0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x64, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x3d, 0x0a, 0x06,
0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62,
0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x48, 0x00, 0x52, 0x06, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x53,
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x75,
0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x48, 0x00, 0x52, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x49, 0x6e,
0x70, 0x75, 0x74, 0x22, 0x91, 0x01, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49,
0x44, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x44, 0x12,
0x46, 0x0a, 0x0c, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x46, 0x0a, 0x0c, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63,
@@ -2659,97 +2665,97 @@ var file_github_com_docker_buildx_controller_pb_controller_proto_rawDesc = []byt
0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x22, 0x23, 0x0a, 0x0d, 0x53, 0x69, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x22, 0x23, 0x0a, 0x0d, 0x53, 0x69,
0x67, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x67, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22,
0x21, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2d, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20,
0x65, 0x66, 0x22, 0xf0, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0xf0,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x65, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x65, 0x12, 0x34, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x65, 0x73, 0x18, 0x01, 0x20,
0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x74, 0x65, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x78, 0x52, 0x08, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x73, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x52, 0x08, 0x76,
0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x65, 0x72, 0x74, 0x65, 0x78, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75,
0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x6f, 0x62, 0x79,
0x2e, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72,
0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x74, 0x65, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75,
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x73, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x4c, 0x0b, 0x32, 0x1b, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69,
0x6f, 0x67, 0x52, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x4c, 0x6f, 0x67, 0x52, 0x04,
0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x6f, 0x62, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x3b, 0x0a, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73,
0x79, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x6f, 0x62, 0x79, 0x2e, 0x62, 0x75,
0x72, 0x74, 0x65, 0x78, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x77, 0x61, 0x72, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78,
0x6e, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x0d, 0x0a, 0x0b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67,
0x75, 0x65, 0x73, 0x74, 0x22, 0x59, 0x0a, 0x0c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x73, 0x22, 0x0d, 0x0a, 0x0b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x22, 0x59, 0x0a, 0x0c, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x75, 0x12, 0x49, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78,
0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42,
0x52, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x62, 0x75,
0x5f, 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5f, 0x0a, 0x0d, 0x42,
0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07,
0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
0x32, 0x8c, 0x07, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0x8c, 0x07, 0x0a,
0x50, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x05, 0x42,
0x75, 0x69, 0x6c, 0x64, 0x12, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c,
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x62, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a,
0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x07, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x56, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x62,
0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x25, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63,
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x06, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x12, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25,
0x12, 0x52, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c,
0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x23, 0x2e,
0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x28, 0x01, 0x12, 0x4a, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x1d,
0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1d, 0x2e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73,
0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x55, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
0x12, 0x4d, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f,
0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x62, 0x75, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74,
0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x05,
0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63,
0x5f, 0x0a, 0x0a, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x27, 0x2e, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70,
0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x75, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x23, 0x2e, 0x62, 0x75, 0x69, 0x6c,
0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x12, 0x4a, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x1d, 0x2e, 0x62, 0x75, 0x69,
0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76,
0x12, 0x4d, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x31, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1d, 0x2e, 0x62, 0x75, 0x69, 0x6c,
0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x62, 0x75, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x04,
0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f,
0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x68, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78,
0x12, 0x2a, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x0a, 0x44,
0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x62, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x27, 0x2e, 0x62, 0x75, 0x69, 0x6c,
0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31,
0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x28, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x04,
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x21, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x66, 0x6f,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x49,
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x4c,
0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x62,
0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x11, 0x44, 0x69, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64,
0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x11, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e,
0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x2e, 0x62, 0x75, 0x69,
0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76,
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x63,
0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x62, 0x75, 0x69,
0x28, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x6c, 0x64, 0x78, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76,
0x63, 0x6b, 0x65, 0x72, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x63,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x28, 0x5a, 0x26, 0x67,
0x33, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72,
0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
0x65, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -21,7 +21,7 @@ service Controller {
} }
message ListProcessesRequest { message ListProcessesRequest {
string Ref = 1; string SessionID = 1;
} }
message ListProcessesResponse { message ListProcessesResponse {
@@ -34,7 +34,7 @@ message ProcessInfo {
} }
message DisconnectProcessRequest { message DisconnectProcessRequest {
string Ref = 1; string SessionID = 1;
string ProcessID = 2; string ProcessID = 2;
} }
@@ -42,7 +42,7 @@ message DisconnectProcessResponse {
} }
message BuildRequest { message BuildRequest {
string Ref = 1; string SessionID = 1;
BuildOptions Options = 2; BuildOptions Options = 2;
} }
@@ -118,7 +118,7 @@ message CallFunc {
} }
message InspectRequest { message InspectRequest {
string Ref = 1; string SessionID = 1;
} }
message InspectResponse { message InspectResponse {
@@ -140,13 +140,13 @@ message BuildResponse {
} }
message DisconnectRequest { message DisconnectRequest {
string Ref = 1; string SessionID = 1;
} }
message DisconnectResponse {} message DisconnectResponse {}
message ListRequest { message ListRequest {
string Ref = 1; string SessionID = 1;
} }
message ListResponse { message ListResponse {
@@ -161,7 +161,7 @@ message InputMessage {
} }
message InputInitMessage { message InputInitMessage {
string Ref = 1; string SessionID = 1;
} }
message DataMessage { message DataMessage {
@@ -186,7 +186,7 @@ message Message {
} }
message InitMessage { message InitMessage {
string Ref = 1; string SessionID = 1;
// If ProcessID already exists in the server, it tries to connect to it // If ProcessID already exists in the server, it tries to connect to it
// instead of invoking the new one. In this case, InvokeConfig will be ignored. // instead of invoking the new one. In this case, InvokeConfig will be ignored.
@@ -227,7 +227,7 @@ message SignalMessage {
} }
message StatusRequest { message StatusRequest {
string Ref = 1; string SessionID = 1;
} }
message StatusResponse { message StatusResponse {

View File

@@ -26,7 +26,7 @@ func (m *ListProcessesRequest) CloneVT() *ListProcessesRequest {
return (*ListProcessesRequest)(nil) return (*ListProcessesRequest)(nil)
} }
r := new(ListProcessesRequest) r := new(ListProcessesRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
copy(r.unknownFields, m.unknownFields) copy(r.unknownFields, m.unknownFields)
@@ -84,7 +84,7 @@ func (m *DisconnectProcessRequest) CloneVT() *DisconnectProcessRequest {
return (*DisconnectProcessRequest)(nil) return (*DisconnectProcessRequest)(nil)
} }
r := new(DisconnectProcessRequest) r := new(DisconnectProcessRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
r.ProcessID = m.ProcessID r.ProcessID = m.ProcessID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
@@ -118,7 +118,7 @@ func (m *BuildRequest) CloneVT() *BuildRequest {
return (*BuildRequest)(nil) return (*BuildRequest)(nil)
} }
r := new(BuildRequest) r := new(BuildRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
r.Options = m.Options.CloneVT() r.Options = m.Options.CloneVT()
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
@@ -396,7 +396,7 @@ func (m *InspectRequest) CloneVT() *InspectRequest {
return (*InspectRequest)(nil) return (*InspectRequest)(nil)
} }
r := new(InspectRequest) r := new(InspectRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
copy(r.unknownFields, m.unknownFields) copy(r.unknownFields, m.unknownFields)
@@ -495,7 +495,7 @@ func (m *DisconnectRequest) CloneVT() *DisconnectRequest {
return (*DisconnectRequest)(nil) return (*DisconnectRequest)(nil)
} }
r := new(DisconnectRequest) r := new(DisconnectRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
copy(r.unknownFields, m.unknownFields) copy(r.unknownFields, m.unknownFields)
@@ -528,7 +528,7 @@ func (m *ListRequest) CloneVT() *ListRequest {
return (*ListRequest)(nil) return (*ListRequest)(nil)
} }
r := new(ListRequest) r := new(ListRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
copy(r.unknownFields, m.unknownFields) copy(r.unknownFields, m.unknownFields)
@@ -603,7 +603,7 @@ func (m *InputInitMessage) CloneVT() *InputInitMessage {
return (*InputInitMessage)(nil) return (*InputInitMessage)(nil)
} }
r := new(InputInitMessage) r := new(InputInitMessage)
r.Ref = m.Ref r.SessionID = m.SessionID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
copy(r.unknownFields, m.unknownFields) copy(r.unknownFields, m.unknownFields)
@@ -713,7 +713,7 @@ func (m *InitMessage) CloneVT() *InitMessage {
return (*InitMessage)(nil) return (*InitMessage)(nil)
} }
r := new(InitMessage) r := new(InitMessage)
r.Ref = m.Ref r.SessionID = m.SessionID
r.ProcessID = m.ProcessID r.ProcessID = m.ProcessID
r.InvokeConfig = m.InvokeConfig.CloneVT() r.InvokeConfig = m.InvokeConfig.CloneVT()
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
@@ -829,7 +829,7 @@ func (m *StatusRequest) CloneVT() *StatusRequest {
return (*StatusRequest)(nil) return (*StatusRequest)(nil)
} }
r := new(StatusRequest) r := new(StatusRequest)
r.Ref = m.Ref r.SessionID = m.SessionID
if len(m.unknownFields) > 0 { if len(m.unknownFields) > 0 {
r.unknownFields = make([]byte, len(m.unknownFields)) r.unknownFields = make([]byte, len(m.unknownFields))
copy(r.unknownFields, m.unknownFields) copy(r.unknownFields, m.unknownFields)
@@ -959,7 +959,7 @@ func (this *ListProcessesRequest) EqualVT(that *ListProcessesRequest) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
return string(this.unknownFields) == string(that.unknownFields) return string(this.unknownFields) == string(that.unknownFields)
@@ -1033,7 +1033,7 @@ func (this *DisconnectProcessRequest) EqualVT(that *DisconnectProcessRequest) bo
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
if this.ProcessID != that.ProcessID { if this.ProcessID != that.ProcessID {
@@ -1071,7 +1071,7 @@ func (this *BuildRequest) EqualVT(that *BuildRequest) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
if !this.Options.EqualVT(that.Options) { if !this.Options.EqualVT(that.Options) {
@@ -1524,7 +1524,7 @@ func (this *InspectRequest) EqualVT(that *InspectRequest) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
return string(this.unknownFields) == string(that.unknownFields) return string(this.unknownFields) == string(that.unknownFields)
@@ -1651,7 +1651,7 @@ func (this *DisconnectRequest) EqualVT(that *DisconnectRequest) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
return string(this.unknownFields) == string(that.unknownFields) return string(this.unknownFields) == string(that.unknownFields)
@@ -1686,7 +1686,7 @@ func (this *ListRequest) EqualVT(that *ListRequest) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
return string(this.unknownFields) == string(that.unknownFields) return string(this.unknownFields) == string(that.unknownFields)
@@ -1808,7 +1808,7 @@ func (this *InputInitMessage) EqualVT(that *InputInitMessage) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
return string(this.unknownFields) == string(that.unknownFields) return string(this.unknownFields) == string(that.unknownFields)
@@ -1991,7 +1991,7 @@ func (this *InitMessage) EqualVT(that *InitMessage) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
if this.ProcessID != that.ProcessID { if this.ProcessID != that.ProcessID {
@@ -2149,7 +2149,7 @@ func (this *StatusRequest) EqualVT(that *StatusRequest) bool {
} else if this == nil || that == nil { } else if this == nil || that == nil {
return false return false
} }
if this.Ref != that.Ref { if this.SessionID != that.SessionID {
return false return false
} }
return string(this.unknownFields) == string(that.unknownFields) return string(this.unknownFields) == string(that.unknownFields)
@@ -2356,10 +2356,10 @@ func (m *ListProcessesRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error)
i -= len(m.unknownFields) i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields) copy(dAtA[i:], m.unknownFields)
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -2498,10 +2498,10 @@ func (m *DisconnectProcessRequest) MarshalToSizedBufferVT(dAtA []byte) (int, err
i-- i--
dAtA[i] = 0x12 dAtA[i] = 0x12
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -2581,10 +2581,10 @@ func (m *BuildRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i-- i--
dAtA[i] = 0x12 dAtA[i] = 0x12
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -3363,10 +3363,10 @@ func (m *InspectRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields) i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields) copy(dAtA[i:], m.unknownFields)
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -3603,10 +3603,10 @@ func (m *DisconnectRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields) i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields) copy(dAtA[i:], m.unknownFields)
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -3676,10 +3676,10 @@ func (m *ListRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields) i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields) copy(dAtA[i:], m.unknownFields)
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -3846,10 +3846,10 @@ func (m *InputInitMessage) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields) i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields) copy(dAtA[i:], m.unknownFields)
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -4120,10 +4120,10 @@ func (m *InitMessage) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i-- i--
dAtA[i] = 0x12 dAtA[i] = 0x12
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -4432,10 +4432,10 @@ func (m *StatusRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
i -= len(m.unknownFields) i -= len(m.unknownFields)
copy(dAtA[i:], m.unknownFields) copy(dAtA[i:], m.unknownFields)
} }
if len(m.Ref) > 0 { if len(m.SessionID) > 0 {
i -= len(m.Ref) i -= len(m.SessionID)
copy(dAtA[i:], m.Ref) copy(dAtA[i:], m.SessionID)
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref))) i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.SessionID)))
i-- i--
dAtA[i] = 0xa dAtA[i] = 0xa
} }
@@ -4707,7 +4707,7 @@ func (m *ListProcessesRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -4755,7 +4755,7 @@ func (m *DisconnectProcessRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -4783,7 +4783,7 @@ func (m *BuildRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5108,7 +5108,7 @@ func (m *InspectRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5197,7 +5197,7 @@ func (m *DisconnectRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5221,7 +5221,7 @@ func (m *ListRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5292,7 +5292,7 @@ func (m *InputInitMessage) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5402,7 +5402,7 @@ func (m *InitMessage) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5528,7 +5528,7 @@ func (m *StatusRequest) SizeVT() (n int) {
} }
var l int var l int
_ = l _ = l
l = len(m.Ref) l = len(m.SessionID)
if l > 0 { if l > 0 {
n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
} }
@@ -5671,7 +5671,7 @@ func (m *ListProcessesRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -5699,7 +5699,7 @@ func (m *ListProcessesRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
@@ -5958,7 +5958,7 @@ func (m *DisconnectProcessRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -5986,7 +5986,7 @@ func (m *DisconnectProcessRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 2 { if wireType != 2 {
@@ -6124,7 +6124,7 @@ func (m *BuildRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -6152,7 +6152,7 @@ func (m *BuildRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 2 { if wireType != 2 {
@@ -8558,7 +8558,7 @@ func (m *InspectRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -8586,7 +8586,7 @@ func (m *InspectRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
@@ -9207,7 +9207,7 @@ func (m *DisconnectRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -9235,7 +9235,7 @@ func (m *DisconnectRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
@@ -9341,7 +9341,7 @@ func (m *ListRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -9369,7 +9369,7 @@ func (m *ListRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
@@ -9640,7 +9640,7 @@ func (m *InputInitMessage) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -9668,7 +9668,7 @@ func (m *InputInitMessage) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
@@ -10094,7 +10094,7 @@ func (m *InitMessage) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -10122,7 +10122,7 @@ func (m *InitMessage) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 2: case 2:
if wireType != 2 { if wireType != 2 {
@@ -10872,7 +10872,7 @@ func (m *StatusRequest) UnmarshalVT(dAtA []byte) error {
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 2 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) return fmt.Errorf("proto: wrong wireType = %d for field SessionID", wireType)
} }
var stringLen uint64 var stringLen uint64
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
@@ -10900,7 +10900,7 @@ func (m *StatusRequest) UnmarshalVT(dAtA []byte) error {
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
m.Ref = string(dAtA[iNdEx:postIndex]) m.SessionID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex

View File

@@ -75,36 +75,36 @@ func (c *Client) List(ctx context.Context) (keys []string, retErr error) {
return res.Keys, nil return res.Keys, nil
} }
func (c *Client) Disconnect(ctx context.Context, key string) error { func (c *Client) Disconnect(ctx context.Context, sessionID string) error {
if key == "" { if sessionID == "" {
return nil return nil
} }
_, err := c.client().Disconnect(ctx, &pb.DisconnectRequest{Ref: key}) _, err := c.client().Disconnect(ctx, &pb.DisconnectRequest{SessionID: sessionID})
return err return err
} }
func (c *Client) ListProcesses(ctx context.Context, ref string) (infos []*pb.ProcessInfo, retErr error) { func (c *Client) ListProcesses(ctx context.Context, sessionID string) (infos []*pb.ProcessInfo, retErr error) {
res, err := c.client().ListProcesses(ctx, &pb.ListProcessesRequest{Ref: ref}) res, err := c.client().ListProcesses(ctx, &pb.ListProcessesRequest{SessionID: sessionID})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res.Infos, nil return res.Infos, nil
} }
func (c *Client) DisconnectProcess(ctx context.Context, ref, pid string) error { func (c *Client) DisconnectProcess(ctx context.Context, sessionID, pid string) error {
_, err := c.client().DisconnectProcess(ctx, &pb.DisconnectProcessRequest{Ref: ref, ProcessID: pid}) _, err := c.client().DisconnectProcess(ctx, &pb.DisconnectProcessRequest{SessionID: sessionID, ProcessID: pid})
return err return err
} }
func (c *Client) Invoke(ctx context.Context, ref string, pid string, invokeConfig *pb.InvokeConfig, in io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error { func (c *Client) Invoke(ctx context.Context, sessionID string, pid string, invokeConfig *pb.InvokeConfig, in io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
if ref == "" || pid == "" { if sessionID == "" || pid == "" {
return errors.New("build reference must be specified") return errors.New("build session ID must be specified")
} }
stream, err := c.client().Invoke(ctx) stream, err := c.client().Invoke(ctx)
if err != nil { if err != nil {
return err return err
} }
return attachIO(ctx, stream, &pb.InitMessage{Ref: ref, ProcessID: pid, InvokeConfig: invokeConfig}, ioAttachConfig{ return attachIO(ctx, stream, &pb.InitMessage{SessionID: sessionID, ProcessID: pid, InvokeConfig: invokeConfig}, ioAttachConfig{
stdin: in, stdin: in,
stdout: stdout, stdout: stdout,
stderr: stderr, stderr: stderr,
@@ -112,8 +112,8 @@ func (c *Client) Invoke(ctx context.Context, ref string, pid string, invokeConfi
}) })
} }
func (c *Client) Inspect(ctx context.Context, ref string) (*pb.InspectResponse, error) { func (c *Client) Inspect(ctx context.Context, sessionID string) (*pb.InspectResponse, error) {
return c.client().Inspect(ctx, &pb.InspectRequest{Ref: ref}) return c.client().Inspect(ctx, &pb.InspectRequest{SessionID: sessionID})
} }
func (c *Client) Build(ctx context.Context, options *pb.BuildOptions, in io.ReadCloser, progress progress.Writer) (string, *client.SolveResponse, *build.Inputs, error) { func (c *Client) Build(ctx context.Context, options *pb.BuildOptions, in io.ReadCloser, progress progress.Writer) (string, *client.SolveResponse, *build.Inputs, error) {
@@ -137,7 +137,7 @@ func (c *Client) Build(ctx context.Context, options *pb.BuildOptions, in io.Read
return ref, resp, nil, eg.Wait() return ref, resp, nil, eg.Wait()
} }
func (c *Client) build(ctx context.Context, ref string, options *pb.BuildOptions, in io.ReadCloser, statusChan chan *client.SolveStatus) (*client.SolveResponse, error) { func (c *Client) build(ctx context.Context, sessionID 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{})
@@ -146,8 +146,8 @@ func (c *Client) build(ctx context.Context, ref string, options *pb.BuildOptions
eg.Go(func() error { eg.Go(func() error {
defer close(done) defer close(done)
pbResp, err := c.client().Build(egCtx, &pb.BuildRequest{ pbResp, err := c.client().Build(egCtx, &pb.BuildRequest{
Ref: ref, SessionID: sessionID,
Options: options, Options: options,
}) })
if err != nil { if err != nil {
return err return err
@@ -159,7 +159,7 @@ func (c *Client) build(ctx context.Context, ref string, options *pb.BuildOptions
}) })
eg.Go(func() error { eg.Go(func() error {
stream, err := c.client().Status(egCtx, &pb.StatusRequest{ stream, err := c.client().Status(egCtx, &pb.StatusRequest{
Ref: ref, SessionID: sessionID,
}) })
if err != nil { if err != nil {
return err return err
@@ -184,7 +184,7 @@ func (c *Client) build(ctx context.Context, ref string, options *pb.BuildOptions
if err := stream.Send(&pb.InputMessage{ if err := stream.Send(&pb.InputMessage{
Input: &pb.InputMessage_Init{ Input: &pb.InputMessage_Init{
Init: &pb.InputInitMessage{ Init: &pb.InputInitMessage{
Ref: ref, SessionID: sessionID,
}, },
}, },
}); err != nil { }); err != nil {

View File

@@ -258,7 +258,7 @@ func prepareRootDir(dockerCli command.Cli, config *serverConfig) (string, error)
} }
func rootDataDir(dockerCli command.Cli) string { func rootDataDir(dockerCli command.Cli) string {
return filepath.Join(confutil.ConfigDir(dockerCli), "controller") return filepath.Join(confutil.NewConfig(dockerCli).Dir(), "controller")
} }
func newBuildxClientAndCheck(ctx context.Context, addr string) (*Client, error) { func newBuildxClientAndCheck(ctx context.Context, addr string) (*Client, error) {

View File

@@ -43,9 +43,9 @@ func serveIO(attachCtx context.Context, srv msgStream, initFn func(*pb.InitMessa
if init == nil { if init == nil {
return errors.Errorf("unexpected message: %T; wanted init", msg.GetInput()) return errors.Errorf("unexpected message: %T; wanted init", msg.GetInput())
} }
ref := init.Ref sessionID := init.SessionID
if ref == "" { if sessionID == "" {
return errors.New("no ref is provided") return errors.New("no session ID is provided")
} }
if err := initFn(init); err != nil { if err := initFn(init); err != nil {
return errors.Wrap(err, "failed to initialize IO server") return errors.Wrap(err, "failed to initialize IO server")

View File

@@ -11,6 +11,7 @@ import (
controllererrors "github.com/docker/buildx/controller/errdefs" controllererrors "github.com/docker/buildx/controller/errdefs"
"github.com/docker/buildx/controller/pb" "github.com/docker/buildx/controller/pb"
"github.com/docker/buildx/controller/processes" "github.com/docker/buildx/controller/processes"
"github.com/docker/buildx/util/desktop"
"github.com/docker/buildx/util/ioset" "github.com/docker/buildx/util/ioset"
"github.com/docker/buildx/util/progress" "github.com/docker/buildx/util/progress"
"github.com/docker/buildx/version" "github.com/docker/buildx/version"
@@ -52,9 +53,9 @@ func (s *session) cancelRunningProcesses() {
func (m *Server) ListProcesses(ctx context.Context, req *pb.ListProcessesRequest) (res *pb.ListProcessesResponse, err error) { func (m *Server) ListProcesses(ctx context.Context, req *pb.ListProcessesRequest) (res *pb.ListProcessesResponse, err error) {
m.sessionMu.Lock() m.sessionMu.Lock()
defer m.sessionMu.Unlock() defer m.sessionMu.Unlock()
s, ok := m.session[req.Ref] s, ok := m.session[req.SessionID]
if !ok { if !ok {
return nil, errors.Errorf("unknown ref %q", req.Ref) return nil, errors.Errorf("unknown session ID %q", req.SessionID)
} }
res = new(pb.ListProcessesResponse) res = new(pb.ListProcessesResponse)
res.Infos = append(res.Infos, s.processes.ListProcesses()...) res.Infos = append(res.Infos, s.processes.ListProcesses()...)
@@ -64,9 +65,9 @@ func (m *Server) ListProcesses(ctx context.Context, req *pb.ListProcessesRequest
func (m *Server) DisconnectProcess(ctx context.Context, req *pb.DisconnectProcessRequest) (res *pb.DisconnectProcessResponse, err error) { func (m *Server) DisconnectProcess(ctx context.Context, req *pb.DisconnectProcessRequest) (res *pb.DisconnectProcessResponse, err error) {
m.sessionMu.Lock() m.sessionMu.Lock()
defer m.sessionMu.Unlock() defer m.sessionMu.Unlock()
s, ok := m.session[req.Ref] s, ok := m.session[req.SessionID]
if !ok { if !ok {
return nil, errors.Errorf("unknown ref %q", req.Ref) return nil, errors.Errorf("unknown session ID %q", req.SessionID)
} }
return res, s.processes.DeleteProcess(req.ProcessID) return res, s.processes.DeleteProcess(req.ProcessID)
} }
@@ -100,13 +101,13 @@ func (m *Server) List(ctx context.Context, req *pb.ListRequest) (res *pb.ListRes
} }
func (m *Server) Disconnect(ctx context.Context, req *pb.DisconnectRequest) (res *pb.DisconnectResponse, err error) { func (m *Server) Disconnect(ctx context.Context, req *pb.DisconnectRequest) (res *pb.DisconnectResponse, err error) {
key := req.Ref sessionID := req.SessionID
if key == "" { if sessionID == "" {
return nil, errors.New("disconnect: empty key") return nil, errors.New("disconnect: empty session ID")
} }
m.sessionMu.Lock() m.sessionMu.Lock()
if s, ok := m.session[key]; ok { if s, ok := m.session[sessionID]; ok {
if s.cancelBuild != nil { if s.cancelBuild != nil {
s.cancelBuild() s.cancelBuild()
} }
@@ -115,7 +116,7 @@ func (m *Server) Disconnect(ctx context.Context, req *pb.DisconnectRequest) (res
s.result.Done() s.result.Done()
} }
} }
delete(m.session, key) delete(m.session, sessionID)
m.sessionMu.Unlock() m.sessionMu.Unlock()
return &pb.DisconnectResponse{}, nil return &pb.DisconnectResponse{}, nil
@@ -136,26 +137,26 @@ func (m *Server) Close() error {
} }
func (m *Server) Inspect(ctx context.Context, req *pb.InspectRequest) (*pb.InspectResponse, error) { func (m *Server) Inspect(ctx context.Context, req *pb.InspectRequest) (*pb.InspectResponse, error) {
ref := req.Ref sessionID := req.SessionID
if ref == "" { if sessionID == "" {
return nil, errors.New("inspect: empty key") return nil, errors.New("inspect: empty session ID")
} }
var bo *pb.BuildOptions var bo *pb.BuildOptions
m.sessionMu.Lock() m.sessionMu.Lock()
if s, ok := m.session[ref]; ok { if s, ok := m.session[sessionID]; ok {
bo = s.buildOptions bo = s.buildOptions
} else { } else {
m.sessionMu.Unlock() m.sessionMu.Unlock()
return nil, errors.Errorf("inspect: unknown key %v", ref) return nil, errors.Errorf("inspect: unknown key %v", sessionID)
} }
m.sessionMu.Unlock() m.sessionMu.Unlock()
return &pb.InspectResponse{Options: bo}, nil return &pb.InspectResponse{Options: bo}, nil
} }
func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResponse, error) { func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResponse, error) {
ref := req.Ref sessionID := req.SessionID
if ref == "" { if sessionID == "" {
return nil, errors.New("build: empty key") return nil, errors.New("build: empty session ID")
} }
// Prepare status channel and session // Prepare status channel and session
@@ -163,7 +164,7 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
if m.session == nil { if m.session == nil {
m.session = make(map[string]*session) m.session = make(map[string]*session)
} }
s, ok := m.session[ref] s, ok := m.session[sessionID]
if ok { if ok {
if !s.buildOnGoing.CompareAndSwap(false, true) { if !s.buildOnGoing.CompareAndSwap(false, true) {
m.sessionMu.Unlock() m.sessionMu.Unlock()
@@ -182,12 +183,12 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
inR, inW := io.Pipe() inR, inW := io.Pipe()
defer inR.Close() defer inR.Close()
s.inputPipe = inW s.inputPipe = inW
m.session[ref] = s m.session[sessionID] = s
m.sessionMu.Unlock() m.sessionMu.Unlock()
defer func() { defer func() {
close(statusChan) close(statusChan)
m.sessionMu.Lock() m.sessionMu.Lock()
s, ok := m.session[ref] s, ok := m.session[sessionID]
if ok { if ok {
s.statusChan = nil s.statusChan = nil
s.buildOnGoing.Store(false) s.buildOnGoing.Store(false)
@@ -202,20 +203,25 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
defer cancel() defer cancel()
resp, res, _, buildErr := m.buildFunc(ctx, req.Options, inR, pw) resp, res, _, buildErr := m.buildFunc(ctx, req.Options, inR, pw)
m.sessionMu.Lock() m.sessionMu.Lock()
if s, ok := m.session[ref]; ok { if s, ok := m.session[sessionID]; ok {
// NOTE: buildFunc can return *build.ResultHandle even on error (e.g. when it's implemented using (github.com/docker/buildx/controller/build).RunBuild). // NOTE: buildFunc can return *build.ResultHandle even on error (e.g. when it's implemented using (github.com/docker/buildx/controller/build).RunBuild).
if res != nil { if res != nil {
s.result = res s.result = res
s.cancelBuild = cancel s.cancelBuild = cancel
s.buildOptions = req.Options s.buildOptions = req.Options
m.session[ref] = s m.session[sessionID] = s
if buildErr != nil { if buildErr != nil {
buildErr = controllererrors.WrapBuild(buildErr, ref) var ref string
var ebr *desktop.ErrorWithBuildRef
if errors.As(buildErr, &ebr) {
ref = ebr.Ref
}
buildErr = controllererrors.WrapBuild(buildErr, sessionID, ref)
} }
} }
} else { } else {
m.sessionMu.Unlock() m.sessionMu.Unlock()
return nil, errors.Errorf("build: unknown key %v", ref) return nil, errors.Errorf("build: unknown session ID %v", sessionID)
} }
m.sessionMu.Unlock() m.sessionMu.Unlock()
@@ -232,9 +238,9 @@ func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResp
} }
func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer) error { func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer) error {
ref := req.Ref sessionID := req.SessionID
if ref == "" { if sessionID == "" {
return errors.New("status: empty key") return errors.New("status: empty session ID")
} }
// Wait and get status channel prepared by Build() // Wait and get status channel prepared by Build()
@@ -242,12 +248,12 @@ func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer
for { for {
// TODO: timeout? // TODO: timeout?
m.sessionMu.Lock() m.sessionMu.Lock()
if _, ok := m.session[ref]; !ok || m.session[ref].statusChan == nil { if _, ok := m.session[sessionID]; !ok || m.session[sessionID].statusChan == nil {
m.sessionMu.Unlock() m.sessionMu.Unlock()
time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable
continue continue
} }
statusChan = m.session[ref].statusChan statusChan = m.session[sessionID].statusChan
m.sessionMu.Unlock() m.sessionMu.Unlock()
break break
} }
@@ -278,9 +284,9 @@ func (m *Server) Input(stream pb.Controller_InputServer) (err error) {
if init == nil { if init == nil {
return errors.Errorf("unexpected message: %T; wanted init", msg.GetInit()) return errors.Errorf("unexpected message: %T; wanted init", msg.GetInit())
} }
ref := init.Ref sessionID := init.SessionID
if ref == "" { if sessionID == "" {
return errors.New("input: no ref is provided") return errors.New("input: no session ID is provided")
} }
// Wait and get input stream pipe prepared by Build() // Wait and get input stream pipe prepared by Build()
@@ -288,12 +294,12 @@ func (m *Server) Input(stream pb.Controller_InputServer) (err error) {
for { for {
// TODO: timeout? // TODO: timeout?
m.sessionMu.Lock() m.sessionMu.Lock()
if _, ok := m.session[ref]; !ok || m.session[ref].inputPipe == nil { if _, ok := m.session[sessionID]; !ok || m.session[sessionID].inputPipe == nil {
m.sessionMu.Unlock() m.sessionMu.Unlock()
time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable
continue continue
} }
inputPipeW = m.session[ref].inputPipe inputPipeW = m.session[sessionID].inputPipe
m.sessionMu.Unlock() m.sessionMu.Unlock()
break break
} }
@@ -373,14 +379,14 @@ func (m *Server) Invoke(srv pb.Controller_InvokeServer) error {
initErrCh <- retErr initErrCh <- retErr
} }
}() }()
ref := initMessage.Ref sessionID := initMessage.SessionID
cfg := initMessage.InvokeConfig cfg := initMessage.InvokeConfig
m.sessionMu.Lock() m.sessionMu.Lock()
s, ok := m.session[ref] s, ok := m.session[sessionID]
if !ok { if !ok {
m.sessionMu.Unlock() m.sessionMu.Unlock()
return errors.Errorf("invoke: unknown key %v", ref) return errors.Errorf("invoke: unknown session ID %v", sessionID)
} }
m.sessionMu.Unlock() m.sessionMu.Unlock()

View File

@@ -844,7 +844,7 @@ The following example forces the builder to always pull all images referenced in
```hcl ```hcl
target "default" { target "default" {
pull = "always" pull = true
} }
``` ```

View File

@@ -626,7 +626,7 @@ For example, the following Dockerfile contains four stages:
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM oven/bun:1 as base FROM oven/bun:1 AS base
WORKDIR /app WORKDIR /app
FROM base AS install FROM base AS install
@@ -912,17 +912,39 @@ For more information about how to use build secrets, see
Supported types are: Supported types are:
- [`file`](#file) - [`type=file`](#typefile)
- [`env`](#env) - [`type=env`](#typeenv)
Buildx attempts to detect the `type` automatically if unset. Buildx attempts to detect the `type` automatically if unset. If an environment
variable with the same key as `id` is set, then Buildx uses `type=env` and the
variable value becomes the secret. If no such environment variable is set, and
`type` is not set, then Buildx falls back to `type=file`.
#### `file` #### `type=file`
Attribute keys: Source a build secret from a file.
- `id` - ID of the secret. Defaults to base name of the `src` path. ##### `type=file` synopsis
- `src`, `source` - Secret filename. `id` used if unset.
```console
$ docker buildx build --secret [type=file,]id=<ID>[,src=<FILEPATH>] .
```
##### `type=file` attributes
| Key | Description | Default |
| --------------- | ----------------------------------------------------------------------------------------------------- | -------------------------- |
| `id` | ID of the secret. | N/A (this key is required) |
| `src`, `source` | Filepath of the file containing the secret value (absolute or relative to current working directory). | `id` if unset. |
###### `type=file` usage
In the following example, `type=file` is automatically detected because no
environment variable mathing `aws` (the ID) is set.
```console
$ docker buildx build --secret id=aws,src=$HOME/.aws/credentials .
```
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
@@ -932,16 +954,31 @@ RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
aws s3 cp s3://... ... aws s3 cp s3://... ...
``` ```
#### `type=env`
Source a build secret from an environment variable.
##### `type=env` synopsis
```console ```console
$ docker buildx build --secret id=aws,src=$HOME/.aws/credentials . $ docker buildx build --secret [type=env,]id=<ID>[,env=<VARIABLE>] .
``` ```
#### `env` ##### `type=env` attributes
Attribute keys: | Key | Description | Default |
| ---------------------- | ----------------------------------------------- | -------------------------- |
| `id` | ID of the secret. | N/A (this key is required) |
| `env`, `src`, `source` | Environment variable to source the secret from. | `id` if unset. |
- `id` - ID of the secret. Defaults to `env` name. ##### `type=env` usage
- `env` - Secret environment variable. `id` used if unset, otherwise will look for `src`, `source` if `id` unset.
In the following example, `type=env` is automatically detected because an
environment variable matching `id` is set.
```console
$ SECRET_TOKEN=token docker buildx build --secret id=SECRET_TOKEN .
```
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
@@ -951,10 +988,26 @@ RUN --mount=type=bind,target=. \
yarn run test yarn run test
``` ```
In the following example, the build argument `SECRET_TOKEN` is set to contain
the value of the environment variable `API_KEY`.
```console ```console
$ SECRET_TOKEN=token docker buildx build --secret id=SECRET_TOKEN . $ API_KEY=token docker buildx build --secret id=SECRET_TOKEN,env=API_KEY .
``` ```
You can also specify the name of the environment variable with `src` or `source`:
```console
$ API_KEY=token docker buildx build --secret type=env,id=SECRET_TOKEN,src=API_KEY .
```
> [!NOTE]
> Specifying the environment variable name with `src` or `source`, you are
> required to set `type=env` explicitly, or else Buildx assumes that the secret
> is `type=file`, and looks for a file with the name of `src` or `source` (in
> this case, a file named `API_KEY` relative to the location where the `docker
> buildx build` command was executed.
### <a name="shm-size"></a> Shared memory size for build containers (--shm-size) ### <a name="shm-size"></a> Shared memory size for build containers (--shm-size)
Sets the size of the shared memory allocated for build containers when using Sets the size of the shared memory allocated for build containers when using

17
go.mod
View File

@@ -6,10 +6,10 @@ require (
github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/semver/v3 v3.2.1
github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/go-winio v0.6.2
github.com/aws/aws-sdk-go-v2/config v1.26.6 github.com/aws/aws-sdk-go-v2/config v1.26.6
github.com/compose-spec/compose-go/v2 v2.2.0 github.com/compose-spec/compose-go/v2 v2.4.1
github.com/containerd/console v1.0.4 github.com/containerd/console v1.0.4
github.com/containerd/containerd v1.7.22 github.com/containerd/containerd v1.7.22
github.com/containerd/continuity v0.4.3 github.com/containerd/continuity v0.4.4
github.com/containerd/errdefs v0.1.0 github.com/containerd/errdefs v0.1.0
github.com/containerd/log v0.1.0 github.com/containerd/log v0.1.0
github.com/containerd/platforms v0.2.1 github.com/containerd/platforms v0.2.1
@@ -27,7 +27,7 @@ require (
github.com/hashicorp/hcl/v2 v2.20.1 github.com/hashicorp/hcl/v2 v2.20.1
github.com/in-toto/in-toto-golang v0.5.0 github.com/in-toto/in-toto-golang v0.5.0
github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/moby/buildkit v0.17.0-rc1 github.com/moby/buildkit v0.17.0-rc2
github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/mountinfo v0.7.2
github.com/moby/sys/signal v0.7.1 github.com/moby/sys/signal v0.7.1
github.com/morikuni/aec v1.0.0 github.com/morikuni/aec v1.0.0
@@ -41,7 +41,7 @@ require (
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/tonistiigi/fsutil v0.0.0-20241003195857-3f140a1299b0 github.com/tonistiigi/fsutil v0.0.0-20241028165955-397af5306b5c
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4
github.com/zclconf/go-cty v1.14.4 github.com/zclconf/go-cty v1.14.4
go.opentelemetry.io/otel v1.21.0 go.opentelemetry.io/otel v1.21.0
@@ -50,12 +50,12 @@ require (
go.opentelemetry.io/otel/trace v1.21.0 go.opentelemetry.io/otel/trace v1.21.0
golang.org/x/mod v0.21.0 golang.org/x/mod v0.21.0
golang.org/x/sync v0.8.0 golang.org/x/sync v0.8.0
golang.org/x/sys v0.25.0 golang.org/x/sys v0.26.0
golang.org/x/term v0.24.0 golang.org/x/term v0.24.0
golang.org/x/text v0.18.0 golang.org/x/text v0.18.0
google.golang.org/grpc v1.66.2 google.golang.org/grpc v1.66.2
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
google.golang.org/protobuf v1.34.1 google.golang.org/protobuf v1.35.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.2 k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2 k8s.io/apimachinery v0.29.2
@@ -86,7 +86,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/containerd/api v1.7.19 // indirect github.com/containerd/containerd/api v1.7.19 // indirect
github.com/containerd/ttrpc v1.2.5 // indirect github.com/containerd/ttrpc v1.2.5 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect
@@ -117,7 +117,7 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.17.11 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect
@@ -147,6 +147,7 @@ require (
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/theupdateframework/notary v0.7.0 // indirect github.com/theupdateframework/notary v0.7.0 // indirect
github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect

40
go.sum
View File

@@ -14,8 +14,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ= github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0=
github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8=
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
@@ -83,18 +83,19 @@ github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnTh
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.2.0 h1:VsQosGhuO+H9wh5laiIiAe4TVd73kQ5NWwmNrdm0HRA= github.com/compose-spec/compose-go/v2 v2.4.1 h1:tEg6Qn/9LZnKg42fZlFmxN4lxSqnCvsiG5TXnxzvI4c=
github.com/compose-spec/compose-go/v2 v2.2.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/compose-spec/compose-go/v2 v2.4.1/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0= github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0=
github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g= github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g=
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA= github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig= github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
@@ -112,8 +113,9 @@ github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oL
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso=
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -264,8 +266,8 @@ github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVE
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -301,8 +303,8 @@ github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/z
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.17.0-rc1 h1:LTHa+CEoGZGWWEJcOEUj/5fv+6FPvMZTOD/KVEW4syA= github.com/moby/buildkit v0.17.0-rc2 h1:+L7qAYuBEA9D7IBTEYdzFf4SsC7JBEOcAG8oRVrzveA=
github.com/moby/buildkit v0.17.0-rc1/go.mod h1:BprE7bOBNMZPwd3YR7iUmHdqt618BDvS49hZySzr5Mg= github.com/moby/buildkit v0.17.0-rc2/go.mod h1:ru8NFyDHD8HbuKaLXJIjK9nr3x6FZR+IWjtF07S+wdM=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -439,8 +441,10 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c=
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
github.com/tonistiigi/fsutil v0.0.0-20241003195857-3f140a1299b0 h1:H9++AiQUqjwrOMA/DOpWhxWp3JLyyT+MN4sRPbMmwoY= github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 h1:eUk79E1w8yMtXeHSzjKorxuC8qJOnyXQnLaJehxpJaI=
github.com/tonistiigi/fsutil v0.0.0-20241003195857-3f140a1299b0/go.mod h1:Dl/9oEjK7IqnjAm21Okx/XIxUCFJzvh+XdVHUlBwXTw= github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=
github.com/tonistiigi/fsutil v0.0.0-20241028165955-397af5306b5c h1:bQLsfX+uEPZUjyR2qmoJs5F8Z57bPVmF3IsUf22Xo9Y=
github.com/tonistiigi/fsutil v0.0.0-20241028165955-397af5306b5c/go.mod h1:Dl/9oEjK7IqnjAm21Okx/XIxUCFJzvh+XdVHUlBwXTw=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8= github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE= github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
@@ -543,8 +547,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
@@ -577,8 +581,8 @@ google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII=

View File

@@ -8,7 +8,7 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"github.com/docker/docker/pkg/ioutils" "github.com/docker/buildx/util/confutil"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@@ -42,18 +42,18 @@ type StateGroup struct {
} }
type LocalState struct { type LocalState struct {
root string cfg *confutil.Config
} }
func New(root string) (*LocalState, error) { func New(cfg *confutil.Config) (*LocalState, error) {
if root == "" { if cfg.Dir() == "" {
return nil, errors.Errorf("root dir empty") return nil, errors.Errorf("config dir empty")
} }
if err := os.MkdirAll(filepath.Join(root, refsDir), 0700); err != nil { if err := cfg.MkdirAll(refsDir, 0700); err != nil {
return nil, err return nil, err
} }
return &LocalState{ return &LocalState{
root: root, cfg: cfg,
}, nil }, nil
} }
@@ -61,7 +61,7 @@ func (ls *LocalState) ReadRef(builderName, nodeName, id string) (*State, error)
if err := ls.validate(builderName, nodeName, id); err != nil { if err := ls.validate(builderName, nodeName, id); err != nil {
return nil, err return nil, err
} }
dt, err := os.ReadFile(filepath.Join(ls.root, refsDir, builderName, nodeName, id)) dt, err := os.ReadFile(filepath.Join(ls.cfg.Dir(), refsDir, builderName, nodeName, id))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -76,19 +76,19 @@ func (ls *LocalState) SaveRef(builderName, nodeName, id string, st State) error
if err := ls.validate(builderName, nodeName, id); err != nil { if err := ls.validate(builderName, nodeName, id); err != nil {
return err return err
} }
refDir := filepath.Join(ls.root, refsDir, builderName, nodeName) refDir := filepath.Join(refsDir, builderName, nodeName)
if err := os.MkdirAll(refDir, 0700); err != nil { if err := ls.cfg.MkdirAll(refDir, 0700); err != nil {
return err return err
} }
dt, err := json.Marshal(st) dt, err := json.Marshal(st)
if err != nil { if err != nil {
return err return err
} }
return ioutils.AtomicWriteFile(filepath.Join(refDir, id), dt, 0600) return ls.cfg.AtomicWriteFile(filepath.Join(refDir, id), dt, 0644)
} }
func (ls *LocalState) ReadGroup(id string) (*StateGroup, error) { func (ls *LocalState) ReadGroup(id string) (*StateGroup, error) {
dt, err := os.ReadFile(filepath.Join(ls.root, refsDir, groupDir, id)) dt, err := os.ReadFile(filepath.Join(ls.cfg.Dir(), refsDir, groupDir, id))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -100,15 +100,15 @@ func (ls *LocalState) ReadGroup(id string) (*StateGroup, error) {
} }
func (ls *LocalState) SaveGroup(id string, stg StateGroup) error { func (ls *LocalState) SaveGroup(id string, stg StateGroup) error {
refDir := filepath.Join(ls.root, refsDir, groupDir) refDir := filepath.Join(refsDir, groupDir)
if err := os.MkdirAll(refDir, 0700); err != nil { if err := ls.cfg.MkdirAll(refDir, 0700); err != nil {
return err return err
} }
dt, err := json.Marshal(stg) dt, err := json.Marshal(stg)
if err != nil { if err != nil {
return err return err
} }
return ioutils.AtomicWriteFile(filepath.Join(refDir, id), dt, 0600) return ls.cfg.AtomicWriteFile(filepath.Join(refDir, id), dt, 0600)
} }
func (ls *LocalState) RemoveBuilder(builderName string) error { func (ls *LocalState) RemoveBuilder(builderName string) error {
@@ -116,7 +116,7 @@ func (ls *LocalState) RemoveBuilder(builderName string) error {
return errors.Errorf("builder name empty") return errors.Errorf("builder name empty")
} }
dir := filepath.Join(ls.root, refsDir, builderName) dir := filepath.Join(ls.cfg.Dir(), refsDir, builderName)
if _, err := os.Lstat(dir); err != nil { if _, err := os.Lstat(dir); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return err
@@ -147,7 +147,7 @@ func (ls *LocalState) RemoveBuilderNode(builderName string, nodeName string) err
return errors.Errorf("node name empty") return errors.Errorf("node name empty")
} }
dir := filepath.Join(ls.root, refsDir, builderName, nodeName) dir := filepath.Join(ls.cfg.Dir(), refsDir, builderName, nodeName)
if _, err := os.Lstat(dir); err != nil { if _, err := os.Lstat(dir); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return err
@@ -208,7 +208,7 @@ func (ls *LocalState) removeGroup(id string) error {
if id == "" { if id == "" {
return errors.Errorf("group ref empty") return errors.Errorf("group ref empty")
} }
f := filepath.Join(ls.root, refsDir, groupDir, id) f := filepath.Join(ls.cfg.Dir(), refsDir, groupDir, id)
if _, err := os.Lstat(f); err != nil { if _, err := os.Lstat(f); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return err

View File

@@ -4,6 +4,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/docker/buildx/util/confutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -39,10 +40,10 @@ func newls(t *testing.T) *LocalState {
t.Helper() t.Helper()
tmpdir := t.TempDir() tmpdir := t.TempDir()
l, err := New(tmpdir) l, err := New(confutil.NewConfig(nil, confutil.WithDir(tmpdir)))
require.NoError(t, err) require.NoError(t, err)
require.DirExists(t, filepath.Join(tmpdir, refsDir)) require.DirExists(t, filepath.Join(tmpdir, refsDir))
require.Equal(t, tmpdir, l.root) require.Equal(t, tmpdir, l.cfg.Dir())
require.NoError(t, l.SaveRef(testBuilderName, testNodeName, testStateRefID, testStateRef)) require.NoError(t, l.SaveRef(testBuilderName, testNodeName, testStateRefID, testStateRef))

View File

@@ -8,7 +8,7 @@ import (
"time" "time"
"github.com/docker/buildx/localstate" "github.com/docker/buildx/localstate"
"github.com/docker/docker/pkg/ioutils" "github.com/docker/buildx/util/confutil"
"github.com/gofrs/flock" "github.com/gofrs/flock"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
@@ -20,25 +20,25 @@ const (
activityDir = "activity" activityDir = "activity"
) )
func New(root string) (*Store, error) { func New(cfg *confutil.Config) (*Store, error) {
if err := os.MkdirAll(filepath.Join(root, instanceDir), 0700); err != nil { if err := cfg.MkdirAll(instanceDir, 0700); err != nil {
return nil, err return nil, err
} }
if err := os.MkdirAll(filepath.Join(root, defaultsDir), 0700); err != nil { if err := cfg.MkdirAll(defaultsDir, 0700); err != nil {
return nil, err return nil, err
} }
if err := os.MkdirAll(filepath.Join(root, activityDir), 0700); err != nil { if err := cfg.MkdirAll(activityDir, 0700); err != nil {
return nil, err return nil, err
} }
return &Store{root: root}, nil return &Store{cfg: cfg}, nil
} }
type Store struct { type Store struct {
root string cfg *confutil.Config
} }
func (s *Store) Txn() (*Txn, func(), error) { func (s *Store) Txn() (*Txn, func(), error) {
l := flock.New(filepath.Join(s.root, ".lock")) l := flock.New(filepath.Join(s.cfg.Dir(), ".lock"))
if err := l.Lock(); err != nil { if err := l.Lock(); err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -54,7 +54,7 @@ type Txn struct {
} }
func (t *Txn) List() ([]*NodeGroup, error) { func (t *Txn) List() ([]*NodeGroup, error) {
pp := filepath.Join(t.s.root, instanceDir) pp := filepath.Join(t.s.cfg.Dir(), instanceDir)
fis, err := os.ReadDir(pp) fis, err := os.ReadDir(pp)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -84,7 +84,7 @@ func (t *Txn) NodeGroupByName(name string) (*NodeGroup, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
dt, err := os.ReadFile(filepath.Join(t.s.root, instanceDir, name)) dt, err := os.ReadFile(filepath.Join(t.s.cfg.Dir(), instanceDir, name))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -110,7 +110,7 @@ func (t *Txn) Save(ng *NodeGroup) error {
if err != nil { if err != nil {
return err return err
} }
return ioutils.AtomicWriteFile(filepath.Join(t.s.root, instanceDir, name), dt, 0600) return t.s.cfg.AtomicWriteFile(filepath.Join(instanceDir, name), dt, 0600)
} }
func (t *Txn) Remove(name string) error { func (t *Txn) Remove(name string) error {
@@ -121,14 +121,14 @@ func (t *Txn) Remove(name string) error {
if err := t.RemoveLastActivity(name); err != nil { if err := t.RemoveLastActivity(name); err != nil {
return err return err
} }
ls, err := localstate.New(t.s.root) ls, err := localstate.New(t.s.cfg)
if err != nil { if err != nil {
return err return err
} }
if err := ls.RemoveBuilder(name); err != nil { if err := ls.RemoveBuilder(name); err != nil {
return err return err
} }
return os.RemoveAll(filepath.Join(t.s.root, instanceDir, name)) return os.RemoveAll(filepath.Join(t.s.cfg.Dir(), instanceDir, name))
} }
func (t *Txn) SetCurrent(key, name string, global, def bool) error { func (t *Txn) SetCurrent(key, name string, global, def bool) error {
@@ -141,28 +141,28 @@ func (t *Txn) SetCurrent(key, name string, global, def bool) error {
if err != nil { if err != nil {
return err return err
} }
if err := ioutils.AtomicWriteFile(filepath.Join(t.s.root, "current"), dt, 0600); err != nil { if err := t.s.cfg.AtomicWriteFile("current", dt, 0600); err != nil {
return err return err
} }
h := toHash(key) h := toHash(key)
if def { if def {
if err := ioutils.AtomicWriteFile(filepath.Join(t.s.root, defaultsDir, h), []byte(name), 0600); err != nil { if err := t.s.cfg.AtomicWriteFile(filepath.Join(defaultsDir, h), []byte(name), 0600); err != nil {
return err return err
} }
} else { } else {
os.RemoveAll(filepath.Join(t.s.root, defaultsDir, h)) // ignore error os.RemoveAll(filepath.Join(t.s.cfg.Dir(), defaultsDir, h)) // ignore error
} }
return nil return nil
} }
func (t *Txn) UpdateLastActivity(ng *NodeGroup) error { func (t *Txn) UpdateLastActivity(ng *NodeGroup) error {
return ioutils.AtomicWriteFile(filepath.Join(t.s.root, activityDir, ng.Name), []byte(time.Now().UTC().Format(time.RFC3339)), 0600) return t.s.cfg.AtomicWriteFile(filepath.Join(activityDir, ng.Name), []byte(time.Now().UTC().Format(time.RFC3339)), 0600)
} }
func (t *Txn) GetLastActivity(ng *NodeGroup) (la time.Time, _ error) { func (t *Txn) GetLastActivity(ng *NodeGroup) (la time.Time, _ error) {
dt, err := os.ReadFile(filepath.Join(t.s.root, activityDir, ng.Name)) dt, err := os.ReadFile(filepath.Join(t.s.cfg.Dir(), activityDir, ng.Name))
if err != nil { if err != nil {
if os.IsNotExist(errors.Cause(err)) { if os.IsNotExist(errors.Cause(err)) {
return la, nil return la, nil
@@ -177,7 +177,7 @@ func (t *Txn) RemoveLastActivity(name string) error {
if err != nil { if err != nil {
return err return err
} }
return os.RemoveAll(filepath.Join(t.s.root, activityDir, name)) return os.RemoveAll(filepath.Join(t.s.cfg.Dir(), activityDir, name))
} }
func (t *Txn) reset(key string) error { func (t *Txn) reset(key string) error {
@@ -185,11 +185,11 @@ func (t *Txn) reset(key string) error {
if err != nil { if err != nil {
return err return err
} }
return ioutils.AtomicWriteFile(filepath.Join(t.s.root, "current"), dt, 0600) return t.s.cfg.AtomicWriteFile("current", dt, 0600)
} }
func (t *Txn) Current(key string) (*NodeGroup, error) { func (t *Txn) Current(key string) (*NodeGroup, error) {
dt, err := os.ReadFile(filepath.Join(t.s.root, "current")) dt, err := os.ReadFile(filepath.Join(t.s.cfg.Dir(), "current"))
if err != nil { if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return nil, err return nil, err
@@ -220,7 +220,7 @@ func (t *Txn) Current(key string) (*NodeGroup, error) {
h := toHash(key) h := toHash(key)
dt, err = os.ReadFile(filepath.Join(t.s.root, defaultsDir, h)) dt, err = os.ReadFile(filepath.Join(t.s.cfg.Dir(), defaultsDir, h))
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
t.reset(key) t.reset(key)

View File

@@ -5,6 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/docker/buildx/util/confutil"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -15,7 +16,7 @@ func TestEmptyStartup(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
s, err := New(tmpdir) s, err := New(confutil.NewConfig(nil, confutil.WithDir(tmpdir)))
require.NoError(t, err) require.NoError(t, err)
txn, release, err := s.Txn() txn, release, err := s.Txn()
@@ -33,7 +34,7 @@ func TestNodeLocking(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
s, err := New(tmpdir) s, err := New(confutil.NewConfig(nil, confutil.WithDir(tmpdir)))
require.NoError(t, err) require.NoError(t, err)
_, release, err := s.Txn() _, release, err := s.Txn()
@@ -68,7 +69,7 @@ func TestNodeManagement(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer os.RemoveAll(tmpdir) defer os.RemoveAll(tmpdir)
s, err := New(tmpdir) s, err := New(confutil.NewConfig(nil, confutil.WithDir(tmpdir)))
require.NoError(t, err) require.NoError(t, err)
txn, release, err := s.Txn() txn, release, err := s.Txn()
@@ -240,7 +241,7 @@ func TestNodeInvalidName(t *testing.T) {
t.Parallel() t.Parallel()
tmpdir := t.TempDir() tmpdir := t.TempDir()
s, err := New(tmpdir) s, err := New(confutil.NewConfig(nil, confutil.WithDir(tmpdir)))
require.NoError(t, err) require.NoError(t, err)
txn, release, err := s.Txn() txn, release, err := s.Txn()

View File

@@ -17,7 +17,7 @@ import (
// GetStore returns current builder instance store // GetStore returns current builder instance store
func GetStore(dockerCli command.Cli) (*store.Txn, func(), error) { func GetStore(dockerCli command.Cli) (*store.Txn, func(), error) {
s, err := store.New(confutil.ConfigDir(dockerCli)) s, err := store.New(confutil.NewConfig(dockerCli))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@@ -17,6 +17,7 @@ import (
"github.com/containerd/platforms" "github.com/containerd/platforms"
"github.com/creack/pty" "github.com/creack/pty"
"github.com/docker/buildx/localstate" "github.com/docker/buildx/localstate"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/gitutil" "github.com/docker/buildx/util/gitutil"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/frontend/subrequests/lint" "github.com/moby/buildkit/frontend/subrequests/lint"
@@ -167,7 +168,7 @@ COPY --from=base /etc/bar /bar
err = json.Unmarshal(dt, &md) err = json.Unmarshal(dt, &md)
require.NoError(t, err) require.NoError(t, err)
ls, err := localstate.New(buildxConfig(sb)) ls, err := localstate.New(confutil.NewConfig(nil, confutil.WithDir(buildxConfig(sb))))
require.NoError(t, err) require.NoError(t, err)
refParts := strings.Split(md.BuildRef, "/") refParts := strings.Split(md.BuildRef, "/")
@@ -209,7 +210,7 @@ COPY --from=base /etc/bar /bar
err = json.Unmarshal(dt, &md) err = json.Unmarshal(dt, &md)
require.NoError(t, err) require.NoError(t, err)
ls, err := localstate.New(buildxConfig(sb)) ls, err := localstate.New(confutil.NewConfig(nil, confutil.WithDir(buildxConfig(sb))))
require.NoError(t, err) require.NoError(t, err)
refParts := strings.Split(md.BuildRef, "/") refParts := strings.Split(md.BuildRef, "/")
@@ -261,7 +262,7 @@ COPY foo /foo
err = json.Unmarshal(dt, &md) err = json.Unmarshal(dt, &md)
require.NoError(t, err) require.NoError(t, err)
ls, err := localstate.New(buildxConfig(sb)) ls, err := localstate.New(confutil.NewConfig(nil, confutil.WithDir(buildxConfig(sb))))
require.NoError(t, err) require.NoError(t, err)
refParts := strings.Split(md.BuildRef, "/") refParts := strings.Split(md.BuildRef, "/")
@@ -492,11 +493,6 @@ RUN echo foo > /bar`)
require.NoError(t, err, string(out)) require.NoError(t, err, string(out))
require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out)) require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out))
if isExperimental() {
// FIXME: https://github.com/docker/buildx/issues/2382
t.Skip("build details link not displayed in experimental mode when build fails: https://github.com/docker/buildx/issues/2382")
}
// build erroneous dockerfile // build erroneous dockerfile
dockerfile = []byte(`FROM busybox:latest dockerfile = []byte(`FROM busybox:latest
RUN exit 1`) RUN exit 1`)

29
tests/common.go Normal file
View File

@@ -0,0 +1,29 @@
package tests
import (
"testing"
"github.com/moby/buildkit/util/testutil/integration"
"github.com/stretchr/testify/require"
)
var commonTests = []func(t *testing.T, sb integration.Sandbox){
testUnknownCommand,
testUnknownFlag,
}
func testUnknownCommand(t *testing.T, sb integration.Sandbox) {
cmd := buildxCmd(sb, withArgs("foo"))
out, err := cmd.CombinedOutput()
require.Error(t, err, string(out))
cmd = buildxCmd(sb, withArgs("imagetools", "foo"))
out, err = cmd.CombinedOutput()
require.Error(t, err, string(out))
}
func testUnknownFlag(t *testing.T, sb integration.Sandbox) {
cmd := buildxCmd(sb, withArgs("build", "--foo=bar"))
out, err := cmd.CombinedOutput()
require.Error(t, err, string(out))
}

View File

@@ -21,6 +21,7 @@ func init() {
func TestIntegration(t *testing.T) { func TestIntegration(t *testing.T) {
var tests []func(t *testing.T, sb integration.Sandbox) var tests []func(t *testing.T, sb integration.Sandbox)
tests = append(tests, commonTests...)
tests = append(tests, buildTests...) tests = append(tests, buildTests...)
tests = append(tests, bakeTests...) tests = append(tests, bakeTests...)
tests = append(tests, inspectTests...) tests = append(tests, inspectTests...)

View File

@@ -1,39 +1,144 @@
package confutil package confutil
import ( import (
"crypto/rand"
"encoding/hex"
"os" "os"
"path"
"path/filepath" "path/filepath"
"sync"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/docker/pkg/ioutils"
"github.com/pelletier/go-toml" "github.com/pelletier/go-toml"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" fs "github.com/tonistiigi/fsutil/copy"
) )
// ConfigDir will look for correct configuration store path; const defaultBuildKitConfigFile = "buildkitd.default.toml"
// if `$BUILDX_CONFIG` is set - use it, otherwise use parent directory
// of Docker config file (i.e. `${DOCKER_CONFIG}/buildx`)
func ConfigDir(dockerCli command.Cli) string {
if buildxConfig := os.Getenv("BUILDX_CONFIG"); buildxConfig != "" {
logrus.Debugf("using config store %q based in \"$BUILDX_CONFIG\" environment variable", buildxConfig)
return buildxConfig
}
buildxConfig := filepath.Join(filepath.Dir(dockerCli.ConfigFile().Filename), "buildx") type Config struct {
logrus.Debugf("using default config store %q", buildxConfig) dir string
return buildxConfig chowner *chowner
} }
// DefaultConfigFile returns the default BuildKit configuration file path type chowner struct {
func DefaultConfigFile(dockerCli command.Cli) (string, bool) { uid int
f := path.Join(ConfigDir(dockerCli), "buildkitd.default.toml") gid int
}
type ConfigOption func(*configOptions)
type configOptions struct {
dir string
}
func WithDir(dir string) ConfigOption {
return func(o *configOptions) {
o.dir = dir
}
}
func NewConfig(dockerCli command.Cli, opts ...ConfigOption) *Config {
co := configOptions{}
for _, opt := range opts {
opt(&co)
}
configDir := co.dir
if configDir == "" {
configDir = os.Getenv("BUILDX_CONFIG")
if configDir == "" {
configDir = filepath.Join(filepath.Dir(dockerCli.ConfigFile().Filename), "buildx")
}
}
return &Config{
dir: configDir,
chowner: sudoer(configDir),
}
}
// Dir will look for correct configuration store path;
// if `$BUILDX_CONFIG` is set - use it, otherwise use parent directory
// of Docker config file (i.e. `${DOCKER_CONFIG}/buildx`)
func (c *Config) Dir() string {
return c.dir
}
// BuildKitConfigFile returns the default BuildKit configuration file path
func (c *Config) BuildKitConfigFile() (string, bool) {
f := filepath.Join(c.dir, defaultBuildKitConfigFile)
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
return f, true return f, true
} }
return "", false return "", false
} }
// MkdirAll creates a directory and all necessary parents within the config dir.
func (c *Config) MkdirAll(dir string, perm os.FileMode) error {
var chown fs.Chowner
if c.chowner != nil {
chown = func(user *fs.User) (*fs.User, error) {
return &fs.User{UID: c.chowner.uid, GID: c.chowner.gid}, nil
}
}
d := filepath.Join(c.dir, dir)
st, err := os.Stat(d)
if err != nil {
if os.IsNotExist(err) {
_, err := fs.MkdirAll(d, perm, chown, nil)
return err
}
return err
}
// if directory already exists, fix the owner if necessary
if c.chowner == nil {
return nil
}
currentOwner := fileOwner(st)
if currentOwner != nil && (currentOwner.uid != c.chowner.uid || currentOwner.gid != c.chowner.gid) {
return os.Chown(d, c.chowner.uid, c.chowner.gid)
}
return nil
}
// AtomicWriteFile writes data to a file within the config dir atomically
func (c *Config) AtomicWriteFile(filename string, data []byte, perm os.FileMode) error {
f := filepath.Join(c.dir, filename)
if err := ioutils.AtomicWriteFile(f, data, perm); err != nil {
return err
}
if c.chowner == nil {
return nil
}
return os.Chown(f, c.chowner.uid, c.chowner.gid)
}
var nodeIdentifierMu sync.Mutex
func (c *Config) TryNodeIdentifier() (out string) {
nodeIdentifierMu.Lock()
defer nodeIdentifierMu.Unlock()
sessionFilename := ".buildNodeID"
sessionFilepath := filepath.Join(c.Dir(), sessionFilename)
if _, err := os.Lstat(sessionFilepath); err != nil {
if os.IsNotExist(err) { // create a new file with stored randomness
b := make([]byte, 8)
if _, err := rand.Read(b); err != nil {
return out
}
if err := c.AtomicWriteFile(sessionFilename, []byte(hex.EncodeToString(b)), 0600); err != nil {
return out
}
}
}
dt, err := os.ReadFile(sessionFilepath)
if err == nil {
return string(dt)
}
return
}
// LoadConfigTree loads BuildKit config toml tree // LoadConfigTree loads BuildKit config toml tree
func LoadConfigTree(fp string) (*toml.Tree, error) { func LoadConfigTree(fp string) (*toml.Tree, error) {
f, err := os.Open(fp) f, err := os.Open(fp)

View File

@@ -0,0 +1,60 @@
//go:build !windows
// +build !windows
package confutil
import (
"os"
"os/user"
"path/filepath"
"strconv"
"strings"
"syscall"
)
// sudoer returns the user that invoked the current process with sudo only if
// sudo HOME env matches the home directory of the user that ran sudo and is
// part of configDir.
func sudoer(configDir string) *chowner {
if _, ok := os.LookupEnv("SUDO_COMMAND"); !ok {
return nil
}
suidenv := os.Getenv("SUDO_UID") // https://www.sudo.ws/docs/man/sudo.man/#SUDO_UID
sgidenv := os.Getenv("SUDO_GID") // https://www.sudo.ws/docs/man/sudo.man/#SUDO_GID
if suidenv == "" || sgidenv == "" {
return nil
}
u, err := user.LookupId(suidenv)
if err != nil {
return nil
}
suid, err := strconv.Atoi(suidenv)
if err != nil {
return nil
}
sgid, err := strconv.Atoi(sgidenv)
if err != nil {
return nil
}
home, _ := os.UserHomeDir()
if home == "" || u.HomeDir != home {
return nil
}
if ok, _ := isSubPath(home, configDir); !ok {
return nil
}
return &chowner{uid: suid, gid: sgid}
}
func fileOwner(fi os.FileInfo) *chowner {
st := fi.Sys().(*syscall.Stat_t)
return &chowner{uid: int(st.Uid), gid: int(st.Gid)}
}
func isSubPath(basePath, subPath string) (bool, error) {
rel, err := filepath.Rel(basePath, subPath)
if err != nil {
return false, err
}
return !strings.HasPrefix(rel, "..") && rel != ".", nil
}

View File

@@ -0,0 +1,58 @@
//go:build !windows
// +build !windows
package confutil
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIsSubPath(t *testing.T) {
tests := []struct {
name string
basePath string
subPath string
expected bool
}{
{
name: "SubPath is a direct subdirectory",
basePath: "/home/user",
subPath: "/home/user/docs",
expected: true,
},
{
name: "SubPath is the same as basePath",
basePath: "/home/user",
subPath: "/home/user",
expected: false,
},
{
name: "SubPath is not a subdirectory",
basePath: "/home/user",
subPath: "/home/otheruser",
expected: false,
},
{
name: "SubPath is a nested subdirectory",
basePath: "/home/user",
subPath: "/home/user/docs/reports",
expected: true,
},
{
name: "SubPath is a sibling directory",
basePath: "/home/user",
subPath: "/home/user2",
expected: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
ok, err := isSubPath(tt.basePath, tt.subPath)
assert.NoError(t, err)
assert.Equal(t, tt.expected, ok)
})
}
}

View File

@@ -0,0 +1,11 @@
package confutil
import "os"
func sudoer(_ string) *chowner {
return nil
}
func fileOwner(_ os.FileInfo) *chowner {
return nil
}

View File

@@ -1,34 +0,0 @@
package confutil
import (
"crypto/rand"
"encoding/hex"
"os"
"path/filepath"
"sync"
)
var nodeIdentifierMu sync.Mutex
func TryNodeIdentifier(configDir string) (out string) {
nodeIdentifierMu.Lock()
defer nodeIdentifierMu.Unlock()
sessionFile := filepath.Join(configDir, ".buildNodeID")
if _, err := os.Lstat(sessionFile); err != nil {
if os.IsNotExist(err) { // create a new file with stored randomness
b := make([]byte, 8)
if _, err := rand.Read(b); err != nil {
return out
}
if err := os.WriteFile(sessionFile, []byte(hex.EncodeToString(b)), 0600); err != nil {
return out
}
}
}
dt, err := os.ReadFile(sessionFile)
if err == nil {
return string(dt)
}
return
}

View File

@@ -65,7 +65,6 @@ func hyperlink(url string) string {
type ErrorWithBuildRef struct { type ErrorWithBuildRef struct {
Ref string Ref string
Err error Err error
Msg string
} }
func (e *ErrorWithBuildRef) Error() string { func (e *ErrorWithBuildRef) Error() string {

View File

@@ -403,22 +403,24 @@ func (o *ProjectOptions) GetWorkingDir() (string, error) {
return os.Getwd() return os.Getwd()
} }
func (o *ProjectOptions) GetConfigFiles() ([]types.ConfigFile, error) { // ReadConfigFiles reads ConfigFiles and populates the content field
configPaths, err := o.getConfigPaths() func (o *ProjectOptions) ReadConfigFiles(ctx context.Context, workingDir string, options *ProjectOptions) (*types.ConfigDetails, error) {
config, err := loader.LoadConfigFiles(ctx, options.ConfigPaths, workingDir, options.loadOptions...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
configs := make([][]byte, len(config.ConfigFiles))
var configs []types.ConfigFile for i, c := range config.ConfigFiles {
for _, f := range configPaths { var err error
var b []byte var b []byte
if f == "-" { if c.Filename == "-" {
b, err = io.ReadAll(os.Stdin) b, err = io.ReadAll(os.Stdin)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
f, err := filepath.Abs(f) f, err := filepath.Abs(c.Filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -427,27 +429,31 @@ func (o *ProjectOptions) GetConfigFiles() ([]types.ConfigFile, error) {
return nil, err return nil, err
} }
} }
configs = append(configs, types.ConfigFile{ configs[i] = b
Filename: f,
Content: b,
})
} }
return configs, err for i, c := range configs {
config.ConfigFiles[i].Content = c
}
return config, nil
} }
// LoadProject loads compose file according to options and bind to types.Project go structs // LoadProject loads compose file according to options and bind to types.Project go structs
func (o *ProjectOptions) LoadProject(ctx context.Context) (*types.Project, error) { func (o *ProjectOptions) LoadProject(ctx context.Context) (*types.Project, error) {
configDetails, err := o.prepare() config, err := o.prepare(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
project, err := loader.LoadWithContext(ctx, configDetails, o.loadOptions...) project, err := loader.LoadWithContext(ctx, types.ConfigDetails{
ConfigFiles: config.ConfigFiles,
WorkingDir: config.WorkingDir,
Environment: o.Environment,
}, o.loadOptions...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, config := range configDetails.ConfigFiles { for _, config := range config.ConfigFiles {
project.ComposeFiles = append(project.ComposeFiles, config.Filename) project.ComposeFiles = append(project.ComposeFiles, config.Filename)
} }
@@ -456,36 +462,31 @@ func (o *ProjectOptions) LoadProject(ctx context.Context) (*types.Project, error
// LoadModel loads compose file according to options and returns a raw (yaml tree) model // LoadModel loads compose file according to options and returns a raw (yaml tree) model
func (o *ProjectOptions) LoadModel(ctx context.Context) (map[string]any, error) { func (o *ProjectOptions) LoadModel(ctx context.Context) (map[string]any, error) {
configDetails, err := o.prepare() configDetails, err := o.prepare(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return loader.LoadModelWithContext(ctx, configDetails, o.loadOptions...) return loader.LoadModelWithContext(ctx, *configDetails, o.loadOptions...)
} }
// prepare converts ProjectOptions into loader's types.ConfigDetails and configures default load options // prepare converts ProjectOptions into loader's types.ConfigDetails and configures default load options
func (o *ProjectOptions) prepare() (types.ConfigDetails, error) { func (o *ProjectOptions) prepare(ctx context.Context) (*types.ConfigDetails, error) {
configs, err := o.GetConfigFiles() defaultDir, err := o.GetWorkingDir()
if err != nil { if err != nil {
return types.ConfigDetails{}, err return &types.ConfigDetails{}, err
} }
workingDir, err := o.GetWorkingDir() configDetails, err := o.ReadConfigFiles(ctx, defaultDir, o)
if err != nil { if err != nil {
return types.ConfigDetails{}, err return configDetails, err
}
configDetails := types.ConfigDetails{
ConfigFiles: configs,
WorkingDir: workingDir,
Environment: o.Environment,
} }
o.loadOptions = append(o.loadOptions, o.loadOptions = append(o.loadOptions,
withNamePrecedenceLoad(workingDir, o), withNamePrecedenceLoad(defaultDir, o),
withConvertWindowsPaths(o), withConvertWindowsPaths(o),
withListeners(o)) withListeners(o))
return configDetails, nil return configDetails, nil
} }
@@ -502,8 +503,13 @@ func withNamePrecedenceLoad(absWorkingDir string, options *ProjectOptions) func(
} else if nameFromEnv, ok := options.Environment[consts.ComposeProjectName]; ok && nameFromEnv != "" { } else if nameFromEnv, ok := options.Environment[consts.ComposeProjectName]; ok && nameFromEnv != "" {
opts.SetProjectName(nameFromEnv, true) opts.SetProjectName(nameFromEnv, true)
} else { } else {
dirname := filepath.Base(absWorkingDir)
symlink, err := filepath.EvalSymlinks(absWorkingDir)
if err == nil && filepath.Base(symlink) != dirname {
logrus.Warnf("project has been loaded without an explicit name from a symlink. Using name %q", dirname)
}
opts.SetProjectName( opts.SetProjectName(
loader.NormalizeProjectName(filepath.Base(absWorkingDir)), loader.NormalizeProjectName(dirname),
false, false,
) )
} }

View File

@@ -0,0 +1,38 @@
/*
Copyright 2020 The Compose Specification Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package dotenv
import (
"fmt"
"io"
)
var formats = map[string]Parser{}
type Parser func(r io.Reader, filename string, lookup func(key string) (string, bool)) (map[string]string, error)
func RegisterFormat(format string, p Parser) {
formats[format] = p
}
func ParseWithFormat(r io.Reader, filename string, resolve LookupFn, format string) (map[string]string, error) {
parser, ok := formats[format]
if !ok {
return nil, fmt.Errorf("unsupported env_file format %q", format)
}
return parser(r, filename, resolve)
}

View File

@@ -86,7 +86,7 @@ func ReadWithLookup(lookupFn LookupFn, filenames ...string) (map[string]string,
envMap := make(map[string]string) envMap := make(map[string]string)
for _, filename := range filenames { for _, filename := range filenames {
individualEnvMap, individualErr := readFile(filename, lookupFn) individualEnvMap, individualErr := ReadFile(filename, lookupFn)
if individualErr != nil { if individualErr != nil {
return envMap, individualErr return envMap, individualErr
@@ -129,7 +129,7 @@ func filenamesOrDefault(filenames []string) []string {
} }
func loadFile(filename string, overload bool) error { func loadFile(filename string, overload bool) error {
envMap, err := readFile(filename, nil) envMap, err := ReadFile(filename, nil)
if err != nil { if err != nil {
return err return err
} }
@@ -150,7 +150,7 @@ func loadFile(filename string, overload bool) error {
return nil return nil
} }
func readFile(filename string, lookupFn LookupFn) (map[string]string, error) { func ReadFile(filename string, lookupFn LookupFn) (map[string]string, error) {
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -119,7 +119,7 @@ loop:
offset = i + 1 offset = i + 1
inherited = rune == '\n' inherited = rune == '\n'
break loop break loop
case '_', '.', '[', ']': case '_', '.', '-', '[', ']':
default: default:
// variable name should match [A-Za-z0-9_.-] // variable name should match [A-Za-z0-9_.-]
if unicode.IsLetter(rune) || unicode.IsNumber(rune) { if unicode.IsLetter(rune) || unicode.IsNumber(rune) {
@@ -136,6 +136,10 @@ loop:
return "", "", inherited, errors.New("zero length string") return "", "", inherited, errors.New("zero length string")
} }
if inherited && strings.IndexByte(key, ' ') == -1 {
p.line++
}
// trim whitespace // trim whitespace
key = strings.TrimRightFunc(key, unicode.IsSpace) key = strings.TrimRightFunc(key, unicode.IsSpace)
cutset := strings.TrimLeftFunc(src[offset:], isSpace) cutset := strings.TrimLeftFunc(src[offset:], isSpace)

View File

@@ -95,7 +95,7 @@ func populateFieldFromBuffer(char rune, buffer []rune, volume *types.ServiceVolu
if isBindOption(option) { if isBindOption(option) {
setBindOption(volume, option) setBindOption(volume, option)
} }
// ignore unknown options // ignore unknown options FIXME why not report an error here?
} }
} }
return nil return nil

View File

@@ -30,6 +30,7 @@ import (
"strings" "strings"
"github.com/compose-spec/compose-go/v2/consts" "github.com/compose-spec/compose-go/v2/consts"
"github.com/compose-spec/compose-go/v2/errdefs"
interp "github.com/compose-spec/compose-go/v2/interpolation" interp "github.com/compose-spec/compose-go/v2/interpolation"
"github.com/compose-spec/compose-go/v2/override" "github.com/compose-spec/compose-go/v2/override"
"github.com/compose-spec/compose-go/v2/paths" "github.com/compose-spec/compose-go/v2/paths"
@@ -139,9 +140,9 @@ func (l localResourceLoader) abs(p string) string {
return filepath.Join(l.WorkingDir, p) return filepath.Join(l.WorkingDir, p)
} }
func (l localResourceLoader) Accept(p string) bool { func (l localResourceLoader) Accept(_ string) bool {
_, err := os.Stat(l.abs(p)) // LocalResourceLoader is the last loader tested so it always should accept the config and try to get the content.
return err == nil return true
} }
func (l localResourceLoader) Load(_ context.Context, p string) (string, error) { func (l localResourceLoader) Load(_ context.Context, p string) (string, error) {
@@ -300,6 +301,51 @@ func parseYAML(decoder *yaml.Decoder) (map[string]interface{}, PostProcessor, er
return converted.(map[string]interface{}), &processor, nil return converted.(map[string]interface{}), &processor, nil
} }
// LoadConfigFiles ingests config files with ResourceLoader and returns config details with paths to local copies
func LoadConfigFiles(ctx context.Context, configFiles []string, workingDir string, options ...func(*Options)) (*types.ConfigDetails, error) {
if len(configFiles) < 1 {
return &types.ConfigDetails{}, fmt.Errorf("no configuration file provided: %w", errdefs.ErrNotFound)
}
opts := &Options{}
config := &types.ConfigDetails{
ConfigFiles: make([]types.ConfigFile, len(configFiles)),
}
for _, op := range options {
op(opts)
}
opts.ResourceLoaders = append(opts.ResourceLoaders, localResourceLoader{})
for i, p := range configFiles {
for _, loader := range opts.ResourceLoaders {
_, isLocalResourceLoader := loader.(localResourceLoader)
if !loader.Accept(p) {
continue
}
local, err := loader.Load(ctx, p)
if err != nil {
return nil, err
}
if config.WorkingDir == "" && !isLocalResourceLoader {
config.WorkingDir = filepath.Dir(local)
}
abs, err := filepath.Abs(local)
if err != nil {
abs = local
}
config.ConfigFiles[i] = types.ConfigFile{
Filename: abs,
}
break
}
}
if config.WorkingDir == "" {
config.WorkingDir = workingDir
}
return config, nil
}
// Load reads a ConfigDetails and returns a fully loaded configuration. // Load reads a ConfigDetails and returns a fully loaded configuration.
// Deprecated: use LoadWithContext. // Deprecated: use LoadWithContext.
func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.Project, error) { func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.Project, error) {
@@ -470,6 +516,8 @@ func loadYamlFile(ctx context.Context, file types.ConfigFile, opts *Options, wor
return err return err
} }
dict = OmitEmpty(dict)
// Canonical transformation can reveal duplicates, typically as ports can be a range and conflict with an override // Canonical transformation can reveal duplicates, typically as ports can be a range and conflict with an override
dict, err = override.EnforceUnicity(dict) dict, err = override.EnforceUnicity(dict)
return err return err
@@ -675,6 +723,7 @@ func NormalizeProjectName(s string) string {
var userDefinedKeys = []tree.Path{ var userDefinedKeys = []tree.Path{
"services", "services",
"services.*.depends_on",
"volumes", "volumes",
"networks", "networks",
"secrets", "secrets",
@@ -687,7 +736,7 @@ func processExtensions(dict map[string]any, p tree.Path, extensions map[string]a
for key, value := range dict { for key, value := range dict {
skip := false skip := false
for _, uk := range userDefinedKeys { for _, uk := range userDefinedKeys {
if uk.Matches(p) { if p.Matches(uk) {
skip = true skip = true
break break
} }
@@ -770,14 +819,14 @@ func secretConfigDecoderHook(from, to reflect.Type, data interface{}) (interface
// Check if the input is a map and we're decoding into a SecretConfig // Check if the input is a map and we're decoding into a SecretConfig
if from.Kind() == reflect.Map && to == reflect.TypeOf(types.SecretConfig{}) { if from.Kind() == reflect.Map && to == reflect.TypeOf(types.SecretConfig{}) {
if v, ok := data.(map[string]interface{}); ok { if v, ok := data.(map[string]interface{}); ok {
if ext, ok := v["#extensions"].(map[string]interface{}); ok { if ext, ok := v[consts.Extensions].(map[string]interface{}); ok {
if val, ok := ext[types.SecretConfigXValue].(string); ok { if val, ok := ext[types.SecretConfigXValue].(string); ok {
// Return a map with the Content field populated // Return a map with the Content field populated
v["Content"] = val v["Content"] = val
delete(ext, types.SecretConfigXValue) delete(ext, types.SecretConfigXValue)
if len(ext) == 0 { if len(ext) == 0 {
delete(v, "#extensions") delete(v, consts.Extensions)
} }
} }
} }

View File

@@ -18,6 +18,7 @@ package loader
import ( import (
"fmt" "fmt"
"path"
"strconv" "strconv"
"strings" "strings"
@@ -102,6 +103,17 @@ func Normalize(dict map[string]any, env types.Mapping) (map[string]any, error) {
} }
} }
if v, ok := service["volumes"]; ok {
volumes := v.([]any)
for i, volume := range volumes {
vol := volume.(map[string]any)
target := vol["target"].(string)
vol["target"] = path.Clean(target)
volumes[i] = vol
}
service["volumes"] = volumes
}
if n, ok := service["volumes_from"]; ok { if n, ok := service["volumes_from"]; ok {
volumesFrom := n.([]any) volumesFrom := n.([]any)
for _, v := range volumesFrom { for _, v := range volumesFrom {
@@ -123,9 +135,9 @@ func Normalize(dict map[string]any, env types.Mapping) (map[string]any, error) {
} }
services[name] = service services[name] = service
} }
dict["services"] = services dict["services"] = services
} }
setNameFromKey(dict) setNameFromKey(dict)
return dict, nil return dict, nil

View File

@@ -0,0 +1,74 @@
/*
Copyright 2020 The Compose Specification Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package loader
import "github.com/compose-spec/compose-go/v2/tree"
var omitempty = []tree.Path{
"services.*.dns"}
// OmitEmpty removes empty attributes which are irrelevant when unset
func OmitEmpty(yaml map[string]any) map[string]any {
cleaned := omitEmpty(yaml, tree.NewPath())
return cleaned.(map[string]any)
}
func omitEmpty(data any, p tree.Path) any {
switch v := data.(type) {
case map[string]any:
for k, e := range v {
if isEmpty(e) && mustOmit(p) {
delete(v, k)
continue
}
v[k] = omitEmpty(e, p.Next(k))
}
return v
case []any:
var c []any
for _, e := range v {
if isEmpty(e) && mustOmit(p) {
continue
}
c = append(c, omitEmpty(e, p.Next("[]")))
}
return c
default:
return data
}
}
func mustOmit(p tree.Path) bool {
for _, pattern := range omitempty {
if p.Matches(pattern) {
return true
}
}
return false
}
func isEmpty(e any) bool {
if e == nil {
return true
}
if v, ok := e.(string); ok && v == "" {
return true
}
return false
}

View File

@@ -26,13 +26,15 @@ import (
) )
type ResetProcessor struct { type ResetProcessor struct {
target interface{} target interface{}
paths []tree.Path paths []tree.Path
visitedNodes map[*yaml.Node]string
} }
// UnmarshalYAML implement yaml.Unmarshaler // UnmarshalYAML implement yaml.Unmarshaler
func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error { func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
resolved, err := p.resolveReset(value, tree.NewPath()) resolved, err := p.resolveReset(value, tree.NewPath())
p.visitedNodes = nil
if err != nil { if err != nil {
return err return err
} }
@@ -41,10 +43,28 @@ func (p *ResetProcessor) UnmarshalYAML(value *yaml.Node) error {
// resolveReset detects `!reset` tag being set on yaml nodes and record position in the yaml tree // resolveReset detects `!reset` tag being set on yaml nodes and record position in the yaml tree
func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.Node, error) { func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.Node, error) {
pathStr := path.String()
// If the path contains "<<", removing the "<<" element and merging the path // If the path contains "<<", removing the "<<" element and merging the path
if strings.Contains(path.String(), ".<<") { if strings.Contains(pathStr, ".<<") {
path = tree.NewPath(strings.Replace(path.String(), ".<<", "", 1)) path = tree.NewPath(strings.Replace(pathStr, ".<<", "", 1))
} }
// Check for cycle
if p.visitedNodes == nil {
p.visitedNodes = make(map[*yaml.Node]string)
}
// Check for cycle by seeing if the node has already been visited at this path
if previousPath, found := p.visitedNodes[node]; found {
// If the current node has been visited, we have a cycle if the previous path is a prefix
if strings.HasPrefix(pathStr, previousPath) {
return nil, fmt.Errorf("cycle detected at path: %s", pathStr)
}
}
// Mark the current node as visited
p.visitedNodes[node] = pathStr
// If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags // If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags
if node.Kind == yaml.AliasNode { if node.Kind == yaml.AliasNode {
return p.resolveReset(node.Alias, path) return p.resolveReset(node.Alias, path)

View File

@@ -47,7 +47,7 @@ func init() {
mergeSpecials["services.*.build"] = mergeBuild mergeSpecials["services.*.build"] = mergeBuild
mergeSpecials["services.*.build.args"] = mergeToSequence mergeSpecials["services.*.build.args"] = mergeToSequence
mergeSpecials["services.*.build.additional_contexts"] = mergeToSequence mergeSpecials["services.*.build.additional_contexts"] = mergeToSequence
mergeSpecials["services.*.build.extra_hosts"] = mergeToSequence mergeSpecials["services.*.build.extra_hosts"] = mergeExtraHosts
mergeSpecials["services.*.build.labels"] = mergeToSequence mergeSpecials["services.*.build.labels"] = mergeToSequence
mergeSpecials["services.*.command"] = override mergeSpecials["services.*.command"] = override
mergeSpecials["services.*.depends_on"] = mergeDependsOn mergeSpecials["services.*.depends_on"] = mergeDependsOn
@@ -58,7 +58,7 @@ func init() {
mergeSpecials["services.*.entrypoint"] = override mergeSpecials["services.*.entrypoint"] = override
mergeSpecials["services.*.env_file"] = mergeToSequence mergeSpecials["services.*.env_file"] = mergeToSequence
mergeSpecials["services.*.environment"] = mergeToSequence mergeSpecials["services.*.environment"] = mergeToSequence
mergeSpecials["services.*.extra_hosts"] = mergeToSequence mergeSpecials["services.*.extra_hosts"] = mergeExtraHosts
mergeSpecials["services.*.healthcheck.test"] = override mergeSpecials["services.*.healthcheck.test"] = override
mergeSpecials["services.*.labels"] = mergeToSequence mergeSpecials["services.*.labels"] = mergeToSequence
mergeSpecials["services.*.logging"] = mergeLogging mergeSpecials["services.*.logging"] = mergeLogging
@@ -163,6 +163,22 @@ func mergeNetworks(c any, o any, path tree.Path) (any, error) {
return mergeMappings(right, left, path) return mergeMappings(right, left, path)
} }
func mergeExtraHosts(c any, o any, _ tree.Path) (any, error) {
right := convertIntoSequence(c)
left := convertIntoSequence(o)
// Rewrite content of left slice to remove duplicate elements
i := 0
for _, v := range left {
if !slices.Contains(right, v) {
left[i] = v
i++
}
}
// keep only not duplicated elements from left slice
left = left[:i]
return append(right, left...), nil
}
func mergeToSequence(c any, o any, _ tree.Path) (any, error) { func mergeToSequence(c any, o any, _ tree.Path) (any, error) {
right := convertIntoSequence(c) right := convertIntoSequence(c)
left := convertIntoSequence(o) left := convertIntoSequence(o)
@@ -172,15 +188,21 @@ func mergeToSequence(c any, o any, _ tree.Path) (any, error) {
func convertIntoSequence(value any) []any { func convertIntoSequence(value any) []any {
switch v := value.(type) { switch v := value.(type) {
case map[string]any: case map[string]any:
seq := make([]any, len(v)) var seq []any
i := 0 for k, val := range v {
for k, v := range v { if val == nil {
if v == nil { seq = append(seq, k)
seq[i] = k
} else { } else {
seq[i] = fmt.Sprintf("%s=%v", k, v) switch vl := val.(type) {
// if val is an array we need to add the key with each value one by one
case []any:
for _, vlv := range vl {
seq = append(seq, fmt.Sprintf("%s=%v", k, vlv))
}
default:
seq = append(seq, fmt.Sprintf("%s=%v", k, val))
}
} }
i++
} }
slices.SortFunc(seq, func(a, b any) int { slices.SortFunc(seq, func(a, b any) int {
return cmp.Compare(a.(string), b.(string)) return cmp.Compare(a.(string), b.(string))

View File

@@ -267,6 +267,7 @@
}, },
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true}, "external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
"extra_hosts": {"$ref": "#/definitions/extra_hosts"}, "extra_hosts": {"$ref": "#/definitions/extra_hosts"},
"gpus": {"$ref": "#/definitions/gpus"},
"group_add": { "group_add": {
"type": "array", "type": "array",
"items": { "items": {
@@ -370,6 +371,8 @@
}, },
"uniqueItems": true "uniqueItems": true
}, },
"post_start": {"type": "array", "items": {"$ref": "#/definitions/service_hook"}},
"pre_stop": {"type": "array", "items": {"$ref": "#/definitions/service_hook"}},
"privileged": {"type": ["boolean", "string"]}, "privileged": {"type": ["boolean", "string"]},
"profiles": {"$ref": "#/definitions/list_of_strings"}, "profiles": {"$ref": "#/definitions/list_of_strings"},
"pull_policy": {"type": "string", "enum": [ "pull_policy": {"type": "string", "enum": [
@@ -416,6 +419,7 @@
"properties": { "properties": {
"propagation": {"type": "string"}, "propagation": {"type": "string"},
"create_host_path": {"type": ["boolean", "string"]}, "create_host_path": {"type": ["boolean", "string"]},
"recursive": {"type": "string", "enum": ["enabled", "disabled", "writable", "readonly"]},
"selinux": {"type": "string", "enum": ["z", "Z"]} "selinux": {"type": "string", "enum": ["z", "Z"]}
}, },
"additionalProperties": false, "additionalProperties": false,
@@ -500,11 +504,11 @@
}, },
"additionalProperties": false, "additionalProperties": false,
"patternProperties": {"^x-": {}} "patternProperties": {"^x-": {}}
}, }
"additionalProperties": false,
"patternProperties": {"^x-": {}}
} }
} },
"additionalProperties": false,
"patternProperties": {"^x-": {}}
}, },
"deployment": { "deployment": {
"id": "#/definitions/deployment", "id": "#/definitions/deployment",
@@ -632,6 +636,26 @@
"devices": { "devices": {
"id": "#/definitions/devices", "id": "#/definitions/devices",
"type": "array", "type": "array",
"items": {
"type": "object",
"properties": {
"capabilities": {"$ref": "#/definitions/list_of_strings"},
"count": {"type": ["string", "integer"]},
"device_ids": {"$ref": "#/definitions/list_of_strings"},
"driver":{"type": "string"},
"options":{"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false,
"patternProperties": {"^x-": {}},
"required": [
"capabilities"
]
}
},
"gpus": {
"id": "#/definitions/gpus",
"type": "array",
"items": { "items": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -813,6 +837,20 @@
] ]
}, },
"service_hook": {
"id": "#/definitions/service_hook",
"type": "object",
"properties": {
"command": {"$ref": "#/definitions/command"},
"user": {"type": "string"},
"privileged": {"type": ["boolean", "string"]},
"working_dir": {"type": "string"},
"environment": {"$ref": "#/definitions/list_or_dict"}
},
"additionalProperties": false,
"patternProperties": {"^x-": {}}
},
"env_file": { "env_file": {
"oneOf": [ "oneOf": [
{"type": "string"}, {"type": "string"},
@@ -828,6 +866,9 @@
"path": { "path": {
"type": "string" "type": "string"
}, },
"format": {
"type": "string"
},
"required": { "required": {
"type": ["boolean", "string"], "type": ["boolean", "string"],
"default": true "default": true
@@ -878,7 +919,8 @@
"patternProperties": { "patternProperties": {
".+": { ".+": {
"type": ["string", "array"] "type": ["string", "array"]
} },
"uniqueItems": false
}, },
"additionalProperties": false "additionalProperties": false
}, },

View File

@@ -33,6 +33,7 @@ func init() {
transformers["services.*.extends"] = transformExtends transformers["services.*.extends"] = transformExtends
transformers["services.*.networks"] = transformServiceNetworks transformers["services.*.networks"] = transformServiceNetworks
transformers["services.*.volumes.*"] = transformVolumeMount transformers["services.*.volumes.*"] = transformVolumeMount
transformers["services.*.dns"] = transformStringOrList
transformers["services.*.devices.*"] = transformDeviceMapping transformers["services.*.devices.*"] = transformDeviceMapping
transformers["services.*.secrets.*"] = transformFileMount transformers["services.*.secrets.*"] = transformFileMount
transformers["services.*.configs.*"] = transformFileMount transformers["services.*.configs.*"] = transformFileMount
@@ -48,6 +49,15 @@ func init() {
transformers["include.*"] = transformInclude transformers["include.*"] = transformInclude
} }
func transformStringOrList(data any, _ tree.Path, _ bool) (any, error) {
switch t := data.(type) {
case string:
return []any{t}, nil
default:
return data, nil
}
}
// Canonical transforms a compose model into canonical syntax // Canonical transforms a compose model into canonical syntax
func Canonical(yaml map[string]any, ignoreParseError bool) (map[string]any, error) { func Canonical(yaml map[string]any, ignoreParseError bool) (map[string]any, error) {
canonical, err := transform(yaml, tree.NewPath(), ignoreParseError) canonical, err := transform(yaml, tree.NewPath(), ignoreParseError)

View File

@@ -26,6 +26,8 @@ func init() {
defaultValues["services.*.build"] = defaultBuildContext defaultValues["services.*.build"] = defaultBuildContext
defaultValues["services.*.secrets.*"] = defaultSecretMount defaultValues["services.*.secrets.*"] = defaultSecretMount
defaultValues["services.*.ports.*"] = portDefaults defaultValues["services.*.ports.*"] = portDefaults
defaultValues["services.*.deploy.resources.reservations.devices.*"] = deviceRequestDefaults
defaultValues["services.*.gpus.*"] = deviceRequestDefaults
} }
// SetDefaultValues transforms a compose model to set default values to missing attributes // SetDefaultValues transforms a compose model to set default values to missing attributes

View File

@@ -0,0 +1,36 @@
/*
Copyright 2020 The Compose Specification Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package transform
import (
"fmt"
"github.com/compose-spec/compose-go/v2/tree"
)
func deviceRequestDefaults(data any, p tree.Path, _ bool) (any, error) {
v, ok := data.(map[string]any)
if !ok {
return data, fmt.Errorf("%s: invalid type %T for device request", p, v)
}
_, hasCount := v["count"]
_, hasIds := v["device_ids"]
if !hasCount && !hasIds {
v["count"] = "all"
}
return v, nil
}

View File

@@ -0,0 +1,48 @@
/*
Copyright 2020 The Compose Specification Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package types
import (
"fmt"
"strconv"
)
type NanoCPUs float32
func (n *NanoCPUs) DecodeMapstructure(a any) error {
switch v := a.(type) {
case string:
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return err
}
*n = NanoCPUs(f)
case int:
*n = NanoCPUs(v)
case float32:
*n = NanoCPUs(v)
case float64:
*n = NanoCPUs(v)
default:
return fmt.Errorf("unexpected value type %T for cpus", v)
}
return nil
}
func (n *NanoCPUs) Value() float32 {
return float32(*n)
}

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@ type DeviceRequest struct {
Driver string `yaml:"driver,omitempty" json:"driver,omitempty"` Driver string `yaml:"driver,omitempty" json:"driver,omitempty"`
Count DeviceCount `yaml:"count,omitempty" json:"count,omitempty"` Count DeviceCount `yaml:"count,omitempty" json:"count,omitempty"`
IDs []string `yaml:"device_ids,omitempty" json:"device_ids,omitempty"` IDs []string `yaml:"device_ids,omitempty" json:"device_ids,omitempty"`
Options Mapping `yaml:"options,omitempty" json:"options,omitempty"`
} }
type DeviceCount int64 type DeviceCount int64

View File

@@ -23,6 +23,7 @@ import (
type EnvFile struct { type EnvFile struct {
Path string `yaml:"path,omitempty" json:"path,omitempty"` Path string `yaml:"path,omitempty" json:"path,omitempty"`
Required bool `yaml:"required" json:"required"` Required bool `yaml:"required" json:"required"`
Format string `yaml:"format,omitempty" json:"format,omitempty"`
} }
// MarshalYAML makes EnvFile implement yaml.Marshaler // MarshalYAML makes EnvFile implement yaml.Marshaler

View File

@@ -0,0 +1,28 @@
/*
Copyright 2020 The Compose Specification Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package types
// ServiceHook is a command to exec inside container by some lifecycle events
type ServiceHook struct {
Command ShellCommand `yaml:"command,omitempty" json:"command"`
User string `yaml:"user,omitempty" json:"user,omitempty"`
Privileged bool `yaml:"privileged,omitempty" json:"privileged,omitempty"`
WorkingDir string `yaml:"working_dir,omitempty" json:"working_dir,omitempty"`
Environment MappingWithEquals `yaml:"environment,omitempty" json:"environment,omitempty"`
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
}

View File

@@ -616,22 +616,11 @@ func (p Project) WithServicesEnvironmentResolved(discardEnvFiles bool) (*Project
} }
for _, envFile := range service.EnvFiles { for _, envFile := range service.EnvFiles {
if _, err := os.Stat(envFile.Path); os.IsNotExist(err) { vars, err := loadEnvFile(envFile, resolve)
if envFile.Required {
return nil, fmt.Errorf("env file %s not found: %w", envFile.Path, err)
}
continue
}
b, err := os.ReadFile(envFile.Path)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load %s: %w", envFile.Path, err) return nil, err
} }
environment.OverrideBy(vars.ToMappingWithEquals())
fileVars, err := dotenv.ParseWithLookup(bytes.NewBuffer(b), resolve)
if err != nil {
return nil, fmt.Errorf("failed to read %s: %w", envFile.Path, err)
}
environment.OverrideBy(Mapping(fileVars).ToMappingWithEquals())
} }
service.Environment = environment.OverrideBy(service.Environment) service.Environment = environment.OverrideBy(service.Environment)
@@ -644,6 +633,31 @@ func (p Project) WithServicesEnvironmentResolved(discardEnvFiles bool) (*Project
return newProject, nil return newProject, nil
} }
func loadEnvFile(envFile EnvFile, resolve dotenv.LookupFn) (Mapping, error) {
if _, err := os.Stat(envFile.Path); os.IsNotExist(err) {
if envFile.Required {
return nil, fmt.Errorf("env file %s not found: %w", envFile.Path, err)
}
return nil, nil
}
file, err := os.Open(envFile.Path)
if err != nil {
return nil, err
}
defer file.Close() //nolint:errcheck
var fileVars map[string]string
if envFile.Format != "" {
fileVars, err = dotenv.ParseWithFormat(file, envFile.Path, resolve, envFile.Format)
} else {
fileVars, err = dotenv.ParseWithLookup(file, resolve)
}
if err != nil {
return nil, err
}
return fileVars, nil
}
func (p *Project) deepCopy() *Project { func (p *Project) deepCopy() *Project {
if p == nil { if p == nil {
return nil return nil

View File

@@ -20,7 +20,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"sort" "sort"
"strconv"
"strings" "strings"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
@@ -82,6 +81,7 @@ type ServiceConfig struct {
ExternalLinks []string `yaml:"external_links,omitempty" json:"external_links,omitempty"` ExternalLinks []string `yaml:"external_links,omitempty" json:"external_links,omitempty"`
ExtraHosts HostsList `yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"` ExtraHosts HostsList `yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"`
GroupAdd []string `yaml:"group_add,omitempty" json:"group_add,omitempty"` GroupAdd []string `yaml:"group_add,omitempty" json:"group_add,omitempty"`
Gpus []DeviceRequest `yaml:"gpus,omitempty" json:"gpus,omitempty"`
Hostname string `yaml:"hostname,omitempty" json:"hostname,omitempty"` Hostname string `yaml:"hostname,omitempty" json:"hostname,omitempty"`
HealthCheck *HealthCheckConfig `yaml:"healthcheck,omitempty" json:"healthcheck,omitempty"` HealthCheck *HealthCheckConfig `yaml:"healthcheck,omitempty" json:"healthcheck,omitempty"`
Image string `yaml:"image,omitempty" json:"image,omitempty"` Image string `yaml:"image,omitempty" json:"image,omitempty"`
@@ -132,6 +132,8 @@ type ServiceConfig struct {
Volumes []ServiceVolumeConfig `yaml:"volumes,omitempty" json:"volumes,omitempty"` Volumes []ServiceVolumeConfig `yaml:"volumes,omitempty" json:"volumes,omitempty"`
VolumesFrom []string `yaml:"volumes_from,omitempty" json:"volumes_from,omitempty"` VolumesFrom []string `yaml:"volumes_from,omitempty" json:"volumes_from,omitempty"`
WorkingDir string `yaml:"working_dir,omitempty" json:"working_dir,omitempty"` WorkingDir string `yaml:"working_dir,omitempty" json:"working_dir,omitempty"`
PostStart []ServiceHook `yaml:"post_start,omitempty" json:"post_start,omitempty"`
PreStop []ServiceHook `yaml:"pre_stop,omitempty" json:"pre_stop,omitempty"`
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
} }
@@ -388,30 +390,6 @@ type Resource struct {
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
} }
type NanoCPUs float32
func (n *NanoCPUs) DecodeMapstructure(a any) error {
switch v := a.(type) {
case string:
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return err
}
*n = NanoCPUs(f)
case float32:
*n = NanoCPUs(v)
case float64:
*n = NanoCPUs(v)
default:
return fmt.Errorf("unexpected value type %T for cpus", v)
}
return nil
}
func (n *NanoCPUs) Value() float32 {
return float32(*n)
}
// GenericResource represents a "user defined" resource which can // GenericResource represents a "user defined" resource which can
// only be an integer (e.g: SSD=3) for a service // only be an integer (e.g: SSD=3) for a service
type GenericResource struct { type GenericResource struct {
@@ -552,9 +530,6 @@ func (s ServiceVolumeConfig) String() string {
if s.Volume != nil && s.Volume.NoCopy { if s.Volume != nil && s.Volume.NoCopy {
options = append(options, "nocopy") options = append(options, "nocopy")
} }
if s.Volume != nil && s.Volume.Subpath != "" {
options = append(options, s.Volume.Subpath)
}
return fmt.Sprintf("%s:%s:%s", s.Source, s.Target, strings.Join(options, ",")) return fmt.Sprintf("%s:%s:%s", s.Source, s.Target, strings.Join(options, ","))
} }
@@ -581,6 +556,7 @@ type ServiceVolumeBind struct {
SELinux string `yaml:"selinux,omitempty" json:"selinux,omitempty"` SELinux string `yaml:"selinux,omitempty" json:"selinux,omitempty"`
Propagation string `yaml:"propagation,omitempty" json:"propagation,omitempty"` Propagation string `yaml:"propagation,omitempty" json:"propagation,omitempty"`
CreateHostPath bool `yaml:"create_host_path,omitempty" json:"create_host_path,omitempty"` CreateHostPath bool `yaml:"create_host_path,omitempty" json:"create_host_path,omitempty"`
Recursive string `yaml:"recursive,omitempty" json:"recursive,omitempty"`
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"` Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
} }

View File

@@ -30,6 +30,8 @@ var checks = map[tree.Path]checkerFunc{
"configs.*": checkFileObject("file", "environment", "content"), "configs.*": checkFileObject("file", "environment", "content"),
"secrets.*": checkFileObject("file", "environment"), "secrets.*": checkFileObject("file", "environment"),
"services.*.develop.watch.*.path": checkPath, "services.*.develop.watch.*.path": checkPath,
"services.*.deploy.resources.reservations.devices.*": checkDeviceRequest,
"services.*.gpus.*": checkDeviceRequest,
} }
func Validate(dict map[string]any) error { func Validate(dict map[string]any) error {
@@ -94,3 +96,13 @@ func checkPath(value any, p tree.Path) error {
} }
return nil return nil
} }
func checkDeviceRequest(value any, p tree.Path) error {
v := value.(map[string]any)
_, hasCount := v["count"]
_, hasIds := v["device_ids"]
if hasCount && hasIds {
return fmt.Errorf(`%s: "count" and "device_ids" attributes are exclusive`, p)
}
return nil
}

View File

@@ -12,5 +12,11 @@ linters:
disable: disable:
- errcheck - errcheck
issues:
exclude-rules:
- linters:
- revive
text: "unused-parameter"
run: run:
timeout: 3m timeout: 3m

View File

@@ -57,7 +57,7 @@ test:
root-test: root-test:
@echo "+ $@" @echo "+ $@"
@go test -exec sudo ${TEST_REQUIRES_ROOT_PACKAGES} -test.root @go test -exec sudo ${TEST_REQUIRES_ROOT_PACKAGES} -test.root -test.v
test-compile: test-compile:
@echo "+ $@" @echo "+ $@"

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build freebsd || dragonfly //go:build freebsd || dragonfly
// +build freebsd dragonfly
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build !(freebsd || windows) //go:build !(freebsd || windows)
// +build !freebsd,!windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build go1.13 //go:build go1.13
// +build go1.13
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build darwin || freebsd || netbsd || openbsd || dragonfly || solaris //go:build darwin || freebsd || netbsd || openbsd || dragonfly || solaris
// +build darwin freebsd netbsd openbsd dragonfly solaris
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -22,7 +22,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/sirupsen/logrus" "github.com/containerd/log"
) )
// XAttrErrorHandler transform a non-nil xattr error. // XAttrErrorHandler transform a non-nil xattr error.
@@ -161,7 +161,7 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
return fmt.Errorf("failed to create irregular file: %w", err) return fmt.Errorf("failed to create irregular file: %w", err)
} }
default: default:
logrus.Warnf("unsupported mode: %s: %s", source, fileInfo.Mode()) log.L.Warnf("unsupported mode: %s: %s", source, fileInfo.Mode())
return nil return nil
} }

View File

@@ -1,5 +1,4 @@
//go:build !windows && !freebsd //go:build !windows && !freebsd
// +build !windows,!freebsd
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -17,6 +17,7 @@
package fs package fs
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"syscall" "syscall"
@@ -64,6 +65,9 @@ func copyFileInfo(fi os.FileInfo, src, name string) error {
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error { func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
xattrKeys, err := sysx.LListxattr(src) xattrKeys, err := sysx.LListxattr(src)
if err != nil { if err != nil {
if errors.Is(err, unix.ENOTSUP) {
return nil
}
e := fmt.Errorf("failed to list xattrs on %s: %w", src, err) e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
if errorHandler != nil { if errorHandler != nil {
e = errorHandler(dst, src, "", e) e = errorHandler(dst, src, "", e)

View File

@@ -1,5 +1,4 @@
//go:build !darwin //go:build !darwin
// +build !darwin
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build darwin || freebsd || openbsd || netbsd || dragonfly || solaris //go:build darwin || freebsd || openbsd || netbsd || dragonfly || solaris
// +build darwin freebsd openbsd netbsd dragonfly solaris
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@@ -20,12 +19,14 @@
package fs package fs
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"syscall" "syscall"
"github.com/containerd/continuity/sysx" "github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix"
) )
func copyFileInfo(fi os.FileInfo, src, name string) error { func copyFileInfo(fi os.FileInfo, src, name string) error {
@@ -67,6 +68,9 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt
// On darwin, character devices do not permit listing xattrs // On darwin, character devices do not permit listing xattrs
return nil return nil
} }
if errors.Is(err, unix.ENOTSUP) {
return nil
}
e := fmt.Errorf("failed to list xattrs on %s: %w", src, err) e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
if errorHandler != nil { if errorHandler != nil {
e = errorHandler(dst, src, "", e) e = errorHandler(dst, src, "", e)

View File

@@ -18,11 +18,12 @@ package fs
import ( import (
"context" "context"
"errors"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/sirupsen/logrus" "github.com/containerd/log"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@@ -100,14 +101,11 @@ type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error
// is to account for timestamp truncation during archiving. // is to account for timestamp truncation during archiving.
func Changes(ctx context.Context, a, b string, changeFn ChangeFunc) error { func Changes(ctx context.Context, a, b string, changeFn ChangeFunc) error {
if a == "" { if a == "" {
logrus.Debugf("Using single walk diff for %s", b) log.G(ctx).Debugf("Using single walk diff for %s", b)
return addDirChanges(ctx, changeFn, b) return addDirChanges(ctx, changeFn, b)
} else if diffOptions := detectDirDiff(b, a); diffOptions != nil {
logrus.Debugf("Using single walk diff for %s from %s", diffOptions.diffDir, a)
return diffDirChanges(ctx, changeFn, a, diffOptions)
} }
logrus.Debugf("Using double walk diff for %s from %s", b, a) log.G(ctx).Debugf("Using double walk diff for %s from %s", b, a)
return doubleWalkDiff(ctx, changeFn, a, b) return doubleWalkDiff(ctx, changeFn, a, b)
} }
@@ -134,24 +132,53 @@ func addDirChanges(ctx context.Context, changeFn ChangeFunc, root string) error
}) })
} }
// DiffChangeSource is the source of diff directory.
type DiffSource int
const (
// DiffSourceOverlayFS indicates that a diff directory is from
// OverlayFS.
DiffSourceOverlayFS DiffSource = iota
)
// diffDirOptions is used when the diff can be directly calculated from // diffDirOptions is used when the diff can be directly calculated from
// a diff directory to its base, without walking both trees. // a diff directory to its base, without walking both trees.
type diffDirOptions struct { type diffDirOptions struct {
diffDir string skipChange func(string, os.FileInfo) (bool, error)
skipChange func(string) (bool, error) deleteChange func(string, string, os.FileInfo, ChangeFunc) (bool, error)
deleteChange func(string, string, os.FileInfo) (string, error)
} }
// diffDirChanges walks the diff directory and compares changes against the base. // DiffDirChanges walks the diff directory and compares changes against the base.
func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *diffDirOptions) error { //
// NOTE: If all the children of a dir are removed, or that dir are recreated
// after remove, we will mark non-existing `.wh..opq` file as deleted. It's
// unlikely to create explicit whiteout files for all the children and all
// descendants. And based on OCI spec, it's not possible to create a file or
// dir with a name beginning with `.wh.`. So, after `.wh..opq` file has been
// deleted, the ChangeFunc, the receiver will add whiteout prefix to create a
// opaque whiteout `.wh..wh..opq`.
//
// REF: https://github.com/opencontainers/image-spec/blob/v1.0/layer.md#whiteouts
func DiffDirChanges(ctx context.Context, baseDir, diffDir string, source DiffSource, changeFn ChangeFunc) error {
var o *diffDirOptions
switch source {
case DiffSourceOverlayFS:
o = &diffDirOptions{
deleteChange: overlayFSWhiteoutConvert,
}
default:
return errors.New("unknown diff change source")
}
changedDirs := make(map[string]struct{}) changedDirs := make(map[string]struct{})
return filepath.Walk(o.diffDir, func(path string, f os.FileInfo, err error) error { return filepath.Walk(diffDir, func(path string, f os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
// Rebase path // Rebase path
path, err = filepath.Rel(o.diffDir, path) path, err = filepath.Rel(diffDir, path)
if err != nil { if err != nil {
return err return err
} }
@@ -163,38 +190,45 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di
return nil return nil
} }
// TODO: handle opaqueness, start new double walker at this
// location to get deletes, and skip tree in single walker
if o.skipChange != nil { if o.skipChange != nil {
if skip, err := o.skipChange(path); skip { if skip, err := o.skipChange(path, f); skip {
return err return err
} }
} }
var kind ChangeKind var kind ChangeKind
deletedFile, err := o.deleteChange(o.diffDir, path, f) deletedFile := false
if err != nil {
return err if o.deleteChange != nil {
deletedFile, err = o.deleteChange(diffDir, path, f, changeFn)
if err != nil {
return err
}
_, err = os.Stat(filepath.Join(baseDir, path))
if err != nil {
if !os.IsNotExist(err) {
return err
}
deletedFile = false
}
} }
// Find out what kind of modification happened // Find out what kind of modification happened
if deletedFile != "" { if deletedFile {
path = deletedFile
kind = ChangeKindDelete kind = ChangeKindDelete
f = nil
} else { } else {
// Otherwise, the file was added // Otherwise, the file was added
kind = ChangeKindAdd kind = ChangeKindAdd
// ...Unless it already existed in a base, in which case, it's a modification // ...Unless it already existed in a baseDir, in which case, it's a modification
stat, err := os.Stat(filepath.Join(base, path)) stat, err := os.Stat(filepath.Join(baseDir, path))
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return err return err
} }
if err == nil { if err == nil {
// The file existed in the base, so that's a modification // The file existed in the baseDir, so that's a modification
// However, if it's a directory, maybe it wasn't actually modified. // However, if it's a directory, maybe it wasn't actually modified.
// If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
@@ -215,10 +249,12 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di
if f.IsDir() { if f.IsDir() {
changedDirs[path] = struct{}{} changedDirs[path] = struct{}{}
} }
if kind == ChangeKindAdd || kind == ChangeKindDelete { if kind == ChangeKindAdd || kind == ChangeKindDelete {
parent := filepath.Dir(path) parent := filepath.Dir(path)
if _, ok := changedDirs[parent]; !ok && parent != "/" { if _, ok := changedDirs[parent]; !ok && parent != "/" {
pi, err := os.Stat(filepath.Join(o.diffDir, parent)) pi, err := os.Stat(filepath.Join(diffDir, parent))
if err := changeFn(ChangeKindModify, parent, pi, err); err != nil { if err := changeFn(ChangeKindModify, parent, pi, err); err != nil {
return err return err
} }
@@ -226,6 +262,9 @@ func diffDirChanges(ctx context.Context, changeFn ChangeFunc, base string, o *di
} }
} }
if kind == ChangeKindDelete {
f = nil
}
return changeFn(kind, path, f, nil) return changeFn(kind, path, f, nil)
}) })
} }

View File

@@ -0,0 +1,101 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"errors"
"fmt"
"os"
"path/filepath"
"syscall"
"github.com/containerd/continuity/devices"
"github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix"
)
const (
// whiteoutPrefix prefix means file is a whiteout. If this is followed
// by a filename this means that file has been removed from the base
// layer.
//
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#whiteouts
whiteoutPrefix = ".wh."
)
// overlayFSWhiteoutConvert detects whiteouts and opaque directories.
//
// It returns deleted indicator if the file is a character device with 0/0
// device number. And call changeFn with ChangeKindDelete for opaque
// directories.
//
// Check: https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt
func overlayFSWhiteoutConvert(diffDir, path string, f os.FileInfo, changeFn ChangeFunc) (deleted bool, _ error) {
if f.Mode()&os.ModeCharDevice != 0 {
if _, ok := f.Sys().(*syscall.Stat_t); !ok {
return false, nil
}
maj, min, err := devices.DeviceInfo(f)
if err != nil {
return false, err
}
return (maj == 0 && min == 0), nil
}
if f.IsDir() {
originalPath := filepath.Join(diffDir, path)
opaque, err := getOpaqueValue(originalPath)
if err != nil {
if errors.Is(err, unix.ENODATA) {
return false, nil
}
return false, err
}
if len(opaque) == 1 && opaque[0] == 'y' {
opaqueDirPath := filepath.Join(path, whiteoutPrefix+".opq")
return false, changeFn(ChangeKindDelete, opaqueDirPath, nil, nil)
}
}
return false, nil
}
// getOpaqueValue returns opaque value for a given file.
func getOpaqueValue(filePath string) ([]byte, error) {
for _, xattr := range []string{
"trusted.overlay.opaque",
// TODO(fuweid):
//
// user.overlay.* is available since 5.11. We should check
// kernel version before read.
//
// REF: https://github.com/torvalds/linux/commit/2d2f2d7322ff43e0fe92bf8cccdc0b09449bf2e1
"user.overlay.opaque",
} {
opaque, err := sysx.LGetxattr(filePath, xattr)
if err != nil {
if errors.Is(err, unix.ENODATA) || errors.Is(err, unix.ENOTSUP) {
continue
}
return nil, fmt.Errorf("failed to retrieve %s attr: %w", xattr, err)
}
return opaque, nil
}
return nil, unix.ENODATA
}

View File

@@ -0,0 +1,28 @@
//go:build !linux
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fs
import (
"errors"
"os"
)
func overlayFSWhiteoutConvert(string, string, os.FileInfo, ChangeFunc) (bool, error) {
return false, errors.New("unsupported")
}

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@@ -28,16 +27,6 @@ import (
"github.com/containerd/continuity/sysx" "github.com/containerd/continuity/sysx"
) )
// detectDirDiff returns diff dir options if a directory could
// be found in the mount info for upper which is the direct
// diff with the provided lower directory
func detectDirDiff(upper, lower string) *diffDirOptions {
// TODO: get mount options for upper
// TODO: detect AUFS
// TODO: detect overlay
return nil
}
// compareSysStat returns whether the stats are equivalent, // compareSysStat returns whether the stats are equivalent,
// whether the files are considered the same file, and // whether the files are considered the same file, and
// an error // an error

View File

@@ -22,10 +22,6 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
func detectDirDiff(upper, lower string) *diffDirOptions {
return nil
}
func compareSysStat(s1, s2 interface{}) (bool, error) { func compareSysStat(s1, s2 interface{}) (bool, error) {
f1, ok := s1.(windows.Win32FileAttributeData) f1, ok := s1.(windows.Win32FileAttributeData)
if !ok { if !ok {

View File

@@ -1,5 +1,4 @@
//go:build linux //go:build linux
// +build linux
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build windows //go:build windows
// +build windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.
@@ -20,9 +19,11 @@
package fstest package fstest
import ( import (
"os"
"path/filepath" "path/filepath"
"time" "time"
"github.com/containerd/continuity/devices"
"github.com/containerd/continuity/sysx" "github.com/containerd/continuity/sysx"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@@ -46,6 +47,14 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
}) })
} }
// CreateDeviceFile provides creates devices Applier.
func CreateDeviceFile(name string, mode os.FileMode, maj, min int) Applier {
return applyFn(func(root string) error {
fullPath := filepath.Join(root, name)
return devices.Mknod(fullPath, mode, maj, min)
})
}
func Base() Applier { func Base() Applier {
return applyFn(func(root string) error { return applyFn(func(root string) error {
// do nothing, as the base is not special // do nothing, as the base is not special

View File

@@ -18,9 +18,17 @@ package fstest
import ( import (
"errors" "errors"
"os"
"time" "time"
) )
// SetXAttr sets the xatter for the file
func SetXAttr(name, key, value string) Applier {
return applyFn(func(root string) error {
return errors.New("Not implemented")
})
}
// Lchtimes changes access and mod time of file without following symlink // Lchtimes changes access and mod time of file without following symlink
func Lchtimes(name string, atime, mtime time.Time) Applier { func Lchtimes(name string, atime, mtime time.Time) Applier {
return applyFn(func(root string) error { return applyFn(func(root string) error {
@@ -28,6 +36,13 @@ func Lchtimes(name string, atime, mtime time.Time) Applier {
}) })
} }
// CreateDeviceFile provides creates devices Applier.
func CreateDeviceFile(name string, mode os.FileMode, maj, min int) Applier {
return applyFn(func(root string) error {
return errors.New("Not implemented")
})
}
// Base applies the files required to make a valid Windows container layer // Base applies the files required to make a valid Windows container layer
// that the filter will mount. It is used for testing the snapshotter // that the filter will mount. It is used for testing the snapshotter
func Base() Applier { func Base() Applier {

View File

@@ -0,0 +1,44 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fstest
import (
"os/exec"
"testing"
"github.com/containerd/continuity/testutil"
"github.com/containerd/continuity/testutil/loopback"
)
func WithMkfs(t *testing.T, f func(), mkfs ...string) {
testutil.RequiresRoot(t)
mnt := t.TempDir()
loop, err := loopback.New(100 << 20) // 100 MB
if err != nil {
t.Fatal(err)
}
defer loop.Close()
if out, err := exec.Command(mkfs[0], append(mkfs[1:], loop.Device)...).CombinedOutput(); err != nil {
t.Fatalf("could not mkfs (%v) %s: %v (out: %q)", mkfs, loop.Device, err, string(out))
}
if out, err := exec.Command("mount", loop.Device, mnt).CombinedOutput(); err != nil {
t.Fatalf("could not mount %s: %v (out: %q)", loop.Device, err, string(out))
}
defer testutil.Unmount(t, mnt)
t.Setenv("TMPDIR", mnt)
f()
}

View File

@@ -0,0 +1,25 @@
//go:build !linux
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fstest
import "testing"
func WithMkfs(t *testing.T, f func(), mkfs ...string) {
t.Fatal("WithMkfs requires Linux")
}

View File

@@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
/* /*
Copyright The containerd Authors. Copyright The containerd Authors.

View File

@@ -0,0 +1,123 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Copyright 2013-2018 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Original source: https://github.com/moby/moby/blob/v26.0.0/daemon/graphdriver/driver_linux.go
package fs
import (
"path/filepath"
"syscall"
)
// Magic unsigned id of the filesystem in use.
type Magic uint32
const (
// MagicUnsupported is a predefined constant value other than a valid filesystem id.
MagicUnsupported = Magic(0x00000000)
)
const (
// MagicAufs filesystem id for Aufs
MagicAufs = Magic(0x61756673)
// MagicBtrfs filesystem id for Btrfs
MagicBtrfs = Magic(0x9123683E)
// MagicCramfs filesystem id for Cramfs
MagicCramfs = Magic(0x28cd3d45)
// MagicEcryptfs filesystem id for eCryptfs
MagicEcryptfs = Magic(0xf15f)
// MagicExtfs filesystem id for Extfs
MagicExtfs = Magic(0x0000EF53)
// MagicF2fs filesystem id for F2fs
MagicF2fs = Magic(0xF2F52010)
// MagicGPFS filesystem id for GPFS
MagicGPFS = Magic(0x47504653)
// MagicJffs2Fs filesystem if for Jffs2Fs
MagicJffs2Fs = Magic(0x000072b6)
// MagicJfs filesystem id for Jfs
MagicJfs = Magic(0x3153464a)
// MagicNfsFs filesystem id for NfsFs
MagicNfsFs = Magic(0x00006969)
// MagicRAMFs filesystem id for RamFs
MagicRAMFs = Magic(0x858458f6)
// MagicReiserFs filesystem id for ReiserFs
MagicReiserFs = Magic(0x52654973)
// MagicSmbFs filesystem id for SmbFs
MagicSmbFs = Magic(0x0000517B)
// MagicSquashFs filesystem id for SquashFs
MagicSquashFs = Magic(0x73717368)
// MagicTmpFs filesystem id for TmpFs
MagicTmpFs = Magic(0x01021994)
// MagicVxFS filesystem id for VxFs
MagicVxFS = Magic(0xa501fcf5)
// MagicXfs filesystem id for Xfs
MagicXfs = Magic(0x58465342)
// MagicZfs filesystem id for Zfs
MagicZfs = Magic(0x2fc12fc1)
// MagicOverlay filesystem id for overlay
MagicOverlay = Magic(0x794C7630)
)
var (
// FsNames maps filesystem id to name of the filesystem.
FsNames = map[Magic]string{
MagicAufs: "aufs",
MagicBtrfs: "btrfs",
MagicCramfs: "cramfs",
MagicExtfs: "extfs",
MagicF2fs: "f2fs",
MagicGPFS: "gpfs",
MagicJffs2Fs: "jffs2",
MagicJfs: "jfs",
MagicNfsFs: "nfs",
MagicOverlay: "overlayfs",
MagicRAMFs: "ramfs",
MagicReiserFs: "reiserfs",
MagicSmbFs: "smb",
MagicSquashFs: "squashfs",
MagicTmpFs: "tmpfs",
MagicUnsupported: "unsupported",
MagicVxFS: "vxfs",
MagicXfs: "xfs",
MagicZfs: "zfs",
}
)
// GetMagic returns the filesystem id given the path.
func GetMagic(rootpath string) (Magic, error) {
var buf syscall.Statfs_t
if err := syscall.Statfs(filepath.Dir(rootpath), &buf); err != nil {
return 0, err
}
return Magic(buf.Type), nil
}

Some files were not shown because too many files have changed in this diff Show More