mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-08-13 23:35:57 +08:00
Compare commits
65 Commits
v0.23.0-rc
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9e17bc7a4c | ||
![]() |
e1e8f5c68d | ||
![]() |
6ed39b2618 | ||
![]() |
03019049e8 | ||
![]() |
23ce21c341 | ||
![]() |
4dac5295a1 | ||
![]() |
9a48aca461 | ||
![]() |
679407862f | ||
![]() |
674cfff1a4 | ||
![]() |
19a241f4ed | ||
![]() |
7da31076ae | ||
![]() |
384f0565f5 | ||
![]() |
6df3a09284 | ||
![]() |
e7be640d9b | ||
![]() |
2f1be25b8f | ||
![]() |
a40edbb47b | ||
![]() |
2eaea647d8 | ||
![]() |
f3a3d9c26b | ||
![]() |
9ba3f77219 | ||
![]() |
2799ed6dd8 | ||
![]() |
719a41a4c3 | ||
![]() |
a9807be458 | ||
![]() |
7a7be2ffa1 | ||
![]() |
ab533b0cb4 | ||
![]() |
0855cab1bd | ||
![]() |
735555ff7b | ||
![]() |
67ccbd06f6 | ||
![]() |
c370f90b73 | ||
![]() |
9730a20f6b | ||
![]() |
2e93ac32bc | ||
![]() |
19c22136b4 | ||
![]() |
bad5063577 | ||
![]() |
286c018f84 | ||
![]() |
ac970c03e7 | ||
![]() |
5398c33937 | ||
![]() |
1365652a74 | ||
![]() |
a4f0a21468 | ||
![]() |
d55616b22c | ||
![]() |
113606a24c | ||
![]() |
cd38da0244 | ||
![]() |
cc6547c51d | ||
![]() |
26f2e002c6 | ||
![]() |
372feb38ff | ||
![]() |
b08d576ec0 | ||
![]() |
0034cdbffc | ||
![]() |
a9666e7df1 | ||
![]() |
b7e77af256 | ||
![]() |
d72ff8f88c | ||
![]() |
d75c650792 | ||
![]() |
8c74109330 | ||
![]() |
9f102b5c34 | ||
![]() |
b4b2dc9664 | ||
![]() |
2e81e301ae | ||
![]() |
fb4417e14d | ||
![]() |
eb74b483bd | ||
![]() |
db194abdc8 | ||
![]() |
86eb3be1c4 | ||
![]() |
a05a166f81 | ||
![]() |
cfc9d3a8c9 | ||
![]() |
5bac0b1197 | ||
![]() |
0b4e624aaa | ||
![]() |
b7b5a3a1cc | ||
![]() |
f8de3c3bdc | ||
![]() |
fa0c3e3786 | ||
![]() |
df6d36af35 |
11
.github/workflows/build.yml
vendored
11
.github/workflows/build.yml
vendored
@@ -260,6 +260,9 @@ jobs:
|
||||
- freebsd
|
||||
- netbsd
|
||||
- openbsd
|
||||
env:
|
||||
# https://github.com/hashicorp/vagrant/issues/13652
|
||||
VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT: 1
|
||||
steps:
|
||||
-
|
||||
name: Prepare
|
||||
@@ -420,6 +423,9 @@ jobs:
|
||||
haskell: true
|
||||
large-packages: true
|
||||
swap-storage: true
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
@@ -453,9 +459,10 @@ jobs:
|
||||
name: Build and push image
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: .
|
||||
files: |
|
||||
./docker-bake.hcl
|
||||
cwd://${{ steps.meta.outputs.bake-file }}
|
||||
${{ steps.meta.outputs.bake-file }}
|
||||
targets: image-cross
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
sbom: true
|
||||
@@ -528,7 +535,7 @@ jobs:
|
||||
-
|
||||
name: GitHub Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda # v2.2.1
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
17
.github/workflows/pr-assign-author.yml
vendored
Normal file
17
.github/workflows/pr-assign-author.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: pr-assign-author
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: crazy-max/.github/.github/workflows/pr-assign-author.yml@c27924b5b93ccfe6dcc0d7b22e779ef3c05f9a92
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
@@ -5,13 +5,13 @@ ARG ALPINE_VERSION=3.21
|
||||
ARG XX_VERSION=1.6.1
|
||||
|
||||
# for testing
|
||||
ARG DOCKER_VERSION=28.0.0
|
||||
ARG DOCKER_VERSION=28.1.0
|
||||
ARG DOCKER_VERSION_ALT_27=27.5.1
|
||||
ARG DOCKER_VERSION_ALT_26=26.1.3
|
||||
ARG DOCKER_CLI_VERSION=${DOCKER_VERSION}
|
||||
ARG GOTESTSUM_VERSION=v1.12.0
|
||||
ARG REGISTRY_VERSION=2.8.3
|
||||
ARG BUILDKIT_VERSION=v0.20.2
|
||||
ARG REGISTRY_VERSION=3.0.0
|
||||
ARG BUILDKIT_VERSION=v0.21.0
|
||||
ARG UNDOCK_VERSION=0.9.0
|
||||
|
||||
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
@@ -1360,8 +1360,8 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
|
||||
if strings.HasPrefix(bi.ContextPath, "cwd://") {
|
||||
bi.ContextPath = path.Clean(strings.TrimPrefix(bi.ContextPath, "cwd://"))
|
||||
}
|
||||
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextState == nil && !path.IsAbs(bi.DockerfilePath) {
|
||||
bi.DockerfilePath = path.Join(bi.ContextPath, bi.DockerfilePath)
|
||||
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextState == nil && !filepath.IsAbs(bi.DockerfilePath) {
|
||||
bi.DockerfilePath = filepath.Join(bi.ContextPath, bi.DockerfilePath)
|
||||
}
|
||||
for k, v := range bi.NamedContexts {
|
||||
if strings.HasPrefix(v.Path, "cwd://") {
|
||||
|
@@ -692,7 +692,7 @@ func TestHCLContextCwdPrefix(t *testing.T) {
|
||||
require.Contains(t, m, "app")
|
||||
assert.Equal(t, "test", *m["app"].Dockerfile)
|
||||
assert.Equal(t, "foo", *m["app"].Context)
|
||||
assert.Equal(t, "foo/test", bo["app"].Inputs.DockerfilePath)
|
||||
assert.Equal(t, filepath.Clean("foo/test"), bo["app"].Inputs.DockerfilePath)
|
||||
assert.Equal(t, "foo", bo["app"].Inputs.ContextPath)
|
||||
}
|
||||
|
||||
|
@@ -42,7 +42,7 @@ type variableValidation struct {
|
||||
type functionDef struct {
|
||||
Name string `json:"-" hcl:"name,label"`
|
||||
Params *hcl.Attribute `json:"params,omitempty" hcl:"params"`
|
||||
Variadic *hcl.Attribute `json:"variadic_param,omitempty" hcl:"variadic_params"`
|
||||
Variadic *hcl.Attribute `json:"variadic_params,omitempty" hcl:"variadic_params"`
|
||||
Result *hcl.Attribute `json:"result,omitempty" hcl:"result"`
|
||||
}
|
||||
|
||||
|
@@ -205,15 +205,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defers := make([]func(), 0, 2)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
for _, f := range defers {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
reqForNodes := make(map[string][]*reqForNode)
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
@@ -243,11 +234,11 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer release()
|
||||
if err := saveLocalState(so, k, opt, np.Node(), cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addGitAttrs(so)
|
||||
defers = append(defers, release)
|
||||
reqn = append(reqn, &reqForNode{
|
||||
resolvedNode: np,
|
||||
so: so,
|
||||
@@ -534,7 +525,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node := dp.Node().Driver
|
||||
if node.IsMobyDriver() {
|
||||
for _, e := range so.Exports {
|
||||
@@ -570,6 +560,14 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
|
||||
}
|
||||
}
|
||||
}
|
||||
// if prefer-image-digest is set in the solver options, remove the image
|
||||
// config digest from the exporter's response
|
||||
for _, e := range so.Exports {
|
||||
if e.Attrs["prefer-image-digest"] == "true" {
|
||||
delete(rr.ExporterResponse, exptypes.ExporterImageConfigDigestKey)
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@@ -237,6 +237,11 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *O
|
||||
opt.Exports[i].Output = func(_ map[string]string) (io.WriteCloser, error) {
|
||||
return w, nil
|
||||
}
|
||||
// if docker is using the containerd snapshotter, prefer to export the image digest
|
||||
// (rather than the image config digest). See https://github.com/moby/moby/issues/45458.
|
||||
if features[dockerutil.OCIImporter] {
|
||||
opt.Exports[i].Attrs["prefer-image-digest"] = "true"
|
||||
}
|
||||
}
|
||||
} else if !nodeDriver.Features(ctx)[driver.DockerExporter] {
|
||||
return nil, nil, notSupported(driver.DockerExporter, nodeDriver, "https://docs.docker.com/go/build-exporters/")
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/buildx/commands"
|
||||
controllererrors "github.com/docker/buildx/controller/errdefs"
|
||||
"github.com/docker/buildx/util/desktop"
|
||||
"github.com/docker/buildx/version"
|
||||
"github.com/docker/cli/cli"
|
||||
@@ -112,11 +111,6 @@ func main() {
|
||||
var ebr *desktop.ErrorWithBuildRef
|
||||
if errors.As(err, &ebr) {
|
||||
ebr.Print(cmd.Err())
|
||||
} else {
|
||||
var be *controllererrors.BuildError
|
||||
if errors.As(err, &be) {
|
||||
be.PrintBuildDetails(cmd.Err())
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
|
@@ -424,6 +424,14 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
|
||||
fmt.Fprintln(dockerCli.Out(), string(dt))
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
if sp, ok := resp[name]; ok {
|
||||
if v, ok := sp.ExporterResponse["frontend.result.inlinemessage"]; ok {
|
||||
fmt.Fprintf(dockerCli.Out(), "\n# %s\n%s\n", name, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if exitCode != 0 {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
@@ -42,7 +42,6 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
dockeropts "github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/pkg/atomicwriter"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||
"github.com/moby/buildkit/frontend/subrequests"
|
||||
@@ -53,6 +52,7 @@ import (
|
||||
solverpb "github.com/moby/buildkit/solver/pb"
|
||||
"github.com/moby/buildkit/util/grpcerrors"
|
||||
"github.com/moby/buildkit/util/progress/progressui"
|
||||
"github.com/moby/sys/atomicwriter"
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -104,12 +104,10 @@ type buildOptions struct {
|
||||
exportPush bool
|
||||
exportLoad bool
|
||||
|
||||
control.ControlOptions
|
||||
|
||||
invokeConfig *invokeConfig
|
||||
}
|
||||
|
||||
func (o *buildOptions) toControllerOptions() (*controllerapi.BuildOptions, error) {
|
||||
func (o *buildOptions) toControllerOptions() (*cbuild.Options, error) {
|
||||
var err error
|
||||
|
||||
buildArgs, err := listToMap(o.buildArgs, true)
|
||||
@@ -122,7 +120,7 @@ func (o *buildOptions) toControllerOptions() (*controllerapi.BuildOptions, error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := controllerapi.BuildOptions{
|
||||
opts := cbuild.Options{
|
||||
Allow: o.allow,
|
||||
Annotations: o.annotations,
|
||||
BuildArgs: buildArgs,
|
||||
@@ -404,6 +402,10 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
|
||||
os.Exit(exitcode)
|
||||
}
|
||||
}
|
||||
if v, ok := resp.ExporterResponse["frontend.result.inlinemessage"]; ok {
|
||||
fmt.Fprintf(dockerCli.Out(), "\n%s\n", v)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -416,7 +418,7 @@ func getImageID(resp map[string]string) string {
|
||||
return dgst
|
||||
}
|
||||
|
||||
func runBasicBuild(ctx context.Context, dockerCli command.Cli, opts *controllerapi.BuildOptions, printer *progress.Printer) (*client.SolveResponse, *build.Inputs, error) {
|
||||
func runBasicBuild(ctx context.Context, dockerCli command.Cli, opts *cbuild.Options, printer *progress.Printer) (*client.SolveResponse, *build.Inputs, error) {
|
||||
resp, res, dfmap, err := cbuild.RunBuild(ctx, dockerCli, opts, dockerCli.In(), printer, false)
|
||||
if res != nil {
|
||||
res.Done()
|
||||
@@ -424,15 +426,12 @@ func runBasicBuild(ctx context.Context, dockerCli command.Cli, opts *controllera
|
||||
return resp, dfmap, err
|
||||
}
|
||||
|
||||
func runControllerBuild(ctx context.Context, dockerCli command.Cli, opts *controllerapi.BuildOptions, options buildOptions, printer *progress.Printer) (*client.SolveResponse, *build.Inputs, error) {
|
||||
func runControllerBuild(ctx context.Context, dockerCli command.Cli, opts *cbuild.Options, options buildOptions, printer *progress.Printer) (*client.SolveResponse, *build.Inputs, error) {
|
||||
if options.invokeConfig != nil && (options.dockerfileName == "-" || options.contextPath == "-") {
|
||||
// stdin must be usable for monitor
|
||||
return nil, nil, errors.Errorf("Dockerfile or context from stdin is not supported with invoke")
|
||||
}
|
||||
c, err := controller.NewController(ctx, options.ControlOptions, dockerCli, printer)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
c := controller.NewController(ctx, dockerCli)
|
||||
defer func() {
|
||||
if err := c.Close(); err != nil {
|
||||
logrus.Warnf("failed to close server connection %v", err)
|
||||
@@ -441,7 +440,7 @@ func runControllerBuild(ctx context.Context, dockerCli command.Cli, opts *contro
|
||||
|
||||
// NOTE: buildx server has the current working directory different from the client
|
||||
// so we need to resolve paths to abosolute ones in the client.
|
||||
opts, err = controllerapi.ResolveOptionPaths(opts)
|
||||
opts, err := cbuild.ResolveOptionPaths(opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -467,11 +466,10 @@ func runControllerBuild(ctx context.Context, dockerCli command.Cli, opts *contro
|
||||
})
|
||||
}
|
||||
|
||||
ref, resp, inputs, err = c.Build(ctx, opts, pr, printer)
|
||||
resp, inputs, err = c.Build(ctx, opts, pr, printer)
|
||||
if err != nil {
|
||||
var be *controllererrors.BuildError
|
||||
if errors.As(err, &be) {
|
||||
ref = be.SessionID
|
||||
retErr = err
|
||||
// We can proceed to monitor
|
||||
} else {
|
||||
@@ -511,8 +509,8 @@ func runControllerBuild(ctx context.Context, dockerCli command.Cli, opts *contro
|
||||
resp, retErr = monitorBuildResult.Resp, monitorBuildResult.Err
|
||||
}
|
||||
} else {
|
||||
if err := c.Disconnect(ctx, ref); err != nil {
|
||||
logrus.Warnf("disconnect error: %v", err)
|
||||
if err := c.Close(); err != nil {
|
||||
logrus.Warnf("close error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,14 +647,6 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions, debugConfig *debug.D
|
||||
flags.StringVar(&options.sbom, "sbom", "", `Shorthand for "--attest=type=sbom"`)
|
||||
flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--attest=type=provenance"`)
|
||||
|
||||
if confutil.IsExperimental() {
|
||||
// TODO: move this to debug command if needed
|
||||
flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect")
|
||||
flags.BoolVar(&options.Detach, "detach", false, "Detach buildx server (supported only on linux)")
|
||||
flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server)")
|
||||
cobrautil.MarkFlagsExperimental(flags, "root", "detach", "server-config")
|
||||
}
|
||||
|
||||
flags.StringVar(&options.callFunc, "call", "build", `Set method for evaluating build ("check", "outline", "targets")`)
|
||||
flags.VarPF(callAlias(&options.callFunc, "check"), "check", "", `Shorthand for "--call=check"`)
|
||||
flags.Lookup("check").NoOptDefVal = "true"
|
||||
@@ -1013,12 +1003,12 @@ func (cfg *invokeConfig) needsDebug(retErr error) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *invokeConfig) runDebug(ctx context.Context, ref string, options *controllerapi.BuildOptions, c control.BuildxController, stdin io.ReadCloser, stdout io.WriteCloser, stderr console.File, progress *progress.Printer) (*monitor.MonitorBuildResult, error) {
|
||||
func (cfg *invokeConfig) runDebug(ctx context.Context, ref string, options *cbuild.Options, c control.BuildxController, stdin io.ReadCloser, stdout io.WriteCloser, stderr console.File, progress *progress.Printer) (*monitor.MonitorBuildResult, error) {
|
||||
con := console.Current()
|
||||
if err := con.SetRaw(); err != nil {
|
||||
// TODO: run disconnect in build command (on error case)
|
||||
if err := c.Disconnect(ctx, ref); err != nil {
|
||||
logrus.Warnf("disconnect error: %v", err)
|
||||
if err := c.Close(); err != nil {
|
||||
logrus.Warnf("close error: %v", err)
|
||||
}
|
||||
return nil, errors.Errorf("failed to configure terminal: %v", err)
|
||||
}
|
||||
|
@@ -3,11 +3,9 @@ package debug
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/docker/buildx/controller"
|
||||
"github.com/docker/buildx/controller/control"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/monitor"
|
||||
"github.com/docker/buildx/util/cobrautil"
|
||||
@@ -35,7 +33,6 @@ type DebuggableCmd interface {
|
||||
}
|
||||
|
||||
func RootCmd(dockerCli command.Cli, children ...DebuggableCmd) *cobra.Command {
|
||||
var controlOptions control.ControlOptions
|
||||
var progressMode string
|
||||
var options DebugConfig
|
||||
|
||||
@@ -50,10 +47,7 @@ func RootCmd(dockerCli command.Cli, children ...DebuggableCmd) *cobra.Command {
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
c, err := controller.NewController(ctx, controlOptions, dockerCli, printer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c := controller.NewController(ctx, dockerCli)
|
||||
defer func() {
|
||||
if err := c.Close(); err != nil {
|
||||
logrus.Warnf("failed to close server connection %v", err)
|
||||
@@ -76,13 +70,9 @@ func RootCmd(dockerCli command.Cli, children ...DebuggableCmd) *cobra.Command {
|
||||
flags := cmd.Flags()
|
||||
flags.StringVar(&options.InvokeFlag, "invoke", "", "Launch a monitor with executing specified command")
|
||||
flags.StringVar(&options.OnFlag, "on", "error", "When to launch the monitor ([always, error])")
|
||||
|
||||
flags.StringVar(&controlOptions.Root, "root", "", "Specify root directory of server to connect for the monitor")
|
||||
flags.BoolVar(&controlOptions.Detach, "detach", runtime.GOOS == "linux", "Detach buildx server for the monitor (supported only on linux)")
|
||||
flags.StringVar(&controlOptions.ServerConfig, "server-config", "", "Specify buildx server config file for the monitor (used only when launching new server)")
|
||||
flags.StringVar(&progressMode, "progress", "auto", `Set type of progress output ("auto", "plain", "tty", "rawjson") for the monitor. Use plain to show container output`)
|
||||
|
||||
cobrautil.MarkFlagsExperimental(flags, "invoke", "on", "root", "detach", "server-config")
|
||||
cobrautil.MarkFlagsExperimental(flags, "invoke", "on")
|
||||
|
||||
for _, c := range children {
|
||||
cmd.AddCommand(c.NewDebugger(&options))
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
debugcmd "github.com/docker/buildx/commands/debug"
|
||||
historycmd "github.com/docker/buildx/commands/history"
|
||||
imagetoolscmd "github.com/docker/buildx/commands/imagetools"
|
||||
"github.com/docker/buildx/controller/remote"
|
||||
"github.com/docker/buildx/util/cobrautil/completion"
|
||||
"github.com/docker/buildx/util/confutil"
|
||||
"github.com/docker/buildx/util/logutil"
|
||||
@@ -124,7 +123,6 @@ func addCommands(cmd *cobra.Command, opts *rootOptions, dockerCli command.Cli) {
|
||||
cmd.AddCommand(debugcmd.RootCmd(dockerCli,
|
||||
newDebuggableBuild(dockerCli, opts),
|
||||
))
|
||||
remote.AddControllerCommands(cmd, dockerCli)
|
||||
}
|
||||
|
||||
cmd.RegisterFlagCompletionFunc( //nolint:errcheck
|
||||
|
@@ -34,7 +34,7 @@ const defaultTargetName = "default"
|
||||
// NOTE: When an error happens during the build and this function acquires the debuggable *build.ResultHandle,
|
||||
// this function returns it in addition to the error (i.e. it does "return nil, res, err"). The caller can
|
||||
// inspect the result and debug the cause of that error.
|
||||
func RunBuild(ctx context.Context, dockerCli command.Cli, in *controllerapi.BuildOptions, inStream io.Reader, progress progress.Writer, generateResult bool) (*client.SolveResponse, *build.ResultHandle, *build.Inputs, error) {
|
||||
func RunBuild(ctx context.Context, dockerCli command.Cli, in *Options, inStream io.Reader, progress progress.Writer, generateResult bool) (*client.SolveResponse, *build.ResultHandle, *build.Inputs, error) {
|
||||
if in.NoCache && len(in.NoCacheFilter) > 0 {
|
||||
return nil, nil, nil, errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together")
|
||||
}
|
||||
|
@@ -1,15 +1,52 @@
|
||||
package pb
|
||||
package build
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
sourcepolicy "github.com/moby/buildkit/sourcepolicy/pb"
|
||||
"github.com/moby/buildkit/util/gitutil"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
ContextPath string
|
||||
DockerfileName string
|
||||
CallFunc *pb.CallFunc
|
||||
NamedContexts map[string]string
|
||||
Allow []string
|
||||
Attests []*pb.Attest
|
||||
BuildArgs map[string]string
|
||||
CacheFrom []*pb.CacheOptionsEntry
|
||||
CacheTo []*pb.CacheOptionsEntry
|
||||
CgroupParent string
|
||||
Exports []*pb.ExportEntry
|
||||
ExtraHosts []string
|
||||
Labels map[string]string
|
||||
NetworkMode string
|
||||
NoCacheFilter []string
|
||||
Platforms []string
|
||||
Secrets []*pb.Secret
|
||||
ShmSize int64
|
||||
SSH []*pb.SSH
|
||||
Tags []string
|
||||
Target string
|
||||
Ulimits *pb.UlimitOpt
|
||||
Builder string
|
||||
NoCache bool
|
||||
Pull bool
|
||||
ExportPush bool
|
||||
ExportLoad bool
|
||||
SourcePolicy *sourcepolicy.Policy
|
||||
Ref string
|
||||
GroupRef string
|
||||
Annotations []string
|
||||
ProvenanceResponseMode string
|
||||
}
|
||||
|
||||
// ResolveOptionPaths resolves all paths contained in BuildOptions
|
||||
// and replaces them to absolute paths.
|
||||
func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
|
||||
func ResolveOptionPaths(options *Options) (_ *Options, err error) {
|
||||
localContext := false
|
||||
if options.ContextPath != "" && options.ContextPath != "-" {
|
||||
if !isRemoteURL(options.ContextPath) {
|
||||
@@ -56,7 +93,7 @@ func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
|
||||
}
|
||||
options.NamedContexts = contexts
|
||||
|
||||
var cacheFrom []*CacheOptionsEntry
|
||||
var cacheFrom []*pb.CacheOptionsEntry
|
||||
for _, co := range options.CacheFrom {
|
||||
switch co.Type {
|
||||
case "local":
|
||||
@@ -87,7 +124,7 @@ func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
|
||||
}
|
||||
options.CacheFrom = cacheFrom
|
||||
|
||||
var cacheTo []*CacheOptionsEntry
|
||||
var cacheTo []*pb.CacheOptionsEntry
|
||||
for _, co := range options.CacheTo {
|
||||
switch co.Type {
|
||||
case "local":
|
||||
@@ -117,7 +154,7 @@ func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
|
||||
}
|
||||
}
|
||||
options.CacheTo = cacheTo
|
||||
var exports []*ExportEntry
|
||||
var exports []*pb.ExportEntry
|
||||
for _, e := range options.Exports {
|
||||
if e.Destination != "" && e.Destination != "-" {
|
||||
e.Destination, err = filepath.Abs(e.Destination)
|
||||
@@ -129,7 +166,7 @@ func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
|
||||
}
|
||||
options.Exports = exports
|
||||
|
||||
var secrets []*Secret
|
||||
var secrets []*pb.Secret
|
||||
for _, s := range options.Secrets {
|
||||
if s.FilePath != "" {
|
||||
s.FilePath, err = filepath.Abs(s.FilePath)
|
||||
@@ -141,7 +178,7 @@ func ResolveOptionPaths(options *BuildOptions) (_ *BuildOptions, err error) {
|
||||
}
|
||||
options.Secrets = secrets
|
||||
|
||||
var ssh []*SSH
|
||||
var ssh []*pb.SSH
|
||||
for _, s := range options.SSH {
|
||||
var ps []string
|
||||
for _, pt := range s.Paths {
|
@@ -1,12 +1,12 @@
|
||||
package pb
|
||||
package build
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestResolvePaths(t *testing.T) {
|
||||
@@ -16,59 +16,59 @@ func TestResolvePaths(t *testing.T) {
|
||||
require.NoError(t, os.Chdir(tmpwd))
|
||||
tests := []struct {
|
||||
name string
|
||||
options *BuildOptions
|
||||
want *BuildOptions
|
||||
options *Options
|
||||
want *Options
|
||||
}{
|
||||
{
|
||||
name: "contextpath",
|
||||
options: &BuildOptions{ContextPath: "test"},
|
||||
want: &BuildOptions{ContextPath: filepath.Join(tmpwd, "test")},
|
||||
options: &Options{ContextPath: "test"},
|
||||
want: &Options{ContextPath: filepath.Join(tmpwd, "test")},
|
||||
},
|
||||
{
|
||||
name: "contextpath-cwd",
|
||||
options: &BuildOptions{ContextPath: "."},
|
||||
want: &BuildOptions{ContextPath: tmpwd},
|
||||
options: &Options{ContextPath: "."},
|
||||
want: &Options{ContextPath: tmpwd},
|
||||
},
|
||||
{
|
||||
name: "contextpath-dash",
|
||||
options: &BuildOptions{ContextPath: "-"},
|
||||
want: &BuildOptions{ContextPath: "-"},
|
||||
options: &Options{ContextPath: "-"},
|
||||
want: &Options{ContextPath: "-"},
|
||||
},
|
||||
{
|
||||
name: "contextpath-ssh",
|
||||
options: &BuildOptions{ContextPath: "git@github.com:docker/buildx.git"},
|
||||
want: &BuildOptions{ContextPath: "git@github.com:docker/buildx.git"},
|
||||
options: &Options{ContextPath: "git@github.com:docker/buildx.git"},
|
||||
want: &Options{ContextPath: "git@github.com:docker/buildx.git"},
|
||||
},
|
||||
{
|
||||
name: "dockerfilename",
|
||||
options: &BuildOptions{DockerfileName: "test", ContextPath: "."},
|
||||
want: &BuildOptions{DockerfileName: filepath.Join(tmpwd, "test"), ContextPath: tmpwd},
|
||||
options: &Options{DockerfileName: "test", ContextPath: "."},
|
||||
want: &Options{DockerfileName: filepath.Join(tmpwd, "test"), ContextPath: tmpwd},
|
||||
},
|
||||
{
|
||||
name: "dockerfilename-dash",
|
||||
options: &BuildOptions{DockerfileName: "-", ContextPath: "."},
|
||||
want: &BuildOptions{DockerfileName: "-", ContextPath: tmpwd},
|
||||
options: &Options{DockerfileName: "-", ContextPath: "."},
|
||||
want: &Options{DockerfileName: "-", ContextPath: tmpwd},
|
||||
},
|
||||
{
|
||||
name: "dockerfilename-remote",
|
||||
options: &BuildOptions{DockerfileName: "test", ContextPath: "git@github.com:docker/buildx.git"},
|
||||
want: &BuildOptions{DockerfileName: "test", ContextPath: "git@github.com:docker/buildx.git"},
|
||||
options: &Options{DockerfileName: "test", ContextPath: "git@github.com:docker/buildx.git"},
|
||||
want: &Options{DockerfileName: "test", ContextPath: "git@github.com:docker/buildx.git"},
|
||||
},
|
||||
{
|
||||
name: "contexts",
|
||||
options: &BuildOptions{NamedContexts: map[string]string{
|
||||
options: &Options{NamedContexts: map[string]string{
|
||||
"a": "test1", "b": "test2",
|
||||
"alpine": "docker-image://alpine@sha256:0123456789", "project": "https://github.com/myuser/project.git",
|
||||
}},
|
||||
want: &BuildOptions{NamedContexts: map[string]string{
|
||||
want: &Options{NamedContexts: map[string]string{
|
||||
"a": filepath.Join(tmpwd, "test1"), "b": filepath.Join(tmpwd, "test2"),
|
||||
"alpine": "docker-image://alpine@sha256:0123456789", "project": "https://github.com/myuser/project.git",
|
||||
}},
|
||||
},
|
||||
{
|
||||
name: "cache-from",
|
||||
options: &BuildOptions{
|
||||
CacheFrom: []*CacheOptionsEntry{
|
||||
options: &Options{
|
||||
CacheFrom: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"src": "test"},
|
||||
@@ -79,8 +79,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &BuildOptions{
|
||||
CacheFrom: []*CacheOptionsEntry{
|
||||
want: &Options{
|
||||
CacheFrom: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"src": filepath.Join(tmpwd, "test")},
|
||||
@@ -94,8 +94,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "cache-to",
|
||||
options: &BuildOptions{
|
||||
CacheTo: []*CacheOptionsEntry{
|
||||
options: &Options{
|
||||
CacheTo: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"dest": "test"},
|
||||
@@ -106,8 +106,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &BuildOptions{
|
||||
CacheTo: []*CacheOptionsEntry{
|
||||
want: &Options{
|
||||
CacheTo: []*pb.CacheOptionsEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Attrs: map[string]string{"dest": filepath.Join(tmpwd, "test")},
|
||||
@@ -121,8 +121,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "exports",
|
||||
options: &BuildOptions{
|
||||
Exports: []*ExportEntry{
|
||||
options: &Options{
|
||||
Exports: []*pb.ExportEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Destination: "-",
|
||||
@@ -149,8 +149,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &BuildOptions{
|
||||
Exports: []*ExportEntry{
|
||||
want: &Options{
|
||||
Exports: []*pb.ExportEntry{
|
||||
{
|
||||
Type: "local",
|
||||
Destination: "-",
|
||||
@@ -180,8 +180,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "secrets",
|
||||
options: &BuildOptions{
|
||||
Secrets: []*Secret{
|
||||
options: &Options{
|
||||
Secrets: []*pb.Secret{
|
||||
{
|
||||
FilePath: "test1",
|
||||
},
|
||||
@@ -195,8 +195,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &BuildOptions{
|
||||
Secrets: []*Secret{
|
||||
want: &Options{
|
||||
Secrets: []*pb.Secret{
|
||||
{
|
||||
FilePath: filepath.Join(tmpwd, "test1"),
|
||||
},
|
||||
@@ -213,8 +213,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "ssh",
|
||||
options: &BuildOptions{
|
||||
SSH: []*SSH{
|
||||
options: &Options{
|
||||
SSH: []*pb.SSH{
|
||||
{
|
||||
ID: "default",
|
||||
Paths: []string{"test1", "test2"},
|
||||
@@ -225,8 +225,8 @@ func TestResolvePaths(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: &BuildOptions{
|
||||
SSH: []*SSH{
|
||||
want: &Options{
|
||||
SSH: []*pb.SSH{
|
||||
{
|
||||
ID: "default",
|
||||
Paths: []string{filepath.Join(tmpwd, "test1"), filepath.Join(tmpwd, "test2")},
|
||||
@@ -244,9 +244,7 @@ func TestResolvePaths(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ResolveOptionPaths(tt.options)
|
||||
require.NoError(t, err)
|
||||
if !proto.Equal(tt.want, got) {
|
||||
t.Fatalf("expected %#v, got %#v", tt.want, got)
|
||||
}
|
||||
require.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
@@ -5,29 +5,22 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/buildx/build"
|
||||
cbuild "github.com/docker/buildx/controller/build"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/controller/processes"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/moby/buildkit/client"
|
||||
)
|
||||
|
||||
type BuildxController interface {
|
||||
Build(ctx context.Context, options *controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (ref string, resp *client.SolveResponse, inputs *build.Inputs, err error)
|
||||
Build(ctx context.Context, options *cbuild.Options, in io.ReadCloser, progress progress.Writer) (resp *client.SolveResponse, inputs *build.Inputs, err error)
|
||||
// Invoke starts an IO session into the specified process.
|
||||
// If pid doesn't match to any running processes, it starts a new process with the specified config.
|
||||
// If there is no container running or InvokeConfig.Rollback is specified, the process will start in a newly created container.
|
||||
// NOTE: If needed, in the future, we can split this API into three APIs (NewContainer, NewProcess and Attach).
|
||||
Invoke(ctx context.Context, ref, pid string, options *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error
|
||||
Kill(ctx context.Context) error
|
||||
Invoke(ctx context.Context, pid string, options *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error
|
||||
Close() error
|
||||
List(ctx context.Context) (refs []string, _ error)
|
||||
Disconnect(ctx context.Context, ref string) error
|
||||
ListProcesses(ctx context.Context, ref string) (infos []*controllerapi.ProcessInfo, retErr error)
|
||||
DisconnectProcess(ctx context.Context, ref, pid string) error
|
||||
Inspect(ctx context.Context, ref string) (*controllerapi.InspectResponse, error)
|
||||
}
|
||||
|
||||
type ControlOptions struct {
|
||||
ServerConfig string
|
||||
Root string
|
||||
Detach bool
|
||||
ListProcesses(ctx context.Context) (infos []*processes.ProcessInfo, retErr error)
|
||||
DisconnectProcess(ctx context.Context, pid string) error
|
||||
Inspect(ctx context.Context) *cbuild.Options
|
||||
}
|
||||
|
@@ -2,35 +2,12 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/buildx/controller/control"
|
||||
"github.com/docker/buildx/controller/local"
|
||||
"github.com/docker/buildx/controller/remote"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NewController(ctx context.Context, opts control.ControlOptions, dockerCli command.Cli, pw progress.Writer) (control.BuildxController, error) {
|
||||
var name string
|
||||
if opts.Detach {
|
||||
name = "remote"
|
||||
} else {
|
||||
name = "local"
|
||||
}
|
||||
|
||||
var c control.BuildxController
|
||||
err := progress.Wrap(fmt.Sprintf("[internal] connecting to %s controller", name), pw.Write, func(l progress.SubLogger) (err error) {
|
||||
if opts.Detach {
|
||||
c, err = remote.NewRemoteBuildxController(ctx, dockerCli, opts, l)
|
||||
} else {
|
||||
c = local.NewLocalBuildxController(ctx, dockerCli, l)
|
||||
}
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to start buildx controller")
|
||||
}
|
||||
return c, nil
|
||||
func NewController(ctx context.Context, dockerCli command.Cli) control.BuildxController {
|
||||
return local.NewLocalBuildxController(ctx, dockerCli)
|
||||
}
|
||||
|
@@ -1,48 +1,20 @@
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/containerd/typeurl/v2"
|
||||
"github.com/docker/buildx/util/desktop"
|
||||
"github.com/moby/buildkit/util/grpcerrors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
typeurl.Register((*Build)(nil), "github.com/docker/buildx", "errdefs.Build+json")
|
||||
}
|
||||
|
||||
type BuildError struct {
|
||||
*Build
|
||||
error
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *BuildError) Unwrap() error {
|
||||
return e.error
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e *BuildError) ToProto() grpcerrors.TypedErrorProto {
|
||||
return e.Build
|
||||
func (e *BuildError) Error() string {
|
||||
return e.err.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 {
|
||||
func WrapBuild(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &BuildError{Build: &Build{SessionID: sessionID, Ref: ref}, error: err}
|
||||
}
|
||||
|
||||
func (b *Build) WrapError(err error) error {
|
||||
return &BuildError{error: err, Build: b}
|
||||
return &BuildError{err: err}
|
||||
}
|
||||
|
@@ -1,157 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v3.11.4
|
||||
// source: github.com/docker/buildx/controller/errdefs/errdefs.proto
|
||||
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Build struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
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() {
|
||||
*x = Build{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_github_com_docker_buildx_controller_errdefs_errdefs_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Build) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Build) ProtoMessage() {}
|
||||
|
||||
func (x *Build) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_github_com_docker_buildx_controller_errdefs_errdefs_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Build.ProtoReflect.Descriptor instead.
|
||||
func (*Build) Descriptor() ([]byte, []int) {
|
||||
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 {
|
||||
if x != nil {
|
||||
return x.Ref
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_github_com_docker_buildx_controller_errdefs_errdefs_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDesc = []byte{
|
||||
0x0a, 0x39, 0x67, 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, 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,
|
||||
0x6b, 0x65, 0x72, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x78, 0x2e, 0x65, 0x72, 0x72, 0x64, 0x65,
|
||||
0x66, 0x73, 0x22, 0x37, 0x0a, 0x05, 0x42, 0x75, 0x69, 0x6c, 0x64, 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, 0x10, 0x0a, 0x03, 0x52, 0x65, 0x66,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x52, 0x65, 0x66, 0x42, 0x2d, 0x5a, 0x2b, 0x67,
|
||||
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, 0x65, 0x72, 0x72, 0x64, 0x65, 0x66, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescOnce sync.Once
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescData = file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescGZIP() []byte {
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescOnce.Do(func() {
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescData)
|
||||
})
|
||||
return file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_github_com_docker_buildx_controller_errdefs_errdefs_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_github_com_docker_buildx_controller_errdefs_errdefs_proto_goTypes = []interface{}{
|
||||
(*Build)(nil), // 0: docker.buildx.errdefs.Build
|
||||
}
|
||||
var file_github_com_docker_buildx_controller_errdefs_errdefs_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_github_com_docker_buildx_controller_errdefs_errdefs_proto_init() }
|
||||
func file_github_com_docker_buildx_controller_errdefs_errdefs_proto_init() {
|
||||
if File_github_com_docker_buildx_controller_errdefs_errdefs_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Build); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_github_com_docker_buildx_controller_errdefs_errdefs_proto_goTypes,
|
||||
DependencyIndexes: file_github_com_docker_buildx_controller_errdefs_errdefs_proto_depIdxs,
|
||||
MessageInfos: file_github_com_docker_buildx_controller_errdefs_errdefs_proto_msgTypes,
|
||||
}.Build()
|
||||
File_github_com_docker_buildx_controller_errdefs_errdefs_proto = out.File
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_rawDesc = nil
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_goTypes = nil
|
||||
file_github_com_docker_buildx_controller_errdefs_errdefs_proto_depIdxs = nil
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package docker.buildx.errdefs;
|
||||
|
||||
option go_package = "github.com/docker/buildx/controller/errdefs";
|
||||
|
||||
message Build {
|
||||
string SessionID = 1;
|
||||
string Ref = 2;
|
||||
}
|
@@ -1,241 +0,0 @@
|
||||
// Code generated by protoc-gen-go-vtproto. DO NOT EDIT.
|
||||
// protoc-gen-go-vtproto version: v0.6.1-0.20240319094008-0393e58bdf10
|
||||
// source: github.com/docker/buildx/controller/errdefs/errdefs.proto
|
||||
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
protohelpers "github.com/planetscale/vtprotobuf/protohelpers"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
io "io"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
func (m *Build) CloneVT() *Build {
|
||||
if m == nil {
|
||||
return (*Build)(nil)
|
||||
}
|
||||
r := new(Build)
|
||||
r.SessionID = m.SessionID
|
||||
r.Ref = m.Ref
|
||||
if len(m.unknownFields) > 0 {
|
||||
r.unknownFields = make([]byte, len(m.unknownFields))
|
||||
copy(r.unknownFields, m.unknownFields)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (m *Build) CloneMessageVT() proto.Message {
|
||||
return m.CloneVT()
|
||||
}
|
||||
|
||||
func (this *Build) EqualVT(that *Build) bool {
|
||||
if this == that {
|
||||
return true
|
||||
} else if this == nil || that == nil {
|
||||
return false
|
||||
}
|
||||
if this.SessionID != that.SessionID {
|
||||
return false
|
||||
}
|
||||
if this.Ref != that.Ref {
|
||||
return false
|
||||
}
|
||||
return string(this.unknownFields) == string(that.unknownFields)
|
||||
}
|
||||
|
||||
func (this *Build) EqualMessageVT(thatMsg proto.Message) bool {
|
||||
that, ok := thatMsg.(*Build)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return this.EqualVT(that)
|
||||
}
|
||||
func (m *Build) MarshalVT() (dAtA []byte, err error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
size := m.SizeVT()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Build) MarshalToVT(dAtA []byte) (int, error) {
|
||||
size := m.SizeVT()
|
||||
return m.MarshalToSizedBufferVT(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Build) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.unknownFields != nil {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Ref) > 0 {
|
||||
i -= len(m.Ref)
|
||||
copy(dAtA[i:], m.Ref)
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Ref)))
|
||||
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
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *Build) SizeVT() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.SessionID)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
l = len(m.Ref)
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Build) UnmarshalVT(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Build: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Build: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
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 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Ref", 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.Ref = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return protohelpers.ErrInvalidLength
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -11,7 +11,6 @@ import (
|
||||
controllererrors "github.com/docker/buildx/controller/errdefs"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/controller/processes"
|
||||
"github.com/docker/buildx/util/desktop"
|
||||
"github.com/docker/buildx/util/ioset"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/cli/cli/command"
|
||||
@@ -19,10 +18,9 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func NewLocalBuildxController(ctx context.Context, dockerCli command.Cli, logger progress.SubLogger) control.BuildxController {
|
||||
func NewLocalBuildxController(ctx context.Context, dockerCli command.Cli) control.BuildxController {
|
||||
return &localController{
|
||||
dockerCli: dockerCli,
|
||||
sessionID: "local",
|
||||
processes: processes.NewManager(),
|
||||
}
|
||||
}
|
||||
@@ -31,21 +29,20 @@ type buildConfig struct {
|
||||
// TODO: these two structs should be merged
|
||||
// Discussion: https://github.com/docker/buildx/pull/1640#discussion_r1113279719
|
||||
resultCtx *build.ResultHandle
|
||||
buildOptions *controllerapi.BuildOptions
|
||||
buildOptions *cbuild.Options
|
||||
}
|
||||
|
||||
type localController struct {
|
||||
dockerCli command.Cli
|
||||
sessionID string
|
||||
buildConfig buildConfig
|
||||
processes *processes.Manager
|
||||
|
||||
buildOnGoing atomic.Bool
|
||||
}
|
||||
|
||||
func (b *localController) Build(ctx context.Context, options *controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (string, *client.SolveResponse, *build.Inputs, error) {
|
||||
func (b *localController) Build(ctx context.Context, options *cbuild.Options, in io.ReadCloser, progress progress.Writer) (*client.SolveResponse, *build.Inputs, error) {
|
||||
if !b.buildOnGoing.CompareAndSwap(false, true) {
|
||||
return "", nil, nil, errors.New("build ongoing")
|
||||
return nil, nil, errors.New("build ongoing")
|
||||
}
|
||||
defer b.buildOnGoing.Store(false)
|
||||
|
||||
@@ -57,31 +54,20 @@ func (b *localController) Build(ctx context.Context, options *controllerapi.Buil
|
||||
buildOptions: options,
|
||||
}
|
||||
if buildErr != nil {
|
||||
var ref string
|
||||
var ebr *desktop.ErrorWithBuildRef
|
||||
if errors.As(buildErr, &ebr) {
|
||||
ref = ebr.Ref
|
||||
}
|
||||
buildErr = controllererrors.WrapBuild(buildErr, b.sessionID, ref)
|
||||
buildErr = controllererrors.WrapBuild(buildErr)
|
||||
}
|
||||
}
|
||||
if buildErr != nil {
|
||||
return "", nil, nil, buildErr
|
||||
return nil, nil, buildErr
|
||||
}
|
||||
return b.sessionID, resp, dockerfileMappings, nil
|
||||
return resp, dockerfileMappings, nil
|
||||
}
|
||||
|
||||
func (b *localController) ListProcesses(ctx context.Context, sessionID string) (infos []*controllerapi.ProcessInfo, retErr error) {
|
||||
if sessionID != b.sessionID {
|
||||
return nil, errors.Errorf("unknown session ID %q", sessionID)
|
||||
}
|
||||
func (b *localController) ListProcesses(ctx context.Context) (infos []*processes.ProcessInfo, retErr error) {
|
||||
return b.processes.ListProcesses(), nil
|
||||
}
|
||||
|
||||
func (b *localController) DisconnectProcess(ctx context.Context, sessionID, pid string) error {
|
||||
if sessionID != b.sessionID {
|
||||
return errors.Errorf("unknown session ID %q", sessionID)
|
||||
}
|
||||
func (b *localController) DisconnectProcess(ctx context.Context, pid string) error {
|
||||
return b.processes.DeleteProcess(pid)
|
||||
}
|
||||
|
||||
@@ -89,11 +75,7 @@ func (b *localController) cancelRunningProcesses() {
|
||||
b.processes.CancelRunningProcesses()
|
||||
}
|
||||
|
||||
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 sessionID != b.sessionID {
|
||||
return errors.Errorf("unknown session ID %q", sessionID)
|
||||
}
|
||||
|
||||
func (b *localController) Invoke(ctx context.Context, pid string, cfg *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error {
|
||||
proc, ok := b.processes.Get(pid)
|
||||
if !ok {
|
||||
// Start a new process.
|
||||
@@ -121,11 +103,6 @@ func (b *localController) Invoke(ctx context.Context, sessionID string, pid stri
|
||||
}
|
||||
}
|
||||
|
||||
func (b *localController) Kill(context.Context) error {
|
||||
b.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *localController) Close() error {
|
||||
b.cancelRunningProcesses()
|
||||
if b.buildConfig.resultCtx != nil {
|
||||
@@ -135,18 +112,6 @@ func (b *localController) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *localController) List(ctx context.Context) (res []string, _ error) {
|
||||
return []string{b.sessionID}, nil
|
||||
}
|
||||
|
||||
func (b *localController) Disconnect(ctx context.Context, key string) error {
|
||||
b.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *localController) Inspect(ctx context.Context, sessionID string) (*controllerapi.InspectResponse, error) {
|
||||
if sessionID != b.sessionID {
|
||||
return nil, errors.Errorf("unknown session ID %q", sessionID)
|
||||
}
|
||||
return &controllerapi.InspectResponse{Options: b.buildConfig.buildOptions}, nil
|
||||
func (b *localController) Inspect(ctx context.Context) *cbuild.Options {
|
||||
return b.buildConfig.buildOptions
|
||||
}
|
||||
|
@@ -1,5 +1,11 @@
|
||||
package pb
|
||||
|
||||
type Attest struct {
|
||||
Type string
|
||||
Disabled bool
|
||||
Attrs string
|
||||
}
|
||||
|
||||
func CreateAttestations(attests []*Attest) map[string]*string {
|
||||
result := map[string]*string{}
|
||||
for _, attest := range attests {
|
||||
|
@@ -6,6 +6,11 @@ import (
|
||||
"github.com/moby/buildkit/client"
|
||||
)
|
||||
|
||||
type CacheOptionsEntry struct {
|
||||
Type string
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
func CreateCaches(entries []*CacheOptionsEntry) []client.CacheOptionsEntry {
|
||||
var outs []client.CacheOptionsEntry
|
||||
if len(entries) == 0 {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,250 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package buildx.controller.v1;
|
||||
|
||||
import "github.com/moby/buildkit/api/services/control/control.proto";
|
||||
import "github.com/moby/buildkit/sourcepolicy/pb/policy.proto";
|
||||
|
||||
option go_package = "github.com/docker/buildx/controller/pb";
|
||||
|
||||
service Controller {
|
||||
rpc Build(BuildRequest) returns (BuildResponse);
|
||||
rpc Inspect(InspectRequest) returns (InspectResponse);
|
||||
rpc Status(StatusRequest) returns (stream StatusResponse);
|
||||
rpc Input(stream InputMessage) returns (InputResponse);
|
||||
rpc Invoke(stream Message) returns (stream Message);
|
||||
rpc List(ListRequest) returns (ListResponse);
|
||||
rpc Disconnect(DisconnectRequest) returns (DisconnectResponse);
|
||||
rpc Info(InfoRequest) returns (InfoResponse);
|
||||
rpc ListProcesses(ListProcessesRequest) returns (ListProcessesResponse);
|
||||
rpc DisconnectProcess(DisconnectProcessRequest) returns (DisconnectProcessResponse);
|
||||
}
|
||||
|
||||
message ListProcessesRequest {
|
||||
string SessionID = 1;
|
||||
}
|
||||
|
||||
message ListProcessesResponse {
|
||||
repeated ProcessInfo Infos = 1;
|
||||
}
|
||||
|
||||
message ProcessInfo {
|
||||
string ProcessID = 1;
|
||||
InvokeConfig InvokeConfig = 2;
|
||||
}
|
||||
|
||||
message DisconnectProcessRequest {
|
||||
string SessionID = 1;
|
||||
string ProcessID = 2;
|
||||
}
|
||||
|
||||
message DisconnectProcessResponse {
|
||||
}
|
||||
|
||||
message BuildRequest {
|
||||
string SessionID = 1;
|
||||
BuildOptions Options = 2;
|
||||
}
|
||||
|
||||
message BuildOptions {
|
||||
string ContextPath = 1;
|
||||
string DockerfileName = 2;
|
||||
CallFunc CallFunc = 3;
|
||||
map<string, string> NamedContexts = 4;
|
||||
|
||||
repeated string Allow = 5;
|
||||
repeated Attest Attests = 6;
|
||||
map<string, string> BuildArgs = 7;
|
||||
repeated CacheOptionsEntry CacheFrom = 8;
|
||||
repeated CacheOptionsEntry CacheTo = 9;
|
||||
string CgroupParent = 10;
|
||||
repeated ExportEntry Exports = 11;
|
||||
repeated string ExtraHosts = 12;
|
||||
map<string, string> Labels = 13;
|
||||
string NetworkMode = 14;
|
||||
repeated string NoCacheFilter = 15;
|
||||
repeated string Platforms = 16;
|
||||
repeated Secret Secrets = 17;
|
||||
int64 ShmSize = 18;
|
||||
repeated SSH SSH = 19;
|
||||
repeated string Tags = 20;
|
||||
string Target = 21;
|
||||
UlimitOpt Ulimits = 22;
|
||||
|
||||
string Builder = 23;
|
||||
bool NoCache = 24;
|
||||
bool Pull = 25;
|
||||
bool ExportPush = 26;
|
||||
bool ExportLoad = 27;
|
||||
moby.buildkit.v1.sourcepolicy.Policy SourcePolicy = 28;
|
||||
string Ref = 29;
|
||||
string GroupRef = 30;
|
||||
repeated string Annotations = 31;
|
||||
string ProvenanceResponseMode = 32;
|
||||
}
|
||||
|
||||
message ExportEntry {
|
||||
string Type = 1;
|
||||
map<string, string> Attrs = 2;
|
||||
string Destination = 3;
|
||||
}
|
||||
|
||||
message CacheOptionsEntry {
|
||||
string Type = 1;
|
||||
map<string, string> Attrs = 2;
|
||||
}
|
||||
|
||||
message Attest {
|
||||
string Type = 1;
|
||||
bool Disabled = 2;
|
||||
string Attrs = 3;
|
||||
}
|
||||
|
||||
message SSH {
|
||||
string ID = 1;
|
||||
repeated string Paths = 2;
|
||||
}
|
||||
|
||||
message Secret {
|
||||
string ID = 1;
|
||||
string FilePath = 2;
|
||||
string Env = 3;
|
||||
}
|
||||
|
||||
message CallFunc {
|
||||
string Name = 1;
|
||||
string Format = 2;
|
||||
bool IgnoreStatus = 3;
|
||||
}
|
||||
|
||||
message InspectRequest {
|
||||
string SessionID = 1;
|
||||
}
|
||||
|
||||
message InspectResponse {
|
||||
BuildOptions Options = 1;
|
||||
}
|
||||
|
||||
message UlimitOpt {
|
||||
map<string, Ulimit> values = 1;
|
||||
}
|
||||
|
||||
message Ulimit {
|
||||
string Name = 1;
|
||||
int64 Hard = 2;
|
||||
int64 Soft = 3;
|
||||
}
|
||||
|
||||
message BuildResponse {
|
||||
map<string, string> ExporterResponse = 1;
|
||||
}
|
||||
|
||||
message DisconnectRequest {
|
||||
string SessionID = 1;
|
||||
}
|
||||
|
||||
message DisconnectResponse {}
|
||||
|
||||
message ListRequest {
|
||||
string SessionID = 1;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated string keys = 1;
|
||||
}
|
||||
|
||||
message InputMessage {
|
||||
oneof Input {
|
||||
InputInitMessage Init = 1;
|
||||
DataMessage Data = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message InputInitMessage {
|
||||
string SessionID = 1;
|
||||
}
|
||||
|
||||
message DataMessage {
|
||||
bool EOF = 1; // true if eof was reached
|
||||
bytes Data = 2; // should be chunked smaller than 4MB:
|
||||
// https://pkg.go.dev/google.golang.org/grpc#MaxRecvMsgSize
|
||||
}
|
||||
|
||||
message InputResponse {}
|
||||
|
||||
message Message {
|
||||
oneof Input {
|
||||
InitMessage Init = 1;
|
||||
// FdMessage used from client to server for input (stdin) and
|
||||
// from server to client for output (stdout, stderr)
|
||||
FdMessage File = 2;
|
||||
// ResizeMessage used from client to server for terminal resize events
|
||||
ResizeMessage Resize = 3;
|
||||
// SignalMessage is used from client to server to send signal events
|
||||
SignalMessage Signal = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message InitMessage {
|
||||
string SessionID = 1;
|
||||
|
||||
// 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.
|
||||
string ProcessID = 2;
|
||||
InvokeConfig InvokeConfig = 3;
|
||||
}
|
||||
|
||||
message InvokeConfig {
|
||||
repeated string Entrypoint = 1;
|
||||
repeated string Cmd = 2;
|
||||
bool NoCmd = 11; // Do not set cmd but use the image's default
|
||||
repeated string Env = 3;
|
||||
string User = 4;
|
||||
bool NoUser = 5; // Do not set user but use the image's default
|
||||
string Cwd = 6;
|
||||
bool NoCwd = 7; // Do not set cwd but use the image's default
|
||||
bool Tty = 8;
|
||||
bool Rollback = 9; // Kill all process in the container and recreate it.
|
||||
bool Initial = 10; // Run container from the initial state of that stage (supported only on the failed step)
|
||||
}
|
||||
|
||||
message FdMessage {
|
||||
uint32 Fd = 1; // what fd the data was from
|
||||
bool EOF = 2; // true if eof was reached
|
||||
bytes Data = 3; // should be chunked smaller than 4MB:
|
||||
// https://pkg.go.dev/google.golang.org/grpc#MaxRecvMsgSize
|
||||
}
|
||||
|
||||
message ResizeMessage {
|
||||
uint32 Rows = 1;
|
||||
uint32 Cols = 2;
|
||||
}
|
||||
|
||||
message SignalMessage {
|
||||
// we only send name (ie HUP, INT) because the int values
|
||||
// are platform dependent.
|
||||
string Name = 1;
|
||||
}
|
||||
|
||||
message StatusRequest {
|
||||
string SessionID = 1;
|
||||
}
|
||||
|
||||
message StatusResponse {
|
||||
repeated moby.buildkit.v1.Vertex vertexes = 1;
|
||||
repeated moby.buildkit.v1.VertexStatus statuses = 2;
|
||||
repeated moby.buildkit.v1.VertexLog logs = 3;
|
||||
repeated moby.buildkit.v1.VertexWarning warnings = 4;
|
||||
}
|
||||
|
||||
message InfoRequest {}
|
||||
|
||||
message InfoResponse {
|
||||
BuildxVersion buildxVersion = 1;
|
||||
}
|
||||
|
||||
message BuildxVersion {
|
||||
string package = 1;
|
||||
string version = 2;
|
||||
string revision = 3;
|
||||
}
|
@@ -1,452 +0,0 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v3.11.4
|
||||
// source: github.com/docker/buildx/controller/pb/controller.proto
|
||||
|
||||
package pb
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Controller_Build_FullMethodName = "/buildx.controller.v1.Controller/Build"
|
||||
Controller_Inspect_FullMethodName = "/buildx.controller.v1.Controller/Inspect"
|
||||
Controller_Status_FullMethodName = "/buildx.controller.v1.Controller/Status"
|
||||
Controller_Input_FullMethodName = "/buildx.controller.v1.Controller/Input"
|
||||
Controller_Invoke_FullMethodName = "/buildx.controller.v1.Controller/Invoke"
|
||||
Controller_List_FullMethodName = "/buildx.controller.v1.Controller/List"
|
||||
Controller_Disconnect_FullMethodName = "/buildx.controller.v1.Controller/Disconnect"
|
||||
Controller_Info_FullMethodName = "/buildx.controller.v1.Controller/Info"
|
||||
Controller_ListProcesses_FullMethodName = "/buildx.controller.v1.Controller/ListProcesses"
|
||||
Controller_DisconnectProcess_FullMethodName = "/buildx.controller.v1.Controller/DisconnectProcess"
|
||||
)
|
||||
|
||||
// ControllerClient is the client API for Controller service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type ControllerClient interface {
|
||||
Build(ctx context.Context, in *BuildRequest, opts ...grpc.CallOption) (*BuildResponse, error)
|
||||
Inspect(ctx context.Context, in *InspectRequest, opts ...grpc.CallOption) (*InspectResponse, error)
|
||||
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StatusResponse], error)
|
||||
Input(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[InputMessage, InputResponse], error)
|
||||
Invoke(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[Message, Message], error)
|
||||
List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error)
|
||||
Disconnect(ctx context.Context, in *DisconnectRequest, opts ...grpc.CallOption) (*DisconnectResponse, error)
|
||||
Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error)
|
||||
ListProcesses(ctx context.Context, in *ListProcessesRequest, opts ...grpc.CallOption) (*ListProcessesResponse, error)
|
||||
DisconnectProcess(ctx context.Context, in *DisconnectProcessRequest, opts ...grpc.CallOption) (*DisconnectProcessResponse, error)
|
||||
}
|
||||
|
||||
type controllerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewControllerClient(cc grpc.ClientConnInterface) ControllerClient {
|
||||
return &controllerClient{cc}
|
||||
}
|
||||
|
||||
func (c *controllerClient) Build(ctx context.Context, in *BuildRequest, opts ...grpc.CallOption) (*BuildResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(BuildResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_Build_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *controllerClient) Inspect(ctx context.Context, in *InspectRequest, opts ...grpc.CallOption) (*InspectResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(InspectResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_Inspect_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *controllerClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StatusResponse], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &Controller_ServiceDesc.Streams[0], Controller_Status_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[StatusRequest, StatusResponse]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type Controller_StatusClient = grpc.ServerStreamingClient[StatusResponse]
|
||||
|
||||
func (c *controllerClient) Input(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[InputMessage, InputResponse], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &Controller_ServiceDesc.Streams[1], Controller_Input_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[InputMessage, InputResponse]{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type Controller_InputClient = grpc.ClientStreamingClient[InputMessage, InputResponse]
|
||||
|
||||
func (c *controllerClient) Invoke(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[Message, Message], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &Controller_ServiceDesc.Streams[2], Controller_Invoke_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[Message, Message]{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type Controller_InvokeClient = grpc.BidiStreamingClient[Message, Message]
|
||||
|
||||
func (c *controllerClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_List_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *controllerClient) Disconnect(ctx context.Context, in *DisconnectRequest, opts ...grpc.CallOption) (*DisconnectResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(DisconnectResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_Disconnect_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *controllerClient) Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(InfoResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_Info_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *controllerClient) ListProcesses(ctx context.Context, in *ListProcessesRequest, opts ...grpc.CallOption) (*ListProcessesResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListProcessesResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_ListProcesses_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *controllerClient) DisconnectProcess(ctx context.Context, in *DisconnectProcessRequest, opts ...grpc.CallOption) (*DisconnectProcessResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(DisconnectProcessResponse)
|
||||
err := c.cc.Invoke(ctx, Controller_DisconnectProcess_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ControllerServer is the server API for Controller service.
|
||||
// All implementations should embed UnimplementedControllerServer
|
||||
// for forward compatibility.
|
||||
type ControllerServer interface {
|
||||
Build(context.Context, *BuildRequest) (*BuildResponse, error)
|
||||
Inspect(context.Context, *InspectRequest) (*InspectResponse, error)
|
||||
Status(*StatusRequest, grpc.ServerStreamingServer[StatusResponse]) error
|
||||
Input(grpc.ClientStreamingServer[InputMessage, InputResponse]) error
|
||||
Invoke(grpc.BidiStreamingServer[Message, Message]) error
|
||||
List(context.Context, *ListRequest) (*ListResponse, error)
|
||||
Disconnect(context.Context, *DisconnectRequest) (*DisconnectResponse, error)
|
||||
Info(context.Context, *InfoRequest) (*InfoResponse, error)
|
||||
ListProcesses(context.Context, *ListProcessesRequest) (*ListProcessesResponse, error)
|
||||
DisconnectProcess(context.Context, *DisconnectProcessRequest) (*DisconnectProcessResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedControllerServer should be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedControllerServer struct{}
|
||||
|
||||
func (UnimplementedControllerServer) Build(context.Context, *BuildRequest) (*BuildResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Build not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) Inspect(context.Context, *InspectRequest) (*InspectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Inspect not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) Status(*StatusRequest, grpc.ServerStreamingServer[StatusResponse]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Status not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) Input(grpc.ClientStreamingServer[InputMessage, InputResponse]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Input not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) Invoke(grpc.BidiStreamingServer[Message, Message]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Invoke not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) List(context.Context, *ListRequest) (*ListResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method List not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) Disconnect(context.Context, *DisconnectRequest) (*DisconnectResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Disconnect not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) Info(context.Context, *InfoRequest) (*InfoResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Info not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) ListProcesses(context.Context, *ListProcessesRequest) (*ListProcessesResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListProcesses not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) DisconnectProcess(context.Context, *DisconnectProcessRequest) (*DisconnectProcessResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DisconnectProcess not implemented")
|
||||
}
|
||||
func (UnimplementedControllerServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeControllerServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ControllerServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeControllerServer interface {
|
||||
mustEmbedUnimplementedControllerServer()
|
||||
}
|
||||
|
||||
func RegisterControllerServer(s grpc.ServiceRegistrar, srv ControllerServer) {
|
||||
// If the following call pancis, it indicates UnimplementedControllerServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Controller_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Controller_Build_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(BuildRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).Build(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_Build_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).Build(ctx, req.(*BuildRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Controller_Inspect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(InspectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).Inspect(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_Inspect_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).Inspect(ctx, req.(*InspectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Controller_Status_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(StatusRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ControllerServer).Status(m, &grpc.GenericServerStream[StatusRequest, StatusResponse]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type Controller_StatusServer = grpc.ServerStreamingServer[StatusResponse]
|
||||
|
||||
func _Controller_Input_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(ControllerServer).Input(&grpc.GenericServerStream[InputMessage, InputResponse]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type Controller_InputServer = grpc.ClientStreamingServer[InputMessage, InputResponse]
|
||||
|
||||
func _Controller_Invoke_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(ControllerServer).Invoke(&grpc.GenericServerStream[Message, Message]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type Controller_InvokeServer = grpc.BidiStreamingServer[Message, Message]
|
||||
|
||||
func _Controller_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).List(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_List_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).List(ctx, req.(*ListRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Controller_Disconnect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DisconnectRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).Disconnect(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_Disconnect_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).Disconnect(ctx, req.(*DisconnectRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Controller_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(InfoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).Info(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_Info_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).Info(ctx, req.(*InfoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Controller_ListProcesses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListProcessesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).ListProcesses(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_ListProcesses_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).ListProcesses(ctx, req.(*ListProcessesRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Controller_DisconnectProcess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DisconnectProcessRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ControllerServer).DisconnectProcess(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Controller_DisconnectProcess_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ControllerServer).DisconnectProcess(ctx, req.(*DisconnectProcessRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Controller_ServiceDesc is the grpc.ServiceDesc for Controller service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Controller_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "buildx.controller.v1.Controller",
|
||||
HandlerType: (*ControllerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Build",
|
||||
Handler: _Controller_Build_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Inspect",
|
||||
Handler: _Controller_Inspect_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "List",
|
||||
Handler: _Controller_List_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Disconnect",
|
||||
Handler: _Controller_Disconnect_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Info",
|
||||
Handler: _Controller_Info_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListProcesses",
|
||||
Handler: _Controller_ListProcesses_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "DisconnectProcess",
|
||||
Handler: _Controller_DisconnectProcess_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Status",
|
||||
Handler: _Controller_Status_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "Input",
|
||||
Handler: _Controller_Input_Handler,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "Invoke",
|
||||
Handler: _Controller_Invoke_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "github.com/docker/buildx/controller/pb/controller.proto",
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,12 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ExportEntry struct {
|
||||
Type string
|
||||
Attrs map[string]string
|
||||
Destination string
|
||||
}
|
||||
|
||||
func CreateExports(entries []*ExportEntry) ([]client.ExportEntry, []string, error) {
|
||||
var outs []client.ExportEntry
|
||||
var localPaths []string
|
||||
|
40
controller/pb/invoke.go
Normal file
40
controller/pb/invoke.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CallFunc struct {
|
||||
Name string
|
||||
Format string
|
||||
IgnoreStatus bool
|
||||
}
|
||||
|
||||
func (x *CallFunc) String() string {
|
||||
var elems []string
|
||||
if x.Name != "" {
|
||||
elems = append(elems, fmt.Sprintf("Name:%q", x.Name))
|
||||
}
|
||||
if x.Format != "" {
|
||||
elems = append(elems, fmt.Sprintf("Format:%q", x.Format))
|
||||
}
|
||||
if x.IgnoreStatus {
|
||||
elems = append(elems, fmt.Sprintf("IgnoreStatus:%v", x.IgnoreStatus))
|
||||
}
|
||||
return strings.Join(elems, " ")
|
||||
}
|
||||
|
||||
type InvokeConfig struct {
|
||||
Entrypoint []string
|
||||
Cmd []string
|
||||
NoCmd bool
|
||||
Env []string
|
||||
User string
|
||||
NoUser bool
|
||||
Cwd string
|
||||
NoCwd bool
|
||||
Tty bool
|
||||
Rollback bool
|
||||
Initial bool
|
||||
}
|
@@ -1,162 +0,0 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/buildx/util/progress"
|
||||
control "github.com/moby/buildkit/api/services/control"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
type writer struct {
|
||||
ch chan<- *StatusResponse
|
||||
}
|
||||
|
||||
func NewProgressWriter(ch chan<- *StatusResponse) progress.Writer {
|
||||
return &writer{ch: ch}
|
||||
}
|
||||
|
||||
func (w *writer) Write(status *client.SolveStatus) {
|
||||
w.ch <- ToControlStatus(status)
|
||||
}
|
||||
|
||||
func (w *writer) WriteBuildRef(target string, ref string) {}
|
||||
|
||||
func (w *writer) ValidateLogSource(digest.Digest, any) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *writer) ClearLogSource(any) {}
|
||||
|
||||
func ToControlStatus(s *client.SolveStatus) *StatusResponse {
|
||||
resp := StatusResponse{}
|
||||
for _, v := range s.Vertexes {
|
||||
resp.Vertexes = append(resp.Vertexes, &control.Vertex{
|
||||
Digest: string(v.Digest),
|
||||
Inputs: digestSliceToPB(v.Inputs),
|
||||
Name: v.Name,
|
||||
Started: timestampToPB(v.Started),
|
||||
Completed: timestampToPB(v.Completed),
|
||||
Error: v.Error,
|
||||
Cached: v.Cached,
|
||||
ProgressGroup: v.ProgressGroup,
|
||||
})
|
||||
}
|
||||
for _, v := range s.Statuses {
|
||||
resp.Statuses = append(resp.Statuses, &control.VertexStatus{
|
||||
ID: v.ID,
|
||||
Vertex: string(v.Vertex),
|
||||
Name: v.Name,
|
||||
Total: v.Total,
|
||||
Current: v.Current,
|
||||
Timestamp: timestamppb.New(v.Timestamp),
|
||||
Started: timestampToPB(v.Started),
|
||||
Completed: timestampToPB(v.Completed),
|
||||
})
|
||||
}
|
||||
for _, v := range s.Logs {
|
||||
resp.Logs = append(resp.Logs, &control.VertexLog{
|
||||
Vertex: string(v.Vertex),
|
||||
Stream: int64(v.Stream),
|
||||
Msg: v.Data,
|
||||
Timestamp: timestamppb.New(v.Timestamp),
|
||||
})
|
||||
}
|
||||
for _, v := range s.Warnings {
|
||||
resp.Warnings = append(resp.Warnings, &control.VertexWarning{
|
||||
Vertex: string(v.Vertex),
|
||||
Level: int64(v.Level),
|
||||
Short: v.Short,
|
||||
Detail: v.Detail,
|
||||
Url: v.URL,
|
||||
Info: v.SourceInfo,
|
||||
Ranges: v.Range,
|
||||
})
|
||||
}
|
||||
return &resp
|
||||
}
|
||||
|
||||
func FromControlStatus(resp *StatusResponse) *client.SolveStatus {
|
||||
s := client.SolveStatus{}
|
||||
for _, v := range resp.Vertexes {
|
||||
s.Vertexes = append(s.Vertexes, &client.Vertex{
|
||||
Digest: digest.Digest(v.Digest),
|
||||
Inputs: digestSliceFromPB(v.Inputs),
|
||||
Name: v.Name,
|
||||
Started: timestampFromPB(v.Started),
|
||||
Completed: timestampFromPB(v.Completed),
|
||||
Error: v.Error,
|
||||
Cached: v.Cached,
|
||||
ProgressGroup: v.ProgressGroup,
|
||||
})
|
||||
}
|
||||
for _, v := range resp.Statuses {
|
||||
s.Statuses = append(s.Statuses, &client.VertexStatus{
|
||||
ID: v.ID,
|
||||
Vertex: digest.Digest(v.Vertex),
|
||||
Name: v.Name,
|
||||
Total: v.Total,
|
||||
Current: v.Current,
|
||||
Timestamp: v.Timestamp.AsTime(),
|
||||
Started: timestampFromPB(v.Started),
|
||||
Completed: timestampFromPB(v.Completed),
|
||||
})
|
||||
}
|
||||
for _, v := range resp.Logs {
|
||||
s.Logs = append(s.Logs, &client.VertexLog{
|
||||
Vertex: digest.Digest(v.Vertex),
|
||||
Stream: int(v.Stream),
|
||||
Data: v.Msg,
|
||||
Timestamp: v.Timestamp.AsTime(),
|
||||
})
|
||||
}
|
||||
for _, v := range resp.Warnings {
|
||||
s.Warnings = append(s.Warnings, &client.VertexWarning{
|
||||
Vertex: digest.Digest(v.Vertex),
|
||||
Level: int(v.Level),
|
||||
Short: v.Short,
|
||||
Detail: v.Detail,
|
||||
URL: v.Url,
|
||||
SourceInfo: v.Info,
|
||||
Range: v.Ranges,
|
||||
})
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
func timestampFromPB(ts *timestamppb.Timestamp) *time.Time {
|
||||
if ts == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
t := ts.AsTime()
|
||||
if t.IsZero() {
|
||||
return nil
|
||||
}
|
||||
return &t
|
||||
}
|
||||
|
||||
func timestampToPB(ts *time.Time) *timestamppb.Timestamp {
|
||||
if ts == nil {
|
||||
return nil
|
||||
}
|
||||
return timestamppb.New(*ts)
|
||||
}
|
||||
|
||||
func digestSliceFromPB(elems []string) []digest.Digest {
|
||||
clone := make([]digest.Digest, len(elems))
|
||||
for i, e := range elems {
|
||||
clone[i] = digest.Digest(e)
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
func digestSliceToPB(elems []digest.Digest) []string {
|
||||
clone := make([]string, len(elems))
|
||||
for i, e := range elems {
|
||||
clone[i] = string(e)
|
||||
}
|
||||
return clone
|
||||
}
|
@@ -5,6 +5,12 @@ import (
|
||||
"github.com/moby/buildkit/session/secrets/secretsprovider"
|
||||
)
|
||||
|
||||
type Secret struct {
|
||||
ID string
|
||||
FilePath string
|
||||
Env string
|
||||
}
|
||||
|
||||
func CreateSecrets(secrets []*Secret) (session.Attachable, error) {
|
||||
fs := make([]secretsprovider.Source, 0, len(secrets))
|
||||
for _, secret := range secrets {
|
||||
|
@@ -7,6 +7,11 @@ import (
|
||||
"github.com/moby/buildkit/session/sshforward/sshprovider"
|
||||
)
|
||||
|
||||
type SSH struct {
|
||||
ID string
|
||||
Paths []string
|
||||
}
|
||||
|
||||
func CreateSSH(ssh []*SSH) (session.Attachable, error) {
|
||||
configs := make([]sshprovider.AgentConfig, 0, len(ssh))
|
||||
for _, ssh := range ssh {
|
||||
|
11
controller/pb/ulimit.go
Normal file
11
controller/pb/ulimit.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package pb
|
||||
|
||||
type UlimitOpt struct {
|
||||
Values map[string]*Ulimit
|
||||
}
|
||||
|
||||
type Ulimit struct {
|
||||
Name string
|
||||
Hard int64
|
||||
Soft int64
|
||||
}
|
@@ -73,9 +73,9 @@ func (m *Manager) CancelRunningProcesses() {
|
||||
}
|
||||
|
||||
// ListProcesses lists all running processes.
|
||||
func (m *Manager) ListProcesses() (res []*pb.ProcessInfo) {
|
||||
func (m *Manager) ListProcesses() (res []*ProcessInfo) {
|
||||
m.processes.Range(func(key, value any) bool {
|
||||
res = append(res, &pb.ProcessInfo{
|
||||
res = append(res, &ProcessInfo{
|
||||
ProcessID: key.(string),
|
||||
InvokeConfig: value.(*Process).invokeConfig,
|
||||
})
|
||||
@@ -154,3 +154,8 @@ func (m *Manager) StartProcess(pid string, resultCtx *build.ResultHandle, cfg *p
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
type ProcessInfo struct {
|
||||
ProcessID string
|
||||
InvokeConfig *pb.InvokeConfig
|
||||
}
|
||||
|
@@ -1,243 +0,0 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/v2/defaults"
|
||||
"github.com/containerd/containerd/v2/pkg/dialer"
|
||||
"github.com/docker/buildx/build"
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/identity"
|
||||
"github.com/moby/buildkit/util/grpcerrors"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
func NewClient(ctx context.Context, addr string) (*Client, error) {
|
||||
backoffConfig := backoff.DefaultConfig
|
||||
backoffConfig.MaxDelay = 3 * time.Second
|
||||
connParams := grpc.ConnectParams{
|
||||
Backoff: backoffConfig,
|
||||
}
|
||||
gopts := []grpc.DialOption{
|
||||
//nolint:staticcheck // ignore SA1019: WithBlock is deprecated and does not work with NewClient.
|
||||
grpc.WithBlock(),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithConnectParams(connParams),
|
||||
grpc.WithContextDialer(dialer.ContextDialer),
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
|
||||
grpc.WithUnaryInterceptor(grpcerrors.UnaryClientInterceptor),
|
||||
grpc.WithStreamInterceptor(grpcerrors.StreamClientInterceptor),
|
||||
}
|
||||
//nolint:staticcheck // ignore SA1019: Recommended NewClient has different behavior from DialContext.
|
||||
conn, err := grpc.DialContext(ctx, dialer.DialAddress(addr), gopts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Client{conn: conn}, nil
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
conn *grpc.ClientConn
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func (c *Client) Close() (err error) {
|
||||
c.closeOnce.Do(func() {
|
||||
err = c.conn.Close()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) Version(ctx context.Context) (string, string, string, error) {
|
||||
res, err := c.client().Info(ctx, &pb.InfoRequest{})
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
v := res.BuildxVersion
|
||||
return v.Package, v.Version, v.Revision, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context) (keys []string, retErr error) {
|
||||
res, err := c.client().List(ctx, &pb.ListRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Keys, nil
|
||||
}
|
||||
|
||||
func (c *Client) Disconnect(ctx context.Context, sessionID string) error {
|
||||
if sessionID == "" {
|
||||
return nil
|
||||
}
|
||||
_, err := c.client().Disconnect(ctx, &pb.DisconnectRequest{SessionID: sessionID})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) ListProcesses(ctx context.Context, sessionID string) (infos []*pb.ProcessInfo, retErr error) {
|
||||
res, err := c.client().ListProcesses(ctx, &pb.ListProcessesRequest{SessionID: sessionID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Infos, nil
|
||||
}
|
||||
|
||||
func (c *Client) DisconnectProcess(ctx context.Context, sessionID, pid string) error {
|
||||
_, err := c.client().DisconnectProcess(ctx, &pb.DisconnectProcessRequest{SessionID: sessionID, ProcessID: pid})
|
||||
return err
|
||||
}
|
||||
|
||||
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 sessionID == "" || pid == "" {
|
||||
return errors.New("build session ID must be specified")
|
||||
}
|
||||
stream, err := c.client().Invoke(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return attachIO(ctx, stream, &pb.InitMessage{SessionID: sessionID, ProcessID: pid, InvokeConfig: invokeConfig}, ioAttachConfig{
|
||||
stdin: in,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
// TODO: Signal, Resize
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Client) Inspect(ctx context.Context, sessionID string) (*pb.InspectResponse, error) {
|
||||
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) {
|
||||
ref := identity.NewID()
|
||||
statusChan := make(chan *client.SolveStatus)
|
||||
eg, egCtx := errgroup.WithContext(ctx)
|
||||
var resp *client.SolveResponse
|
||||
eg.Go(func() error {
|
||||
defer close(statusChan)
|
||||
var err error
|
||||
resp, err = c.build(egCtx, ref, options, in, statusChan)
|
||||
return err
|
||||
})
|
||||
eg.Go(func() error {
|
||||
for s := range statusChan {
|
||||
st := s
|
||||
progress.Write(st)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return ref, resp, nil, eg.Wait()
|
||||
}
|
||||
|
||||
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)
|
||||
done := make(chan struct{})
|
||||
|
||||
var resp *client.SolveResponse
|
||||
|
||||
eg.Go(func() error {
|
||||
defer close(done)
|
||||
pbResp, err := c.client().Build(egCtx, &pb.BuildRequest{
|
||||
SessionID: sessionID,
|
||||
Options: options,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = &client.SolveResponse{
|
||||
ExporterResponse: pbResp.ExporterResponse,
|
||||
}
|
||||
return nil
|
||||
})
|
||||
eg.Go(func() error {
|
||||
stream, err := c.client().Status(egCtx, &pb.StatusRequest{
|
||||
SessionID: sessionID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
resp, err := stream.Recv()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "failed to receive status")
|
||||
}
|
||||
statusChan <- pb.FromControlStatus(resp)
|
||||
}
|
||||
})
|
||||
if in != nil {
|
||||
eg.Go(func() error {
|
||||
stream, err := c.client().Input(egCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := stream.Send(&pb.InputMessage{
|
||||
Input: &pb.InputMessage_Init{
|
||||
Init: &pb.InputInitMessage{
|
||||
SessionID: sessionID,
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to init input")
|
||||
}
|
||||
|
||||
inReader, inWriter := io.Pipe()
|
||||
eg2, _ := errgroup.WithContext(ctx)
|
||||
eg2.Go(func() error {
|
||||
<-done
|
||||
return inWriter.Close()
|
||||
})
|
||||
go func() {
|
||||
// do not wait for read completion but return here and let the caller send EOF
|
||||
// this allows us to return on ctx.Done() without being blocked by this reader.
|
||||
io.Copy(inWriter, in)
|
||||
inWriter.Close()
|
||||
}()
|
||||
eg2.Go(func() error {
|
||||
for {
|
||||
buf := make([]byte, 32*1024)
|
||||
n, err := inReader.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break // break loop and send EOF
|
||||
}
|
||||
return err
|
||||
} else if n > 0 {
|
||||
if err := stream.Send(&pb.InputMessage{
|
||||
Input: &pb.InputMessage_Data{
|
||||
Data: &pb.DataMessage{
|
||||
Data: buf[:n],
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return stream.Send(&pb.InputMessage{
|
||||
Input: &pb.InputMessage_Data{
|
||||
Data: &pb.DataMessage{
|
||||
EOF: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
return eg2.Wait()
|
||||
})
|
||||
}
|
||||
return resp, eg.Wait()
|
||||
}
|
||||
|
||||
func (c *Client) client() pb.ControllerClient {
|
||||
return pb.NewControllerClient(c.conn)
|
||||
}
|
@@ -1,335 +0,0 @@
|
||||
//go:build linux
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/buildx/build"
|
||||
cbuild "github.com/docker/buildx/controller/build"
|
||||
"github.com/docker/buildx/controller/control"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/util/confutil"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/buildx/version"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/util/grpcerrors"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
const (
|
||||
serveCommandName = "_INTERNAL_SERVE"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultLogFilename = fmt.Sprintf("buildx.%s.log", version.Revision)
|
||||
defaultSocketFilename = fmt.Sprintf("buildx.%s.sock", version.Revision)
|
||||
defaultPIDFilename = fmt.Sprintf("buildx.%s.pid", version.Revision)
|
||||
)
|
||||
|
||||
type serverConfig struct {
|
||||
// Specify buildx server root
|
||||
Root string `toml:"root"`
|
||||
|
||||
// LogLevel sets the logging level [trace, debug, info, warn, error, fatal, panic]
|
||||
LogLevel string `toml:"log_level"`
|
||||
|
||||
// Specify file to output buildx server log
|
||||
LogFile string `toml:"log_file"`
|
||||
}
|
||||
|
||||
func NewRemoteBuildxController(ctx context.Context, dockerCli command.Cli, opts control.ControlOptions, logger progress.SubLogger) (control.BuildxController, error) {
|
||||
rootDir := opts.Root
|
||||
if rootDir == "" {
|
||||
rootDir = rootDataDir(dockerCli)
|
||||
}
|
||||
serverRoot := filepath.Join(rootDir, "shared")
|
||||
|
||||
// connect to buildx server if it is already running
|
||||
ctx2, cancel := context.WithCancelCause(ctx)
|
||||
ctx2, _ = context.WithTimeoutCause(ctx2, 1*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
|
||||
c, err := newBuildxClientAndCheck(ctx2, filepath.Join(serverRoot, defaultSocketFilename))
|
||||
cancel(errors.WithStack(context.Canceled))
|
||||
if err != nil {
|
||||
if !errors.Is(err, context.DeadlineExceeded) {
|
||||
return nil, errors.Wrap(err, "cannot connect to the buildx server")
|
||||
}
|
||||
} else {
|
||||
return &buildxController{c, serverRoot}, nil
|
||||
}
|
||||
|
||||
// start buildx server via subcommand
|
||||
err = logger.Wrap("no buildx server found; launching...", func() error {
|
||||
launchFlags := []string{}
|
||||
if opts.ServerConfig != "" {
|
||||
launchFlags = append(launchFlags, "--config", opts.ServerConfig)
|
||||
}
|
||||
logFile, err := getLogFilePath(dockerCli, opts.ServerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wait, err := launch(ctx, logFile, append([]string{serveCommandName}, launchFlags...)...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go wait()
|
||||
|
||||
// wait for buildx server to be ready
|
||||
ctx2, cancel = context.WithCancelCause(ctx)
|
||||
ctx2, _ = context.WithTimeoutCause(ctx2, 10*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet,lostcancel // no need to manually cancel this context as we already rely on parent
|
||||
c, err = newBuildxClientAndCheck(ctx2, filepath.Join(serverRoot, defaultSocketFilename))
|
||||
cancel(errors.WithStack(context.Canceled))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot connect to the buildx server")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &buildxController{c, serverRoot}, nil
|
||||
}
|
||||
|
||||
func AddControllerCommands(cmd *cobra.Command, dockerCli command.Cli) {
|
||||
cmd.AddCommand(
|
||||
serveCmd(dockerCli),
|
||||
)
|
||||
}
|
||||
|
||||
func serveCmd(dockerCli command.Cli) *cobra.Command {
|
||||
var serverConfigPath string
|
||||
cmd := &cobra.Command{
|
||||
Use: fmt.Sprintf("%s [OPTIONS]", serveCommandName),
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// Parse config
|
||||
config, err := getConfig(dockerCli, serverConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config.LogLevel == "" {
|
||||
logrus.SetLevel(logrus.InfoLevel)
|
||||
} else {
|
||||
lvl, err := logrus.ParseLevel(config.LogLevel)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to prepare logger")
|
||||
}
|
||||
logrus.SetLevel(lvl)
|
||||
}
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{
|
||||
TimestampFormat: log.RFC3339NanoFixed,
|
||||
})
|
||||
root, err := prepareRootDir(dockerCli, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pidF := filepath.Join(root, defaultPIDFilename)
|
||||
if err := os.WriteFile(pidF, fmt.Appendf(nil, "%d", os.Getpid()), 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Remove(pidF); err != nil {
|
||||
logrus.Errorf("failed to clean up info file %q: %v", pidF, err)
|
||||
}
|
||||
}()
|
||||
|
||||
// prepare server
|
||||
b := NewServer(func(ctx context.Context, options *controllerapi.BuildOptions, stdin io.Reader, progress progress.Writer) (*client.SolveResponse, *build.ResultHandle, *build.Inputs, error) {
|
||||
return cbuild.RunBuild(ctx, dockerCli, options, stdin, progress, true)
|
||||
})
|
||||
defer b.Close()
|
||||
|
||||
// serve server
|
||||
addr := filepath.Join(root, defaultSocketFilename)
|
||||
if err := os.Remove(addr); err != nil && !os.IsNotExist(err) { // avoid EADDRINUSE
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := os.Remove(addr); err != nil {
|
||||
logrus.Errorf("failed to clean up socket %q: %v", addr, err)
|
||||
}
|
||||
}()
|
||||
logrus.Infof("starting server at %q", addr)
|
||||
l, err := net.Listen("unix", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rpc := grpc.NewServer(
|
||||
grpc.UnaryInterceptor(grpcerrors.UnaryServerInterceptor),
|
||||
grpc.StreamInterceptor(grpcerrors.StreamServerInterceptor),
|
||||
)
|
||||
controllerapi.RegisterControllerServer(rpc, b)
|
||||
doneCh := make(chan struct{})
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
defer close(doneCh)
|
||||
if err := rpc.Serve(l); err != nil {
|
||||
errCh <- errors.Wrapf(err, "error on serving via socket %q", addr)
|
||||
}
|
||||
}()
|
||||
|
||||
var s os.Signal
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT)
|
||||
signal.Notify(sigCh, syscall.SIGTERM)
|
||||
select {
|
||||
case err := <-errCh:
|
||||
logrus.Errorf("got error %s, exiting", err)
|
||||
return err
|
||||
case s = <-sigCh:
|
||||
logrus.Infof("got signal %s, exiting", s)
|
||||
return nil
|
||||
case <-doneCh:
|
||||
logrus.Infof("rpc server done, exiting")
|
||||
return nil
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.StringVar(&serverConfigPath, "config", "", "Specify buildx server config file")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getLogFilePath(dockerCli command.Cli, configPath string) (string, error) {
|
||||
config, err := getConfig(dockerCli, configPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if config.LogFile == "" {
|
||||
root, err := prepareRootDir(dockerCli, config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(root, defaultLogFilename), nil
|
||||
}
|
||||
return config.LogFile, nil
|
||||
}
|
||||
|
||||
func getConfig(dockerCli command.Cli, configPath string) (*serverConfig, error) {
|
||||
var defaultConfigPath bool
|
||||
if configPath == "" {
|
||||
defaultRoot := rootDataDir(dockerCli)
|
||||
configPath = filepath.Join(defaultRoot, "config.toml")
|
||||
defaultConfigPath = true
|
||||
}
|
||||
var config serverConfig
|
||||
tree, err := toml.LoadFile(configPath)
|
||||
if err != nil && !(os.IsNotExist(err) && defaultConfigPath) {
|
||||
return nil, errors.Wrapf(err, "failed to read config %q", configPath)
|
||||
} else if err == nil {
|
||||
if err := tree.Unmarshal(&config); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal config %q", configPath)
|
||||
}
|
||||
}
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func prepareRootDir(dockerCli command.Cli, config *serverConfig) (string, error) {
|
||||
rootDir := config.Root
|
||||
if rootDir == "" {
|
||||
rootDir = rootDataDir(dockerCli)
|
||||
}
|
||||
if rootDir == "" {
|
||||
return "", errors.New("buildx root dir must be determined")
|
||||
}
|
||||
if err := os.MkdirAll(rootDir, 0700); err != nil {
|
||||
return "", err
|
||||
}
|
||||
serverRoot := filepath.Join(rootDir, "shared")
|
||||
if err := os.MkdirAll(serverRoot, 0700); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return serverRoot, nil
|
||||
}
|
||||
|
||||
func rootDataDir(dockerCli command.Cli) string {
|
||||
return filepath.Join(confutil.NewConfig(dockerCli).Dir(), "controller")
|
||||
}
|
||||
|
||||
func newBuildxClientAndCheck(ctx context.Context, addr string) (*Client, error) {
|
||||
c, err := NewClient(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, v, r, err := c.Version(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logrus.Debugf("connected to server (\"%v %v %v\")", p, v, r)
|
||||
if !(p == version.Package && v == version.Version && r == version.Revision) {
|
||||
return nil, errors.Errorf("version mismatch (client: \"%v %v %v\", server: \"%v %v %v\")", version.Package, version.Version, version.Revision, p, v, r)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
type buildxController struct {
|
||||
*Client
|
||||
serverRoot string
|
||||
}
|
||||
|
||||
func (c *buildxController) Kill(ctx context.Context) error {
|
||||
pidB, err := os.ReadFile(filepath.Join(c.serverRoot, defaultPIDFilename))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pid, err := strconv.ParseInt(string(pidB), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pid <= 0 {
|
||||
return errors.New("no PID is recorded for buildx server")
|
||||
}
|
||||
p, err := os.FindProcess(int(pid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Signal(syscall.SIGINT); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Should we send SIGKILL if process doesn't finish?
|
||||
return nil
|
||||
}
|
||||
|
||||
func launch(ctx context.Context, logFile string, args ...string) (func() error, error) {
|
||||
// set absolute path of binary, since we set the working directory to the root
|
||||
pathname, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bCmd := exec.CommandContext(ctx, pathname, args...)
|
||||
if logFile != "" {
|
||||
f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
bCmd.Stdout = f
|
||||
bCmd.Stderr = f
|
||||
}
|
||||
bCmd.Stdin = nil
|
||||
bCmd.Dir = "/"
|
||||
bCmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setsid: true,
|
||||
}
|
||||
if err := bCmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bCmd.Wait, nil
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
//go:build !linux
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/buildx/controller/control"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewRemoteBuildxController(ctx context.Context, dockerCli command.Cli, opts control.ControlOptions, logger progress.SubLogger) (control.BuildxController, error) {
|
||||
return nil, errors.New("remote buildx unsupported")
|
||||
}
|
||||
|
||||
func AddControllerCommands(cmd *cobra.Command, dockerCli command.Cli) {}
|
@@ -1,430 +0,0 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
"github.com/moby/sys/signal"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type msgStream interface {
|
||||
Send(*pb.Message) error
|
||||
Recv() (*pb.Message, error)
|
||||
}
|
||||
|
||||
type ioServerConfig struct {
|
||||
stdin io.WriteCloser
|
||||
stdout, stderr io.ReadCloser
|
||||
|
||||
// signalFn is a callback function called when a signal is reached to the client.
|
||||
signalFn func(context.Context, syscall.Signal) error
|
||||
|
||||
// resizeFn is a callback function called when a resize event is reached to the client.
|
||||
resizeFn func(context.Context, winSize) error
|
||||
}
|
||||
|
||||
func serveIO(attachCtx context.Context, srv msgStream, initFn func(*pb.InitMessage) error, ioConfig *ioServerConfig) (err error) {
|
||||
stdin, stdout, stderr := ioConfig.stdin, ioConfig.stdout, ioConfig.stderr
|
||||
stream := &debugStream{srv, "server=" + time.Now().String()}
|
||||
eg, ctx := errgroup.WithContext(attachCtx)
|
||||
done := make(chan struct{})
|
||||
|
||||
msg, err := receive(ctx, stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
init := msg.GetInit()
|
||||
if init == nil {
|
||||
return errors.Errorf("unexpected message: %T; wanted init", msg.GetInput())
|
||||
}
|
||||
sessionID := init.SessionID
|
||||
if sessionID == "" {
|
||||
return errors.New("no session ID is provided")
|
||||
}
|
||||
if err := initFn(init); err != nil {
|
||||
return errors.Wrap(err, "failed to initialize IO server")
|
||||
}
|
||||
|
||||
if stdout != nil {
|
||||
stdoutReader, stdoutWriter := io.Pipe()
|
||||
eg.Go(func() error {
|
||||
<-done
|
||||
return stdoutWriter.Close()
|
||||
})
|
||||
|
||||
go func() {
|
||||
// do not wait for read completion but return here and let the caller send EOF
|
||||
// this allows us to return on ctx.Done() without being blocked by this reader.
|
||||
io.Copy(stdoutWriter, stdout)
|
||||
stdoutWriter.Close()
|
||||
}()
|
||||
|
||||
eg.Go(func() error {
|
||||
defer stdoutReader.Close()
|
||||
return copyToStream(1, stream, stdoutReader)
|
||||
})
|
||||
}
|
||||
|
||||
if stderr != nil {
|
||||
stderrReader, stderrWriter := io.Pipe()
|
||||
eg.Go(func() error {
|
||||
<-done
|
||||
return stderrWriter.Close()
|
||||
})
|
||||
|
||||
go func() {
|
||||
// do not wait for read completion but return here and let the caller send EOF
|
||||
// this allows us to return on ctx.Done() without being blocked by this reader.
|
||||
io.Copy(stderrWriter, stderr)
|
||||
stderrWriter.Close()
|
||||
}()
|
||||
|
||||
eg.Go(func() error {
|
||||
defer stderrReader.Close()
|
||||
return copyToStream(2, stream, stderrReader)
|
||||
})
|
||||
}
|
||||
|
||||
msgCh := make(chan *pb.Message)
|
||||
eg.Go(func() error {
|
||||
defer close(msgCh)
|
||||
for {
|
||||
msg, err := receive(ctx, stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case msgCh <- msg:
|
||||
case <-done:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
defer close(done)
|
||||
for {
|
||||
var msg *pb.Message
|
||||
select {
|
||||
case msg = <-msgCh:
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
if file := msg.GetFile(); file != nil {
|
||||
if file.Fd != 0 {
|
||||
return errors.Errorf("unexpected fd: %v", file.Fd)
|
||||
}
|
||||
if stdin == nil {
|
||||
continue // no stdin destination is specified so ignore the data
|
||||
}
|
||||
if len(file.Data) > 0 {
|
||||
_, err := stdin.Write(file.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if file.EOF {
|
||||
stdin.Close()
|
||||
}
|
||||
} else if resize := msg.GetResize(); resize != nil {
|
||||
if ioConfig.resizeFn != nil {
|
||||
ioConfig.resizeFn(ctx, winSize{
|
||||
cols: resize.Cols,
|
||||
rows: resize.Rows,
|
||||
})
|
||||
}
|
||||
} else if sig := msg.GetSignal(); sig != nil {
|
||||
if ioConfig.signalFn != nil {
|
||||
syscallSignal, ok := signal.SignalMap[sig.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
ioConfig.signalFn(ctx, syscallSignal)
|
||||
}
|
||||
} else {
|
||||
return errors.Errorf("unexpected message: %T", msg.GetInput())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
type ioAttachConfig struct {
|
||||
stdin io.ReadCloser
|
||||
stdout, stderr io.WriteCloser
|
||||
signal <-chan syscall.Signal
|
||||
resize <-chan winSize
|
||||
}
|
||||
|
||||
type winSize struct {
|
||||
rows uint32
|
||||
cols uint32
|
||||
}
|
||||
|
||||
func attachIO(ctx context.Context, stream msgStream, initMessage *pb.InitMessage, cfg ioAttachConfig) (retErr error) {
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
done := make(chan struct{})
|
||||
|
||||
if err := stream.Send(&pb.Message{
|
||||
Input: &pb.Message_Init{
|
||||
Init: initMessage,
|
||||
},
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to init")
|
||||
}
|
||||
|
||||
if cfg.stdin != nil {
|
||||
stdinReader, stdinWriter := io.Pipe()
|
||||
eg.Go(func() error {
|
||||
<-done
|
||||
return stdinWriter.Close()
|
||||
})
|
||||
|
||||
go func() {
|
||||
// do not wait for read completion but return here and let the caller send EOF
|
||||
// this allows us to return on ctx.Done() without being blocked by this reader.
|
||||
io.Copy(stdinWriter, cfg.stdin)
|
||||
stdinWriter.Close()
|
||||
}()
|
||||
|
||||
eg.Go(func() error {
|
||||
defer stdinReader.Close()
|
||||
return copyToStream(0, stream, stdinReader)
|
||||
})
|
||||
}
|
||||
|
||||
if cfg.signal != nil {
|
||||
eg.Go(func() error {
|
||||
names := signalNames()
|
||||
for {
|
||||
var sig syscall.Signal
|
||||
select {
|
||||
case sig = <-cfg.signal:
|
||||
case <-done:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
name := names[sig]
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
if err := stream.Send(&pb.Message{
|
||||
Input: &pb.Message_Signal{
|
||||
Signal: &pb.SignalMessage{
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to send signal")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if cfg.resize != nil {
|
||||
eg.Go(func() error {
|
||||
for {
|
||||
var win winSize
|
||||
select {
|
||||
case win = <-cfg.resize:
|
||||
case <-done:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
if err := stream.Send(&pb.Message{
|
||||
Input: &pb.Message_Resize{
|
||||
Resize: &pb.ResizeMessage{
|
||||
Rows: win.rows,
|
||||
Cols: win.cols,
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to send resize")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
msgCh := make(chan *pb.Message)
|
||||
eg.Go(func() error {
|
||||
defer close(msgCh)
|
||||
for {
|
||||
msg, err := receive(ctx, stream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case msgCh <- msg:
|
||||
case <-done:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
eofs := make(map[uint32]struct{})
|
||||
defer close(done)
|
||||
for {
|
||||
var msg *pb.Message
|
||||
select {
|
||||
case msg = <-msgCh:
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
if file := msg.GetFile(); file != nil {
|
||||
if _, ok := eofs[file.Fd]; ok {
|
||||
continue
|
||||
}
|
||||
var out io.WriteCloser
|
||||
switch file.Fd {
|
||||
case 1:
|
||||
out = cfg.stdout
|
||||
case 2:
|
||||
out = cfg.stderr
|
||||
default:
|
||||
return errors.Errorf("unsupported fd %d", file.Fd)
|
||||
}
|
||||
if out == nil {
|
||||
logrus.Warnf("attachIO: no writer for fd %d", file.Fd)
|
||||
continue
|
||||
}
|
||||
if len(file.Data) > 0 {
|
||||
if _, err := out.Write(file.Data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if file.EOF {
|
||||
eofs[file.Fd] = struct{}{}
|
||||
}
|
||||
} else {
|
||||
return errors.Errorf("unexpected message: %T", msg.GetInput())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func receive(ctx context.Context, stream msgStream) (*pb.Message, error) {
|
||||
msgCh := make(chan *pb.Message)
|
||||
errCh := make(chan error)
|
||||
go func() {
|
||||
msg, err := stream.Recv()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return
|
||||
}
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
msgCh <- msg
|
||||
}()
|
||||
select {
|
||||
case msg := <-msgCh:
|
||||
return msg, nil
|
||||
case err := <-errCh:
|
||||
return nil, err
|
||||
case <-ctx.Done():
|
||||
return nil, context.Cause(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func copyToStream(fd uint32, snd msgStream, r io.Reader) error {
|
||||
for {
|
||||
buf := make([]byte, 32*1024)
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break // break loop and send EOF
|
||||
}
|
||||
return err
|
||||
} else if n > 0 {
|
||||
if err := snd.Send(&pb.Message{
|
||||
Input: &pb.Message_File{
|
||||
File: &pb.FdMessage{
|
||||
Fd: fd,
|
||||
Data: buf[:n],
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return snd.Send(&pb.Message{
|
||||
Input: &pb.Message_File{
|
||||
File: &pb.FdMessage{
|
||||
Fd: fd,
|
||||
EOF: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func signalNames() map[syscall.Signal]string {
|
||||
m := make(map[syscall.Signal]string, len(signal.SignalMap))
|
||||
for name, value := range signal.SignalMap {
|
||||
m[value] = name
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
type debugStream struct {
|
||||
msgStream
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (s *debugStream) Send(msg *pb.Message) error {
|
||||
switch m := msg.GetInput().(type) {
|
||||
case *pb.Message_File:
|
||||
if m.File.EOF {
|
||||
logrus.Debugf("|---> File Message (sender:%v) fd=%d, EOF", s.prefix, m.File.Fd)
|
||||
} else {
|
||||
logrus.Debugf("|---> File Message (sender:%v) fd=%d, %d bytes", s.prefix, m.File.Fd, len(m.File.Data))
|
||||
}
|
||||
case *pb.Message_Resize:
|
||||
logrus.Debugf("|---> Resize Message (sender:%v): %+v", s.prefix, m.Resize)
|
||||
case *pb.Message_Signal:
|
||||
logrus.Debugf("|---> Signal Message (sender:%v): %s", s.prefix, m.Signal.Name)
|
||||
}
|
||||
return s.msgStream.Send(msg)
|
||||
}
|
||||
|
||||
func (s *debugStream) Recv() (*pb.Message, error) {
|
||||
msg, err := s.msgStream.Recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch m := msg.GetInput().(type) {
|
||||
case *pb.Message_File:
|
||||
if m.File.EOF {
|
||||
logrus.Debugf("|<--- File Message (receiver:%v) fd=%d, EOF", s.prefix, m.File.Fd)
|
||||
} else {
|
||||
logrus.Debugf("|<--- File Message (receiver:%v) fd=%d, %d bytes", s.prefix, m.File.Fd, len(m.File.Data))
|
||||
}
|
||||
case *pb.Message_Resize:
|
||||
logrus.Debugf("|<--- Resize Message (receiver:%v): %+v", s.prefix, m.Resize)
|
||||
case *pb.Message_Signal:
|
||||
logrus.Debugf("|<--- Signal Message (receiver:%v): %s", s.prefix, m.Signal.Name)
|
||||
}
|
||||
return msg, nil
|
||||
}
|
@@ -1,445 +0,0 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/docker/buildx/build"
|
||||
controllererrors "github.com/docker/buildx/controller/errdefs"
|
||||
"github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/controller/processes"
|
||||
"github.com/docker/buildx/util/desktop"
|
||||
"github.com/docker/buildx/util/ioset"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/buildx/version"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type BuildFunc func(ctx context.Context, options *pb.BuildOptions, stdin io.Reader, progress progress.Writer) (resp *client.SolveResponse, res *build.ResultHandle, inp *build.Inputs, err error)
|
||||
|
||||
func NewServer(buildFunc BuildFunc) *Server {
|
||||
return &Server{
|
||||
buildFunc: buildFunc,
|
||||
}
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
buildFunc BuildFunc
|
||||
session map[string]*session
|
||||
sessionMu sync.Mutex
|
||||
}
|
||||
|
||||
type session struct {
|
||||
buildOnGoing atomic.Bool
|
||||
statusChan chan *pb.StatusResponse
|
||||
cancelBuild func(error)
|
||||
buildOptions *pb.BuildOptions
|
||||
inputPipe *io.PipeWriter
|
||||
|
||||
result *build.ResultHandle
|
||||
|
||||
processes *processes.Manager
|
||||
}
|
||||
|
||||
func (s *session) cancelRunningProcesses() {
|
||||
s.processes.CancelRunningProcesses()
|
||||
}
|
||||
|
||||
func (m *Server) ListProcesses(ctx context.Context, req *pb.ListProcessesRequest) (res *pb.ListProcessesResponse, err error) {
|
||||
m.sessionMu.Lock()
|
||||
defer m.sessionMu.Unlock()
|
||||
s, ok := m.session[req.SessionID]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unknown session ID %q", req.SessionID)
|
||||
}
|
||||
res = new(pb.ListProcessesResponse)
|
||||
res.Infos = append(res.Infos, s.processes.ListProcesses()...)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (m *Server) DisconnectProcess(ctx context.Context, req *pb.DisconnectProcessRequest) (res *pb.DisconnectProcessResponse, err error) {
|
||||
m.sessionMu.Lock()
|
||||
defer m.sessionMu.Unlock()
|
||||
s, ok := m.session[req.SessionID]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unknown session ID %q", req.SessionID)
|
||||
}
|
||||
return res, s.processes.DeleteProcess(req.ProcessID)
|
||||
}
|
||||
|
||||
func (m *Server) Info(ctx context.Context, req *pb.InfoRequest) (res *pb.InfoResponse, err error) {
|
||||
return &pb.InfoResponse{
|
||||
BuildxVersion: &pb.BuildxVersion{
|
||||
Package: version.Package,
|
||||
Version: version.Version,
|
||||
Revision: version.Revision,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Server) List(ctx context.Context, req *pb.ListRequest) (res *pb.ListResponse, err error) {
|
||||
keys := make(map[string]struct{})
|
||||
|
||||
m.sessionMu.Lock()
|
||||
for k := range m.session {
|
||||
keys[k] = struct{}{}
|
||||
}
|
||||
m.sessionMu.Unlock()
|
||||
|
||||
var keysL []string
|
||||
for k := range keys {
|
||||
keysL = append(keysL, k)
|
||||
}
|
||||
return &pb.ListResponse{
|
||||
Keys: keysL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Server) Disconnect(ctx context.Context, req *pb.DisconnectRequest) (res *pb.DisconnectResponse, err error) {
|
||||
sessionID := req.SessionID
|
||||
if sessionID == "" {
|
||||
return nil, errors.New("disconnect: empty session ID")
|
||||
}
|
||||
|
||||
m.sessionMu.Lock()
|
||||
if s, ok := m.session[sessionID]; ok {
|
||||
if s.cancelBuild != nil {
|
||||
s.cancelBuild(errors.WithStack(context.Canceled))
|
||||
}
|
||||
s.cancelRunningProcesses()
|
||||
if s.result != nil {
|
||||
s.result.Done()
|
||||
}
|
||||
}
|
||||
delete(m.session, sessionID)
|
||||
m.sessionMu.Unlock()
|
||||
|
||||
return &pb.DisconnectResponse{}, nil
|
||||
}
|
||||
|
||||
func (m *Server) Close() error {
|
||||
m.sessionMu.Lock()
|
||||
for k := range m.session {
|
||||
if s, ok := m.session[k]; ok {
|
||||
if s.cancelBuild != nil {
|
||||
s.cancelBuild(errors.WithStack(context.Canceled))
|
||||
}
|
||||
s.cancelRunningProcesses()
|
||||
}
|
||||
}
|
||||
m.sessionMu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Server) Inspect(ctx context.Context, req *pb.InspectRequest) (*pb.InspectResponse, error) {
|
||||
sessionID := req.SessionID
|
||||
if sessionID == "" {
|
||||
return nil, errors.New("inspect: empty session ID")
|
||||
}
|
||||
var bo *pb.BuildOptions
|
||||
m.sessionMu.Lock()
|
||||
if s, ok := m.session[sessionID]; ok {
|
||||
bo = s.buildOptions
|
||||
} else {
|
||||
m.sessionMu.Unlock()
|
||||
return nil, errors.Errorf("inspect: unknown key %v", sessionID)
|
||||
}
|
||||
m.sessionMu.Unlock()
|
||||
return &pb.InspectResponse{Options: bo}, nil
|
||||
}
|
||||
|
||||
func (m *Server) Build(ctx context.Context, req *pb.BuildRequest) (*pb.BuildResponse, error) {
|
||||
sessionID := req.SessionID
|
||||
if sessionID == "" {
|
||||
return nil, errors.New("build: empty session ID")
|
||||
}
|
||||
|
||||
// Prepare status channel and session
|
||||
m.sessionMu.Lock()
|
||||
if m.session == nil {
|
||||
m.session = make(map[string]*session)
|
||||
}
|
||||
s, ok := m.session[sessionID]
|
||||
if ok {
|
||||
if !s.buildOnGoing.CompareAndSwap(false, true) {
|
||||
m.sessionMu.Unlock()
|
||||
return &pb.BuildResponse{}, errors.New("build ongoing")
|
||||
}
|
||||
s.cancelRunningProcesses()
|
||||
s.result = nil
|
||||
} else {
|
||||
s = &session{}
|
||||
s.buildOnGoing.Store(true)
|
||||
}
|
||||
|
||||
s.processes = processes.NewManager()
|
||||
statusChan := make(chan *pb.StatusResponse)
|
||||
s.statusChan = statusChan
|
||||
inR, inW := io.Pipe()
|
||||
defer inR.Close()
|
||||
s.inputPipe = inW
|
||||
m.session[sessionID] = s
|
||||
m.sessionMu.Unlock()
|
||||
defer func() {
|
||||
close(statusChan)
|
||||
m.sessionMu.Lock()
|
||||
s, ok := m.session[sessionID]
|
||||
if ok {
|
||||
s.statusChan = nil
|
||||
s.buildOnGoing.Store(false)
|
||||
}
|
||||
m.sessionMu.Unlock()
|
||||
}()
|
||||
|
||||
pw := pb.NewProgressWriter(statusChan)
|
||||
|
||||
// Build the specified request
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
defer func() { cancel(errors.WithStack(context.Canceled)) }()
|
||||
resp, res, _, buildErr := m.buildFunc(ctx, req.Options, inR, pw)
|
||||
m.sessionMu.Lock()
|
||||
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).
|
||||
if res != nil {
|
||||
s.result = res
|
||||
s.cancelBuild = cancel
|
||||
s.buildOptions = req.Options
|
||||
m.session[sessionID] = s
|
||||
if buildErr != nil {
|
||||
var ref string
|
||||
var ebr *desktop.ErrorWithBuildRef
|
||||
if errors.As(buildErr, &ebr) {
|
||||
ref = ebr.Ref
|
||||
}
|
||||
buildErr = controllererrors.WrapBuild(buildErr, sessionID, ref)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m.sessionMu.Unlock()
|
||||
return nil, errors.Errorf("build: unknown session ID %v", sessionID)
|
||||
}
|
||||
m.sessionMu.Unlock()
|
||||
|
||||
if buildErr != nil {
|
||||
return nil, buildErr
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
resp = &client.SolveResponse{}
|
||||
}
|
||||
return &pb.BuildResponse{
|
||||
ExporterResponse: resp.ExporterResponse,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Server) Status(req *pb.StatusRequest, stream pb.Controller_StatusServer) error {
|
||||
sessionID := req.SessionID
|
||||
if sessionID == "" {
|
||||
return errors.New("status: empty session ID")
|
||||
}
|
||||
|
||||
// Wait and get status channel prepared by Build()
|
||||
var statusChan <-chan *pb.StatusResponse
|
||||
for {
|
||||
// TODO: timeout?
|
||||
m.sessionMu.Lock()
|
||||
if _, ok := m.session[sessionID]; !ok || m.session[sessionID].statusChan == nil {
|
||||
m.sessionMu.Unlock()
|
||||
time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable
|
||||
continue
|
||||
}
|
||||
statusChan = m.session[sessionID].statusChan
|
||||
m.sessionMu.Unlock()
|
||||
break
|
||||
}
|
||||
|
||||
// forward status
|
||||
for ss := range statusChan {
|
||||
if ss == nil {
|
||||
break
|
||||
}
|
||||
if err := stream.Send(ss); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Server) Input(stream pb.Controller_InputServer) (err error) {
|
||||
// Get the target ref from init message
|
||||
msg, err := stream.Recv()
|
||||
if err != nil {
|
||||
if !errors.Is(err, io.EOF) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
init := msg.GetInit()
|
||||
if init == nil {
|
||||
return errors.Errorf("unexpected message: %T; wanted init", msg.GetInit())
|
||||
}
|
||||
sessionID := init.SessionID
|
||||
if sessionID == "" {
|
||||
return errors.New("input: no session ID is provided")
|
||||
}
|
||||
|
||||
// Wait and get input stream pipe prepared by Build()
|
||||
var inputPipeW *io.PipeWriter
|
||||
for {
|
||||
// TODO: timeout?
|
||||
m.sessionMu.Lock()
|
||||
if _, ok := m.session[sessionID]; !ok || m.session[sessionID].inputPipe == nil {
|
||||
m.sessionMu.Unlock()
|
||||
time.Sleep(time.Millisecond) // TODO: wait Build without busy loop and make it cancellable
|
||||
continue
|
||||
}
|
||||
inputPipeW = m.session[sessionID].inputPipe
|
||||
m.sessionMu.Unlock()
|
||||
break
|
||||
}
|
||||
|
||||
// Forward input stream
|
||||
eg, ctx := errgroup.WithContext(context.TODO())
|
||||
done := make(chan struct{})
|
||||
msgCh := make(chan *pb.InputMessage)
|
||||
eg.Go(func() error {
|
||||
defer close(msgCh)
|
||||
for {
|
||||
msg, err := stream.Recv()
|
||||
if err != nil {
|
||||
if !errors.Is(err, io.EOF) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case msgCh <- msg:
|
||||
case <-done:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
}
|
||||
})
|
||||
eg.Go(func() (retErr error) {
|
||||
defer close(done)
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
inputPipeW.CloseWithError(retErr)
|
||||
return
|
||||
}
|
||||
inputPipeW.Close()
|
||||
}()
|
||||
for {
|
||||
var msg *pb.InputMessage
|
||||
select {
|
||||
case msg = <-msgCh:
|
||||
case <-ctx.Done():
|
||||
return context.Cause(ctx)
|
||||
}
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
if data := msg.GetData(); data != nil {
|
||||
if len(data.Data) > 0 {
|
||||
_, err := inputPipeW.Write(data.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if data.EOF {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func (m *Server) Invoke(srv pb.Controller_InvokeServer) error {
|
||||
containerIn, containerOut := ioset.Pipe()
|
||||
defer func() { containerOut.Close(); containerIn.Close() }()
|
||||
|
||||
initDoneCh := make(chan *processes.Process)
|
||||
initErrCh := make(chan error)
|
||||
eg, egCtx := errgroup.WithContext(context.TODO())
|
||||
srvIOCtx, srvIOCancel := context.WithCancelCause(egCtx)
|
||||
eg.Go(func() error {
|
||||
defer srvIOCancel(errors.WithStack(context.Canceled))
|
||||
return serveIO(srvIOCtx, srv, func(initMessage *pb.InitMessage) (retErr error) {
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
initErrCh <- retErr
|
||||
}
|
||||
}()
|
||||
sessionID := initMessage.SessionID
|
||||
cfg := initMessage.InvokeConfig
|
||||
|
||||
m.sessionMu.Lock()
|
||||
s, ok := m.session[sessionID]
|
||||
if !ok {
|
||||
m.sessionMu.Unlock()
|
||||
return errors.Errorf("invoke: unknown session ID %v", sessionID)
|
||||
}
|
||||
m.sessionMu.Unlock()
|
||||
|
||||
pid := initMessage.ProcessID
|
||||
if pid == "" {
|
||||
return errors.Errorf("invoke: specify process ID")
|
||||
}
|
||||
proc, ok := s.processes.Get(pid)
|
||||
if !ok {
|
||||
// Start a new process.
|
||||
if cfg == nil {
|
||||
return errors.New("no container config is provided")
|
||||
}
|
||||
var err error
|
||||
proc, err = s.processes.StartProcess(pid, s.result, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Attach containerIn to this process
|
||||
proc.ForwardIO(&containerIn, srvIOCancel)
|
||||
initDoneCh <- proc
|
||||
return nil
|
||||
}, &ioServerConfig{
|
||||
stdin: containerOut.Stdin,
|
||||
stdout: containerOut.Stdout,
|
||||
stderr: containerOut.Stderr,
|
||||
// TODO: signal, resize
|
||||
})
|
||||
})
|
||||
eg.Go(func() (rErr error) {
|
||||
defer srvIOCancel(errors.WithStack(context.Canceled))
|
||||
// Wait for init done
|
||||
var proc *processes.Process
|
||||
select {
|
||||
case p := <-initDoneCh:
|
||||
proc = p
|
||||
case err := <-initErrCh:
|
||||
return err
|
||||
case <-egCtx.Done():
|
||||
return egCtx.Err()
|
||||
}
|
||||
|
||||
// Wait for IO done
|
||||
select {
|
||||
case <-srvIOCtx.Done():
|
||||
return srvIOCtx.Err()
|
||||
case err := <-proc.Done():
|
||||
return err
|
||||
case <-egCtx.Done():
|
||||
return egCtx.Err()
|
||||
}
|
||||
})
|
||||
|
||||
return eg.Wait()
|
||||
}
|
@@ -28,7 +28,6 @@ Start a build
|
||||
| [`--cgroup-parent`](#cgroup-parent) | `string` | | Set the parent cgroup for the `RUN` instructions during build |
|
||||
| [`--check`](#check) | `bool` | | Shorthand for `--call=check` |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--detach` | `bool` | | Detach buildx server (supported only on linux) (EXPERIMENTAL) |
|
||||
| [`-f`](#file), [`--file`](#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) |
|
||||
| `--iidfile` | `string` | | Write the image ID to a file |
|
||||
| `--label` | `stringArray` | | Set metadata for an image |
|
||||
@@ -44,10 +43,8 @@ Start a build
|
||||
| `--pull` | `bool` | | Always attempt to pull all referenced images |
|
||||
| [`--push`](#push) | `bool` | | Shorthand for `--output=type=registry` |
|
||||
| `-q`, `--quiet` | `bool` | | Suppress the build output and print image ID on success |
|
||||
| `--root` | `string` | | Specify root directory of server to connect (EXPERIMENTAL) |
|
||||
| [`--sbom`](#sbom) | `string` | | Shorthand for `--attest=type=sbom` |
|
||||
| [`--secret`](#secret) | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) |
|
||||
| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) (EXPERIMENTAL) |
|
||||
| [`--shm-size`](#shm-size) | `bytes` | `0` | Shared memory size for build containers |
|
||||
| [`--ssh`](#ssh) | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) |
|
||||
| [`-t`](#tag), [`--tag`](#tag) | `stringArray` | | Name and optionally a tag (format: `name:tag`) |
|
||||
|
@@ -12,16 +12,13 @@ Start debugger (EXPERIMENTAL)
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------|:---------|:--------|:--------------------------------------------------------------------------------------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--detach` | `bool` | `true` | Detach buildx server for the monitor (supported only on linux) (EXPERIMENTAL) |
|
||||
| `--invoke` | `string` | | Launch a monitor with executing specified command (EXPERIMENTAL) |
|
||||
| `--on` | `string` | `error` | When to launch the monitor ([always, error]) (EXPERIMENTAL) |
|
||||
| `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`, `rawjson`) for the monitor. Use plain to show container output |
|
||||
| `--root` | `string` | | Specify root directory of server to connect for the monitor (EXPERIMENTAL) |
|
||||
| `--server-config` | `string` | | Specify buildx server config file for the monitor (used only when launching new server) (EXPERIMENTAL) |
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:---------|:--------|:--------------------------------------------------------------------------------------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--invoke` | `string` | | Launch a monitor with executing specified command (EXPERIMENTAL) |
|
||||
| `--on` | `string` | `error` | When to launch the monitor ([always, error]) (EXPERIMENTAL) |
|
||||
| `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`, `rawjson`) for the monitor. Use plain to show container output |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
@@ -24,7 +24,6 @@ Start a build
|
||||
| `--cgroup-parent` | `string` | | Set the parent cgroup for the `RUN` instructions during build |
|
||||
| `--check` | `bool` | | Shorthand for `--call=check` |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--detach` | `bool` | | Detach buildx server (supported only on linux) (EXPERIMENTAL) |
|
||||
| `-f`, `--file` | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) |
|
||||
| `--iidfile` | `string` | | Write the image ID to a file |
|
||||
| `--label` | `stringArray` | | Set metadata for an image |
|
||||
@@ -40,10 +39,8 @@ Start a build
|
||||
| `--pull` | `bool` | | Always attempt to pull all referenced images |
|
||||
| `--push` | `bool` | | Shorthand for `--output=type=registry` |
|
||||
| `-q`, `--quiet` | `bool` | | Suppress the build output and print image ID on success |
|
||||
| `--root` | `string` | | Specify root directory of server to connect (EXPERIMENTAL) |
|
||||
| `--sbom` | `string` | | Shorthand for `--attest=type=sbom` |
|
||||
| `--secret` | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) |
|
||||
| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) (EXPERIMENTAL) |
|
||||
| `--shm-size` | `bytes` | `0` | Shared memory size for build containers |
|
||||
| `--ssh` | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) |
|
||||
| `-t`, `--tag` | `stringArray` | | Name and optionally a tag (format: `name:tag`) |
|
||||
|
@@ -27,3 +27,32 @@ Commands to work on build records
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
### Build references
|
||||
|
||||
Most `buildx history` subcommands accept a build reference to identify which
|
||||
build to act on. You can specify the build in two ways:
|
||||
|
||||
- By build ID, fetched by `docker buildx history ls`:
|
||||
|
||||
```console
|
||||
docker buildx history export qu2gsuo8ejqrwdfii23xkkckt --output build.dockerbuild
|
||||
```
|
||||
|
||||
- By relative offset, to refer to recent builds:
|
||||
|
||||
```console
|
||||
docker buildx history export ^1 --output build.dockerbuild
|
||||
```
|
||||
|
||||
- `^0` or no reference targets the most recent build
|
||||
- `^1` refers to the build before the most recent
|
||||
- `^2` refers to two builds back, and so on
|
||||
|
||||
Offset references are supported in the following `buildx history` commands:
|
||||
|
||||
- `logs`
|
||||
- `inspect`
|
||||
- `open`
|
||||
- `trace`
|
||||
- `export`
|
||||
- `rm`
|
||||
|
@@ -5,13 +5,77 @@ Export a build into Docker Desktop bundle
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------|:---------|:--------|:-----------------------------------------|
|
||||
| `--all` | `bool` | | Export all records for the builder |
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `-o`, `--output` | `string` | | Output file path |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------------|:---------|:--------|:-----------------------------------------|
|
||||
| [`--all`](#all) | `bool` | | Export all records for the builder |
|
||||
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
|
||||
| [`-D`](#debug), [`--debug`](#debug) | `bool` | | Enable debug logging |
|
||||
| [`-o`](#output), [`--output`](#output) | `string` | | Output file path |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Export one or more build records to `.dockerbuild` archive files. These archives
|
||||
contain metadata, logs, and build outputs, and can be imported into Docker
|
||||
Desktop or shared across environments.
|
||||
|
||||
## Examples
|
||||
|
||||
### <a name="output"></a> Export a single build to a custom file (--output)
|
||||
|
||||
```console
|
||||
docker buildx history export qu2gsuo8ejqrwdfii23xkkckt --output mybuild.dockerbuild
|
||||
```
|
||||
|
||||
You can find build IDs by running:
|
||||
|
||||
```console
|
||||
docker buildx history ls
|
||||
```
|
||||
|
||||
### <a name="o"></a> Export multiple builds to individual `.dockerbuild` files (-o)
|
||||
|
||||
To export two builds to separate files:
|
||||
|
||||
```console
|
||||
# Using build IDs
|
||||
docker buildx history export qu2gsuo8ejqrwdfii23xkkckt qsiifiuf1ad9pa9qvppc0z1l3 -o multi.dockerbuild
|
||||
|
||||
# Or using relative offsets
|
||||
docker buildx history export ^1 ^2 -o multi.dockerbuild
|
||||
```
|
||||
|
||||
Or use shell redirection:
|
||||
|
||||
```console
|
||||
docker buildx history export ^1 > mybuild.dockerbuild
|
||||
docker buildx history export ^2 > backend-build.dockerbuild
|
||||
```
|
||||
|
||||
### <a name="all"></a> Export all build records to a file (--all)
|
||||
|
||||
Use the `--all` flag and redirect the output:
|
||||
|
||||
```console
|
||||
docker buildx history export --all > all-builds.dockerbuild
|
||||
```
|
||||
|
||||
Or use the `--output` flag:
|
||||
|
||||
```console
|
||||
docker buildx history export --all -o all-builds.dockerbuild
|
||||
```
|
||||
|
||||
### <a name="builder"></a> Use a specific builder instance (--builder)
|
||||
|
||||
```console
|
||||
docker buildx history export --builder builder0 ^1 -o builder0-build.dockerbuild
|
||||
```
|
||||
|
||||
### <a name="debug"></a> Enable debug logging (--debug)
|
||||
|
||||
```console
|
||||
docker buildx history export --debug qu2gsuo8ejqrwdfii23xkkckt -o debug-build.dockerbuild
|
||||
```
|
@@ -5,12 +5,43 @@ Import a build into Docker Desktop
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:--------------|:--------|:-----------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `-f`, `--file` | `stringArray` | | Import from a file path |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------------------|:--------------|:--------|:-----------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| [`-f`](#file), [`--file`](#file) | `stringArray` | | Import from a file path |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Import a build record from a `.dockerbuild` archive into Docker Desktop. This
|
||||
lets you view, inspect, and analyze builds created in other environments or CI
|
||||
pipelines.
|
||||
|
||||
## Examples
|
||||
|
||||
### Import a `.dockerbuild` archive from standard input
|
||||
|
||||
```console
|
||||
docker buildx history import < mybuild.dockerbuild
|
||||
```
|
||||
|
||||
### <a name="file"></a> Import a build archive from a file (--file)
|
||||
|
||||
```console
|
||||
docker buildx history import --file ./artifacts/backend-build.dockerbuild
|
||||
```
|
||||
|
||||
### Open a build manually
|
||||
|
||||
By default, the `import` command automatically opens the imported build in Docker
|
||||
Desktop. You don't need to run `open` unless you're opening a specific build
|
||||
or re-opening it later.
|
||||
|
||||
If you've imported multiple builds, you can open one manually:
|
||||
|
||||
```console
|
||||
docker buildx history open ci-build
|
||||
```
|
||||
|
@@ -21,13 +21,61 @@ Inspect a build
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Inspect a build record to view metadata such as duration, status, build inputs,
|
||||
platforms, outputs, and attached artifacts. You can also use flags to extract
|
||||
provenance, SBOMs, or other detailed information.
|
||||
|
||||
## Examples
|
||||
|
||||
### Inspect the most recent build
|
||||
|
||||
```console
|
||||
$ docker buildx history inspect
|
||||
Name: buildx (binaries)
|
||||
Context: .
|
||||
Dockerfile: Dockerfile
|
||||
VCS Repository: https://github.com/crazy-max/buildx.git
|
||||
VCS Revision: f15eaa1ee324ffbbab29605600d27a84cab86361
|
||||
Target: binaries
|
||||
Platforms: linux/amd64
|
||||
Keep Git Dir: true
|
||||
|
||||
Started: 2025-02-07 11:56:24
|
||||
Duration: 1m 1s
|
||||
Build Steps: 16/16 (25% cached)
|
||||
|
||||
Image Resolve Mode: local
|
||||
|
||||
Materials:
|
||||
URI DIGEST
|
||||
pkg:docker/docker/dockerfile@1 sha256:93bfd3b68c109427185cd78b4779fc82b484b0b7618e36d0f104d4d801e66d25
|
||||
pkg:docker/golang@1.23-alpine3.21?platform=linux%2Famd64 sha256:2c49857f2295e89b23b28386e57e018a86620a8fede5003900f2d138ba9c4037
|
||||
pkg:docker/tonistiigi/xx@1.6.1?platform=linux%2Famd64 sha256:923441d7c25f1e2eb5789f82d987693c47b8ed987c4ab3b075d6ed2b5d6779a3
|
||||
|
||||
Attachments:
|
||||
DIGEST PLATFORM TYPE
|
||||
sha256:217329d2af959d4f02e3a96dcbe62bf100cab1feb8006a047ddfe51a5397f7e3 https://slsa.dev/provenance/v0.2
|
||||
```
|
||||
|
||||
### Inspect a specific build
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history inspect qu2gsuo8ejqrwdfii23xkkckt
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history inspect ^1
|
||||
```
|
||||
|
||||
### <a name="format"></a> Format the output (--format)
|
||||
|
||||
The formatting options (`--format`) pretty-prints the output to `pretty` (default),
|
||||
`json` or using a Go template.
|
||||
|
||||
**Pretty output**
|
||||
|
||||
```console
|
||||
$ docker buildx history inspect
|
||||
Name: buildx (binaries)
|
||||
@@ -57,6 +105,7 @@ sha256:217329d2af959d4f02e3a96dcbe62bf100cab1feb8006a047ddfe51a5397f7e3
|
||||
|
||||
Print build logs: docker buildx history logs g9808bwrjrlkbhdamxklx660b
|
||||
```
|
||||
**JSON output**
|
||||
|
||||
```console
|
||||
$ docker buildx history inspect --format json
|
||||
@@ -111,6 +160,8 @@ $ docker buildx history inspect --format json
|
||||
}
|
||||
```
|
||||
|
||||
**Go template output**
|
||||
|
||||
```console
|
||||
$ docker buildx history inspect --format "{{.Name}}: {{.VCSRepository}} ({{.VCSRevision}})"
|
||||
buildx (binaries): https://github.com/crazy-max/buildx.git (f15eaa1ee324ffbbab29605600d27a84cab86361)
|
||||
|
@@ -5,13 +5,78 @@ Inspect a build attachment
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:---------|:--------|:-----------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--platform` | `string` | | Platform of attachment |
|
||||
| `--type` | `string` | | Type of attachment |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------|:---------|:--------|:-----------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--platform` | `string` | | Platform of attachment |
|
||||
| [`--type`](#type) | `string` | | Type of attachment |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Inspect a specific attachment from a build record, such as a provenance file or
|
||||
SBOM. Attachments are optional artifacts stored with the build and may be
|
||||
platform-specific.
|
||||
|
||||
## Examples
|
||||
|
||||
### <a name="type"></a> Inspect a provenance attachment from a build (--type)
|
||||
|
||||
Supported types include `provenance` and `sbom`.
|
||||
|
||||
```console
|
||||
$ docker buildx history inspect attachment qu2gsuo8ejqrwdfii23xkkckt --type provenance
|
||||
{
|
||||
"_type": "https://slsa.dev/provenance/v0.2",
|
||||
"buildDefinition": {
|
||||
"buildType": "https://build.docker.com/BuildKit@v1",
|
||||
"externalParameters": {
|
||||
"target": "app",
|
||||
"platforms": ["linux/amd64"]
|
||||
}
|
||||
},
|
||||
"runDetails": {
|
||||
"builder": "docker",
|
||||
"by": "ci@docker.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Inspect a SBOM for linux/amd64
|
||||
|
||||
```console
|
||||
$ docker buildx history inspect attachment ^0 \
|
||||
--type sbom \
|
||||
--platform linux/amd64
|
||||
{
|
||||
"bomFormat": "CycloneDX",
|
||||
"specVersion": "1.5",
|
||||
"version": 1,
|
||||
"components": [
|
||||
{
|
||||
"type": "library",
|
||||
"name": "alpine",
|
||||
"version": "3.18.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Inspect an attachment by digest
|
||||
|
||||
You can inspect an attachment directly using its digset, which you can get from
|
||||
the `inspect` output:
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history inspect attachment qu2gsuo8ejqrwdfii23xkkckt sha256:abcdef123456...
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history inspect attachment ^0 sha256:abcdef123456...
|
||||
```
|
||||
|
||||
Use `--type sbom` or `--type provenance` to filter attachments by type. To
|
||||
inspect a specific attachment by digest, omit the `--type` flag.
|
||||
|
@@ -5,12 +5,61 @@ Print the logs of a build
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:---------|:--------|:--------------------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--progress` | `string` | `plain` | Set type of progress output (plain, rawjson, tty) |
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:---------|:--------|:--------------------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| [`--progress`](#progress) | `string` | `plain` | Set type of progress output (plain, rawjson, tty) |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Print the logs for a completed build. The output appears in the same format as
|
||||
`--progress=plain`, showing the full logs for each step.
|
||||
|
||||
By default, this shows logs for the most recent build on the current builder.
|
||||
|
||||
You can also specify an earlier build using an offset. For example:
|
||||
|
||||
- `^1` shows logs for the build before the most recent
|
||||
- `^2` shows logs for the build two steps back
|
||||
|
||||
## Examples
|
||||
|
||||
### Print logs for the most recent build
|
||||
|
||||
```console
|
||||
$ docker buildx history logs
|
||||
#1 [internal] load build definition from Dockerfile
|
||||
#1 transferring dockerfile: 31B done
|
||||
#1 DONE 0.0s
|
||||
#2 [internal] load .dockerignore
|
||||
#2 transferring context: 2B done
|
||||
#2 DONE 0.0s
|
||||
...
|
||||
```
|
||||
|
||||
By default, this shows logs for the most recent build on the current builder.
|
||||
|
||||
### Print logs for a specific build
|
||||
|
||||
To print logs for a specific build, use a build ID or offset:
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history logs qu2gsuo8ejqrwdfii23xkkckt
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history logs ^1
|
||||
```
|
||||
|
||||
### <a name="progress"></a> Set type of progress output (--progress)
|
||||
|
||||
```console
|
||||
$ docker buildx history logs ^1 --progress rawjson
|
||||
{"id":"buildx_step_1","status":"START","timestamp":"2024-05-01T12:34:56.789Z","detail":"[internal] load build definition from Dockerfile"}
|
||||
{"id":"buildx_step_1","status":"COMPLETE","timestamp":"2024-05-01T12:34:57.001Z","duration":212000000}
|
||||
...
|
||||
```
|
||||
|
@@ -5,15 +5,98 @@ List build records
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:--------------|:--------|:---------------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| `--filter` | `stringArray` | | Provide filter values (e.g., `status=error`) |
|
||||
| `--format` | `string` | `table` | Format the output |
|
||||
| `--local` | `bool` | | List records for current repository only |
|
||||
| `--no-trunc` | `bool` | | Don't truncate output |
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:--------------|:--------|:---------------------------------------------|
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| [`--filter`](#filter) | `stringArray` | | Provide filter values (e.g., `status=error`) |
|
||||
| [`--format`](#format) | `string` | `table` | Format the output |
|
||||
| [`--local`](#local) | `bool` | | List records for current repository only |
|
||||
| [`--no-trunc`](#no-trunc) | `bool` | | Don't truncate output |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
List completed builds recorded by the active builder. Each entry includes the
|
||||
build ID, name, status, timestamp, and duration.
|
||||
|
||||
By default, only records for the current builder are shown. You can filter
|
||||
results using flags.
|
||||
|
||||
## Examples
|
||||
|
||||
### List all build records for the current builder
|
||||
|
||||
```console
|
||||
$ docker buildx history ls
|
||||
BUILD ID NAME STATUS CREATED AT DURATION
|
||||
qu2gsuo8ejqrwdfii23xkkckt .dev/2850 Completed 3 days ago 1.4s
|
||||
qsiifiuf1ad9pa9qvppc0z1l3 .dev/2850 Completed 3 days ago 1.3s
|
||||
g9808bwrjrlkbhdamxklx660b .dev/3120 Completed 5 days ago 2.1s
|
||||
```
|
||||
|
||||
### <a name="filter"></a> List failed builds (--filter)
|
||||
|
||||
```console
|
||||
docker buildx history ls --filter status=error
|
||||
```
|
||||
|
||||
You can filter the list using the `--filter` flag. Supported filters include:
|
||||
|
||||
| Filter | Supported comparisons | Example |
|
||||
|:-------|:----------------------|:--------|
|
||||
| `ref`, `repository`, `status` | Support `=` and `!=` comparisons | `--filter status!=success` |
|
||||
| `startedAt`, `completedAt`, `duration` | Support `<` and `>` comparisons with time values | `--filter duration>30s` |
|
||||
|
||||
You can combine multiple filters by repeating the `--filter` flag:
|
||||
|
||||
```console
|
||||
docker buildx history ls --filter status=error --filter duration>30s
|
||||
```
|
||||
|
||||
### <a name="local"></a> List builds from the current project (--local)
|
||||
|
||||
```console
|
||||
docker buildx history ls --local
|
||||
```
|
||||
|
||||
### <a name="no-trunc"></a> Display full output without truncation (--no-trunc)
|
||||
|
||||
```console
|
||||
docker buildx history ls --no-trunc
|
||||
```
|
||||
|
||||
### <a name="format"></a> Format output (--format)
|
||||
|
||||
**JSON output**
|
||||
|
||||
```console
|
||||
$ docker buildx history ls --format json
|
||||
[
|
||||
{
|
||||
"ID": "qu2gsuo8ejqrwdfii23xkkckt",
|
||||
"Name": ".dev/2850",
|
||||
"Status": "Completed",
|
||||
"CreatedAt": "2025-04-15T12:33:00Z",
|
||||
"Duration": "1.4s"
|
||||
},
|
||||
{
|
||||
"ID": "qsiifiuf1ad9pa9qvppc0z1l3",
|
||||
"Name": ".dev/2850",
|
||||
"Status": "Completed",
|
||||
"CreatedAt": "2025-04-15T12:29:00Z",
|
||||
"Duration": "1.3s"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Go template output**
|
||||
|
||||
```console
|
||||
$ docker buildx history ls --format '{{.Name}} - {{.Duration}}'
|
||||
.dev/2850 - 1.4s
|
||||
.dev/2850 - 1.3s
|
||||
.dev/3120 - 2.1s
|
||||
```
|
||||
|
@@ -13,3 +13,27 @@ Open a build in Docker Desktop
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Open a build record in Docker Desktop for visual inspection. This requires
|
||||
Docker Desktop to be installed and running on the host machine.
|
||||
|
||||
## Examples
|
||||
|
||||
### Open the most recent build in Docker Desktop
|
||||
|
||||
```console
|
||||
docker buildx history open
|
||||
```
|
||||
|
||||
By default, this opens the most recent build on the current builder.
|
||||
|
||||
### Open a specific build
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history open qu2gsuo8ejqrwdfii23xkkckt
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history open ^1
|
||||
```
|
||||
|
@@ -14,3 +14,36 @@ Remove build records
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
Remove one or more build records from the current builder’s history. You can
|
||||
remove specific builds by ID or offset, or delete all records at once using
|
||||
the `--all` flag.
|
||||
|
||||
## Examples
|
||||
|
||||
### Remove a specific build
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history rm qu2gsuo8ejqrwdfii23xkkckt
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history rm ^1
|
||||
```
|
||||
|
||||
### Remove multiple builds
|
||||
|
||||
```console
|
||||
# Using build IDs
|
||||
docker buildx history rm qu2gsuo8ejqrwdfii23xkkckt qsiifiuf1ad9pa9qvppc0z1l3
|
||||
|
||||
# Or using relative offsets
|
||||
docker buildx history rm ^1 ^2
|
||||
```
|
||||
|
||||
### Remove all build records from the current builder
|
||||
|
||||
```console
|
||||
docker buildx history rm --all
|
||||
```
|
||||
|
@@ -5,13 +5,65 @@ Show the OpenTelemetry trace of a build record
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:---------|:--------------|:-----------------------------------------|
|
||||
| `--addr` | `string` | `127.0.0.1:0` | Address to bind the UI server |
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| `--compare` | `string` | | Compare with another build reference |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------------|:---------|:--------------|:-----------------------------------------|
|
||||
| [`--addr`](#addr) | `string` | `127.0.0.1:0` | Address to bind the UI server |
|
||||
| `--builder` | `string` | | Override the configured builder instance |
|
||||
| [`--compare`](#compare) | `string` | | Compare with another build reference |
|
||||
| `-D`, `--debug` | `bool` | | Enable debug logging |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
View the OpenTelemetry trace for a completed build. This command loads the
|
||||
trace into a Jaeger UI viewer and opens it in your browser.
|
||||
|
||||
This helps analyze build performance, step timing, and internal execution flows.
|
||||
|
||||
## Examples
|
||||
|
||||
### Open the OpenTelemetry trace for the most recent build
|
||||
|
||||
This command starts a temporary Jaeger UI server and opens your default browser
|
||||
to view the trace.
|
||||
|
||||
```console
|
||||
docker buildx history trace
|
||||
```
|
||||
|
||||
### Open the trace for a specific build
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history trace qu2gsuo8ejqrwdfii23xkkckt
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history trace ^1
|
||||
```
|
||||
|
||||
### <a name="addr"></a> Run the Jaeger UI on a specific port (--addr)
|
||||
|
||||
```console
|
||||
# Using a build ID
|
||||
docker buildx history trace qu2gsuo8ejqrwdfii23xkkckt --addr 127.0.0.1:16686
|
||||
|
||||
# Or using a relative offset
|
||||
docker buildx history trace ^1 --addr 127.0.0.1:16686
|
||||
```
|
||||
|
||||
### <a name="compare"></a> Compare two build traces (--compare)
|
||||
|
||||
Compare two specific builds by name:
|
||||
|
||||
```console
|
||||
# Using build IDs
|
||||
docker buildx history trace --compare=qu2gsuo8ejqrwdfii23xkkckt qsiifiuf1ad9pa9qvppc0z1l3
|
||||
|
||||
# Or using a single relative offset
|
||||
docker buildx history trace --compare=^1
|
||||
```
|
||||
|
||||
When you use a single reference with `--compare`, it compares that build
|
||||
against the most recent one.
|
||||
|
@@ -24,11 +24,10 @@ import (
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/api/types/system"
|
||||
"github.com/docker/docker/errdefs"
|
||||
dockerarchive "github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/moby/buildkit/client"
|
||||
mobyarchive "github.com/moby/go-archive"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -250,8 +249,8 @@ func (d *Driver) copyToContainer(ctx context.Context, files map[string][]byte) e
|
||||
if srcPath != "" {
|
||||
defer os.RemoveAll(srcPath)
|
||||
}
|
||||
srcArchive, err := dockerarchive.TarWithOptions(srcPath, &dockerarchive.TarOptions{
|
||||
ChownOpts: &idtools.Identity{UID: 0, GID: 0},
|
||||
srcArchive, err := mobyarchive.TarWithOptions(srcPath, &mobyarchive.TarOptions{
|
||||
ChownOpts: &mobyarchive.ChownOpts{UID: 0, GID: 0},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
40
go.mod
40
go.mod
@@ -6,32 +6,32 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.2.1
|
||||
github.com/Microsoft/go-winio v0.6.2
|
||||
github.com/aws/aws-sdk-go-v2/config v1.27.27
|
||||
github.com/compose-spec/compose-go/v2 v2.4.9
|
||||
github.com/compose-spec/compose-go/v2 v2.6.0
|
||||
github.com/containerd/console v1.0.4
|
||||
github.com/containerd/containerd/v2 v2.0.4
|
||||
github.com/containerd/containerd/v2 v2.0.5
|
||||
github.com/containerd/continuity v0.4.5
|
||||
github.com/containerd/errdefs v1.0.0
|
||||
github.com/containerd/log v0.1.0
|
||||
github.com/containerd/platforms v1.0.0-rc.1
|
||||
github.com/containerd/typeurl/v2 v2.2.3
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/cli v28.0.4+incompatible
|
||||
github.com/docker/cli v28.1.1+incompatible
|
||||
github.com/docker/cli-docs-tool v0.9.0
|
||||
github.com/docker/docker v28.0.4+incompatible
|
||||
github.com/docker/docker v28.1.1+incompatible
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/gofrs/flock v0.12.1
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/go-cty-funcs v0.0.0-20241120183456-c51673e0b3dd
|
||||
github.com/hashicorp/go-cty-funcs v0.0.0-20250210171435-dda779884a9f
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/hcl/v2 v2.23.0
|
||||
github.com/in-toto/in-toto-golang v0.5.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/moby/buildkit v0.21.0-rc1
|
||||
github.com/moby/buildkit v0.21.0
|
||||
github.com/moby/go-archive v0.1.0
|
||||
github.com/moby/sys/atomicwriter v0.1.0
|
||||
github.com/moby/sys/mountinfo v0.7.2
|
||||
github.com/moby/sys/signal v0.7.1
|
||||
github.com/morikuni/aec v1.0.0
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.1.1
|
||||
@@ -44,10 +44,11 @@ require (
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/pflag v1.0.6
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250318190121-d73a4b3b8a7e
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250410151801-5b74a7ad7583
|
||||
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4
|
||||
github.com/tonistiigi/jaeger-ui-rest v0.0.0-20250408171107-3dd17559e117
|
||||
github.com/zclconf/go-cty v1.16.0
|
||||
github.com/zclconf/go-cty v1.16.2
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0
|
||||
go.opentelemetry.io/otel v1.31.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0
|
||||
go.opentelemetry.io/otel/metric v1.31.0
|
||||
@@ -86,18 +87,15 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
|
||||
github.com/aws/smithy-go v1.20.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/containerd/containerd/api v1.8.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/ttrpc v1.2.7 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
@@ -113,7 +111,6 @@ require (
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@@ -124,14 +121,15 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // 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.16 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/spdystream v0.4.0 // indirect
|
||||
github.com/moby/spdystream v0.5.0 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.1 // indirect
|
||||
github.com/moby/sys/user v0.4.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
@@ -140,10 +138,6 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
|
||||
@@ -159,7 +153,6 @@ require (
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect
|
||||
@@ -168,9 +161,8 @@ require (
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/oauth2 v0.29.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
|
112
go.sum
112
go.sum
@@ -14,13 +14,10 @@ github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEP
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
|
||||
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
|
||||
github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
|
||||
github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
|
||||
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
@@ -52,13 +49,10 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzx
|
||||
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
|
||||
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
|
||||
github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
@@ -70,16 +64,16 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
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/compose-spec/compose-go/v2 v2.4.9 h1:2K4TDw+1ba2idiR6empXHKRXvWYpnvAKoNQy93/sSOs=
|
||||
github.com/compose-spec/compose-go/v2 v2.4.9/go.mod h1:6k5l/0TxCg0/2uLEhRVEsoBWBprS2uvZi32J7xub3lo=
|
||||
github.com/compose-spec/compose-go/v2 v2.6.0 h1:/+oBD2ixSENOeN/TlJqWZmUak0xM8A7J08w/z661Wd4=
|
||||
github.com/compose-spec/compose-go/v2 v2.6.0/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
|
||||
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
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/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
|
||||
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
|
||||
github.com/containerd/containerd/v2 v2.0.4 h1:+r7yJMwhTfMm3CDyiBjMBQO8a9CTBxL2Bg/JtqtIwB8=
|
||||
github.com/containerd/containerd/v2 v2.0.4/go.mod h1:5j9QUUaV/cy9ZeAx4S+8n9ffpf+iYnEj4jiExgcbuLY=
|
||||
github.com/containerd/containerd/v2 v2.0.5 h1:2vg/TjUXnaohAxiHnthQg8K06L9I4gdYEMcOLiMc8BQ=
|
||||
github.com/containerd/containerd/v2 v2.0.5/go.mod h1:Qqo0UN43i2fX1FLkrSTCg6zcHNfjN7gEnx3NPRZI+N0=
|
||||
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
||||
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
@@ -114,15 +108,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v28.0.4+incompatible h1:pBJSJeNd9QeIWPjRcV91RVJihd/TXB77q1ef64XEu4A=
|
||||
github.com/docker/cli v28.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v28.1.1+incompatible h1:eyUemzeI45DY7eDPuwUcmDyDj1pM98oD5MdSpiItp8k=
|
||||
github.com/docker/cli v28.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli-docs-tool v0.9.0 h1:CVwQbE+ZziwlPqrJ7LRyUF6GvCA+6gj7MTCsayaK9t0=
|
||||
github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3Tr1ipoypjAUtc=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok=
|
||||
github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I=
|
||||
github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||
@@ -135,7 +129,6 @@ github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQ
|
||||
github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/dvsekhvalnov/jose2go v0.0.0-20170216131308-f21a8cedbbae/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM=
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
|
||||
@@ -148,9 +141,6 @@ github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqF
|
||||
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
@@ -164,7 +154,6 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
@@ -174,24 +163,18 @@ github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlnd
|
||||
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
||||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
@@ -202,12 +185,10 @@ github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
|
||||
@@ -218,8 +199,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-cty-funcs v0.0.0-20241120183456-c51673e0b3dd h1:nwSMaLX+rf/ZPHTJHWO9K73be04SritSKvKuvpBvC2A=
|
||||
github.com/hashicorp/go-cty-funcs v0.0.0-20241120183456-c51673e0b3dd/go.mod h1:Abjk0jbRkDaNCzsRhOv2iDCofYpX1eVsjozoiK63qLA=
|
||||
github.com/hashicorp/go-cty-funcs v0.0.0-20250210171435-dda779884a9f h1:c+rwTuPxlEHiskGDCl53snuw344sDO/4KU5KSoWhieI=
|
||||
github.com/hashicorp/go-cty-funcs v0.0.0-20250210171435-dda779884a9f/go.mod h1:0AzBnolcBFa/tA5iF378GgeeiZ955EdVdC4TuxJ66m4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos=
|
||||
@@ -237,19 +218,15 @@ github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLl
|
||||
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
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/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
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/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -258,14 +235,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
@@ -273,22 +248,25 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
|
||||
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/buildkit v0.21.0-rc1 h1:QWTyHpHUtsyUMH0CH7QStisI/FmS9njRC1FK4vVYeaE=
|
||||
github.com/moby/buildkit v0.21.0-rc1/go.mod h1:coiVDxJmP1PD+79HAnTJvBMetLTdCws8gpWiYX2vcH8=
|
||||
github.com/moby/buildkit v0.21.0 h1:+z4vVqgt0spLrOSxi4DLedRbIh2gbNVlZ5q4rsnNp60=
|
||||
github.com/moby/buildkit v0.21.0/go.mod h1:mBq0D44uCyz2PdX8T/qym5LBbkBO3GGv0wqgX9ABYYw=
|
||||
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/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
|
||||
github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
@@ -304,15 +282,12 @@ github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFL
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
@@ -340,7 +315,6 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -349,25 +323,15 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
@@ -383,7 +347,6 @@ github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My
|
||||
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
|
||||
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
@@ -417,8 +380,8 @@ github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4D
|
||||
github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw=
|
||||
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 h1:r0p7fK56l8WPequOaR3i9LBqfPtEdXIQbUTzT55iqT4=
|
||||
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250318190121-d73a4b3b8a7e h1:AiXT0JHwQA52AEOVMsxRytSI9mdJSie5gUp6OQ1R8fU=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250318190121-d73a4b3b8a7e/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250410151801-5b74a7ad7583 h1:mK+ZskNt7SG4dxfKIi27C7qHAQzyjAVt1iyTf0hmsNc=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20250410151801-5b74a7ad7583/go.mod h1:BKdcez7BiVtBvIcef90ZPc6ebqIWr4JWD7+EvLm6J98=
|
||||
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/jaeger-ui-rest v0.0.0-20250408171107-3dd17559e117 h1:XFwyh2JZwR5aiKLXHX2C1n0v5F11dCJpyGL1W/Cpl3U=
|
||||
@@ -429,7 +392,6 @@ github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Q
|
||||
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
|
||||
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs=
|
||||
github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -443,9 +405,8 @@ github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8
|
||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
|
||||
github.com/zclconf/go-cty v1.16.0 h1:xPKEhst+BW5D0wxebMZkxgapvOE/dw7bFTlgSc9nD6w=
|
||||
github.com/zclconf/go-cty v1.16.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70=
|
||||
github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
@@ -482,36 +443,28 @@ go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeX
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -519,10 +472,8 @@ golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -535,7 +486,6 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
@@ -551,7 +501,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
||||
@@ -564,10 +513,8 @@ google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zt
|
||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
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/cenkalti/backoff.v2 v2.2.1/go.mod h1:S0QdOvT2AlerfSBkp0O+dk+bbIMaNbEmVk876gPCthU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
@@ -577,7 +524,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1/go.mod h1:WbjuEoo1oadwzQ4apSDU+JTvmllEHtsNHS6y7vFc7iw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -586,8 +532,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
|
||||
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
|
||||
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=
|
||||
|
@@ -10,7 +10,8 @@ Vagrant.configure("2") do |config|
|
||||
|
||||
config.vm.provision "init", type: "shell", run: "once" do |sh|
|
||||
sh.inline = <<~SHELL
|
||||
set -x
|
||||
set -ex
|
||||
export PKG_PATH=https://mirrors.ocf.berkeley.edu/pub/OpenBSD/7.5/packages/amd64/
|
||||
pkg_add -x git
|
||||
|
||||
ftp https://go.dev/dl/go#{ENV['GO_VERSION']}.openbsd-amd64.tar.gz
|
||||
|
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -23,57 +23,33 @@ func NewAttachCmd(m types.Monitor, stdout io.WriteCloser) types.Command {
|
||||
func (cm *AttachCmd) Info() types.CommandInfo {
|
||||
return types.CommandInfo{
|
||||
Name: "attach",
|
||||
HelpMessage: "attach to a buildx server or a process in the container",
|
||||
HelpMessage: "attach to a process in the container",
|
||||
HelpMessageLong: `
|
||||
Usage:
|
||||
attach ID
|
||||
attach PID
|
||||
|
||||
ID is for a session (visible via list command) or a process (visible via ps command).
|
||||
If you attached to a process, use Ctrl-a-c for switching the monitor to that process's STDIO.
|
||||
PID is for a process (visible via ps command).
|
||||
Use Ctrl-a-c for switching the monitor to that process's STDIO.
|
||||
`,
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *AttachCmd) Exec(ctx context.Context, args []string) error {
|
||||
if len(args) < 2 {
|
||||
return errors.Errorf("ID of session or process must be passed")
|
||||
return errors.Errorf("PID of process must be passed")
|
||||
}
|
||||
ref := args[1]
|
||||
var id string
|
||||
pid := args[1]
|
||||
|
||||
isProcess, err := isProcessID(ctx, cm.m, ref)
|
||||
if err == nil && isProcess {
|
||||
cm.m.Attach(ctx, ref)
|
||||
id = ref
|
||||
}
|
||||
if id == "" {
|
||||
refs, err := cm.m.List(ctx)
|
||||
if err != nil {
|
||||
return errors.Errorf("failed to get the list of sessions: %v", err)
|
||||
}
|
||||
if !slices.Contains(refs, ref) {
|
||||
return errors.Errorf("unknown ID: %q", ref)
|
||||
}
|
||||
cm.m.Detach() // Finish existing attach
|
||||
cm.m.AttachSession(ref)
|
||||
}
|
||||
fmt.Fprintf(cm.stdout, "Attached to process %q. Press Ctrl-a-c to switch to the new container\n", id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func isProcessID(ctx context.Context, c types.Monitor, ref string) (bool, error) {
|
||||
sid := c.AttachedSessionID()
|
||||
if sid == "" {
|
||||
return false, errors.Errorf("no attaching session")
|
||||
}
|
||||
infos, err := c.ListProcesses(ctx, sid)
|
||||
infos, err := cm.m.ListProcesses(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
for _, p := range infos {
|
||||
if p.ProcessID == ref {
|
||||
return true, nil
|
||||
if p.ProcessID == pid {
|
||||
cm.m.Attach(ctx, pid)
|
||||
fmt.Fprintf(cm.stdout, "Attached to process %q. Press Ctrl-a-c to switch to the new container\n", pid)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
return errors.Wrapf(cerrdefs.ErrNotFound, "pid %s", pid)
|
||||
}
|
||||
|
@@ -1,54 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type DisconnectCmd struct {
|
||||
m types.Monitor
|
||||
}
|
||||
|
||||
func NewDisconnectCmd(m types.Monitor) types.Command {
|
||||
return &DisconnectCmd{m}
|
||||
}
|
||||
|
||||
func (cm *DisconnectCmd) Info() types.CommandInfo {
|
||||
return types.CommandInfo{
|
||||
Name: "disconnect",
|
||||
HelpMessage: "disconnect a client from a buildx server. Specific session ID can be specified an arg",
|
||||
HelpMessageLong: fmt.Sprintf(`
|
||||
Usage:
|
||||
disconnect [ID]
|
||||
|
||||
ID is for a session (visible via list command). Default is %q.
|
||||
`, cm.m.AttachedSessionID()),
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *DisconnectCmd) Exec(ctx context.Context, args []string) error {
|
||||
target := cm.m.AttachedSessionID()
|
||||
if len(args) >= 2 {
|
||||
target = args[1]
|
||||
} else if target == "" {
|
||||
return errors.Errorf("no attaching session")
|
||||
}
|
||||
isProcess, err := isProcessID(ctx, cm.m, target)
|
||||
if err == nil && isProcess {
|
||||
sid := cm.m.AttachedSessionID()
|
||||
if sid == "" {
|
||||
return errors.Errorf("no attaching session")
|
||||
}
|
||||
if err := cm.m.DisconnectProcess(ctx, sid, target); err != nil {
|
||||
return errors.Errorf("disconnecting from process failed %v", target)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := cm.m.DisconnectSession(ctx, target); err != nil {
|
||||
return errors.Errorf("disconnecting from session failed: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -35,9 +35,6 @@ COMMAND and ARG... will be executed in the container.
|
||||
}
|
||||
|
||||
func (cm *ExecCmd) Exec(ctx context.Context, args []string) error {
|
||||
if ref := cm.m.AttachedSessionID(); ref == "" {
|
||||
return errors.Errorf("no attaching session")
|
||||
}
|
||||
if len(args) < 2 {
|
||||
return errors.Errorf("command must be passed")
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type KillCmd struct {
|
||||
m types.Monitor
|
||||
}
|
||||
|
||||
func NewKillCmd(m types.Monitor) types.Command {
|
||||
return &KillCmd{m}
|
||||
}
|
||||
|
||||
func (cm *KillCmd) Info() types.CommandInfo {
|
||||
return types.CommandInfo{
|
||||
Name: "kill",
|
||||
HelpMessage: "kill buildx server",
|
||||
HelpMessageLong: `
|
||||
Usage:
|
||||
kill
|
||||
|
||||
Kills the currently connecting buildx server process.
|
||||
`,
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *KillCmd) Exec(ctx context.Context, args []string) error {
|
||||
if err := cm.m.Kill(ctx); err != nil {
|
||||
return errors.Errorf("failed to kill: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
)
|
||||
|
||||
type ListCmd struct {
|
||||
m types.Monitor
|
||||
|
||||
stdout io.WriteCloser
|
||||
}
|
||||
|
||||
func NewListCmd(m types.Monitor, stdout io.WriteCloser) types.Command {
|
||||
return &ListCmd{m, stdout}
|
||||
}
|
||||
|
||||
func (cm *ListCmd) Info() types.CommandInfo {
|
||||
return types.CommandInfo{
|
||||
Name: "list",
|
||||
HelpMessage: "list buildx sessions",
|
||||
HelpMessageLong: `
|
||||
Usage:
|
||||
list
|
||||
`,
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *ListCmd) Exec(ctx context.Context, args []string) error {
|
||||
refs, err := cm.m.List(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.Strings(refs)
|
||||
tw := tabwriter.NewWriter(cm.stdout, 1, 8, 1, '\t', 0)
|
||||
fmt.Fprintln(tw, "ID\tCURRENT_SESSION")
|
||||
for _, k := range refs {
|
||||
fmt.Fprintf(tw, "%-20s\t%v\n", k, k == cm.m.AttachedSessionID())
|
||||
}
|
||||
tw.Flush()
|
||||
return nil
|
||||
}
|
@@ -7,7 +7,6 @@ import (
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type PsCmd struct {
|
||||
@@ -31,11 +30,7 @@ Usage:
|
||||
}
|
||||
|
||||
func (cm *PsCmd) Exec(ctx context.Context, args []string) error {
|
||||
ref := cm.m.AttachedSessionID()
|
||||
if ref == "" {
|
||||
return errors.Errorf("no attaching session")
|
||||
}
|
||||
plist, err := cm.m.ListProcesses(ctx, ref)
|
||||
plist, err := cm.m.ListProcesses(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
cbuild "github.com/docker/buildx/controller/build"
|
||||
controllererrors "github.com/docker/buildx/controller/errdefs"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
@@ -19,11 +20,11 @@ type ReloadCmd struct {
|
||||
stdout io.WriteCloser
|
||||
progress *progress.Printer
|
||||
|
||||
options *controllerapi.BuildOptions
|
||||
options *cbuild.Options
|
||||
invokeConfig *controllerapi.InvokeConfig
|
||||
}
|
||||
|
||||
func NewReloadCmd(m types.Monitor, stdout io.WriteCloser, progress *progress.Printer, options *controllerapi.BuildOptions, invokeConfig *controllerapi.InvokeConfig) types.Command {
|
||||
func NewReloadCmd(m types.Monitor, stdout io.WriteCloser, progress *progress.Printer, options *cbuild.Options, invokeConfig *controllerapi.InvokeConfig) types.Command {
|
||||
return &ReloadCmd{m, stdout, progress, options, invokeConfig}
|
||||
}
|
||||
|
||||
@@ -39,34 +40,15 @@ Usage:
|
||||
}
|
||||
|
||||
func (cm *ReloadCmd) Exec(ctx context.Context, args []string) error {
|
||||
var bo *controllerapi.BuildOptions
|
||||
if ref := cm.m.AttachedSessionID(); ref != "" {
|
||||
// Rebuilding an existing session; Restore the build option used for building this session.
|
||||
res, err := cm.m.Inspect(ctx, ref)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to inspect the current build session: %v\n", err)
|
||||
} else {
|
||||
bo = res.Options
|
||||
}
|
||||
} else {
|
||||
bo = cm.options
|
||||
}
|
||||
if bo == nil {
|
||||
return errors.Errorf("no build option is provided")
|
||||
}
|
||||
if ref := cm.m.AttachedSessionID(); ref != "" {
|
||||
if err := cm.m.Disconnect(ctx, ref); err != nil {
|
||||
fmt.Println("disconnect error", err)
|
||||
}
|
||||
}
|
||||
bo := cm.m.Inspect(ctx)
|
||||
|
||||
var resultUpdated bool
|
||||
cm.progress.Unpause()
|
||||
ref, _, _, err := cm.m.Build(ctx, bo, nil, cm.progress) // TODO: support stdin, hold build ref
|
||||
_, _, err := cm.m.Build(ctx, bo, nil, cm.progress) // TODO: support stdin, hold build ref
|
||||
cm.progress.Pause()
|
||||
if err != nil {
|
||||
var be *controllererrors.BuildError
|
||||
if errors.As(err, &be) {
|
||||
ref = be.SessionID
|
||||
resultUpdated = true
|
||||
} else {
|
||||
fmt.Printf("failed to reload: %v\n", err)
|
||||
@@ -79,7 +61,6 @@ func (cm *ReloadCmd) Exec(ctx context.Context, args []string) error {
|
||||
} else {
|
||||
resultUpdated = true
|
||||
}
|
||||
cm.m.AttachSession(ref)
|
||||
if resultUpdated {
|
||||
// rollback the running container with the new result
|
||||
id := cm.m.Rollback(ctx, cm.invokeConfig)
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/monitor/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type RollbackCmd struct {
|
||||
@@ -38,9 +37,6 @@ COMMAND and ARG... will be executed in the container.
|
||||
}
|
||||
|
||||
func (cm *RollbackCmd) Exec(ctx context.Context, args []string) error {
|
||||
if ref := cm.m.AttachedSessionID(); ref == "" {
|
||||
return errors.Errorf("no attaching session")
|
||||
}
|
||||
cfg := cm.invokeConfig
|
||||
if len(args) >= 2 {
|
||||
cmds := args[1:]
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/docker/buildx/build"
|
||||
cbuild "github.com/docker/buildx/controller/build"
|
||||
"github.com/docker/buildx/controller/control"
|
||||
controllerapi "github.com/docker/buildx/controller/pb"
|
||||
"github.com/docker/buildx/monitor/commands"
|
||||
@@ -31,10 +32,10 @@ type MonitorBuildResult struct {
|
||||
}
|
||||
|
||||
// RunMonitor provides an interactive session for running and managing containers via specified IO.
|
||||
func RunMonitor(ctx context.Context, curRef string, options *controllerapi.BuildOptions, invokeConfig *controllerapi.InvokeConfig, c control.BuildxController, stdin io.ReadCloser, stdout io.WriteCloser, stderr console.File, progress *progress.Printer) (*MonitorBuildResult, error) {
|
||||
func RunMonitor(ctx context.Context, curRef string, options *cbuild.Options, invokeConfig *controllerapi.InvokeConfig, c control.BuildxController, stdin io.ReadCloser, stdout io.WriteCloser, stderr console.File, progress *progress.Printer) (*MonitorBuildResult, error) {
|
||||
defer func() {
|
||||
if err := c.Disconnect(ctx, curRef); err != nil {
|
||||
logrus.Warnf("disconnect error: %v", err)
|
||||
if err := c.Close(); err != nil {
|
||||
logrus.Warnf("close error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -95,9 +96,6 @@ func RunMonitor(ctx context.Context, curRef string, options *controllerapi.Build
|
||||
availableCommands := []types.Command{
|
||||
commands.NewReloadCmd(m, stdout, progress, options, invokeConfig),
|
||||
commands.NewRollbackCmd(m, invokeConfig, stdout),
|
||||
commands.NewListCmd(m, stdout),
|
||||
commands.NewDisconnectCmd(m),
|
||||
commands.NewKillCmd(m),
|
||||
commands.NewAttachCmd(m, stdout),
|
||||
commands.NewExecCmd(m, invokeConfig, stdout),
|
||||
commands.NewPsCmd(m, stdout),
|
||||
@@ -244,24 +242,12 @@ type monitor struct {
|
||||
lastBuildResult *MonitorBuildResult
|
||||
}
|
||||
|
||||
func (m *monitor) Build(ctx context.Context, options *controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (ref string, resp *client.SolveResponse, input *build.Inputs, err error) {
|
||||
ref, resp, _, err = m.BuildxController.Build(ctx, options, in, progress)
|
||||
func (m *monitor) Build(ctx context.Context, options *cbuild.Options, in io.ReadCloser, progress progress.Writer) (resp *client.SolveResponse, input *build.Inputs, err error) {
|
||||
resp, _, err = m.BuildxController.Build(ctx, options, in, progress)
|
||||
m.lastBuildResult = &MonitorBuildResult{Resp: resp, Err: err} // Record build result
|
||||
return
|
||||
}
|
||||
|
||||
func (m *monitor) DisconnectSession(ctx context.Context, targetID string) error {
|
||||
return m.Disconnect(ctx, targetID)
|
||||
}
|
||||
|
||||
func (m *monitor) AttachSession(ref string) {
|
||||
m.ref.Store(ref)
|
||||
}
|
||||
|
||||
func (m *monitor) AttachedSessionID() string {
|
||||
return m.ref.Load().(string)
|
||||
}
|
||||
|
||||
func (m *monitor) Rollback(ctx context.Context, cfg *controllerapi.InvokeConfig) string {
|
||||
pid := identity.NewID()
|
||||
cfg1 := cfg
|
||||
@@ -323,9 +309,6 @@ func (m *monitor) invoke(ctx context.Context, pid string, cfg *controllerapi.Inv
|
||||
if err := m.muxIO.SwitchTo(1); err != nil {
|
||||
return errors.Errorf("failed to switch to process IO: %v", err)
|
||||
}
|
||||
if m.AttachedSessionID() == "" {
|
||||
return nil
|
||||
}
|
||||
invokeCtx, invokeCancel := context.WithCancelCause(ctx)
|
||||
|
||||
containerIn, containerOut := ioset.Pipe()
|
||||
@@ -343,7 +326,7 @@ func (m *monitor) invoke(ctx context.Context, pid string, cfg *controllerapi.Inv
|
||||
defer invokeCancelAndDetachFn()
|
||||
m.invokeCancel = invokeCancelAndDetachFn
|
||||
|
||||
err := m.Invoke(invokeCtx, m.AttachedSessionID(), pid, cfg, containerIn.Stdin, containerIn.Stdout, containerIn.Stderr)
|
||||
err := m.Invoke(invokeCtx, pid, cfg, containerIn.Stdin, containerIn.Stdout, containerIn.Stderr)
|
||||
close(waitInvokeDoneCh)
|
||||
|
||||
return err
|
||||
|
@@ -25,15 +25,6 @@ type Monitor interface {
|
||||
|
||||
// Detach detaches IO from the container.
|
||||
Detach()
|
||||
|
||||
// DisconnectSession finishes the specified session.
|
||||
DisconnectSession(ctx context.Context, targetID string) error
|
||||
|
||||
// AttachSession attaches the monitor to the specified session.
|
||||
AttachSession(ref string)
|
||||
|
||||
// AttachedSessionID returns the ID of the attached session.
|
||||
AttachedSessionID() string
|
||||
}
|
||||
|
||||
// CommandInfo is information about a command.
|
||||
|
@@ -399,18 +399,25 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) {
|
||||
|
||||
require.Equal(t, dgst.String(), strings.TrimSpace(stdout.String()))
|
||||
|
||||
// read the md.json file
|
||||
dt, err = os.ReadFile(filepath.Join(targetDir, "md.json"))
|
||||
require.NoError(t, err)
|
||||
|
||||
type mdT struct {
|
||||
Digest string `json:"containerimage.digest"`
|
||||
ConfigDigest string `json:"containerimage.config.digest"`
|
||||
}
|
||||
|
||||
var md mdT
|
||||
err = json.Unmarshal(dt, &md)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotEmpty(t, md.ConfigDigest)
|
||||
require.Equal(t, dgst, digest.Digest(md.ConfigDigest))
|
||||
require.NotEmpty(t, md.Digest)
|
||||
|
||||
// verify the image ID output is correct
|
||||
// XXX: improve this by checking that it's one of the two expected digests depending on the scenario.
|
||||
require.Contains(t, []digest.Digest{digest.Digest(md.ConfigDigest), digest.Digest(md.Digest)}, dgst)
|
||||
}
|
||||
|
||||
func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) {
|
||||
|
@@ -8,8 +8,8 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/docker/pkg/atomicwriter"
|
||||
"github.com/moby/buildkit/cmd/buildkitd/config"
|
||||
"github.com/moby/sys/atomicwriter"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/pkg/errors"
|
||||
fs "github.com/tonistiigi/fsutil/copy"
|
||||
|
@@ -4,6 +4,8 @@ import (
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/cli/context/docker"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
)
|
||||
|
||||
// ClientAPI represents an active docker API object.
|
||||
@@ -36,6 +38,10 @@ func NewClientAPI(cli command.Cli, ep string) (*ClientAPI, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientOpts = append(clientOpts, dockerclient.WithTraceOptions(otelhttp.WithPropagators(
|
||||
propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}),
|
||||
)))
|
||||
|
||||
ca.APIClient, err = dockerclient.NewClientWithOpts(clientOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -13,7 +13,7 @@ function "add" {
|
||||
|
||||
function "list" {
|
||||
params = []
|
||||
variadic_param = items
|
||||
variadic_params = items
|
||||
result = items
|
||||
}
|
||||
```
|
||||
|
@@ -1,79 +0,0 @@
|
||||
package userfunc
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/zclconf/go-cty/cty/function"
|
||||
)
|
||||
|
||||
var funcBodySchema = &hcl.BodySchema{
|
||||
Attributes: []hcl.AttributeSchema{
|
||||
{
|
||||
Name: "params",
|
||||
Required: true,
|
||||
},
|
||||
{
|
||||
Name: "variadic_param",
|
||||
Required: false,
|
||||
},
|
||||
{
|
||||
Name: "result",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func decodeUserFunctions(body hcl.Body, blockType string, contextFunc ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) {
|
||||
schema := &hcl.BodySchema{
|
||||
Blocks: []hcl.BlockHeaderSchema{
|
||||
{
|
||||
Type: blockType,
|
||||
LabelNames: []string{"name"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
content, remain, diags := body.PartialContent(schema)
|
||||
if diags.HasErrors() {
|
||||
return nil, remain, diags
|
||||
}
|
||||
|
||||
// first call to getBaseCtx will populate context, and then the same
|
||||
// context will be used for all subsequent calls. It's assumed that
|
||||
// all functions in a given body should see an identical context.
|
||||
var baseCtx *hcl.EvalContext
|
||||
getBaseCtx := func() *hcl.EvalContext {
|
||||
if baseCtx == nil {
|
||||
if contextFunc != nil {
|
||||
baseCtx = contextFunc()
|
||||
}
|
||||
}
|
||||
// baseCtx might still be nil here, and that's okay
|
||||
return baseCtx
|
||||
}
|
||||
|
||||
funcs = make(map[string]function.Function)
|
||||
|
||||
for _, block := range content.Blocks {
|
||||
name := block.Labels[0]
|
||||
funcContent, funcDiags := block.Body.Content(funcBodySchema)
|
||||
diags = append(diags, funcDiags...)
|
||||
if funcDiags.HasErrors() {
|
||||
continue
|
||||
}
|
||||
|
||||
paramsExpr := funcContent.Attributes["params"].Expr
|
||||
resultExpr := funcContent.Attributes["result"].Expr
|
||||
var varParamExpr hcl.Expression
|
||||
if funcContent.Attributes["variadic_param"] != nil {
|
||||
varParamExpr = funcContent.Attributes["variadic_param"].Expr
|
||||
}
|
||||
f, funcDiags := NewFunction(paramsExpr, varParamExpr, resultExpr, getBaseCtx)
|
||||
if funcDiags.HasErrors() {
|
||||
diags = append(diags, funcDiags...)
|
||||
continue
|
||||
}
|
||||
funcs[name] = f
|
||||
}
|
||||
|
||||
return funcs, remain, diags
|
||||
}
|
@@ -20,28 +20,6 @@ import (
|
||||
// structure a function declaration is found, etc.
|
||||
type ContextFunc func() *hcl.EvalContext
|
||||
|
||||
// DecodeUserFunctions looks for blocks of the given type in the given body
|
||||
// and, for each one found, interprets it as a custom function definition.
|
||||
//
|
||||
// On success, the result is a mapping of function names to implementations,
|
||||
// along with a new body that represents the remaining content of the given
|
||||
// body which can be used for further processing.
|
||||
//
|
||||
// The result expression of each function is parsed during decoding but not
|
||||
// evaluated until the function is called.
|
||||
//
|
||||
// If the given ContextFunc is non-nil, it will be called to obtain the
|
||||
// context in which the function result expressions will be evaluated. If nil,
|
||||
// or if it returns nil, the result expression will have access only to
|
||||
// variables named after the declared parameters. A non-nil context turns
|
||||
// the returned functions into closures, bound to the given context.
|
||||
//
|
||||
// If the returned diagnostics set has errors then the function map and
|
||||
// remain body may be nil or incomplete.
|
||||
func DecodeUserFunctions(body hcl.Body, blockType string, context ContextFunc) (funcs map[string]function.Function, remain hcl.Body, diags hcl.Diagnostics) {
|
||||
return decodeUserFunctions(body, blockType, context)
|
||||
}
|
||||
|
||||
// NewFunction creates a new function instance from preparsed HCL expressions.
|
||||
func NewFunction(paramsExpr, varParamExpr, resultExpr hcl.Expression, getBaseCtx func() *hcl.EvalContext) (function.Function, hcl.Diagnostics) {
|
||||
var params []string
|
||||
@@ -69,7 +47,7 @@ func NewFunction(paramsExpr, varParamExpr, resultExpr hcl.Expression, getBaseCtx
|
||||
if varParam == "" {
|
||||
return function.Function{}, hcl.Diagnostics{{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid variadic_param",
|
||||
Summary: "Invalid variadic_params",
|
||||
Detail: "The variadic parameter name must be an identifier.",
|
||||
Subject: varParamExpr.Range().Ptr(),
|
||||
}}
|
||||
|
20
vendor/github.com/beorn7/perks/LICENSE
generated
vendored
20
vendor/github.com/beorn7/perks/LICENSE
generated
vendored
@@ -1,20 +0,0 @@
|
||||
Copyright (C) 2013 Blake Mizerany
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2388
vendor/github.com/beorn7/perks/quantile/exampledata.txt
generated
vendored
2388
vendor/github.com/beorn7/perks/quantile/exampledata.txt
generated
vendored
File diff suppressed because it is too large
Load Diff
316
vendor/github.com/beorn7/perks/quantile/stream.go
generated
vendored
316
vendor/github.com/beorn7/perks/quantile/stream.go
generated
vendored
@@ -1,316 +0,0 @@
|
||||
// Package quantile computes approximate quantiles over an unbounded data
|
||||
// stream within low memory and CPU bounds.
|
||||
//
|
||||
// A small amount of accuracy is traded to achieve the above properties.
|
||||
//
|
||||
// Multiple streams can be merged before calling Query to generate a single set
|
||||
// of results. This is meaningful when the streams represent the same type of
|
||||
// data. See Merge and Samples.
|
||||
//
|
||||
// For more detailed information about the algorithm used, see:
|
||||
//
|
||||
// Effective Computation of Biased Quantiles over Data Streams
|
||||
//
|
||||
// http://www.cs.rutgers.edu/~muthu/bquant.pdf
|
||||
package quantile
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Sample holds an observed value and meta information for compression. JSON
|
||||
// tags have been added for convenience.
|
||||
type Sample struct {
|
||||
Value float64 `json:",string"`
|
||||
Width float64 `json:",string"`
|
||||
Delta float64 `json:",string"`
|
||||
}
|
||||
|
||||
// Samples represents a slice of samples. It implements sort.Interface.
|
||||
type Samples []Sample
|
||||
|
||||
func (a Samples) Len() int { return len(a) }
|
||||
func (a Samples) Less(i, j int) bool { return a[i].Value < a[j].Value }
|
||||
func (a Samples) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type invariant func(s *stream, r float64) float64
|
||||
|
||||
// NewLowBiased returns an initialized Stream for low-biased quantiles
|
||||
// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
|
||||
// error guarantees can still be given even for the lower ranks of the data
|
||||
// distribution.
|
||||
//
|
||||
// The provided epsilon is a relative error, i.e. the true quantile of a value
|
||||
// returned by a query is guaranteed to be within (1±Epsilon)*Quantile.
|
||||
//
|
||||
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
|
||||
// properties.
|
||||
func NewLowBiased(epsilon float64) *Stream {
|
||||
ƒ := func(s *stream, r float64) float64 {
|
||||
return 2 * epsilon * r
|
||||
}
|
||||
return newStream(ƒ)
|
||||
}
|
||||
|
||||
// NewHighBiased returns an initialized Stream for high-biased quantiles
|
||||
// (e.g. 0.01, 0.1, 0.5) where the needed quantiles are not known a priori, but
|
||||
// error guarantees can still be given even for the higher ranks of the data
|
||||
// distribution.
|
||||
//
|
||||
// The provided epsilon is a relative error, i.e. the true quantile of a value
|
||||
// returned by a query is guaranteed to be within 1-(1±Epsilon)*(1-Quantile).
|
||||
//
|
||||
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error
|
||||
// properties.
|
||||
func NewHighBiased(epsilon float64) *Stream {
|
||||
ƒ := func(s *stream, r float64) float64 {
|
||||
return 2 * epsilon * (s.n - r)
|
||||
}
|
||||
return newStream(ƒ)
|
||||
}
|
||||
|
||||
// NewTargeted returns an initialized Stream concerned with a particular set of
|
||||
// quantile values that are supplied a priori. Knowing these a priori reduces
|
||||
// space and computation time. The targets map maps the desired quantiles to
|
||||
// their absolute errors, i.e. the true quantile of a value returned by a query
|
||||
// is guaranteed to be within (Quantile±Epsilon).
|
||||
//
|
||||
// See http://www.cs.rutgers.edu/~muthu/bquant.pdf for time, space, and error properties.
|
||||
func NewTargeted(targetMap map[float64]float64) *Stream {
|
||||
// Convert map to slice to avoid slow iterations on a map.
|
||||
// ƒ is called on the hot path, so converting the map to a slice
|
||||
// beforehand results in significant CPU savings.
|
||||
targets := targetMapToSlice(targetMap)
|
||||
|
||||
ƒ := func(s *stream, r float64) float64 {
|
||||
var m = math.MaxFloat64
|
||||
var f float64
|
||||
for _, t := range targets {
|
||||
if t.quantile*s.n <= r {
|
||||
f = (2 * t.epsilon * r) / t.quantile
|
||||
} else {
|
||||
f = (2 * t.epsilon * (s.n - r)) / (1 - t.quantile)
|
||||
}
|
||||
if f < m {
|
||||
m = f
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
return newStream(ƒ)
|
||||
}
|
||||
|
||||
type target struct {
|
||||
quantile float64
|
||||
epsilon float64
|
||||
}
|
||||
|
||||
func targetMapToSlice(targetMap map[float64]float64) []target {
|
||||
targets := make([]target, 0, len(targetMap))
|
||||
|
||||
for quantile, epsilon := range targetMap {
|
||||
t := target{
|
||||
quantile: quantile,
|
||||
epsilon: epsilon,
|
||||
}
|
||||
targets = append(targets, t)
|
||||
}
|
||||
|
||||
return targets
|
||||
}
|
||||
|
||||
// Stream computes quantiles for a stream of float64s. It is not thread-safe by
|
||||
// design. Take care when using across multiple goroutines.
|
||||
type Stream struct {
|
||||
*stream
|
||||
b Samples
|
||||
sorted bool
|
||||
}
|
||||
|
||||
func newStream(ƒ invariant) *Stream {
|
||||
x := &stream{ƒ: ƒ}
|
||||
return &Stream{x, make(Samples, 0, 500), true}
|
||||
}
|
||||
|
||||
// Insert inserts v into the stream.
|
||||
func (s *Stream) Insert(v float64) {
|
||||
s.insert(Sample{Value: v, Width: 1})
|
||||
}
|
||||
|
||||
func (s *Stream) insert(sample Sample) {
|
||||
s.b = append(s.b, sample)
|
||||
s.sorted = false
|
||||
if len(s.b) == cap(s.b) {
|
||||
s.flush()
|
||||
}
|
||||
}
|
||||
|
||||
// Query returns the computed qth percentiles value. If s was created with
|
||||
// NewTargeted, and q is not in the set of quantiles provided a priori, Query
|
||||
// will return an unspecified result.
|
||||
func (s *Stream) Query(q float64) float64 {
|
||||
if !s.flushed() {
|
||||
// Fast path when there hasn't been enough data for a flush;
|
||||
// this also yields better accuracy for small sets of data.
|
||||
l := len(s.b)
|
||||
if l == 0 {
|
||||
return 0
|
||||
}
|
||||
i := int(math.Ceil(float64(l) * q))
|
||||
if i > 0 {
|
||||
i -= 1
|
||||
}
|
||||
s.maybeSort()
|
||||
return s.b[i].Value
|
||||
}
|
||||
s.flush()
|
||||
return s.stream.query(q)
|
||||
}
|
||||
|
||||
// Merge merges samples into the underlying streams samples. This is handy when
|
||||
// merging multiple streams from separate threads, database shards, etc.
|
||||
//
|
||||
// ATTENTION: This method is broken and does not yield correct results. The
|
||||
// underlying algorithm is not capable of merging streams correctly.
|
||||
func (s *Stream) Merge(samples Samples) {
|
||||
sort.Sort(samples)
|
||||
s.stream.merge(samples)
|
||||
}
|
||||
|
||||
// Reset reinitializes and clears the list reusing the samples buffer memory.
|
||||
func (s *Stream) Reset() {
|
||||
s.stream.reset()
|
||||
s.b = s.b[:0]
|
||||
}
|
||||
|
||||
// Samples returns stream samples held by s.
|
||||
func (s *Stream) Samples() Samples {
|
||||
if !s.flushed() {
|
||||
return s.b
|
||||
}
|
||||
s.flush()
|
||||
return s.stream.samples()
|
||||
}
|
||||
|
||||
// Count returns the total number of samples observed in the stream
|
||||
// since initialization.
|
||||
func (s *Stream) Count() int {
|
||||
return len(s.b) + s.stream.count()
|
||||
}
|
||||
|
||||
func (s *Stream) flush() {
|
||||
s.maybeSort()
|
||||
s.stream.merge(s.b)
|
||||
s.b = s.b[:0]
|
||||
}
|
||||
|
||||
func (s *Stream) maybeSort() {
|
||||
if !s.sorted {
|
||||
s.sorted = true
|
||||
sort.Sort(s.b)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Stream) flushed() bool {
|
||||
return len(s.stream.l) > 0
|
||||
}
|
||||
|
||||
type stream struct {
|
||||
n float64
|
||||
l []Sample
|
||||
ƒ invariant
|
||||
}
|
||||
|
||||
func (s *stream) reset() {
|
||||
s.l = s.l[:0]
|
||||
s.n = 0
|
||||
}
|
||||
|
||||
func (s *stream) insert(v float64) {
|
||||
s.merge(Samples{{v, 1, 0}})
|
||||
}
|
||||
|
||||
func (s *stream) merge(samples Samples) {
|
||||
// TODO(beorn7): This tries to merge not only individual samples, but
|
||||
// whole summaries. The paper doesn't mention merging summaries at
|
||||
// all. Unittests show that the merging is inaccurate. Find out how to
|
||||
// do merges properly.
|
||||
var r float64
|
||||
i := 0
|
||||
for _, sample := range samples {
|
||||
for ; i < len(s.l); i++ {
|
||||
c := s.l[i]
|
||||
if c.Value > sample.Value {
|
||||
// Insert at position i.
|
||||
s.l = append(s.l, Sample{})
|
||||
copy(s.l[i+1:], s.l[i:])
|
||||
s.l[i] = Sample{
|
||||
sample.Value,
|
||||
sample.Width,
|
||||
math.Max(sample.Delta, math.Floor(s.ƒ(s, r))-1),
|
||||
// TODO(beorn7): How to calculate delta correctly?
|
||||
}
|
||||
i++
|
||||
goto inserted
|
||||
}
|
||||
r += c.Width
|
||||
}
|
||||
s.l = append(s.l, Sample{sample.Value, sample.Width, 0})
|
||||
i++
|
||||
inserted:
|
||||
s.n += sample.Width
|
||||
r += sample.Width
|
||||
}
|
||||
s.compress()
|
||||
}
|
||||
|
||||
func (s *stream) count() int {
|
||||
return int(s.n)
|
||||
}
|
||||
|
||||
func (s *stream) query(q float64) float64 {
|
||||
t := math.Ceil(q * s.n)
|
||||
t += math.Ceil(s.ƒ(s, t) / 2)
|
||||
p := s.l[0]
|
||||
var r float64
|
||||
for _, c := range s.l[1:] {
|
||||
r += p.Width
|
||||
if r+c.Width+c.Delta > t {
|
||||
return p.Value
|
||||
}
|
||||
p = c
|
||||
}
|
||||
return p.Value
|
||||
}
|
||||
|
||||
func (s *stream) compress() {
|
||||
if len(s.l) < 2 {
|
||||
return
|
||||
}
|
||||
x := s.l[len(s.l)-1]
|
||||
xi := len(s.l) - 1
|
||||
r := s.n - 1 - x.Width
|
||||
|
||||
for i := len(s.l) - 2; i >= 0; i-- {
|
||||
c := s.l[i]
|
||||
if c.Width+x.Width+x.Delta <= s.ƒ(s, r) {
|
||||
x.Width += c.Width
|
||||
s.l[xi] = x
|
||||
// Remove element at i.
|
||||
copy(s.l[i:], s.l[i+1:])
|
||||
s.l = s.l[:len(s.l)-1]
|
||||
xi -= 1
|
||||
} else {
|
||||
x = c
|
||||
xi = i
|
||||
}
|
||||
r -= c.Width
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stream) samples() Samples {
|
||||
samples := make(Samples, len(s.l))
|
||||
copy(samples, s.l)
|
||||
return samples
|
||||
}
|
22
vendor/github.com/cespare/xxhash/v2/LICENSE.txt
generated
vendored
22
vendor/github.com/cespare/xxhash/v2/LICENSE.txt
generated
vendored
@@ -1,22 +0,0 @@
|
||||
Copyright (c) 2016 Caleb Spare
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
74
vendor/github.com/cespare/xxhash/v2/README.md
generated
vendored
74
vendor/github.com/cespare/xxhash/v2/README.md
generated
vendored
@@ -1,74 +0,0 @@
|
||||
# xxhash
|
||||
|
||||
[](https://pkg.go.dev/github.com/cespare/xxhash/v2)
|
||||
[](https://github.com/cespare/xxhash/actions/workflows/test.yml)
|
||||
|
||||
xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a
|
||||
high-quality hashing algorithm that is much faster than anything in the Go
|
||||
standard library.
|
||||
|
||||
This package provides a straightforward API:
|
||||
|
||||
```
|
||||
func Sum64(b []byte) uint64
|
||||
func Sum64String(s string) uint64
|
||||
type Digest struct{ ... }
|
||||
func New() *Digest
|
||||
```
|
||||
|
||||
The `Digest` type implements hash.Hash64. Its key methods are:
|
||||
|
||||
```
|
||||
func (*Digest) Write([]byte) (int, error)
|
||||
func (*Digest) WriteString(string) (int, error)
|
||||
func (*Digest) Sum64() uint64
|
||||
```
|
||||
|
||||
The package is written with optimized pure Go and also contains even faster
|
||||
assembly implementations for amd64 and arm64. If desired, the `purego` build tag
|
||||
opts into using the Go code even on those architectures.
|
||||
|
||||
[xxHash]: http://cyan4973.github.io/xxHash/
|
||||
|
||||
## Compatibility
|
||||
|
||||
This package is in a module and the latest code is in version 2 of the module.
|
||||
You need a version of Go with at least "minimal module compatibility" to use
|
||||
github.com/cespare/xxhash/v2:
|
||||
|
||||
* 1.9.7+ for Go 1.9
|
||||
* 1.10.3+ for Go 1.10
|
||||
* Go 1.11 or later
|
||||
|
||||
I recommend using the latest release of Go.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Here are some quick benchmarks comparing the pure-Go and assembly
|
||||
implementations of Sum64.
|
||||
|
||||
| input size | purego | asm |
|
||||
| ---------- | --------- | --------- |
|
||||
| 4 B | 1.3 GB/s | 1.2 GB/s |
|
||||
| 16 B | 2.9 GB/s | 3.5 GB/s |
|
||||
| 100 B | 6.9 GB/s | 8.1 GB/s |
|
||||
| 4 KB | 11.7 GB/s | 16.7 GB/s |
|
||||
| 10 MB | 12.0 GB/s | 17.3 GB/s |
|
||||
|
||||
These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C
|
||||
CPU using the following commands under Go 1.19.2:
|
||||
|
||||
```
|
||||
benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$')
|
||||
benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$')
|
||||
```
|
||||
|
||||
## Projects using this package
|
||||
|
||||
- [InfluxDB](https://github.com/influxdata/influxdb)
|
||||
- [Prometheus](https://github.com/prometheus/prometheus)
|
||||
- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics)
|
||||
- [FreeCache](https://github.com/coocood/freecache)
|
||||
- [FastCache](https://github.com/VictoriaMetrics/fastcache)
|
||||
- [Ristretto](https://github.com/dgraph-io/ristretto)
|
||||
- [Badger](https://github.com/dgraph-io/badger)
|
10
vendor/github.com/cespare/xxhash/v2/testall.sh
generated
vendored
10
vendor/github.com/cespare/xxhash/v2/testall.sh
generated
vendored
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -eu -o pipefail
|
||||
|
||||
# Small convenience script for running the tests with various combinations of
|
||||
# arch/tags. This assumes we're running on amd64 and have qemu available.
|
||||
|
||||
go test ./...
|
||||
go test -tags purego ./...
|
||||
GOARCH=arm64 go test
|
||||
GOARCH=arm64 go test -tags purego
|
243
vendor/github.com/cespare/xxhash/v2/xxhash.go
generated
vendored
243
vendor/github.com/cespare/xxhash/v2/xxhash.go
generated
vendored
@@ -1,243 +0,0 @@
|
||||
// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
|
||||
// at http://cyan4973.github.io/xxHash/.
|
||||
package xxhash
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
const (
|
||||
prime1 uint64 = 11400714785074694791
|
||||
prime2 uint64 = 14029467366897019727
|
||||
prime3 uint64 = 1609587929392839161
|
||||
prime4 uint64 = 9650029242287828579
|
||||
prime5 uint64 = 2870177450012600261
|
||||
)
|
||||
|
||||
// Store the primes in an array as well.
|
||||
//
|
||||
// The consts are used when possible in Go code to avoid MOVs but we need a
|
||||
// contiguous array for the assembly code.
|
||||
var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5}
|
||||
|
||||
// Digest implements hash.Hash64.
|
||||
//
|
||||
// Note that a zero-valued Digest is not ready to receive writes.
|
||||
// Call Reset or create a Digest using New before calling other methods.
|
||||
type Digest struct {
|
||||
v1 uint64
|
||||
v2 uint64
|
||||
v3 uint64
|
||||
v4 uint64
|
||||
total uint64
|
||||
mem [32]byte
|
||||
n int // how much of mem is used
|
||||
}
|
||||
|
||||
// New creates a new Digest with a zero seed.
|
||||
func New() *Digest {
|
||||
return NewWithSeed(0)
|
||||
}
|
||||
|
||||
// NewWithSeed creates a new Digest with the given seed.
|
||||
func NewWithSeed(seed uint64) *Digest {
|
||||
var d Digest
|
||||
d.ResetWithSeed(seed)
|
||||
return &d
|
||||
}
|
||||
|
||||
// Reset clears the Digest's state so that it can be reused.
|
||||
// It uses a seed value of zero.
|
||||
func (d *Digest) Reset() {
|
||||
d.ResetWithSeed(0)
|
||||
}
|
||||
|
||||
// ResetWithSeed clears the Digest's state so that it can be reused.
|
||||
// It uses the given seed to initialize the state.
|
||||
func (d *Digest) ResetWithSeed(seed uint64) {
|
||||
d.v1 = seed + prime1 + prime2
|
||||
d.v2 = seed + prime2
|
||||
d.v3 = seed
|
||||
d.v4 = seed - prime1
|
||||
d.total = 0
|
||||
d.n = 0
|
||||
}
|
||||
|
||||
// Size always returns 8 bytes.
|
||||
func (d *Digest) Size() int { return 8 }
|
||||
|
||||
// BlockSize always returns 32 bytes.
|
||||
func (d *Digest) BlockSize() int { return 32 }
|
||||
|
||||
// Write adds more data to d. It always returns len(b), nil.
|
||||
func (d *Digest) Write(b []byte) (n int, err error) {
|
||||
n = len(b)
|
||||
d.total += uint64(n)
|
||||
|
||||
memleft := d.mem[d.n&(len(d.mem)-1):]
|
||||
|
||||
if d.n+n < 32 {
|
||||
// This new data doesn't even fill the current block.
|
||||
copy(memleft, b)
|
||||
d.n += n
|
||||
return
|
||||
}
|
||||
|
||||
if d.n > 0 {
|
||||
// Finish off the partial block.
|
||||
c := copy(memleft, b)
|
||||
d.v1 = round(d.v1, u64(d.mem[0:8]))
|
||||
d.v2 = round(d.v2, u64(d.mem[8:16]))
|
||||
d.v3 = round(d.v3, u64(d.mem[16:24]))
|
||||
d.v4 = round(d.v4, u64(d.mem[24:32]))
|
||||
b = b[c:]
|
||||
d.n = 0
|
||||
}
|
||||
|
||||
if len(b) >= 32 {
|
||||
// One or more full blocks left.
|
||||
nw := writeBlocks(d, b)
|
||||
b = b[nw:]
|
||||
}
|
||||
|
||||
// Store any remaining partial block.
|
||||
copy(d.mem[:], b)
|
||||
d.n = len(b)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Sum appends the current hash to b and returns the resulting slice.
|
||||
func (d *Digest) Sum(b []byte) []byte {
|
||||
s := d.Sum64()
|
||||
return append(
|
||||
b,
|
||||
byte(s>>56),
|
||||
byte(s>>48),
|
||||
byte(s>>40),
|
||||
byte(s>>32),
|
||||
byte(s>>24),
|
||||
byte(s>>16),
|
||||
byte(s>>8),
|
||||
byte(s),
|
||||
)
|
||||
}
|
||||
|
||||
// Sum64 returns the current hash.
|
||||
func (d *Digest) Sum64() uint64 {
|
||||
var h uint64
|
||||
|
||||
if d.total >= 32 {
|
||||
v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
|
||||
h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
|
||||
h = mergeRound(h, v1)
|
||||
h = mergeRound(h, v2)
|
||||
h = mergeRound(h, v3)
|
||||
h = mergeRound(h, v4)
|
||||
} else {
|
||||
h = d.v3 + prime5
|
||||
}
|
||||
|
||||
h += d.total
|
||||
|
||||
b := d.mem[:d.n&(len(d.mem)-1)]
|
||||
for ; len(b) >= 8; b = b[8:] {
|
||||
k1 := round(0, u64(b[:8]))
|
||||
h ^= k1
|
||||
h = rol27(h)*prime1 + prime4
|
||||
}
|
||||
if len(b) >= 4 {
|
||||
h ^= uint64(u32(b[:4])) * prime1
|
||||
h = rol23(h)*prime2 + prime3
|
||||
b = b[4:]
|
||||
}
|
||||
for ; len(b) > 0; b = b[1:] {
|
||||
h ^= uint64(b[0]) * prime5
|
||||
h = rol11(h) * prime1
|
||||
}
|
||||
|
||||
h ^= h >> 33
|
||||
h *= prime2
|
||||
h ^= h >> 29
|
||||
h *= prime3
|
||||
h ^= h >> 32
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
const (
|
||||
magic = "xxh\x06"
|
||||
marshaledSize = len(magic) + 8*5 + 32
|
||||
)
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||
func (d *Digest) MarshalBinary() ([]byte, error) {
|
||||
b := make([]byte, 0, marshaledSize)
|
||||
b = append(b, magic...)
|
||||
b = appendUint64(b, d.v1)
|
||||
b = appendUint64(b, d.v2)
|
||||
b = appendUint64(b, d.v3)
|
||||
b = appendUint64(b, d.v4)
|
||||
b = appendUint64(b, d.total)
|
||||
b = append(b, d.mem[:d.n]...)
|
||||
b = b[:len(b)+len(d.mem)-d.n]
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||
func (d *Digest) UnmarshalBinary(b []byte) error {
|
||||
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
|
||||
return errors.New("xxhash: invalid hash state identifier")
|
||||
}
|
||||
if len(b) != marshaledSize {
|
||||
return errors.New("xxhash: invalid hash state size")
|
||||
}
|
||||
b = b[len(magic):]
|
||||
b, d.v1 = consumeUint64(b)
|
||||
b, d.v2 = consumeUint64(b)
|
||||
b, d.v3 = consumeUint64(b)
|
||||
b, d.v4 = consumeUint64(b)
|
||||
b, d.total = consumeUint64(b)
|
||||
copy(d.mem[:], b)
|
||||
d.n = int(d.total % uint64(len(d.mem)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func appendUint64(b []byte, x uint64) []byte {
|
||||
var a [8]byte
|
||||
binary.LittleEndian.PutUint64(a[:], x)
|
||||
return append(b, a[:]...)
|
||||
}
|
||||
|
||||
func consumeUint64(b []byte) ([]byte, uint64) {
|
||||
x := u64(b)
|
||||
return b[8:], x
|
||||
}
|
||||
|
||||
func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
|
||||
func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
|
||||
|
||||
func round(acc, input uint64) uint64 {
|
||||
acc += input * prime2
|
||||
acc = rol31(acc)
|
||||
acc *= prime1
|
||||
return acc
|
||||
}
|
||||
|
||||
func mergeRound(acc, val uint64) uint64 {
|
||||
val = round(0, val)
|
||||
acc ^= val
|
||||
acc = acc*prime1 + prime4
|
||||
return acc
|
||||
}
|
||||
|
||||
func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) }
|
||||
func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) }
|
||||
func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) }
|
||||
func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) }
|
||||
func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) }
|
||||
func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) }
|
||||
func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) }
|
||||
func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) }
|
209
vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s
generated
vendored
209
vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s
generated
vendored
@@ -1,209 +0,0 @@
|
||||
//go:build !appengine && gc && !purego
|
||||
// +build !appengine
|
||||
// +build gc
|
||||
// +build !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// Registers:
|
||||
#define h AX
|
||||
#define d AX
|
||||
#define p SI // pointer to advance through b
|
||||
#define n DX
|
||||
#define end BX // loop end
|
||||
#define v1 R8
|
||||
#define v2 R9
|
||||
#define v3 R10
|
||||
#define v4 R11
|
||||
#define x R12
|
||||
#define prime1 R13
|
||||
#define prime2 R14
|
||||
#define prime4 DI
|
||||
|
||||
#define round(acc, x) \
|
||||
IMULQ prime2, x \
|
||||
ADDQ x, acc \
|
||||
ROLQ $31, acc \
|
||||
IMULQ prime1, acc
|
||||
|
||||
// round0 performs the operation x = round(0, x).
|
||||
#define round0(x) \
|
||||
IMULQ prime2, x \
|
||||
ROLQ $31, x \
|
||||
IMULQ prime1, x
|
||||
|
||||
// mergeRound applies a merge round on the two registers acc and x.
|
||||
// It assumes that prime1, prime2, and prime4 have been loaded.
|
||||
#define mergeRound(acc, x) \
|
||||
round0(x) \
|
||||
XORQ x, acc \
|
||||
IMULQ prime1, acc \
|
||||
ADDQ prime4, acc
|
||||
|
||||
// blockLoop processes as many 32-byte blocks as possible,
|
||||
// updating v1, v2, v3, and v4. It assumes that there is at least one block
|
||||
// to process.
|
||||
#define blockLoop() \
|
||||
loop: \
|
||||
MOVQ +0(p), x \
|
||||
round(v1, x) \
|
||||
MOVQ +8(p), x \
|
||||
round(v2, x) \
|
||||
MOVQ +16(p), x \
|
||||
round(v3, x) \
|
||||
MOVQ +24(p), x \
|
||||
round(v4, x) \
|
||||
ADDQ $32, p \
|
||||
CMPQ p, end \
|
||||
JLE loop
|
||||
|
||||
// func Sum64(b []byte) uint64
|
||||
TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
|
||||
// Load fixed primes.
|
||||
MOVQ ·primes+0(SB), prime1
|
||||
MOVQ ·primes+8(SB), prime2
|
||||
MOVQ ·primes+24(SB), prime4
|
||||
|
||||
// Load slice.
|
||||
MOVQ b_base+0(FP), p
|
||||
MOVQ b_len+8(FP), n
|
||||
LEAQ (p)(n*1), end
|
||||
|
||||
// The first loop limit will be len(b)-32.
|
||||
SUBQ $32, end
|
||||
|
||||
// Check whether we have at least one block.
|
||||
CMPQ n, $32
|
||||
JLT noBlocks
|
||||
|
||||
// Set up initial state (v1, v2, v3, v4).
|
||||
MOVQ prime1, v1
|
||||
ADDQ prime2, v1
|
||||
MOVQ prime2, v2
|
||||
XORQ v3, v3
|
||||
XORQ v4, v4
|
||||
SUBQ prime1, v4
|
||||
|
||||
blockLoop()
|
||||
|
||||
MOVQ v1, h
|
||||
ROLQ $1, h
|
||||
MOVQ v2, x
|
||||
ROLQ $7, x
|
||||
ADDQ x, h
|
||||
MOVQ v3, x
|
||||
ROLQ $12, x
|
||||
ADDQ x, h
|
||||
MOVQ v4, x
|
||||
ROLQ $18, x
|
||||
ADDQ x, h
|
||||
|
||||
mergeRound(h, v1)
|
||||
mergeRound(h, v2)
|
||||
mergeRound(h, v3)
|
||||
mergeRound(h, v4)
|
||||
|
||||
JMP afterBlocks
|
||||
|
||||
noBlocks:
|
||||
MOVQ ·primes+32(SB), h
|
||||
|
||||
afterBlocks:
|
||||
ADDQ n, h
|
||||
|
||||
ADDQ $24, end
|
||||
CMPQ p, end
|
||||
JG try4
|
||||
|
||||
loop8:
|
||||
MOVQ (p), x
|
||||
ADDQ $8, p
|
||||
round0(x)
|
||||
XORQ x, h
|
||||
ROLQ $27, h
|
||||
IMULQ prime1, h
|
||||
ADDQ prime4, h
|
||||
|
||||
CMPQ p, end
|
||||
JLE loop8
|
||||
|
||||
try4:
|
||||
ADDQ $4, end
|
||||
CMPQ p, end
|
||||
JG try1
|
||||
|
||||
MOVL (p), x
|
||||
ADDQ $4, p
|
||||
IMULQ prime1, x
|
||||
XORQ x, h
|
||||
|
||||
ROLQ $23, h
|
||||
IMULQ prime2, h
|
||||
ADDQ ·primes+16(SB), h
|
||||
|
||||
try1:
|
||||
ADDQ $4, end
|
||||
CMPQ p, end
|
||||
JGE finalize
|
||||
|
||||
loop1:
|
||||
MOVBQZX (p), x
|
||||
ADDQ $1, p
|
||||
IMULQ ·primes+32(SB), x
|
||||
XORQ x, h
|
||||
ROLQ $11, h
|
||||
IMULQ prime1, h
|
||||
|
||||
CMPQ p, end
|
||||
JL loop1
|
||||
|
||||
finalize:
|
||||
MOVQ h, x
|
||||
SHRQ $33, x
|
||||
XORQ x, h
|
||||
IMULQ prime2, h
|
||||
MOVQ h, x
|
||||
SHRQ $29, x
|
||||
XORQ x, h
|
||||
IMULQ ·primes+16(SB), h
|
||||
MOVQ h, x
|
||||
SHRQ $32, x
|
||||
XORQ x, h
|
||||
|
||||
MOVQ h, ret+24(FP)
|
||||
RET
|
||||
|
||||
// func writeBlocks(d *Digest, b []byte) int
|
||||
TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
|
||||
// Load fixed primes needed for round.
|
||||
MOVQ ·primes+0(SB), prime1
|
||||
MOVQ ·primes+8(SB), prime2
|
||||
|
||||
// Load slice.
|
||||
MOVQ b_base+8(FP), p
|
||||
MOVQ b_len+16(FP), n
|
||||
LEAQ (p)(n*1), end
|
||||
SUBQ $32, end
|
||||
|
||||
// Load vN from d.
|
||||
MOVQ s+0(FP), d
|
||||
MOVQ 0(d), v1
|
||||
MOVQ 8(d), v2
|
||||
MOVQ 16(d), v3
|
||||
MOVQ 24(d), v4
|
||||
|
||||
// We don't need to check the loop condition here; this function is
|
||||
// always called with at least one block of data to process.
|
||||
blockLoop()
|
||||
|
||||
// Copy vN back to d.
|
||||
MOVQ v1, 0(d)
|
||||
MOVQ v2, 8(d)
|
||||
MOVQ v3, 16(d)
|
||||
MOVQ v4, 24(d)
|
||||
|
||||
// The number of bytes written is p minus the old base pointer.
|
||||
SUBQ b_base+8(FP), p
|
||||
MOVQ p, ret+32(FP)
|
||||
|
||||
RET
|
183
vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s
generated
vendored
183
vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s
generated
vendored
@@ -1,183 +0,0 @@
|
||||
//go:build !appengine && gc && !purego
|
||||
// +build !appengine
|
||||
// +build gc
|
||||
// +build !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// Registers:
|
||||
#define digest R1
|
||||
#define h R2 // return value
|
||||
#define p R3 // input pointer
|
||||
#define n R4 // input length
|
||||
#define nblocks R5 // n / 32
|
||||
#define prime1 R7
|
||||
#define prime2 R8
|
||||
#define prime3 R9
|
||||
#define prime4 R10
|
||||
#define prime5 R11
|
||||
#define v1 R12
|
||||
#define v2 R13
|
||||
#define v3 R14
|
||||
#define v4 R15
|
||||
#define x1 R20
|
||||
#define x2 R21
|
||||
#define x3 R22
|
||||
#define x4 R23
|
||||
|
||||
#define round(acc, x) \
|
||||
MADD prime2, acc, x, acc \
|
||||
ROR $64-31, acc \
|
||||
MUL prime1, acc
|
||||
|
||||
// round0 performs the operation x = round(0, x).
|
||||
#define round0(x) \
|
||||
MUL prime2, x \
|
||||
ROR $64-31, x \
|
||||
MUL prime1, x
|
||||
|
||||
#define mergeRound(acc, x) \
|
||||
round0(x) \
|
||||
EOR x, acc \
|
||||
MADD acc, prime4, prime1, acc
|
||||
|
||||
// blockLoop processes as many 32-byte blocks as possible,
|
||||
// updating v1, v2, v3, and v4. It assumes that n >= 32.
|
||||
#define blockLoop() \
|
||||
LSR $5, n, nblocks \
|
||||
PCALIGN $16 \
|
||||
loop: \
|
||||
LDP.P 16(p), (x1, x2) \
|
||||
LDP.P 16(p), (x3, x4) \
|
||||
round(v1, x1) \
|
||||
round(v2, x2) \
|
||||
round(v3, x3) \
|
||||
round(v4, x4) \
|
||||
SUB $1, nblocks \
|
||||
CBNZ nblocks, loop
|
||||
|
||||
// func Sum64(b []byte) uint64
|
||||
TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32
|
||||
LDP b_base+0(FP), (p, n)
|
||||
|
||||
LDP ·primes+0(SB), (prime1, prime2)
|
||||
LDP ·primes+16(SB), (prime3, prime4)
|
||||
MOVD ·primes+32(SB), prime5
|
||||
|
||||
CMP $32, n
|
||||
CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 }
|
||||
BLT afterLoop
|
||||
|
||||
ADD prime1, prime2, v1
|
||||
MOVD prime2, v2
|
||||
MOVD $0, v3
|
||||
NEG prime1, v4
|
||||
|
||||
blockLoop()
|
||||
|
||||
ROR $64-1, v1, x1
|
||||
ROR $64-7, v2, x2
|
||||
ADD x1, x2
|
||||
ROR $64-12, v3, x3
|
||||
ROR $64-18, v4, x4
|
||||
ADD x3, x4
|
||||
ADD x2, x4, h
|
||||
|
||||
mergeRound(h, v1)
|
||||
mergeRound(h, v2)
|
||||
mergeRound(h, v3)
|
||||
mergeRound(h, v4)
|
||||
|
||||
afterLoop:
|
||||
ADD n, h
|
||||
|
||||
TBZ $4, n, try8
|
||||
LDP.P 16(p), (x1, x2)
|
||||
|
||||
round0(x1)
|
||||
|
||||
// NOTE: here and below, sequencing the EOR after the ROR (using a
|
||||
// rotated register) is worth a small but measurable speedup for small
|
||||
// inputs.
|
||||
ROR $64-27, h
|
||||
EOR x1 @> 64-27, h, h
|
||||
MADD h, prime4, prime1, h
|
||||
|
||||
round0(x2)
|
||||
ROR $64-27, h
|
||||
EOR x2 @> 64-27, h, h
|
||||
MADD h, prime4, prime1, h
|
||||
|
||||
try8:
|
||||
TBZ $3, n, try4
|
||||
MOVD.P 8(p), x1
|
||||
|
||||
round0(x1)
|
||||
ROR $64-27, h
|
||||
EOR x1 @> 64-27, h, h
|
||||
MADD h, prime4, prime1, h
|
||||
|
||||
try4:
|
||||
TBZ $2, n, try2
|
||||
MOVWU.P 4(p), x2
|
||||
|
||||
MUL prime1, x2
|
||||
ROR $64-23, h
|
||||
EOR x2 @> 64-23, h, h
|
||||
MADD h, prime3, prime2, h
|
||||
|
||||
try2:
|
||||
TBZ $1, n, try1
|
||||
MOVHU.P 2(p), x3
|
||||
AND $255, x3, x1
|
||||
LSR $8, x3, x2
|
||||
|
||||
MUL prime5, x1
|
||||
ROR $64-11, h
|
||||
EOR x1 @> 64-11, h, h
|
||||
MUL prime1, h
|
||||
|
||||
MUL prime5, x2
|
||||
ROR $64-11, h
|
||||
EOR x2 @> 64-11, h, h
|
||||
MUL prime1, h
|
||||
|
||||
try1:
|
||||
TBZ $0, n, finalize
|
||||
MOVBU (p), x4
|
||||
|
||||
MUL prime5, x4
|
||||
ROR $64-11, h
|
||||
EOR x4 @> 64-11, h, h
|
||||
MUL prime1, h
|
||||
|
||||
finalize:
|
||||
EOR h >> 33, h
|
||||
MUL prime2, h
|
||||
EOR h >> 29, h
|
||||
MUL prime3, h
|
||||
EOR h >> 32, h
|
||||
|
||||
MOVD h, ret+24(FP)
|
||||
RET
|
||||
|
||||
// func writeBlocks(d *Digest, b []byte) int
|
||||
TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40
|
||||
LDP ·primes+0(SB), (prime1, prime2)
|
||||
|
||||
// Load state. Assume v[1-4] are stored contiguously.
|
||||
MOVD d+0(FP), digest
|
||||
LDP 0(digest), (v1, v2)
|
||||
LDP 16(digest), (v3, v4)
|
||||
|
||||
LDP b_base+8(FP), (p, n)
|
||||
|
||||
blockLoop()
|
||||
|
||||
// Store updated state.
|
||||
STP (v1, v2), 0(digest)
|
||||
STP (v3, v4), 16(digest)
|
||||
|
||||
BIC $31, n
|
||||
MOVD n, ret+32(FP)
|
||||
RET
|
15
vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
generated
vendored
15
vendor/github.com/cespare/xxhash/v2/xxhash_asm.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
//go:build (amd64 || arm64) && !appengine && gc && !purego
|
||||
// +build amd64 arm64
|
||||
// +build !appengine
|
||||
// +build gc
|
||||
// +build !purego
|
||||
|
||||
package xxhash
|
||||
|
||||
// Sum64 computes the 64-bit xxHash digest of b with a zero seed.
|
||||
//
|
||||
//go:noescape
|
||||
func Sum64(b []byte) uint64
|
||||
|
||||
//go:noescape
|
||||
func writeBlocks(d *Digest, b []byte) int
|
76
vendor/github.com/cespare/xxhash/v2/xxhash_other.go
generated
vendored
76
vendor/github.com/cespare/xxhash/v2/xxhash_other.go
generated
vendored
@@ -1,76 +0,0 @@
|
||||
//go:build (!amd64 && !arm64) || appengine || !gc || purego
|
||||
// +build !amd64,!arm64 appengine !gc purego
|
||||
|
||||
package xxhash
|
||||
|
||||
// Sum64 computes the 64-bit xxHash digest of b with a zero seed.
|
||||
func Sum64(b []byte) uint64 {
|
||||
// A simpler version would be
|
||||
// d := New()
|
||||
// d.Write(b)
|
||||
// return d.Sum64()
|
||||
// but this is faster, particularly for small inputs.
|
||||
|
||||
n := len(b)
|
||||
var h uint64
|
||||
|
||||
if n >= 32 {
|
||||
v1 := primes[0] + prime2
|
||||
v2 := prime2
|
||||
v3 := uint64(0)
|
||||
v4 := -primes[0]
|
||||
for len(b) >= 32 {
|
||||
v1 = round(v1, u64(b[0:8:len(b)]))
|
||||
v2 = round(v2, u64(b[8:16:len(b)]))
|
||||
v3 = round(v3, u64(b[16:24:len(b)]))
|
||||
v4 = round(v4, u64(b[24:32:len(b)]))
|
||||
b = b[32:len(b):len(b)]
|
||||
}
|
||||
h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
|
||||
h = mergeRound(h, v1)
|
||||
h = mergeRound(h, v2)
|
||||
h = mergeRound(h, v3)
|
||||
h = mergeRound(h, v4)
|
||||
} else {
|
||||
h = prime5
|
||||
}
|
||||
|
||||
h += uint64(n)
|
||||
|
||||
for ; len(b) >= 8; b = b[8:] {
|
||||
k1 := round(0, u64(b[:8]))
|
||||
h ^= k1
|
||||
h = rol27(h)*prime1 + prime4
|
||||
}
|
||||
if len(b) >= 4 {
|
||||
h ^= uint64(u32(b[:4])) * prime1
|
||||
h = rol23(h)*prime2 + prime3
|
||||
b = b[4:]
|
||||
}
|
||||
for ; len(b) > 0; b = b[1:] {
|
||||
h ^= uint64(b[0]) * prime5
|
||||
h = rol11(h) * prime1
|
||||
}
|
||||
|
||||
h ^= h >> 33
|
||||
h *= prime2
|
||||
h ^= h >> 29
|
||||
h *= prime3
|
||||
h ^= h >> 32
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func writeBlocks(d *Digest, b []byte) int {
|
||||
v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
|
||||
n := len(b)
|
||||
for len(b) >= 32 {
|
||||
v1 = round(v1, u64(b[0:8:len(b)]))
|
||||
v2 = round(v2, u64(b[8:16:len(b)]))
|
||||
v3 = round(v3, u64(b[16:24:len(b)]))
|
||||
v4 = round(v4, u64(b[24:32:len(b)]))
|
||||
b = b[32:len(b):len(b)]
|
||||
}
|
||||
d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4
|
||||
return n - len(b)
|
||||
}
|
16
vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
generated
vendored
16
vendor/github.com/cespare/xxhash/v2/xxhash_safe.go
generated
vendored
@@ -1,16 +0,0 @@
|
||||
//go:build appengine
|
||||
// +build appengine
|
||||
|
||||
// This file contains the safe implementations of otherwise unsafe-using code.
|
||||
|
||||
package xxhash
|
||||
|
||||
// Sum64String computes the 64-bit xxHash digest of s with a zero seed.
|
||||
func Sum64String(s string) uint64 {
|
||||
return Sum64([]byte(s))
|
||||
}
|
||||
|
||||
// WriteString adds more data to d. It always returns len(s), nil.
|
||||
func (d *Digest) WriteString(s string) (n int, err error) {
|
||||
return d.Write([]byte(s))
|
||||
}
|
58
vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
generated
vendored
58
vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go
generated
vendored
@@ -1,58 +0,0 @@
|
||||
//go:build !appengine
|
||||
// +build !appengine
|
||||
|
||||
// This file encapsulates usage of unsafe.
|
||||
// xxhash_safe.go contains the safe implementations.
|
||||
|
||||
package xxhash
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// In the future it's possible that compiler optimizations will make these
|
||||
// XxxString functions unnecessary by realizing that calls such as
|
||||
// Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205.
|
||||
// If that happens, even if we keep these functions they can be replaced with
|
||||
// the trivial safe code.
|
||||
|
||||
// NOTE: The usual way of doing an unsafe string-to-[]byte conversion is:
|
||||
//
|
||||
// var b []byte
|
||||
// bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
// bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
|
||||
// bh.Len = len(s)
|
||||
// bh.Cap = len(s)
|
||||
//
|
||||
// Unfortunately, as of Go 1.15.3 the inliner's cost model assigns a high enough
|
||||
// weight to this sequence of expressions that any function that uses it will
|
||||
// not be inlined. Instead, the functions below use a different unsafe
|
||||
// conversion designed to minimize the inliner weight and allow both to be
|
||||
// inlined. There is also a test (TestInlining) which verifies that these are
|
||||
// inlined.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/42739 for discussion.
|
||||
|
||||
// Sum64String computes the 64-bit xxHash digest of s with a zero seed.
|
||||
// It may be faster than Sum64([]byte(s)) by avoiding a copy.
|
||||
func Sum64String(s string) uint64 {
|
||||
b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)}))
|
||||
return Sum64(b)
|
||||
}
|
||||
|
||||
// WriteString adds more data to d. It always returns len(s), nil.
|
||||
// It may be faster than Write([]byte(s)) by avoiding a copy.
|
||||
func (d *Digest) WriteString(s string) (n int, err error) {
|
||||
d.Write(*(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})))
|
||||
// d.Write always returns len(s), nil.
|
||||
// Ignoring the return output and returning these fixed values buys a
|
||||
// savings of 6 in the inliner's cost model.
|
||||
return len(s), nil
|
||||
}
|
||||
|
||||
// sliceHeader is similar to reflect.SliceHeader, but it assumes that the layout
|
||||
// of the first two words is the same as the layout of a string.
|
||||
type sliceHeader struct {
|
||||
s string
|
||||
cap int
|
||||
}
|
4
vendor/github.com/compose-spec/compose-go/v2/dotenv/env.go
generated
vendored
4
vendor/github.com/compose-spec/compose-go/v2/dotenv/env.go
generated
vendored
@@ -35,7 +35,7 @@ func GetEnvFromFile(currentEnv map[string]string, filenames []string) (map[strin
|
||||
|
||||
s, err := os.Stat(dotEnvFile)
|
||||
if os.IsNotExist(err) {
|
||||
return envMap, fmt.Errorf("Couldn't find env file: %s", dotEnvFile)
|
||||
return envMap, fmt.Errorf("couldn't find env file: %s", dotEnvFile)
|
||||
}
|
||||
if err != nil {
|
||||
return envMap, err
|
||||
@@ -50,7 +50,7 @@ func GetEnvFromFile(currentEnv map[string]string, filenames []string) (map[strin
|
||||
|
||||
b, err := os.ReadFile(dotEnvFile)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("Couldn't read env file: %s", dotEnvFile)
|
||||
return nil, fmt.Errorf("couldn't read env file: %s", dotEnvFile)
|
||||
}
|
||||
if err != nil {
|
||||
return envMap, err
|
||||
|
16
vendor/github.com/compose-spec/compose-go/v2/dotenv/format.go
generated
vendored
16
vendor/github.com/compose-spec/compose-go/v2/dotenv/format.go
generated
vendored
@@ -24,28 +24,28 @@ import (
|
||||
const DotEnv = ".env"
|
||||
|
||||
var formats = map[string]Parser{
|
||||
DotEnv: func(r io.Reader, filename string, lookup func(key string) (string, bool)) (map[string]string, error) {
|
||||
m, err := ParseWithLookup(r, lookup)
|
||||
DotEnv: func(r io.Reader, filename string, vars map[string]string, lookup func(key string) (string, bool)) error {
|
||||
err := parseWithLookup(r, vars, lookup)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read %s: %w", filename, err)
|
||||
return fmt.Errorf("failed to read %s: %w", filename, err)
|
||||
}
|
||||
return m, nil
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
type Parser func(r io.Reader, filename string, lookup func(key string) (string, bool)) (map[string]string, error)
|
||||
type Parser func(r io.Reader, filename string, vars map[string]string, lookup func(key string) (string, bool)) 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) {
|
||||
func ParseWithFormat(r io.Reader, filename string, vars map[string]string, resolve LookupFn, format string) error {
|
||||
if format == "" {
|
||||
format = DotEnv
|
||||
}
|
||||
fn, ok := formats[format]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported env_file format %q", format)
|
||||
return fmt.Errorf("unsupported env_file format %q", format)
|
||||
}
|
||||
return fn(r, filename, resolve)
|
||||
return fn(r, filename, vars, resolve)
|
||||
}
|
||||
|
11
vendor/github.com/compose-spec/compose-go/v2/dotenv/godotenv.go
generated
vendored
11
vendor/github.com/compose-spec/compose-go/v2/dotenv/godotenv.go
generated
vendored
@@ -41,16 +41,23 @@ func Parse(r io.Reader) (map[string]string, error) {
|
||||
|
||||
// ParseWithLookup reads an env file from io.Reader, returning a map of keys and values.
|
||||
func ParseWithLookup(r io.Reader, lookupFn LookupFn) (map[string]string, error) {
|
||||
vars := map[string]string{}
|
||||
err := parseWithLookup(r, vars, lookupFn)
|
||||
return vars, err
|
||||
}
|
||||
|
||||
// ParseWithLookup reads an env file from io.Reader, returning a map of keys and values.
|
||||
func parseWithLookup(r io.Reader, vars map[string]string, lookupFn LookupFn) error {
|
||||
data, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// seek past the UTF-8 BOM if it exists (particularly on Windows, some
|
||||
// editors tend to add it, and it'll cause parsing to fail)
|
||||
data = bytes.TrimPrefix(data, utf8BOM)
|
||||
|
||||
return UnmarshalBytesWithLookup(data, lookupFn)
|
||||
return newParser().parse(string(data), vars, lookupFn)
|
||||
}
|
||||
|
||||
// Load will read your env file(s) and load them into ENV for this process.
|
||||
|
2
vendor/github.com/compose-spec/compose-go/v2/graph/cycle.go
generated
vendored
2
vendor/github.com/compose-spec/compose-go/v2/graph/cycle.go
generated
vendored
@@ -18,11 +18,11 @@ package graph
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/types"
|
||||
"github.com/compose-spec/compose-go/v2/utils"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// CheckCycle analyze project's depends_on relation and report an error on cycle detection
|
||||
|
2
vendor/github.com/compose-spec/compose-go/v2/graph/traversal.go
generated
vendored
2
vendor/github.com/compose-spec/compose-go/v2/graph/traversal.go
generated
vendored
@@ -18,9 +18,9 @@ package graph
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
|
8
vendor/github.com/compose-spec/compose-go/v2/loader/loader.go
generated
vendored
8
vendor/github.com/compose-spec/compose-go/v2/loader/loader.go
generated
vendored
@@ -26,6 +26,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -42,7 +43,6 @@ import (
|
||||
"github.com/compose-spec/compose-go/v2/validation"
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/exp/slices"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -337,7 +337,7 @@ func LoadModelWithContext(ctx context.Context, configDetails types.ConfigDetails
|
||||
// LoadModelWithContext reads a ConfigDetails and returns a fully loaded configuration as a yaml dictionary
|
||||
func loadModelWithContext(ctx context.Context, configDetails *types.ConfigDetails, opts *Options) (map[string]any, error) {
|
||||
if len(configDetails.ConfigFiles) < 1 {
|
||||
return nil, errors.New("No files specified")
|
||||
return nil, errors.New("no compose file specified")
|
||||
}
|
||||
|
||||
err := projectName(configDetails, opts)
|
||||
@@ -432,7 +432,7 @@ func loadYamlFile(ctx context.Context,
|
||||
}
|
||||
cfg, ok := converted.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("Top-level object must be a mapping")
|
||||
return errors.New("top-level object must be a mapping")
|
||||
}
|
||||
|
||||
if opts.Interpolate != nil && !opts.SkipInterpolation {
|
||||
@@ -877,7 +877,7 @@ func formatInvalidKeyError(keyPrefix string, key interface{}) error {
|
||||
} else {
|
||||
location = fmt.Sprintf("in %s", keyPrefix)
|
||||
}
|
||||
return fmt.Errorf("Non-string key %s: %#v", location, key)
|
||||
return fmt.Errorf("non-string key %s: %#v", location, key)
|
||||
}
|
||||
|
||||
// Windows path, c:\\my\\path\\shiny, need to be changed to be compatible with
|
||||
|
6
vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
generated
vendored
6
vendor/github.com/compose-spec/compose-go/v2/loader/reset.go
generated
vendored
@@ -67,6 +67,8 @@ func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.No
|
||||
p.paths = append(p.paths, path)
|
||||
return node, nil
|
||||
}
|
||||
|
||||
keys := map[string]int{}
|
||||
switch node.Kind {
|
||||
case yaml.SequenceNode:
|
||||
var nodes []*yaml.Node
|
||||
@@ -87,6 +89,10 @@ func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.No
|
||||
for idx, v := range node.Content {
|
||||
if idx%2 == 0 {
|
||||
key = v.Value
|
||||
if line, seen := keys[key]; seen {
|
||||
return nil, fmt.Errorf("line %d: mapping key %#v already defined at line %d", v.Line, key, line)
|
||||
}
|
||||
keys[key] = v.Line
|
||||
} else {
|
||||
resolved, err := p.resolveReset(v, path.Next(key))
|
||||
if err != nil {
|
||||
|
2
vendor/github.com/compose-spec/compose-go/v2/loader/validate.go
generated
vendored
2
vendor/github.com/compose-spec/compose-go/v2/loader/validate.go
generated
vendored
@@ -29,7 +29,7 @@ import (
|
||||
// checkConsistency validate a compose model is consistent
|
||||
func checkConsistency(project *types.Project) error { //nolint:gocyclo
|
||||
for name, s := range project.Services {
|
||||
if s.Build == nil && s.Image == "" {
|
||||
if s.Build == nil && s.Image == "" && s.Provider == nil {
|
||||
return fmt.Errorf("service %q has neither an image nor a build context specified: %w", s.Name, errdefs.ErrInvalid)
|
||||
}
|
||||
|
||||
|
18
vendor/github.com/compose-spec/compose-go/v2/override/merge.go
generated
vendored
18
vendor/github.com/compose-spec/compose-go/v2/override/merge.go
generated
vendored
@@ -19,10 +19,9 @@ package override
|
||||
import (
|
||||
"cmp"
|
||||
"fmt"
|
||||
"strings"
|
||||
"slices"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/tree"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// Merge applies overrides to a config model
|
||||
@@ -62,6 +61,7 @@ func init() {
|
||||
mergeSpecials["services.*.extra_hosts"] = mergeExtraHosts
|
||||
mergeSpecials["services.*.healthcheck.test"] = override
|
||||
mergeSpecials["services.*.labels"] = mergeToSequence
|
||||
mergeSpecials["services.*.volumes.*.volume.labels"] = mergeToSequence
|
||||
mergeSpecials["services.*.logging"] = mergeLogging
|
||||
mergeSpecials["services.*.networks"] = mergeNetworks
|
||||
mergeSpecials["services.*.sysctls"] = mergeToSequence
|
||||
@@ -104,7 +104,7 @@ func mergeYaml(e any, o any, p tree.Path) (any, error) {
|
||||
func mergeMappings(mapping map[string]any, other map[string]any, p tree.Path) (map[string]any, error) {
|
||||
for k, v := range other {
|
||||
e, ok := mapping[k]
|
||||
if !ok || strings.HasPrefix(k, "x-") {
|
||||
if !ok {
|
||||
mapping[k] = v
|
||||
continue
|
||||
}
|
||||
@@ -227,9 +227,17 @@ func mergeUlimit(_ any, o any, p tree.Path) (any, error) {
|
||||
|
||||
func mergeIPAMConfig(c any, o any, path tree.Path) (any, error) {
|
||||
var ipamConfigs []any
|
||||
for _, original := range c.([]any) {
|
||||
configs, ok := c.([]any)
|
||||
if !ok {
|
||||
return o, fmt.Errorf("%s: unexpected type %T", path, c)
|
||||
}
|
||||
overrides, ok := o.([]any)
|
||||
if !ok {
|
||||
return o, fmt.Errorf("%s: unexpected type %T", path, c)
|
||||
}
|
||||
for _, original := range configs {
|
||||
right := convertIntoMapping(original, nil)
|
||||
for _, override := range o.([]any) {
|
||||
for _, override := range overrides {
|
||||
left := convertIntoMapping(override, nil)
|
||||
if left["subnet"] != right["subnet"] {
|
||||
// check if left is already in ipamConfigs, add it if not and continue with the next config
|
||||
|
28
vendor/github.com/compose-spec/compose-go/v2/schema/compose-spec.json
generated
vendored
28
vendor/github.com/compose-spec/compose-go/v2/schema/compose-spec.json
generated
vendored
@@ -259,6 +259,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"provider": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"options": {
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.+$": {"type": ["string", "number", "null"]}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"external_links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"extra_hosts": {"$ref": "#/definitions/extra_hosts"},
|
||||
"gpus": {"$ref": "#/definitions/gpus"},
|
||||
@@ -279,7 +293,6 @@
|
||||
"links": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
|
||||
"logging": {
|
||||
"type": "object",
|
||||
|
||||
"properties": {
|
||||
"driver": {"type": "string"},
|
||||
"options": {
|
||||
@@ -405,7 +418,9 @@
|
||||
"type": "object",
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"type": {"type": "string"},
|
||||
"type": {"type": "string",
|
||||
"enum": ["bind", "volume", "tmpfs", "cluster", "image"]
|
||||
},
|
||||
"source": {"type": "string"},
|
||||
"target": {"type": "string"},
|
||||
"read_only": {"type": ["boolean", "string"]},
|
||||
@@ -424,6 +439,7 @@
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"labels": {"$ref": "#/definitions/list_or_dict"},
|
||||
"nocopy": {"type": ["boolean", "string"]},
|
||||
"subpath": {"type": "string"}
|
||||
},
|
||||
@@ -443,6 +459,14 @@
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subpath": {"type": "string"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {"^x-": {}}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
432
vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go
generated
vendored
432
vendor/github.com/compose-spec/compose-go/v2/types/derived.gen.go
generated
vendored
@@ -355,9 +355,15 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
}
|
||||
copy(dst.Entrypoint, src.Entrypoint)
|
||||
}
|
||||
if src.Provider == nil {
|
||||
dst.Provider = nil
|
||||
} else {
|
||||
dst.Provider = new(ServiceProviderConfig)
|
||||
deriveDeepCopy_13(dst.Provider, src.Provider)
|
||||
}
|
||||
if src.Environment != nil {
|
||||
dst.Environment = make(map[string]*string, len(src.Environment))
|
||||
deriveDeepCopy_13(dst.Environment, src.Environment)
|
||||
deriveDeepCopy_14(dst.Environment, src.Environment)
|
||||
} else {
|
||||
dst.Environment = nil
|
||||
}
|
||||
@@ -423,7 +429,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
}
|
||||
if src.ExtraHosts != nil {
|
||||
dst.ExtraHosts = make(map[string][]string, len(src.ExtraHosts))
|
||||
deriveDeepCopy_14(dst.ExtraHosts, src.ExtraHosts)
|
||||
deriveDeepCopy_15(dst.ExtraHosts, src.ExtraHosts)
|
||||
} else {
|
||||
dst.ExtraHosts = nil
|
||||
}
|
||||
@@ -461,14 +467,14 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
} else {
|
||||
dst.Gpus = make([]DeviceRequest, len(src.Gpus))
|
||||
}
|
||||
deriveDeepCopy_15(dst.Gpus, src.Gpus)
|
||||
deriveDeepCopy_16(dst.Gpus, src.Gpus)
|
||||
}
|
||||
dst.Hostname = src.Hostname
|
||||
if src.HealthCheck == nil {
|
||||
dst.HealthCheck = nil
|
||||
} else {
|
||||
dst.HealthCheck = new(HealthCheckConfig)
|
||||
deriveDeepCopy_16(dst.HealthCheck, src.HealthCheck)
|
||||
deriveDeepCopy_17(dst.HealthCheck, src.HealthCheck)
|
||||
}
|
||||
dst.Image = src.Image
|
||||
if src.Init == nil {
|
||||
@@ -531,7 +537,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
dst.Logging = nil
|
||||
} else {
|
||||
dst.Logging = new(LoggingConfig)
|
||||
deriveDeepCopy_17(dst.Logging, src.Logging)
|
||||
deriveDeepCopy_18(dst.Logging, src.Logging)
|
||||
}
|
||||
dst.LogDriver = src.LogDriver
|
||||
if src.LogOpt != nil {
|
||||
@@ -549,7 +555,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
dst.NetworkMode = src.NetworkMode
|
||||
if src.Networks != nil {
|
||||
dst.Networks = make(map[string]*ServiceNetworkConfig, len(src.Networks))
|
||||
deriveDeepCopy_18(dst.Networks, src.Networks)
|
||||
deriveDeepCopy_19(dst.Networks, src.Networks)
|
||||
} else {
|
||||
dst.Networks = nil
|
||||
}
|
||||
@@ -574,7 +580,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
} else {
|
||||
dst.Ports = make([]ServicePortConfig, len(src.Ports))
|
||||
}
|
||||
deriveDeepCopy_19(dst.Ports, src.Ports)
|
||||
deriveDeepCopy_20(dst.Ports, src.Ports)
|
||||
}
|
||||
dst.Privileged = src.Privileged
|
||||
dst.PullPolicy = src.PullPolicy
|
||||
@@ -603,7 +609,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
} else {
|
||||
dst.Secrets = make([]ServiceSecretConfig, len(src.Secrets))
|
||||
}
|
||||
deriveDeepCopy_20(dst.Secrets, src.Secrets)
|
||||
deriveDeepCopy_21(dst.Secrets, src.Secrets)
|
||||
}
|
||||
if src.SecurityOpt == nil {
|
||||
dst.SecurityOpt = nil
|
||||
@@ -665,7 +671,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
dst.Tty = src.Tty
|
||||
if src.Ulimits != nil {
|
||||
dst.Ulimits = make(map[string]*UlimitsConfig, len(src.Ulimits))
|
||||
deriveDeepCopy_21(dst.Ulimits, src.Ulimits)
|
||||
deriveDeepCopy_22(dst.Ulimits, src.Ulimits)
|
||||
} else {
|
||||
dst.Ulimits = nil
|
||||
}
|
||||
@@ -689,7 +695,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
} else {
|
||||
dst.Volumes = make([]ServiceVolumeConfig, len(src.Volumes))
|
||||
}
|
||||
deriveDeepCopy_22(dst.Volumes, src.Volumes)
|
||||
deriveDeepCopy_23(dst.Volumes, src.Volumes)
|
||||
}
|
||||
if src.VolumesFrom == nil {
|
||||
dst.VolumesFrom = nil
|
||||
@@ -726,7 +732,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
} else {
|
||||
dst.PostStart = make([]ServiceHook, len(src.PostStart))
|
||||
}
|
||||
deriveDeepCopy_23(dst.PostStart, src.PostStart)
|
||||
deriveDeepCopy_24(dst.PostStart, src.PostStart)
|
||||
}
|
||||
if src.PreStop == nil {
|
||||
dst.PreStop = nil
|
||||
@@ -744,7 +750,7 @@ func deriveDeepCopyService(dst, src *ServiceConfig) {
|
||||
} else {
|
||||
dst.PreStop = make([]ServiceHook, len(src.PreStop))
|
||||
}
|
||||
deriveDeepCopy_23(dst.PreStop, src.PreStop)
|
||||
deriveDeepCopy_24(dst.PreStop, src.PreStop)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -770,7 +776,7 @@ func deriveDeepCopy_(dst, src map[string]NetworkConfig) {
|
||||
for src_key, src_value := range src {
|
||||
func() {
|
||||
field := new(NetworkConfig)
|
||||
deriveDeepCopy_24(field, &src_value)
|
||||
deriveDeepCopy_25(field, &src_value)
|
||||
dst[src_key] = *field
|
||||
}()
|
||||
}
|
||||
@@ -781,7 +787,7 @@ func deriveDeepCopy_1(dst, src map[string]VolumeConfig) {
|
||||
for src_key, src_value := range src {
|
||||
func() {
|
||||
field := new(VolumeConfig)
|
||||
deriveDeepCopy_25(field, &src_value)
|
||||
deriveDeepCopy_26(field, &src_value)
|
||||
dst[src_key] = *field
|
||||
}()
|
||||
}
|
||||
@@ -792,7 +798,7 @@ func deriveDeepCopy_2(dst, src map[string]SecretConfig) {
|
||||
for src_key, src_value := range src {
|
||||
func() {
|
||||
field := new(SecretConfig)
|
||||
deriveDeepCopy_26(field, &src_value)
|
||||
deriveDeepCopy_27(field, &src_value)
|
||||
dst[src_key] = *field
|
||||
}()
|
||||
}
|
||||
@@ -803,7 +809,7 @@ func deriveDeepCopy_3(dst, src map[string]ConfigObjConfig) {
|
||||
for src_key, src_value := range src {
|
||||
func() {
|
||||
field := new(ConfigObjConfig)
|
||||
deriveDeepCopy_27(field, &src_value)
|
||||
deriveDeepCopy_28(field, &src_value)
|
||||
dst[src_key] = *field
|
||||
}()
|
||||
}
|
||||
@@ -841,7 +847,7 @@ func deriveDeepCopy_5(dst, src *BuildConfig) {
|
||||
}
|
||||
if src.Args != nil {
|
||||
dst.Args = make(map[string]*string, len(src.Args))
|
||||
deriveDeepCopy_13(dst.Args, src.Args)
|
||||
deriveDeepCopy_14(dst.Args, src.Args)
|
||||
} else {
|
||||
dst.Args = nil
|
||||
}
|
||||
@@ -915,7 +921,7 @@ func deriveDeepCopy_5(dst, src *BuildConfig) {
|
||||
dst.Pull = src.Pull
|
||||
if src.ExtraHosts != nil {
|
||||
dst.ExtraHosts = make(map[string][]string, len(src.ExtraHosts))
|
||||
deriveDeepCopy_14(dst.ExtraHosts, src.ExtraHosts)
|
||||
deriveDeepCopy_15(dst.ExtraHosts, src.ExtraHosts)
|
||||
} else {
|
||||
dst.ExtraHosts = nil
|
||||
}
|
||||
@@ -938,7 +944,7 @@ func deriveDeepCopy_5(dst, src *BuildConfig) {
|
||||
} else {
|
||||
dst.Secrets = make([]ServiceSecretConfig, len(src.Secrets))
|
||||
}
|
||||
deriveDeepCopy_20(dst.Secrets, src.Secrets)
|
||||
deriveDeepCopy_21(dst.Secrets, src.Secrets)
|
||||
}
|
||||
dst.ShmSize = src.ShmSize
|
||||
if src.Tags == nil {
|
||||
@@ -961,7 +967,7 @@ func deriveDeepCopy_5(dst, src *BuildConfig) {
|
||||
}
|
||||
if src.Ulimits != nil {
|
||||
dst.Ulimits = make(map[string]*UlimitsConfig, len(src.Ulimits))
|
||||
deriveDeepCopy_21(dst.Ulimits, src.Ulimits)
|
||||
deriveDeepCopy_22(dst.Ulimits, src.Ulimits)
|
||||
} else {
|
||||
dst.Ulimits = nil
|
||||
}
|
||||
@@ -1010,7 +1016,7 @@ func deriveDeepCopy_6(dst, src *DevelopConfig) {
|
||||
} else {
|
||||
dst.Watch = make([]Trigger, len(src.Watch))
|
||||
}
|
||||
deriveDeepCopy_28(dst.Watch, src.Watch)
|
||||
deriveDeepCopy_29(dst.Watch, src.Watch)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -1039,7 +1045,7 @@ func deriveDeepCopy_7(dst, src *BlkioConfig) {
|
||||
} else {
|
||||
dst.WeightDevice = make([]WeightDevice, len(src.WeightDevice))
|
||||
}
|
||||
deriveDeepCopy_29(dst.WeightDevice, src.WeightDevice)
|
||||
deriveDeepCopy_30(dst.WeightDevice, src.WeightDevice)
|
||||
}
|
||||
if src.DeviceReadBps == nil {
|
||||
dst.DeviceReadBps = nil
|
||||
@@ -1057,7 +1063,7 @@ func deriveDeepCopy_7(dst, src *BlkioConfig) {
|
||||
} else {
|
||||
dst.DeviceReadBps = make([]ThrottleDevice, len(src.DeviceReadBps))
|
||||
}
|
||||
deriveDeepCopy_30(dst.DeviceReadBps, src.DeviceReadBps)
|
||||
deriveDeepCopy_31(dst.DeviceReadBps, src.DeviceReadBps)
|
||||
}
|
||||
if src.DeviceReadIOps == nil {
|
||||
dst.DeviceReadIOps = nil
|
||||
@@ -1075,7 +1081,7 @@ func deriveDeepCopy_7(dst, src *BlkioConfig) {
|
||||
} else {
|
||||
dst.DeviceReadIOps = make([]ThrottleDevice, len(src.DeviceReadIOps))
|
||||
}
|
||||
deriveDeepCopy_30(dst.DeviceReadIOps, src.DeviceReadIOps)
|
||||
deriveDeepCopy_31(dst.DeviceReadIOps, src.DeviceReadIOps)
|
||||
}
|
||||
if src.DeviceWriteBps == nil {
|
||||
dst.DeviceWriteBps = nil
|
||||
@@ -1093,7 +1099,7 @@ func deriveDeepCopy_7(dst, src *BlkioConfig) {
|
||||
} else {
|
||||
dst.DeviceWriteBps = make([]ThrottleDevice, len(src.DeviceWriteBps))
|
||||
}
|
||||
deriveDeepCopy_30(dst.DeviceWriteBps, src.DeviceWriteBps)
|
||||
deriveDeepCopy_31(dst.DeviceWriteBps, src.DeviceWriteBps)
|
||||
}
|
||||
if src.DeviceWriteIOps == nil {
|
||||
dst.DeviceWriteIOps = nil
|
||||
@@ -1111,7 +1117,7 @@ func deriveDeepCopy_7(dst, src *BlkioConfig) {
|
||||
} else {
|
||||
dst.DeviceWriteIOps = make([]ThrottleDevice, len(src.DeviceWriteIOps))
|
||||
}
|
||||
deriveDeepCopy_30(dst.DeviceWriteIOps, src.DeviceWriteIOps)
|
||||
deriveDeepCopy_31(dst.DeviceWriteIOps, src.DeviceWriteIOps)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -1126,7 +1132,7 @@ func deriveDeepCopy_8(dst, src []ServiceConfigObjConfig) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceConfigObjConfig)
|
||||
deriveDeepCopy_31(field, &src_value)
|
||||
deriveDeepCopy_32(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
@@ -1150,7 +1156,7 @@ func deriveDeepCopy_10(dst, src map[string]ServiceDependency) {
|
||||
for src_key, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceDependency)
|
||||
deriveDeepCopy_32(field, &src_value)
|
||||
deriveDeepCopy_33(field, &src_value)
|
||||
dst[src_key] = *field
|
||||
}()
|
||||
}
|
||||
@@ -1175,28 +1181,28 @@ func deriveDeepCopy_11(dst, src *DeployConfig) {
|
||||
dst.UpdateConfig = nil
|
||||
} else {
|
||||
dst.UpdateConfig = new(UpdateConfig)
|
||||
deriveDeepCopy_33(dst.UpdateConfig, src.UpdateConfig)
|
||||
deriveDeepCopy_34(dst.UpdateConfig, src.UpdateConfig)
|
||||
}
|
||||
if src.RollbackConfig == nil {
|
||||
dst.RollbackConfig = nil
|
||||
} else {
|
||||
dst.RollbackConfig = new(UpdateConfig)
|
||||
deriveDeepCopy_33(dst.RollbackConfig, src.RollbackConfig)
|
||||
deriveDeepCopy_34(dst.RollbackConfig, src.RollbackConfig)
|
||||
}
|
||||
func() {
|
||||
field := new(Resources)
|
||||
deriveDeepCopy_34(field, &src.Resources)
|
||||
deriveDeepCopy_35(field, &src.Resources)
|
||||
dst.Resources = *field
|
||||
}()
|
||||
if src.RestartPolicy == nil {
|
||||
dst.RestartPolicy = nil
|
||||
} else {
|
||||
dst.RestartPolicy = new(RestartPolicy)
|
||||
deriveDeepCopy_35(dst.RestartPolicy, src.RestartPolicy)
|
||||
deriveDeepCopy_36(dst.RestartPolicy, src.RestartPolicy)
|
||||
}
|
||||
func() {
|
||||
field := new(Placement)
|
||||
deriveDeepCopy_36(field, &src.Placement)
|
||||
deriveDeepCopy_37(field, &src.Placement)
|
||||
dst.Placement = *field
|
||||
}()
|
||||
dst.EndpointMode = src.EndpointMode
|
||||
@@ -1213,14 +1219,31 @@ func deriveDeepCopy_12(dst, src []DeviceMapping) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(DeviceMapping)
|
||||
deriveDeepCopy_37(field, &src_value)
|
||||
deriveDeepCopy_38(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_13 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_13(dst, src map[string]*string) {
|
||||
func deriveDeepCopy_13(dst, src *ServiceProviderConfig) {
|
||||
dst.Type = src.Type
|
||||
if src.Options != nil {
|
||||
dst.Options = make(map[string]string, len(src.Options))
|
||||
deriveDeepCopy_4(dst.Options, src.Options)
|
||||
} else {
|
||||
dst.Options = nil
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
src.Extensions.DeepCopy(dst.Extensions)
|
||||
} else {
|
||||
dst.Extensions = nil
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_14 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_14(dst, src map[string]*string) {
|
||||
for src_key, src_value := range src {
|
||||
if src_value == nil {
|
||||
dst[src_key] = nil
|
||||
@@ -1234,8 +1257,8 @@ func deriveDeepCopy_13(dst, src map[string]*string) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_14 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_14(dst, src map[string][]string) {
|
||||
// deriveDeepCopy_15 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_15(dst, src map[string][]string) {
|
||||
for src_key, src_value := range src {
|
||||
if src_value == nil {
|
||||
dst[src_key] = nil
|
||||
@@ -1261,19 +1284,19 @@ func deriveDeepCopy_14(dst, src map[string][]string) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_15 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_15(dst, src []DeviceRequest) {
|
||||
// deriveDeepCopy_16 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_16(dst, src []DeviceRequest) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(DeviceRequest)
|
||||
deriveDeepCopy_38(field, &src_value)
|
||||
deriveDeepCopy_39(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_16 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_16(dst, src *HealthCheckConfig) {
|
||||
// deriveDeepCopy_17 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_17(dst, src *HealthCheckConfig) {
|
||||
if src.Test == nil {
|
||||
dst.Test = nil
|
||||
} else {
|
||||
@@ -1331,8 +1354,8 @@ func deriveDeepCopy_16(dst, src *HealthCheckConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_17 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_17(dst, src *LoggingConfig) {
|
||||
// deriveDeepCopy_18 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_18(dst, src *LoggingConfig) {
|
||||
dst.Driver = src.Driver
|
||||
if src.Options != nil {
|
||||
dst.Options = make(map[string]string, len(src.Options))
|
||||
@@ -1348,8 +1371,8 @@ func deriveDeepCopy_17(dst, src *LoggingConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_18 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_18(dst, src map[string]*ServiceNetworkConfig) {
|
||||
// deriveDeepCopy_19 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_19(dst, src map[string]*ServiceNetworkConfig) {
|
||||
for src_key, src_value := range src {
|
||||
if src_value == nil {
|
||||
dst[src_key] = nil
|
||||
@@ -1358,27 +1381,16 @@ func deriveDeepCopy_18(dst, src map[string]*ServiceNetworkConfig) {
|
||||
dst[src_key] = nil
|
||||
} else {
|
||||
dst[src_key] = new(ServiceNetworkConfig)
|
||||
deriveDeepCopy_39(dst[src_key], src_value)
|
||||
deriveDeepCopy_40(dst[src_key], src_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_19 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_19(dst, src []ServicePortConfig) {
|
||||
// deriveDeepCopy_20 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_20(dst, src []ServicePortConfig) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServicePortConfig)
|
||||
deriveDeepCopy_40(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_20 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_20(dst, src []ServiceSecretConfig) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceSecretConfig)
|
||||
deriveDeepCopy_41(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
@@ -1386,7 +1398,18 @@ func deriveDeepCopy_20(dst, src []ServiceSecretConfig) {
|
||||
}
|
||||
|
||||
// deriveDeepCopy_21 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_21(dst, src map[string]*UlimitsConfig) {
|
||||
func deriveDeepCopy_21(dst, src []ServiceSecretConfig) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceSecretConfig)
|
||||
deriveDeepCopy_42(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_22 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_22(dst, src map[string]*UlimitsConfig) {
|
||||
for src_key, src_value := range src {
|
||||
if src_value == nil {
|
||||
dst[src_key] = nil
|
||||
@@ -1395,27 +1418,16 @@ func deriveDeepCopy_21(dst, src map[string]*UlimitsConfig) {
|
||||
dst[src_key] = nil
|
||||
} else {
|
||||
dst[src_key] = new(UlimitsConfig)
|
||||
deriveDeepCopy_42(dst[src_key], src_value)
|
||||
deriveDeepCopy_43(dst[src_key], src_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_22 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_22(dst, src []ServiceVolumeConfig) {
|
||||
// deriveDeepCopy_23 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_23(dst, src []ServiceVolumeConfig) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceVolumeConfig)
|
||||
deriveDeepCopy_43(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_23 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_23(dst, src []ServiceHook) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceHook)
|
||||
deriveDeepCopy_44(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
@@ -1423,7 +1435,18 @@ func deriveDeepCopy_23(dst, src []ServiceHook) {
|
||||
}
|
||||
|
||||
// deriveDeepCopy_24 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_24(dst, src *NetworkConfig) {
|
||||
func deriveDeepCopy_24(dst, src []ServiceHook) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ServiceHook)
|
||||
deriveDeepCopy_45(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_25 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_25(dst, src *NetworkConfig) {
|
||||
dst.Name = src.Name
|
||||
dst.Driver = src.Driver
|
||||
if src.DriverOpts != nil {
|
||||
@@ -1434,7 +1457,7 @@ func deriveDeepCopy_24(dst, src *NetworkConfig) {
|
||||
}
|
||||
func() {
|
||||
field := new(IPAMConfig)
|
||||
deriveDeepCopy_45(field, &src.Ipam)
|
||||
deriveDeepCopy_46(field, &src.Ipam)
|
||||
dst.Ipam = *field
|
||||
}()
|
||||
dst.External = src.External
|
||||
@@ -1472,8 +1495,8 @@ func deriveDeepCopy_24(dst, src *NetworkConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_25 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_25(dst, src *VolumeConfig) {
|
||||
// deriveDeepCopy_26 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_26(dst, src *VolumeConfig) {
|
||||
dst.Name = src.Name
|
||||
dst.Driver = src.Driver
|
||||
if src.DriverOpts != nil {
|
||||
@@ -1503,38 +1526,8 @@ func deriveDeepCopy_25(dst, src *VolumeConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_26 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_26(dst, src *SecretConfig) {
|
||||
dst.Name = src.Name
|
||||
dst.File = src.File
|
||||
dst.Environment = src.Environment
|
||||
dst.Content = src.Content
|
||||
dst.marshallContent = src.marshallContent
|
||||
dst.External = src.External
|
||||
if src.Labels != nil {
|
||||
dst.Labels = make(map[string]string, len(src.Labels))
|
||||
deriveDeepCopy_4(dst.Labels, src.Labels)
|
||||
} else {
|
||||
dst.Labels = nil
|
||||
}
|
||||
dst.Driver = src.Driver
|
||||
if src.DriverOpts != nil {
|
||||
dst.DriverOpts = make(map[string]string, len(src.DriverOpts))
|
||||
deriveDeepCopy_4(dst.DriverOpts, src.DriverOpts)
|
||||
} else {
|
||||
dst.DriverOpts = nil
|
||||
}
|
||||
dst.TemplateDriver = src.TemplateDriver
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
src.Extensions.DeepCopy(dst.Extensions)
|
||||
} else {
|
||||
dst.Extensions = nil
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_27 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_27(dst, src *ConfigObjConfig) {
|
||||
func deriveDeepCopy_27(dst, src *SecretConfig) {
|
||||
dst.Name = src.Name
|
||||
dst.File = src.File
|
||||
dst.Environment = src.Environment
|
||||
@@ -1564,21 +1557,40 @@ func deriveDeepCopy_27(dst, src *ConfigObjConfig) {
|
||||
}
|
||||
|
||||
// deriveDeepCopy_28 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_28(dst, src []Trigger) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(Trigger)
|
||||
deriveDeepCopy_46(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
func deriveDeepCopy_28(dst, src *ConfigObjConfig) {
|
||||
dst.Name = src.Name
|
||||
dst.File = src.File
|
||||
dst.Environment = src.Environment
|
||||
dst.Content = src.Content
|
||||
dst.marshallContent = src.marshallContent
|
||||
dst.External = src.External
|
||||
if src.Labels != nil {
|
||||
dst.Labels = make(map[string]string, len(src.Labels))
|
||||
deriveDeepCopy_4(dst.Labels, src.Labels)
|
||||
} else {
|
||||
dst.Labels = nil
|
||||
}
|
||||
dst.Driver = src.Driver
|
||||
if src.DriverOpts != nil {
|
||||
dst.DriverOpts = make(map[string]string, len(src.DriverOpts))
|
||||
deriveDeepCopy_4(dst.DriverOpts, src.DriverOpts)
|
||||
} else {
|
||||
dst.DriverOpts = nil
|
||||
}
|
||||
dst.TemplateDriver = src.TemplateDriver
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
src.Extensions.DeepCopy(dst.Extensions)
|
||||
} else {
|
||||
dst.Extensions = nil
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_29 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_29(dst, src []WeightDevice) {
|
||||
func deriveDeepCopy_29(dst, src []Trigger) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(WeightDevice)
|
||||
field := new(Trigger)
|
||||
deriveDeepCopy_47(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
@@ -1586,10 +1598,10 @@ func deriveDeepCopy_29(dst, src []WeightDevice) {
|
||||
}
|
||||
|
||||
// deriveDeepCopy_30 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_30(dst, src []ThrottleDevice) {
|
||||
func deriveDeepCopy_30(dst, src []WeightDevice) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ThrottleDevice)
|
||||
field := new(WeightDevice)
|
||||
deriveDeepCopy_48(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
@@ -1597,7 +1609,18 @@ func deriveDeepCopy_30(dst, src []ThrottleDevice) {
|
||||
}
|
||||
|
||||
// deriveDeepCopy_31 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_31(dst, src *ServiceConfigObjConfig) {
|
||||
func deriveDeepCopy_31(dst, src []ThrottleDevice) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(ThrottleDevice)
|
||||
deriveDeepCopy_49(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_32 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_32(dst, src *ServiceConfigObjConfig) {
|
||||
dst.Source = src.Source
|
||||
dst.Target = src.Target
|
||||
dst.UID = src.UID
|
||||
@@ -1616,8 +1639,8 @@ func deriveDeepCopy_31(dst, src *ServiceConfigObjConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_32 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_32(dst, src *ServiceDependency) {
|
||||
// deriveDeepCopy_33 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_33(dst, src *ServiceDependency) {
|
||||
dst.Condition = src.Condition
|
||||
dst.Restart = src.Restart
|
||||
if src.Extensions != nil {
|
||||
@@ -1629,8 +1652,8 @@ func deriveDeepCopy_32(dst, src *ServiceDependency) {
|
||||
dst.Required = src.Required
|
||||
}
|
||||
|
||||
// deriveDeepCopy_33 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_33(dst, src *UpdateConfig) {
|
||||
// deriveDeepCopy_34 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_34(dst, src *UpdateConfig) {
|
||||
if src.Parallelism == nil {
|
||||
dst.Parallelism = nil
|
||||
} else {
|
||||
@@ -1650,19 +1673,19 @@ func deriveDeepCopy_33(dst, src *UpdateConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_34 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_34(dst, src *Resources) {
|
||||
// deriveDeepCopy_35 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_35(dst, src *Resources) {
|
||||
if src.Limits == nil {
|
||||
dst.Limits = nil
|
||||
} else {
|
||||
dst.Limits = new(Resource)
|
||||
deriveDeepCopy_49(dst.Limits, src.Limits)
|
||||
deriveDeepCopy_50(dst.Limits, src.Limits)
|
||||
}
|
||||
if src.Reservations == nil {
|
||||
dst.Reservations = nil
|
||||
} else {
|
||||
dst.Reservations = new(Resource)
|
||||
deriveDeepCopy_49(dst.Reservations, src.Reservations)
|
||||
deriveDeepCopy_50(dst.Reservations, src.Reservations)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -1672,8 +1695,8 @@ func deriveDeepCopy_34(dst, src *Resources) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_35 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_35(dst, src *RestartPolicy) {
|
||||
// deriveDeepCopy_36 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_36(dst, src *RestartPolicy) {
|
||||
dst.Condition = src.Condition
|
||||
if src.Delay == nil {
|
||||
dst.Delay = nil
|
||||
@@ -1701,8 +1724,8 @@ func deriveDeepCopy_35(dst, src *RestartPolicy) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_36 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_36(dst, src *Placement) {
|
||||
// deriveDeepCopy_37 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_37(dst, src *Placement) {
|
||||
if src.Constraints == nil {
|
||||
dst.Constraints = nil
|
||||
} else {
|
||||
@@ -1737,7 +1760,7 @@ func deriveDeepCopy_36(dst, src *Placement) {
|
||||
} else {
|
||||
dst.Preferences = make([]PlacementPreferences, len(src.Preferences))
|
||||
}
|
||||
deriveDeepCopy_50(dst.Preferences, src.Preferences)
|
||||
deriveDeepCopy_51(dst.Preferences, src.Preferences)
|
||||
}
|
||||
dst.MaxReplicas = src.MaxReplicas
|
||||
if src.Extensions != nil {
|
||||
@@ -1748,8 +1771,8 @@ func deriveDeepCopy_36(dst, src *Placement) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_37 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_37(dst, src *DeviceMapping) {
|
||||
// deriveDeepCopy_38 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_38(dst, src *DeviceMapping) {
|
||||
dst.Source = src.Source
|
||||
dst.Target = src.Target
|
||||
dst.Permissions = src.Permissions
|
||||
@@ -1761,8 +1784,8 @@ func deriveDeepCopy_37(dst, src *DeviceMapping) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_38 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_38(dst, src *DeviceRequest) {
|
||||
// deriveDeepCopy_39 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_39(dst, src *DeviceRequest) {
|
||||
if src.Capabilities == nil {
|
||||
dst.Capabilities = nil
|
||||
} else {
|
||||
@@ -1809,8 +1832,8 @@ func deriveDeepCopy_38(dst, src *DeviceRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_39 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_39(dst, src *ServiceNetworkConfig) {
|
||||
// deriveDeepCopy_40 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_40(dst, src *ServiceNetworkConfig) {
|
||||
dst.Priority = src.Priority
|
||||
dst.GatewayPriority = src.GatewayPriority
|
||||
if src.Aliases == nil {
|
||||
@@ -1866,8 +1889,8 @@ func deriveDeepCopy_39(dst, src *ServiceNetworkConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_40 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_40(dst, src *ServicePortConfig) {
|
||||
// deriveDeepCopy_41 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_41(dst, src *ServicePortConfig) {
|
||||
dst.Name = src.Name
|
||||
dst.Mode = src.Mode
|
||||
dst.HostIP = src.HostIP
|
||||
@@ -1883,8 +1906,8 @@ func deriveDeepCopy_40(dst, src *ServicePortConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_41 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_41(dst, src *ServiceSecretConfig) {
|
||||
// deriveDeepCopy_42 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_42(dst, src *ServiceSecretConfig) {
|
||||
dst.Source = src.Source
|
||||
dst.Target = src.Target
|
||||
dst.UID = src.UID
|
||||
@@ -1903,8 +1926,8 @@ func deriveDeepCopy_41(dst, src *ServiceSecretConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_42 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_42(dst, src *UlimitsConfig) {
|
||||
// deriveDeepCopy_43 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_43(dst, src *UlimitsConfig) {
|
||||
dst.Single = src.Single
|
||||
dst.Soft = src.Soft
|
||||
dst.Hard = src.Hard
|
||||
@@ -1916,8 +1939,8 @@ func deriveDeepCopy_42(dst, src *UlimitsConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_43 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_43(dst, src *ServiceVolumeConfig) {
|
||||
// deriveDeepCopy_44 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_44(dst, src *ServiceVolumeConfig) {
|
||||
dst.Type = src.Type
|
||||
dst.Source = src.Source
|
||||
dst.Target = src.Target
|
||||
@@ -1927,19 +1950,25 @@ func deriveDeepCopy_43(dst, src *ServiceVolumeConfig) {
|
||||
dst.Bind = nil
|
||||
} else {
|
||||
dst.Bind = new(ServiceVolumeBind)
|
||||
deriveDeepCopy_51(dst.Bind, src.Bind)
|
||||
deriveDeepCopy_52(dst.Bind, src.Bind)
|
||||
}
|
||||
if src.Volume == nil {
|
||||
dst.Volume = nil
|
||||
} else {
|
||||
dst.Volume = new(ServiceVolumeVolume)
|
||||
deriveDeepCopy_52(dst.Volume, src.Volume)
|
||||
deriveDeepCopy_53(dst.Volume, src.Volume)
|
||||
}
|
||||
if src.Tmpfs == nil {
|
||||
dst.Tmpfs = nil
|
||||
} else {
|
||||
dst.Tmpfs = new(ServiceVolumeTmpfs)
|
||||
deriveDeepCopy_53(dst.Tmpfs, src.Tmpfs)
|
||||
deriveDeepCopy_54(dst.Tmpfs, src.Tmpfs)
|
||||
}
|
||||
if src.Image == nil {
|
||||
dst.Image = nil
|
||||
} else {
|
||||
dst.Image = new(ServiceVolumeImage)
|
||||
deriveDeepCopy_55(dst.Image, src.Image)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -1949,8 +1978,8 @@ func deriveDeepCopy_43(dst, src *ServiceVolumeConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_44 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_44(dst, src *ServiceHook) {
|
||||
// deriveDeepCopy_45 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_45(dst, src *ServiceHook) {
|
||||
if src.Command == nil {
|
||||
dst.Command = nil
|
||||
} else {
|
||||
@@ -1974,7 +2003,7 @@ func deriveDeepCopy_44(dst, src *ServiceHook) {
|
||||
dst.WorkingDir = src.WorkingDir
|
||||
if src.Environment != nil {
|
||||
dst.Environment = make(map[string]*string, len(src.Environment))
|
||||
deriveDeepCopy_13(dst.Environment, src.Environment)
|
||||
deriveDeepCopy_14(dst.Environment, src.Environment)
|
||||
} else {
|
||||
dst.Environment = nil
|
||||
}
|
||||
@@ -1986,8 +2015,8 @@ func deriveDeepCopy_44(dst, src *ServiceHook) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_45 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_45(dst, src *IPAMConfig) {
|
||||
// deriveDeepCopy_46 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_46(dst, src *IPAMConfig) {
|
||||
dst.Driver = src.Driver
|
||||
if src.Config == nil {
|
||||
dst.Config = nil
|
||||
@@ -2005,7 +2034,7 @@ func deriveDeepCopy_45(dst, src *IPAMConfig) {
|
||||
} else {
|
||||
dst.Config = make([]*IPAMPool, len(src.Config))
|
||||
}
|
||||
deriveDeepCopy_54(dst.Config, src.Config)
|
||||
deriveDeepCopy_56(dst.Config, src.Config)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -2015,14 +2044,14 @@ func deriveDeepCopy_45(dst, src *IPAMConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_46 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_46(dst, src *Trigger) {
|
||||
// deriveDeepCopy_47 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_47(dst, src *Trigger) {
|
||||
dst.Path = src.Path
|
||||
dst.Action = src.Action
|
||||
dst.Target = src.Target
|
||||
func() {
|
||||
field := new(ServiceHook)
|
||||
deriveDeepCopy_44(field, &src.Exec)
|
||||
deriveDeepCopy_45(field, &src.Exec)
|
||||
dst.Exec = *field
|
||||
}()
|
||||
if src.Include == nil {
|
||||
@@ -2069,8 +2098,8 @@ func deriveDeepCopy_46(dst, src *Trigger) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_47 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_47(dst, src *WeightDevice) {
|
||||
// deriveDeepCopy_48 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_48(dst, src *WeightDevice) {
|
||||
dst.Path = src.Path
|
||||
dst.Weight = src.Weight
|
||||
if src.Extensions != nil {
|
||||
@@ -2081,8 +2110,8 @@ func deriveDeepCopy_47(dst, src *WeightDevice) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_48 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_48(dst, src *ThrottleDevice) {
|
||||
// deriveDeepCopy_49 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_49(dst, src *ThrottleDevice) {
|
||||
dst.Path = src.Path
|
||||
dst.Rate = src.Rate
|
||||
if src.Extensions != nil {
|
||||
@@ -2093,8 +2122,8 @@ func deriveDeepCopy_48(dst, src *ThrottleDevice) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_49 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_49(dst, src *Resource) {
|
||||
// deriveDeepCopy_50 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_50(dst, src *Resource) {
|
||||
dst.NanoCPUs = src.NanoCPUs
|
||||
dst.MemoryBytes = src.MemoryBytes
|
||||
dst.Pids = src.Pids
|
||||
@@ -2114,7 +2143,7 @@ func deriveDeepCopy_49(dst, src *Resource) {
|
||||
} else {
|
||||
dst.Devices = make([]DeviceRequest, len(src.Devices))
|
||||
}
|
||||
deriveDeepCopy_15(dst.Devices, src.Devices)
|
||||
deriveDeepCopy_16(dst.Devices, src.Devices)
|
||||
}
|
||||
if src.GenericResources == nil {
|
||||
dst.GenericResources = nil
|
||||
@@ -2132,7 +2161,7 @@ func deriveDeepCopy_49(dst, src *Resource) {
|
||||
} else {
|
||||
dst.GenericResources = make([]GenericResource, len(src.GenericResources))
|
||||
}
|
||||
deriveDeepCopy_55(dst.GenericResources, src.GenericResources)
|
||||
deriveDeepCopy_57(dst.GenericResources, src.GenericResources)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -2142,19 +2171,19 @@ func deriveDeepCopy_49(dst, src *Resource) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_50 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_50(dst, src []PlacementPreferences) {
|
||||
// deriveDeepCopy_51 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_51(dst, src []PlacementPreferences) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(PlacementPreferences)
|
||||
deriveDeepCopy_56(field, &src_value)
|
||||
deriveDeepCopy_58(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_51 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_51(dst, src *ServiceVolumeBind) {
|
||||
// deriveDeepCopy_52 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_52(dst, src *ServiceVolumeBind) {
|
||||
dst.SELinux = src.SELinux
|
||||
dst.Propagation = src.Propagation
|
||||
dst.CreateHostPath = src.CreateHostPath
|
||||
@@ -2167,8 +2196,14 @@ func deriveDeepCopy_51(dst, src *ServiceVolumeBind) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_52 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_52(dst, src *ServiceVolumeVolume) {
|
||||
// deriveDeepCopy_53 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_53(dst, src *ServiceVolumeVolume) {
|
||||
if src.Labels != nil {
|
||||
dst.Labels = make(map[string]string, len(src.Labels))
|
||||
deriveDeepCopy_4(dst.Labels, src.Labels)
|
||||
} else {
|
||||
dst.Labels = nil
|
||||
}
|
||||
dst.NoCopy = src.NoCopy
|
||||
dst.Subpath = src.Subpath
|
||||
if src.Extensions != nil {
|
||||
@@ -2179,8 +2214,8 @@ func deriveDeepCopy_52(dst, src *ServiceVolumeVolume) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_53 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_53(dst, src *ServiceVolumeTmpfs) {
|
||||
// deriveDeepCopy_54 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_54(dst, src *ServiceVolumeTmpfs) {
|
||||
dst.Size = src.Size
|
||||
dst.Mode = src.Mode
|
||||
if src.Extensions != nil {
|
||||
@@ -2191,31 +2226,42 @@ func deriveDeepCopy_53(dst, src *ServiceVolumeTmpfs) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_54 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_54(dst, src []*IPAMPool) {
|
||||
// deriveDeepCopy_55 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_55(dst, src *ServiceVolumeImage) {
|
||||
dst.SubPath = src.SubPath
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
src.Extensions.DeepCopy(dst.Extensions)
|
||||
} else {
|
||||
dst.Extensions = nil
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_56 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_56(dst, src []*IPAMPool) {
|
||||
for src_i, src_value := range src {
|
||||
if src_value == nil {
|
||||
dst[src_i] = nil
|
||||
} else {
|
||||
dst[src_i] = new(IPAMPool)
|
||||
deriveDeepCopy_57(dst[src_i], src_value)
|
||||
deriveDeepCopy_59(dst[src_i], src_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_55 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_55(dst, src []GenericResource) {
|
||||
// deriveDeepCopy_57 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_57(dst, src []GenericResource) {
|
||||
for src_i, src_value := range src {
|
||||
func() {
|
||||
field := new(GenericResource)
|
||||
deriveDeepCopy_58(field, &src_value)
|
||||
deriveDeepCopy_60(field, &src_value)
|
||||
dst[src_i] = *field
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_56 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_56(dst, src *PlacementPreferences) {
|
||||
// deriveDeepCopy_58 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_58(dst, src *PlacementPreferences) {
|
||||
dst.Spread = src.Spread
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -2225,8 +2271,8 @@ func deriveDeepCopy_56(dst, src *PlacementPreferences) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_57 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_57(dst, src *IPAMPool) {
|
||||
// deriveDeepCopy_59 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_59(dst, src *IPAMPool) {
|
||||
dst.Subnet = src.Subnet
|
||||
dst.Gateway = src.Gateway
|
||||
dst.IPRange = src.IPRange
|
||||
@@ -2244,13 +2290,13 @@ func deriveDeepCopy_57(dst, src *IPAMPool) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_58 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_58(dst, src *GenericResource) {
|
||||
// deriveDeepCopy_60 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_60(dst, src *GenericResource) {
|
||||
if src.DiscreteResourceSpec == nil {
|
||||
dst.DiscreteResourceSpec = nil
|
||||
} else {
|
||||
dst.DiscreteResourceSpec = new(DiscreteGenericResource)
|
||||
deriveDeepCopy_59(dst.DiscreteResourceSpec, src.DiscreteResourceSpec)
|
||||
deriveDeepCopy_61(dst.DiscreteResourceSpec, src.DiscreteResourceSpec)
|
||||
}
|
||||
if src.Extensions != nil {
|
||||
dst.Extensions = make(map[string]any, len(src.Extensions))
|
||||
@@ -2260,8 +2306,8 @@ func deriveDeepCopy_58(dst, src *GenericResource) {
|
||||
}
|
||||
}
|
||||
|
||||
// deriveDeepCopy_59 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_59(dst, src *DiscreteGenericResource) {
|
||||
// deriveDeepCopy_61 recursively copies the contents of src into dst.
|
||||
func deriveDeepCopy_61(dst, src *DiscreteGenericResource) {
|
||||
dst.Kind = src.Kind
|
||||
dst.Value = src.Value
|
||||
if src.Extensions != nil {
|
||||
|
99
vendor/github.com/compose-spec/compose-go/v2/types/project.go
generated
vendored
99
vendor/github.com/compose-spec/compose-go/v2/types/project.go
generated
vendored
@@ -21,8 +21,10 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
"github.com/compose-spec/compose-go/v2/dotenv"
|
||||
@@ -30,7 +32,6 @@ import (
|
||||
"github.com/compose-spec/compose-go/v2/utils"
|
||||
"github.com/distribution/reference"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -120,21 +121,21 @@ func (p *Project) ServicesWithBuild() []string {
|
||||
servicesBuild := p.Services.Filter(func(s ServiceConfig) bool {
|
||||
return s.Build != nil && s.Build.Context != ""
|
||||
})
|
||||
return maps.Keys(servicesBuild)
|
||||
return slices.Collect(maps.Keys(servicesBuild))
|
||||
}
|
||||
|
||||
func (p *Project) ServicesWithExtends() []string {
|
||||
servicesExtends := p.Services.Filter(func(s ServiceConfig) bool {
|
||||
return s.Extends != nil && *s.Extends != (ExtendsConfig{})
|
||||
})
|
||||
return maps.Keys(servicesExtends)
|
||||
return slices.Collect(maps.Keys(servicesExtends))
|
||||
}
|
||||
|
||||
func (p *Project) ServicesWithDependsOn() []string {
|
||||
servicesDependsOn := p.Services.Filter(func(s ServiceConfig) bool {
|
||||
return len(s.DependsOn) > 0
|
||||
})
|
||||
return maps.Keys(servicesDependsOn)
|
||||
return slices.Collect(maps.Keys(servicesDependsOn))
|
||||
}
|
||||
|
||||
func (p *Project) ServicesWithCapabilities() ([]string, []string, []string) {
|
||||
@@ -156,9 +157,10 @@ func (p *Project) ServicesWithCapabilities() ([]string, []string, []string) {
|
||||
capabilities = append(capabilities, service.Name)
|
||||
}
|
||||
for _, c := range d.Capabilities {
|
||||
if c == "gpu" {
|
||||
switch c {
|
||||
case "gpu":
|
||||
gpu = append(gpu, service.Name)
|
||||
} else if c == "tpu" {
|
||||
case "tpu":
|
||||
tpu = append(tpu, service.Name)
|
||||
}
|
||||
}
|
||||
@@ -188,16 +190,25 @@ func (p *Project) getServicesByNames(names ...string) (Services, []string) {
|
||||
if len(names) == 0 {
|
||||
return p.Services, nil
|
||||
}
|
||||
|
||||
services := Services{}
|
||||
var servicesNotFound []string
|
||||
for _, name := range names {
|
||||
service, ok := p.Services[name]
|
||||
if !ok {
|
||||
servicesNotFound = append(servicesNotFound, name)
|
||||
continue
|
||||
matched := false
|
||||
|
||||
for serviceName, service := range p.Services {
|
||||
match, _ := filepath.Match(name, serviceName)
|
||||
if match {
|
||||
services[serviceName] = service
|
||||
matched = true
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
servicesNotFound = append(servicesNotFound, name)
|
||||
}
|
||||
services[name] = service
|
||||
}
|
||||
|
||||
return services, servicesNotFound
|
||||
}
|
||||
|
||||
@@ -298,16 +309,25 @@ func (p *Project) withServices(names []string, fn ServiceFunc, seen map[string]b
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Project) GetDependentsForService(s ServiceConfig) []string {
|
||||
return utils.MapKeys(p.dependentsForService(s))
|
||||
func (p *Project) GetDependentsForService(s ServiceConfig, filter ...func(ServiceDependency) bool) []string {
|
||||
return utils.MapKeys(p.dependentsForService(s, filter...))
|
||||
}
|
||||
|
||||
func (p *Project) dependentsForService(s ServiceConfig) map[string]ServiceDependency {
|
||||
func (p *Project) dependentsForService(s ServiceConfig, filter ...func(ServiceDependency) bool) map[string]ServiceDependency {
|
||||
dependent := make(map[string]ServiceDependency)
|
||||
for _, service := range p.Services {
|
||||
for name, dependency := range service.DependsOn {
|
||||
if name == s.Name {
|
||||
dependent[service.Name] = dependency
|
||||
depends := true
|
||||
for _, f := range filter {
|
||||
if !f(dependency) {
|
||||
depends = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if depends {
|
||||
dependent[service.Name] = dependency
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -630,25 +650,25 @@ func (p Project) WithServicesEnvironmentResolved(discardEnvFiles bool) (*Project
|
||||
for i, service := range newProject.Services {
|
||||
service.Environment = service.Environment.Resolve(newProject.Environment.Resolve)
|
||||
|
||||
environment := MappingWithEquals{}
|
||||
// resolve variables based on other files we already parsed, + project's environment
|
||||
var resolve dotenv.LookupFn = func(s string) (string, bool) {
|
||||
v, ok := environment[s]
|
||||
if ok && v != nil {
|
||||
return *v, ok
|
||||
}
|
||||
return newProject.Environment.Resolve(s)
|
||||
}
|
||||
|
||||
environment := service.Environment.ToMapping()
|
||||
for _, envFile := range service.EnvFiles {
|
||||
vars, err := loadEnvFile(envFile, resolve)
|
||||
err := loadEnvFile(envFile, environment, func(k string) (string, bool) {
|
||||
// project.env has precedence doing interpolation
|
||||
if resolve, ok := p.Environment.Resolve(k); ok {
|
||||
return resolve, true
|
||||
}
|
||||
// then service.environment
|
||||
if s, ok := service.Environment[k]; ok {
|
||||
return *s, true
|
||||
}
|
||||
return "", false
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
environment.OverrideBy(vars.ToMappingWithEquals())
|
||||
}
|
||||
|
||||
service.Environment = environment.OverrideBy(service.Environment)
|
||||
service.Environment = environment.ToMappingWithEquals().OverrideBy(service.Environment)
|
||||
|
||||
if discardEnvFiles {
|
||||
service.EnvFiles = nil
|
||||
@@ -696,15 +716,16 @@ func (p Project) WithServicesLabelsResolved(discardLabelFiles bool) (*Project, e
|
||||
return newProject, nil
|
||||
}
|
||||
|
||||
func loadEnvFile(envFile EnvFile, resolve dotenv.LookupFn) (Mapping, error) {
|
||||
func loadEnvFile(envFile EnvFile, environment Mapping, resolve dotenv.LookupFn) 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 fmt.Errorf("env file %s not found: %w", envFile.Path, err)
|
||||
}
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
return loadMappingFile(envFile.Path, envFile.Format, resolve)
|
||||
err := loadMappingFile(envFile.Path, envFile.Format, environment, resolve)
|
||||
return err
|
||||
}
|
||||
|
||||
func loadLabelFile(labelFile string, resolve dotenv.LookupFn) (Mapping, error) {
|
||||
@@ -712,21 +733,19 @@ func loadLabelFile(labelFile string, resolve dotenv.LookupFn) (Mapping, error) {
|
||||
return nil, fmt.Errorf("label file %s not found: %w", labelFile, err)
|
||||
}
|
||||
|
||||
return loadMappingFile(labelFile, "", resolve)
|
||||
labels := Mapping{}
|
||||
err := loadMappingFile(labelFile, "", labels, resolve)
|
||||
return labels, err
|
||||
}
|
||||
|
||||
func loadMappingFile(path string, format string, resolve dotenv.LookupFn) (Mapping, error) {
|
||||
func loadMappingFile(path string, format string, vars Mapping, resolve dotenv.LookupFn) error {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileVars, err := dotenv.ParseWithFormat(file, path, resolve, format)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fileVars, nil
|
||||
return dotenv.ParseWithFormat(file, path, vars, resolve, format)
|
||||
}
|
||||
|
||||
func (p *Project) deepCopy() *Project {
|
||||
|
23
vendor/github.com/compose-spec/compose-go/v2/types/types.go
generated
vendored
23
vendor/github.com/compose-spec/compose-go/v2/types/types.go
generated
vendored
@@ -75,8 +75,8 @@ type ServiceConfig struct {
|
||||
// If set, overrides ENTRYPOINT from the image.
|
||||
//
|
||||
// Set to `[]` or an empty string to clear the entrypoint from the image.
|
||||
Entrypoint ShellCommand `yaml:"entrypoint,omitempty" json:"entrypoint"` // NOTE: we can NOT omitempty for JSON! see ShellCommand type for details.
|
||||
|
||||
Entrypoint ShellCommand `yaml:"entrypoint,omitempty" json:"entrypoint"` // NOTE: we can NOT omitempty for JSON! see ShellCommand type for details.
|
||||
Provider *ServiceProviderConfig `yaml:"provider,omitempty" json:"provider,omitempty"`
|
||||
Environment MappingWithEquals `yaml:"environment,omitempty" json:"environment,omitempty"`
|
||||
EnvFiles []EnvFile `yaml:"env_file,omitempty" json:"env_file,omitempty"`
|
||||
Expose StringOrNumberList `yaml:"expose,omitempty" json:"expose,omitempty"`
|
||||
@@ -142,6 +142,12 @@ type ServiceConfig struct {
|
||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||
}
|
||||
|
||||
type ServiceProviderConfig struct {
|
||||
Type string `yaml:"type,omitempty" json:"driver,omitempty"`
|
||||
Options Options `yaml:"options,omitempty" json:"options,omitempty"`
|
||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||
}
|
||||
|
||||
// MarshalYAML makes ServiceConfig implement yaml.Marshaller
|
||||
func (s ServiceConfig) MarshalYAML() (interface{}, error) {
|
||||
type t ServiceConfig
|
||||
@@ -535,6 +541,7 @@ type ServiceVolumeConfig struct {
|
||||
Bind *ServiceVolumeBind `yaml:"bind,omitempty" json:"bind,omitempty"`
|
||||
Volume *ServiceVolumeVolume `yaml:"volume,omitempty" json:"volume,omitempty"`
|
||||
Tmpfs *ServiceVolumeTmpfs `yaml:"tmpfs,omitempty" json:"tmpfs,omitempty"`
|
||||
Image *ServiceVolumeImage `yaml:"image,omitempty" json:"image,omitempty"`
|
||||
|
||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||
}
|
||||
@@ -569,6 +576,8 @@ const (
|
||||
VolumeTypeNamedPipe = "npipe"
|
||||
// VolumeTypeCluster is the type for mounting container storage interface (CSI) volumes
|
||||
VolumeTypeCluster = "cluster"
|
||||
// VolumeTypeImage is the tpe for mounting an image
|
||||
VolumeTypeImage = "image"
|
||||
|
||||
// SElinuxShared share the volume content
|
||||
SElinuxShared = "z"
|
||||
@@ -612,8 +621,9 @@ const (
|
||||
|
||||
// ServiceVolumeVolume are options for a service volume of type volume
|
||||
type ServiceVolumeVolume struct {
|
||||
NoCopy bool `yaml:"nocopy,omitempty" json:"nocopy,omitempty"`
|
||||
Subpath string `yaml:"subpath,omitempty" json:"subpath,omitempty"`
|
||||
Labels Mapping `yaml:"labels,omitempty" json:"labels,omitempty"`
|
||||
NoCopy bool `yaml:"nocopy,omitempty" json:"nocopy,omitempty"`
|
||||
Subpath string `yaml:"subpath,omitempty" json:"subpath,omitempty"`
|
||||
|
||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||
}
|
||||
@@ -627,6 +637,11 @@ type ServiceVolumeTmpfs struct {
|
||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||
}
|
||||
|
||||
type ServiceVolumeImage struct {
|
||||
SubPath string `yaml:"subpath,omitempty" json:"subpath,omitempty"`
|
||||
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
|
||||
}
|
||||
|
||||
type FileMode int64
|
||||
|
||||
// FileReferenceConfig for a reference to a swarm file object
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user