Compare commits
27 Commits
cmd/v0.17.
...
main
Author | SHA1 | Date |
---|---|---|
|
554629b4a1 | |
|
a986f8c194 | |
|
38cf9aa57c | |
|
e07c7abb8c | |
|
7b508b1afe | |
|
08272a30af | |
|
d09a4ffa5b | |
|
1227c8e42b | |
|
21fb6a16e4 | |
|
f400f935f7 | |
|
d0487729a1 | |
|
2aef7a6e63 | |
|
18e393af96 | |
|
927075ba7b | |
|
e53cec5266 | |
|
555e167719 | |
|
f72d3aecc8 | |
|
19a5bd5157 | |
|
f62679453f | |
|
17134ee517 | |
|
420a03fa46 | |
|
3aa69eaac5 | |
|
b3743e7916 | |
|
4677721cfc | |
|
9e6b9b72af | |
|
cfa57c95a9 | |
|
24e8a7858a |
|
@ -50,7 +50,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Download Builds
|
- name: Download Builds
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
path: ${{ env.OUTPUT_DIR }}
|
path: ${{ env.OUTPUT_DIR }}
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
|
|
|
@ -246,7 +246,7 @@ RUN apt-get update && apt-get install -y iptables && \
|
||||||
curl -Ls https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${TARGETARCH:-amd64}-${CNI_PLUGINS_VERSION}.tgz | tar xzv -C /opt/cni/bin
|
curl -Ls https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/cni-plugins-linux-${TARGETARCH:-amd64}-${CNI_PLUGINS_VERSION}.tgz | tar xzv -C /opt/cni/bin
|
||||||
|
|
||||||
# Image which can be used as a node image for KinD (containerd with builtin snapshotter)
|
# Image which can be used as a node image for KinD (containerd with builtin snapshotter)
|
||||||
FROM kindest/node:v1.33.1 AS kind-builtin-snapshotter
|
FROM kindest/node:v1.33.2 AS kind-builtin-snapshotter
|
||||||
COPY --from=containerd-snapshotter-dev /out/bin/containerd /out/bin/containerd-shim-runc-v2 /usr/local/bin/
|
COPY --from=containerd-snapshotter-dev /out/bin/containerd /out/bin/containerd-shim-runc-v2 /usr/local/bin/
|
||||||
COPY --from=snapshotter-dev /out/ctr-remote /usr/local/bin/
|
COPY --from=snapshotter-dev /out/ctr-remote /usr/local/bin/
|
||||||
COPY ./script/config/ /
|
COPY ./script/config/ /
|
||||||
|
@ -287,7 +287,7 @@ COPY ./script/config-cri-o/ /
|
||||||
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
|
ENTRYPOINT [ "/usr/local/bin/entrypoint" ]
|
||||||
|
|
||||||
# Image which can be used as a node image for KinD
|
# Image which can be used as a node image for KinD
|
||||||
FROM kindest/node:v1.33.1
|
FROM kindest/node:v1.33.2
|
||||||
COPY --from=containerd-dev /out/bin/containerd /out/bin/containerd-shim-runc-v2 /usr/local/bin/
|
COPY --from=containerd-dev /out/bin/containerd /out/bin/containerd-shim-runc-v2 /usr/local/bin/
|
||||||
COPY --from=snapshotter-dev /out/* /usr/local/bin/
|
COPY --from=snapshotter-dev /out/* /usr/local/bin/
|
||||||
COPY ./script/config/ /
|
COPY ./script/config/ /
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/containerd/stargz-snapshotter/util/cacheutil"
|
"github.com/containerd/stargz-snapshotter/util/cacheutil"
|
||||||
"github.com/containerd/stargz-snapshotter/util/namedmutex"
|
"github.com/containerd/stargz-snapshotter/util/namedmutex"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -61,6 +62,9 @@ type DirectoryCacheConfig struct {
|
||||||
// Direct forcefully enables direct mode for all operation in cache.
|
// Direct forcefully enables direct mode for all operation in cache.
|
||||||
// Thus operation won't use on-memory caches.
|
// Thus operation won't use on-memory caches.
|
||||||
Direct bool
|
Direct bool
|
||||||
|
|
||||||
|
// FadvDontNeed forcefully clean fscache pagecache for saving memory.
|
||||||
|
FadvDontNeed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: contents validation.
|
// TODO: contents validation.
|
||||||
|
@ -173,6 +177,7 @@ func NewDirectoryCache(directory string, config DirectoryCacheConfig) (BlobCache
|
||||||
wipDirectory: wipdir,
|
wipDirectory: wipdir,
|
||||||
bufPool: bufPool,
|
bufPool: bufPool,
|
||||||
direct: config.Direct,
|
direct: config.Direct,
|
||||||
|
fadvDontNeed: config.FadvDontNeed,
|
||||||
}
|
}
|
||||||
dc.syncAdd = config.SyncAdd
|
dc.syncAdd = config.SyncAdd
|
||||||
return dc, nil
|
return dc, nil
|
||||||
|
@ -188,8 +193,9 @@ type directoryCache struct {
|
||||||
|
|
||||||
bufPool *sync.Pool
|
bufPool *sync.Pool
|
||||||
|
|
||||||
syncAdd bool
|
syncAdd bool
|
||||||
direct bool
|
direct bool
|
||||||
|
fadvDontNeed bool
|
||||||
|
|
||||||
closed bool
|
closed bool
|
||||||
closedMu sync.Mutex
|
closedMu sync.Mutex
|
||||||
|
@ -244,6 +250,12 @@ func (dc *directoryCache) Get(key string, opts ...Option) (Reader, error) {
|
||||||
return &reader{
|
return &reader{
|
||||||
ReaderAt: file,
|
ReaderAt: file,
|
||||||
closeFunc: func() error {
|
closeFunc: func() error {
|
||||||
|
if dc.fadvDontNeed {
|
||||||
|
if err := dropFilePageCache(file); err != nil {
|
||||||
|
fmt.Printf("Warning: failed to drop page cache: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// In passthough model, close will be toke over by go-fuse
|
// In passthough model, close will be toke over by go-fuse
|
||||||
// If "passThrough" option is specified, "direct" option also will
|
// If "passThrough" option is specified, "direct" option also will
|
||||||
// be specified, so adding this branch here is enough
|
// be specified, so adding this branch here is enough
|
||||||
|
@ -301,6 +313,13 @@ func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) {
|
||||||
errs = append(errs, fmt.Errorf("failed to create cache directory %q: %w", c, err))
|
errs = append(errs, fmt.Errorf("failed to create cache directory %q: %w", c, err))
|
||||||
return errors.Join(errs...)
|
return errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dc.fadvDontNeed {
|
||||||
|
if err := dropFilePageCache(wip); err != nil {
|
||||||
|
fmt.Printf("Warning: failed to drop page cache: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return os.Rename(wip.Name(), c)
|
return os.Rename(wip.Name(), c)
|
||||||
},
|
},
|
||||||
abortFunc: func() error {
|
abortFunc: func() error {
|
||||||
|
@ -463,3 +482,16 @@ func (w *writeCloser) Close() error { return w.closeFunc() }
|
||||||
func nopWriteCloser(w io.Writer) io.WriteCloser {
|
func nopWriteCloser(w io.Writer) io.WriteCloser {
|
||||||
return &writeCloser{w, func() error { return nil }}
|
return &writeCloser{w, func() error { return nil }}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dropFilePageCache(file *os.File) error {
|
||||||
|
if file == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fd := file.Fd()
|
||||||
|
err := unix.Fadvise(int(fd), 0, 0, unix.FADV_DONTNEED)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("posix_fadvise failed, ret=%d", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -29,15 +29,60 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReader(t *testing.T) {
|
func TestReader(t *testing.T) {
|
||||||
testutil.TestReader(t, newTestableReader)
|
testRunner := &testutil.TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT testutil.TestingT, name string, run func(t testutil.TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testutil.TestReader(testRunner, newTestableReader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFSReader(t *testing.T) {
|
func TestFSReader(t *testing.T) {
|
||||||
fsreader.TestSuiteReader(t, newStore)
|
testRunner := &fsreader.TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT fsreader.TestingT, name string, run func(t fsreader.TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fsreader.TestSuiteReader(testRunner, newStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFSLayer(t *testing.T) {
|
func TestFSLayer(t *testing.T) {
|
||||||
layer.TestSuiteLayer(t, newStore)
|
testRunner := &layer.TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT layer.TestingT, name string, run func(t layer.TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
layer.TestSuiteLayer(testRunner, newStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestableReader(sr *io.SectionReader, opts ...metadata.Option) (testutil.TestableReader, error) {
|
func newTestableReader(sr *io.SectionReader, opts ...metadata.Option) (testutil.TestableReader, error) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
containerd "github.com/containerd/containerd/v2/client"
|
containerd "github.com/containerd/containerd/v2/client"
|
||||||
|
@ -45,6 +46,24 @@ import (
|
||||||
|
|
||||||
const netnsMountDir = "/var/run/netns"
|
const netnsMountDir = "/var/run/netns"
|
||||||
|
|
||||||
|
func parseGPUs(gpuStr string) ([]int, bool) {
|
||||||
|
if gpuStr == "" {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if gpuStr == "all" {
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
parts := strings.Split(gpuStr, ",")
|
||||||
|
var devices []int
|
||||||
|
for _, part := range parts {
|
||||||
|
part = strings.TrimSpace(part)
|
||||||
|
if device, err := strconv.Atoi(part); err == nil {
|
||||||
|
devices = append(devices, device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return devices, false
|
||||||
|
}
|
||||||
|
|
||||||
var samplerFlags = []cli.Flag{
|
var samplerFlags = []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "terminal,t",
|
Name: "terminal,t",
|
||||||
|
@ -116,9 +135,9 @@ var samplerFlags = []cli.Flag{
|
||||||
Name: "cni-plugin-dir",
|
Name: "cni-plugin-dir",
|
||||||
Usage: "path to the CNI plugins binary directory",
|
Usage: "path to the CNI plugins binary directory",
|
||||||
},
|
},
|
||||||
&cli.IntSliceFlag{
|
&cli.StringFlag{
|
||||||
Name: "gpus",
|
Name: "gpus",
|
||||||
Usage: "add gpus to the container",
|
Usage: "add gpus to the container (comma-separated list of indices or 'all')",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "net-host",
|
Name: "net-host",
|
||||||
|
@ -213,7 +232,12 @@ func getSpecOpts(clicontext *cli.Context) func(image containerd.Image, rootfs st
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
log.L.Warn("option --gpus is not supported on Windows")
|
log.L.Warn("option --gpus is not supported on Windows")
|
||||||
} else {
|
} else {
|
||||||
opts = append(opts, nvidia.WithGPUs(nvidia.WithDevices(clicontext.IntSlice("gpus")...), nvidia.WithAllCapabilities))
|
devices, useAll := parseGPUs(clicontext.String("gpus"))
|
||||||
|
if useAll {
|
||||||
|
opts = append(opts, nvidia.WithGPUs(nvidia.WithAllCapabilities))
|
||||||
|
} else if len(devices) > 0 {
|
||||||
|
opts = append(opts, nvidia.WithGPUs(nvidia.WithDevices(devices...), nvidia.WithAllCapabilities))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
38
cmd/go.mod
38
cmd/go.mod
|
@ -6,8 +6,8 @@ toolchain go1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/containerd/containerd/api v1.9.0
|
github.com/containerd/containerd/api v1.9.0
|
||||||
github.com/containerd/containerd/v2 v2.1.3
|
github.com/containerd/containerd/v2 v2.1.4
|
||||||
github.com/containerd/go-cni v1.1.12
|
github.com/containerd/go-cni v1.1.13
|
||||||
github.com/containerd/log v0.1.0
|
github.com/containerd/log v0.1.0
|
||||||
github.com/containerd/platforms v1.0.0-rc.1
|
github.com/containerd/platforms v1.0.0-rc.1
|
||||||
github.com/containerd/stargz-snapshotter v0.15.2-0.20240622031358-6405f362966d
|
github.com/containerd/stargz-snapshotter v0.15.2-0.20240622031358-6405f362966d
|
||||||
|
@ -26,7 +26,7 @@ require (
|
||||||
go.etcd.io/bbolt v1.4.2
|
go.etcd.io/bbolt v1.4.2
|
||||||
golang.org/x/sync v0.16.0
|
golang.org/x/sync v0.16.0
|
||||||
golang.org/x/sys v0.34.0
|
golang.org/x/sys v0.34.0
|
||||||
google.golang.org/grpc v1.73.0
|
google.golang.org/grpc v1.74.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -50,14 +50,14 @@ require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/distribution/reference v0.6.0 // indirect
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/docker/cli v28.3.2+incompatible // indirect
|
github.com/docker/cli v28.3.3+incompatible // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // 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/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||||
|
@ -93,7 +93,7 @@ require (
|
||||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||||
github.com/multiformats/go-multiaddr v0.16.0 // indirect
|
github.com/multiformats/go-multiaddr v0.16.1 // indirect
|
||||||
github.com/multiformats/go-multibase v0.2.0 // indirect
|
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||||
|
@ -103,10 +103,10 @@ require (
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
github.com/prometheus/client_golang v1.23.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.62.0 // indirect
|
github.com/prometheus/common v0.65.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
@ -119,18 +119,18 @@ require (
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.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 v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.38.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
golang.org/x/mod v0.24.0 // indirect
|
||||||
golang.org/x/net v0.38.0 // indirect
|
golang.org/x/net v0.40.0 // indirect
|
||||||
golang.org/x/oauth2 v0.28.0 // indirect
|
golang.org/x/oauth2 v0.30.0 // indirect
|
||||||
golang.org/x/term v0.30.0 // indirect
|
golang.org/x/term v0.32.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/time v0.9.0 // indirect
|
golang.org/x/time v0.9.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
|
84
cmd/go.sum
84
cmd/go.sum
|
@ -27,8 +27,8 @@ github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/q
|
||||||
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
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 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
|
||||||
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
|
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.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
|
||||||
github.com/containerd/containerd/v2 v2.1.3/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
||||||
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
||||||
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
@ -37,8 +37,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
|
||||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||||
github.com/containerd/go-cni v1.1.12 h1:wm/5VD/i255hjM4uIZjBRiEQ7y98W9ACy/mHeLi4+94=
|
github.com/containerd/go-cni v1.1.13 h1:eFSGOKlhoYNxpJ51KRIMHZNlg5UgocXEIEBGkY7Hnis=
|
||||||
github.com/containerd/go-cni v1.1.12/go.mod h1:+jaqRBdtW5faJxj2Qwg1Of7GsV66xcvnCx4mSJtUlxU=
|
github.com/containerd/go-cni v1.1.13/go.mod h1:nTieub0XDRmvCZ9VI/SBG6PyqT95N4FIhxsauF1vSBI=
|
||||||
github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA=
|
github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA=
|
||||||
github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U=
|
github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U=
|
||||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
|
@ -66,8 +66,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/docker/cli v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS3hP2huFsY=
|
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
|
||||||
github.com/docker/cli v28.3.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||||
|
@ -92,8 +92,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.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.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
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 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||||
|
@ -248,8 +248,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg
|
||||||
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
|
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
|
||||||
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||||
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||||
github.com/multiformats/go-multiaddr v0.16.0 h1:oGWEVKioVQcdIOBlYM8BH1rZDWOGJSqr9/BKl6zQ4qc=
|
github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw=
|
||||||
github.com/multiformats/go-multiaddr v0.16.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
||||||
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
|
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
|
||||||
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||||
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||||
|
@ -293,22 +293,22 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
||||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
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.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
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.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
|
@ -369,16 +369,16 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
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/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.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
@ -389,8 +389,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||||
|
@ -413,11 +413,11 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
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-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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -444,12 +444,12 @@ golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -471,15 +471,15 @@ 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-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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
|
|
@ -74,10 +74,11 @@ You can enable host networking for the container using the `net-host` flag.
|
||||||
# ctr-remote i optimize -t -i --oci --entrypoint='[ "/bin/bash", "-c" ]' --net-host --args='[ "ip a && curl example.com" ]' ghcr.io/stargz-containers/centos:8-test registry2:5000/centos:8-test-esgz
|
# ctr-remote i optimize -t -i --oci --entrypoint='[ "/bin/bash", "-c" ]' --net-host --args='[ "ip a && curl example.com" ]' ghcr.io/stargz-containers/centos:8-test registry2:5000/centos:8-test-esgz
|
||||||
```
|
```
|
||||||
|
|
||||||
You can optimize GPU-based images using the `gpu` flag. The flag expects a comma separated list of integers.
|
You can optimize GPU-based images using the `gpu` flag. The flag expects a comma separated list of integers or 'all'.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
# ctr-remote i optimize --oci --gpus "0" <src> <target>
|
# ctr-remote i optimize --oci --gpus "0" <src> <target>
|
||||||
|
# ctr-remote i optimize --oci --gpus "all" <src> <target>
|
||||||
```
|
```
|
||||||
|
|
||||||
`--oci` option is highly recommended to add when you create eStargz image.
|
`--oci` option is highly recommended to add when you create eStargz image.
|
||||||
|
|
|
@ -144,6 +144,14 @@ When stopping FUSE manager for upgrading the binary or restarting the node, you
|
||||||
4. Restart the containerd-stargz-grpc process. This restores all snapshot mounts by lazy pulling them. `allow_invalid_mounts_on_restart` (described in the above) can still be used for controlling the behaviour of the error cases.
|
4. Restart the containerd-stargz-grpc process. This restores all snapshot mounts by lazy pulling them. `allow_invalid_mounts_on_restart` (described in the above) can still be used for controlling the behaviour of the error cases.
|
||||||
5. Restart the containers.
|
5. Restart the containers.
|
||||||
|
|
||||||
|
### Unexpected restart handling
|
||||||
|
|
||||||
|
When Stargz Snapshotter is killed unexpectedly (e.g., by OOM killer or system crash), the process doesn't get a chance to perform graceful cleanup. In such cases, the snapshotter can successfully restart and restore remote snapshots, but this may lead to fscache duplicating cached data.
|
||||||
|
|
||||||
|
**Recommended handling:**
|
||||||
|
|
||||||
|
Since this scenario is caused by abnormal exit, users are expected to manually clean up the cache directory after an unexpected restart to avoid cache duplication issues. The cache cleanup should be performed before restarting the snapshotter service.
|
||||||
|
|
||||||
## Registry-related configuration
|
## Registry-related configuration
|
||||||
|
|
||||||
You can configure stargz snapshotter for accessing registries with custom configurations.
|
You can configure stargz snapshotter for accessing registries with custom configurations.
|
||||||
|
|
|
@ -27,7 +27,22 @@ import (
|
||||||
|
|
||||||
// TestGzipEStargz tests gzip-based external TOC eStargz
|
// TestGzipEStargz tests gzip-based external TOC eStargz
|
||||||
func TestGzipEStargz(t *testing.T) {
|
func TestGzipEStargz(t *testing.T) {
|
||||||
estargz.CompressionTestSuite(t,
|
testRunner := &estargz.TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT estargz.TestingT, name string, run func(t estargz.TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
estargz.CompressionTestSuite(testRunner,
|
||||||
gzipControllerWithLevel(gzip.NoCompression),
|
gzipControllerWithLevel(gzip.NoCompression),
|
||||||
gzipControllerWithLevel(gzip.BestSpeed),
|
gzipControllerWithLevel(gzip.BestSpeed),
|
||||||
gzipControllerWithLevel(gzip.BestCompression),
|
gzipControllerWithLevel(gzip.BestCompression),
|
||||||
|
@ -60,11 +75,11 @@ func (gc *gzipController) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestStream tests the passed estargz blob contains the specified list of streams.
|
// TestStream tests the passed estargz blob contains the specified list of streams.
|
||||||
func (gc *gzipController) TestStreams(t *testing.T, b []byte, streams []int64) {
|
func (gc *gzipController) TestStreams(t estargz.TestingT, b []byte, streams []int64) {
|
||||||
estargz.CheckGzipHasStreams(t, b, streams)
|
estargz.CheckGzipHasStreams(t, b, streams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *gzipController) DiffIDOf(t *testing.T, b []byte) string {
|
func (gc *gzipController) DiffIDOf(t estargz.TestingT, b []byte) string {
|
||||||
return estargz.GzipDiffIDOf(t, b)
|
return estargz.GzipDiffIDOf(t, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,22 @@ import (
|
||||||
|
|
||||||
// TestGzipEStargz tests gzip-based eStargz
|
// TestGzipEStargz tests gzip-based eStargz
|
||||||
func TestGzipEStargz(t *testing.T) {
|
func TestGzipEStargz(t *testing.T) {
|
||||||
CompressionTestSuite(t,
|
testRunner := &TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT TestingT, name string, run func(t TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
CompressionTestSuite(testRunner,
|
||||||
gzipControllerWithLevel(gzip.NoCompression),
|
gzipControllerWithLevel(gzip.NoCompression),
|
||||||
gzipControllerWithLevel(gzip.BestSpeed),
|
gzipControllerWithLevel(gzip.BestSpeed),
|
||||||
gzipControllerWithLevel(gzip.BestCompression),
|
gzipControllerWithLevel(gzip.BestCompression),
|
||||||
|
@ -56,11 +71,11 @@ func (gc *gzipController) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestStream tests the passed estargz blob contains the specified list of streams.
|
// TestStream tests the passed estargz blob contains the specified list of streams.
|
||||||
func (gc *gzipController) TestStreams(t *testing.T, b []byte, streams []int64) {
|
func (gc *gzipController) TestStreams(t TestingT, b []byte, streams []int64) {
|
||||||
CheckGzipHasStreams(t, b, streams)
|
CheckGzipHasStreams(t, b, streams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *gzipController) DiffIDOf(t *testing.T, b []byte) string {
|
func (gc *gzipController) DiffIDOf(t TestingT, b []byte) string {
|
||||||
return GzipDiffIDOf(t, b)
|
return GzipDiffIDOf(t, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/stargz-snapshotter/estargz/errorutil"
|
"github.com/containerd/stargz-snapshotter/estargz/errorutil"
|
||||||
|
@ -49,16 +48,48 @@ import (
|
||||||
// TestingController is Compression with some helper methods necessary for testing.
|
// TestingController is Compression with some helper methods necessary for testing.
|
||||||
type TestingController interface {
|
type TestingController interface {
|
||||||
Compression
|
Compression
|
||||||
TestStreams(t *testing.T, b []byte, streams []int64)
|
TestStreams(t TestingT, b []byte, streams []int64)
|
||||||
DiffIDOf(*testing.T, []byte) string
|
DiffIDOf(TestingT, []byte) string
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestingT is the minimal set of testing.T required to run the
|
||||||
|
// tests defined in CompressionTestSuite. This interface exists to prevent
|
||||||
|
// leaking the testing package from being exposed outside tests.
|
||||||
|
type TestingT interface {
|
||||||
|
Errorf(format string, args ...any)
|
||||||
|
FailNow()
|
||||||
|
Failed() bool
|
||||||
|
Fatal(args ...any)
|
||||||
|
Fatalf(format string, args ...any)
|
||||||
|
Logf(format string, args ...any)
|
||||||
|
Parallel()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runner allows running subtests of TestingT. This exists instead of adding
|
||||||
|
// a Run method to TestingT interface because the Run implementation of
|
||||||
|
// testing.T would not satisfy the interface.
|
||||||
|
type Runner func(t TestingT, name string, fn func(t TestingT))
|
||||||
|
|
||||||
|
type TestRunner struct {
|
||||||
|
TestingT
|
||||||
|
Runner Runner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TestRunner) Run(name string, run func(*TestRunner)) {
|
||||||
|
r.Runner(r.TestingT, name, func(t TestingT) {
|
||||||
|
run(&TestRunner{TestingT: t, Runner: r.Runner})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// CompressionTestSuite tests this pkg with controllers can build valid eStargz blobs and parse them.
|
// CompressionTestSuite tests this pkg with controllers can build valid eStargz blobs and parse them.
|
||||||
func CompressionTestSuite(t *testing.T, controllers ...TestingControllerFactory) {
|
func CompressionTestSuite(t *TestRunner, controllers ...TestingControllerFactory) {
|
||||||
t.Run("testBuild", func(t *testing.T) { t.Parallel(); testBuild(t, controllers...) })
|
t.Run("testBuild", func(t *TestRunner) { t.Parallel(); testBuild(t, controllers...) })
|
||||||
t.Run("testDigestAndVerify", func(t *testing.T) { t.Parallel(); testDigestAndVerify(t, controllers...) })
|
t.Run("testDigestAndVerify", func(t *TestRunner) {
|
||||||
t.Run("testWriteAndOpen", func(t *testing.T) { t.Parallel(); testWriteAndOpen(t, controllers...) })
|
t.Parallel()
|
||||||
|
testDigestAndVerify(t, controllers...)
|
||||||
|
})
|
||||||
|
t.Run("testWriteAndOpen", func(t *TestRunner) { t.Parallel(); testWriteAndOpen(t, controllers...) })
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestingControllerFactory func() TestingController
|
type TestingControllerFactory func() TestingController
|
||||||
|
@ -79,7 +110,7 @@ var allowedPrefix = [4]string{"", "./", "/", "../"}
|
||||||
|
|
||||||
// testBuild tests the resulting stargz blob built by this pkg has the same
|
// testBuild tests the resulting stargz blob built by this pkg has the same
|
||||||
// contents as the normal stargz blob.
|
// contents as the normal stargz blob.
|
||||||
func testBuild(t *testing.T, controllers ...TestingControllerFactory) {
|
func testBuild(t *TestRunner, controllers ...TestingControllerFactory) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
chunkSize int
|
chunkSize int
|
||||||
|
@ -165,7 +196,7 @@ func testBuild(t *testing.T, controllers ...TestingControllerFactory) {
|
||||||
prefix := prefix
|
prefix := prefix
|
||||||
for _, minChunkSize := range tt.minChunkSize {
|
for _, minChunkSize := range tt.minChunkSize {
|
||||||
minChunkSize := minChunkSize
|
minChunkSize := minChunkSize
|
||||||
t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,src=%d,format=%s,minChunkSize=%d", newCL(), prefix, srcCompression, srcTarFormat, minChunkSize), func(t *testing.T) {
|
t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,src=%d,format=%s,minChunkSize=%d", newCL(), prefix, srcCompression, srcTarFormat, minChunkSize), func(t *TestRunner) {
|
||||||
tarBlob := buildTar(t, tt.in, prefix, srcTarFormat)
|
tarBlob := buildTar(t, tt.in, prefix, srcTarFormat)
|
||||||
// Test divideEntries()
|
// Test divideEntries()
|
||||||
entries, err := sortEntries(tarBlob, nil, nil) // identical order
|
entries, err := sortEntries(tarBlob, nil, nil) // identical order
|
||||||
|
@ -265,7 +296,7 @@ func testBuild(t *testing.T, controllers ...TestingControllerFactory) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSameTarGz(t *testing.T, cla TestingController, a []byte, clb TestingController, b []byte) bool {
|
func isSameTarGz(t TestingT, cla TestingController, a []byte, clb TestingController, b []byte) bool {
|
||||||
aGz, err := cla.Reader(bytes.NewReader(a))
|
aGz, err := cla.Reader(bytes.NewReader(a))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to read A")
|
t.Fatalf("failed to read A")
|
||||||
|
@ -325,7 +356,7 @@ func isSameTarGz(t *testing.T, cla TestingController, a []byte, clb TestingContr
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSameVersion(t *testing.T, cla TestingController, a []byte, clb TestingController, b []byte) bool {
|
func isSameVersion(t TestingT, cla TestingController, a []byte, clb TestingController, b []byte) bool {
|
||||||
aJTOC, _, err := parseStargz(io.NewSectionReader(bytes.NewReader(a), 0, int64(len(a))), cla)
|
aJTOC, _, err := parseStargz(io.NewSectionReader(bytes.NewReader(a), 0, int64(len(a))), cla)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to parse A: %v", err)
|
t.Fatalf("failed to parse A: %v", err)
|
||||||
|
@ -339,7 +370,7 @@ func isSameVersion(t *testing.T, cla TestingController, a []byte, clb TestingCon
|
||||||
return aJTOC.Version == bJTOC.Version
|
return aJTOC.Version == bJTOC.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSameEntries(t *testing.T, a, b *Reader) bool {
|
func isSameEntries(t TestingT, a, b *Reader) bool {
|
||||||
aroot, ok := a.Lookup("")
|
aroot, ok := a.Lookup("")
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("failed to get root of A")
|
t.Fatalf("failed to get root of A")
|
||||||
|
@ -353,7 +384,7 @@ func isSameEntries(t *testing.T, a, b *Reader) bool {
|
||||||
return contains(t, aEntry, bEntry) && contains(t, bEntry, aEntry)
|
return contains(t, aEntry, bEntry) && contains(t, bEntry, aEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compressBlob(t *testing.T, src *io.SectionReader, srcCompression int) *io.SectionReader {
|
func compressBlob(t TestingT, src *io.SectionReader, srcCompression int) *io.SectionReader {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
var w io.WriteCloser
|
var w io.WriteCloser
|
||||||
var err error
|
var err error
|
||||||
|
@ -387,7 +418,7 @@ type stargzEntry struct {
|
||||||
|
|
||||||
// contains checks if all child entries in "b" are also contained in "a".
|
// contains checks if all child entries in "b" are also contained in "a".
|
||||||
// This function also checks if the files/chunks contain the same contents among "a" and "b".
|
// This function also checks if the files/chunks contain the same contents among "a" and "b".
|
||||||
func contains(t *testing.T, a, b stargzEntry) bool {
|
func contains(t TestingT, a, b stargzEntry) bool {
|
||||||
ae, ar := a.e, a.r
|
ae, ar := a.e, a.r
|
||||||
be, br := b.e, b.r
|
be, br := b.e, b.r
|
||||||
t.Logf("Comparing: %q vs %q", ae.Name, be.Name)
|
t.Logf("Comparing: %q vs %q", ae.Name, be.Name)
|
||||||
|
@ -498,7 +529,7 @@ func equalEntry(a, b *TOCEntry) bool {
|
||||||
a.Digest == b.Digest
|
a.Digest == b.Digest
|
||||||
}
|
}
|
||||||
|
|
||||||
func readOffset(t *testing.T, r *io.SectionReader, offset int64, e stargzEntry) ([]byte, int64, bool) {
|
func readOffset(t TestingT, r *io.SectionReader, offset int64, e stargzEntry) ([]byte, int64, bool) {
|
||||||
ce, ok := e.r.ChunkEntryForOffset(e.e.Name, offset)
|
ce, ok := e.r.ChunkEntryForOffset(e.e.Name, offset)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
|
@ -517,7 +548,7 @@ func readOffset(t *testing.T, r *io.SectionReader, offset int64, e stargzEntry)
|
||||||
return data[:n], offset + ce.ChunkSize, true
|
return data[:n], offset + ce.ChunkSize, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpTOCJSON(t *testing.T, tocJSON *JTOC) string {
|
func dumpTOCJSON(t TestingT, tocJSON *JTOC) string {
|
||||||
jtocData, err := json.Marshal(*tocJSON)
|
jtocData, err := json.Marshal(*tocJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to marshal TOC JSON: %v", err)
|
t.Fatalf("failed to marshal TOC JSON: %v", err)
|
||||||
|
@ -531,20 +562,19 @@ func dumpTOCJSON(t *testing.T, tocJSON *JTOC) string {
|
||||||
|
|
||||||
const chunkSize = 3
|
const chunkSize = 3
|
||||||
|
|
||||||
// type check func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, compressionLevel int)
|
type check func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory)
|
||||||
type check func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory)
|
|
||||||
|
|
||||||
// testDigestAndVerify runs specified checks against sample stargz blobs.
|
// testDigestAndVerify runs specified checks against sample stargz blobs.
|
||||||
func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory) {
|
func testDigestAndVerify(t *TestRunner, controllers ...TestingControllerFactory) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
tarInit func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry)
|
tarInit func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry)
|
||||||
checks []check
|
checks []check
|
||||||
minChunkSize []int
|
minChunkSize []int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no-regfile",
|
name: "no-regfile",
|
||||||
tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
||||||
return tarOf(
|
return tarOf(
|
||||||
dir("test/"),
|
dir("test/"),
|
||||||
)
|
)
|
||||||
|
@ -559,7 +589,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "small-files",
|
name: "small-files",
|
||||||
tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
||||||
return tarOf(
|
return tarOf(
|
||||||
regDigest(t, "baz.txt", "", dgstMap),
|
regDigest(t, "baz.txt", "", dgstMap),
|
||||||
regDigest(t, "foo.txt", "a", dgstMap),
|
regDigest(t, "foo.txt", "a", dgstMap),
|
||||||
|
@ -583,7 +613,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "big-files",
|
name: "big-files",
|
||||||
tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
||||||
return tarOf(
|
return tarOf(
|
||||||
regDigest(t, "baz.txt", "bazbazbazbazbazbazbaz", dgstMap),
|
regDigest(t, "baz.txt", "bazbazbazbazbazbazbaz", dgstMap),
|
||||||
regDigest(t, "foo.txt", "a", dgstMap),
|
regDigest(t, "foo.txt", "a", dgstMap),
|
||||||
|
@ -607,7 +637,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory)
|
||||||
{
|
{
|
||||||
name: "with-non-regfiles",
|
name: "with-non-regfiles",
|
||||||
minChunkSize: []int{0, 64000},
|
minChunkSize: []int{0, 64000},
|
||||||
tarInit: func(t *testing.T, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
tarInit: func(t TestingT, dgstMap map[string]digest.Digest) (blob []tarEntry) {
|
||||||
return tarOf(
|
return tarOf(
|
||||||
regDigest(t, "baz.txt", "bazbazbazbazbazbazbaz", dgstMap),
|
regDigest(t, "baz.txt", "bazbazbazbazbazbazbaz", dgstMap),
|
||||||
regDigest(t, "foo.txt", "a", dgstMap),
|
regDigest(t, "foo.txt", "a", dgstMap),
|
||||||
|
@ -654,7 +684,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory)
|
||||||
srcTarFormat := srcTarFormat
|
srcTarFormat := srcTarFormat
|
||||||
for _, minChunkSize := range tt.minChunkSize {
|
for _, minChunkSize := range tt.minChunkSize {
|
||||||
minChunkSize := minChunkSize
|
minChunkSize := minChunkSize
|
||||||
t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,format=%s,minChunkSize=%d", newCL(), prefix, srcTarFormat, minChunkSize), func(t *testing.T) {
|
t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,format=%s,minChunkSize=%d", newCL(), prefix, srcTarFormat, minChunkSize), func(t *TestRunner) {
|
||||||
// Get original tar file and chunk digests
|
// Get original tar file and chunk digests
|
||||||
dgstMap := make(map[string]digest.Digest)
|
dgstMap := make(map[string]digest.Digest)
|
||||||
tarBlob := buildTar(t, tt.tarInit(t, dgstMap), prefix, srcTarFormat)
|
tarBlob := buildTar(t, tt.tarInit(t, dgstMap), prefix, srcTarFormat)
|
||||||
|
@ -690,7 +720,7 @@ func testDigestAndVerify(t *testing.T, controllers ...TestingControllerFactory)
|
||||||
// checkStargzTOC checks the TOC JSON of the passed stargz has the expected
|
// checkStargzTOC checks the TOC JSON of the passed stargz has the expected
|
||||||
// digest and contains valid chunks. It walks all entries in the stargz and
|
// digest and contains valid chunks. It walks all entries in the stargz and
|
||||||
// checks all chunk digests stored to the TOC JSON match the actual contents.
|
// checks all chunk digests stored to the TOC JSON match the actual contents.
|
||||||
func checkStargzTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
func checkStargzTOC(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
||||||
sgz, err := Open(
|
sgz, err := Open(
|
||||||
io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))),
|
io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))),
|
||||||
WithDecompressors(controller),
|
WithDecompressors(controller),
|
||||||
|
@ -801,7 +831,7 @@ func checkStargzTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstM
|
||||||
// checkVerifyTOC checks the verification works for the TOC JSON of the passed
|
// checkVerifyTOC checks the verification works for the TOC JSON of the passed
|
||||||
// stargz. It walks all entries in the stargz and checks the verifications for
|
// stargz. It walks all entries in the stargz and checks the verifications for
|
||||||
// all chunks work.
|
// all chunks work.
|
||||||
func checkVerifyTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
func checkVerifyTOC(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
||||||
sgz, err := Open(
|
sgz, err := Open(
|
||||||
io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))),
|
io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))),
|
||||||
WithDecompressors(controller),
|
WithDecompressors(controller),
|
||||||
|
@ -882,9 +912,9 @@ func checkVerifyTOC(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstM
|
||||||
// checkVerifyInvalidTOCEntryFail checks if misconfigured TOC JSON can be
|
// checkVerifyInvalidTOCEntryFail checks if misconfigured TOC JSON can be
|
||||||
// detected during the verification and the verification returns an error.
|
// detected during the verification and the verification returns an error.
|
||||||
func checkVerifyInvalidTOCEntryFail(filename string) check {
|
func checkVerifyInvalidTOCEntryFail(filename string) check {
|
||||||
return func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
return func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
||||||
funcs := map[string]rewriteFunc{
|
funcs := map[string]rewriteFunc{
|
||||||
"lost digest in a entry": func(t *testing.T, toc *JTOC, sgz *io.SectionReader) {
|
"lost digest in a entry": func(t TestingT, toc *JTOC, sgz *io.SectionReader) {
|
||||||
var found bool
|
var found bool
|
||||||
for _, e := range toc.Entries {
|
for _, e := range toc.Entries {
|
||||||
if cleanEntryName(e.Name) == filename {
|
if cleanEntryName(e.Name) == filename {
|
||||||
|
@ -902,7 +932,7 @@ func checkVerifyInvalidTOCEntryFail(filename string) check {
|
||||||
t.Fatalf("rewrite target not found")
|
t.Fatalf("rewrite target not found")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"duplicated entry offset": func(t *testing.T, toc *JTOC, sgz *io.SectionReader) {
|
"duplicated entry offset": func(t TestingT, toc *JTOC, sgz *io.SectionReader) {
|
||||||
var (
|
var (
|
||||||
sampleEntry *TOCEntry
|
sampleEntry *TOCEntry
|
||||||
targetEntry *TOCEntry
|
targetEntry *TOCEntry
|
||||||
|
@ -929,7 +959,7 @@ func checkVerifyInvalidTOCEntryFail(filename string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, rFunc := range funcs {
|
for name, rFunc := range funcs {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *TestRunner) {
|
||||||
newSgz, newTocDigest := rewriteTOCJSON(t, io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))), rFunc, controller)
|
newSgz, newTocDigest := rewriteTOCJSON(t, io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))), rFunc, controller)
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
if _, err := io.Copy(buf, newSgz); err != nil {
|
if _, err := io.Copy(buf, newSgz); err != nil {
|
||||||
|
@ -958,7 +988,7 @@ func checkVerifyInvalidTOCEntryFail(filename string) check {
|
||||||
// checkVerifyInvalidStargzFail checks if the verification detects that the
|
// checkVerifyInvalidStargzFail checks if the verification detects that the
|
||||||
// given stargz file doesn't match to the expected digest and returns error.
|
// given stargz file doesn't match to the expected digest and returns error.
|
||||||
func checkVerifyInvalidStargzFail(invalid *io.SectionReader) check {
|
func checkVerifyInvalidStargzFail(invalid *io.SectionReader) check {
|
||||||
return func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
return func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
||||||
cl := newController()
|
cl := newController()
|
||||||
rc, err := Build(invalid, WithChunkSize(chunkSize), WithCompression(cl))
|
rc, err := Build(invalid, WithChunkSize(chunkSize), WithCompression(cl))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -990,7 +1020,7 @@ func checkVerifyInvalidStargzFail(invalid *io.SectionReader) check {
|
||||||
// checkVerifyBrokenContentFail checks if the verifier detects broken contents
|
// checkVerifyBrokenContentFail checks if the verifier detects broken contents
|
||||||
// that doesn't match to the expected digest and returns error.
|
// that doesn't match to the expected digest and returns error.
|
||||||
func checkVerifyBrokenContentFail(filename string) check {
|
func checkVerifyBrokenContentFail(filename string) check {
|
||||||
return func(t *testing.T, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
return func(t *TestRunner, sgzData []byte, tocDigest digest.Digest, dgstMap map[string]digest.Digest, controller TestingController, newController TestingControllerFactory) {
|
||||||
// Parse stargz file
|
// Parse stargz file
|
||||||
sgz, err := Open(
|
sgz, err := Open(
|
||||||
io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))),
|
io.NewSectionReader(bytes.NewReader(sgzData), 0, int64(len(sgzData))),
|
||||||
|
@ -1047,9 +1077,9 @@ func chunkID(name string, offset, size int64) string {
|
||||||
return fmt.Sprintf("%s-%d-%d", cleanEntryName(name), offset, size)
|
return fmt.Sprintf("%s-%d-%d", cleanEntryName(name), offset, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
type rewriteFunc func(t *testing.T, toc *JTOC, sgz *io.SectionReader)
|
type rewriteFunc func(t TestingT, toc *JTOC, sgz *io.SectionReader)
|
||||||
|
|
||||||
func rewriteTOCJSON(t *testing.T, sgz *io.SectionReader, rewrite rewriteFunc, controller TestingController) (newSgz io.Reader, tocDigest digest.Digest) {
|
func rewriteTOCJSON(t TestingT, sgz *io.SectionReader, rewrite rewriteFunc, controller TestingController) (newSgz io.Reader, tocDigest digest.Digest) {
|
||||||
decodedJTOC, jtocOffset, err := parseStargz(sgz, controller)
|
decodedJTOC, jtocOffset, err := parseStargz(sgz, controller)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to extract TOC JSON: %v", err)
|
t.Fatalf("failed to extract TOC JSON: %v", err)
|
||||||
|
@ -1120,7 +1150,7 @@ func parseStargz(sgz *io.SectionReader, controller TestingController) (decodedJT
|
||||||
return decodedJTOC, tocOffset, nil
|
return decodedJTOC, tocOffset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWriteAndOpen(t *testing.T, controllers ...TestingControllerFactory) {
|
func testWriteAndOpen(t *TestRunner, controllers ...TestingControllerFactory) {
|
||||||
const content = "Some contents"
|
const content = "Some contents"
|
||||||
invalidUtf8 := "\xff\xfe\xfd"
|
invalidUtf8 := "\xff\xfe\xfd"
|
||||||
|
|
||||||
|
@ -1464,7 +1494,7 @@ func testWriteAndOpen(t *testing.T, controllers ...TestingControllerFactory) {
|
||||||
for _, srcTarFormat := range []tar.Format{tar.FormatUSTAR, tar.FormatPAX, tar.FormatGNU} {
|
for _, srcTarFormat := range []tar.Format{tar.FormatUSTAR, tar.FormatPAX, tar.FormatGNU} {
|
||||||
srcTarFormat := srcTarFormat
|
srcTarFormat := srcTarFormat
|
||||||
for _, lossless := range []bool{true, false} {
|
for _, lossless := range []bool{true, false} {
|
||||||
t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,lossless=%v,format=%s", newCL(), prefix, lossless, srcTarFormat), func(t *testing.T) {
|
t.Run(tt.name+"-"+fmt.Sprintf("compression=%v,prefix=%q,lossless=%v,format=%s", newCL(), prefix, lossless, srcTarFormat), func(t *TestRunner) {
|
||||||
var tr io.Reader = buildTar(t, tt.in, prefix, srcTarFormat)
|
var tr io.Reader = buildTar(t, tt.in, prefix, srcTarFormat)
|
||||||
origTarDgstr := digest.Canonical.Digester()
|
origTarDgstr := digest.Canonical.Digester()
|
||||||
tr = io.TeeReader(tr, origTarDgstr.Hash())
|
tr = io.TeeReader(tr, origTarDgstr.Hash())
|
||||||
|
@ -1628,7 +1658,7 @@ func digestFor(content string) string {
|
||||||
|
|
||||||
type numTOCEntries int
|
type numTOCEntries int
|
||||||
|
|
||||||
func (n numTOCEntries) check(t *testing.T, r *Reader) {
|
func (n numTOCEntries) check(t TestingT, r *Reader) {
|
||||||
if r.toc == nil {
|
if r.toc == nil {
|
||||||
t.Fatal("nil TOC")
|
t.Fatal("nil TOC")
|
||||||
}
|
}
|
||||||
|
@ -1648,15 +1678,15 @@ func (n numTOCEntries) check(t *testing.T, r *Reader) {
|
||||||
func checks(s ...stargzCheck) []stargzCheck { return s }
|
func checks(s ...stargzCheck) []stargzCheck { return s }
|
||||||
|
|
||||||
type stargzCheck interface {
|
type stargzCheck interface {
|
||||||
check(t *testing.T, r *Reader)
|
check(t TestingT, r *Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
type stargzCheckFn func(*testing.T, *Reader)
|
type stargzCheckFn func(TestingT, *Reader)
|
||||||
|
|
||||||
func (f stargzCheckFn) check(t *testing.T, r *Reader) { f(t, r) }
|
func (f stargzCheckFn) check(t TestingT, r *Reader) { f(t, r) }
|
||||||
|
|
||||||
func maxDepth(max int) stargzCheck {
|
func maxDepth(max int) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
e, ok := r.Lookup("")
|
e, ok := r.Lookup("")
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("root directory not found")
|
t.Fatal("root directory not found")
|
||||||
|
@ -1673,7 +1703,7 @@ func maxDepth(max int) stargzCheck {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMaxDepth(t *testing.T, e *TOCEntry, current, limit int) (max int, rErr error) {
|
func getMaxDepth(t TestingT, e *TOCEntry, current, limit int) (max int, rErr error) {
|
||||||
if current > limit {
|
if current > limit {
|
||||||
return -1, fmt.Errorf("walkMaxDepth: exceeds limit: current:%d > limit:%d",
|
return -1, fmt.Errorf("walkMaxDepth: exceeds limit: current:%d > limit:%d",
|
||||||
current, limit)
|
current, limit)
|
||||||
|
@ -1695,7 +1725,7 @@ func getMaxDepth(t *testing.T, e *TOCEntry, current, limit int) (max int, rErr e
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileLen(file string, wantLen int) stargzCheck {
|
func hasFileLen(file string, wantLen int) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
for _, ent := range r.toc.Entries {
|
for _, ent := range r.toc.Entries {
|
||||||
if ent.Name == file {
|
if ent.Name == file {
|
||||||
if ent.Type != "reg" {
|
if ent.Type != "reg" {
|
||||||
|
@ -1711,7 +1741,7 @@ func hasFileLen(file string, wantLen int) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileXattrs(file, name, value string) stargzCheck {
|
func hasFileXattrs(file, name, value string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
for _, ent := range r.toc.Entries {
|
for _, ent := range r.toc.Entries {
|
||||||
if ent.Name == file {
|
if ent.Name == file {
|
||||||
if ent.Type != "reg" {
|
if ent.Type != "reg" {
|
||||||
|
@ -1738,7 +1768,7 @@ func hasFileXattrs(file, name, value string) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileDigest(file string, digest string) stargzCheck {
|
func hasFileDigest(file string, digest string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
ent, ok := r.Lookup(file)
|
ent, ok := r.Lookup(file)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("didn't find TOCEntry for file %q", file)
|
t.Fatalf("didn't find TOCEntry for file %q", file)
|
||||||
|
@ -1750,7 +1780,7 @@ func hasFileDigest(file string, digest string) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsWithPreRead(file string, offset int, want string, extra ...chunkInfo) stargzCheck {
|
func hasFileContentsWithPreRead(file string, offset int, want string, extra ...chunkInfo) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
extraMap := make(map[string]chunkInfo)
|
extraMap := make(map[string]chunkInfo)
|
||||||
for _, e := range extra {
|
for _, e := range extra {
|
||||||
extraMap[e.name] = e
|
extraMap[e.name] = e
|
||||||
|
@ -1797,7 +1827,7 @@ func hasFileContentsWithPreRead(file string, offset int, want string, extra ...c
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsRange(file string, offset int, want string) stargzCheck {
|
func hasFileContentsRange(file string, offset int, want string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
f, err := r.OpenFile(file)
|
f, err := r.OpenFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -1814,7 +1844,7 @@ func hasFileContentsRange(file string, offset int, want string) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasChunkEntries(file string, wantChunks int) stargzCheck {
|
func hasChunkEntries(file string, wantChunks int) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
ent, ok := r.Lookup(file)
|
ent, ok := r.Lookup(file)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("no file for %q", file)
|
t.Fatalf("no file for %q", file)
|
||||||
|
@ -1858,7 +1888,7 @@ func hasChunkEntries(file string, wantChunks int) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func entryHasChildren(dir string, want ...string) stargzCheck {
|
func entryHasChildren(dir string, want ...string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
want := append([]string(nil), want...)
|
want := append([]string(nil), want...)
|
||||||
var got []string
|
var got []string
|
||||||
ent, ok := r.Lookup(dir)
|
ent, ok := r.Lookup(dir)
|
||||||
|
@ -1877,7 +1907,7 @@ func entryHasChildren(dir string, want ...string) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasDir(file string) stargzCheck {
|
func hasDir(file string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
for _, ent := range r.toc.Entries {
|
for _, ent := range r.toc.Entries {
|
||||||
if ent.Name == cleanEntryName(file) {
|
if ent.Name == cleanEntryName(file) {
|
||||||
if ent.Type != "dir" {
|
if ent.Type != "dir" {
|
||||||
|
@ -1891,7 +1921,7 @@ func hasDir(file string) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasDirLinkCount(file string, count int) stargzCheck {
|
func hasDirLinkCount(file string, count int) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
for _, ent := range r.toc.Entries {
|
for _, ent := range r.toc.Entries {
|
||||||
if ent.Name == cleanEntryName(file) {
|
if ent.Name == cleanEntryName(file) {
|
||||||
if ent.Type != "dir" {
|
if ent.Type != "dir" {
|
||||||
|
@ -1909,7 +1939,7 @@ func hasDirLinkCount(file string, count int) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasMode(file string, mode os.FileMode) stargzCheck {
|
func hasMode(file string, mode os.FileMode) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
for _, ent := range r.toc.Entries {
|
for _, ent := range r.toc.Entries {
|
||||||
if ent.Name == cleanEntryName(file) {
|
if ent.Name == cleanEntryName(file) {
|
||||||
if ent.Stat().Mode() != mode {
|
if ent.Stat().Mode() != mode {
|
||||||
|
@ -1924,7 +1954,7 @@ func hasMode(file string, mode os.FileMode) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasSymlink(file, target string) stargzCheck {
|
func hasSymlink(file, target string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
for _, ent := range r.toc.Entries {
|
for _, ent := range r.toc.Entries {
|
||||||
if ent.Name == file {
|
if ent.Name == file {
|
||||||
if ent.Type != "symlink" {
|
if ent.Type != "symlink" {
|
||||||
|
@ -1940,7 +1970,7 @@ func hasSymlink(file, target string) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupMatch(name string, want *TOCEntry) stargzCheck {
|
func lookupMatch(name string, want *TOCEntry) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
e, ok := r.Lookup(name)
|
e, ok := r.Lookup(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("failed to Lookup entry %q", name)
|
t.Fatalf("failed to Lookup entry %q", name)
|
||||||
|
@ -1953,7 +1983,7 @@ func lookupMatch(name string, want *TOCEntry) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasEntryOwner(entry string, owner owner) stargzCheck {
|
func hasEntryOwner(entry string, owner owner) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
ent, ok := r.Lookup(strings.TrimSuffix(entry, "/"))
|
ent, ok := r.Lookup(strings.TrimSuffix(entry, "/"))
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("entry %q not found", entry)
|
t.Errorf("entry %q not found", entry)
|
||||||
|
@ -1967,7 +1997,7 @@ func hasEntryOwner(entry string, owner owner) stargzCheck {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustSameEntry(files ...string) stargzCheck {
|
func mustSameEntry(files ...string) stargzCheck {
|
||||||
return stargzCheckFn(func(t *testing.T, r *Reader) {
|
return stargzCheckFn(func(t TestingT, r *Reader) {
|
||||||
var first *TOCEntry
|
var first *TOCEntry
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if first == nil {
|
if first == nil {
|
||||||
|
@ -2039,7 +2069,7 @@ func (f tarEntryFunc) appendTar(tw *tar.Writer, prefix string, format tar.Format
|
||||||
return f(tw, prefix, format)
|
return f(tw, prefix, format)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTar(t *testing.T, ents []tarEntry, prefix string, opts ...interface{}) *io.SectionReader {
|
func buildTar(t TestingT, ents []tarEntry, prefix string, opts ...interface{}) *io.SectionReader {
|
||||||
format := tar.FormatUnknown
|
format := tar.FormatUnknown
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
switch v := opt.(type) {
|
switch v := opt.(type) {
|
||||||
|
@ -2248,7 +2278,7 @@ func noPrefetchLandmark() tarEntry {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func regDigest(t *testing.T, name string, contentStr string, digestMap map[string]digest.Digest) tarEntry {
|
func regDigest(t TestingT, name string, contentStr string, digestMap map[string]digest.Digest) tarEntry {
|
||||||
if digestMap == nil {
|
if digestMap == nil {
|
||||||
t.Fatalf("digest map mustn't be nil")
|
t.Fatalf("digest map mustn't be nil")
|
||||||
}
|
}
|
||||||
|
@ -2318,7 +2348,7 @@ func (f fileInfoOnlyMode) ModTime() time.Time { return time.Now() }
|
||||||
func (f fileInfoOnlyMode) IsDir() bool { return os.FileMode(f).IsDir() }
|
func (f fileInfoOnlyMode) IsDir() bool { return os.FileMode(f).IsDir() }
|
||||||
func (f fileInfoOnlyMode) Sys() interface{} { return nil }
|
func (f fileInfoOnlyMode) Sys() interface{} { return nil }
|
||||||
|
|
||||||
func CheckGzipHasStreams(t *testing.T, b []byte, streams []int64) {
|
func CheckGzipHasStreams(t TestingT, b []byte, streams []int64) {
|
||||||
if len(streams) == 0 {
|
if len(streams) == 0 {
|
||||||
return // nop
|
return // nop
|
||||||
}
|
}
|
||||||
|
@ -2356,7 +2386,7 @@ func CheckGzipHasStreams(t *testing.T, b []byte, streams []int64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GzipDiffIDOf(t *testing.T, b []byte) string {
|
func GzipDiffIDOf(t TestingT, b []byte) string {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
zr, err := gzip.NewReader(bytes.NewReader(b))
|
zr, err := gzip.NewReader(bytes.NewReader(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,7 +30,22 @@ import (
|
||||||
|
|
||||||
// TestZstdChunked tests zstd:chunked
|
// TestZstdChunked tests zstd:chunked
|
||||||
func TestZstdChunked(t *testing.T) {
|
func TestZstdChunked(t *testing.T) {
|
||||||
estargz.CompressionTestSuite(t,
|
testRunner := &estargz.TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT estargz.TestingT, name string, run func(t estargz.TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
estargz.CompressionTestSuite(testRunner,
|
||||||
zstdControllerWithLevel(zstd.SpeedFastest),
|
zstdControllerWithLevel(zstd.SpeedFastest),
|
||||||
zstdControllerWithLevel(zstd.SpeedDefault),
|
zstdControllerWithLevel(zstd.SpeedDefault),
|
||||||
zstdControllerWithLevel(zstd.SpeedBetterCompression),
|
zstdControllerWithLevel(zstd.SpeedBetterCompression),
|
||||||
|
@ -55,7 +70,7 @@ func (zc *zstdController) String() string {
|
||||||
|
|
||||||
// TestStream tests the passed zstdchunked blob contains the specified list of streams.
|
// TestStream tests the passed zstdchunked blob contains the specified list of streams.
|
||||||
// The last entry of streams must be the offset of footer (len(b) - footerSize).
|
// The last entry of streams must be the offset of footer (len(b) - footerSize).
|
||||||
func (zc *zstdController) TestStreams(t *testing.T, b []byte, streams []int64) {
|
func (zc *zstdController) TestStreams(t estargz.TestingT, b []byte, streams []int64) {
|
||||||
t.Logf("got zstd streams (compressed size: %d):", len(b))
|
t.Logf("got zstd streams (compressed size: %d):", len(b))
|
||||||
|
|
||||||
if len(streams) == 0 {
|
if len(streams) == 0 {
|
||||||
|
@ -122,7 +137,7 @@ func nextIndex(s1, sub []byte) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (zc *zstdController) DiffIDOf(t *testing.T, b []byte) string {
|
func (zc *zstdController) DiffIDOf(t estargz.TestingT, b []byte) string {
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
zr, err := zstd.NewReader(bytes.NewReader(b))
|
zr, err := zstd.NewReader(bytes.NewReader(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -139,6 +139,9 @@ type DirectoryCacheConfig struct {
|
||||||
|
|
||||||
// Direct disables on-memory data cache. Default is true for saving memory usage.
|
// Direct disables on-memory data cache. Default is true for saving memory usage.
|
||||||
Direct bool `toml:"direct" default:"true" json:"direct"`
|
Direct bool `toml:"direct" default:"true" json:"direct"`
|
||||||
|
|
||||||
|
// FadvDontNeed forcefully clean fscache pagecache for saving memory. Default is false.
|
||||||
|
FadvDontNeed bool `toml:"fadv_dontneed" json:"fadv_dontneed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuseConfig is configuration for FUSE fs.
|
// FuseConfig is configuration for FUSE fs.
|
||||||
|
|
|
@ -235,11 +235,12 @@ func newCache(root string, cacheType string, cfg config.Config) (cache.BlobCache
|
||||||
return cache.NewDirectoryCache(
|
return cache.NewDirectoryCache(
|
||||||
cachePath,
|
cachePath,
|
||||||
cache.DirectoryCacheConfig{
|
cache.DirectoryCacheConfig{
|
||||||
SyncAdd: dcc.SyncAdd,
|
SyncAdd: dcc.SyncAdd,
|
||||||
DataCache: dCache,
|
DataCache: dCache,
|
||||||
FdCache: fCache,
|
FdCache: fCache,
|
||||||
BufPool: bufPool,
|
BufPool: bufPool,
|
||||||
Direct: dcc.Direct,
|
Direct: dcc.Direct,
|
||||||
|
FadvDontNeed: dcc.FadvDontNeed,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,22 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLayer(t *testing.T) {
|
func TestLayer(t *testing.T) {
|
||||||
TestSuiteLayer(t, memorymetadata.NewReader)
|
testRunner := &TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT TestingT, name string, run func(t TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
TestSuiteLayer(testRunner, memorymetadata.NewReader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWaiter(t *testing.T) {
|
func TestWaiter(t *testing.T) {
|
||||||
|
|
|
@ -39,7 +39,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/v2/pkg/reference"
|
"github.com/containerd/containerd/v2/pkg/reference"
|
||||||
|
@ -76,7 +75,33 @@ type layerConfig struct {
|
||||||
passThroughConfig passThroughConfig
|
passThroughConfig passThroughConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSuiteLayer(t *testing.T, store metadata.Store) {
|
// TestingT is the minimal set of testing.T required to run the
|
||||||
|
// tests defined in TestSuiteLayer. This interface exists to prevent
|
||||||
|
// leaking the testing package from being exposed outside tests.
|
||||||
|
type TestingT interface {
|
||||||
|
Errorf(format string, args ...any)
|
||||||
|
Fatal(args ...any)
|
||||||
|
Fatalf(format string, args ...any)
|
||||||
|
Logf(format string, args ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runner allows running subtests of TestingT. This exists instead of adding
|
||||||
|
// a Run method to TestingT interface because the Run implementation of
|
||||||
|
// testing.T would not satisfy the interface.
|
||||||
|
type Runner func(t TestingT, name string, fn func(t TestingT))
|
||||||
|
|
||||||
|
type TestRunner struct {
|
||||||
|
TestingT
|
||||||
|
Runner Runner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TestRunner) Run(name string, run func(*TestRunner)) {
|
||||||
|
r.Runner(r.TestingT, name, func(t TestingT) {
|
||||||
|
run(&TestRunner{TestingT: t, Runner: r.Runner})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSuiteLayer(t *TestRunner, store metadata.Store) {
|
||||||
for _, lc := range []layerConfig{
|
for _, lc := range []layerConfig{
|
||||||
{
|
{
|
||||||
name: "default",
|
name: "default",
|
||||||
|
@ -117,10 +142,14 @@ func TestSuiteLayer(t *testing.T, store metadata.Store) {
|
||||||
|
|
||||||
var testStateLayerDigest = digest.FromString("dummy")
|
var testStateLayerDigest = digest.FromString("dummy")
|
||||||
|
|
||||||
func testPrefetch(t *testing.T, factory metadata.Store, lc layerConfig) {
|
func testPrefetch(t *TestRunner, factory metadata.Store, lc layerConfig) {
|
||||||
data64KB := string(tutil.RandomBytes(t, 64000))
|
randomData, err := tutil.RandomBytes(64000)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed rand.Read: %v", err)
|
||||||
|
}
|
||||||
|
data64KB := string(randomData)
|
||||||
defaultPrefetchSize := int64(10000)
|
defaultPrefetchSize := int64(10000)
|
||||||
landmarkPosition := func(t *testing.T, l *layer) int64 {
|
landmarkPosition := func(t TestingT, l *layer) int64 {
|
||||||
if l.r == nil {
|
if l.r == nil {
|
||||||
t.Fatalf("layer hasn't been verified yet")
|
t.Fatalf("layer hasn't been verified yet")
|
||||||
}
|
}
|
||||||
|
@ -140,7 +169,7 @@ func testPrefetch(t *testing.T, factory metadata.Store, lc layerConfig) {
|
||||||
in []tutil.TarEntry
|
in []tutil.TarEntry
|
||||||
wantNum int // number of chunks wanted in the cache
|
wantNum int // number of chunks wanted in the cache
|
||||||
wants []string // filenames to compare
|
wants []string // filenames to compare
|
||||||
prefetchSize func(*testing.T, *layer) int64
|
prefetchSize func(TestingT, *layer) int64
|
||||||
prioritizedFiles []string
|
prioritizedFiles []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -218,7 +247,7 @@ func testPrefetch(t *testing.T, factory metadata.Store, lc layerConfig) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
for srcCompressionName, srcCompression := range srcCompressions {
|
for srcCompressionName, srcCompression := range srcCompressions {
|
||||||
cl := srcCompression()
|
cl := srcCompression()
|
||||||
t.Run("testPrefetch-"+tt.name+"-"+srcCompressionName+"-"+lc.name, func(t *testing.T) {
|
t.Run("testPrefetch-"+tt.name+"-"+srcCompressionName+"-"+lc.name, func(t *TestRunner) {
|
||||||
chunkSize := sampleChunkSize
|
chunkSize := sampleChunkSize
|
||||||
if tt.chunkSize > 0 {
|
if tt.chunkSize > 0 {
|
||||||
chunkSize = tt.chunkSize
|
chunkSize = tt.chunkSize
|
||||||
|
@ -345,7 +374,7 @@ func isDup(a, b region) bool {
|
||||||
return b.end >= a.begin
|
return b.end >= a.begin
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBlob(t *testing.T, sr *io.SectionReader) *sampleBlob {
|
func newBlob(t TestingT, sr *io.SectionReader) *sampleBlob {
|
||||||
return &sampleBlob{
|
return &sampleBlob{
|
||||||
t: t,
|
t: t,
|
||||||
r: sr,
|
r: sr,
|
||||||
|
@ -353,7 +382,7 @@ func newBlob(t *testing.T, sr *io.SectionReader) *sampleBlob {
|
||||||
}
|
}
|
||||||
|
|
||||||
type sampleBlob struct {
|
type sampleBlob struct {
|
||||||
t *testing.T
|
t TestingT
|
||||||
|
|
||||||
r *io.SectionReader
|
r *io.SectionReader
|
||||||
readCalled bool
|
readCalled bool
|
||||||
|
@ -418,7 +447,7 @@ const (
|
||||||
lastChunkOffset1 = sampleChunkSize * (int64(len(sampleData1)) / sampleChunkSize)
|
lastChunkOffset1 = sampleChunkSize * (int64(len(sampleData1)) / sampleChunkSize)
|
||||||
)
|
)
|
||||||
|
|
||||||
func testNodeRead(t *testing.T, factory metadata.Store, lc layerConfig) {
|
func testNodeRead(t *TestRunner, factory metadata.Store, lc layerConfig) {
|
||||||
sizeCond := map[string]int64{
|
sizeCond := map[string]int64{
|
||||||
"single_chunk": sampleChunkSize - sampleMiddleOffset,
|
"single_chunk": sampleChunkSize - sampleMiddleOffset,
|
||||||
"multi_chunks": sampleChunkSize + sampleMiddleOffset,
|
"multi_chunks": sampleChunkSize + sampleMiddleOffset,
|
||||||
|
@ -443,7 +472,7 @@ func testNodeRead(t *testing.T, factory metadata.Store, lc layerConfig) {
|
||||||
for fn, filesize := range fileSizeCond {
|
for fn, filesize := range fileSizeCond {
|
||||||
for _, srcCompression := range srcCompressions {
|
for _, srcCompression := range srcCompressions {
|
||||||
cl := srcCompression()
|
cl := srcCompression()
|
||||||
t.Run(fmt.Sprintf("reading_%s_%s_%s_%s_%s", sn, in, bo, fn, lc.name), func(t *testing.T) {
|
t.Run(fmt.Sprintf("reading_%s_%s_%s_%s_%s", sn, in, bo, fn, lc.name), func(t *TestRunner) {
|
||||||
if filesize > int64(len(sampleData1)) {
|
if filesize > int64(len(sampleData1)) {
|
||||||
t.Fatal("sample file size is larger than sample data")
|
t.Fatal("sample file size is larger than sample data")
|
||||||
}
|
}
|
||||||
|
@ -498,7 +527,7 @@ func testNodeRead(t *testing.T, factory metadata.Store, lc layerConfig) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeNodeReader(t *testing.T, contents []byte, chunkSize int, factory metadata.Store, cl tutil.Compression, lc layerConfig) (_ *file, closeFn func() error) {
|
func makeNodeReader(t TestingT, contents []byte, chunkSize int, factory metadata.Store, cl tutil.Compression, lc layerConfig) (_ *file, closeFn func() error) {
|
||||||
testName := "test"
|
testName := "test"
|
||||||
sr, tocDgst, err := tutil.BuildEStargz(
|
sr, tocDgst, err := tutil.BuildEStargz(
|
||||||
[]tutil.TarEntry{tutil.File(testName, string(contents))},
|
[]tutil.TarEntry{tutil.File(testName, string(contents))},
|
||||||
|
@ -526,16 +555,20 @@ func makeNodeReader(t *testing.T, contents []byte, chunkSize int, factory metada
|
||||||
return f.(*file), r.Close
|
return f.(*file), r.Close
|
||||||
}
|
}
|
||||||
|
|
||||||
func testNodes(t *testing.T, factory metadata.Store, lc layerConfig) {
|
func testNodes(t *TestRunner, factory metadata.Store, lc layerConfig) {
|
||||||
for _, o := range []OverlayOpaqueType{OverlayOpaqueAll, OverlayOpaqueTrusted, OverlayOpaqueUser} {
|
for _, o := range []OverlayOpaqueType{OverlayOpaqueAll, OverlayOpaqueTrusted, OverlayOpaqueUser} {
|
||||||
testNodesWithOpaque(t, factory, o, lc)
|
testNodesWithOpaque(t, factory, o, lc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testNodesWithOpaque(t *testing.T, factory metadata.Store, opaque OverlayOpaqueType, lc layerConfig) {
|
func testNodesWithOpaque(t *TestRunner, factory metadata.Store, opaque OverlayOpaqueType, lc layerConfig) {
|
||||||
data64KB := string(tutil.RandomBytes(t, 64000))
|
randomData, err := tutil.RandomBytes(64000)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed rand.Read: %v", err)
|
||||||
|
}
|
||||||
|
data64KB := string(randomData)
|
||||||
hasOpaque := func(entry string) check {
|
hasOpaque := func(entry string) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
for _, k := range opaqueXattrs[opaque] {
|
for _, k := range opaqueXattrs[opaque] {
|
||||||
hasNodeXattrs(entry, k, opaqueXattrValue)(t, root, cc, cr)
|
hasNodeXattrs(entry, k, opaqueXattrValue)(t, root, cc, cr)
|
||||||
}
|
}
|
||||||
|
@ -741,7 +774,7 @@ func testNodesWithOpaque(t *testing.T, factory metadata.Store, opaque OverlayOpa
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
for _, srcCompression := range srcCompressions {
|
for _, srcCompression := range srcCompressions {
|
||||||
cl := srcCompression()
|
cl := srcCompression()
|
||||||
t.Run(tt.name+"-"+lc.name, func(t *testing.T) {
|
t.Run(tt.name+"-"+lc.name, func(t *TestRunner) {
|
||||||
opts := []tutil.BuildEStargzOption{
|
opts := []tutil.BuildEStargzOption{
|
||||||
tutil.WithEStargzOptions(estargz.WithCompression(cl)),
|
tutil.WithEStargzOptions(estargz.WithCompression(cl)),
|
||||||
}
|
}
|
||||||
|
@ -772,7 +805,7 @@ func testNodesWithOpaque(t *testing.T, factory metadata.Store, opaque OverlayOpa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRootNode(t *testing.T, r metadata.Reader, opaque OverlayOpaqueType, tocDgst digest.Digest, cc cache.BlobCache, lc layerConfig) *node {
|
func getRootNode(t TestingT, r metadata.Reader, opaque OverlayOpaqueType, tocDgst digest.Digest, cc cache.BlobCache, lc layerConfig) *node {
|
||||||
vr, err := reader.NewReader(r, cc, digest.FromString(""))
|
vr, err := reader.NewReader(r, cc, digest.FromString(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create reader: %v", err)
|
t.Fatalf("failed to create reader: %v", err)
|
||||||
|
@ -806,10 +839,10 @@ func (tb *testBlobState) Refresh(ctx context.Context, host source.RegistryHosts,
|
||||||
}
|
}
|
||||||
func (tb *testBlobState) Close() error { return nil }
|
func (tb *testBlobState) Close() error { return nil }
|
||||||
|
|
||||||
type check func(*testing.T, *node, cache.BlobCache, *calledReaderAt)
|
type check func(TestingT, *node, cache.BlobCache, *calledReaderAt)
|
||||||
|
|
||||||
func fileNotExist(file string) check {
|
func fileNotExist(file string) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
if _, _, err := getDirentAndNode(t, root, file); err == nil {
|
if _, _, err := getDirentAndNode(t, root, file); err == nil {
|
||||||
t.Errorf("Node %q exists", file)
|
t.Errorf("Node %q exists", file)
|
||||||
}
|
}
|
||||||
|
@ -817,7 +850,7 @@ func fileNotExist(file string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileDigest(filename string, digest string) check {
|
func hasFileDigest(filename string, digest string) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
_, n, err := getDirentAndNode(t, root, filename)
|
_, n, err := getDirentAndNode(t, root, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get node %q: %v", filename, err)
|
t.Fatalf("failed to get node %q: %v", filename, err)
|
||||||
|
@ -846,7 +879,7 @@ func hasFileDigest(filename string, digest string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasSize(name string, size int) check {
|
func hasSize(name string, size int) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
_, n, err := getDirentAndNode(t, root, name)
|
_, n, err := getDirentAndNode(t, root, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get node %q: %v", name, err)
|
t.Fatalf("failed to get node %q: %v", name, err)
|
||||||
|
@ -862,7 +895,7 @@ func hasSize(name string, size int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasExtraMode(name string, mode os.FileMode) check {
|
func hasExtraMode(name string, mode os.FileMode) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
_, n, err := getDirentAndNode(t, root, name)
|
_, n, err := getDirentAndNode(t, root, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get node %q: %v", name, err)
|
t.Fatalf("failed to get node %q: %v", name, err)
|
||||||
|
@ -881,7 +914,7 @@ func hasExtraMode(name string, mode os.FileMode) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasValidWhiteout(name string) check {
|
func hasValidWhiteout(name string) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
ent, n, err := getDirentAndNode(t, root, name)
|
ent, n, err := getDirentAndNode(t, root, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get node %q: %v", name, err)
|
t.Fatalf("failed to get node %q: %v", name, err)
|
||||||
|
@ -917,7 +950,7 @@ func hasValidWhiteout(name string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasNodeXattrs(entry, name, value string) check {
|
func hasNodeXattrs(entry, name, value string) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
_, n, err := getDirentAndNode(t, root, entry)
|
_, n, err := getDirentAndNode(t, root, entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get node %q: %v", entry, err)
|
t.Fatalf("failed to get node %q: %v", entry, err)
|
||||||
|
@ -958,7 +991,7 @@ func hasNodeXattrs(entry, name, value string) check {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasEntry(t *testing.T, name string, ents fusefs.DirStream) (fuse.DirEntry, bool) {
|
func hasEntry(t TestingT, name string, ents fusefs.DirStream) (fuse.DirEntry, bool) {
|
||||||
for ents.HasNext() {
|
for ents.HasNext() {
|
||||||
de, errno := ents.Next()
|
de, errno := ents.Next()
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
|
@ -971,8 +1004,8 @@ func hasEntry(t *testing.T, name string, ents fusefs.DirStream) (fuse.DirEntry,
|
||||||
return fuse.DirEntry{}, false
|
return fuse.DirEntry{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasStateFile(t *testing.T, id string) check {
|
func hasStateFile(t TestingT, id string) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
|
|
||||||
// Check the state dir is hidden on OpenDir for "/"
|
// Check the state dir is hidden on OpenDir for "/"
|
||||||
ents, errno := root.Readdir(context.Background())
|
ents, errno := root.Readdir(context.Background())
|
||||||
|
@ -1069,7 +1102,7 @@ func hasStateFile(t *testing.T, id string) check {
|
||||||
|
|
||||||
// getDirentAndNode gets dirent and node at the specified path at once and makes
|
// getDirentAndNode gets dirent and node at the specified path at once and makes
|
||||||
// sure that the both of them exist.
|
// sure that the both of them exist.
|
||||||
func getDirentAndNode(t *testing.T, root *node, path string) (ent fuse.DirEntry, n *fusefs.Inode, err error) {
|
func getDirentAndNode(t TestingT, root *node, path string) (ent fuse.DirEntry, n *fusefs.Inode, err error) {
|
||||||
dir, base := filepath.Split(filepath.Clean(path))
|
dir, base := filepath.Split(filepath.Clean(path))
|
||||||
|
|
||||||
// get the target's parent directory.
|
// get the target's parent directory.
|
||||||
|
@ -1145,7 +1178,7 @@ type chunkInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsWithPreCached(name string, off int64, contents string, extra ...chunkInfo) check {
|
func hasFileContentsWithPreCached(name string, off int64, contents string, extra ...chunkInfo) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
buf := readFile(t, root, name, int64(len(contents)), off)
|
buf := readFile(t, root, name, int64(len(contents)), off)
|
||||||
if len(buf) != len(contents) {
|
if len(buf) != len(contents) {
|
||||||
t.Fatalf("failed to read contents %q (off:%d, want:%q) got %q", name, off, longBytesView([]byte(contents)), longBytesView(buf))
|
t.Fatalf("failed to read contents %q (off:%d, want:%q) got %q", name, off, longBytesView([]byte(contents)), longBytesView(buf))
|
||||||
|
@ -1167,7 +1200,7 @@ func hasFileContentsWithPreCached(name string, off int64, contents string, extra
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsOffset(name string, off int64, contents string, fromCache bool) check {
|
func hasFileContentsOffset(name string, off int64, contents string, fromCache bool) check {
|
||||||
return func(t *testing.T, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
return func(t TestingT, root *node, cc cache.BlobCache, cr *calledReaderAt) {
|
||||||
cr.called = nil // reset test
|
cr.called = nil // reset test
|
||||||
buf := readFile(t, root, name, int64(len(contents)), off)
|
buf := readFile(t, root, name, int64(len(contents)), off)
|
||||||
if len(buf) != len(contents) {
|
if len(buf) != len(contents) {
|
||||||
|
@ -1189,7 +1222,7 @@ func hasFileContentsOffset(name string, off int64, contents string, fromCache bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFile(t *testing.T, root *node, filename string, size, off int64) []byte {
|
func readFile(t TestingT, root *node, filename string, size, off int64) []byte {
|
||||||
_, n, err := getDirentAndNode(t, root, filename)
|
_, n, err := getDirentAndNode(t, root, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to get node %q: %v", filename, err)
|
t.Fatalf("failed to get node %q: %v", filename, err)
|
||||||
|
|
|
@ -29,5 +29,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReader(t *testing.T) {
|
func TestReader(t *testing.T) {
|
||||||
TestSuiteReader(t, memorymetadata.NewReader)
|
testRunner := &TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT TestingT, name string, run func(t TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
TestSuiteReader(testRunner, memorymetadata.NewReader)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/stargz-snapshotter/cache"
|
"github.com/containerd/stargz-snapshotter/cache"
|
||||||
|
@ -64,7 +63,34 @@ var (
|
||||||
MockReadAtOutput = 4194304
|
MockReadAtOutput = 4194304
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSuiteReader(t *testing.T, store metadata.Store) {
|
// TestingT is the minimal set of testing.T required to run the
|
||||||
|
// tests defined in TestSuiteReader. This interface exists to prevent
|
||||||
|
// leaking the testing package from being exposed outside tests.
|
||||||
|
type TestingT interface {
|
||||||
|
Cleanup(func())
|
||||||
|
Errorf(format string, args ...any)
|
||||||
|
Fatal(args ...any)
|
||||||
|
Fatalf(format string, args ...any)
|
||||||
|
Logf(format string, args ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runner allows running subtests of TestingT. This exists instead of adding
|
||||||
|
// a Run method to TestingT interface because the Run implementation of
|
||||||
|
// testing.T would not satisfy the interface.
|
||||||
|
type Runner func(t TestingT, name string, fn func(t TestingT))
|
||||||
|
|
||||||
|
type TestRunner struct {
|
||||||
|
TestingT
|
||||||
|
Runner Runner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TestRunner) Run(name string, run func(*TestRunner)) {
|
||||||
|
r.Runner(r.TestingT, name, func(t TestingT) {
|
||||||
|
run(&TestRunner{TestingT: t, Runner: r.Runner})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSuiteReader(t *TestRunner, store metadata.Store) {
|
||||||
testFileReadAt(t, store)
|
testFileReadAt(t, store)
|
||||||
testCacheVerify(t, store)
|
testCacheVerify(t, store)
|
||||||
testFailReader(t, store)
|
testFailReader(t, store)
|
||||||
|
@ -72,7 +98,7 @@ func TestSuiteReader(t *testing.T, store metadata.Store) {
|
||||||
testProcessBatchChunks(t)
|
testProcessBatchChunks(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFileReadAt(t *testing.T, factory metadata.Store) {
|
func testFileReadAt(t *TestRunner, factory metadata.Store) {
|
||||||
sizeCond := map[string]int64{
|
sizeCond := map[string]int64{
|
||||||
"single_chunk": sampleChunkSize - sampleMiddleOffset,
|
"single_chunk": sampleChunkSize - sampleMiddleOffset,
|
||||||
"multi_chunks": sampleChunkSize + sampleMiddleOffset,
|
"multi_chunks": sampleChunkSize + sampleMiddleOffset,
|
||||||
|
@ -109,7 +135,7 @@ func testFileReadAt(t *testing.T, factory metadata.Store) {
|
||||||
for cc, cacheExcept := range cacheCond {
|
for cc, cacheExcept := range cacheCond {
|
||||||
for srcCompressionName, srcCompression := range srcCompressions {
|
for srcCompressionName, srcCompression := range srcCompressions {
|
||||||
srcCompression := srcCompression()
|
srcCompression := srcCompression()
|
||||||
t.Run(fmt.Sprintf("reading_%s_%s_%s_%s_%s_%s", sn, in, bo, fn, cc, srcCompressionName), func(t *testing.T) {
|
t.Run(fmt.Sprintf("reading_%s_%s_%s_%s_%s_%s", sn, in, bo, fn, cc, srcCompressionName), func(t *TestRunner) {
|
||||||
if filesize > int64(len(sampleData1)) {
|
if filesize > int64(len(sampleData1)) {
|
||||||
t.Fatal("sample file size is larger than sample data")
|
t.Fatal("sample file size is larger than sample data")
|
||||||
}
|
}
|
||||||
|
@ -199,7 +225,7 @@ func testFileReadAt(t *testing.T, factory metadata.Store) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newExceptFile(t *testing.T, fr metadata.File, except ...region) metadata.File {
|
func newExceptFile(t TestingT, fr metadata.File, except ...region) metadata.File {
|
||||||
er := exceptFile{fr: fr, t: t}
|
er := exceptFile{fr: fr, t: t}
|
||||||
er.except = map[region]bool{}
|
er.except = map[region]bool{}
|
||||||
for _, reg := range except {
|
for _, reg := range except {
|
||||||
|
@ -211,7 +237,7 @@ func newExceptFile(t *testing.T, fr metadata.File, except ...region) metadata.Fi
|
||||||
type exceptFile struct {
|
type exceptFile struct {
|
||||||
fr metadata.File
|
fr metadata.File
|
||||||
except map[region]bool
|
except map[region]bool
|
||||||
t *testing.T
|
t TestingT
|
||||||
}
|
}
|
||||||
|
|
||||||
func (er *exceptFile) ReadAt(p []byte, offset int64) (int, error) {
|
func (er *exceptFile) ReadAt(p []byte, offset int64) (int, error) {
|
||||||
|
@ -225,7 +251,7 @@ func (er *exceptFile) ChunkEntryForOffset(offset int64) (off int64, size int64,
|
||||||
return er.fr.ChunkEntryForOffset(offset)
|
return er.fr.ChunkEntryForOffset(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeFile(t *testing.T, contents []byte, chunkSize int, factory metadata.Store, comp tutil.Compression) (*file, func() error) {
|
func makeFile(t TestingT, contents []byte, chunkSize int, factory metadata.Store, comp tutil.Compression) (*file, func() error) {
|
||||||
testName := "test"
|
testName := "test"
|
||||||
sr, dgst, err := tutil.BuildEStargz([]tutil.TarEntry{
|
sr, dgst, err := tutil.BuildEStargz([]tutil.TarEntry{
|
||||||
tutil.File(testName, string(contents)),
|
tutil.File(testName, string(contents)),
|
||||||
|
@ -265,7 +291,7 @@ func makeFile(t *testing.T, contents []byte, chunkSize int, factory metadata.Sto
|
||||||
return f, vr.Close
|
return f, vr.Close
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCacheVerify(t *testing.T, factory metadata.Store) {
|
func testCacheVerify(t *TestRunner, factory metadata.Store) {
|
||||||
for _, skipVerify := range [2]bool{true, false} {
|
for _, skipVerify := range [2]bool{true, false} {
|
||||||
for _, invalidChunkBeforeVerify := range [2]bool{true, false} {
|
for _, invalidChunkBeforeVerify := range [2]bool{true, false} {
|
||||||
for _, invalidChunkAfterVerify := range [2]bool{true, false} {
|
for _, invalidChunkAfterVerify := range [2]bool{true, false} {
|
||||||
|
@ -273,7 +299,7 @@ func testCacheVerify(t *testing.T, factory metadata.Store) {
|
||||||
srcCompression := srcCompression()
|
srcCompression := srcCompression()
|
||||||
name := fmt.Sprintf("test_cache_verify_%v_%v_%v_%v",
|
name := fmt.Sprintf("test_cache_verify_%v_%v_%v_%v",
|
||||||
skipVerify, invalidChunkBeforeVerify, invalidChunkAfterVerify, srcCompressionName)
|
skipVerify, invalidChunkBeforeVerify, invalidChunkAfterVerify, srcCompressionName)
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *TestRunner) {
|
||||||
sr, tocDgst, err := tutil.BuildEStargz([]tutil.TarEntry{
|
sr, tocDgst, err := tutil.BuildEStargz([]tutil.TarEntry{
|
||||||
tutil.File("a", sampleData1+"a"),
|
tutil.File("a", sampleData1+"a"),
|
||||||
tutil.File("b", sampleData1+"b"),
|
tutil.File("b", sampleData1+"b"),
|
||||||
|
@ -483,11 +509,11 @@ func prepareMap(mr metadata.Reader, id uint32, p string) (off2id map[int64]uint3
|
||||||
return off2id, id2path, nil
|
return off2id, id2path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFailReader(t *testing.T, factory metadata.Store) {
|
func testFailReader(t *TestRunner, factory metadata.Store) {
|
||||||
testFileName := "test"
|
testFileName := "test"
|
||||||
for srcCompressionName, srcCompression := range srcCompressions {
|
for srcCompressionName, srcCompression := range srcCompressions {
|
||||||
srcCompression := srcCompression()
|
srcCompression := srcCompression()
|
||||||
t.Run(fmt.Sprintf("%v", srcCompressionName), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%v", srcCompressionName), func(t *TestRunner) {
|
||||||
for _, rs := range []bool{true, false} {
|
for _, rs := range []bool{true, false} {
|
||||||
for _, vs := range []bool{true, false} {
|
for _, vs := range []bool{true, false} {
|
||||||
stargzFile, tocDigest, err := tutil.BuildEStargz([]tutil.TarEntry{
|
stargzFile, tocDigest, err := tutil.BuildEStargz([]tutil.TarEntry{
|
||||||
|
@ -595,8 +621,12 @@ func (bev *testChunkVerifier) verifier(id uint32, chunkDigest string) (digest.Ve
|
||||||
return &testVerifier{bev.success}, nil
|
return &testVerifier{bev.success}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPreReader(t *testing.T, factory metadata.Store) {
|
func testPreReader(t *TestRunner, factory metadata.Store) {
|
||||||
data64KB := string(tutil.RandomBytes(t, 64000))
|
randomData, err := tutil.RandomBytes(64000)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed rand.Read: %v", err)
|
||||||
|
}
|
||||||
|
data64KB := string(randomData)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
chunkSize int
|
chunkSize int
|
||||||
|
@ -666,7 +696,7 @@ func testPreReader(t *testing.T, factory metadata.Store) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
for srcCompresionName, srcCompression := range srcCompressions {
|
for srcCompresionName, srcCompression := range srcCompressions {
|
||||||
srcCompression := srcCompression()
|
srcCompression := srcCompression()
|
||||||
t.Run(tt.name+"-"+srcCompresionName, func(t *testing.T) {
|
t.Run(tt.name+"-"+srcCompresionName, func(t *TestRunner) {
|
||||||
opts := []tutil.BuildEStargzOption{
|
opts := []tutil.BuildEStargzOption{
|
||||||
tutil.WithEStargzOptions(estargz.WithCompression(srcCompression)),
|
tutil.WithEStargzOptions(estargz.WithCompression(srcCompression)),
|
||||||
}
|
}
|
||||||
|
@ -705,7 +735,7 @@ func testPreReader(t *testing.T, factory metadata.Store) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type check func(*testing.T, *reader, *calledReaderAt)
|
type check func(TestingT, *reader, *calledReaderAt)
|
||||||
|
|
||||||
type chunkInfo struct {
|
type chunkInfo struct {
|
||||||
name string
|
name string
|
||||||
|
@ -715,7 +745,7 @@ type chunkInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsOffset(name string, off int64, contents string, fromCache bool) check {
|
func hasFileContentsOffset(name string, off int64, contents string, fromCache bool) check {
|
||||||
return func(t *testing.T, r *reader, cr *calledReaderAt) {
|
return func(t TestingT, r *reader, cr *calledReaderAt) {
|
||||||
tid, err := lookup(r, name)
|
tid, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to lookup %q", name)
|
t.Fatalf("failed to lookup %q", name)
|
||||||
|
@ -750,7 +780,7 @@ func hasFileContentsOffset(name string, off int64, contents string, fromCache bo
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsWithPreCached(name string, off int64, contents string, extra ...chunkInfo) check {
|
func hasFileContentsWithPreCached(name string, off int64, contents string, extra ...chunkInfo) check {
|
||||||
return func(t *testing.T, r *reader, cr *calledReaderAt) {
|
return func(t TestingT, r *reader, cr *calledReaderAt) {
|
||||||
tid, err := lookup(r, name)
|
tid, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to lookup %q", name)
|
t.Fatalf("failed to lookup %q", name)
|
||||||
|
@ -870,7 +900,7 @@ func (f *mockFile) ReadAt(p []byte, offset int64) (int, error) {
|
||||||
return MockReadAtOutput, nil
|
return MockReadAtOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testProcessBatchChunks(t *testing.T) {
|
func testProcessBatchChunks(t *TestRunner) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
setupMock func()
|
setupMock func()
|
||||||
|
@ -878,7 +908,7 @@ func testProcessBatchChunks(t *testing.T) {
|
||||||
expectErrorInHoles bool
|
expectErrorInHoles bool
|
||||||
}
|
}
|
||||||
|
|
||||||
runTest := func(t *testing.T, tc testCase) {
|
runTest := func(t TestingT, tc testCase) {
|
||||||
if tc.setupMock != nil {
|
if tc.setupMock != nil {
|
||||||
tc.setupMock()
|
tc.setupMock()
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +1030,7 @@ func testProcessBatchChunks(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *TestRunner) {
|
||||||
runTest(t, tc)
|
runTest(t, tc)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
34
go.mod
34
go.mod
|
@ -6,7 +6,7 @@ toolchain go1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/containerd/console v1.0.5
|
github.com/containerd/console v1.0.5
|
||||||
github.com/containerd/containerd/v2 v2.1.3
|
github.com/containerd/containerd/v2 v2.1.4
|
||||||
github.com/containerd/continuity v0.4.5
|
github.com/containerd/continuity v0.4.5
|
||||||
github.com/containerd/errdefs v1.0.0
|
github.com/containerd/errdefs v1.0.0
|
||||||
github.com/containerd/log v0.1.0
|
github.com/containerd/log v0.1.0
|
||||||
|
@ -14,7 +14,7 @@ require (
|
||||||
github.com/containerd/plugin v1.0.0
|
github.com/containerd/plugin v1.0.0
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.17.0
|
github.com/containerd/stargz-snapshotter/estargz v0.17.0
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli v28.3.2+incompatible
|
github.com/docker/cli v28.3.3+incompatible
|
||||||
github.com/docker/go-metrics v0.0.1
|
github.com/docker/go-metrics v0.0.1
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
||||||
|
@ -25,13 +25,13 @@ require (
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.1
|
github.com/opencontainers/image-spec v1.1.1
|
||||||
github.com/opencontainers/runtime-spec v1.2.1
|
github.com/opencontainers/runtime-spec v1.2.1
|
||||||
github.com/prometheus/client_golang v1.22.0
|
github.com/prometheus/client_golang v1.23.0
|
||||||
github.com/rs/xid v1.6.0
|
github.com/rs/xid v1.6.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
go.etcd.io/bbolt v1.4.2
|
go.etcd.io/bbolt v1.4.2
|
||||||
golang.org/x/sync v0.16.0
|
golang.org/x/sync v0.16.0
|
||||||
golang.org/x/sys v0.34.0
|
golang.org/x/sys v0.34.0
|
||||||
google.golang.org/grpc v1.73.0
|
google.golang.org/grpc v1.74.2
|
||||||
k8s.io/api v0.33.3
|
k8s.io/api v0.33.3
|
||||||
k8s.io/apimachinery v0.33.3
|
k8s.io/apimachinery v0.33.3
|
||||||
k8s.io/client-go v0.33.3
|
k8s.io/client-go v0.33.3
|
||||||
|
@ -47,7 +47,7 @@ require (
|
||||||
github.com/containerd/containerd/api v1.9.0 // indirect
|
github.com/containerd/containerd/api v1.9.0 // indirect
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
github.com/containerd/fifo v1.1.0 // indirect
|
github.com/containerd/fifo v1.1.0 // indirect
|
||||||
github.com/containerd/go-cni v1.1.12 // indirect
|
github.com/containerd/go-cni v1.1.13 // indirect
|
||||||
github.com/containerd/ttrpc v1.2.7 // indirect
|
github.com/containerd/ttrpc v1.2.7 // indirect
|
||||||
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
||||||
github.com/containernetworking/cni v1.3.0 // indirect
|
github.com/containernetworking/cni v1.3.0 // indirect
|
||||||
|
@ -57,7 +57,7 @@ require (
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // 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/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||||
|
@ -82,9 +82,9 @@ require (
|
||||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
github.com/prometheus/common v0.62.0 // indirect
|
github.com/prometheus/common v0.65.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
github.com/sasha-s/go-deadlock v0.3.5 // indirect
|
||||||
github.com/spf13/pflag v1.0.6 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
|
@ -96,15 +96,15 @@ require (
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.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 v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
golang.org/x/net v0.38.0 // indirect
|
golang.org/x/net v0.40.0 // indirect
|
||||||
golang.org/x/oauth2 v0.28.0 // indirect
|
golang.org/x/oauth2 v0.30.0 // indirect
|
||||||
golang.org/x/term v0.30.0 // indirect
|
golang.org/x/term v0.32.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/time v0.9.0 // indirect
|
golang.org/x/time v0.9.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
|
76
go.sum
76
go.sum
|
@ -23,8 +23,8 @@ github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/q
|
||||||
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
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 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
|
||||||
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
|
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.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
|
||||||
github.com/containerd/containerd/v2 v2.1.3/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
||||||
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
||||||
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
@ -33,8 +33,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
|
||||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||||
github.com/containerd/go-cni v1.1.12 h1:wm/5VD/i255hjM4uIZjBRiEQ7y98W9ACy/mHeLi4+94=
|
github.com/containerd/go-cni v1.1.13 h1:eFSGOKlhoYNxpJ51KRIMHZNlg5UgocXEIEBGkY7Hnis=
|
||||||
github.com/containerd/go-cni v1.1.12/go.mod h1:+jaqRBdtW5faJxj2Qwg1Of7GsV66xcvnCx4mSJtUlxU=
|
github.com/containerd/go-cni v1.1.13/go.mod h1:nTieub0XDRmvCZ9VI/SBG6PyqT95N4FIhxsauF1vSBI=
|
||||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
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/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||||
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
|
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
|
||||||
|
@ -55,8 +55,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/docker/cli v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS3hP2huFsY=
|
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
|
||||||
github.com/docker/cli v28.3.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||||
|
@ -77,8 +77,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.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.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
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 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||||
|
@ -212,22 +212,22 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
||||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
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.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
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.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
|
@ -275,16 +275,16 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
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/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.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
@ -308,11 +308,11 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
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-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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -332,12 +332,12 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -359,15 +359,15 @@ 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-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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
|
22
ipfs/go.mod
22
ipfs/go.mod
|
@ -5,10 +5,10 @@ go 1.23.0
|
||||||
toolchain go1.24.1
|
toolchain go1.24.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/containerd/containerd/v2 v2.1.3
|
github.com/containerd/containerd/v2 v2.1.4
|
||||||
github.com/containerd/platforms v1.0.0-rc.1
|
github.com/containerd/platforms v1.0.0-rc.1
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/multiformats/go-multiaddr v0.16.0
|
github.com/multiformats/go-multiaddr v0.16.1
|
||||||
github.com/opencontainers/image-spec v1.1.1
|
github.com/opencontainers/image-spec v1.1.1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ require (
|
||||||
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
||||||
github.com/distribution/reference v0.6.0 // indirect
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // 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/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
|
@ -57,17 +57,17 @@ require (
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.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 v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.38.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||||
golang.org/x/net v0.38.0 // indirect
|
golang.org/x/net v0.40.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.16.0 // indirect
|
||||||
golang.org/x/sys v0.34.0 // indirect
|
golang.org/x/sys v0.34.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||||
google.golang.org/grpc v1.73.0 // indirect
|
google.golang.org/grpc v1.74.2 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
lukechampine.com/blake3 v1.2.1 // indirect
|
lukechampine.com/blake3 v1.2.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
52
ipfs/go.sum
52
ipfs/go.sum
|
@ -13,8 +13,8 @@ github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJ
|
||||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||||
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
|
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/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.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
|
||||||
github.com/containerd/containerd/v2 v2.1.3/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
|
||||||
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
||||||
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
@ -45,8 +45,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
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.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
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 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
@ -114,8 +114,8 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg
|
||||||
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
|
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
|
||||||
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||||
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||||
github.com/multiformats/go-multiaddr v0.16.0 h1:oGWEVKioVQcdIOBlYM8BH1rZDWOGJSqr9/BKl6zQ4qc=
|
github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw=
|
||||||
github.com/multiformats/go-multiaddr v0.16.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
||||||
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
|
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
|
||||||
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||||
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||||
|
@ -162,22 +162,22 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
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/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.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||||
|
@ -195,8 +195,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -215,8 +215,8 @@ golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
@ -234,15 +234,15 @@ 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-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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
|
|
@ -25,7 +25,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReader(t *testing.T) {
|
func TestReader(t *testing.T) {
|
||||||
testutil.TestReader(t, readerFactory)
|
testRunner := &testutil.TestRunner{
|
||||||
|
TestingT: t,
|
||||||
|
Runner: func(testingT testutil.TestingT, name string, run func(t testutil.TestingT)) {
|
||||||
|
tt, ok := testingT.(*testing.T)
|
||||||
|
if !ok {
|
||||||
|
testingT.Fatal("TestingT is not a *testing.T")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.Run(name, func(t *testing.T) {
|
||||||
|
run(t)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testutil.TestReader(testRunner, readerFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readerFactory(sr *io.SectionReader, opts ...metadata.Option) (testutil.TestableReader, error) {
|
func readerFactory(sr *io.SectionReader, opts ...metadata.Option) (testutil.TestableReader, error) {
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/stargz-snapshotter/estargz"
|
"github.com/containerd/stargz-snapshotter/estargz"
|
||||||
|
@ -60,11 +59,41 @@ type TestableReader interface {
|
||||||
NumOfNodes() (i int, _ error)
|
NumOfNodes() (i int, _ error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestingT is the minimal set of testing.T required to run the
|
||||||
|
// tests defined in TestReader. This interface exists to prevent
|
||||||
|
// leaking the testing package from being exposed outside tests.
|
||||||
|
type TestingT interface {
|
||||||
|
Errorf(format string, args ...any)
|
||||||
|
Fatal(args ...any)
|
||||||
|
Fatalf(format string, args ...any)
|
||||||
|
Logf(format string, args ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runner allows running subtests of TestingT. This exists instead of adding
|
||||||
|
// a Run method to TestingT interface because the Run implementation of
|
||||||
|
// testing.T would not satisfy the interface.
|
||||||
|
type Runner func(t TestingT, name string, fn func(t TestingT))
|
||||||
|
|
||||||
|
type TestRunner struct {
|
||||||
|
TestingT
|
||||||
|
Runner Runner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TestRunner) Run(name string, run func(*TestRunner)) {
|
||||||
|
r.Runner(r.TestingT, name, func(t TestingT) {
|
||||||
|
run(&TestRunner{TestingT: t, Runner: r.Runner})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TestReader tests Reader returns correct file metadata.
|
// TestReader tests Reader returns correct file metadata.
|
||||||
func TestReader(t *testing.T, factory ReaderFactory) {
|
func TestReader(t *TestRunner, factory ReaderFactory) {
|
||||||
sampleTime := time.Now().Truncate(time.Second)
|
sampleTime := time.Now().Truncate(time.Second)
|
||||||
sampleText := "qwer" + "tyui" + "opas" + "dfgh" + "jk"
|
sampleText := "qwer" + "tyui" + "opas" + "dfgh" + "jk"
|
||||||
data64KB := string(tutil.RandomBytes(t, 64000))
|
randomData, err := tutil.RandomBytes(64000)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed rand.Read: %v", err)
|
||||||
|
}
|
||||||
|
data64KB := string(randomData)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
chunkSize int
|
chunkSize int
|
||||||
|
@ -286,7 +315,8 @@ func TestReader(t *testing.T, factory ReaderFactory) {
|
||||||
prefix := prefix
|
prefix := prefix
|
||||||
for srcCompresionName, srcCompression := range srcCompressions {
|
for srcCompresionName, srcCompression := range srcCompressions {
|
||||||
srcCompression := srcCompression()
|
srcCompression := srcCompression()
|
||||||
t.Run(tt.name+"-"+srcCompresionName, func(t *testing.T) {
|
|
||||||
|
t.Run(tt.name+"-"+srcCompresionName, func(t *TestRunner) {
|
||||||
opts := []tutil.BuildEStargzOption{
|
opts := []tutil.BuildEStargzOption{
|
||||||
tutil.WithBuildTarOptions(tutil.WithPrefix(prefix)),
|
tutil.WithBuildTarOptions(tutil.WithPrefix(prefix)),
|
||||||
tutil.WithEStargzOptions(estargz.WithCompression(srcCompression)),
|
tutil.WithEStargzOptions(estargz.WithCompression(srcCompression)),
|
||||||
|
@ -343,7 +373,7 @@ func TestReader(t *testing.T, factory ReaderFactory) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("clone-id-stability", func(t *testing.T) {
|
t.Run("clone-id-stability", func(t *TestRunner) {
|
||||||
var mapEntries func(r TestableReader, id uint32, m map[string]uint32) (map[string]uint32, error)
|
var mapEntries func(r TestableReader, id uint32, m map[string]uint32) (map[string]uint32, error)
|
||||||
mapEntries = func(r TestableReader, id uint32, m map[string]uint32) (map[string]uint32, error) {
|
mapEntries = func(r TestableReader, id uint32, m map[string]uint32) (map[string]uint32, error) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
|
@ -426,7 +456,7 @@ func newCalledTelemetry() (telemetry *metadata.Telemetry, check func() error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpNodes(t *testing.T, r TestableReader, id uint32, level int) {
|
func dumpNodes(t TestingT, r TestableReader, id uint32, level int) {
|
||||||
if err := r.ForeachChild(id, func(name string, id uint32, mode os.FileMode) bool {
|
if err := r.ForeachChild(id, func(name string, id uint32, mode os.FileMode) bool {
|
||||||
ind := ""
|
ind := ""
|
||||||
for i := 0; i < level; i++ {
|
for i := 0; i < level; i++ {
|
||||||
|
@ -440,10 +470,10 @@ func dumpNodes(t *testing.T, r TestableReader, id uint32, level int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type check func(*testing.T, TestableReader)
|
type check func(TestingT, TestableReader)
|
||||||
|
|
||||||
func numOfNodes(want int) check {
|
func numOfNodes(want int) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
i, err := r.NumOfNodes()
|
i, err := r.NumOfNodes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("num of nodes: %v", err)
|
t.Errorf("num of nodes: %v", err)
|
||||||
|
@ -455,7 +485,7 @@ func numOfNodes(want int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func numOfChunks(name string, num int) check {
|
func numOfChunks(name string, num int) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
nr, ok := r.(interface {
|
nr, ok := r.(interface {
|
||||||
NumOfChunks(id uint32) (i int, _ error)
|
NumOfChunks(id uint32) (i int, _ error)
|
||||||
})
|
})
|
||||||
|
@ -479,7 +509,7 @@ func numOfChunks(name string, num int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sameNodes(n string, nodes ...string) check {
|
func sameNodes(n string, nodes ...string) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, n)
|
id, err := lookup(r, n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to lookup %q: %v", n, err)
|
t.Errorf("failed to lookup %q: %v", n, err)
|
||||||
|
@ -499,7 +529,7 @@ func sameNodes(n string, nodes ...string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkName(name string, linkName string) check {
|
func linkName(name string, linkName string) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to lookup %q: %v", name, err)
|
t.Errorf("failed to lookup %q: %v", name, err)
|
||||||
|
@ -522,7 +552,7 @@ func linkName(name string, linkName string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasNumLink(name string, numLink int) check {
|
func hasNumLink(name string, numLink int) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to lookup %q: %v", name, err)
|
t.Errorf("failed to lookup %q: %v", name, err)
|
||||||
|
@ -541,7 +571,7 @@ func hasNumLink(name string, numLink int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasDirChildren(name string, children ...string) check {
|
func hasDirChildren(name string, children ...string) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to lookup %q: %v", name, err)
|
t.Errorf("failed to lookup %q: %v", name, err)
|
||||||
|
@ -576,7 +606,7 @@ func hasDirChildren(name string, children ...string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasChardev(name string, maj, min int) check {
|
func hasChardev(name string, maj, min int) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find chardev %q: %v", name, err)
|
t.Errorf("cannot find chardev %q: %v", name, err)
|
||||||
|
@ -599,7 +629,7 @@ func hasChardev(name string, maj, min int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasBlockdev(name string, maj, min int) check {
|
func hasBlockdev(name string, maj, min int) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find blockdev %q: %v", name, err)
|
t.Errorf("cannot find blockdev %q: %v", name, err)
|
||||||
|
@ -622,7 +652,7 @@ func hasBlockdev(name string, maj, min int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFifo(name string) check {
|
func hasFifo(name string) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find blockdev %q: %v", name, err)
|
t.Errorf("cannot find blockdev %q: %v", name, err)
|
||||||
|
@ -641,7 +671,7 @@ func hasFifo(name string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFile(name, content string, size int64) check {
|
func hasFile(name, content string, size int64) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find file %q: %v", name, err)
|
t.Errorf("cannot find file %q: %v", name, err)
|
||||||
|
@ -686,7 +716,7 @@ type chunkInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsWithPreRead(name string, off int64, contents string, extra ...chunkInfo) check {
|
func hasFileContentsWithPreRead(name string, off int64, contents string, extra ...chunkInfo) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
extraMap := make(map[uint32]chunkInfo)
|
extraMap := make(map[uint32]chunkInfo)
|
||||||
for _, e := range extra {
|
for _, e := range extra {
|
||||||
id, err := lookup(r, e.name)
|
id, err := lookup(r, e.name)
|
||||||
|
@ -753,7 +783,7 @@ func hasFileContentsWithPreRead(name string, off int64, contents string, extra .
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasFileContentsOffset(name string, off int64, contents string) check {
|
func hasFileContentsOffset(name string, off int64, contents string) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to lookup %q: %v", name, err)
|
t.Errorf("failed to lookup %q: %v", name, err)
|
||||||
|
@ -782,7 +812,7 @@ func hasFileContentsOffset(name string, off int64, contents string) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasMode(name string, mode os.FileMode) check {
|
func hasMode(name string, mode os.FileMode) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find file %q: %v", name, err)
|
t.Errorf("cannot find file %q: %v", name, err)
|
||||||
|
@ -801,7 +831,7 @@ func hasMode(name string, mode os.FileMode) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasOwner(name string, uid, gid int) check {
|
func hasOwner(name string, uid, gid int) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find file %q: %v", name, err)
|
t.Errorf("cannot find file %q: %v", name, err)
|
||||||
|
@ -820,7 +850,7 @@ func hasOwner(name string, uid, gid int) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasModTime(name string, modTime time.Time) check {
|
func hasModTime(name string, modTime time.Time) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find file %q: %v", name, err)
|
t.Errorf("cannot find file %q: %v", name, err)
|
||||||
|
@ -840,7 +870,7 @@ func hasModTime(name string, modTime time.Time) check {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasXattrs(name string, xattrs map[string]string) check {
|
func hasXattrs(name string, xattrs map[string]string) check {
|
||||||
return func(t *testing.T, r TestableReader) {
|
return func(t TestingT, r TestableReader) {
|
||||||
id, err := lookup(r, name)
|
id, err := lookup(r, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("cannot find file %q: %v", name, err)
|
t.Errorf("cannot find file %q: %v", name, err)
|
||||||
|
|
|
@ -760,10 +760,13 @@ func (o *snapshotter) restoreRemoteSnapshot(ctx context.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.Mkdir(filepath.Join(o.root, "snapshots", id), 0700); err != nil {
|
if err := os.Mkdir(filepath.Join(o.root, "snapshots", id), 0700); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return os.Mkdir(o.upperPath(id), 0755)
|
if err := os.Mkdir(o.upperPath(id), 0755); err != nil && !os.IsExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}(); err != nil {
|
}(); err != nil {
|
||||||
return fmt.Errorf("failed to create remote snapshot directory: %s: %w", info.Name, err)
|
return fmt.Errorf("failed to create remote snapshot directory: %s: %w", info.Name, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,13 @@ package testutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// RandomBytes returns the specified number of random bytes
|
// RandomBytes returns the specified number of random bytes
|
||||||
func RandomBytes(t *testing.T, n int) []byte {
|
func RandomBytes(n int) ([]byte, error) {
|
||||||
b := make([]byte, n)
|
b := make([]byte, n)
|
||||||
if _, err := rand.Read(b); err != nil {
|
if _, err := rand.Read(b); err != nil {
|
||||||
t.Fatalf("failed rand.Read: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return b
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue