mirror of
https://github.com/linuxkit/linuxkit.git
synced 2026-03-25 17:10:27 +00:00
Compare commits
10 Commits
pkg-v1.3.0
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cfb70d3cc | ||
|
|
3751bb6d79 | ||
|
|
bdef7e865a | ||
|
|
666bbfdbd5 | ||
|
|
c766f572ce | ||
|
|
72a76e5b79 | ||
|
|
a85160e4d6 | ||
|
|
ccb0787e2a | ||
|
|
e0151386c8 | ||
|
|
4129cc7999 |
@@ -382,6 +382,38 @@ ARG all_proxy
|
||||
LinuxKit does not judge between lower-cased or upper-cased variants of these options, e.g. `http_proxy` vs `HTTP_PROXY`,
|
||||
as `docker build` does not either. It just passes them through "as-is".
|
||||
|
||||
### Environment Variables
|
||||
|
||||
The following environment variables can be used to configure `linuxkit` without
|
||||
modifying command-line invocations — useful for CI/CD runners and shared build
|
||||
scripts. CLI flags always take precedence over env vars, which take precedence
|
||||
over built-in defaults.
|
||||
|
||||
| Variable | Equivalent flag | Scope | Description |
|
||||
|---|---|---|---|
|
||||
| `LINUXKIT_MIRROR` | `--mirror` | All commands | Space- or comma-separated list of mirror specs, each in `[<registry>=]<url>` format (same as `--mirror`). E.g. `LINUXKIT_MIRROR=docker.io=http://mymirror.local` |
|
||||
| `LINUXKIT_PKG_ORG` | `--org` | `pkg` subcommands | Override the registry organisation used when tagging and pushing packages. E.g. `LINUXKIT_PKG_ORG=myorg/lfedge` |
|
||||
| `LINUXKIT_BUILDER_IMAGE` | `--builder-image` | `pkg build` | buildkit container image to use. Useful when the builder image must come from an internal mirror. |
|
||||
| `LINUXKIT_BUILDER_CONFIG` | `--builder-config` | `pkg build` | Path to a buildkit `config.toml` file. The primary way to configure buildkit's own registry mirrors for `FROM` pulls inside Dockerfiles. |
|
||||
| `LINUXKIT_BUILDER_NAME` | `--builder-name` | `pkg build` | Name of the buildkit builder container. |
|
||||
| `LINUXKIT_BUILDERS` | `--builders` | `pkg build` | Platform-to-builder-context mapping; see [Providing native builder nodes](#providing-native-builder-nodes). |
|
||||
| `LINUXKIT_CACHE` | `--cache` | All commands | Path to the linuxkit OCI image cache directory (default `~/.linuxkit/cache`). |
|
||||
|
||||
#### Registry mirrors in CI
|
||||
|
||||
There are two layers of registry access in `linuxkit pkg build`, each requiring
|
||||
its own mirror configuration:
|
||||
|
||||
1. **linuxkit's own pulls** (cache lookups, `show-tag`, `cache pull`, etc.) —
|
||||
configure via `LINUXKIT_MIRROR` or `--mirror`.
|
||||
|
||||
2. **buildkit's pulls** (`FROM` and `COPY --from` inside Dockerfiles) —
|
||||
buildkit has its own registry client. Configure its mirrors via a
|
||||
`config.toml` file passed through `LINUXKIT_BUILDER_CONFIG` or
|
||||
`--builder-config`. See the
|
||||
[buildkit registry configuration docs](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md)
|
||||
for the file format.
|
||||
|
||||
## Build Args
|
||||
|
||||
`linuxkit` does not support passing random CLI flags for build arguments when building packages.
|
||||
|
||||
@@ -58,6 +58,12 @@ func newCmd() *cobra.Command {
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
readConfig()
|
||||
|
||||
// prepend mirrors from env var so CLI flags take precedence (last SetProxy call wins)
|
||||
if envMirrors := os.Getenv(envVarMirror); envMirrors != "" {
|
||||
envList := strings.FieldsFunc(envMirrors, func(r rune) bool { return r == ',' || r == ' ' })
|
||||
mirrorsRaw = append(envList, mirrorsRaw...)
|
||||
}
|
||||
|
||||
// convert the provided mirrors to a map
|
||||
for _, m := range mirrorsRaw {
|
||||
if m == "" {
|
||||
@@ -115,7 +121,7 @@ func newCmd() *cobra.Command {
|
||||
cmd.AddCommand(versionCmd())
|
||||
|
||||
cmd.PersistentFlags().StringVar(&cacheDir, "cache", defaultLinuxkitCache(), fmt.Sprintf("Directory for caching and finding cached image, overrides env var %s", envVarCacheDir))
|
||||
cmd.PersistentFlags().StringArrayVar(&mirrorsRaw, "mirror", nil, "Mirror to use for pulling images, format is <registry>=<mirror>, e.g. docker.io=http://mymirror.io, or just http://mymirror.io for all not otherwise specified; must include protocol. Can be provided multiple times.")
|
||||
cmd.PersistentFlags().StringArrayVar(&mirrorsRaw, "mirror", nil, fmt.Sprintf("Mirror to use for pulling images, format is <registry>=<mirror>, e.g. docker.io=http://mymirror.io, or just http://mymirror.io for all not otherwise specified; must include protocol. Can be provided multiple times. Also read from env var %s (space/comma-separated list); CLI flags take precedence.", envVarMirror))
|
||||
cmd.PersistentFlags().StringArrayVar(&certFiles, "cert-file", nil, "Path to certificate files to use for pulling images, can be provided multiple times. Will augment system-provided certs.")
|
||||
cmd.PersistentFlags().BoolVarP(&flagQuiet, "quiet", "q", false, "Quiet execution")
|
||||
cmd.PersistentFlags().IntVarP(&flagVerbose, flagVerboseName, "v", 1, "Verbosity of logging: 0 = quiet, 1 = info, 2 = debug, 3 = trace. Default is info. Setting it explicitly will create structured logging lines.")
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
module github.com/linuxkit/linuxkit/src/cmd/linuxkit
|
||||
|
||||
go 1.24.2
|
||||
go 1.24.3
|
||||
|
||||
toolchain go1.24.12
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go v56.3.0+incompatible
|
||||
@@ -11,7 +13,7 @@ require (
|
||||
github.com/Microsoft/go-winio v0.6.2
|
||||
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681
|
||||
github.com/aws/aws-sdk-go v1.44.82
|
||||
github.com/docker/cli v28.2.2+incompatible
|
||||
github.com/docker/cli v28.5.0+incompatible
|
||||
github.com/docker/docker v28.2.2+incompatible
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/google/go-containerregistry v0.20.3
|
||||
@@ -19,7 +21,7 @@ require (
|
||||
github.com/gophercloud/gophercloud v0.1.0
|
||||
github.com/gophercloud/utils v0.0.0-20181029231510-34f5991525d1
|
||||
github.com/klauspost/pgzip v1.2.5
|
||||
github.com/moby/buildkit v0.23.1
|
||||
github.com/moby/buildkit v0.26.3
|
||||
github.com/moby/hyperkit v0.0.0-20180416161519-d65b09c1c28a
|
||||
//github.com/moby/moby v20.10.3-0.20220728162118-71cb54cec41e+incompatible // indirect
|
||||
github.com/moby/term v0.5.2
|
||||
@@ -33,36 +35,36 @@ require (
|
||||
github.com/rn/iso9660wrap v0.0.0-20171120145750-baf8d62ad315
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/surma/gocpio v1.0.2-0.20160926205914-fcb68777e7dc
|
||||
github.com/vmware/govmomi v0.20.3
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/oauth2 v0.27.0
|
||||
golang.org/x/sync v0.14.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/term v0.31.0
|
||||
golang.org/x/crypto v0.42.0
|
||||
golang.org/x/net v0.44.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.17.0
|
||||
golang.org/x/sys v0.37.0
|
||||
golang.org/x/term v0.35.0
|
||||
google.golang.org/api v0.149.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Code-Hex/vz/v3 v3.0.0
|
||||
github.com/containerd/containerd/v2 v2.1.3
|
||||
github.com/containerd/platforms v1.0.0-rc.1
|
||||
github.com/containerd/containerd/v2 v2.2.0
|
||||
github.com/containerd/platforms v1.0.0-rc.2
|
||||
github.com/docker/buildx v0.21.1
|
||||
github.com/equinix/equinix-sdk-go v0.42.0
|
||||
github.com/hashicorp/go-version v1.7.0
|
||||
github.com/in-toto/in-toto-golang v0.9.0
|
||||
github.com/moby/sys/capability v0.3.0
|
||||
github.com/moby/sys/capability v0.4.0
|
||||
github.com/spdx/tools-golang v0.5.5
|
||||
github.com/spf13/cobra v1.8.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.1-0.20210115164004-c0fe8b0fea3d+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
@@ -70,14 +72,14 @@ require (
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/containerd/console v1.0.5 // indirect
|
||||
github.com/containerd/containerd/api v1.9.0 // indirect
|
||||
github.com/containerd/containerd/api v1.10.0 // indirect
|
||||
github.com/containerd/continuity v0.4.5 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.17.0 // indirect
|
||||
github.com/containerd/ttrpc v1.2.7 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
||||
github.com/creack/goselect v0.0.0-20180501195510-58854f77ee8d // indirect
|
||||
@@ -89,26 +91,24 @@ require (
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/gofrs/flock v0.13.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/compress v1.18.1 // indirect
|
||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
@@ -127,7 +127,7 @@ require (
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
|
||||
github.com/shibumi/go-pathspec v1.3.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.8.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
@@ -136,28 +136,28 @@ require (
|
||||
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 // indirect
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
|
||||
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect
|
||||
github.com/vbatts/tar-split v0.12.1 // indirect
|
||||
github.com/vbatts/tar-split v0.12.2 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect
|
||||
google.golang.org/grpc v1.72.2 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/grpc v1.76.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
|
||||
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||
github.com/Azure/azure-sdk-for-go v56.3.0+incompatible h1:DmhwMrUIvpeoTDiWRDtNHqelNUd3Og8JCkrLHQK795c=
|
||||
@@ -31,8 +31,8 @@ github.com/Code-Hex/vz/v3 v3.0.0 h1:UuYAZz8NF8n+R4MLfn/lpUlepgzZ8BlhKtioQ+q9LXk=
|
||||
github.com/Code-Hex/vz/v3 v3.0.0/go.mod h1:+xPQOXVzNaZ4OeIIhlJFumtbFhsvRfqKwX7wuZS4dFA=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
|
||||
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
|
||||
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
|
||||
github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boSWAHyK/tNAaYZL0c=
|
||||
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681 h1:JS2rl38kZmHgWa0xINSaSYH0Whtvem64/4+Ef0+Y5pE=
|
||||
github.com/ScaleFT/sshkeys v0.0.0-20181112160850-82451a803681/go.mod h1:WfDateMPQ/55dPbZRp5Zxrux5WiEaHsjk9puUhz0KgY=
|
||||
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
|
||||
@@ -43,8 +43,8 @@ github.com/aws/aws-sdk-go v1.44.82 h1:Miji7nHIMxTWfa831nZf8XAcMWGLaT+PvsS6CdbMG7
|
||||
github.com/aws/aws-sdk-go v1.44.82/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@@ -52,14 +52,14 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
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/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/containerd/cgroups/v3 v3.1.0 h1:azxYVj+91ZgSnIBp2eI3k9y2iYQSR/ZQIgh9vKO+HSY=
|
||||
github.com/containerd/cgroups/v3 v3.1.0/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
|
||||
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
|
||||
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
|
||||
github.com/containerd/containerd/v2 v2.1.3 h1:eMD2SLcIQPdMlnlNF6fatlrlRLAeDaiGPGwmRKLZKNs=
|
||||
github.com/containerd/containerd/v2 v2.1.3/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
||||
github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
|
||||
github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
|
||||
github.com/containerd/containerd/v2 v2.2.0 h1:K7TqcXy+LnFmZaui2DgHsnp2gAHhVNWYaHlx7HXfys8=
|
||||
github.com/containerd/containerd/v2 v2.2.0/go.mod h1:YCMjKjA4ZA7egdHNi3/93bJR1+2oniYlnS+c0N62HdE=
|
||||
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=
|
||||
@@ -70,14 +70,14 @@ github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY
|
||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/nydus-snapshotter v0.15.2 h1:qsHI4M+Wwrf6Jr4eBqhNx8qh+YU0dSiJ+WPmcLFWNcg=
|
||||
github.com/containerd/nydus-snapshotter v0.15.2/go.mod h1:FfwH2KBkNYoisK/e+KsmNr7xTU53DmnavQHMFOcXwfM=
|
||||
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
|
||||
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
|
||||
github.com/containerd/nydus-snapshotter v0.15.4 h1:l59kGRVMtwMLDLh322HsWhEsBCkRKMkGWYV5vBeLYCE=
|
||||
github.com/containerd/nydus-snapshotter v0.15.4/go.mod h1:eRJqnxQDr48HNop15kZdLZpFF5B6vf6Q11Aq1K0E4Ms=
|
||||
github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
|
||||
github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
|
||||
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
|
||||
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.17.0 h1:+TyQIsR/zSFI1Rm31EQBwpAA1ovYgIKHy7kctL3sLcE=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.17.0/go.mod h1:s06tWAiJcXQo9/8AReBCIo/QxcXFZ2n4qfsRnpl71SM=
|
||||
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
|
||||
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
|
||||
@@ -98,8 +98,8 @@ github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/buildx v0.21.1 h1:YjV2k6CsSDbkDTOMsjARUIrj2xv+zZR+M2dtrRyzXhg=
|
||||
github.com/docker/buildx v0.21.1/go.mod h1:8V4UMnlKsaGYwz83BygmIbJIFEAYGHT6KAv8akDZmqo=
|
||||
github.com/docker/cli v28.2.2+incompatible h1:qzx5BNUDFqlvyq4AHzdNB7gSyVTmU4cgsyN9SdInc1A=
|
||||
github.com/docker/cli v28.2.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v28.5.0+incompatible h1:crVqLrtKsrhC9c00ythRx435H8LiQnUKRtJLRR+Auxk=
|
||||
github.com/docker/cli v28.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
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.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw=
|
||||
@@ -125,12 +125,12 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
|
||||
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
|
||||
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
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=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
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/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
|
||||
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
@@ -139,8 +139,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
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/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -184,17 +184,12 @@ github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25d
|
||||
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||
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.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
||||
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-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/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
|
||||
@@ -209,8 +204,8 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
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/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
|
||||
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -229,8 +224,8 @@ github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b h1:9+ke9YJ9KGWw5AN
|
||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
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/moby/buildkit v0.23.1 h1:CZtFmPRF+IFG1C8QfPnktGO1Dzzt5JSwtQ5eDqIh+ag=
|
||||
github.com/moby/buildkit v0.23.1/go.mod h1:keNXljNmKX1T0AtM0bMObc8OV6mA9cOuquVbPcRpU/Y=
|
||||
github.com/moby/buildkit v0.26.3 h1:D+ruZVAk/3ipRq5XRxBH9/DIFpRjSlTtMbghT5gQP9g=
|
||||
github.com/moby/buildkit v0.26.3/go.mod h1:4T4wJzQS4kYWIfFRjsbJry4QoxDBjK+UGOEOs1izL7w=
|
||||
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/hyperkit v0.0.0-20180416161519-d65b09c1c28a h1:hExo7kltIidoitYnXsnqfvkJXG3YEMbHuQbf9nOMvow=
|
||||
@@ -241,8 +236,8 @@ github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkV
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
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/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
|
||||
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
|
||||
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
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=
|
||||
@@ -281,15 +276,15 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgm
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
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 v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/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.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
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/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/radu-matei/azure-sdk-for-go v5.0.0-beta.0.20161118192335-3b1282355199+incompatible h1:lh3lhjZXXLv7/8cJKQQtgWLJnszuN1xYD9QHTf/dKgE=
|
||||
github.com/radu-matei/azure-sdk-for-go v5.0.0-beta.0.20161118192335-3b1282355199+incompatible/go.mod h1:dK8sDtj2CPkz+pRG4nNF7+WzmyYjtJwfYrZApxB+zFg=
|
||||
github.com/radu-matei/azure-vhd-utils v0.0.0-20170531165126-e52754d5569d h1:9aQ38JpJEOfipvLKM/NZ2MWxpZIlZgR+6AjotW+a2T8=
|
||||
@@ -298,13 +293,13 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rn/iso9660wrap v0.0.0-20171120145750-baf8d62ad315 h1:DjbO/+j3556fy07xoEM/MyLYN3WwwYyt4dHRC5U+KN8=
|
||||
github.com/rn/iso9660wrap v0.0.0-20171120145750-baf8d62ad315/go.mod h1:qrZfINtl+sTGgS3elQWqWsD2Ke4Il5jDzBr2Q+lzuuE=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6 h1:C1/pvkxkGN/H03mDxLzItaceYJDBk1HdClgR15suAzI=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.6/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.6.0 h1:T65atpAVCJQK14UA57LMdZGpHi4QYSH/9FZyNGqMYIA=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.6.0/go.mod h1:8Mtpo9JKks/qhPG4HGZ2LGMvrPbzuxwfz/f/zLfEWkk=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL5qTdn9lR8XKHf4RUyG1Sx3g=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU=
|
||||
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.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
@@ -331,8 +326,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/surma/gocpio v1.0.2-0.20160926205914-fcb68777e7dc h1:iA3Eg1OVd2o0M4M+0PBsBBssMz98L8CUH7x0xVkuyUA=
|
||||
github.com/surma/gocpio v1.0.2-0.20160926205914-fcb68777e7dc/go.mod h1:zaLNaN+EDnfSnNdWPJJf9OZxWF817w5dt8JNzF9LCVI=
|
||||
github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c=
|
||||
@@ -347,8 +342,8 @@ github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
|
||||
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw=
|
||||
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
|
||||
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
|
||||
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=
|
||||
github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/vmware/govmomi v0.20.3 h1:gpw/0Ku+6RgF3jsi7fnCLmlcikBHfKBCUcu1qgc16OU=
|
||||
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
@@ -362,52 +357,54 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0 h1:4BZHA+B1wXEQoGNHxW8mURaLhcdGwvRnmhGbm+odRbc=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.56.0/go.mod h1:3qi2EEwMgB4xnKgPLqsDP3j9qxnHDZeHsnAxfjQqTko=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0 h1:FZ6ei8GFW7kyPYdxJaV2rgI6M+4tvZzhYsQ2wgyVC08=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.31.0/go.mod h1:MdEu/mC6j3D+tTEfvI15b5Ci2Fn7NneJ71YMoiS3tpI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.61.0 h1:lREC4C0ilyP4WibDhQ7Gg2ygAQFP8oR07Fst/5cafwI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.61.0/go.mod h1:HfvuU0kW9HewH14VCOLImqKvUgONodURG7Alj/IrnGI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 h1:vl9obrcoWVKp/lwl8tRE33853I8Xru9HFbw/skNeLs8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0/go.mod h1:GAXRxmLJcVM3u22IjTg74zWBrRCKq8BnOqUVLodpcpw=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
|
||||
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
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/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -420,18 +417,18 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
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/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
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-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=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -445,20 +442,20 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -471,6 +468,8 @@ 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=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY=
|
||||
google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
@@ -478,17 +477,17 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
|
||||
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -498,8 +497,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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=
|
||||
|
||||
@@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/linuxkit/linuxkit/src/cmd/linuxkit/pkglib"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -74,6 +76,8 @@ func pkgCmd() *cobra.Command {
|
||||
}
|
||||
if cmd.Flags().Changed("org") {
|
||||
pkglibConfig.Org = &argOrg
|
||||
} else if org := os.Getenv(envVarPkgOrg); org != "" {
|
||||
pkglibConfig.Org = &org
|
||||
}
|
||||
if cmd.Flags().Changed("tag") {
|
||||
pkglibConfig.Tag = tag
|
||||
@@ -100,7 +104,7 @@ func pkgCmd() *cobra.Command {
|
||||
cmd.PersistentFlags().BoolVar(&argNoNetwork, "nonetwork", !piBase.Network, "Disallow network use during build")
|
||||
cmd.PersistentFlags().BoolVar(&argNetwork, "network", piBase.Network, "Allow network use during build")
|
||||
|
||||
cmd.PersistentFlags().StringVar(&argOrg, "org", piBase.Org, "Override the hub org")
|
||||
cmd.PersistentFlags().StringVar(&argOrg, "org", piBase.Org, fmt.Sprintf("Override the hub org. Also read from env var %s; CLI flag takes precedence.", envVarPkgOrg))
|
||||
cmd.PersistentFlags().StringVar(&buildYML, "build-yml", defaultPkgBuildYML, "Override the name of the yml file")
|
||||
cmd.PersistentFlags().StringVar(&hash, "hash", "", "Override the image hash (default is to query git for the package's tree-sh)")
|
||||
cmd.PersistentFlags().StringVar(&tag, "tag", piBase.Tag, "Override the tag using fixed strings and/or text templates. Acceptable are .Hash for the hash")
|
||||
|
||||
@@ -16,7 +16,12 @@ import (
|
||||
const (
|
||||
buildersEnvVar = "LINUXKIT_BUILDERS"
|
||||
envVarCacheDir = "LINUXKIT_CACHE"
|
||||
defaultBuilderImage = "moby/buildkit:v0.23.1"
|
||||
envVarBuilderName = "LINUXKIT_BUILDER_NAME"
|
||||
envVarBuilderImage = "LINUXKIT_BUILDER_IMAGE"
|
||||
envVarBuilderConfig = "LINUXKIT_BUILDER_CONFIG"
|
||||
envVarMirror = "LINUXKIT_MIRROR"
|
||||
envVarPkgOrg = "LINUXKIT_PKG_ORG"
|
||||
defaultBuilderImage = "moby/buildkit:v0.26.3"
|
||||
)
|
||||
|
||||
// some logic clarification:
|
||||
@@ -40,8 +45,9 @@ func pkgBuildCmd() *cobra.Command {
|
||||
platforms string
|
||||
skipPlatforms string
|
||||
builders string
|
||||
builderImage string
|
||||
builderConfig string
|
||||
builderName = flagOverEnvVarOverDefaultString{def: pkglib.DefaultBuilderName(), envVar: envVarBuilderName}
|
||||
builderImage = flagOverEnvVarOverDefaultString{def: defaultBuilderImage, envVar: envVarBuilderImage}
|
||||
builderConfig = flagOverEnvVarOverDefaultString{def: "", envVar: envVarBuilderConfig}
|
||||
builderRestart bool
|
||||
preCacheImages bool
|
||||
release string
|
||||
@@ -191,16 +197,19 @@ func pkgBuildCmd() *cobra.Command {
|
||||
if err != nil {
|
||||
return fmt.Errorf("error in --builders flag: %w", err)
|
||||
}
|
||||
if builderConfig != "" {
|
||||
if _, err := os.Stat(builderConfig); err != nil {
|
||||
return fmt.Errorf("error reading builder config file %s: %w", builderConfig, err)
|
||||
if builderConfig.String() != "" {
|
||||
if _, err := os.Stat(builderConfig.String()); err != nil {
|
||||
return fmt.Errorf("error reading builder config file %s: %w", builderConfig.String(), err)
|
||||
}
|
||||
opts = append(opts, pkglib.WithBuildBuilderConfig(builderConfig))
|
||||
}
|
||||
|
||||
opts = append(opts, pkglib.WithBuildBuilders(buildersMap))
|
||||
opts = append(opts, pkglib.WithBuildBuilderImage(builderImage))
|
||||
opts = append(opts, pkglib.WithBuildBuilderRestart(builderRestart))
|
||||
opts = append(opts, pkglib.WithBuildBuilderConfig(pkglib.BuilderConfig{
|
||||
Name: builderName.String(),
|
||||
Image: builderImage.String(),
|
||||
ConfigPath: builderConfig.String(),
|
||||
Restart: builderRestart,
|
||||
}))
|
||||
opts = append(opts, pkglib.WithProgress(progress))
|
||||
if len(ssh) > 0 {
|
||||
opts = append(opts, pkglib.WithSSH(ssh))
|
||||
@@ -303,8 +312,9 @@ func pkgBuildCmd() *cobra.Command {
|
||||
cmd.Flags().StringVar(&platforms, "platforms", "", "Which platforms to build for, defaults to all of those for which the package can be built")
|
||||
cmd.Flags().StringVar(&skipPlatforms, "skip-platforms", "", "Platforms that should be skipped, even if present in build.yml")
|
||||
cmd.Flags().StringVar(&builders, "builders", "", "Which builders to use for which platforms, e.g. linux/arm64=docker-context-arm64, overrides defaults and environment variables, see https://github.com/linuxkit/linuxkit/blob/master/docs/packages.md#Providing-native-builder-nodes")
|
||||
cmd.Flags().StringVar(&builderImage, "builder-image", defaultBuilderImage, "buildkit builder container image to use")
|
||||
cmd.Flags().StringVar(&builderConfig, "builder-config", "", "path to buildkit builder config.toml file to use, overrides the default config.toml in the builder image. When provided, copied over into builder, along with all certs. Use paths for certificates relative to your local host, they will be adjusted on copying into the container. USE WITH CAUTION")
|
||||
cmd.Flags().Var(&builderName, "builder-name", fmt.Sprintf("Name of the buildkit builder container, default: %s, overrides env var %s", pkglib.DefaultBuilderName(), envVarBuilderName))
|
||||
cmd.Flags().Var(&builderImage, "builder-image", fmt.Sprintf("buildkit builder container image to use, overrides env var %s", envVarBuilderImage))
|
||||
cmd.Flags().Var(&builderConfig, "builder-config", fmt.Sprintf("path to buildkit builder config.toml file to use, overrides the default config.toml in the builder image. When provided, copied over into builder, along with all certs. Use paths for certificates relative to your local host, they will be adjusted on copying into the container. USE WITH CAUTION. Overrides env var %s", envVarBuilderConfig))
|
||||
cmd.Flags().BoolVar(&builderRestart, "builder-restart", false, "force restarting builder, even if container with correct name and image exists")
|
||||
cmd.Flags().BoolVar(&preCacheImages, "precache-images", false, "download all referenced images in the Dockerfile to the linuxkit cache before building, thus referencing the local cache instead of pulling from the registry; this is useful for handling mirrors and special connections")
|
||||
cmd.Flags().Var(&cacheDir, "cache", fmt.Sprintf("Directory for caching and finding cached image, overrides env var %s", envVarCacheDir))
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
func pkgBuilderCmd() *cobra.Command {
|
||||
var (
|
||||
builders string
|
||||
builderName = flagOverEnvVarOverDefaultString{def: pkglib.DefaultBuilderName(), envVar: envVarBuilderName}
|
||||
platforms string
|
||||
builderImage string
|
||||
builderConfigPath string
|
||||
@@ -39,13 +40,18 @@ func pkgBuilderCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
platformsToClean := strings.Split(platforms, ",")
|
||||
bc := pkglib.BuilderConfig{
|
||||
Name: builderName.String(),
|
||||
Image: builderImage,
|
||||
ConfigPath: builderConfigPath,
|
||||
}
|
||||
switch command {
|
||||
case "du":
|
||||
if err := pkglib.DiskUsage(buildersMap, builderImage, builderConfigPath, platformsToClean, verbose); err != nil {
|
||||
if err := pkglib.DiskUsage(buildersMap, bc, platformsToClean, verbose); err != nil {
|
||||
return fmt.Errorf("unable to print disk usage of builder: %w", err)
|
||||
}
|
||||
case "prune":
|
||||
if err := pkglib.PruneBuilder(buildersMap, builderImage, builderConfigPath, platformsToClean, verbose); err != nil {
|
||||
if err := pkglib.PruneBuilder(buildersMap, bc, platformsToClean, verbose); err != nil {
|
||||
return fmt.Errorf("unable to prune builder: %w", err)
|
||||
}
|
||||
default:
|
||||
@@ -56,6 +62,7 @@ func pkgBuilderCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVar(&builders, "builders", "", "Which builders to use for which platforms, e.g. linux/arm64=docker-context-arm64, overrides defaults and environment variables, see https://github.com/linuxkit/linuxkit/blob/master/docs/packages.md#Providing-native-builder-nodes")
|
||||
cmd.PersistentFlags().Var(&builderName, "builder-name", fmt.Sprintf("Name of the buildkit builder container, default: %s, overrides env var %s", pkglib.DefaultBuilderName(), envVarBuilderName))
|
||||
cmd.PersistentFlags().StringVar(&platforms, "platforms", fmt.Sprintf("linux/%s", runtime.GOARCH), "Which platforms we built images for")
|
||||
cmd.PersistentFlags().StringVar(&builderImage, "builder-image", defaultBuilderImage, "buildkit builder container image to use")
|
||||
cmd.Flags().StringVar(&builderConfigPath, "builder-config", "", "path to buildkit builder config.toml file to use, overrides the default config.toml in the builder image; USE WITH CAUTION")
|
||||
|
||||
@@ -24,32 +24,30 @@ import (
|
||||
)
|
||||
|
||||
type buildOpts struct {
|
||||
skipBuild bool
|
||||
force bool
|
||||
pull bool
|
||||
ignoreCache bool
|
||||
push bool
|
||||
dryRun bool
|
||||
preCacheImages bool
|
||||
release string
|
||||
manifest bool
|
||||
targetDocker bool
|
||||
cacheDir string
|
||||
cacheProvider spec.CacheProvider
|
||||
platforms []imagespec.Platform
|
||||
builders map[string]string
|
||||
runner DockerRunner
|
||||
writer io.Writer
|
||||
builderImage string
|
||||
builderConfigPath string
|
||||
builderRestart bool
|
||||
sbomScan bool
|
||||
sbomScannerImage string
|
||||
dockerfile string
|
||||
buildArgs []string
|
||||
progress string
|
||||
ssh []string
|
||||
registryAuth map[string]spec.RegistryAuth
|
||||
skipBuild bool
|
||||
force bool
|
||||
pull bool
|
||||
ignoreCache bool
|
||||
push bool
|
||||
dryRun bool
|
||||
preCacheImages bool
|
||||
release string
|
||||
manifest bool
|
||||
targetDocker bool
|
||||
cacheDir string
|
||||
cacheProvider spec.CacheProvider
|
||||
platforms []imagespec.Platform
|
||||
builders map[string]string
|
||||
runner DockerRunner
|
||||
writer io.Writer
|
||||
builderConfig BuilderConfig
|
||||
sbomScan bool
|
||||
sbomScannerImage string
|
||||
dockerfile string
|
||||
buildArgs []string
|
||||
progress string
|
||||
ssh []string
|
||||
registryAuth map[string]spec.RegistryAuth
|
||||
}
|
||||
|
||||
// BuildOpt allows callers to specify options to Build
|
||||
@@ -160,26 +158,10 @@ func WithBuildOutputWriter(w io.Writer) BuildOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithBuildBuilderImage set the builder container image to use.
|
||||
func WithBuildBuilderImage(image string) BuildOpt {
|
||||
// WithBuildBuilderConfig set the builder configuration to use.
|
||||
func WithBuildBuilderConfig(bc BuilderConfig) BuildOpt {
|
||||
return func(bo *buildOpts) error {
|
||||
bo.builderImage = image
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithBuildBuilderConfig set the contents of the
|
||||
func WithBuildBuilderConfig(builderConfigPath string) BuildOpt {
|
||||
return func(bo *buildOpts) error {
|
||||
bo.builderConfigPath = builderConfigPath
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithBuildBuilderRestart restart the builder container even if it already is running with the correct image version
|
||||
func WithBuildBuilderRestart(restart bool) BuildOpt {
|
||||
return func(bo *buildOpts) error {
|
||||
bo.builderRestart = restart
|
||||
bo.builderConfig = bc
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -322,7 +304,7 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
||||
case d == nil && bo.dryRun:
|
||||
d = NewDockerDryRunner()
|
||||
case d == nil:
|
||||
d = NewDockerRunner(p.cache)
|
||||
d = NewDockerRunner(p.cache, bo.builderConfig)
|
||||
}
|
||||
|
||||
c := bo.cacheProvider
|
||||
@@ -492,7 +474,7 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
||||
|
||||
// build for each arch and save in the linuxkit cache
|
||||
for _, platform := range platformsToBuild {
|
||||
builtDescs, err := p.buildArch(ctx, d, c, bo.builderImage, bo.builderConfigPath, platform.Architecture, bo.builderRestart, writer, bo, imageBuildOpts)
|
||||
builtDescs, err := p.buildArch(ctx, d, c, platform.Architecture, writer, bo, imageBuildOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error building for arch %s: %v", platform.Architecture, err)
|
||||
}
|
||||
@@ -555,18 +537,11 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// we only will push if one of these is true:
|
||||
// - we had at least one platform to build
|
||||
// - we found an image in local cache
|
||||
// if neither is true, there is nothing to push
|
||||
|
||||
// determine if we should skip pushing the default tag (no build and no local cache)
|
||||
skipDefaultPush := false
|
||||
if len(platformsToBuild) == 0 {
|
||||
// if we did not yet find the image in local cache,
|
||||
// check, in case we have it and would need to push.
|
||||
// If we did not build it because we were not requested to do so,
|
||||
// then we might not know we have it in local cache.
|
||||
// if we did not yet find the image in local cache, recheck
|
||||
if !imageInLocalCache {
|
||||
// we need this to know whether or not we might push
|
||||
for _, platform := range bo.platforms {
|
||||
exists, err := c.ImageInCache(&ref, "", platform.Architecture)
|
||||
if err == nil && exists {
|
||||
@@ -577,17 +552,22 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
||||
}
|
||||
if !imageInLocalCache {
|
||||
_, _ = fmt.Fprintf(writer, "No new platforms to push, skipping.\n")
|
||||
return nil
|
||||
if bo.release == "" {
|
||||
return nil
|
||||
}
|
||||
skipDefaultPush = true
|
||||
}
|
||||
}
|
||||
|
||||
if p.dirty {
|
||||
return fmt.Errorf("build complete, refusing to push dirty package")
|
||||
}
|
||||
|
||||
// push the manifest
|
||||
if err := c.Push(p.FullTag(), "", bo.manifest, true); err != nil {
|
||||
return err
|
||||
// push the manifest for the default tag if needed
|
||||
if !skipDefaultPush {
|
||||
if err := c.Push(p.FullTag(), "", bo.manifest, true); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, _ = fmt.Fprintf(writer, "Skipping push of default tag %q\n", p.FullTag())
|
||||
}
|
||||
|
||||
if bo.release == "" {
|
||||
@@ -608,7 +588,8 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
||||
if err := c.DescriptorWrite(fullRelTag, *desc); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.Push(fullRelTag, "", bo.manifest, true); err != nil {
|
||||
// push the release tag without overriding existing (skip if already present)
|
||||
if err := c.Push(fullRelTag, "", bo.manifest, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -646,7 +627,7 @@ func (p Pkg) Build(bos ...BuildOpt) error {
|
||||
// C - manifest, saved in cache as is, referenced by the index (E), and returned as a descriptor
|
||||
// D - attestations (if any), saved in cache as is, referenced by the index (E), and returned as a descriptor
|
||||
// E - index, saved in cache as is, stored in cache as tag "image:tag-arch", *not* returned as a descriptor
|
||||
func (p Pkg) buildArch(ctx context.Context, d DockerRunner, c spec.CacheProvider, builderImage, builderConfigPath, arch string, restart bool, writer io.Writer, bo buildOpts, imageBuildOpts spec.ImageBuildOptions) ([]registry.Descriptor, error) {
|
||||
func (p Pkg) buildArch(ctx context.Context, d DockerRunner, c spec.CacheProvider, arch string, writer io.Writer, bo buildOpts, imageBuildOpts spec.ImageBuildOptions) ([]registry.Descriptor, error) {
|
||||
var (
|
||||
tagArch string
|
||||
tag = p.FullTag()
|
||||
@@ -675,8 +656,8 @@ func (p Pkg) buildArch(ctx context.Context, d DockerRunner, c spec.CacheProvider
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// find the desired builder
|
||||
builderName := getBuilderForPlatform(arch, bo.builders)
|
||||
// find the desired docker context for the builder
|
||||
dockerContext := getBuilderForPlatform(arch, bo.builders)
|
||||
|
||||
// set the target
|
||||
var (
|
||||
@@ -715,7 +696,7 @@ func (p Pkg) buildArch(ctx context.Context, d DockerRunner, c spec.CacheProvider
|
||||
|
||||
imageBuildOpts.Dockerfile = bo.dockerfile
|
||||
|
||||
if err := d.Build(ctx, tagArch, p.path, builderName, builderImage, builderConfigPath, platform, restart, bo.preCacheImages, passCache, buildCtx.Reader(), stdout, bo.sbomScan, bo.sbomScannerImage, bo.progress, imageBuildOpts); err != nil {
|
||||
if err := d.Build(ctx, tagArch, p.path, dockerContext, platform, bo.preCacheImages, passCache, buildCtx.Reader(), stdout, bo.sbomScan, bo.sbomScannerImage, bo.progress, imageBuildOpts); err != nil {
|
||||
stdoutCloser()
|
||||
if strings.Contains(err.Error(), "executor failed running [/dev/.buildkit_qemu_emulator") {
|
||||
return nil, fmt.Errorf("buildkit was unable to emulate %s. check binfmt has been set up and works for this platform: %v", platform, err)
|
||||
|
||||
@@ -53,10 +53,10 @@ func (d *dockerMocker) ContextSupportCheck() error {
|
||||
}
|
||||
return errors.New("contexts not supported")
|
||||
}
|
||||
func (d *dockerMocker) Builder(_ context.Context, _, _, _, _ string, _ bool) (*buildkitClient.Client, error) {
|
||||
func (d *dockerMocker) Builder(_ context.Context, _, _ string) (*buildkitClient.Client, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (d *dockerMocker) Build(ctx context.Context, tag, pkg, dockerContext, builderImage, builderConfigPath, platform string, builderRestart, preCacheImages bool, c spec.CacheProvider, r io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, progress string, imageBuildOpts spec.ImageBuildOptions) error {
|
||||
func (d *dockerMocker) Build(ctx context.Context, tag, pkg, dockerContext, platform string, preCacheImages bool, c spec.CacheProvider, r io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, progress string, imageBuildOpts spec.ImageBuildOptions) error {
|
||||
if !d.enableBuild {
|
||||
return errors.New("build disabled")
|
||||
}
|
||||
|
||||
@@ -18,12 +18,25 @@ import (
|
||||
_ "github.com/moby/buildkit/client/connhelper/ssh"
|
||||
)
|
||||
|
||||
// BuilderConfig holds configuration for the buildkit builder container.
|
||||
type BuilderConfig struct {
|
||||
// Name is the container name for the buildkit builder (e.g., "linuxkit-builder-alice").
|
||||
Name string
|
||||
// Image is the container image to run (e.g., "moby/buildkit:v0.26.3").
|
||||
Image string
|
||||
// ConfigPath is an optional path to a buildkitd.toml config file.
|
||||
ConfigPath string
|
||||
// Restart forces recreation of the builder container even if one with the
|
||||
// correct name and image already exists.
|
||||
Restart bool
|
||||
}
|
||||
|
||||
type DockerRunner interface {
|
||||
Tag(ref, tag string) error
|
||||
Build(ctx context.Context, tag, pkg, dockerContext, builderImage, builderConfigPath, platform string, restart, preCacheImages bool, c spec.CacheProvider, r io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, platformType string, imageBuildOpts spec.ImageBuildOptions) error
|
||||
Build(ctx context.Context, tag, pkg, dockerContext, platform string, preCacheImages bool, c spec.CacheProvider, r io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, platformType string, imageBuildOpts spec.ImageBuildOptions) error
|
||||
Save(tgt string, refs ...string) error
|
||||
Load(src io.Reader) error
|
||||
Pull(img string) (bool, error)
|
||||
ContextSupportCheck() error
|
||||
Builder(ctx context.Context, dockerContext, builderImage, builderConfigPath, platform string, restart bool) (*buildkitClient.Client, error)
|
||||
Builder(ctx context.Context, dockerContext, platform string) (*buildkitClient.Client, error)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (dr *dockerDryRunnerImpl) ContextSupportCheck() error {
|
||||
// 1. if dockerContext is provided, try to create a builder with that context; if it succeeds, we are done; if not, return an error.
|
||||
// 2. try to find an existing named runner with the pattern; if it succeeds, we are done; if not, try next.
|
||||
// 3. try to create a generic builder using the default context named "linuxkit".
|
||||
func (dr *dockerDryRunnerImpl) Builder(ctx context.Context, dockerContext, builderImage, builderConfigPath, platform string, restart bool) (*buildkitClient.Client, error) {
|
||||
func (dr *dockerDryRunnerImpl) Builder(ctx context.Context, dockerContext, platform string) (*buildkitClient.Client, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (dr *dockerDryRunnerImpl) Tag(ref, tag string) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (dr *dockerDryRunnerImpl) Build(ctx context.Context, tag, pkg, dockerContext, builderImage, builderConfigPath, platform string, restart, preCacheImages bool, c spec.CacheProvider, stdin io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, progressType string, imageBuildOpts spec.ImageBuildOptions) error {
|
||||
func (dr *dockerDryRunnerImpl) Build(ctx context.Context, tag, pkg, dockerContext, platform string, preCacheImages bool, c spec.CacheProvider, stdin io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, progressType string, imageBuildOpts spec.ImageBuildOptions) error {
|
||||
// build args
|
||||
var buildArgs []string
|
||||
for k, v := range imageBuildOpts.BuildArgs {
|
||||
|
||||
@@ -67,12 +67,27 @@ const (
|
||||
buildkitConfigPath = buildkitConfigDir + "/" + buildkitConfigFileName
|
||||
)
|
||||
|
||||
type dockerRunnerImpl struct {
|
||||
cache bool
|
||||
// DefaultBuilderName returns the default builder container name.
|
||||
func DefaultBuilderName() string {
|
||||
return buildkitBuilderName
|
||||
}
|
||||
|
||||
func NewDockerRunner(cache bool) DockerRunner {
|
||||
return &dockerRunnerImpl{cache: cache}
|
||||
// builderVolumeName returns the named volume used to persist buildkit state
|
||||
// (build cache, snapshots, content store) across container recreations.
|
||||
func builderVolumeName(containerName string) string {
|
||||
return containerName + "-state"
|
||||
}
|
||||
|
||||
type dockerRunnerImpl struct {
|
||||
cache bool
|
||||
builder BuilderConfig
|
||||
}
|
||||
|
||||
func NewDockerRunner(cache bool, bc BuilderConfig) DockerRunner {
|
||||
if bc.Name == "" {
|
||||
bc.Name = DefaultBuilderName()
|
||||
}
|
||||
return &dockerRunnerImpl{cache: cache, builder: bc}
|
||||
}
|
||||
|
||||
func isExecErrNotFound(err error) bool {
|
||||
@@ -219,14 +234,15 @@ func (dr *dockerRunnerImpl) ContextSupportCheck() error {
|
||||
// 1. if dockerContext is provided, try to create a builder with that context; if it succeeds, we are done; if not, return an error.
|
||||
// 2. try to find an existing named runner with the pattern; if it succeeds, we are done; if not, try next.
|
||||
// 3. try to create a generic builder using the default context named "linuxkit".
|
||||
func (dr *dockerRunnerImpl) Builder(ctx context.Context, dockerContext, builderImage, builderConfigPath, platform string, restart bool) (*buildkitClient.Client, error) {
|
||||
func (dr *dockerRunnerImpl) Builder(ctx context.Context, dockerContext, platform string) (*buildkitClient.Client, error) {
|
||||
bc := dr.builder
|
||||
// if we were given a context, we must find a builder and use it, or create one and use it
|
||||
if dockerContext != "" {
|
||||
// does the context exist?
|
||||
if err := dr.command(nil, io.Discard, io.Discard, "context", "inspect", dockerContext); err != nil {
|
||||
return nil, fmt.Errorf("provided docker context '%s' not found", dockerContext)
|
||||
}
|
||||
client, err := dr.builderEnsureContainer(ctx, buildkitBuilderName, builderImage, builderConfigPath, platform, dockerContext, restart)
|
||||
client, err := dr.builderEnsureContainer(ctx, bc.Name, bc.Image, bc.ConfigPath, platform, dockerContext, bc.Restart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error preparing builder based on context '%s': %v", dockerContext, err)
|
||||
}
|
||||
@@ -237,13 +253,13 @@ func (dr *dockerRunnerImpl) Builder(ctx context.Context, dockerContext, builderI
|
||||
dockerContext = fmt.Sprintf("%s-%s", "linuxkit", strings.ReplaceAll(platform, "/", "-"))
|
||||
if err := dr.command(nil, io.Discard, io.Discard, "context", "inspect", dockerContext); err == nil {
|
||||
// we found an appropriately named context, so let us try to use it or error out
|
||||
if client, err := dr.builderEnsureContainer(ctx, buildkitBuilderName, builderImage, builderConfigPath, platform, dockerContext, restart); err == nil {
|
||||
if client, err := dr.builderEnsureContainer(ctx, bc.Name, bc.Image, bc.ConfigPath, platform, dockerContext, bc.Restart); err == nil {
|
||||
return client, nil
|
||||
}
|
||||
}
|
||||
|
||||
// create a generic builder
|
||||
client, err := dr.builderEnsureContainer(ctx, buildkitBuilderName, builderImage, builderConfigPath, "", "default", restart)
|
||||
client, err := dr.builderEnsureContainer(ctx, bc.Name, bc.Image, bc.ConfigPath, "", "default", bc.Restart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error ensuring builder container in default context: %v", err)
|
||||
}
|
||||
@@ -262,9 +278,10 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im
|
||||
// recreate by default (true) unless we already have one that meets all of the requirements - image, permissions, etc.
|
||||
recreate = true
|
||||
// stop existing one
|
||||
stop = false
|
||||
remove = false
|
||||
found = false
|
||||
stop = false
|
||||
remove = false
|
||||
removeVolume = false
|
||||
found = false
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -278,7 +295,16 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im
|
||||
for range buildKitCheckRetryCount {
|
||||
var b bytes.Buffer
|
||||
var cid string
|
||||
// load config files up front so they are available both when checking
|
||||
// an existing container and when creating a brand-new one
|
||||
var filesToLoadIntoContainer map[string][]byte
|
||||
if configPath != "" {
|
||||
var err error
|
||||
filesToLoadIntoContainer, err = confutil.LoadConfigFiles(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load buildkit config file %s: %v", configPath, err)
|
||||
}
|
||||
}
|
||||
if err := dr.command(nil, &b, io.Discard, "--context", dockerContext, "container", "inspect", name); err == nil {
|
||||
// we already have a container named "linuxkit-builder" in the provided context.
|
||||
// get its state and config
|
||||
@@ -298,12 +324,6 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im
|
||||
log.Debugf("checking if configPath %s is correct in container %s", configPath, name)
|
||||
configPathCorrect = false
|
||||
var configB bytes.Buffer
|
||||
// we cannot exactly use the local config file, as it gets modified to get loaded into the container
|
||||
// so we preprocess it using the same library that would load it up
|
||||
filesToLoadIntoContainer, err = confutil.LoadConfigFiles(configPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load buildkit config file %s: %v", configPath, err)
|
||||
}
|
||||
if err := dr.command(nil, &configB, io.Discard, "--context", dockerContext, "container", "exec", name, "cat", buildkitConfigPath); err == nil {
|
||||
// sha256sum the config file to see if it matches the provided configPath
|
||||
containerConfigFileHash := sha256.Sum256(configB.Bytes())
|
||||
@@ -335,11 +355,13 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im
|
||||
stop = isRunning
|
||||
remove = true
|
||||
case existingImage != image:
|
||||
// if image mismatches, recreate
|
||||
// if image mismatches, recreate and remove the state volume since we
|
||||
// cannot guarantee buildkit state compatibility across versions
|
||||
fmt.Printf("existing container %s is running image %s instead of target %s, replacing\n", name, existingImage, image)
|
||||
recreate = true
|
||||
stop = isRunning
|
||||
remove = true
|
||||
removeVolume = true
|
||||
case !containerJSON[0].HostConfig.Privileged:
|
||||
// if unprivileged, we need to remove it and start a new container with the right permissions
|
||||
fmt.Printf("existing container %s is unprivileged, replacing\n", name)
|
||||
@@ -394,11 +416,24 @@ func (dr *dockerRunnerImpl) builderEnsureContainer(ctx context.Context, name, im
|
||||
continue
|
||||
}
|
||||
}
|
||||
if removeVolume {
|
||||
volName := builderVolumeName(name)
|
||||
fmt.Printf("removing builder state volume %s\n", volName)
|
||||
// best-effort: volume may not exist yet on first run
|
||||
_ = dr.command(nil, io.Discard, io.Discard, "--context", dockerContext, "volume", "rm", volName)
|
||||
}
|
||||
if recreate {
|
||||
// create the builder
|
||||
// this could be a single line, but it would be long. And it is easier to read when the
|
||||
// docker command args, the image name, and the image args are all on separate lines.
|
||||
args := []string{"--context", dockerContext, "container", "create", "--name", name, "--privileged"}
|
||||
volName := builderVolumeName(name)
|
||||
if removeVolume {
|
||||
fmt.Printf("creating fresh builder state volume %s\n", volName)
|
||||
} else {
|
||||
fmt.Printf("reusing builder state volume %s\n", volName)
|
||||
}
|
||||
volMount := volName + ":/var/lib/buildkit"
|
||||
args := []string{"--context", dockerContext, "container", "create", "--name", name, "--privileged", "-v", volMount}
|
||||
args = append(args, image)
|
||||
args = append(args, "--allow-insecure-entitlement", "network.host", "--addr", fmt.Sprintf("unix://%s", buildkitSocketPath), "--debug")
|
||||
if configPath != "" {
|
||||
@@ -507,9 +542,9 @@ func (dr *dockerRunnerImpl) Tag(ref, tag string) error {
|
||||
return dr.command(nil, nil, nil, "image", "tag", ref, tag)
|
||||
}
|
||||
|
||||
func (dr *dockerRunnerImpl) Build(ctx context.Context, tag, pkg, dockerContext, builderImage, builderConfigPath, platform string, restart, preCacheImages bool, c spec.CacheProvider, stdin io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, progressType string, imageBuildOpts spec.ImageBuildOptions) error {
|
||||
func (dr *dockerRunnerImpl) Build(ctx context.Context, tag, pkg, dockerContext, platform string, preCacheImages bool, c spec.CacheProvider, stdin io.Reader, stdout io.Writer, sbomScan bool, sbomScannerImage, progressType string, imageBuildOpts spec.ImageBuildOptions) error {
|
||||
// ensure we have a builder
|
||||
client, err := dr.Builder(ctx, dockerContext, builderImage, builderConfigPath, platform, restart)
|
||||
client, err := dr.Builder(ctx, dockerContext, platform)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to ensure builder container: %v", err)
|
||||
}
|
||||
|
||||
@@ -93,14 +93,14 @@ func printVerbose(tw *tabwriter.Writer, du []*buildkitClient.UsageInfo) {
|
||||
_ = tw.Flush()
|
||||
}
|
||||
|
||||
func getClientForPlatform(ctx context.Context, buildersMap map[string]string, builderImage, builderConfigPath, platform string) (*buildkitClient.Client, error) {
|
||||
func getClientForPlatform(ctx context.Context, buildersMap map[string]string, bc BuilderConfig, platform string) (*buildkitClient.Client, error) {
|
||||
p, err := platforms.Parse(platform)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse platform: %s", err)
|
||||
}
|
||||
dr := NewDockerRunner(false)
|
||||
builderName := getBuilderForPlatform(p.Architecture, buildersMap)
|
||||
client, err := dr.Builder(ctx, builderName, builderImage, builderConfigPath, platform, false)
|
||||
dr := NewDockerRunner(false, bc)
|
||||
dockerContext := getBuilderForPlatform(p.Architecture, buildersMap)
|
||||
client, err := dr.Builder(ctx, dockerContext, platform)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to ensure builder container: %v", err)
|
||||
}
|
||||
@@ -108,11 +108,11 @@ func getClientForPlatform(ctx context.Context, buildersMap map[string]string, bu
|
||||
}
|
||||
|
||||
// DiskUsage of builder
|
||||
func DiskUsage(buildersMap map[string]string, builderImage, builderConfigPath string, platformsToClean []string, verbose bool) error {
|
||||
func DiskUsage(buildersMap map[string]string, bc BuilderConfig, platformsToClean []string, verbose bool) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
for _, platform := range platformsToClean {
|
||||
client, err := getClientForPlatform(ctx, buildersMap, builderImage, builderConfigPath, platform)
|
||||
client, err := getClientForPlatform(ctx, buildersMap, bc, platform)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get client: %s", err)
|
||||
}
|
||||
@@ -143,12 +143,12 @@ func DiskUsage(buildersMap map[string]string, builderImage, builderConfigPath st
|
||||
}
|
||||
|
||||
// PruneBuilder clean build cache of builder
|
||||
func PruneBuilder(buildersMap map[string]string, builderImage, builderConfigPath string, platformsToClean []string, verbose bool) error {
|
||||
func PruneBuilder(buildersMap map[string]string, bc BuilderConfig, platformsToClean []string, verbose bool) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
total := int64(0)
|
||||
for _, platform := range platformsToClean {
|
||||
client, err := getClientForPlatform(ctx, buildersMap, builderImage, builderConfigPath, platform)
|
||||
client, err := getClientForPlatform(ctx, buildersMap, bc, platform)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get client: %s", err)
|
||||
}
|
||||
|
||||
7
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/CHANGES.md
generated
vendored
7
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/CHANGES.md
generated
vendored
@@ -1,5 +1,12 @@
|
||||
# Changes
|
||||
|
||||
## [0.7.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.6.0...compute/metadata/v0.7.0) (2025-05-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **compute/metadata:** Allow canceling GCE detection ([#11786](https://github.com/googleapis/google-cloud-go/issues/11786)) ([78100fe](https://github.com/googleapis/google-cloud-go/commit/78100fe7e28cd30f1e10b47191ac3c9839663b64))
|
||||
|
||||
## [0.6.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.5.2...compute/metadata/v0.6.0) (2024-12-13)
|
||||
|
||||
|
||||
|
||||
162
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
162
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
@@ -117,82 +117,20 @@ var (
|
||||
// NOTE: True returned from `OnGCE` does not guarantee that the metadata server
|
||||
// is accessible from this process and have all the metadata defined.
|
||||
func OnGCE() bool {
|
||||
onGCEOnce.Do(initOnGCE)
|
||||
return OnGCEWithContext(context.Background())
|
||||
}
|
||||
|
||||
// OnGCEWithContext reports whether this process is running on Google Compute Platforms.
|
||||
// This function's return value is memoized for better performance.
|
||||
// NOTE: True returned from `OnGCEWithContext` does not guarantee that the metadata server
|
||||
// is accessible from this process and have all the metadata defined.
|
||||
func OnGCEWithContext(ctx context.Context) bool {
|
||||
onGCEOnce.Do(func() {
|
||||
onGCE = defaultClient.OnGCEWithContext(ctx)
|
||||
})
|
||||
return onGCE
|
||||
}
|
||||
|
||||
func initOnGCE() {
|
||||
onGCE = testOnGCE()
|
||||
}
|
||||
|
||||
func testOnGCE() bool {
|
||||
// The user explicitly said they're on GCE, so trust them.
|
||||
if os.Getenv(metadataHostEnv) != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
resc := make(chan bool, 2)
|
||||
|
||||
// Try two strategies in parallel.
|
||||
// See https://github.com/googleapis/google-cloud-go/issues/194
|
||||
go func() {
|
||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := newDefaultHTTPClient().Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
resc <- false
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
resc <- res.Header.Get("Metadata-Flavor") == "Google"
|
||||
}()
|
||||
|
||||
go func() {
|
||||
resolver := &net.Resolver{}
|
||||
addrs, err := resolver.LookupHost(ctx, "metadata.google.internal.")
|
||||
if err != nil || len(addrs) == 0 {
|
||||
resc <- false
|
||||
return
|
||||
}
|
||||
resc <- strsContains(addrs, metadataIP)
|
||||
}()
|
||||
|
||||
tryHarder := systemInfoSuggestsGCE()
|
||||
if tryHarder {
|
||||
res := <-resc
|
||||
if res {
|
||||
// The first strategy succeeded, so let's use it.
|
||||
return true
|
||||
}
|
||||
// Wait for either the DNS or metadata server probe to
|
||||
// contradict the other one and say we are running on
|
||||
// GCE. Give it a lot of time to do so, since the system
|
||||
// info already suggests we're running on a GCE BIOS.
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case res = <-resc:
|
||||
return res
|
||||
case <-timer.C:
|
||||
// Too slow. Who knows what this system is.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// There's no hint from the system info that we're running on
|
||||
// GCE, so use the first probe's result as truth, whether it's
|
||||
// true or false. The goal here is to optimize for speed for
|
||||
// users who are NOT running on GCE. We can't assume that
|
||||
// either a DNS lookup or an HTTP request to a blackholed IP
|
||||
// address is fast. Worst case this should return when the
|
||||
// metaClient's Transport.ResponseHeaderTimeout or
|
||||
// Transport.Dial.Timeout fires (in two seconds).
|
||||
return <-resc
|
||||
}
|
||||
|
||||
// Subscribe calls Client.SubscribeWithContext on the default client.
|
||||
//
|
||||
// Deprecated: Please use the context aware variant [SubscribeWithContext].
|
||||
@@ -450,6 +388,84 @@ func NewWithOptions(opts *Options) *Client {
|
||||
return &Client{hc: client, logger: logger}
|
||||
}
|
||||
|
||||
// NOTE: metadataRequestStrategy is assigned to a variable for test stubbing purposes.
|
||||
var metadataRequestStrategy = func(ctx context.Context, httpClient *http.Client, resc chan bool) {
|
||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := httpClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
resc <- false
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
resc <- res.Header.Get("Metadata-Flavor") == "Google"
|
||||
}
|
||||
|
||||
// NOTE: dnsRequestStrategy is assigned to a variable for test stubbing purposes.
|
||||
var dnsRequestStrategy = func(ctx context.Context, resc chan bool) {
|
||||
resolver := &net.Resolver{}
|
||||
addrs, err := resolver.LookupHost(ctx, "metadata.google.internal.")
|
||||
if err != nil || len(addrs) == 0 {
|
||||
resc <- false
|
||||
return
|
||||
}
|
||||
resc <- strsContains(addrs, metadataIP)
|
||||
}
|
||||
|
||||
// OnGCEWithContext reports whether this process is running on Google Compute Platforms.
|
||||
// NOTE: True returned from `OnGCEWithContext` does not guarantee that the metadata server
|
||||
// is accessible from this process and have all the metadata defined.
|
||||
func (c *Client) OnGCEWithContext(ctx context.Context) bool {
|
||||
// The user explicitly said they're on GCE, so trust them.
|
||||
if os.Getenv(metadataHostEnv) != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
resc := make(chan bool, 2)
|
||||
|
||||
// Try two strategies in parallel.
|
||||
// See https://github.com/googleapis/google-cloud-go/issues/194
|
||||
go metadataRequestStrategy(ctx, c.hc, resc)
|
||||
go dnsRequestStrategy(ctx, resc)
|
||||
|
||||
tryHarder := systemInfoSuggestsGCE()
|
||||
if tryHarder {
|
||||
res := <-resc
|
||||
if res {
|
||||
// The first strategy succeeded, so let's use it.
|
||||
return true
|
||||
}
|
||||
|
||||
// Wait for either the DNS or metadata server probe to
|
||||
// contradict the other one and say we are running on
|
||||
// GCE. Give it a lot of time to do so, since the system
|
||||
// info already suggests we're running on a GCE BIOS.
|
||||
// Ensure cancellations from the calling context are respected.
|
||||
waitContext, cancelWait := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancelWait()
|
||||
select {
|
||||
case res = <-resc:
|
||||
return res
|
||||
case <-waitContext.Done():
|
||||
// Too slow. Who knows what this system is.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// There's no hint from the system info that we're running on
|
||||
// GCE, so use the first probe's result as truth, whether it's
|
||||
// true or false. The goal here is to optimize for speed for
|
||||
// users who are NOT running on GCE. We can't assume that
|
||||
// either a DNS lookup or an HTTP request to a blackholed IP
|
||||
// address is fast. Worst case this should return when the
|
||||
// metaClient's Transport.ResponseHeaderTimeout or
|
||||
// Transport.Dial.Timeout fires (in two seconds).
|
||||
return <-resc
|
||||
}
|
||||
|
||||
// getETag returns a value from the metadata service as well as the associated ETag.
|
||||
// This func is otherwise equivalent to Get.
|
||||
func (c *Client) getETag(ctx context.Context, suffix string) (value, etag string, err error) {
|
||||
|
||||
4
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/syscheck.go
generated
vendored
4
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/syscheck.go
generated
vendored
@@ -20,7 +20,9 @@ package metadata
|
||||
// doing network requests) suggests that we're running on GCE. If this
|
||||
// returns true, testOnGCE tries a bit harder to reach its metadata
|
||||
// server.
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
//
|
||||
// NOTE: systemInfoSuggestsGCE is assigned to a varible for test stubbing purposes.
|
||||
var systemInfoSuggestsGCE = func() bool {
|
||||
// We don't currently have checks for other GOOS
|
||||
return false
|
||||
}
|
||||
|
||||
4
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go
generated
vendored
4
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/syscheck_linux.go
generated
vendored
@@ -21,8 +21,10 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
// NOTE: systemInfoSuggestsGCE is assigned to a varible for test stubbing purposes.
|
||||
var systemInfoSuggestsGCE = func() bool {
|
||||
b, _ := os.ReadFile("/sys/class/dmi/id/product_name")
|
||||
|
||||
name := strings.TrimSpace(string(b))
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
}
|
||||
|
||||
3
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go
generated
vendored
3
src/cmd/linuxkit/vendor/cloud.google.com/go/compute/metadata/syscheck_windows.go
generated
vendored
@@ -22,7 +22,8 @@ import (
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
// NOTE: systemInfoSuggestsGCE is assigned to a varible for test stubbing purposes.
|
||||
var systemInfoSuggestsGCE = func() bool {
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\HardwareConfig\Current`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
62
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
62
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
@@ -1,62 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BackOffContext is a backoff policy that stops retrying after the context
|
||||
// is canceled.
|
||||
type BackOffContext interface { // nolint: golint
|
||||
BackOff
|
||||
Context() context.Context
|
||||
}
|
||||
|
||||
type backOffContext struct {
|
||||
BackOff
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// WithContext returns a BackOffContext with context ctx
|
||||
//
|
||||
// ctx must not be nil
|
||||
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
|
||||
if ctx == nil {
|
||||
panic("nil context")
|
||||
}
|
||||
|
||||
if b, ok := b.(*backOffContext); ok {
|
||||
return &backOffContext{
|
||||
BackOff: b.BackOff,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
return &backOffContext{
|
||||
BackOff: b,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
func getContext(b BackOff) context.Context {
|
||||
if cb, ok := b.(BackOffContext); ok {
|
||||
return cb.Context()
|
||||
}
|
||||
if tb, ok := b.(*backOffTries); ok {
|
||||
return getContext(tb.delegate)
|
||||
}
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func (b *backOffContext) Context() context.Context {
|
||||
return b.ctx
|
||||
}
|
||||
|
||||
func (b *backOffContext) NextBackOff() time.Duration {
|
||||
select {
|
||||
case <-b.ctx.Done():
|
||||
return Stop
|
||||
default:
|
||||
return b.BackOff.NextBackOff()
|
||||
}
|
||||
}
|
||||
216
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
216
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
@@ -1,216 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
ExponentialBackOff is a backoff implementation that increases the backoff
|
||||
period for each retry attempt using a randomization function that grows exponentially.
|
||||
|
||||
NextBackOff() is calculated using the following formula:
|
||||
|
||||
randomized interval =
|
||||
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
||||
|
||||
In other words NextBackOff() will range between the randomization factor
|
||||
percentage below and above the retry interval.
|
||||
|
||||
For example, given the following parameters:
|
||||
|
||||
RetryInterval = 2
|
||||
RandomizationFactor = 0.5
|
||||
Multiplier = 2
|
||||
|
||||
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
||||
multiplied by the exponential, that is, between 2 and 6 seconds.
|
||||
|
||||
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
||||
|
||||
If the time elapsed since an ExponentialBackOff instance is created goes past the
|
||||
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
|
||||
|
||||
The elapsed time can be reset by calling Reset().
|
||||
|
||||
Example: Given the following default arguments, for 10 tries the sequence will be,
|
||||
and assuming we go over the MaxElapsedTime on the 10th try:
|
||||
|
||||
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
||||
|
||||
1 0.5 [0.25, 0.75]
|
||||
2 0.75 [0.375, 1.125]
|
||||
3 1.125 [0.562, 1.687]
|
||||
4 1.687 [0.8435, 2.53]
|
||||
5 2.53 [1.265, 3.795]
|
||||
6 3.795 [1.897, 5.692]
|
||||
7 5.692 [2.846, 8.538]
|
||||
8 8.538 [4.269, 12.807]
|
||||
9 12.807 [6.403, 19.210]
|
||||
10 19.210 backoff.Stop
|
||||
|
||||
Note: Implementation is not thread-safe.
|
||||
*/
|
||||
type ExponentialBackOff struct {
|
||||
InitialInterval time.Duration
|
||||
RandomizationFactor float64
|
||||
Multiplier float64
|
||||
MaxInterval time.Duration
|
||||
// After MaxElapsedTime the ExponentialBackOff returns Stop.
|
||||
// It never stops if MaxElapsedTime == 0.
|
||||
MaxElapsedTime time.Duration
|
||||
Stop time.Duration
|
||||
Clock Clock
|
||||
|
||||
currentInterval time.Duration
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
// Clock is an interface that returns current time for BackOff.
|
||||
type Clock interface {
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options.
|
||||
type ExponentialBackOffOpts func(*ExponentialBackOff)
|
||||
|
||||
// Default values for ExponentialBackOff.
|
||||
const (
|
||||
DefaultInitialInterval = 500 * time.Millisecond
|
||||
DefaultRandomizationFactor = 0.5
|
||||
DefaultMultiplier = 1.5
|
||||
DefaultMaxInterval = 60 * time.Second
|
||||
DefaultMaxElapsedTime = 15 * time.Minute
|
||||
)
|
||||
|
||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
||||
func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff {
|
||||
b := &ExponentialBackOff{
|
||||
InitialInterval: DefaultInitialInterval,
|
||||
RandomizationFactor: DefaultRandomizationFactor,
|
||||
Multiplier: DefaultMultiplier,
|
||||
MaxInterval: DefaultMaxInterval,
|
||||
MaxElapsedTime: DefaultMaxElapsedTime,
|
||||
Stop: Stop,
|
||||
Clock: SystemClock,
|
||||
}
|
||||
for _, fn := range opts {
|
||||
fn(b)
|
||||
}
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
// WithInitialInterval sets the initial interval between retries.
|
||||
func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.InitialInterval = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithRandomizationFactor sets the randomization factor to add jitter to intervals.
|
||||
func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.RandomizationFactor = randomizationFactor
|
||||
}
|
||||
}
|
||||
|
||||
// WithMultiplier sets the multiplier for increasing the interval after each retry.
|
||||
func WithMultiplier(multiplier float64) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.Multiplier = multiplier
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxInterval sets the maximum interval between retries.
|
||||
func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.MaxInterval = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxElapsedTime sets the maximum total time for retries.
|
||||
func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.MaxElapsedTime = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithRetryStopDuration sets the duration after which retries should stop.
|
||||
func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.Stop = duration
|
||||
}
|
||||
}
|
||||
|
||||
// WithClockProvider sets the clock used to measure time.
|
||||
func WithClockProvider(clock Clock) ExponentialBackOffOpts {
|
||||
return func(ebo *ExponentialBackOff) {
|
||||
ebo.Clock = clock
|
||||
}
|
||||
}
|
||||
|
||||
type systemClock struct{}
|
||||
|
||||
func (t systemClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// SystemClock implements Clock interface that uses time.Now().
|
||||
var SystemClock = systemClock{}
|
||||
|
||||
// Reset the interval back to the initial retry interval and restarts the timer.
|
||||
// Reset must be called before using b.
|
||||
func (b *ExponentialBackOff) Reset() {
|
||||
b.currentInterval = b.InitialInterval
|
||||
b.startTime = b.Clock.Now()
|
||||
}
|
||||
|
||||
// NextBackOff calculates the next backoff interval using the formula:
|
||||
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
|
||||
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
||||
// Make sure we have not gone over the maximum elapsed time.
|
||||
elapsed := b.GetElapsedTime()
|
||||
next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
|
||||
b.incrementCurrentInterval()
|
||||
if b.MaxElapsedTime != 0 && elapsed+next > b.MaxElapsedTime {
|
||||
return b.Stop
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
|
||||
// is created and is reset when Reset() is called.
|
||||
//
|
||||
// The elapsed time is computed using time.Now().UnixNano(). It is
|
||||
// safe to call even while the backoff policy is used by a running
|
||||
// ticker.
|
||||
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
|
||||
return b.Clock.Now().Sub(b.startTime)
|
||||
}
|
||||
|
||||
// Increments the current interval by multiplying it with the multiplier.
|
||||
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
||||
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
||||
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
||||
b.currentInterval = b.MaxInterval
|
||||
} else {
|
||||
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a random value from the following interval:
|
||||
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
||||
if randomizationFactor == 0 {
|
||||
return currentInterval // make sure no randomness is used when randomizationFactor is 0.
|
||||
}
|
||||
var delta = randomizationFactor * float64(currentInterval)
|
||||
var minInterval = float64(currentInterval) - delta
|
||||
var maxInterval = float64(currentInterval) + delta
|
||||
|
||||
// Get a random value from the range [minInterval, maxInterval].
|
||||
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
||||
// we want a 33% chance for selecting either 1, 2 or 3.
|
||||
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
||||
}
|
||||
146
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
146
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
@@ -1,146 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData().
|
||||
// The operation will be retried using a backoff policy if it returns an error.
|
||||
type OperationWithData[T any] func() (T, error)
|
||||
|
||||
// An Operation is executing by Retry() or RetryNotify().
|
||||
// The operation will be retried using a backoff policy if it returns an error.
|
||||
type Operation func() error
|
||||
|
||||
func (o Operation) withEmptyData() OperationWithData[struct{}] {
|
||||
return func() (struct{}, error) {
|
||||
return struct{}{}, o()
|
||||
}
|
||||
}
|
||||
|
||||
// Notify is a notify-on-error function. It receives an operation error and
|
||||
// backoff delay if the operation failed (with an error).
|
||||
//
|
||||
// NOTE that if the backoff policy stated to stop retrying,
|
||||
// the notify function isn't called.
|
||||
type Notify func(error, time.Duration)
|
||||
|
||||
// Retry the operation o until it does not return error or BackOff stops.
|
||||
// o is guaranteed to be run at least once.
|
||||
//
|
||||
// If o returns a *PermanentError, the operation is not retried, and the
|
||||
// wrapped error is returned.
|
||||
//
|
||||
// Retry sleeps the goroutine for the duration returned by BackOff after a
|
||||
// failed operation returns.
|
||||
func Retry(o Operation, b BackOff) error {
|
||||
return RetryNotify(o, b, nil)
|
||||
}
|
||||
|
||||
// RetryWithData is like Retry but returns data in the response too.
|
||||
func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) {
|
||||
return RetryNotifyWithData(o, b, nil)
|
||||
}
|
||||
|
||||
// RetryNotify calls notify function with the error and wait duration
|
||||
// for each failed attempt before sleep.
|
||||
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
|
||||
return RetryNotifyWithTimer(operation, b, notify, nil)
|
||||
}
|
||||
|
||||
// RetryNotifyWithData is like RetryNotify but returns data in the response too.
|
||||
func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) {
|
||||
return doRetryNotify(operation, b, notify, nil)
|
||||
}
|
||||
|
||||
// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
|
||||
// for each failed attempt before sleep.
|
||||
// A default timer that uses system timer is used when nil is passed.
|
||||
func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
|
||||
_, err := doRetryNotify(operation.withEmptyData(), b, notify, t)
|
||||
return err
|
||||
}
|
||||
|
||||
// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too.
|
||||
func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
|
||||
return doRetryNotify(operation, b, notify, t)
|
||||
}
|
||||
|
||||
func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
|
||||
var (
|
||||
err error
|
||||
next time.Duration
|
||||
res T
|
||||
)
|
||||
if t == nil {
|
||||
t = &defaultTimer{}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
t.Stop()
|
||||
}()
|
||||
|
||||
ctx := getContext(b)
|
||||
|
||||
b.Reset()
|
||||
for {
|
||||
res, err = operation()
|
||||
if err == nil {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
var permanent *PermanentError
|
||||
if errors.As(err, &permanent) {
|
||||
return res, permanent.Err
|
||||
}
|
||||
|
||||
if next = b.NextBackOff(); next == Stop {
|
||||
if cerr := ctx.Err(); cerr != nil {
|
||||
return res, cerr
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
if notify != nil {
|
||||
notify(err, next)
|
||||
}
|
||||
|
||||
t.Start(next)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return res, ctx.Err()
|
||||
case <-t.C():
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PermanentError signals that the operation should not be retried.
|
||||
type PermanentError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *PermanentError) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
func (e *PermanentError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func (e *PermanentError) Is(target error) bool {
|
||||
_, ok := target.(*PermanentError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Permanent wraps the given err in a *PermanentError.
|
||||
func Permanent(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &PermanentError{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
38
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
38
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
@@ -1,38 +0,0 @@
|
||||
package backoff
|
||||
|
||||
import "time"
|
||||
|
||||
/*
|
||||
WithMaxRetries creates a wrapper around another BackOff, which will
|
||||
return Stop if NextBackOff() has been called too many times since
|
||||
the last time Reset() was called
|
||||
|
||||
Note: Implementation is not thread-safe.
|
||||
*/
|
||||
func WithMaxRetries(b BackOff, max uint64) BackOff {
|
||||
return &backOffTries{delegate: b, maxTries: max}
|
||||
}
|
||||
|
||||
type backOffTries struct {
|
||||
delegate BackOff
|
||||
maxTries uint64
|
||||
numTries uint64
|
||||
}
|
||||
|
||||
func (b *backOffTries) NextBackOff() time.Duration {
|
||||
if b.maxTries == 0 {
|
||||
return Stop
|
||||
}
|
||||
if b.maxTries > 0 {
|
||||
if b.maxTries <= b.numTries {
|
||||
return Stop
|
||||
}
|
||||
b.numTries++
|
||||
}
|
||||
return b.delegate.NextBackOff()
|
||||
}
|
||||
|
||||
func (b *backOffTries) Reset() {
|
||||
b.numTries = 0
|
||||
b.delegate.Reset()
|
||||
}
|
||||
29
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md
generated
vendored
Normal file
29
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [5.0.0] - 2024-12-19
|
||||
|
||||
### Added
|
||||
|
||||
- RetryAfterError can be returned from an operation to indicate how long to wait before the next retry.
|
||||
|
||||
### Changed
|
||||
|
||||
- Retry function now accepts additional options for specifying max number of tries and max elapsed time.
|
||||
- Retry function now accepts a context.Context.
|
||||
- Operation function signature changed to return result (any type) and error.
|
||||
|
||||
### Removed
|
||||
|
||||
- RetryNotify* and RetryWithData functions. Only single Retry function remains.
|
||||
- Optional arguments from ExponentialBackoff constructor.
|
||||
- Clock and Timer interfaces.
|
||||
|
||||
### Fixed
|
||||
|
||||
- The original error is returned from Retry if there's a PermanentError. (#144)
|
||||
- The Retry function respects the wrapped PermanentError. (#140)
|
||||
@@ -1,4 +1,4 @@
|
||||
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls]
|
||||
# Exponential Backoff [![GoDoc][godoc image]][godoc]
|
||||
|
||||
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
||||
|
||||
@@ -9,9 +9,11 @@ The retries exponentially increase and stop increasing when a certain threshold
|
||||
|
||||
## Usage
|
||||
|
||||
Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end.
|
||||
Import path is `github.com/cenkalti/backoff/v5`. Please note the version part at the end.
|
||||
|
||||
Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
|
||||
For most cases, use `Retry` function. See [example_test.go][example] for an example.
|
||||
|
||||
If you have specific needs, copy `Retry` function (from [retry.go][retry-src]) into your code and modify it as needed.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -19,12 +21,11 @@ Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
|
||||
* Please don't send a PR without opening an issue and discussing it first.
|
||||
* If proposed change is not a common use case, I will probably not accept it.
|
||||
|
||||
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
|
||||
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v5
|
||||
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
||||
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
|
||||
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
|
||||
|
||||
[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
|
||||
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
|
||||
|
||||
[advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples
|
||||
[retry-src]: https://github.com/cenkalti/backoff/blob/v5/retry.go
|
||||
[example]: https://github.com/cenkalti/backoff/blob/v5/example_test.go
|
||||
@@ -15,16 +15,16 @@ import "time"
|
||||
// BackOff is a backoff policy for retrying an operation.
|
||||
type BackOff interface {
|
||||
// NextBackOff returns the duration to wait before retrying the operation,
|
||||
// or backoff. Stop to indicate that no more retries should be made.
|
||||
// backoff.Stop to indicate that no more retries should be made.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// duration := backoff.NextBackOff();
|
||||
// if (duration == backoff.Stop) {
|
||||
// // Do not retry operation.
|
||||
// } else {
|
||||
// // Sleep for duration and retry operation.
|
||||
// }
|
||||
// duration := backoff.NextBackOff()
|
||||
// if duration == backoff.Stop {
|
||||
// // Do not retry operation.
|
||||
// } else {
|
||||
// // Sleep for duration and retry operation.
|
||||
// }
|
||||
//
|
||||
NextBackOff() time.Duration
|
||||
|
||||
46
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/error.go
generated
vendored
Normal file
46
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/error.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// PermanentError signals that the operation should not be retried.
|
||||
type PermanentError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// Permanent wraps the given err in a *PermanentError.
|
||||
func Permanent(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &PermanentError{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Error returns a string representation of the Permanent error.
|
||||
func (e *PermanentError) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
// Unwrap returns the wrapped error.
|
||||
func (e *PermanentError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// RetryAfterError signals that the operation should be retried after the given duration.
|
||||
type RetryAfterError struct {
|
||||
Duration time.Duration
|
||||
}
|
||||
|
||||
// RetryAfter returns a RetryAfter error that specifies how long to wait before retrying.
|
||||
func RetryAfter(seconds int) error {
|
||||
return &RetryAfterError{Duration: time.Duration(seconds) * time.Second}
|
||||
}
|
||||
|
||||
// Error returns a string representation of the RetryAfter error.
|
||||
func (e *RetryAfterError) Error() string {
|
||||
return fmt.Sprintf("retry after %s", e.Duration)
|
||||
}
|
||||
118
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/exponential.go
generated
vendored
Normal file
118
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/exponential.go
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
ExponentialBackOff is a backoff implementation that increases the backoff
|
||||
period for each retry attempt using a randomization function that grows exponentially.
|
||||
|
||||
NextBackOff() is calculated using the following formula:
|
||||
|
||||
randomized interval =
|
||||
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
||||
|
||||
In other words NextBackOff() will range between the randomization factor
|
||||
percentage below and above the retry interval.
|
||||
|
||||
For example, given the following parameters:
|
||||
|
||||
RetryInterval = 2
|
||||
RandomizationFactor = 0.5
|
||||
Multiplier = 2
|
||||
|
||||
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
||||
multiplied by the exponential, that is, between 2 and 6 seconds.
|
||||
|
||||
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
||||
|
||||
Example: Given the following default arguments, for 9 tries the sequence will be:
|
||||
|
||||
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
||||
|
||||
1 0.5 [0.25, 0.75]
|
||||
2 0.75 [0.375, 1.125]
|
||||
3 1.125 [0.562, 1.687]
|
||||
4 1.687 [0.8435, 2.53]
|
||||
5 2.53 [1.265, 3.795]
|
||||
6 3.795 [1.897, 5.692]
|
||||
7 5.692 [2.846, 8.538]
|
||||
8 8.538 [4.269, 12.807]
|
||||
9 12.807 [6.403, 19.210]
|
||||
|
||||
Note: Implementation is not thread-safe.
|
||||
*/
|
||||
type ExponentialBackOff struct {
|
||||
InitialInterval time.Duration
|
||||
RandomizationFactor float64
|
||||
Multiplier float64
|
||||
MaxInterval time.Duration
|
||||
|
||||
currentInterval time.Duration
|
||||
}
|
||||
|
||||
// Default values for ExponentialBackOff.
|
||||
const (
|
||||
DefaultInitialInterval = 500 * time.Millisecond
|
||||
DefaultRandomizationFactor = 0.5
|
||||
DefaultMultiplier = 1.5
|
||||
DefaultMaxInterval = 60 * time.Second
|
||||
)
|
||||
|
||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
||||
func NewExponentialBackOff() *ExponentialBackOff {
|
||||
return &ExponentialBackOff{
|
||||
InitialInterval: DefaultInitialInterval,
|
||||
RandomizationFactor: DefaultRandomizationFactor,
|
||||
Multiplier: DefaultMultiplier,
|
||||
MaxInterval: DefaultMaxInterval,
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the interval back to the initial retry interval and restarts the timer.
|
||||
// Reset must be called before using b.
|
||||
func (b *ExponentialBackOff) Reset() {
|
||||
b.currentInterval = b.InitialInterval
|
||||
}
|
||||
|
||||
// NextBackOff calculates the next backoff interval using the formula:
|
||||
//
|
||||
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
|
||||
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
||||
if b.currentInterval == 0 {
|
||||
b.currentInterval = b.InitialInterval
|
||||
}
|
||||
|
||||
next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
|
||||
b.incrementCurrentInterval()
|
||||
return next
|
||||
}
|
||||
|
||||
// Increments the current interval by multiplying it with the multiplier.
|
||||
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
||||
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
||||
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
||||
b.currentInterval = b.MaxInterval
|
||||
} else {
|
||||
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a random value from the following interval:
|
||||
//
|
||||
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
||||
if randomizationFactor == 0 {
|
||||
return currentInterval // make sure no randomness is used when randomizationFactor is 0.
|
||||
}
|
||||
var delta = randomizationFactor * float64(currentInterval)
|
||||
var minInterval = float64(currentInterval) - delta
|
||||
var maxInterval = float64(currentInterval) + delta
|
||||
|
||||
// Get a random value from the range [minInterval, maxInterval].
|
||||
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
||||
// we want a 33% chance for selecting either 1, 2 or 3.
|
||||
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
||||
}
|
||||
139
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/retry.go
generated
vendored
Normal file
139
src/cmd/linuxkit/vendor/github.com/cenkalti/backoff/v5/retry.go
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultMaxElapsedTime sets a default limit for the total retry duration.
|
||||
const DefaultMaxElapsedTime = 15 * time.Minute
|
||||
|
||||
// Operation is a function that attempts an operation and may be retried.
|
||||
type Operation[T any] func() (T, error)
|
||||
|
||||
// Notify is a function called on operation error with the error and backoff duration.
|
||||
type Notify func(error, time.Duration)
|
||||
|
||||
// retryOptions holds configuration settings for the retry mechanism.
|
||||
type retryOptions struct {
|
||||
BackOff BackOff // Strategy for calculating backoff periods.
|
||||
Timer timer // Timer to manage retry delays.
|
||||
Notify Notify // Optional function to notify on each retry error.
|
||||
MaxTries uint // Maximum number of retry attempts.
|
||||
MaxElapsedTime time.Duration // Maximum total time for all retries.
|
||||
}
|
||||
|
||||
type RetryOption func(*retryOptions)
|
||||
|
||||
// WithBackOff configures a custom backoff strategy.
|
||||
func WithBackOff(b BackOff) RetryOption {
|
||||
return func(args *retryOptions) {
|
||||
args.BackOff = b
|
||||
}
|
||||
}
|
||||
|
||||
// withTimer sets a custom timer for managing delays between retries.
|
||||
func withTimer(t timer) RetryOption {
|
||||
return func(args *retryOptions) {
|
||||
args.Timer = t
|
||||
}
|
||||
}
|
||||
|
||||
// WithNotify sets a notification function to handle retry errors.
|
||||
func WithNotify(n Notify) RetryOption {
|
||||
return func(args *retryOptions) {
|
||||
args.Notify = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxTries limits the number of all attempts.
|
||||
func WithMaxTries(n uint) RetryOption {
|
||||
return func(args *retryOptions) {
|
||||
args.MaxTries = n
|
||||
}
|
||||
}
|
||||
|
||||
// WithMaxElapsedTime limits the total duration for retry attempts.
|
||||
func WithMaxElapsedTime(d time.Duration) RetryOption {
|
||||
return func(args *retryOptions) {
|
||||
args.MaxElapsedTime = d
|
||||
}
|
||||
}
|
||||
|
||||
// Retry attempts the operation until success, a permanent error, or backoff completion.
|
||||
// It ensures the operation is executed at least once.
|
||||
//
|
||||
// Returns the operation result or error if retries are exhausted or context is cancelled.
|
||||
func Retry[T any](ctx context.Context, operation Operation[T], opts ...RetryOption) (T, error) {
|
||||
// Initialize default retry options.
|
||||
args := &retryOptions{
|
||||
BackOff: NewExponentialBackOff(),
|
||||
Timer: &defaultTimer{},
|
||||
MaxElapsedTime: DefaultMaxElapsedTime,
|
||||
}
|
||||
|
||||
// Apply user-provided options to the default settings.
|
||||
for _, opt := range opts {
|
||||
opt(args)
|
||||
}
|
||||
|
||||
defer args.Timer.Stop()
|
||||
|
||||
startedAt := time.Now()
|
||||
args.BackOff.Reset()
|
||||
for numTries := uint(1); ; numTries++ {
|
||||
// Execute the operation.
|
||||
res, err := operation()
|
||||
if err == nil {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Stop retrying if maximum tries exceeded.
|
||||
if args.MaxTries > 0 && numTries >= args.MaxTries {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Handle permanent errors without retrying.
|
||||
var permanent *PermanentError
|
||||
if errors.As(err, &permanent) {
|
||||
return res, permanent.Unwrap()
|
||||
}
|
||||
|
||||
// Stop retrying if context is cancelled.
|
||||
if cerr := context.Cause(ctx); cerr != nil {
|
||||
return res, cerr
|
||||
}
|
||||
|
||||
// Calculate next backoff duration.
|
||||
next := args.BackOff.NextBackOff()
|
||||
if next == Stop {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Reset backoff if RetryAfterError is encountered.
|
||||
var retryAfter *RetryAfterError
|
||||
if errors.As(err, &retryAfter) {
|
||||
next = retryAfter.Duration
|
||||
args.BackOff.Reset()
|
||||
}
|
||||
|
||||
// Stop retrying if maximum elapsed time exceeded.
|
||||
if args.MaxElapsedTime > 0 && time.Since(startedAt)+next > args.MaxElapsedTime {
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Notify on error if a notifier function is provided.
|
||||
if args.Notify != nil {
|
||||
args.Notify(err, next)
|
||||
}
|
||||
|
||||
// Wait for the next backoff period or context cancellation.
|
||||
args.Timer.Start(next)
|
||||
select {
|
||||
case <-args.Timer.C():
|
||||
case <-ctx.Done():
|
||||
return res, context.Cause(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package backoff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -14,8 +13,7 @@ type Ticker struct {
|
||||
C <-chan time.Time
|
||||
c chan time.Time
|
||||
b BackOff
|
||||
ctx context.Context
|
||||
timer Timer
|
||||
timer timer
|
||||
stop chan struct{}
|
||||
stopOnce sync.Once
|
||||
}
|
||||
@@ -27,22 +25,12 @@ type Ticker struct {
|
||||
// provided backoff policy (notably calling NextBackOff or Reset)
|
||||
// while the ticker is running.
|
||||
func NewTicker(b BackOff) *Ticker {
|
||||
return NewTickerWithTimer(b, &defaultTimer{})
|
||||
}
|
||||
|
||||
// NewTickerWithTimer returns a new Ticker with a custom timer.
|
||||
// A default timer that uses system timer is used when nil is passed.
|
||||
func NewTickerWithTimer(b BackOff, timer Timer) *Ticker {
|
||||
if timer == nil {
|
||||
timer = &defaultTimer{}
|
||||
}
|
||||
c := make(chan time.Time)
|
||||
t := &Ticker{
|
||||
C: c,
|
||||
c: c,
|
||||
b: b,
|
||||
ctx: getContext(b),
|
||||
timer: timer,
|
||||
timer: &defaultTimer{},
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
t.b.Reset()
|
||||
@@ -73,8 +61,6 @@ func (t *Ticker) run() {
|
||||
case <-t.stop:
|
||||
t.c = nil // Prevent future ticks from being sent to the channel.
|
||||
return
|
||||
case <-t.ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package backoff
|
||||
|
||||
import "time"
|
||||
|
||||
type Timer interface {
|
||||
type timer interface {
|
||||
Start(duration time.Duration)
|
||||
Stop()
|
||||
C() <-chan time.Time
|
||||
5
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/content/content.go
generated
vendored
5
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/content/content.go
generated
vendored
@@ -170,6 +170,11 @@ type Syncer interface {
|
||||
Sync() error
|
||||
}
|
||||
|
||||
// ReferrersProvider handles looking up additional referrer objects for a given descriptor.
|
||||
type ReferrersProvider interface {
|
||||
Referrers(context.Context, ocispec.Descriptor) ([]ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
// Opt is used to alter the mutable properties of content
|
||||
type Opt func(*Info) error
|
||||
|
||||
|
||||
@@ -20,4 +20,10 @@ const (
|
||||
// AnnotationImageName is an annotation on a Descriptor in an index.json
|
||||
// containing the `Name` value as used by an `Image` struct
|
||||
AnnotationImageName = "io.containerd.image.name"
|
||||
|
||||
// AnnotationManifestSubject is an annotation on a Descriptor that means
|
||||
// that current descriptor is a referrer to the subject manifest.
|
||||
// If descriptor in image.json has this annotation, it will not create
|
||||
// a new image.
|
||||
AnnotationManifestSubject = "io.containerd.manifest.subject"
|
||||
)
|
||||
|
||||
35
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/images/handlers.go
generated
vendored
35
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/images/handlers.go
generated
vendored
@@ -20,7 +20,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/v2/core/content"
|
||||
"github.com/containerd/errdefs"
|
||||
@@ -198,6 +200,35 @@ func ChildrenHandler(provider content.Provider) HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// SetReferrers is a handler wrapper which adds referrer descriptors
|
||||
// from the provided ReferrersProvider and adds them to the children
|
||||
// returned by the handler. The referrers will have a container-specific
|
||||
// annotation added to indicate the subject descriptor.
|
||||
func SetReferrers(refProvider content.ReferrersProvider, f HandlerFunc) HandlerFunc {
|
||||
return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
children, err := f(ctx, desc)
|
||||
if err != nil {
|
||||
return children, err
|
||||
}
|
||||
if !IsManifestType(desc.MediaType) && !IsIndexType(desc.MediaType) {
|
||||
return children, nil
|
||||
}
|
||||
refs, err := refProvider.Referrers(ctx, desc)
|
||||
if err != nil {
|
||||
return children, err
|
||||
}
|
||||
children = slices.Grow(children, len(refs))
|
||||
for _, ref := range refs {
|
||||
if ref.Annotations == nil {
|
||||
ref.Annotations = map[string]string{}
|
||||
}
|
||||
ref.Annotations[AnnotationManifestSubject] = desc.Digest.String()
|
||||
children = append(children, ref)
|
||||
}
|
||||
return children, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetChildrenLabels is a handler wrapper which sets labels for the content on
|
||||
// the children returned by the handler and passes through the children.
|
||||
// Must follow a handler that returns the children to be labeled.
|
||||
@@ -235,7 +266,9 @@ func SetChildrenMappedLabels(manager content.Manager, f HandlerFunc, labelMap fu
|
||||
for _, key := range labelKeys {
|
||||
idx := keys[key]
|
||||
keys[key] = idx + 1
|
||||
if idx > 0 || key[len(key)-1] == '.' {
|
||||
if strings.HasSuffix(key, ".sha256.") {
|
||||
key = fmt.Sprintf("%s%s", key, ch.Digest.Hex()[:12])
|
||||
} else if idx > 0 || key[len(key)-1] == '.' {
|
||||
key = fmt.Sprintf("%s%d", key, idx)
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,9 @@ func IsAttestationType(mt string) bool {
|
||||
|
||||
// ChildGCLabels returns the label for a given descriptor to reference it
|
||||
func ChildGCLabels(desc ocispec.Descriptor) []string {
|
||||
if _, ok := desc.Annotations[AnnotationManifestSubject]; ok {
|
||||
return []string{"containerd.io/gc.ref.content.referrer.sha256."}
|
||||
}
|
||||
mt := desc.MediaType
|
||||
if IsKnownConfig(mt) {
|
||||
return []string{"containerd.io/gc.ref.content.config"}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (ec ErrorCode) ErrorCode() ErrorCode {
|
||||
// Error returns the ID/Value
|
||||
func (ec ErrorCode) Error() string {
|
||||
// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.
|
||||
return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1))
|
||||
return strings.ToLower(strings.ReplaceAll(ec.String(), "_", " "))
|
||||
}
|
||||
|
||||
// Descriptor returns the descriptor for the error code.
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -260,7 +259,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
req.path = req.path + "?" + u.RawQuery
|
||||
}
|
||||
|
||||
rc, err := r.open(ctx, req, desc.MediaType, offset, false)
|
||||
rc, _, err := r.open(ctx, req, desc.MediaType, offset, false)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue // try one of the other urls.
|
||||
@@ -282,7 +281,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rc, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
|
||||
rc, _, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
|
||||
if err != nil {
|
||||
// Store the error for referencing later
|
||||
if firstErr == nil {
|
||||
@@ -305,7 +304,7 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rc, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
|
||||
rc, _, err := r.open(ctx, req, desc.MediaType, offset, i == len(r.hosts)-1)
|
||||
if err != nil {
|
||||
// Store the error for referencing later
|
||||
if firstErr == nil {
|
||||
@@ -419,8 +418,9 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest, op
|
||||
return nil, desc, firstErr
|
||||
}
|
||||
|
||||
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (io.ReadCloser, error) {
|
||||
return r.open(ctx, getReq, config.Mediatype, offset, true)
|
||||
seeker, err := newHTTPReadSeeker(sz, func(offset int64) (rc io.ReadCloser, err error) {
|
||||
rc, _, err = r.open(ctx, getReq, config.Mediatype, offset, true)
|
||||
return
|
||||
})
|
||||
if err != nil {
|
||||
return nil, desc, err
|
||||
@@ -437,7 +437,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest, op
|
||||
return seeker, desc, nil
|
||||
}
|
||||
|
||||
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64, lastHost bool) (_ io.ReadCloser, retErr error) {
|
||||
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64, lastHost bool) (_ io.ReadCloser, _ int64, retErr error) {
|
||||
const minChunkSize = 512
|
||||
|
||||
chunkSize := int64(r.performances.ConcurrentLayerFetchBuffer)
|
||||
@@ -457,29 +457,42 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
|
||||
}
|
||||
|
||||
if err := r.Acquire(ctx, 1); err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
resp, err := req.doWithRetries(ctx, lastHost, withErrorCheck, withOffsetCheck(offset))
|
||||
var remaining int64
|
||||
resp, err := req.doWithRetries(ctx, lastHost, withErrorCheck, withOffsetCheck(offset, parallelism))
|
||||
switch err {
|
||||
case nil:
|
||||
// all good
|
||||
remaining = resp.ContentLength
|
||||
case errContentRangeIgnored:
|
||||
if parallelism != 1 {
|
||||
log.G(ctx).WithError(err).Info("remote host ignored content range, forcing parallelism to 1")
|
||||
parallelism = 1
|
||||
}
|
||||
remaining = resp.ContentLength - offset
|
||||
default:
|
||||
log.G(ctx).WithError(err).Debug("fetch failed")
|
||||
r.Release(1)
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
body := resp.Body
|
||||
body := &fnOnClose{
|
||||
BeforeClose: func() {
|
||||
r.Release(1)
|
||||
},
|
||||
ReadCloser: resp.Body,
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
body.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
encoding := strings.FieldsFunc(resp.Header.Get("Content-Encoding"), func(r rune) bool {
|
||||
return r == ' ' || r == '\t' || r == ','
|
||||
})
|
||||
|
||||
remaining, _ := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 0)
|
||||
if remaining <= chunkSize {
|
||||
parallelism = 1
|
||||
}
|
||||
@@ -505,29 +518,33 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
|
||||
for i := range numChunks {
|
||||
readers[i], writers[i] = newPipeWriter(bufPool)
|
||||
}
|
||||
// keep reference of the initial body value to ensure it is closed
|
||||
ibody := body
|
||||
go func() {
|
||||
for i := range numChunks {
|
||||
select {
|
||||
case queue <- i:
|
||||
case <-done:
|
||||
if i == 0 {
|
||||
ibody.Close()
|
||||
}
|
||||
return // avoid leaking a goroutine if we exit early.
|
||||
}
|
||||
}
|
||||
close(queue)
|
||||
}()
|
||||
r.Release(1)
|
||||
for range parallelism {
|
||||
go func() {
|
||||
for i := range queue { // first in first out
|
||||
copy := func() error {
|
||||
if err := r.Acquire(ctx, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Release(1)
|
||||
var body io.ReadCloser
|
||||
if i == 0 {
|
||||
body = resp.Body
|
||||
body = ibody
|
||||
} else {
|
||||
if err := r.Acquire(ctx, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Release(1)
|
||||
reqClone := req.clone()
|
||||
reqClone.setOffset(offset + i*chunkSize)
|
||||
nresp, err := reqClone.doWithRetries(ctx, lastHost, withErrorCheck)
|
||||
@@ -564,40 +581,35 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string,
|
||||
},
|
||||
ReadCloser: io.NopCloser(io.MultiReader(readers...)),
|
||||
}
|
||||
} else {
|
||||
body = &fnOnClose{
|
||||
BeforeClose: func() {
|
||||
r.Release(1)
|
||||
},
|
||||
ReadCloser: body,
|
||||
}
|
||||
}
|
||||
|
||||
for i := len(encoding) - 1; i >= 0; i-- {
|
||||
algorithm := strings.ToLower(encoding[i])
|
||||
switch algorithm {
|
||||
case "zstd":
|
||||
r, err := zstd.NewReader(body,
|
||||
r, err := zstd.NewReader(body.ReadCloser,
|
||||
zstd.WithDecoderLowmem(false),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
body = r.IOReadCloser()
|
||||
body.ReadCloser = r.IOReadCloser()
|
||||
case "gzip":
|
||||
body, err = gzip.NewReader(body)
|
||||
r, err := gzip.NewReader(body.ReadCloser)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, 0, err
|
||||
}
|
||||
body.ReadCloser = r
|
||||
case "deflate":
|
||||
body = flate.NewReader(body)
|
||||
body.ReadCloser = flate.NewReader(body.ReadCloser)
|
||||
case "identity", "":
|
||||
// no content-encoding applied, use raw body
|
||||
default:
|
||||
return nil, errors.New("unsupported Content-Encoding algorithm: " + algorithm)
|
||||
return nil, 0, errors.New("unsupported Content-Encoding algorithm: " + algorithm)
|
||||
}
|
||||
}
|
||||
|
||||
return body, nil
|
||||
return body, remaining, nil
|
||||
}
|
||||
|
||||
type fnOnClose struct {
|
||||
|
||||
@@ -59,7 +59,8 @@ func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
|
||||
if n > 0 || err == nil {
|
||||
hrs.errsWithNoProgress = 0
|
||||
}
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
switch err {
|
||||
case io.ErrUnexpectedEOF:
|
||||
// connection closed unexpectedly. try reconnecting.
|
||||
if n == 0 {
|
||||
hrs.errsWithNoProgress++
|
||||
@@ -76,7 +77,7 @@ func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
|
||||
if _, err2 := hrs.reader(); err2 == nil {
|
||||
return n, nil
|
||||
}
|
||||
} else if err == io.EOF {
|
||||
case io.EOF:
|
||||
// The CRI's imagePullProgressTimeout relies on responseBody.Close to
|
||||
// update the process monitor's status. If the err is io.EOF, close
|
||||
// the connection since there is no more available data.
|
||||
@@ -102,6 +103,36 @@ func (hrs *httpReadSeeker) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) ReadAt(p []byte, offset int64) (n int, err error) {
|
||||
if hrs.closed {
|
||||
return 0, fmt.Errorf("httpReadSeeker.ReadAt: closed: %w", errdefs.ErrUnavailable)
|
||||
}
|
||||
|
||||
if offset < 0 {
|
||||
return 0, fmt.Errorf("httpReadSeeker.ReadAt: negative offset: %w", errdefs.ErrInvalidArgument)
|
||||
}
|
||||
|
||||
if hrs.size != -1 && offset >= hrs.size {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if hrs.open == nil {
|
||||
return 0, fmt.Errorf("httpReadSeeker.ReadAt: cannot open: %w", errdefs.ErrNotImplemented)
|
||||
}
|
||||
|
||||
rc, err := hrs.open(offset)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("httpReadSeeker.ReadAt: failed to open at offset %d: %w", offset, err)
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := rc.Close(); closeErr != nil {
|
||||
log.L.WithError(closeErr).Error("httpReadSeeker.ReadAt: failed to close ReadCloser")
|
||||
}
|
||||
}()
|
||||
|
||||
return io.ReadFull(rc, p)
|
||||
}
|
||||
|
||||
func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
|
||||
if hrs.closed {
|
||||
return 0, fmt.Errorf("Fetcher.Seek: closed: %w", errdefs.ErrUnavailable)
|
||||
|
||||
@@ -526,15 +526,21 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
|
||||
|
||||
if expected == "" {
|
||||
expected = status.Expected
|
||||
} else if expected != status.Expected {
|
||||
return fmt.Errorf("unexpected digest received: got %q, expected %q", status.Expected, expected)
|
||||
}
|
||||
|
||||
actual, err := digest.Parse(resp.Header.Get("Docker-Content-Digest"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid content digest in response: %w", err)
|
||||
}
|
||||
if dgstHdr := resp.Header.Get("Docker-Content-Digest"); dgstHdr != "" {
|
||||
actual, err := digest.Parse(dgstHdr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid content digest in response: %w", err)
|
||||
}
|
||||
|
||||
if actual != expected {
|
||||
return fmt.Errorf("got digest %s, expected %s", actual, expected)
|
||||
if actual != expected {
|
||||
return fmt.Errorf("got digest %s, expected %s", actual, expected)
|
||||
}
|
||||
} else {
|
||||
log.G(ctx).Info("registry did not send a Docker-Content-Digest header")
|
||||
}
|
||||
|
||||
status.Committed = true
|
||||
|
||||
158
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/remotes/docker/referrers.go
generated
vendored
Normal file
158
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/remotes/docker/referrers.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/v2/core/remotes"
|
||||
"github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func (r dockerFetcher) FetchReferrers(ctx context.Context, dgst digest.Digest, opts ...remotes.FetchReferrersOpt) ([]ocispec.Descriptor, error) {
|
||||
var config remotes.FetchReferrersConfig
|
||||
for _, opt := range opts {
|
||||
opt(ctx, &config)
|
||||
}
|
||||
rc, size, err := r.openReferrers(ctx, dgst, config)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
return []ocispec.Descriptor{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer rc.Close()
|
||||
if size < 0 {
|
||||
size = MaxManifestSize
|
||||
} else if size > MaxManifestSize {
|
||||
return nil, fmt.Errorf("referrers index size %d exceeds maximum allowed %d: %w", size, MaxManifestSize, errdefs.ErrNotFound)
|
||||
}
|
||||
|
||||
var index ocispec.Index
|
||||
dec := json.NewDecoder(io.LimitReader(rc, size))
|
||||
if err := dec.Decode(&index); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode referrers index: %w", err)
|
||||
}
|
||||
if _, err := dec.Token(); !errors.Is(err, io.EOF) {
|
||||
return nil, fmt.Errorf("unexpected data after JSON object")
|
||||
}
|
||||
|
||||
if len(config.ArtifactTypes) == 0 {
|
||||
return index.Manifests, nil
|
||||
}
|
||||
|
||||
var referrers []ocispec.Descriptor
|
||||
tFilter := map[string]struct{}{}
|
||||
for _, t := range config.ArtifactTypes {
|
||||
tFilter[t] = struct{}{}
|
||||
}
|
||||
for _, desc := range index.Manifests {
|
||||
if _, ok := tFilter[desc.ArtifactType]; ok {
|
||||
referrers = append(referrers, desc)
|
||||
}
|
||||
}
|
||||
return referrers, nil
|
||||
}
|
||||
|
||||
func (r dockerFetcher) openReferrers(ctx context.Context, dgst digest.Digest, config remotes.FetchReferrersConfig) (io.ReadCloser, int64, error) {
|
||||
mediaType := ocispec.MediaTypeImageIndex
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst))
|
||||
|
||||
hosts := r.filterHosts(HostCapabilityReferrers)
|
||||
var fallbackHosts []RegistryHost
|
||||
if len(hosts) == 0 {
|
||||
fallbackHosts = r.filterHosts(HostCapabilityResolve)
|
||||
if len(fallbackHosts) == 0 {
|
||||
return nil, 0, fmt.Errorf("no referrers hosts: %w", errdefs.ErrNotFound)
|
||||
}
|
||||
} else {
|
||||
// If referrers are defined, use same hosts for fallback
|
||||
fallbackHosts = hosts
|
||||
}
|
||||
|
||||
ctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var firstErr error
|
||||
for i, host := range hosts {
|
||||
req := r.request(host, http.MethodGet, "referrers", dgst.String())
|
||||
for _, artifactType := range config.ArtifactTypes {
|
||||
if err := req.addQuery("artifactType", artifactType); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
for k, vs := range config.QueryFilters {
|
||||
for _, v := range vs {
|
||||
if err := req.addQuery(k, v); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := req.addNamespace(r.refspec.Hostname()); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
rc, cl, err := r.open(ctx, req, mediaType, 0, i == len(hosts)-1)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
log.G(ctx).WithError(err).WithField("host", host.Host).Debug("error fetching referrers")
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return rc, cl, nil
|
||||
}
|
||||
}
|
||||
|
||||
for i, host := range fallbackHosts {
|
||||
req := r.request(host, http.MethodGet, "manifests", strings.Replace(dgst.String(), ":", "-", 1))
|
||||
if err := req.addNamespace(r.refspec.Hostname()); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
rc, cl, err := r.open(ctx, req, mediaType, 0, i == len(fallbackHosts)-1)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
// Equivalent to empty referrers list
|
||||
firstErr = err
|
||||
break
|
||||
}
|
||||
log.G(ctx).WithError(err).WithField("host", host.Host).Debug("error fetching referrers via fallback")
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
} else {
|
||||
return rc, cl, nil
|
||||
}
|
||||
}
|
||||
if firstErr == nil {
|
||||
firstErr = fmt.Errorf("could not be found at any host: %w", errdefs.ErrNotFound)
|
||||
}
|
||||
|
||||
return nil, 0, firstErr
|
||||
}
|
||||
@@ -57,6 +57,10 @@ const (
|
||||
// manifests
|
||||
HostCapabilityPush
|
||||
|
||||
// HostCapabilityReferrers represents the capability to generate a
|
||||
// list of referrers using the OCI Distribution referrers endpoint.
|
||||
HostCapabilityReferrers
|
||||
|
||||
// Reserved for future capabilities (i.e. search, catalog, remove)
|
||||
)
|
||||
|
||||
@@ -168,7 +172,7 @@ func ConfigureDefaultRegistries(ropts ...RegistryOpt) RegistryHosts {
|
||||
Host: host,
|
||||
Scheme: "https",
|
||||
Path: "/v2",
|
||||
Capabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,
|
||||
Capabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush | HostCapabilityReferrers,
|
||||
}
|
||||
|
||||
if config.Client == nil {
|
||||
@@ -212,10 +216,10 @@ func MatchAllHosts(string) (bool, error) {
|
||||
// Note: this does not handle matching of ip addresses in octal,
|
||||
// decimal or hex form.
|
||||
func MatchLocalhost(host string) (bool, error) {
|
||||
switch {
|
||||
case host == "::1":
|
||||
switch host {
|
||||
case "::1":
|
||||
return true, nil
|
||||
case host == "[::1]":
|
||||
case "[::1]":
|
||||
return true, nil
|
||||
}
|
||||
h, p, err := net.SplitHostPort(host)
|
||||
|
||||
@@ -551,29 +551,33 @@ func (r *request) authorize(ctx context.Context, req *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) addNamespace(ns string) (err error) {
|
||||
if !r.host.isProxy(ns) {
|
||||
return nil
|
||||
}
|
||||
func (r *request) addQuery(key, value string) (err error) {
|
||||
var q url.Values
|
||||
// Parse query
|
||||
if i := strings.IndexByte(r.path, '?'); i > 0 {
|
||||
r.path = r.path[:i+1]
|
||||
q, err = url.ParseQuery(r.path[i+1:])
|
||||
if p, query, ok := strings.Cut(r.path, "?"); ok {
|
||||
q, err = url.ParseQuery(query)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r.path = p + "?"
|
||||
} else {
|
||||
r.path = r.path + "?"
|
||||
q = url.Values{}
|
||||
}
|
||||
q.Add("ns", ns)
|
||||
q.Add(key, value)
|
||||
|
||||
r.path = r.path + q.Encode()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *request) addNamespace(ns string) error {
|
||||
if !r.host.isProxy(ns) {
|
||||
return nil
|
||||
}
|
||||
return r.addQuery("ns", ns)
|
||||
}
|
||||
|
||||
type request struct {
|
||||
method string
|
||||
path string
|
||||
@@ -659,9 +663,9 @@ func withErrorCheck(r *request, resp *http.Response) error {
|
||||
|
||||
var errContentRangeIgnored = errors.New("content range requests ignored")
|
||||
|
||||
func withOffsetCheck(offset int64) doChecks {
|
||||
func withOffsetCheck(offset, parallelism int64) doChecks {
|
||||
return func(r *request, resp *http.Response) error {
|
||||
if offset == 0 {
|
||||
if parallelism <= 1 && offset == 0 {
|
||||
return nil
|
||||
}
|
||||
if resp.StatusCode == http.StatusPartialContent {
|
||||
|
||||
34
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/remotes/resolver.go
generated
vendored
34
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/core/remotes/resolver.go
generated
vendored
@@ -19,6 +19,7 @@ package remotes
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"github.com/containerd/containerd/v2/core/content"
|
||||
"github.com/containerd/containerd/v2/core/transfer"
|
||||
@@ -75,6 +76,10 @@ type FetcherByDigest interface {
|
||||
FetchByDigest(ctx context.Context, dgst digest.Digest, opts ...FetchByDigestOpts) (io.ReadCloser, ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
type ReferrersFetcher interface {
|
||||
FetchReferrers(ctx context.Context, dgst digest.Digest, opts ...FetchReferrersOpt) ([]ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
// Pusher pushes content
|
||||
type Pusher interface {
|
||||
// Push returns a content writer for the given resource identified
|
||||
@@ -116,3 +121,32 @@ func WithMediaType(mediatype string) FetchByDigestOpts {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type FetchReferrersConfig struct {
|
||||
// ArtifactTypes specifies the artifact types to filter referrers, this can be
|
||||
// applied to registry queries or filtering the results after fetching.
|
||||
ArtifactTypes []string
|
||||
// QueryFilters specifies additional filters which may get sent as query parameters
|
||||
QueryFilters url.Values
|
||||
}
|
||||
|
||||
type FetchReferrersOpt func(context.Context, *FetchReferrersConfig) error
|
||||
|
||||
// WithReferrerArtifactTypes sets the artifact types to filter referrers
|
||||
func WithReferrerArtifactTypes(artifactTypes ...string) FetchReferrersOpt {
|
||||
return func(ctx context.Context, cfg *FetchReferrersConfig) error {
|
||||
cfg.ArtifactTypes = artifactTypes
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithReferrerQueryFilter sets additional query filters for referrer fetching
|
||||
func WithReferrerQueryFilter(param, value string) FetchReferrersOpt {
|
||||
return func(ctx context.Context, cfg *FetchReferrersConfig) error {
|
||||
if cfg.QueryFilters == nil {
|
||||
cfg.QueryFilters = url.Values{}
|
||||
}
|
||||
cfg.QueryFilters.Add(param, value)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
5
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/defaults/defaults.go
generated
vendored
5
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/defaults/defaults.go
generated
vendored
@@ -29,4 +29,9 @@ const (
|
||||
// DefaultSnapshotterNSLabel defines the namespace label to check for the
|
||||
// default snapshotter
|
||||
DefaultSnapshotterNSLabel = "containerd.io/defaults/snapshotter"
|
||||
// DefaultSandboxerNSLabel defines the namespace label to check for the
|
||||
// default sandboxcr
|
||||
DefaultSandboxerNSLabel = "containerd.io/defaults/sandboxer"
|
||||
// DefaultSandboxer defines the default sandboxer to use for creating sandboxes.
|
||||
DefaultSandboxer = "shim"
|
||||
)
|
||||
|
||||
21
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/defaults/defaults_darwin.go
generated
vendored
21
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/defaults/defaults_darwin.go
generated
vendored
@@ -17,6 +17,23 @@
|
||||
package defaults
|
||||
|
||||
const (
|
||||
// DefaultRuntime would be a multiple of choices, thus empty
|
||||
DefaultRuntime = ""
|
||||
// DefaultRuntime is the default darwin runtime for running containers
|
||||
DefaultRuntime = "io.containerd.nerdbox.v1"
|
||||
// DefaultAddress is the default unix socket address
|
||||
DefaultAddress = "/var/run/containerd/containerd.sock"
|
||||
// DefaultDebugAddress is the default unix socket address for pprof data
|
||||
DefaultDebugAddress = "/var/run/containerd/debug.sock"
|
||||
// DefaultFIFODir is the default location used by client-side cio library
|
||||
// to store FIFOs.
|
||||
DefaultFIFODir = "/var/run/containerd/fifo"
|
||||
// DefaultSnapshotter will set the default snapshotter for the platform.
|
||||
// Since mounts are not supported on Darwin, use erofs as the default
|
||||
// which does not require mount support.
|
||||
DefaultSnapshotter = "erofs"
|
||||
// DefaultStateDir is the default location used by containerd to store
|
||||
// transient data
|
||||
DefaultStateDir = "/var/run/containerd"
|
||||
// DefaultDiffer will set the default differ for the platform, use the
|
||||
// erofs differ which does not require mount support.
|
||||
DefaultDiffer = "erofs"
|
||||
)
|
||||
|
||||
@@ -24,4 +24,7 @@ const (
|
||||
// DefaultRootDir is the default location used by containerd to store
|
||||
// persistent data
|
||||
DefaultRootDir = "/var/lib/containerd"
|
||||
|
||||
// DefaultConfigIncludePattern is the default location for drop-in configuration files.
|
||||
DefaultConfigIncludePattern = "/etc/containerd/conf.d/*.toml"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build unix && !linux
|
||||
//go:build unix && !linux && !darwin
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
@@ -31,6 +31,9 @@ var (
|
||||
|
||||
// DefaultConfigDir is the default location for config files.
|
||||
DefaultConfigDir = filepath.Join(os.Getenv("programfiles"), "containerd")
|
||||
|
||||
// DefaultConfigIncludePattern is the default location for drop-in configuration files.
|
||||
DefaultConfigIncludePattern = filepath.Join(os.Getenv("programfiles"), "containerd\\conf.d\\*.toml")
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -139,6 +139,9 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest,
|
||||
return err
|
||||
}
|
||||
|
||||
if err := syncDir(filepath.Dir(target)); err != nil {
|
||||
return err
|
||||
}
|
||||
// Enable content blob integrity verification if supported
|
||||
|
||||
if w.s.integritySupported {
|
||||
|
||||
37
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/plugins/content/local/writer_unix.go
generated
vendored
Normal file
37
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/plugins/content/local/writer_unix.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
//go:build !windows
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package local
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func syncDir(dir string) error {
|
||||
dirF, err := os.Open(dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open dir %s: %w", dir, err)
|
||||
}
|
||||
err = dirF.Sync()
|
||||
dirF.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to sync dir %s: %w", dir, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
22
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/plugins/content/local/writer_windows.go
generated
vendored
Normal file
22
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/plugins/content/local/writer_windows.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package local
|
||||
|
||||
// sync dir doesn't support in windows
|
||||
func syncDir(dir string) error {
|
||||
return nil
|
||||
}
|
||||
2
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/version/version.go
generated
vendored
2
src/cmd/linuxkit/vendor/github.com/containerd/containerd/v2/version/version.go
generated
vendored
@@ -24,7 +24,7 @@ var (
|
||||
Package = "github.com/containerd/containerd/v2"
|
||||
|
||||
// Version holds the complete version number. Filled in at linking time.
|
||||
Version = "2.1.3+unknown"
|
||||
Version = "2.2.0+unknown"
|
||||
|
||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||
// the program at linking time.
|
||||
|
||||
2
src/cmd/linuxkit/vendor/github.com/containerd/platforms/defaults_windows.go
generated
vendored
2
src/cmd/linuxkit/vendor/github.com/containerd/platforms/defaults_windows.go
generated
vendored
@@ -38,5 +38,5 @@ func DefaultSpec() specs.Platform {
|
||||
|
||||
// Default returns the current platform's default platform specification.
|
||||
func Default() MatchComparer {
|
||||
return Only(DefaultSpec())
|
||||
return &windowsMatchComparer{Matcher: NewMatcher(DefaultSpec())}
|
||||
}
|
||||
|
||||
48
src/cmd/linuxkit/vendor/github.com/containerd/platforms/platform_windows_compat.go
generated
vendored
48
src/cmd/linuxkit/vendor/github.com/containerd/platforms/platform_windows_compat.go
generated
vendored
@@ -42,18 +42,30 @@ const (
|
||||
// rs5 (version 1809, codename "Redstone 5") corresponds to Windows Server
|
||||
// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
|
||||
rs5 = 17763
|
||||
// ltsc2019 (Windows Server 2019) is an alias for [RS5].
|
||||
ltsc2019 = rs5
|
||||
|
||||
// v21H2Server corresponds to Windows Server 2022 (ltsc2022).
|
||||
v21H2Server = 20348
|
||||
// ltsc2022 (Windows Server 2022) is an alias for [v21H2Server]
|
||||
ltsc2022 = v21H2Server
|
||||
|
||||
// v22H2Win11 corresponds to Windows 11 (2022 Update).
|
||||
v22H2Win11 = 22621
|
||||
|
||||
// v23H2 is the 23H2 release in the Windows Server annual channel.
|
||||
v23H2 = 25398
|
||||
|
||||
// Windows Server 2025 build 26100
|
||||
v25H1Server = 26100
|
||||
ltsc2025 = v25H1Server
|
||||
)
|
||||
|
||||
// List of stable ABI compliant ltsc releases
|
||||
// Note: List must be sorted in ascending order
|
||||
var compatLTSCReleases = []uint16{
|
||||
v21H2Server,
|
||||
ltsc2022,
|
||||
ltsc2025,
|
||||
}
|
||||
|
||||
// CheckHostAndContainerCompat checks if given host and container
|
||||
@@ -70,18 +82,27 @@ func checkWindowsHostAndContainerCompat(host, ctr windowsOSVersion) bool {
|
||||
}
|
||||
|
||||
// If host is < WS 2022, exact version match is required
|
||||
if host.Build < v21H2Server {
|
||||
if host.Build < ltsc2022 {
|
||||
return host.Build == ctr.Build
|
||||
}
|
||||
|
||||
var supportedLtscRelease uint16
|
||||
// Find the latest LTSC version that is earlier than the host version.
|
||||
// This is the earliest version of container that the host can run.
|
||||
//
|
||||
// If the host version is an LTSC, then it supports compatibility with
|
||||
// everything from the previous LTSC up to itself, so we want supportedLTSCRelease
|
||||
// to be the previous entry.
|
||||
//
|
||||
// If no match is found, then we know that the host is LTSC2022 exactly,
|
||||
// since we already checked that it's not less than LTSC2022.
|
||||
var supportedLTSCRelease uint16 = ltsc2022
|
||||
for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
|
||||
if host.Build >= compatLTSCReleases[i] {
|
||||
supportedLtscRelease = compatLTSCReleases[i]
|
||||
if host.Build > compatLTSCReleases[i] {
|
||||
supportedLTSCRelease = compatLTSCReleases[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
|
||||
return supportedLTSCRelease <= ctr.Build && ctr.Build <= host.Build
|
||||
}
|
||||
|
||||
func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion {
|
||||
@@ -114,18 +135,6 @@ func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion {
|
||||
}
|
||||
}
|
||||
|
||||
func winRevision(v string) int {
|
||||
parts := strings.Split(v, ".")
|
||||
if len(parts) < 4 {
|
||||
return 0
|
||||
}
|
||||
r, err := strconv.Atoi(parts[3])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
type windowsVersionMatcher struct {
|
||||
windowsOSVersion
|
||||
}
|
||||
@@ -149,8 +158,7 @@ type windowsMatchComparer struct {
|
||||
func (c *windowsMatchComparer) Less(p1, p2 specs.Platform) bool {
|
||||
m1, m2 := c.Match(p1), c.Match(p2)
|
||||
if m1 && m2 {
|
||||
r1, r2 := winRevision(p1.OSVersion), winRevision(p2.OSVersion)
|
||||
return r1 > r2
|
||||
return p1.OSVersion > p2.OSVersion
|
||||
}
|
||||
return m1 && !m2
|
||||
}
|
||||
|
||||
8
src/cmd/linuxkit/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go
generated
vendored
8
src/cmd/linuxkit/vendor/github.com/containerd/stargz-snapshotter/estargz/build.go
generated
vendored
@@ -408,11 +408,11 @@ func readerFromEntries(entries ...*entry) io.Reader {
|
||||
defer tw.Close()
|
||||
for _, entry := range entries {
|
||||
if err := tw.WriteHeader(entry.header); err != nil {
|
||||
pw.CloseWithError(fmt.Errorf("Failed to write tar header: %v", err))
|
||||
pw.CloseWithError(fmt.Errorf("failed to write tar header: %v", err))
|
||||
return
|
||||
}
|
||||
if _, err := io.Copy(tw, entry.payload); err != nil {
|
||||
pw.CloseWithError(fmt.Errorf("Failed to write tar payload: %v", err))
|
||||
pw.CloseWithError(fmt.Errorf("failed to write tar payload: %v", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -627,12 +627,12 @@ func (cr *countReadSeeker) Seek(offset int64, whence int) (int64, error) {
|
||||
|
||||
switch whence {
|
||||
default:
|
||||
return 0, fmt.Errorf("Unknown whence: %v", whence)
|
||||
return 0, fmt.Errorf("unknown whence: %v", whence)
|
||||
case io.SeekStart:
|
||||
case io.SeekCurrent:
|
||||
offset += *cr.cPos
|
||||
case io.SeekEnd:
|
||||
return 0, fmt.Errorf("Unsupported whence: %v", whence)
|
||||
return 0, fmt.Errorf("unsupported whence: %v", whence)
|
||||
}
|
||||
|
||||
if offset < 0 {
|
||||
|
||||
6
src/cmd/linuxkit/vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go
generated
vendored
6
src/cmd/linuxkit/vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go
generated
vendored
@@ -109,7 +109,7 @@ func gzipFooterBytes(tocOff int64) []byte {
|
||||
header[0], header[1] = 'S', 'G'
|
||||
subfield := fmt.Sprintf("%016xSTARGZ", tocOff)
|
||||
binary.LittleEndian.PutUint16(header[2:4], uint16(len(subfield))) // little-endian per RFC1952
|
||||
gz.Header.Extra = append(header, []byte(subfield)...)
|
||||
gz.Extra = append(header, []byte(subfield)...)
|
||||
gz.Close()
|
||||
if buf.Len() != FooterSize {
|
||||
panic(fmt.Sprintf("footer buffer = %d, not %d", buf.Len(), FooterSize))
|
||||
@@ -136,7 +136,7 @@ func (gz *GzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOffset, t
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
defer zr.Close()
|
||||
extra := zr.Header.Extra
|
||||
extra := zr.Extra
|
||||
si1, si2, subfieldlen, subfield := extra[0], extra[1], extra[2:4], extra[4:]
|
||||
if si1 != 'S' || si2 != 'G' {
|
||||
return 0, 0, 0, fmt.Errorf("invalid subfield IDs: %q, %q; want E, S", si1, si2)
|
||||
@@ -181,7 +181,7 @@ func (gz *LegacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOff
|
||||
return 0, 0, 0, fmt.Errorf("legacy: failed to get footer gzip reader: %w", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
extra := zr.Header.Extra
|
||||
extra := zr.Extra
|
||||
if len(extra) != 16+len("STARGZ") {
|
||||
return 0, 0, 0, fmt.Errorf("legacy: invalid stargz's extra field size")
|
||||
}
|
||||
|
||||
13
src/cmd/linuxkit/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go
generated
vendored
13
src/cmd/linuxkit/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go
generated
vendored
@@ -357,14 +357,15 @@ func compressBlob(t *testing.T, src *io.SectionReader, srcCompression int) *io.S
|
||||
buf := new(bytes.Buffer)
|
||||
var w io.WriteCloser
|
||||
var err error
|
||||
if srcCompression == gzipType {
|
||||
switch srcCompression {
|
||||
case gzipType:
|
||||
w = gzip.NewWriter(buf)
|
||||
} else if srcCompression == zstdType {
|
||||
case zstdType:
|
||||
w, err = zstd.NewWriter(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to init zstd writer: %v", err)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
return src
|
||||
}
|
||||
src.Seek(0, io.SeekStart)
|
||||
@@ -445,7 +446,7 @@ func contains(t *testing.T, a, b stargzEntry) bool {
|
||||
bbytes, bnext, bok := readOffset(t, bf, nr, b)
|
||||
if !aok && !bok {
|
||||
break
|
||||
} else if !(aok && bok) || anext != bnext {
|
||||
} else if !aok || !bok || anext != bnext {
|
||||
t.Logf("%q != %q (offset=%d): chunk existence a=%v vs b=%v, anext=%v vs bnext=%v",
|
||||
ae.Name, be.Name, nr, aok, bok, anext, bnext)
|
||||
return false
|
||||
@@ -2346,8 +2347,8 @@ func CheckGzipHasStreams(t *testing.T, b []byte, streams []int64) {
|
||||
t.Fatalf("countStreams(gzip), Copy: %v", err)
|
||||
}
|
||||
var extra string
|
||||
if len(zr.Header.Extra) > 0 {
|
||||
extra = fmt.Sprintf("; extra=%q", zr.Header.Extra)
|
||||
if len(zr.Extra) > 0 {
|
||||
extra = fmt.Sprintf("; extra=%q", zr.Extra)
|
||||
}
|
||||
t.Logf(" [%d] at %d in stargz, uncompressed length %d%s", numStreams, zoff, n, extra)
|
||||
delete(wants, int64(zoff))
|
||||
|
||||
102
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/cli.go
generated
vendored
102
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/cli.go
generated
vendored
@@ -48,9 +48,7 @@ type Cli interface {
|
||||
Apply(ops ...CLIOption) error
|
||||
config.Provider
|
||||
ServerInfo() ServerInfo
|
||||
DefaultVersion() string
|
||||
CurrentVersion() string
|
||||
ContentTrustEnabled() bool
|
||||
BuildKitEnabled() (bool, error)
|
||||
ContextStore() store.Store
|
||||
CurrentContext() string
|
||||
@@ -78,6 +76,7 @@ type DockerCli struct {
|
||||
dockerEndpoint docker.Endpoint
|
||||
contextStoreConfig *store.Config
|
||||
initTimeout time.Duration
|
||||
userAgent string
|
||||
res telemetryResource
|
||||
|
||||
// baseCtx is the base context used for internal operations. In the future
|
||||
@@ -89,6 +88,8 @@ type DockerCli struct {
|
||||
}
|
||||
|
||||
// DefaultVersion returns [api.DefaultVersion].
|
||||
//
|
||||
// Deprecated: this function is no longer used and will be removed in the next release.
|
||||
func (*DockerCli) DefaultVersion() string {
|
||||
return api.DefaultVersion
|
||||
}
|
||||
@@ -159,6 +160,8 @@ func (cli *DockerCli) ServerInfo() ServerInfo {
|
||||
|
||||
// ContentTrustEnabled returns whether content trust has been enabled by an
|
||||
// environment variable.
|
||||
//
|
||||
// Deprecated: check the value of the DOCKER_CONTENT_TRUST environment variable to detect whether content-trust is enabled.
|
||||
func (cli *DockerCli) ContentTrustEnabled() bool {
|
||||
return cli.contentTrust
|
||||
}
|
||||
@@ -269,7 +272,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
|
||||
cli.contextStore = &ContextStoreWithDefault{
|
||||
Store: store.New(config.ContextStoreDir(), *cli.contextStoreConfig),
|
||||
Resolver: func() (*DefaultContext, error) {
|
||||
return ResolveDefaultContext(cli.options, *cli.contextStoreConfig)
|
||||
return resolveDefaultContext(cli.options, *cli.contextStoreConfig)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -282,6 +285,17 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
|
||||
}
|
||||
filterResourceAttributesEnvvar()
|
||||
|
||||
// early return if GODEBUG is already set or the docker context is
|
||||
// the default context, i.e. is a virtual context where we won't override
|
||||
// any GODEBUG values.
|
||||
if v := os.Getenv("GODEBUG"); cli.currentContext == DefaultContextName || v != "" {
|
||||
return nil
|
||||
}
|
||||
meta, err := cli.contextStore.GetMetadata(cli.currentContext)
|
||||
if err == nil {
|
||||
setGoDebug(meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -295,17 +309,17 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
|
||||
contextStore := &ContextStoreWithDefault{
|
||||
Store: store.New(config.ContextStoreDir(), storeConfig),
|
||||
Resolver: func() (*DefaultContext, error) {
|
||||
return ResolveDefaultContext(opts, storeConfig)
|
||||
return resolveDefaultContext(opts, storeConfig)
|
||||
},
|
||||
}
|
||||
endpoint, err := resolveDockerEndpoint(contextStore, resolveContextName(opts, configFile))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to resolve docker endpoint")
|
||||
}
|
||||
return newAPIClientFromEndpoint(endpoint, configFile)
|
||||
return newAPIClientFromEndpoint(endpoint, configFile, client.WithUserAgent(UserAgent()))
|
||||
}
|
||||
|
||||
func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigFile) (client.APIClient, error) {
|
||||
func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigFile, extraOpts ...client.Opt) (client.APIClient, error) {
|
||||
opts, err := ep.ClientOpts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -313,7 +327,14 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
|
||||
if len(configFile.HTTPHeaders) > 0 {
|
||||
opts = append(opts, client.WithHTTPHeaders(configFile.HTTPHeaders))
|
||||
}
|
||||
opts = append(opts, withCustomHeadersFromEnv(), client.WithUserAgent(UserAgent()))
|
||||
withCustomHeaders, err := withCustomHeadersFromEnv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if withCustomHeaders != nil {
|
||||
opts = append(opts, withCustomHeaders)
|
||||
}
|
||||
opts = append(opts, extraOpts...)
|
||||
return client.NewClientWithOpts(opts...)
|
||||
}
|
||||
|
||||
@@ -475,6 +496,57 @@ func (cli *DockerCli) getDockerEndPoint() (ep docker.Endpoint, err error) {
|
||||
return resolveDockerEndpoint(cli.contextStore, cn)
|
||||
}
|
||||
|
||||
// setGoDebug is an escape hatch that sets the GODEBUG environment
|
||||
// variable value using docker context metadata.
|
||||
//
|
||||
// {
|
||||
// "Name": "my-context",
|
||||
// "Metadata": { "GODEBUG": "x509negativeserial=1" }
|
||||
// }
|
||||
//
|
||||
// WARNING: Setting x509negativeserial=1 allows Go's x509 library to accept
|
||||
// X.509 certificates with negative serial numbers.
|
||||
// This behavior is deprecated and non-compliant with current security
|
||||
// standards (RFC 5280). Accepting negative serial numbers can introduce
|
||||
// serious security vulnerabilities, including the risk of certificate
|
||||
// collision or bypass attacks.
|
||||
// This option should only be used for legacy compatibility and never in
|
||||
// production environments.
|
||||
// Use at your own risk.
|
||||
func setGoDebug(meta store.Metadata) {
|
||||
fieldName := "GODEBUG"
|
||||
godebugEnv := os.Getenv(fieldName)
|
||||
// early return if GODEBUG is already set. We don't want to override what
|
||||
// the user already sets.
|
||||
if godebugEnv != "" {
|
||||
return
|
||||
}
|
||||
|
||||
var cfg any
|
||||
var ok bool
|
||||
switch m := meta.Metadata.(type) {
|
||||
case DockerContext:
|
||||
cfg, ok = m.AdditionalFields[fieldName]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
case map[string]any:
|
||||
cfg, ok = m[fieldName]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
v, ok := cfg.(string)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
// set the GODEBUG environment variable with whatever was in the context
|
||||
_ = os.Setenv(fieldName, v)
|
||||
}
|
||||
|
||||
func (cli *DockerCli) initialize() error {
|
||||
cli.init.Do(func() {
|
||||
cli.dockerEndpoint, cli.initErr = cli.getDockerEndPoint()
|
||||
@@ -483,7 +555,8 @@ func (cli *DockerCli) initialize() error {
|
||||
return
|
||||
}
|
||||
if cli.client == nil {
|
||||
if cli.client, cli.initErr = newAPIClientFromEndpoint(cli.dockerEndpoint, cli.configFile); cli.initErr != nil {
|
||||
ops := []client.Opt{client.WithUserAgent(cli.userAgent)}
|
||||
if cli.client, cli.initErr = newAPIClientFromEndpoint(cli.dockerEndpoint, cli.configFile, ops...); cli.initErr != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -496,6 +569,8 @@ func (cli *DockerCli) initialize() error {
|
||||
}
|
||||
|
||||
// Apply all the operation on the cli
|
||||
//
|
||||
// Deprecated: this method is no longer used and will be removed in the next release if there are no remaining users.
|
||||
func (cli *DockerCli) Apply(ops ...CLIOption) error {
|
||||
for _, op := range ops {
|
||||
if err := op(cli); err != nil {
|
||||
@@ -527,15 +602,18 @@ type ServerInfo struct {
|
||||
// environment.
|
||||
func NewDockerCli(ops ...CLIOption) (*DockerCli, error) {
|
||||
defaultOps := []CLIOption{
|
||||
WithContentTrustFromEnv(),
|
||||
withContentTrustFromEnv(),
|
||||
WithDefaultContextStoreConfig(),
|
||||
WithStandardStreams(),
|
||||
WithUserAgent(UserAgent()),
|
||||
}
|
||||
ops = append(defaultOps, ops...)
|
||||
|
||||
cli := &DockerCli{baseCtx: context.Background()}
|
||||
if err := cli.Apply(ops...); err != nil {
|
||||
return nil, err
|
||||
for _, op := range ops {
|
||||
if err := op(cli); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cli, nil
|
||||
}
|
||||
@@ -551,7 +629,7 @@ func getServerHost(hosts []string, defaultToTLS bool) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// UserAgent returns the user agent string used for making API requests
|
||||
// UserAgent returns the default user agent string used for making API requests.
|
||||
func UserAgent() string {
|
||||
return "Docker-Client/" + version.Version + " (" + runtime.GOOS + ")"
|
||||
}
|
||||
|
||||
118
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/cli_options.go
generated
vendored
118
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/cli_options.go
generated
vendored
@@ -75,8 +75,8 @@ func WithErrorStream(err io.Writer) CLIOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithContentTrustFromEnv enables content trust on a cli from environment variable DOCKER_CONTENT_TRUST value.
|
||||
func WithContentTrustFromEnv() CLIOption {
|
||||
// withContentTrustFromEnv enables content trust on a cli from environment variable DOCKER_CONTENT_TRUST value.
|
||||
func withContentTrustFromEnv() CLIOption {
|
||||
return func(cli *DockerCli) error {
|
||||
cli.contentTrust = false
|
||||
if e := os.Getenv("DOCKER_CONTENT_TRUST"); e != "" {
|
||||
@@ -89,7 +89,16 @@ func WithContentTrustFromEnv() CLIOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithContentTrustFromEnv enables content trust on a cli from environment variable DOCKER_CONTENT_TRUST value.
|
||||
//
|
||||
// Deprecated: this option is no longer used, and will be removed in the next release.
|
||||
func WithContentTrustFromEnv() CLIOption {
|
||||
return withContentTrustFromEnv()
|
||||
}
|
||||
|
||||
// WithContentTrust enables content trust on a cli.
|
||||
//
|
||||
// Deprecated: this option is no longer used, and will be removed in the next release.
|
||||
func WithContentTrust(enabled bool) CLIOption {
|
||||
return func(cli *DockerCli) error {
|
||||
cli.contentTrust = enabled
|
||||
@@ -180,61 +189,70 @@ const envOverrideHTTPHeaders = "DOCKER_CUSTOM_HEADERS"
|
||||
// override headers with the same name).
|
||||
//
|
||||
// TODO(thaJeztah): this is a client Option, and should be moved to the client. It is non-exported for that reason.
|
||||
func withCustomHeadersFromEnv() client.Opt {
|
||||
return func(apiClient *client.Client) error {
|
||||
value := os.Getenv(envOverrideHTTPHeaders)
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
csvReader := csv.NewReader(strings.NewReader(value))
|
||||
fields, err := csvReader.Read()
|
||||
if err != nil {
|
||||
return invalidParameter(errors.Errorf(
|
||||
"failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs",
|
||||
envOverrideHTTPHeaders,
|
||||
func withCustomHeadersFromEnv() (client.Opt, error) {
|
||||
value := os.Getenv(envOverrideHTTPHeaders)
|
||||
if value == "" {
|
||||
return nil, nil
|
||||
}
|
||||
csvReader := csv.NewReader(strings.NewReader(value))
|
||||
fields, err := csvReader.Read()
|
||||
if err != nil {
|
||||
return nil, invalidParameter(errors.Errorf(
|
||||
"failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs",
|
||||
envOverrideHTTPHeaders,
|
||||
))
|
||||
}
|
||||
if len(fields) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
env := map[string]string{}
|
||||
for _, kv := range fields {
|
||||
k, v, hasValue := strings.Cut(kv, "=")
|
||||
|
||||
// Only strip whitespace in keys; preserve whitespace in values.
|
||||
k = strings.TrimSpace(k)
|
||||
|
||||
if k == "" {
|
||||
return nil, invalidParameter(errors.Errorf(
|
||||
`failed to set custom headers from %s environment variable: value contains a key=value pair with an empty key: '%s'`,
|
||||
envOverrideHTTPHeaders, kv,
|
||||
))
|
||||
}
|
||||
if len(fields) == 0 {
|
||||
return nil
|
||||
|
||||
// We don't currently allow empty key=value pairs, and produce an error.
|
||||
// This is something we could allow in future (e.g. to read value
|
||||
// from an environment variable with the same name). In the meantime,
|
||||
// produce an error to prevent users from depending on this.
|
||||
if !hasValue {
|
||||
return nil, invalidParameter(errors.Errorf(
|
||||
`failed to set custom headers from %s environment variable: missing "=" in key=value pair: '%s'`,
|
||||
envOverrideHTTPHeaders, kv,
|
||||
))
|
||||
}
|
||||
|
||||
env := map[string]string{}
|
||||
for _, kv := range fields {
|
||||
k, v, hasValue := strings.Cut(kv, "=")
|
||||
env[http.CanonicalHeaderKey(k)] = v
|
||||
}
|
||||
|
||||
// Only strip whitespace in keys; preserve whitespace in values.
|
||||
k = strings.TrimSpace(k)
|
||||
if len(env) == 0 {
|
||||
// We should probably not hit this case, as we don't skip values
|
||||
// (only return errors), but we don't want to discard existing
|
||||
// headers with an empty set.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if k == "" {
|
||||
return invalidParameter(errors.Errorf(
|
||||
`failed to set custom headers from %s environment variable: value contains a key=value pair with an empty key: '%s'`,
|
||||
envOverrideHTTPHeaders, kv,
|
||||
))
|
||||
}
|
||||
// TODO(thaJeztah): add a client.WithExtraHTTPHeaders() function to allow these headers to be _added_ to existing ones, instead of _replacing_
|
||||
// see https://github.com/docker/cli/pull/5098#issuecomment-2147403871 (when updating, also update the WARNING in the function and env-var GoDoc)
|
||||
return client.WithHTTPHeaders(env), nil
|
||||
}
|
||||
|
||||
// We don't currently allow empty key=value pairs, and produce an error.
|
||||
// This is something we could allow in future (e.g. to read value
|
||||
// from an environment variable with the same name). In the meantime,
|
||||
// produce an error to prevent users from depending on this.
|
||||
if !hasValue {
|
||||
return invalidParameter(errors.Errorf(
|
||||
`failed to set custom headers from %s environment variable: missing "=" in key=value pair: '%s'`,
|
||||
envOverrideHTTPHeaders, kv,
|
||||
))
|
||||
}
|
||||
|
||||
env[http.CanonicalHeaderKey(k)] = v
|
||||
// WithUserAgent configures the User-Agent string for cli HTTP requests.
|
||||
func WithUserAgent(userAgent string) CLIOption {
|
||||
return func(cli *DockerCli) error {
|
||||
if userAgent == "" {
|
||||
return errors.New("user agent cannot be blank")
|
||||
}
|
||||
|
||||
if len(env) == 0 {
|
||||
// We should probably not hit this case, as we don't skip values
|
||||
// (only return errors), but we don't want to discard existing
|
||||
// headers with an empty set.
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(thaJeztah): add a client.WithExtraHTTPHeaders() function to allow these headers to be _added_ to existing ones, instead of _replacing_
|
||||
// see https://github.com/docker/cli/pull/5098#issuecomment-2147403871 (when updating, also update the WARNING in the function and env-var GoDoc)
|
||||
return client.WithHTTPHeaders(env)(apiClient)
|
||||
cli.userAgent = userAgent
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
7
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/defaultcontextstore.go
generated
vendored
7
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/defaultcontextstore.go
generated
vendored
@@ -52,7 +52,14 @@ type EndpointDefaultResolver interface {
|
||||
}
|
||||
|
||||
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
|
||||
//
|
||||
// Deprecated: this function is exported for testing and meant for internal use. It will be removed in the next release.
|
||||
func ResolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) {
|
||||
return resolveDefaultContext(opts, config)
|
||||
}
|
||||
|
||||
// resolveDefaultContext creates a Metadata for the current CLI invocation parameters
|
||||
func resolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) {
|
||||
contextTLSData := store.ContextTLSData{
|
||||
Endpoints: make(map[string]store.EndpointTLSData),
|
||||
}
|
||||
|
||||
102
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/registry.go
generated
vendored
102
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/registry.go
generated
vendored
@@ -31,11 +31,13 @@ const (
|
||||
// authConfigKey is the key used to store credentials for Docker Hub. It is
|
||||
// a copy of [registry.IndexServer].
|
||||
//
|
||||
// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker/registry#IndexServer
|
||||
// [registry.IndexServer]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#IndexServer
|
||||
const authConfigKey = "https://index.docker.io/v1/"
|
||||
|
||||
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
|
||||
// for the given command.
|
||||
// for the given command to prompt the user for username and password.
|
||||
//
|
||||
// Deprecated: this function is no longer used and will be removed in the next release.
|
||||
func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) registrytypes.RequestAuthConfig {
|
||||
configKey := getAuthConfigKey(index.Name)
|
||||
isDefaultRegistry := configKey == authConfigKey || index.Official
|
||||
@@ -43,7 +45,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
_, _ = fmt.Fprintf(cli.Out(), "\nLogin prior to %s:\n", cmdName)
|
||||
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, configKey, isDefaultRegistry)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", authConfigKey, err)
|
||||
_, _ = fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", configKey, err)
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -52,7 +54,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
default:
|
||||
}
|
||||
|
||||
authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, authConfigKey)
|
||||
authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, configKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -66,6 +68,8 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||
//
|
||||
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
|
||||
// store, instead of looking up credentials from a map.
|
||||
//
|
||||
// [registry.ResolveAuthConfig]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#ResolveAuthConfig
|
||||
func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
|
||||
configKey := index.Name
|
||||
if index.Official {
|
||||
@@ -73,7 +77,16 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf
|
||||
}
|
||||
|
||||
a, _ := cfg.GetAuthConfig(configKey)
|
||||
return registrytypes.AuthConfig(a)
|
||||
return registrytypes.AuthConfig{
|
||||
Username: a.Username,
|
||||
Password: a.Password,
|
||||
ServerAddress: a.ServerAddress,
|
||||
|
||||
// TODO(thaJeztah): Are these expected to be included?
|
||||
Auth: a.Auth,
|
||||
IdentityToken: a.IdentityToken,
|
||||
RegistryToken: a.RegistryToken,
|
||||
}
|
||||
}
|
||||
|
||||
// GetDefaultAuthConfig gets the default auth config given a serverAddress
|
||||
@@ -82,36 +95,27 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve
|
||||
if !isDefaultRegistry {
|
||||
serverAddress = credentials.ConvertToHostname(serverAddress)
|
||||
}
|
||||
authconfig := configtypes.AuthConfig{}
|
||||
authCfg := configtypes.AuthConfig{}
|
||||
var err error
|
||||
if checkCredStore {
|
||||
authconfig, err = cfg.GetAuthConfig(serverAddress)
|
||||
authCfg, err = cfg.GetAuthConfig(serverAddress)
|
||||
if err != nil {
|
||||
return registrytypes.AuthConfig{
|
||||
ServerAddress: serverAddress,
|
||||
}, err
|
||||
}
|
||||
}
|
||||
authconfig.ServerAddress = serverAddress
|
||||
authconfig.IdentityToken = ""
|
||||
return registrytypes.AuthConfig(authconfig), nil
|
||||
}
|
||||
|
||||
// ConfigureAuth handles prompting of user's username and password if needed.
|
||||
//
|
||||
// Deprecated: use [PromptUserForCredentials] instead.
|
||||
func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, authConfig *registrytypes.AuthConfig, _ bool) error {
|
||||
defaultUsername := authConfig.Username
|
||||
serverAddress := authConfig.ServerAddress
|
||||
return registrytypes.AuthConfig{
|
||||
Username: authCfg.Username,
|
||||
Password: authCfg.Password,
|
||||
ServerAddress: serverAddress,
|
||||
|
||||
newAuthConfig, err := PromptUserForCredentials(ctx, cli, flUser, flPassword, defaultUsername, serverAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authConfig.Username = newAuthConfig.Username
|
||||
authConfig.Password = newAuthConfig.Password
|
||||
return nil
|
||||
// TODO(thaJeztah): Are these expected to be included?
|
||||
Auth: authCfg.Auth,
|
||||
IdentityToken: "",
|
||||
RegistryToken: authCfg.RegistryToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PromptUserForCredentials handles the CLI prompt for the user to input
|
||||
@@ -209,47 +213,47 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete
|
||||
// image. The auth configuration is serialized as a base64url encoded RFC4648,
|
||||
// section 5) JSON string for sending through the X-Registry-Auth header.
|
||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a
|
||||
// complete image reference. The auth configuration is serialized as a
|
||||
// base64url encoded ([RFC 4648, Section 5]) JSON string for sending through
|
||||
// the "X-Registry-Auth" header.
|
||||
//
|
||||
// For details on base64url encoding, see:
|
||||
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
|
||||
// [RFC 4648, Section 5]: https://tools.ietf.org/html/rfc4648#section-5
|
||||
func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) {
|
||||
// Retrieve encoded auth token from the image reference
|
||||
authConfig, err := resolveAuthConfigFromImage(cfg, image)
|
||||
registryRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
|
||||
configKey := getAuthConfigKey(reference.Domain(registryRef))
|
||||
authConfig, err := cfg.GetAuthConfig(configKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
encodedAuth, err := registrytypes.EncodeAuthConfig(registrytypes.AuthConfig{
|
||||
Username: authConfig.Username,
|
||||
Password: authConfig.Password,
|
||||
ServerAddress: authConfig.ServerAddress,
|
||||
|
||||
// TODO(thaJeztah): Are these expected to be included?
|
||||
Auth: authConfig.Auth,
|
||||
IdentityToken: authConfig.IdentityToken,
|
||||
RegistryToken: authConfig.RegistryToken,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return encodedAuth, nil
|
||||
}
|
||||
|
||||
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
|
||||
func resolveAuthConfigFromImage(cfg *configfile.ConfigFile, image string) (registrytypes.AuthConfig, error) {
|
||||
registryRef, err := reference.ParseNormalizedNamed(image)
|
||||
if err != nil {
|
||||
return registrytypes.AuthConfig{}, err
|
||||
}
|
||||
configKey := getAuthConfigKey(reference.Domain(registryRef))
|
||||
a, err := cfg.GetAuthConfig(configKey)
|
||||
if err != nil {
|
||||
return registrytypes.AuthConfig{}, err
|
||||
}
|
||||
return registrytypes.AuthConfig(a), nil
|
||||
}
|
||||
|
||||
// getAuthConfigKey special-cases using the full index address of the official
|
||||
// index as the AuthConfig key, and uses the (host)name[:port] for private indexes.
|
||||
//
|
||||
// It is similar to [registry.GetAuthConfigKey], but does not require on
|
||||
// [registrytypes.IndexInfo] as intermediate.
|
||||
//
|
||||
// [registry.GetAuthConfigKey]: https://pkg.go.dev/github.com/docker/docker/registry#GetAuthConfigKey
|
||||
// [registrytypes.IndexInfo]:https://pkg.go.dev/github.com/docker/docker/api/types/registry#IndexInfo
|
||||
// [registry.GetAuthConfigKey]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/registry#GetAuthConfigKey
|
||||
// [registrytypes.IndexInfo]: https://pkg.go.dev/github.com/docker/docker@v28.3.3+incompatible/api/types/registry#IndexInfo
|
||||
func getAuthConfigKey(domainName string) string {
|
||||
if domainName == "docker.io" || domainName == "index.docker.io" {
|
||||
return authConfigKey
|
||||
|
||||
15
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/trust.go
generated
vendored
15
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/trust.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// AddTrustVerificationFlags adds content trust flags to the provided flagset
|
||||
func AddTrustVerificationFlags(fs *pflag.FlagSet, v *bool, trusted bool) {
|
||||
fs.BoolVar(v, "disable-content-trust", !trusted, "Skip image verification")
|
||||
}
|
||||
|
||||
// AddTrustSigningFlags adds "signing" flags to the provided flagset
|
||||
func AddTrustSigningFlags(fs *pflag.FlagSet, v *bool, trusted bool) {
|
||||
fs.BoolVar(v, "disable-content-trust", !trusted, "Skip image signing")
|
||||
}
|
||||
28
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/utils.go
generated
vendored
28
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/command/utils.go
generated
vendored
@@ -14,30 +14,20 @@ import (
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/cli/internal/prompt"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/moby/sys/atomicwriter"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// CopyToFile writes the content of the reader to the specified file
|
||||
// ErrPromptTerminated is returned if the user terminated the prompt.
|
||||
//
|
||||
// Deprecated: use [atomicwriter.New].
|
||||
func CopyToFile(outfile string, r io.Reader) error {
|
||||
writer, err := atomicwriter.New(outfile, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer writer.Close()
|
||||
_, err = io.Copy(writer, r)
|
||||
return err
|
||||
}
|
||||
|
||||
// Deprecated: this error is for internal use and will be removed in the next release.
|
||||
const ErrPromptTerminated = prompt.ErrTerminated
|
||||
|
||||
// DisableInputEcho disables input echo on the provided streams.In.
|
||||
// This is useful when the user provides sensitive information like passwords.
|
||||
// The function returns a restore function that should be called to restore the
|
||||
// terminal state.
|
||||
//
|
||||
// Deprecated: this function is for internal use and will be removed in the next release.
|
||||
func DisableInputEcho(ins *streams.In) (restore func() error, err error) {
|
||||
return prompt.DisableInputEcho(ins)
|
||||
}
|
||||
@@ -49,6 +39,8 @@ func DisableInputEcho(ins *streams.In) (restore func() error, err error) {
|
||||
// When the prompt returns an error, the caller should propagate the error up
|
||||
// the stack and close the io.Reader used for the prompt which will prevent the
|
||||
// background goroutine from blocking indefinitely.
|
||||
//
|
||||
// Deprecated: this function is for internal use and will be removed in the next release.
|
||||
func PromptForInput(ctx context.Context, in io.Reader, out io.Writer, message string) (string, error) {
|
||||
return prompt.ReadInput(ctx, in, out, message)
|
||||
}
|
||||
@@ -63,6 +55,8 @@ func PromptForInput(ctx context.Context, in io.Reader, out io.Writer, message st
|
||||
// When the prompt returns an error, the caller should propagate the error up
|
||||
// the stack and close the io.Reader used for the prompt which will prevent the
|
||||
// background goroutine from blocking indefinitely.
|
||||
//
|
||||
// Deprecated: this function is for internal use and will be removed in the next release.
|
||||
func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, message string) (bool, error) {
|
||||
return prompt.Confirm(ctx, ins, outs, message)
|
||||
}
|
||||
@@ -108,12 +102,6 @@ func PruneFilters(dockerCLI config.Provider, pruneFilters filters.Args) filters.
|
||||
return pruneFilters
|
||||
}
|
||||
|
||||
// AddPlatformFlag adds `platform` to a set of flags for API version 1.32 and later.
|
||||
func AddPlatformFlag(flags *pflag.FlagSet, target *string) {
|
||||
flags.StringVar(target, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
|
||||
_ = flags.SetAnnotation("platform", "version", []string{"1.32"})
|
||||
}
|
||||
|
||||
// ValidateOutputPath validates the output paths of the "docker cp" command.
|
||||
func ValidateOutputPath(path string) error {
|
||||
dir := filepath.Dir(filepath.Clean(path))
|
||||
|
||||
85
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/config/configfile/file.go
generated
vendored
85
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/config/configfile/file.go
generated
vendored
@@ -3,12 +3,14 @@ package configfile
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli/config/credentials"
|
||||
"github.com/docker/cli/cli/config/memorystore"
|
||||
"github.com/docker/cli/cli/config/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -46,6 +48,31 @@ type ConfigFile struct {
|
||||
Experimental string `json:"experimental,omitempty"`
|
||||
}
|
||||
|
||||
type configEnvAuth struct {
|
||||
Auth string `json:"auth"`
|
||||
}
|
||||
|
||||
type configEnv struct {
|
||||
AuthConfigs map[string]configEnvAuth `json:"auths"`
|
||||
}
|
||||
|
||||
// DockerEnvConfigKey is an environment variable that contains a JSON encoded
|
||||
// credential config. It only supports storing the credentials as a base64
|
||||
// encoded string in the format base64("username:pat").
|
||||
//
|
||||
// Adding additional fields will produce a parsing error.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// {
|
||||
// "auths": {
|
||||
// "example.test": {
|
||||
// "auth": base64-encoded-username-pat
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
const DockerEnvConfigKey = "DOCKER_AUTH_CONFIG"
|
||||
|
||||
// ProxyConfig contains proxy configuration settings
|
||||
type ProxyConfig struct {
|
||||
HTTPProxy string `json:"httpProxy,omitempty"`
|
||||
@@ -263,10 +290,64 @@ func decodeAuth(authStr string) (string, string, error) {
|
||||
// GetCredentialsStore returns a new credentials store from the settings in the
|
||||
// configuration file
|
||||
func (configFile *ConfigFile) GetCredentialsStore(registryHostname string) credentials.Store {
|
||||
store := credentials.NewFileStore(configFile)
|
||||
|
||||
if helper := getConfiguredCredentialStore(configFile, registryHostname); helper != "" {
|
||||
return newNativeStore(configFile, helper)
|
||||
store = newNativeStore(configFile, helper)
|
||||
}
|
||||
return credentials.NewFileStore(configFile)
|
||||
|
||||
envConfig := os.Getenv(DockerEnvConfigKey)
|
||||
if envConfig == "" {
|
||||
return store
|
||||
}
|
||||
|
||||
authConfig, err := parseEnvConfig(envConfig)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "Failed to create credential store from DOCKER_AUTH_CONFIG: ", err)
|
||||
return store
|
||||
}
|
||||
|
||||
// use DOCKER_AUTH_CONFIG if set
|
||||
// it uses the native or file store as a fallback to fetch and store credentials
|
||||
envStore, err := memorystore.New(
|
||||
memorystore.WithAuthConfig(authConfig),
|
||||
memorystore.WithFallbackStore(store),
|
||||
)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "Failed to create credential store from DOCKER_AUTH_CONFIG: ", err)
|
||||
return store
|
||||
}
|
||||
|
||||
return envStore
|
||||
}
|
||||
|
||||
func parseEnvConfig(v string) (map[string]types.AuthConfig, error) {
|
||||
envConfig := &configEnv{}
|
||||
decoder := json.NewDecoder(strings.NewReader(v))
|
||||
decoder.DisallowUnknownFields()
|
||||
if err := decoder.Decode(envConfig); err != nil && !errors.Is(err, io.EOF) {
|
||||
return nil, err
|
||||
}
|
||||
if decoder.More() {
|
||||
return nil, errors.New("DOCKER_AUTH_CONFIG does not support more than one JSON object")
|
||||
}
|
||||
|
||||
authConfigs := make(map[string]types.AuthConfig)
|
||||
for addr, envAuth := range envConfig.AuthConfigs {
|
||||
if envAuth.Auth == "" {
|
||||
return nil, fmt.Errorf("DOCKER_AUTH_CONFIG environment variable is missing key `auth` for %s", addr)
|
||||
}
|
||||
username, password, err := decodeAuth(envAuth.Auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authConfigs[addr] = types.AuthConfig{
|
||||
Username: username,
|
||||
Password: password,
|
||||
ServerAddress: addr,
|
||||
}
|
||||
}
|
||||
return authConfigs, nil
|
||||
}
|
||||
|
||||
// var for unit testing.
|
||||
|
||||
130
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/config/memorystore/store.go
generated
vendored
Normal file
130
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/config/memorystore/store.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
//go:build go1.23
|
||||
|
||||
package memorystore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/cli/cli/config/credentials"
|
||||
"github.com/docker/cli/cli/config/types"
|
||||
)
|
||||
|
||||
// notFoundErr is the error returned when a plugin could not be found.
|
||||
type notFoundErr string
|
||||
|
||||
func (notFoundErr) NotFound() {}
|
||||
|
||||
func (e notFoundErr) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
var errValueNotFound notFoundErr = "value not found"
|
||||
|
||||
type Config struct {
|
||||
lock sync.RWMutex
|
||||
memoryCredentials map[string]types.AuthConfig
|
||||
fallbackStore credentials.Store
|
||||
}
|
||||
|
||||
func (e *Config) Erase(serverAddress string) error {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
delete(e.memoryCredentials, serverAddress)
|
||||
|
||||
if e.fallbackStore != nil {
|
||||
err := e.fallbackStore.Erase(serverAddress)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "memorystore: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Config) Get(serverAddress string) (types.AuthConfig, error) {
|
||||
e.lock.RLock()
|
||||
defer e.lock.RUnlock()
|
||||
authConfig, ok := e.memoryCredentials[serverAddress]
|
||||
if !ok {
|
||||
if e.fallbackStore != nil {
|
||||
return e.fallbackStore.Get(serverAddress)
|
||||
}
|
||||
return types.AuthConfig{}, errValueNotFound
|
||||
}
|
||||
return authConfig, nil
|
||||
}
|
||||
|
||||
func (e *Config) GetAll() (map[string]types.AuthConfig, error) {
|
||||
e.lock.RLock()
|
||||
defer e.lock.RUnlock()
|
||||
creds := make(map[string]types.AuthConfig)
|
||||
|
||||
if e.fallbackStore != nil {
|
||||
fileCredentials, err := e.fallbackStore.GetAll()
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "memorystore: ", err)
|
||||
} else {
|
||||
creds = fileCredentials
|
||||
}
|
||||
}
|
||||
|
||||
maps.Copy(creds, e.memoryCredentials)
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
func (e *Config) Store(authConfig types.AuthConfig) error {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
e.memoryCredentials[authConfig.ServerAddress] = authConfig
|
||||
|
||||
if e.fallbackStore != nil {
|
||||
return e.fallbackStore.Store(authConfig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithFallbackStore sets a fallback store.
|
||||
//
|
||||
// Write operations will be performed on both the memory store and the
|
||||
// fallback store.
|
||||
//
|
||||
// Read operations will first check the memory store, and if the credential
|
||||
// is not found, it will then check the fallback store.
|
||||
//
|
||||
// Retrieving all credentials will return from both the memory store and the
|
||||
// fallback store, merging the results from both stores into a single map.
|
||||
//
|
||||
// Data stored in the memory store will take precedence over data in the
|
||||
// fallback store.
|
||||
func WithFallbackStore(store credentials.Store) Options {
|
||||
return func(s *Config) error {
|
||||
s.fallbackStore = store
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuthConfig allows to set the initial credentials in the memory store.
|
||||
func WithAuthConfig(config map[string]types.AuthConfig) Options {
|
||||
return func(s *Config) error {
|
||||
s.memoryCredentials = config
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type Options func(*Config) error
|
||||
|
||||
// New creates a new in memory credential store
|
||||
func New(opts ...Options) (credentials.Store, error) {
|
||||
m := &Config{
|
||||
memoryCredentials: make(map[string]types.AuthConfig),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
if err := opt(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
4
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/config/types/authconfig.go
generated
vendored
4
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/config/types/authconfig.go
generated
vendored
@@ -7,8 +7,8 @@ type AuthConfig struct {
|
||||
Auth string `json:"auth,omitempty"`
|
||||
|
||||
// Email is an optional value associated with the username.
|
||||
// This field is deprecated and will be removed in a later
|
||||
// version of docker.
|
||||
//
|
||||
// Deprecated: This field is deprecated since docker 1.11 (API v1.23) and will be removed in the next release.
|
||||
Email string `json:"email,omitempty"`
|
||||
|
||||
ServerAddress string `json:"serveraddress,omitempty"`
|
||||
|
||||
17
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/connhelper.go
generated
vendored
17
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/connhelper.go
generated
vendored
@@ -47,14 +47,19 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
|
||||
}
|
||||
sshFlags = addSSHTimeout(sshFlags)
|
||||
sshFlags = disablePseudoTerminalAllocation(sshFlags)
|
||||
|
||||
remoteCommand := []string{"docker", "system", "dial-stdio"}
|
||||
socketPath := sp.Path
|
||||
if strings.Trim(sp.Path, "/") != "" {
|
||||
remoteCommand = []string{"docker", "--host=unix://" + socketPath, "system", "dial-stdio"}
|
||||
}
|
||||
sshArgs, err := sp.Command(sshFlags, remoteCommand...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ConnectionHelper{
|
||||
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
args := []string{"docker"}
|
||||
if sp.Path != "" {
|
||||
args = append(args, "--host", "unix://"+sp.Path)
|
||||
}
|
||||
args = append(args, "system", "dial-stdio")
|
||||
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
|
||||
return commandconn.New(ctx, "ssh", sshArgs...)
|
||||
},
|
||||
Host: "http://docker.example.com",
|
||||
}, nil
|
||||
|
||||
27
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/LICENSE
generated
vendored
Normal file
27
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2016, Daniel Martí. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
13
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/doc.go
generated
vendored
Normal file
13
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/doc.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Package syntax is a fork of [mvdan.cc/sh/v3@v3.10.0/syntax].
|
||||
//
|
||||
// Copyright (c) 2016, Daniel Martí. All rights reserved.
|
||||
//
|
||||
// It is a reduced set of the package to only provide the [Quote] function,
|
||||
// and contains the [LICENSE], [quote.go] and [parser.go] files at the given
|
||||
// revision.
|
||||
//
|
||||
// [quote.go]: https://raw.githubusercontent.com/mvdan/sh/refs/tags/v3.10.0/syntax/quote.go
|
||||
// [parser.go]: https://raw.githubusercontent.com/mvdan/sh/refs/tags/v3.10.0/syntax/parser.go
|
||||
// [LICENSE]: https://raw.githubusercontent.com/mvdan/sh/refs/tags/v3.10.0/LICENSE
|
||||
// [mvdan.cc/sh/v3@v3.10.0/syntax]: https://pkg.go.dev/mvdan.cc/sh/v3@v3.10.0/syntax
|
||||
package syntax
|
||||
95
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/parser.go
generated
vendored
Normal file
95
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/parser.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
|
||||
// See LICENSE for licensing information
|
||||
|
||||
package syntax
|
||||
|
||||
// LangVariant describes a shell language variant to use when tokenizing and
|
||||
// parsing shell code. The zero value is [LangBash].
|
||||
type LangVariant int
|
||||
|
||||
const (
|
||||
// LangBash corresponds to the GNU Bash language, as described in its
|
||||
// manual at https://www.gnu.org/software/bash/manual/bash.html.
|
||||
//
|
||||
// We currently follow Bash version 5.2.
|
||||
//
|
||||
// Its string representation is "bash".
|
||||
LangBash LangVariant = iota
|
||||
|
||||
// LangPOSIX corresponds to the POSIX Shell language, as described at
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html.
|
||||
//
|
||||
// Its string representation is "posix" or "sh".
|
||||
LangPOSIX
|
||||
|
||||
// LangMirBSDKorn corresponds to the MirBSD Korn Shell, also known as
|
||||
// mksh, as described at http://www.mirbsd.org/htman/i386/man1/mksh.htm.
|
||||
// Note that it shares some features with Bash, due to the shared
|
||||
// ancestry that is ksh.
|
||||
//
|
||||
// We currently follow mksh version 59.
|
||||
//
|
||||
// Its string representation is "mksh".
|
||||
LangMirBSDKorn
|
||||
|
||||
// LangBats corresponds to the Bash Automated Testing System language,
|
||||
// as described at https://github.com/bats-core/bats-core. Note that
|
||||
// it's just a small extension of the Bash language.
|
||||
//
|
||||
// Its string representation is "bats".
|
||||
LangBats
|
||||
|
||||
// LangAuto corresponds to automatic language detection,
|
||||
// commonly used by end-user applications like shfmt,
|
||||
// which can guess a file's language variant given its filename or shebang.
|
||||
//
|
||||
// At this time, [Variant] does not support LangAuto.
|
||||
LangAuto
|
||||
)
|
||||
|
||||
func (l LangVariant) String() string {
|
||||
switch l {
|
||||
case LangBash:
|
||||
return "bash"
|
||||
case LangPOSIX:
|
||||
return "posix"
|
||||
case LangMirBSDKorn:
|
||||
return "mksh"
|
||||
case LangBats:
|
||||
return "bats"
|
||||
case LangAuto:
|
||||
return "auto"
|
||||
}
|
||||
return "unknown shell language variant"
|
||||
}
|
||||
|
||||
// IsKeyword returns true if the given word is part of the language keywords.
|
||||
func IsKeyword(word string) bool {
|
||||
// This list has been copied from the bash 5.1 source code, file y.tab.c +4460
|
||||
switch word {
|
||||
case
|
||||
"!",
|
||||
"[[", // only if COND_COMMAND is defined
|
||||
"]]", // only if COND_COMMAND is defined
|
||||
"case",
|
||||
"coproc", // only if COPROCESS_SUPPORT is defined
|
||||
"do",
|
||||
"done",
|
||||
"else",
|
||||
"esac",
|
||||
"fi",
|
||||
"for",
|
||||
"function",
|
||||
"if",
|
||||
"in",
|
||||
"select", // only if SELECT_COMMAND is defined
|
||||
"then",
|
||||
"time", // only if COMMAND_TIMING is defined
|
||||
"until",
|
||||
"while",
|
||||
"{",
|
||||
"}":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
187
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/quote.go
generated
vendored
Normal file
187
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/internal/syntax/quote.go
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2021, Daniel Martí <mvdan@mvdan.cc>
|
||||
// See LICENSE for licensing information
|
||||
|
||||
package syntax
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type QuoteError struct {
|
||||
ByteOffset int
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e QuoteError) Error() string {
|
||||
return fmt.Sprintf("cannot quote character at byte %d: %s", e.ByteOffset, e.Message)
|
||||
}
|
||||
|
||||
const (
|
||||
quoteErrNull = "shell strings cannot contain null bytes"
|
||||
quoteErrPOSIX = "POSIX shell lacks escape sequences"
|
||||
quoteErrRange = "rune out of range"
|
||||
quoteErrMksh = "mksh cannot escape codepoints above 16 bits"
|
||||
)
|
||||
|
||||
// Quote returns a quoted version of the input string,
|
||||
// so that the quoted version is expanded or interpreted
|
||||
// as the original string in the given language variant.
|
||||
//
|
||||
// Quoting is necessary when using arbitrary literal strings
|
||||
// as words in a shell script or command.
|
||||
// Without quoting, one can run into syntax errors,
|
||||
// as well as the possibility of running unintended code.
|
||||
//
|
||||
// An error is returned when a string cannot be quoted for a variant.
|
||||
// For instance, POSIX lacks escape sequences for non-printable characters,
|
||||
// and no language variant can represent a string containing null bytes.
|
||||
// In such cases, the returned error type will be *QuoteError.
|
||||
//
|
||||
// The quoting strategy is chosen on a best-effort basis,
|
||||
// to minimize the amount of extra bytes necessary.
|
||||
//
|
||||
// Some strings do not require any quoting and are returned unchanged.
|
||||
// Those strings can be directly surrounded in single quotes as well.
|
||||
//
|
||||
//nolint:gocyclo // ignore "cyclomatic complexity 35 of func `Quote` is high (> 16) (gocyclo)"
|
||||
func Quote(s string, lang LangVariant) (string, error) {
|
||||
if s == "" {
|
||||
// Special case; an empty string must always be quoted,
|
||||
// as otherwise it expands to zero fields.
|
||||
return "''", nil
|
||||
}
|
||||
shellChars := false
|
||||
nonPrintable := false
|
||||
offs := 0
|
||||
for rem := s; len(rem) > 0; {
|
||||
r, size := utf8.DecodeRuneInString(rem)
|
||||
switch r {
|
||||
// Like regOps; token characters.
|
||||
case ';', '"', '\'', '(', ')', '$', '|', '&', '>', '<', '`',
|
||||
// Whitespace; might result in multiple fields.
|
||||
' ', '\t', '\r', '\n',
|
||||
// Escape sequences would be expanded.
|
||||
'\\',
|
||||
// Would start a comment unless quoted.
|
||||
'#',
|
||||
// Might result in brace expansion.
|
||||
'{',
|
||||
// Might result in tilde expansion.
|
||||
'~',
|
||||
// Might result in globbing.
|
||||
'*', '?', '[',
|
||||
// Might result in an assignment.
|
||||
'=':
|
||||
shellChars = true
|
||||
case '\x00':
|
||||
return "", &QuoteError{ByteOffset: offs, Message: quoteErrNull}
|
||||
}
|
||||
if r == utf8.RuneError || !unicode.IsPrint(r) {
|
||||
if lang == LangPOSIX {
|
||||
return "", &QuoteError{ByteOffset: offs, Message: quoteErrPOSIX}
|
||||
}
|
||||
nonPrintable = true
|
||||
}
|
||||
rem = rem[size:]
|
||||
offs += size
|
||||
}
|
||||
if !shellChars && !nonPrintable && !IsKeyword(s) {
|
||||
// Nothing to quote; avoid allocating.
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Single quotes are usually best,
|
||||
// as they don't require any escaping of characters.
|
||||
// If we have any invalid utf8 or non-printable runes,
|
||||
// use $'' so that we can escape them.
|
||||
// Note that we can't use double quotes for those.
|
||||
var b strings.Builder
|
||||
if nonPrintable {
|
||||
b.WriteString("$'")
|
||||
lastRequoteIfHex := false
|
||||
offs = 0
|
||||
for rem := s; len(rem) > 0; {
|
||||
nextRequoteIfHex := false
|
||||
r, size := utf8.DecodeRuneInString(rem)
|
||||
switch {
|
||||
case r == '\'', r == '\\':
|
||||
b.WriteByte('\\')
|
||||
b.WriteRune(r)
|
||||
case unicode.IsPrint(r) && r != utf8.RuneError:
|
||||
if lastRequoteIfHex && isHex(r) {
|
||||
b.WriteString("'$'")
|
||||
}
|
||||
b.WriteRune(r)
|
||||
case r == '\a':
|
||||
b.WriteString(`\a`)
|
||||
case r == '\b':
|
||||
b.WriteString(`\b`)
|
||||
case r == '\f':
|
||||
b.WriteString(`\f`)
|
||||
case r == '\n':
|
||||
b.WriteString(`\n`)
|
||||
case r == '\r':
|
||||
b.WriteString(`\r`)
|
||||
case r == '\t':
|
||||
b.WriteString(`\t`)
|
||||
case r == '\v':
|
||||
b.WriteString(`\v`)
|
||||
case r < utf8.RuneSelf, r == utf8.RuneError && size == 1:
|
||||
// \xXX, fixed at two hexadecimal characters.
|
||||
fmt.Fprintf(&b, "\\x%02x", rem[0])
|
||||
// Unfortunately, mksh allows \x to consume more hex characters.
|
||||
// Ensure that we don't allow it to read more than two.
|
||||
if lang == LangMirBSDKorn {
|
||||
nextRequoteIfHex = true
|
||||
}
|
||||
case r > utf8.MaxRune:
|
||||
// Not a valid Unicode code point?
|
||||
return "", &QuoteError{ByteOffset: offs, Message: quoteErrRange}
|
||||
case lang == LangMirBSDKorn && r > 0xFFFD:
|
||||
// From the CAVEATS section in R59's man page:
|
||||
//
|
||||
// mksh currently uses OPTU-16 internally, which is the same as
|
||||
// UTF-8 and CESU-8 with 0000..FFFD being valid codepoints.
|
||||
return "", &QuoteError{ByteOffset: offs, Message: quoteErrMksh}
|
||||
case r < 0x10000:
|
||||
// \uXXXX, fixed at four hexadecimal characters.
|
||||
fmt.Fprintf(&b, "\\u%04x", r)
|
||||
default:
|
||||
// \UXXXXXXXX, fixed at eight hexadecimal characters.
|
||||
fmt.Fprintf(&b, "\\U%08x", r)
|
||||
}
|
||||
rem = rem[size:]
|
||||
lastRequoteIfHex = nextRequoteIfHex
|
||||
offs += size
|
||||
}
|
||||
b.WriteString("'")
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
// Single quotes without any need for escaping.
|
||||
if !strings.Contains(s, "'") {
|
||||
return "'" + s + "'", nil
|
||||
}
|
||||
|
||||
// The string contains single quotes,
|
||||
// so fall back to double quotes.
|
||||
b.WriteByte('"')
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case '"', '\\', '`', '$':
|
||||
b.WriteByte('\\')
|
||||
}
|
||||
b.WriteRune(r)
|
||||
}
|
||||
b.WriteByte('"')
|
||||
return b.String(), nil
|
||||
}
|
||||
|
||||
func isHex(r rune) bool {
|
||||
return (r >= '0' && r <= '9') ||
|
||||
(r >= 'a' && r <= 'f') ||
|
||||
(r >= 'A' && r <= 'F')
|
||||
}
|
||||
106
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/ssh/ssh.go
generated
vendored
106
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/connhelper/ssh/ssh.go
generated
vendored
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/cli/cli/connhelper/internal/syntax"
|
||||
)
|
||||
|
||||
// ParseURL creates a [Spec] from the given ssh URL. It returns an error if
|
||||
@@ -76,16 +78,106 @@ type Spec struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Args returns args except "ssh" itself combined with optional additional command args
|
||||
func (sp *Spec) Args(add ...string) []string {
|
||||
// Args returns args except "ssh" itself combined with optional additional
|
||||
// command and args to be executed on the remote host. It attempts to quote
|
||||
// the given arguments to account for ssh executing the remote command in a
|
||||
// shell. It returns nil when unable to quote the remote command.
|
||||
func (sp *Spec) Args(remoteCommandAndArgs ...string) []string {
|
||||
// Format the remote command to run using the ssh connection, quoting
|
||||
// values where needed because ssh executes these in a POSIX shell.
|
||||
remoteCommand, err := quoteCommand(remoteCommandAndArgs...)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sshArgs, err := sp.args()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if remoteCommand != "" {
|
||||
sshArgs = append(sshArgs, remoteCommand)
|
||||
}
|
||||
return sshArgs
|
||||
}
|
||||
|
||||
func (sp *Spec) args(sshFlags ...string) ([]string, error) {
|
||||
var args []string
|
||||
if sp.Host == "" {
|
||||
return nil, errors.New("no host specified")
|
||||
}
|
||||
if sp.User != "" {
|
||||
args = append(args, "-l", sp.User)
|
||||
// Quote user, as it's obtained from the URL.
|
||||
usr, err := syntax.Quote(sp.User, syntax.LangPOSIX)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid user: %w", err)
|
||||
}
|
||||
args = append(args, "-l", usr)
|
||||
}
|
||||
if sp.Port != "" {
|
||||
args = append(args, "-p", sp.Port)
|
||||
// Quote port, as it's obtained from the URL.
|
||||
port, err := syntax.Quote(sp.Port, syntax.LangPOSIX)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid port: %w", err)
|
||||
}
|
||||
args = append(args, "-p", port)
|
||||
}
|
||||
args = append(args, "--", sp.Host)
|
||||
args = append(args, add...)
|
||||
return args
|
||||
|
||||
// We consider "sshFlags" to be "trusted", and set from code only,
|
||||
// as they are not parsed from the DOCKER_HOST URL.
|
||||
args = append(args, sshFlags...)
|
||||
|
||||
host, err := syntax.Quote(sp.Host, syntax.LangPOSIX)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid host: %w", err)
|
||||
}
|
||||
|
||||
return append(args, "--", host), nil
|
||||
}
|
||||
|
||||
// Command returns the ssh flags and arguments to execute a command
|
||||
// (remoteCommandAndArgs) on the remote host. Where needed, it quotes
|
||||
// values passed in remoteCommandAndArgs to account for ssh executing
|
||||
// the remote command in a shell. It returns an error if no remote command
|
||||
// is passed, or when unable to quote the remote command.
|
||||
//
|
||||
// Important: to preserve backward-compatibility, Command does not currently
|
||||
// perform sanitization or quoting on the sshFlags and callers are expected
|
||||
// to sanitize this argument.
|
||||
func (sp *Spec) Command(sshFlags []string, remoteCommandAndArgs ...string) ([]string, error) {
|
||||
if len(remoteCommandAndArgs) == 0 {
|
||||
return nil, errors.New("no remote command specified")
|
||||
}
|
||||
sshArgs, err := sp.args(sshFlags...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
remoteCommand, err := quoteCommand(remoteCommandAndArgs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if remoteCommand != "" {
|
||||
sshArgs = append(sshArgs, remoteCommand)
|
||||
}
|
||||
return sshArgs, nil
|
||||
}
|
||||
|
||||
// quoteCommand returns the remote command to run using the ssh connection
|
||||
// as a single string, quoting values where needed because ssh executes
|
||||
// these in a POSIX shell.
|
||||
func quoteCommand(commandAndArgs ...string) (string, error) {
|
||||
var quotedCmd string
|
||||
for i, arg := range commandAndArgs {
|
||||
a, err := syntax.Quote(arg, syntax.LangPOSIX)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid argument: %w", err)
|
||||
}
|
||||
if i == 0 {
|
||||
quotedCmd = a
|
||||
continue
|
||||
}
|
||||
quotedCmd += " " + a
|
||||
}
|
||||
// each part is quoted appropriately, so now we'll have a full
|
||||
// shell command to pass off to "ssh"
|
||||
return quotedCmd, nil
|
||||
}
|
||||
|
||||
36
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/context/docker/load.go
generated
vendored
36
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/context/docker/load.go
generated
vendored
@@ -101,7 +101,22 @@ func (ep *Endpoint) ClientOpts() ([]client.Opt, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, withHTTPClient(tlsConfig))
|
||||
|
||||
// If there's no tlsConfig available, we use the default HTTPClient.
|
||||
if tlsConfig != nil {
|
||||
result = append(result,
|
||||
client.WithHTTPClient(&http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
DialContext: (&net.Dialer{
|
||||
KeepAlive: 30 * time.Second,
|
||||
Timeout: 30 * time.Second,
|
||||
}).DialContext,
|
||||
},
|
||||
CheckRedirect: client.CheckRedirect,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
result = append(result, client.WithHost(ep.Host))
|
||||
} else {
|
||||
@@ -133,25 +148,6 @@ func isSocket(addr string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func withHTTPClient(tlsConfig *tls.Config) func(*client.Client) error {
|
||||
return func(c *client.Client) error {
|
||||
if tlsConfig == nil {
|
||||
// Use the default HTTPClient
|
||||
return nil
|
||||
}
|
||||
return client.WithHTTPClient(&http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
DialContext: (&net.Dialer{
|
||||
KeepAlive: 30 * time.Second,
|
||||
Timeout: 30 * time.Second,
|
||||
}).DialContext,
|
||||
},
|
||||
CheckRedirect: client.CheckRedirect,
|
||||
})(c)
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointFromContext parses a context docker endpoint metadata into a typed EndpointMeta structure
|
||||
func EndpointFromContext(metadata store.Metadata) (EndpointMeta, error) {
|
||||
ep, ok := metadata.Endpoints[DockerEndpoint]
|
||||
|
||||
6
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/context/store/errors.go
generated
vendored
6
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/context/store/errors.go
generated
vendored
@@ -1,9 +1,9 @@
|
||||
package store
|
||||
|
||||
import cerrdefs "github.com/containerd/errdefs"
|
||||
import "github.com/containerd/errdefs"
|
||||
|
||||
func invalidParameter(err error) error {
|
||||
if err == nil || cerrdefs.IsInvalidArgument(err) {
|
||||
if err == nil || errdefs.IsInvalidArgument(err) {
|
||||
return err
|
||||
}
|
||||
return invalidParameterErr{err}
|
||||
@@ -14,7 +14,7 @@ type invalidParameterErr struct{ error }
|
||||
func (invalidParameterErr) InvalidParameter() {}
|
||||
|
||||
func notFound(err error) error {
|
||||
if err == nil || cerrdefs.IsNotFound(err) {
|
||||
if err == nil || errdefs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return notFoundErr{err}
|
||||
|
||||
3
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/debug/debug.go
generated
vendored
3
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/debug/debug.go
generated
vendored
@@ -33,5 +33,8 @@ func IsEnabled() bool {
|
||||
// The default is to log to the debug level which is only
|
||||
// enabled when debugging is enabled.
|
||||
var OTELErrorHandler otel.ErrorHandler = otel.ErrorHandlerFunc(func(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
logrus.WithError(err).Debug("otel error")
|
||||
})
|
||||
|
||||
77
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/flags/options.go
generated
vendored
77
src/cmd/linuxkit/vendor/github.com/docker/cli/cli/flags/options.go
generated
vendored
@@ -1,12 +1,12 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/cli/cli/config"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -54,6 +54,39 @@ var (
|
||||
dockerTLS = os.Getenv(EnvEnableTLS) != ""
|
||||
)
|
||||
|
||||
// hostVar is used for the '--host' / '-H' flag to set [ClientOptions.Hosts].
|
||||
// The [ClientOptions.Hosts] field is a slice because it was originally shared
|
||||
// with the daemon config. However, the CLI only allows for a single host to
|
||||
// be specified.
|
||||
//
|
||||
// hostVar presents itself as a "string", but stores the value in a string
|
||||
// slice. It produces an error when trying to set multiple values, matching
|
||||
// the check in [getServerHost].
|
||||
//
|
||||
// [getServerHost]: https://github.com/docker/cli/blob/7eab668982645def1cd46fe1b60894cba6fd17a4/cli/command/cli.go#L542-L551
|
||||
type hostVar struct {
|
||||
dst *[]string
|
||||
set bool
|
||||
}
|
||||
|
||||
func (h *hostVar) String() string {
|
||||
if h.dst == nil || len(*h.dst) == 0 {
|
||||
return ""
|
||||
}
|
||||
return (*h.dst)[0]
|
||||
}
|
||||
|
||||
func (h *hostVar) Set(s string) error {
|
||||
if h.set {
|
||||
return errors.New("specify only one -H")
|
||||
}
|
||||
*h.dst = []string{s}
|
||||
h.set = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*hostVar) Type() string { return "string" }
|
||||
|
||||
// ClientOptions are the options used to configure the client cli.
|
||||
type ClientOptions struct {
|
||||
Debug bool
|
||||
@@ -90,13 +123,13 @@ func (o *ClientOptions) InstallFlags(flags *pflag.FlagSet) {
|
||||
KeyFile: filepath.Join(dockerCertPath, DefaultKeyFile),
|
||||
}
|
||||
tlsOptions := o.TLSOptions
|
||||
flags.Var(opts.NewQuotedString(&tlsOptions.CAFile), "tlscacert", "Trust certs signed only by this CA")
|
||||
flags.Var(opts.NewQuotedString(&tlsOptions.CertFile), "tlscert", "Path to TLS certificate file")
|
||||
flags.Var(opts.NewQuotedString(&tlsOptions.KeyFile), "tlskey", "Path to TLS key file")
|
||||
flags.Var("edString{&tlsOptions.CAFile}, "tlscacert", "Trust certs signed only by this CA")
|
||||
flags.Var("edString{&tlsOptions.CertFile}, "tlscert", "Path to TLS certificate file")
|
||||
flags.Var("edString{&tlsOptions.KeyFile}, "tlskey", "Path to TLS key file")
|
||||
|
||||
// opts.ValidateHost is not used here, so as to allow connection helpers
|
||||
hostOpt := opts.NewNamedListOptsRef("hosts", &o.Hosts, nil)
|
||||
flags.VarP(hostOpt, "host", "H", "Daemon socket to connect to")
|
||||
// TODO(thaJeztah): show the default host.
|
||||
// TODO(thaJeztah): this should be a string, not an "array" as we only allow a single host.
|
||||
flags.VarP(&hostVar{dst: &o.Hosts}, "host", "H", "Daemon socket to connect to")
|
||||
flags.StringVarP(&o.Context, "context", "c", "",
|
||||
`Name of the context to use to connect to the daemon (overrides `+client.EnvOverrideHost+` env var and default context set with "docker context use")`)
|
||||
}
|
||||
@@ -146,3 +179,33 @@ func SetLogLevel(logLevel string) {
|
||||
logrus.SetLevel(logrus.InfoLevel)
|
||||
}
|
||||
}
|
||||
|
||||
type quotedString struct {
|
||||
value *string
|
||||
}
|
||||
|
||||
func (s *quotedString) Set(val string) error {
|
||||
*s.value = trimQuotes(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*quotedString) Type() string {
|
||||
return "string"
|
||||
}
|
||||
|
||||
func (s *quotedString) String() string {
|
||||
return *s.value
|
||||
}
|
||||
|
||||
func trimQuotes(value string) string {
|
||||
if len(value) < 2 {
|
||||
return value
|
||||
}
|
||||
lastIndex := len(value) - 1
|
||||
for _, char := range []byte{'\'', '"'} {
|
||||
if value[0] == char && value[lastIndex] == char {
|
||||
return value[1:lastIndex]
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
41
src/cmd/linuxkit/vendor/github.com/docker/cli/internal/tui/note.go
generated
vendored
41
src/cmd/linuxkit/vendor/github.com/docker/cli/internal/tui/note.go
generated
vendored
@@ -15,19 +15,39 @@ var InfoHeader = Str{
|
||||
Fancy: aec.Bold.Apply(aec.LightCyanB.Apply(aec.BlackF.Apply("i")) + " " + aec.LightCyanF.Apply("Info → ")),
|
||||
}
|
||||
|
||||
func (o Output) PrintNote(format string, args ...any) {
|
||||
type options struct {
|
||||
header Str
|
||||
}
|
||||
|
||||
type noteOptions func(o *options)
|
||||
|
||||
func withHeader(header Str) noteOptions {
|
||||
return func(o *options) {
|
||||
o.header = header
|
||||
}
|
||||
}
|
||||
|
||||
func (o Output) printNoteWithOptions(format string, args []any, opts ...noteOptions) {
|
||||
if o.isTerminal {
|
||||
// TODO: Handle all flags
|
||||
format = strings.ReplaceAll(format, "--platform", ColorFlag.Apply("--platform"))
|
||||
}
|
||||
|
||||
header := o.Sprint(InfoHeader)
|
||||
opt := &options{
|
||||
header: InfoHeader,
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprint(o, "\n", header)
|
||||
for _, override := range opts {
|
||||
override(opt)
|
||||
}
|
||||
|
||||
h := o.Sprint(opt.header)
|
||||
|
||||
_, _ = fmt.Fprint(o, "\n", h)
|
||||
s := fmt.Sprintf(format, args...)
|
||||
for idx, line := range strings.Split(s, "\n") {
|
||||
if idx > 0 {
|
||||
_, _ = fmt.Fprint(o, strings.Repeat(" ", Width(header)))
|
||||
_, _ = fmt.Fprint(o, strings.Repeat(" ", Width(h)))
|
||||
}
|
||||
|
||||
l := line
|
||||
@@ -37,3 +57,16 @@ func (o Output) PrintNote(format string, args ...any) {
|
||||
_, _ = fmt.Fprintln(o, l)
|
||||
}
|
||||
}
|
||||
|
||||
func (o Output) PrintNote(format string, args ...any) {
|
||||
o.printNoteWithOptions(format, args, withHeader(InfoHeader))
|
||||
}
|
||||
|
||||
var warningHeader = Str{
|
||||
Plain: " Warn -> ",
|
||||
Fancy: aec.Bold.Apply(aec.LightYellowB.Apply(aec.BlackF.Apply("w")) + " " + ColorWarning.Apply("Warn → ")),
|
||||
}
|
||||
|
||||
func (o Output) PrintWarning(format string, args ...any) {
|
||||
o.printNoteWithOptions(format, args, withHeader(warningHeader))
|
||||
}
|
||||
|
||||
11
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/env.go
generated
vendored
11
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/env.go
generated
vendored
@@ -7,13 +7,14 @@ import (
|
||||
)
|
||||
|
||||
// ValidateEnv validates an environment variable and returns it.
|
||||
// If no value is specified, it obtains its value from the current environment
|
||||
// If no value is specified, it obtains its value from the current environment.
|
||||
//
|
||||
// As on ParseEnvFile and related to #16585, environment variable names
|
||||
// are not validated, and it's up to the application inside the container
|
||||
// to validate them or not.
|
||||
// Environment variable names are not validated, and it's up to the application
|
||||
// inside the container to validate them (see [moby-16585]). The only validation
|
||||
// here is to check if name is empty, per [moby-25099].
|
||||
//
|
||||
// The only validation here is to check if name is empty, per #25099
|
||||
// [moby-16585]: https://github.com/moby/moby/issues/16585
|
||||
// [moby-25099]: https://github.com/moby/moby/issues/25099
|
||||
func ValidateEnv(val string) (string, error) {
|
||||
k, _, hasValue := strings.Cut(val, "=")
|
||||
if k == "" {
|
||||
|
||||
24
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/envfile.go
generated
vendored
24
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/envfile.go
generated
vendored
@@ -1,24 +0,0 @@
|
||||
package opts
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/cli/pkg/kvfile"
|
||||
)
|
||||
|
||||
// ParseEnvFile reads a file with environment variables enumerated by lines
|
||||
//
|
||||
// “Environment variable names used by the utilities in the Shell and
|
||||
// Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase
|
||||
// letters, digits, and the '_' (underscore) from the characters defined in
|
||||
// Portable Character Set and do not begin with a digit. *But*, other
|
||||
// characters may be permitted by an implementation; applications shall
|
||||
// tolerate the presence of such names.”
|
||||
// -- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html
|
||||
//
|
||||
// As of #16585, it's up to application inside docker to validate or not
|
||||
// environment variables, that's why we just strip leading whitespace and
|
||||
// nothing more.
|
||||
func ParseEnvFile(filename string) ([]string, error) {
|
||||
return kvfile.Parse(filename, os.LookupEnv)
|
||||
}
|
||||
14
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/envfile_deprecated.go
generated
vendored
Normal file
14
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/envfile_deprecated.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package opts
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/cli/pkg/kvfile"
|
||||
)
|
||||
|
||||
// ParseEnvFile reads a file with environment variables enumerated by lines
|
||||
//
|
||||
// Deprecated: use [kvfile.Parse] and pass [os.LookupEnv] to lookup env-vars from the current environment.
|
||||
func ParseEnvFile(filename string) ([]string, error) {
|
||||
return kvfile.Parse(filename, os.LookupEnv)
|
||||
}
|
||||
2
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/hosts.go
generated
vendored
2
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/hosts.go
generated
vendored
@@ -34,7 +34,7 @@ const (
|
||||
|
||||
// ValidateHost validates that the specified string is a valid host and returns it.
|
||||
//
|
||||
// TODO(thaJeztah): ValidateHost appears to be unused; deprecate it.
|
||||
// Deprecated: this function is no longer used, and will be removed in the next release.
|
||||
func ValidateHost(val string) (string, error) {
|
||||
host := strings.TrimSpace(val)
|
||||
// The empty string means default and is not handled by parseDockerDaemonHost
|
||||
|
||||
14
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/opts.go
generated
vendored
14
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/opts.go
generated
vendored
@@ -134,6 +134,8 @@ func (opts *ListOpts) WithValidator(validator ValidatorFctType) *ListOpts {
|
||||
|
||||
// NamedOption is an interface that list and map options
|
||||
// with names implement.
|
||||
//
|
||||
// Deprecated: NamedOption is no longer used and will be removed in the next release.
|
||||
type NamedOption interface {
|
||||
Name() string
|
||||
}
|
||||
@@ -141,6 +143,8 @@ type NamedOption interface {
|
||||
// NamedListOpts is a ListOpts with a configuration name.
|
||||
// This struct is useful to keep reference to the assigned
|
||||
// field name in the internal configuration struct.
|
||||
//
|
||||
// Deprecated: NamedListOpts is no longer used and will be removed in the next release.
|
||||
type NamedListOpts struct {
|
||||
name string
|
||||
ListOpts
|
||||
@@ -149,6 +153,8 @@ type NamedListOpts struct {
|
||||
var _ NamedOption = &NamedListOpts{}
|
||||
|
||||
// NewNamedListOptsRef creates a reference to a new NamedListOpts struct.
|
||||
//
|
||||
// Deprecated: NewNamedListOptsRef is no longer used and will be removed in the next release.
|
||||
func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts {
|
||||
return &NamedListOpts{
|
||||
name: name,
|
||||
@@ -157,6 +163,8 @@ func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctTy
|
||||
}
|
||||
|
||||
// Name returns the name of the NamedListOpts in the configuration.
|
||||
//
|
||||
// Deprecated: NamedListOpts is no longer used and will be removed in the next release.
|
||||
func (o *NamedListOpts) Name() string {
|
||||
return o.name
|
||||
}
|
||||
@@ -210,6 +218,8 @@ func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts {
|
||||
// NamedMapOpts is a MapOpts struct with a configuration name.
|
||||
// This struct is useful to keep reference to the assigned
|
||||
// field name in the internal configuration struct.
|
||||
//
|
||||
// Deprecated: NamedMapOpts is no longer used and will be removed in the next release.
|
||||
type NamedMapOpts struct {
|
||||
name string
|
||||
MapOpts
|
||||
@@ -218,6 +228,8 @@ type NamedMapOpts struct {
|
||||
var _ NamedOption = &NamedMapOpts{}
|
||||
|
||||
// NewNamedMapOpts creates a reference to a new NamedMapOpts struct.
|
||||
//
|
||||
// Deprecated: NamedMapOpts is no longer used and will be removed in the next release.
|
||||
func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts {
|
||||
return &NamedMapOpts{
|
||||
name: name,
|
||||
@@ -226,6 +238,8 @@ func NewNamedMapOpts(name string, values map[string]string, validator ValidatorF
|
||||
}
|
||||
|
||||
// Name returns the name of the NamedMapOpts in the configuration.
|
||||
//
|
||||
// Deprecated: NamedMapOpts is no longer used and will be removed in the next release.
|
||||
func (o *NamedMapOpts) Name() string {
|
||||
return o.name
|
||||
}
|
||||
|
||||
4
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/quotedstring.go
generated
vendored
4
src/cmd/linuxkit/vendor/github.com/docker/cli/opts/quotedstring.go
generated
vendored
@@ -2,6 +2,8 @@ package opts
|
||||
|
||||
// QuotedString is a string that may have extra quotes around the value. The
|
||||
// quotes are stripped from the value.
|
||||
//
|
||||
// Deprecated: This option type is no longer used and will be removed in the next release.
|
||||
type QuotedString struct {
|
||||
value *string
|
||||
}
|
||||
@@ -35,6 +37,8 @@ func trimQuotes(value string) string {
|
||||
}
|
||||
|
||||
// NewQuotedString returns a new quoted string option
|
||||
//
|
||||
// Deprecated: This option type is no longer used and will be removed in the next release.
|
||||
func NewQuotedString(value *string) *QuotedString {
|
||||
return &QuotedString{value: value}
|
||||
}
|
||||
|
||||
16
src/cmd/linuxkit/vendor/github.com/go-logr/logr/.golangci.yaml
generated
vendored
16
src/cmd/linuxkit/vendor/github.com/go-logr/logr/.golangci.yaml
generated
vendored
@@ -1,26 +1,28 @@
|
||||
version: "2"
|
||||
|
||||
run:
|
||||
timeout: 1m
|
||||
tests: true
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
default: none
|
||||
enable: # please keep this alphabetized
|
||||
- asasalint
|
||||
- asciicheck
|
||||
- copyloopvar
|
||||
- dupl
|
||||
- errcheck
|
||||
- forcetypeassert
|
||||
- goconst
|
||||
- gocritic
|
||||
- gofmt
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- musttag
|
||||
- revive
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unused
|
||||
|
||||
issues:
|
||||
exclude-use-default: false
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 10
|
||||
|
||||
8
src/cmd/linuxkit/vendor/github.com/go-logr/logr/funcr/funcr.go
generated
vendored
8
src/cmd/linuxkit/vendor/github.com/go-logr/logr/funcr/funcr.go
generated
vendored
@@ -77,7 +77,7 @@ func newSink(fn func(prefix, args string), formatter Formatter) logr.LogSink {
|
||||
write: fn,
|
||||
}
|
||||
// For skipping fnlogger.Info and fnlogger.Error.
|
||||
l.Formatter.AddCallDepth(1)
|
||||
l.AddCallDepth(1) // via Formatter
|
||||
return l
|
||||
}
|
||||
|
||||
@@ -164,17 +164,17 @@ type fnlogger struct {
|
||||
}
|
||||
|
||||
func (l fnlogger) WithName(name string) logr.LogSink {
|
||||
l.Formatter.AddName(name)
|
||||
l.AddName(name) // via Formatter
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l fnlogger) WithValues(kvList ...any) logr.LogSink {
|
||||
l.Formatter.AddValues(kvList)
|
||||
l.AddValues(kvList) // via Formatter
|
||||
return &l
|
||||
}
|
||||
|
||||
func (l fnlogger) WithCallDepth(depth int) logr.LogSink {
|
||||
l.Formatter.AddCallDepth(depth)
|
||||
l.AddCallDepth(depth) // via Formatter
|
||||
return &l
|
||||
}
|
||||
|
||||
|
||||
150
src/cmd/linuxkit/vendor/github.com/gofrs/flock/.golangci.yml
generated
vendored
150
src/cmd/linuxkit/vendor/github.com/gofrs/flock/.golangci.yml
generated
vendored
@@ -1,5 +1,12 @@
|
||||
run:
|
||||
timeout: 10m
|
||||
version: "2"
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofumpt
|
||||
- goimports
|
||||
settings:
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
|
||||
linters:
|
||||
enable:
|
||||
@@ -18,9 +25,7 @@ linters:
|
||||
- gocritic
|
||||
- godot
|
||||
- godox
|
||||
- gofumpt
|
||||
- goheader
|
||||
- goimports
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
@@ -31,84 +36,81 @@ linters:
|
||||
- misspell
|
||||
- nolintlint
|
||||
- revive
|
||||
- stylecheck
|
||||
- tenv
|
||||
- staticcheck
|
||||
- testifylint
|
||||
- thelper
|
||||
- unconvert
|
||||
- unparam
|
||||
- usestdlibvars
|
||||
- whitespace
|
||||
|
||||
linters-settings:
|
||||
misspell:
|
||||
locale: US
|
||||
godox:
|
||||
keywords:
|
||||
- FIXME
|
||||
goheader:
|
||||
template: |-
|
||||
Copyright 2015 Tim Heckman. All rights reserved.
|
||||
Copyright 2018-{{ YEAR }} The Gofrs. All rights reserved.
|
||||
Use of this source code is governed by the BSD 3-Clause
|
||||
license that can be found in the LICENSE file.
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- style
|
||||
- performance
|
||||
disabled-checks:
|
||||
- paramTypeCombine # already handle by gofumpt.extra-rules
|
||||
- whyNoLint # already handle by nonolint
|
||||
- unnamedResult
|
||||
- hugeParam
|
||||
- sloppyReassign
|
||||
- rangeValCopy
|
||||
- octalLiteral
|
||||
- ptrToRefParam
|
||||
- appendAssign
|
||||
- ruleguard
|
||||
- httpNoBody
|
||||
- exposedSyncMutex
|
||||
|
||||
revive:
|
||||
rules:
|
||||
- name: struct-tag
|
||||
- name: blank-imports
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: error-naming
|
||||
- name: exported
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: var-naming
|
||||
- name: var-declaration
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: time-naming
|
||||
- name: unexported-return
|
||||
- name: indent-error-flow
|
||||
- name: errorf
|
||||
- name: empty-block
|
||||
- name: superfluous-else
|
||||
- name: unused-parameter
|
||||
- name: unreachable-code
|
||||
- name: redefines-builtin-id
|
||||
- wsl_v5
|
||||
settings:
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- paramTypeCombine # already handle by gofumpt.extra-rules
|
||||
- whyNoLint # already handle by nonolint
|
||||
- unnamedResult
|
||||
- hugeParam
|
||||
- sloppyReassign
|
||||
- rangeValCopy
|
||||
- octalLiteral
|
||||
- ptrToRefParam
|
||||
- appendAssign
|
||||
- ruleguard
|
||||
- httpNoBody
|
||||
- exposedSyncMutex
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- style
|
||||
- performance
|
||||
godox:
|
||||
keywords:
|
||||
- FIXME
|
||||
goheader:
|
||||
template: |-
|
||||
Copyright 2015 Tim Heckman. All rights reserved.
|
||||
Copyright 2018-{{ YEAR }} The Gofrs. All rights reserved.
|
||||
Use of this source code is governed by the BSD 3-Clause
|
||||
license that can be found in the LICENSE file.
|
||||
gosec:
|
||||
excludes:
|
||||
- G115
|
||||
misspell:
|
||||
locale: US
|
||||
revive:
|
||||
rules:
|
||||
- name: struct-tag
|
||||
- name: blank-imports
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: error-naming
|
||||
- name: exported
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: var-naming
|
||||
- name: var-declaration
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: time-naming
|
||||
- name: unexported-return
|
||||
- name: indent-error-flow
|
||||
- name: errorf
|
||||
- name: empty-block
|
||||
- name: superfluous-else
|
||||
- name: unused-parameter
|
||||
- name: unreachable-code
|
||||
- name: redefines-builtin-id
|
||||
exclusions:
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- std-error-handling
|
||||
|
||||
issues:
|
||||
exclude-use-default: true
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
output:
|
||||
show-stats: true
|
||||
sort-results: true
|
||||
sort-order:
|
||||
- linter
|
||||
- file
|
||||
|
||||
2
src/cmd/linuxkit/vendor/github.com/gofrs/flock/LICENSE
generated
vendored
2
src/cmd/linuxkit/vendor/github.com/gofrs/flock/LICENSE
generated
vendored
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2018-2024, The Gofrs
|
||||
Copyright (c) 2018-2025, The Gofrs
|
||||
Copyright (c) 2015-2020, Tim Heckman
|
||||
All rights reserved.
|
||||
|
||||
|
||||
20
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock.go
generated
vendored
20
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock.go
generated
vendored
@@ -1,5 +1,5 @@
|
||||
// Copyright 2015 Tim Heckman. All rights reserved.
|
||||
// Copyright 2018-2024 The Gofrs. All rights reserved.
|
||||
// Copyright 2018-2025 The Gofrs. All rights reserved.
|
||||
// Use of this source code is governed by the BSD 3-Clause
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -62,6 +62,7 @@ type Flock struct {
|
||||
func New(path string, opts ...Option) *Flock {
|
||||
// create it if it doesn't exist, and open the file read-only.
|
||||
flags := os.O_CREATE
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "aix", "solaris", "illumos":
|
||||
// AIX cannot preform write-lock (i.e. exclusive) on a read-only file.
|
||||
@@ -124,6 +125,22 @@ func (f *Flock) RLocked() bool {
|
||||
return f.r
|
||||
}
|
||||
|
||||
// Stat returns the FileInfo structure describing the lock file.
|
||||
// If the lock file does not exist or cannot be accessed, an error is returned.
|
||||
//
|
||||
// This can be used to check the modification time of the lock file,
|
||||
// which is useful for detecting stale locks.
|
||||
func (f *Flock) Stat() (fs.FileInfo, error) {
|
||||
f.m.RLock()
|
||||
defer f.m.RUnlock()
|
||||
|
||||
if f.fh != nil {
|
||||
return f.fh.Stat()
|
||||
}
|
||||
|
||||
return os.Stat(f.path)
|
||||
}
|
||||
|
||||
func (f *Flock) String() string {
|
||||
return f.path
|
||||
}
|
||||
@@ -158,7 +175,6 @@ func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Durati
|
||||
case <-ctx.Done():
|
||||
return false, ctx.Err()
|
||||
case <-time.After(retryDelay):
|
||||
// try again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_others.go
generated
vendored
5
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_others.go
generated
vendored
@@ -1,3 +1,8 @@
|
||||
// Copyright 2015 Tim Heckman. All rights reserved.
|
||||
// Copyright 2018-2025 The Gofrs. All rights reserved.
|
||||
// Use of this source code is governed by the BSD 3-Clause
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (!unix && !windows) || plan9
|
||||
|
||||
package flock
|
||||
|
||||
3
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_unix.go
generated
vendored
3
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_unix.go
generated
vendored
@@ -1,5 +1,5 @@
|
||||
// Copyright 2015 Tim Heckman. All rights reserved.
|
||||
// Copyright 2018-2024 The Gofrs. All rights reserved.
|
||||
// Copyright 2018-2025 The Gofrs. All rights reserved.
|
||||
// Use of this source code is governed by the BSD 3-Clause
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -155,6 +155,7 @@ func (f *Flock) try(locked *bool, flag int) (bool, error) {
|
||||
}
|
||||
|
||||
var retried bool
|
||||
|
||||
retry:
|
||||
err := unix.Flock(int(f.fh.Fd()), flag|unix.LOCK_NB)
|
||||
|
||||
|
||||
2
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_unix_fcntl.go
generated
vendored
2
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_unix_fcntl.go
generated
vendored
@@ -1,5 +1,5 @@
|
||||
// Copyright 2015 Tim Heckman. All rights reserved.
|
||||
// Copyright 2018-2024 The Gofrs. All rights reserved.
|
||||
// Copyright 2018-2025 The Gofrs. All rights reserved.
|
||||
// Use of this source code is governed by the BSD 3-Clause
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
4
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_windows.go
generated
vendored
4
src/cmd/linuxkit/vendor/github.com/gofrs/flock/flock_windows.go
generated
vendored
@@ -1,5 +1,5 @@
|
||||
// Copyright 2015 Tim Heckman. All rights reserved.
|
||||
// Copyright 2018-2024 The Gofrs. All rights reserved.
|
||||
// Copyright 2018-2025 The Gofrs. All rights reserved.
|
||||
// Use of this source code is governed by the BSD 3-Clause
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
@@ -23,6 +23,8 @@ const winLockfileSharedLock = 0x00000000
|
||||
|
||||
// ErrorLockViolation is the error code returned from the Windows syscall when a lock would block,
|
||||
// and you ask to fail immediately.
|
||||
//
|
||||
//nolint:errname // It should be renamed to `ErrLockViolation`.
|
||||
const ErrorLockViolation windows.Errno = 0x21 // 33
|
||||
|
||||
// Lock is a blocking call to try and take an exclusive file lock.
|
||||
|
||||
17
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/README.md
generated
vendored
17
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/README.md
generated
vendored
@@ -7,19 +7,13 @@ Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
|
||||
[WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
|
||||
|
||||
|
||||
---
|
||||
|
||||
⚠️ **[The Gorilla WebSocket Package is looking for a new maintainer](https://github.com/gorilla/websocket/issues/370)**
|
||||
|
||||
---
|
||||
|
||||
### Documentation
|
||||
|
||||
* [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc)
|
||||
* [Chat example](https://github.com/gorilla/websocket/tree/master/examples/chat)
|
||||
* [Command example](https://github.com/gorilla/websocket/tree/master/examples/command)
|
||||
* [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo)
|
||||
* [File watch example](https://github.com/gorilla/websocket/tree/master/examples/filewatch)
|
||||
* [Chat example](https://github.com/gorilla/websocket/tree/main/examples/chat)
|
||||
* [Command example](https://github.com/gorilla/websocket/tree/main/examples/command)
|
||||
* [Client and server example](https://github.com/gorilla/websocket/tree/main/examples/echo)
|
||||
* [File watch example](https://github.com/gorilla/websocket/tree/main/examples/filewatch)
|
||||
|
||||
### Status
|
||||
|
||||
@@ -35,5 +29,4 @@ package API is stable.
|
||||
|
||||
The Gorilla WebSocket package passes the server tests in the [Autobahn Test
|
||||
Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn
|
||||
subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn).
|
||||
|
||||
subdirectory](https://github.com/gorilla/websocket/tree/main/examples/autobahn).
|
||||
|
||||
245
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client.go
generated
vendored
245
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/client.go
generated
vendored
@@ -9,8 +9,8 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
@@ -51,18 +51,34 @@ func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufS
|
||||
//
|
||||
// It is safe to call Dialer's methods concurrently.
|
||||
type Dialer struct {
|
||||
// The following custom dial functions can be set to establish
|
||||
// connections to either the backend server or the proxy (if it
|
||||
// exists). The scheme of the dialed entity (either backend or
|
||||
// proxy) determines which custom dial function is selected:
|
||||
// either NetDialTLSContext for HTTPS or NetDialContext/NetDial
|
||||
// for HTTP. Since the "Proxy" function can determine the scheme
|
||||
// dynamically, it can make sense to set multiple custom dial
|
||||
// functions simultaneously.
|
||||
//
|
||||
// NetDial specifies the dial function for creating TCP connections. If
|
||||
// NetDial is nil, net.Dial is used.
|
||||
// NetDial is nil, net.Dialer DialContext is used.
|
||||
// If "Proxy" field is also set, this function dials the proxy--not
|
||||
// the backend server.
|
||||
NetDial func(network, addr string) (net.Conn, error)
|
||||
|
||||
// NetDialContext specifies the dial function for creating TCP connections. If
|
||||
// NetDialContext is nil, NetDial is used.
|
||||
// If "Proxy" field is also set, this function dials the proxy--not
|
||||
// the backend server.
|
||||
NetDialContext func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
// NetDialTLSContext specifies the dial function for creating TLS/TCP connections. If
|
||||
// NetDialTLSContext is nil, NetDialContext is used.
|
||||
// If NetDialTLSContext is set, Dial assumes the TLS handshake is done there and
|
||||
// TLSClientConfig is ignored.
|
||||
// If "Proxy" field is also set, this function dials the proxy (and performs
|
||||
// the TLS handshake with the proxy, ignoring TLSClientConfig). In this TLS proxy
|
||||
// dialing case the TLSClientConfig could still be necessary for TLS to the backend server.
|
||||
NetDialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
// Proxy specifies a function to return a proxy for a given
|
||||
@@ -73,7 +89,7 @@ type Dialer struct {
|
||||
|
||||
// TLSClientConfig specifies the TLS configuration to use with tls.Client.
|
||||
// If nil, the default configuration is used.
|
||||
// If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake
|
||||
// If NetDialTLSContext is set, Dial assumes the TLS handshake
|
||||
// is done there and TLSClientConfig is ignored.
|
||||
TLSClientConfig *tls.Config
|
||||
|
||||
@@ -244,71 +260,16 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
// Get network dial function.
|
||||
var netDial func(network, add string) (net.Conn, error)
|
||||
|
||||
switch u.Scheme {
|
||||
case "http":
|
||||
if d.NetDialContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialContext(ctx, network, addr)
|
||||
}
|
||||
} else if d.NetDial != nil {
|
||||
netDial = d.NetDial
|
||||
}
|
||||
case "https":
|
||||
if d.NetDialTLSContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialTLSContext(ctx, network, addr)
|
||||
}
|
||||
} else if d.NetDialContext != nil {
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return d.NetDialContext(ctx, network, addr)
|
||||
}
|
||||
} else if d.NetDial != nil {
|
||||
netDial = d.NetDial
|
||||
}
|
||||
default:
|
||||
return nil, nil, errMalformedURL
|
||||
}
|
||||
|
||||
if netDial == nil {
|
||||
netDialer := &net.Dialer{}
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
return netDialer.DialContext(ctx, network, addr)
|
||||
}
|
||||
}
|
||||
|
||||
// If needed, wrap the dial function to set the connection deadline.
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
forwardDial := netDial
|
||||
netDial = func(network, addr string) (net.Conn, error) {
|
||||
c, err := forwardDial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = c.SetDeadline(deadline)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
||||
// If needed, wrap the dial function to connect through a proxy.
|
||||
var proxyURL *url.URL
|
||||
if d.Proxy != nil {
|
||||
proxyURL, err := d.Proxy(req)
|
||||
proxyURL, err = d.Proxy(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if proxyURL != nil {
|
||||
dialer, err := proxy_FromURL(proxyURL, netDialerFunc(netDial))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
netDial = dialer.Dial
|
||||
}
|
||||
}
|
||||
netDial, err := d.netDialFn(ctx, proxyURL, u)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
hostPort, hostNoPort := hostPortNoPort(u)
|
||||
@@ -317,24 +278,30 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
trace.GetConn(hostPort)
|
||||
}
|
||||
|
||||
netConn, err := netDial("tcp", hostPort)
|
||||
netConn, err := netDial(ctx, "tcp", hostPort)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if trace != nil && trace.GotConn != nil {
|
||||
trace.GotConn(httptrace.GotConnInfo{
|
||||
Conn: netConn,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Close the network connection when returning an error. The variable
|
||||
// netConn is set to nil before the success return at the end of the
|
||||
// function.
|
||||
defer func() {
|
||||
if netConn != nil {
|
||||
netConn.Close()
|
||||
// It's safe to ignore the error from Close() because this code is
|
||||
// only executed when returning a more important error to the
|
||||
// application.
|
||||
_ = netConn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
if u.Scheme == "https" && d.NetDialTLSContext == nil {
|
||||
// If NetDialTLSContext is set, assume that the TLS handshake has already been done
|
||||
// Do TLS handshake over established connection if a proxy exists.
|
||||
if proxyURL != nil && u.Scheme == "https" {
|
||||
|
||||
cfg := cloneTLSConfig(d.TLSClientConfig)
|
||||
if cfg.ServerName == "" {
|
||||
@@ -370,6 +337,17 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
|
||||
resp, err := http.ReadResponse(conn.br, req)
|
||||
if err != nil {
|
||||
if d.TLSClientConfig != nil {
|
||||
for _, proto := range d.TLSClientConfig.NextProtos {
|
||||
if proto != "http/1.1" {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"websocket: protocol %q was given but is not supported;"+
|
||||
"sharing tls.Config with net/http Transport can cause this error: %w",
|
||||
proto, err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -388,7 +366,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
// debugging.
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := io.ReadFull(resp.Body, buf)
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader(buf[:n]))
|
||||
resp.Body = io.NopCloser(bytes.NewReader(buf[:n]))
|
||||
return nil, resp, ErrBadHandshake
|
||||
}
|
||||
|
||||
@@ -406,17 +384,134 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
|
||||
break
|
||||
}
|
||||
|
||||
resp.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
|
||||
resp.Body = io.NopCloser(bytes.NewReader([]byte{}))
|
||||
conn.subprotocol = resp.Header.Get("Sec-Websocket-Protocol")
|
||||
|
||||
netConn.SetDeadline(time.Time{})
|
||||
netConn = nil // to avoid close in defer.
|
||||
if err := netConn.SetDeadline(time.Time{}); err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
// Success! Set netConn to nil to stop the deferred function above from
|
||||
// closing the network connection.
|
||||
netConn = nil
|
||||
|
||||
return conn, resp, nil
|
||||
}
|
||||
|
||||
// Returns the dial function to establish the connection to either the backend
|
||||
// server or the proxy (if it exists). If the dialed entity is HTTPS, then the
|
||||
// returned dial function *also* performs the TLS handshake to the dialed entity.
|
||||
// NOTE: If a proxy exists, it is possible for a second TLS handshake to be
|
||||
// necessary over the established connection.
|
||||
func (d *Dialer) netDialFn(ctx context.Context, proxyURL *url.URL, backendURL *url.URL) (netDialerFunc, error) {
|
||||
var netDial netDialerFunc
|
||||
if proxyURL != nil {
|
||||
netDial = d.netDialFromURL(proxyURL)
|
||||
} else {
|
||||
netDial = d.netDialFromURL(backendURL)
|
||||
}
|
||||
// If needed, wrap the dial function to set the connection deadline.
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
netDial = netDialWithDeadline(netDial, deadline)
|
||||
}
|
||||
// Proxy dialing is wrapped to implement CONNECT method and possibly proxy auth.
|
||||
if proxyURL != nil {
|
||||
return proxyFromURL(proxyURL, netDial)
|
||||
}
|
||||
return netDial, nil
|
||||
}
|
||||
|
||||
// Returns function to create the connection depending on the Dialer's
|
||||
// custom dialing functions and the passed URL of entity connecting to.
|
||||
func (d *Dialer) netDialFromURL(u *url.URL) netDialerFunc {
|
||||
var netDial netDialerFunc
|
||||
switch {
|
||||
case d.NetDialContext != nil:
|
||||
netDial = d.NetDialContext
|
||||
case d.NetDial != nil:
|
||||
netDial = func(ctx context.Context, net, addr string) (net.Conn, error) {
|
||||
return d.NetDial(net, addr)
|
||||
}
|
||||
default:
|
||||
netDial = (&net.Dialer{}).DialContext
|
||||
}
|
||||
// If dialed entity is HTTPS, then either use custom TLS dialing function (if exists)
|
||||
// or wrap the previously computed "netDial" to use TLS config for handshake.
|
||||
if u.Scheme == "https" {
|
||||
if d.NetDialTLSContext != nil {
|
||||
netDial = d.NetDialTLSContext
|
||||
} else {
|
||||
netDial = netDialWithTLSHandshake(netDial, d.TLSClientConfig, u)
|
||||
}
|
||||
}
|
||||
return netDial
|
||||
}
|
||||
|
||||
// Returns wrapped "netDial" function, performing TLS handshake after connecting.
|
||||
func netDialWithTLSHandshake(netDial netDialerFunc, tlsConfig *tls.Config, u *url.URL) netDialerFunc {
|
||||
return func(ctx context.Context, unused, addr string) (net.Conn, error) {
|
||||
hostPort, hostNoPort := hostPortNoPort(u)
|
||||
trace := httptrace.ContextClientTrace(ctx)
|
||||
if trace != nil && trace.GetConn != nil {
|
||||
trace.GetConn(hostPort)
|
||||
}
|
||||
// Creates TCP connection to addr using passed "netDial" function.
|
||||
conn, err := netDial(ctx, "tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := cloneTLSConfig(tlsConfig)
|
||||
if cfg.ServerName == "" {
|
||||
cfg.ServerName = hostNoPort
|
||||
}
|
||||
tlsConn := tls.Client(conn, cfg)
|
||||
// Do the TLS handshake using TLSConfig over the wrapped connection.
|
||||
if trace != nil && trace.TLSHandshakeStart != nil {
|
||||
trace.TLSHandshakeStart()
|
||||
}
|
||||
err = doHandshake(ctx, tlsConn, cfg)
|
||||
if trace != nil && trace.TLSHandshakeDone != nil {
|
||||
trace.TLSHandshakeDone(tlsConn.ConnectionState(), err)
|
||||
}
|
||||
if err != nil {
|
||||
tlsConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return tlsConn, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Returns wrapped "netDial" function, setting passed deadline.
|
||||
func netDialWithDeadline(netDial netDialerFunc, deadline time.Time) netDialerFunc {
|
||||
return func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
c, err := netDial(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = c.SetDeadline(deadline)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
||||
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
|
||||
if cfg == nil {
|
||||
return &tls.Config{}
|
||||
}
|
||||
return cfg.Clone()
|
||||
}
|
||||
|
||||
func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
6
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/compression.go
generated
vendored
6
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/compression.go
generated
vendored
@@ -33,7 +33,11 @@ func decompressNoContextTakeover(r io.Reader) io.ReadCloser {
|
||||
"\x01\x00\x00\xff\xff"
|
||||
|
||||
fr, _ := flateReaderPool.Get().(io.ReadCloser)
|
||||
fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
|
||||
mr := io.MultiReader(r, strings.NewReader(tail))
|
||||
if err := fr.(flate.Resetter).Reset(mr, nil); err != nil {
|
||||
// Reset never fails, but handle error in case that changes.
|
||||
fr = flate.NewReader(mr)
|
||||
}
|
||||
return &flateReadWrapper{fr}
|
||||
}
|
||||
|
||||
|
||||
112
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn.go
generated
vendored
112
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/conn.go
generated
vendored
@@ -6,11 +6,10 @@ package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -181,16 +180,16 @@ var (
|
||||
errInvalidControlFrame = errors.New("websocket: invalid control frame")
|
||||
)
|
||||
|
||||
func newMaskKey() [4]byte {
|
||||
n := rand.Uint32()
|
||||
return [4]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24)}
|
||||
}
|
||||
// maskRand is an io.Reader for generating mask bytes. The reader is initialized
|
||||
// to crypto/rand Reader. Tests swap the reader to a math/rand reader for
|
||||
// reproducible results.
|
||||
var maskRand = rand.Reader
|
||||
|
||||
func hideTempErr(err error) error {
|
||||
if e, ok := err.(net.Error); ok && e.Temporary() {
|
||||
err = &netError{msg: e.Error(), timeout: e.Timeout()}
|
||||
}
|
||||
return err
|
||||
// newMaskKey returns a new 32 bit value for masking client frames.
|
||||
func newMaskKey() [4]byte {
|
||||
var k [4]byte
|
||||
_, _ = io.ReadFull(maskRand, k[:])
|
||||
return k
|
||||
}
|
||||
|
||||
func isControl(frameType int) bool {
|
||||
@@ -358,7 +357,6 @@ func (c *Conn) RemoteAddr() net.Addr {
|
||||
// Write methods
|
||||
|
||||
func (c *Conn) writeFatal(err error) error {
|
||||
err = hideTempErr(err)
|
||||
c.writeErrMu.Lock()
|
||||
if c.writeErr == nil {
|
||||
c.writeErr = err
|
||||
@@ -372,7 +370,9 @@ func (c *Conn) read(n int) ([]byte, error) {
|
||||
if err == io.EOF {
|
||||
err = errUnexpectedEOF
|
||||
}
|
||||
c.br.Discard(len(p))
|
||||
// Discard is guaranteed to succeed because the number of bytes to discard
|
||||
// is less than or equal to the number of bytes buffered.
|
||||
_, _ = c.br.Discard(len(p))
|
||||
return p, err
|
||||
}
|
||||
|
||||
@@ -387,7 +387,9 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error
|
||||
return err
|
||||
}
|
||||
|
||||
c.conn.SetWriteDeadline(deadline)
|
||||
if err := c.conn.SetWriteDeadline(deadline); err != nil {
|
||||
return c.writeFatal(err)
|
||||
}
|
||||
if len(buf1) == 0 {
|
||||
_, err = c.conn.Write(buf0)
|
||||
} else {
|
||||
@@ -397,7 +399,7 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error
|
||||
return c.writeFatal(err)
|
||||
}
|
||||
if frameType == CloseMessage {
|
||||
c.writeFatal(ErrCloseSent)
|
||||
_ = c.writeFatal(ErrCloseSent)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -436,21 +438,27 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
|
||||
maskBytes(key, 0, buf[6:])
|
||||
}
|
||||
|
||||
d := 1000 * time.Hour
|
||||
if !deadline.IsZero() {
|
||||
d = deadline.Sub(time.Now())
|
||||
if deadline.IsZero() {
|
||||
// No timeout for zero time.
|
||||
<-c.mu
|
||||
} else {
|
||||
d := time.Until(deadline)
|
||||
if d < 0 {
|
||||
return errWriteTimeout
|
||||
}
|
||||
select {
|
||||
case <-c.mu:
|
||||
default:
|
||||
timer := time.NewTimer(d)
|
||||
select {
|
||||
case <-c.mu:
|
||||
timer.Stop()
|
||||
case <-timer.C:
|
||||
return errWriteTimeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timer := time.NewTimer(d)
|
||||
select {
|
||||
case <-c.mu:
|
||||
timer.Stop()
|
||||
case <-timer.C:
|
||||
return errWriteTimeout
|
||||
}
|
||||
defer func() { c.mu <- struct{}{} }()
|
||||
|
||||
c.writeErrMu.Lock()
|
||||
@@ -460,13 +468,14 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
|
||||
return err
|
||||
}
|
||||
|
||||
c.conn.SetWriteDeadline(deadline)
|
||||
_, err = c.conn.Write(buf)
|
||||
if err != nil {
|
||||
if err := c.conn.SetWriteDeadline(deadline); err != nil {
|
||||
return c.writeFatal(err)
|
||||
}
|
||||
if _, err = c.conn.Write(buf); err != nil {
|
||||
return c.writeFatal(err)
|
||||
}
|
||||
if messageType == CloseMessage {
|
||||
c.writeFatal(ErrCloseSent)
|
||||
_ = c.writeFatal(ErrCloseSent)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -630,7 +639,7 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error {
|
||||
}
|
||||
|
||||
if final {
|
||||
w.endMessage(errWriteClosed)
|
||||
_ = w.endMessage(errWriteClosed)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -795,7 +804,7 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
// 1. Skip remainder of previous frame.
|
||||
|
||||
if c.readRemaining > 0 {
|
||||
if _, err := io.CopyN(ioutil.Discard, c.br, c.readRemaining); err != nil {
|
||||
if _, err := io.CopyN(io.Discard, c.br, c.readRemaining); err != nil {
|
||||
return noFrame, err
|
||||
}
|
||||
}
|
||||
@@ -817,7 +826,7 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
rsv2 := p[0]&rsv2Bit != 0
|
||||
rsv3 := p[0]&rsv3Bit != 0
|
||||
mask := p[1]&maskBit != 0
|
||||
c.setReadRemaining(int64(p[1] & 0x7f))
|
||||
_ = c.setReadRemaining(int64(p[1] & 0x7f)) // will not fail because argument is >= 0
|
||||
|
||||
c.readDecompress = false
|
||||
if rsv1 {
|
||||
@@ -922,7 +931,8 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
}
|
||||
|
||||
if c.readLimit > 0 && c.readLength > c.readLimit {
|
||||
c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait))
|
||||
// Make a best effort to send a close message describing the problem.
|
||||
_ = c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait))
|
||||
return noFrame, ErrReadLimit
|
||||
}
|
||||
|
||||
@@ -934,7 +944,7 @@ func (c *Conn) advanceFrame() (int, error) {
|
||||
var payload []byte
|
||||
if c.readRemaining > 0 {
|
||||
payload, err = c.read(int(c.readRemaining))
|
||||
c.setReadRemaining(0)
|
||||
_ = c.setReadRemaining(0) // will not fail because argument is >= 0
|
||||
if err != nil {
|
||||
return noFrame, err
|
||||
}
|
||||
@@ -981,7 +991,8 @@ func (c *Conn) handleProtocolError(message string) error {
|
||||
if len(data) > maxControlFramePayloadSize {
|
||||
data = data[:maxControlFramePayloadSize]
|
||||
}
|
||||
c.WriteControl(CloseMessage, data, time.Now().Add(writeWait))
|
||||
// Make a best effor to send a close message describing the problem.
|
||||
_ = c.WriteControl(CloseMessage, data, time.Now().Add(writeWait))
|
||||
return errors.New("websocket: " + message)
|
||||
}
|
||||
|
||||
@@ -1008,7 +1019,7 @@ func (c *Conn) NextReader() (messageType int, r io.Reader, err error) {
|
||||
for c.readErr == nil {
|
||||
frameType, err := c.advanceFrame()
|
||||
if err != nil {
|
||||
c.readErr = hideTempErr(err)
|
||||
c.readErr = err
|
||||
break
|
||||
}
|
||||
|
||||
@@ -1048,13 +1059,13 @@ func (r *messageReader) Read(b []byte) (int, error) {
|
||||
b = b[:c.readRemaining]
|
||||
}
|
||||
n, err := c.br.Read(b)
|
||||
c.readErr = hideTempErr(err)
|
||||
c.readErr = err
|
||||
if c.isServer {
|
||||
c.readMaskPos = maskBytes(c.readMaskKey, c.readMaskPos, b[:n])
|
||||
}
|
||||
rem := c.readRemaining
|
||||
rem -= int64(n)
|
||||
c.setReadRemaining(rem)
|
||||
_ = c.setReadRemaining(rem) // rem is guaranteed to be >= 0
|
||||
if c.readRemaining > 0 && c.readErr == io.EOF {
|
||||
c.readErr = errUnexpectedEOF
|
||||
}
|
||||
@@ -1069,7 +1080,7 @@ func (r *messageReader) Read(b []byte) (int, error) {
|
||||
frameType, err := c.advanceFrame()
|
||||
switch {
|
||||
case err != nil:
|
||||
c.readErr = hideTempErr(err)
|
||||
c.readErr = err
|
||||
case frameType == TextMessage || frameType == BinaryMessage:
|
||||
c.readErr = errors.New("websocket: internal error, unexpected text or binary in Reader")
|
||||
}
|
||||
@@ -1094,7 +1105,7 @@ func (c *Conn) ReadMessage() (messageType int, p []byte, err error) {
|
||||
if err != nil {
|
||||
return messageType, nil, err
|
||||
}
|
||||
p, err = ioutil.ReadAll(r)
|
||||
p, err = io.ReadAll(r)
|
||||
return messageType, p, err
|
||||
}
|
||||
|
||||
@@ -1136,7 +1147,8 @@ func (c *Conn) SetCloseHandler(h func(code int, text string) error) {
|
||||
if h == nil {
|
||||
h = func(code int, text string) error {
|
||||
message := FormatCloseMessage(code, "")
|
||||
c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
|
||||
// Make a best effor to send the close message.
|
||||
_ = c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -1158,13 +1170,9 @@ func (c *Conn) PingHandler() func(appData string) error {
|
||||
func (c *Conn) SetPingHandler(h func(appData string) error) {
|
||||
if h == nil {
|
||||
h = func(message string) error {
|
||||
err := c.WriteControl(PongMessage, []byte(message), time.Now().Add(writeWait))
|
||||
if err == ErrCloseSent {
|
||||
return nil
|
||||
} else if e, ok := err.(net.Error); ok && e.Temporary() {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
// Make a best effort to send the pong message.
|
||||
_ = c.WriteControl(PongMessage, []byte(message), time.Now().Add(writeWait))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
c.handlePing = h
|
||||
@@ -1189,8 +1197,16 @@ func (c *Conn) SetPongHandler(h func(appData string) error) {
|
||||
c.handlePong = h
|
||||
}
|
||||
|
||||
// NetConn returns the underlying connection that is wrapped by c.
|
||||
// Note that writing to or reading from this connection directly will corrupt the
|
||||
// WebSocket connection.
|
||||
func (c *Conn) NetConn() net.Conn {
|
||||
return c.conn
|
||||
}
|
||||
|
||||
// UnderlyingConn returns the internal net.Conn. This can be used to further
|
||||
// modifications to connection specific flags.
|
||||
// Deprecated: Use the NetConn method.
|
||||
func (c *Conn) UnderlyingConn() net.Conn {
|
||||
return c.conn
|
||||
}
|
||||
|
||||
53
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
53
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/proxy.go
generated
vendored
@@ -6,34 +6,52 @@ package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
type netDialerFunc func(network, addr string) (net.Conn, error)
|
||||
type netDialerFunc func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) {
|
||||
return fn(network, addr)
|
||||
return fn(context.Background(), network, addr)
|
||||
}
|
||||
|
||||
func init() {
|
||||
proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) {
|
||||
return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil
|
||||
})
|
||||
func (fn netDialerFunc) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return fn(ctx, network, addr)
|
||||
}
|
||||
|
||||
func proxyFromURL(proxyURL *url.URL, forwardDial netDialerFunc) (netDialerFunc, error) {
|
||||
if proxyURL.Scheme == "http" || proxyURL.Scheme == "https" {
|
||||
return (&httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDial}).DialContext, nil
|
||||
}
|
||||
dialer, err := proxy.FromURL(proxyURL, forwardDial)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d, ok := dialer.(proxy.ContextDialer); ok {
|
||||
return d.DialContext, nil
|
||||
}
|
||||
return func(ctx context.Context, net, addr string) (net.Conn, error) {
|
||||
return dialer.Dial(net, addr)
|
||||
}, nil
|
||||
}
|
||||
|
||||
type httpProxyDialer struct {
|
||||
proxyURL *url.URL
|
||||
forwardDial func(network, addr string) (net.Conn, error)
|
||||
forwardDial netDialerFunc
|
||||
}
|
||||
|
||||
func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) {
|
||||
func (hpd *httpProxyDialer) DialContext(ctx context.Context, network string, addr string) (net.Conn, error) {
|
||||
hostPort, _ := hostPortNoPort(hpd.proxyURL)
|
||||
conn, err := hpd.forwardDial(network, hostPort)
|
||||
conn, err := hpd.forwardDial(ctx, network, hostPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -46,7 +64,6 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
|
||||
connectHeader.Set("Proxy-Authorization", "Basic "+credential)
|
||||
}
|
||||
}
|
||||
|
||||
connectReq := &http.Request{
|
||||
Method: http.MethodConnect,
|
||||
URL: &url.URL{Opaque: addr},
|
||||
@@ -59,7 +76,7 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read response. It's OK to use and discard buffered reader here becaue
|
||||
// Read response. It's OK to use and discard buffered reader here because
|
||||
// the remote server does not speak until spoken to.
|
||||
br := bufio.NewReader(conn)
|
||||
resp, err := http.ReadResponse(br, connectReq)
|
||||
@@ -68,8 +85,18 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
conn.Close()
|
||||
// Close the response body to silence false positives from linters. Reset
|
||||
// the buffered reader first to ensure that Close() does not read from
|
||||
// conn.
|
||||
// Note: Applications must call resp.Body.Close() on a response returned
|
||||
// http.ReadResponse to inspect trailers or read another response from the
|
||||
// buffered reader. The call to resp.Body.Close() does not release
|
||||
// resources.
|
||||
br.Reset(bytes.NewReader(nil))
|
||||
_ = resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
_ = conn.Close()
|
||||
f := strings.SplitN(resp.Status, " ", 2)
|
||||
return nil, errors.New(f[1])
|
||||
}
|
||||
|
||||
124
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/server.go
generated
vendored
124
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/server.go
generated
vendored
@@ -6,8 +6,7 @@ package websocket
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -101,8 +100,8 @@ func checkSameOrigin(r *http.Request) bool {
|
||||
func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header) string {
|
||||
if u.Subprotocols != nil {
|
||||
clientProtocols := Subprotocols(r)
|
||||
for _, serverProtocol := range u.Subprotocols {
|
||||
for _, clientProtocol := range clientProtocols {
|
||||
for _, clientProtocol := range clientProtocols {
|
||||
for _, serverProtocol := range u.Subprotocols {
|
||||
if clientProtocol == serverProtocol {
|
||||
return clientProtocol
|
||||
}
|
||||
@@ -130,7 +129,8 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||
}
|
||||
|
||||
if !tokenListContainsValue(r.Header, "Upgrade", "websocket") {
|
||||
return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
|
||||
w.Header().Set("Upgrade", "websocket")
|
||||
return u.returnError(w, r, http.StatusUpgradeRequired, badHandshake+"'websocket' token not found in 'Upgrade' header")
|
||||
}
|
||||
|
||||
if r.Method != http.MethodGet {
|
||||
@@ -154,8 +154,8 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||
}
|
||||
|
||||
challengeKey := r.Header.Get("Sec-Websocket-Key")
|
||||
if challengeKey == "" {
|
||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank")
|
||||
if !isValidChallengeKey(challengeKey) {
|
||||
return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header must be Base64 encoded value of 16-byte in length")
|
||||
}
|
||||
|
||||
subprotocol := u.selectSubprotocol(r, responseHeader)
|
||||
@@ -172,28 +172,37 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||
}
|
||||
}
|
||||
|
||||
h, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
return u.returnError(w, r, http.StatusInternalServerError, "websocket: response does not implement http.Hijacker")
|
||||
}
|
||||
var brw *bufio.ReadWriter
|
||||
netConn, brw, err := h.Hijack()
|
||||
netConn, brw, err := http.NewResponseController(w).Hijack()
|
||||
if err != nil {
|
||||
return u.returnError(w, r, http.StatusInternalServerError, err.Error())
|
||||
return u.returnError(w, r, http.StatusInternalServerError,
|
||||
"websocket: hijack: "+err.Error())
|
||||
}
|
||||
|
||||
if brw.Reader.Buffered() > 0 {
|
||||
netConn.Close()
|
||||
return nil, errors.New("websocket: client sent data before handshake is complete")
|
||||
}
|
||||
// Close the network connection when returning an error. The variable
|
||||
// netConn is set to nil before the success return at the end of the
|
||||
// function.
|
||||
defer func() {
|
||||
if netConn != nil {
|
||||
// It's safe to ignore the error from Close() because this code is
|
||||
// only executed when returning a more important error to the
|
||||
// application.
|
||||
_ = netConn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
var br *bufio.Reader
|
||||
if u.ReadBufferSize == 0 && bufioReaderSize(netConn, brw.Reader) > 256 {
|
||||
// Reuse hijacked buffered reader as connection reader.
|
||||
if u.ReadBufferSize == 0 && brw.Reader.Size() > 256 {
|
||||
// Use hijacked buffered reader as the connection reader.
|
||||
br = brw.Reader
|
||||
} else if brw.Reader.Buffered() > 0 {
|
||||
// Wrap the network connection to read buffered data in brw.Reader
|
||||
// before reading from the network connection. This should be rare
|
||||
// because a client must not send message data before receiving the
|
||||
// handshake response.
|
||||
netConn = &brNetConn{br: brw.Reader, Conn: netConn}
|
||||
}
|
||||
|
||||
buf := bufioWriterBuffer(netConn, brw.Writer)
|
||||
buf := brw.Writer.AvailableBuffer()
|
||||
|
||||
var writeBuf []byte
|
||||
if u.WriteBufferPool == nil && u.WriteBufferSize == 0 && len(buf) >= maxFrameHeaderSize+256 {
|
||||
@@ -247,20 +256,30 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||
}
|
||||
p = append(p, "\r\n"...)
|
||||
|
||||
// Clear deadlines set by HTTP server.
|
||||
netConn.SetDeadline(time.Time{})
|
||||
|
||||
if u.HandshakeTimeout > 0 {
|
||||
netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout))
|
||||
if err := netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Clear deadlines set by HTTP server.
|
||||
if err := netConn.SetDeadline(time.Time{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = netConn.Write(p); err != nil {
|
||||
netConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
if u.HandshakeTimeout > 0 {
|
||||
netConn.SetWriteDeadline(time.Time{})
|
||||
if err := netConn.SetWriteDeadline(time.Time{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Success! Set netConn to nil to stop the deferred function above from
|
||||
// closing the network connection.
|
||||
netConn = nil
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -327,39 +346,28 @@ func IsWebSocketUpgrade(r *http.Request) bool {
|
||||
tokenListContainsValue(r.Header, "Upgrade", "websocket")
|
||||
}
|
||||
|
||||
// bufioReaderSize size returns the size of a bufio.Reader.
|
||||
func bufioReaderSize(originalReader io.Reader, br *bufio.Reader) int {
|
||||
// This code assumes that peek on a reset reader returns
|
||||
// bufio.Reader.buf[:0].
|
||||
// TODO: Use bufio.Reader.Size() after Go 1.10
|
||||
br.Reset(originalReader)
|
||||
if p, err := br.Peek(0); err == nil {
|
||||
return cap(p)
|
||||
type brNetConn struct {
|
||||
br *bufio.Reader
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (b *brNetConn) Read(p []byte) (n int, err error) {
|
||||
if b.br != nil {
|
||||
// Limit read to buferred data.
|
||||
if n := b.br.Buffered(); len(p) > n {
|
||||
p = p[:n]
|
||||
}
|
||||
n, err = b.br.Read(p)
|
||||
if b.br.Buffered() == 0 {
|
||||
b.br = nil
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
return 0
|
||||
return b.Conn.Read(p)
|
||||
}
|
||||
|
||||
// writeHook is an io.Writer that records the last slice passed to it vio
|
||||
// io.Writer.Write.
|
||||
type writeHook struct {
|
||||
p []byte
|
||||
// NetConn returns the underlying connection that is wrapped by b.
|
||||
func (b *brNetConn) NetConn() net.Conn {
|
||||
return b.Conn
|
||||
}
|
||||
|
||||
func (wh *writeHook) Write(p []byte) (int, error) {
|
||||
wh.p = p
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// bufioWriterBuffer grabs the buffer from a bufio.Writer.
|
||||
func bufioWriterBuffer(originalWriter io.Writer, bw *bufio.Writer) []byte {
|
||||
// This code assumes that bufio.Writer.buf[:1] is passed to the
|
||||
// bufio.Writer's underlying writer.
|
||||
var wh writeHook
|
||||
bw.Reset(&wh)
|
||||
bw.WriteByte(0)
|
||||
bw.Flush()
|
||||
|
||||
bw.Reset(originalWriter)
|
||||
|
||||
return wh.p[:cap(wh.p)]
|
||||
}
|
||||
|
||||
21
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/tls_handshake.go
generated
vendored
21
src/cmd/linuxkit/vendor/github.com/gorilla/websocket/tls_handshake.go
generated
vendored
@@ -1,21 +0,0 @@
|
||||
//go:build go1.17
|
||||
// +build go1.17
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
)
|
||||
|
||||
func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user