Compare commits

..

283 Commits

Author SHA1 Message Date
Kohei Tokunaga 554629b4a1
Merge pull request #2105 from containerd/dependabot/go_modules/containerd-2f3dabfc34
build(deps): bump the containerd group across 2 directories with 1 update
2025-08-11 21:37:26 +09:00
Kohei Tokunaga a986f8c194
Merge pull request #2101 from containerd/dependabot/github_actions/actions/download-artifact-5
build(deps): bump actions/download-artifact from 4 to 5
2025-08-10 16:50:38 +09:00
Kohei Tokunaga 38cf9aa57c
Merge pull request #2104 from containerd/dependabot/go_modules/cmd/gomod-cfb98d732f
build(deps): bump the gomod group across 2 directories with 1 update
2025-08-09 12:56:57 +09:00
dependabot[bot] e07c7abb8c
build(deps): bump the containerd group across 2 directories with 1 update
Bumps the containerd group with 1 update in the / directory: [github.com/containerd/go-cni](https://github.com/containerd/go-cni).
Bumps the containerd group with 1 update in the /cmd directory: [github.com/containerd/go-cni](https://github.com/containerd/go-cni).


Updates `github.com/containerd/go-cni` from 1.1.12 to 1.1.13
- [Release notes](https://github.com/containerd/go-cni/releases)
- [Commits](https://github.com/containerd/go-cni/compare/v1.1.12...v1.1.13)

Updates `github.com/containerd/go-cni` from 1.1.12 to 1.1.13
- [Release notes](https://github.com/containerd/go-cni/releases)
- [Commits](https://github.com/containerd/go-cni/compare/v1.1.12...v1.1.13)

---
updated-dependencies:
- dependency-name: github.com/containerd/go-cni
  dependency-version: 1.1.13
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/go-cni
  dependency-version: 1.1.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-08 21:07:10 +00:00
dependabot[bot] 7b508b1afe
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the /cmd directory: [github.com/multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr).
Bumps the gomod group with 1 update in the /ipfs directory: [github.com/multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr).


Updates `github.com/multiformats/go-multiaddr` from 0.16.0 to 0.16.1
- [Release notes](https://github.com/multiformats/go-multiaddr/releases)
- [Commits](https://github.com/multiformats/go-multiaddr/compare/v0.16.0...v0.16.1)

Updates `github.com/multiformats/go-multiaddr` from 0.16.0 to 0.16.1
- [Release notes](https://github.com/multiformats/go-multiaddr/releases)
- [Commits](https://github.com/multiformats/go-multiaddr/compare/v0.16.0...v0.16.1)

---
updated-dependencies:
- dependency-name: github.com/multiformats/go-multiaddr
  dependency-version: 0.16.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/multiformats/go-multiaddr
  dependency-version: 0.16.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-07 20:39:58 +00:00
Kohei Tokunaga 08272a30af
Merge pull request #2102 from wswsmao/main
ctr-remote: support 'all' for --gpus flag
2025-08-07 23:14:01 +09:00
abushwang d09a4ffa5b ctr-remote: support 'all' for --gpus flag
Signed-off-by: abushwang <abushwang@tencent.com>
2025-08-07 20:13:47 +08:00
dependabot[bot] 1227c8e42b
build(deps): bump actions/download-artifact from 4 to 5
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-06 20:29:12 +00:00
Kohei Tokunaga 21fb6a16e4
Merge pull request #2100 from containerd/dependabot/go_modules/gomod-5d31edd0e2
build(deps): bump the gomod group across 2 directories with 1 update
2025-08-01 20:28:39 +09:00
dependabot[bot] f400f935f7
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang).


Updates `github.com/prometheus/client_golang` from 1.22.0 to 1.23.0
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/v1.23.0/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.22.0...v1.23.0)

Updates `github.com/prometheus/client_golang` from 1.22.0 to 1.23.0
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/v1.23.0/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.22.0...v1.23.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-31 20:34:42 +00:00
Kohei Tokunaga d0487729a1
Merge pull request #2098 from rosstimothy/tross/remove_testing
Remove `testing` dependency from code outside tests
2025-08-01 00:34:36 +09:00
Tim Ross 2aef7a6e63
Replace testing.T references with local TestingT interface
Removes the dependency on the `testing` package in the remaining
testutil packages by defining a local TestingT interface which
contains the subset of `testing.T` required for the test helpers.

Signed-off-by: Tim Ross <tim.ross@goteleport.com>
2025-07-31 10:13:18 -04:00
Tim Ross 18e393af96
Remove testing from util/testutil package
RandomBytes now returns an error instead of taking a testing.T
and asserting the error is non nil to eliminate dependence on the
testing package outside of test files.

Signed-off-by: Tim Ross <tim.ross@goteleport.com>
2025-07-31 10:13:17 -04:00
Kohei Tokunaga 927075ba7b
Merge pull request #2099 from containerd/dependabot/go_modules/containerd-24169ab9f1
build(deps): bump the containerd group across 3 directories with 1 update
2025-07-31 09:56:52 +09:00
dependabot[bot] e53cec5266
build(deps): bump the containerd group across 3 directories with 1 update
Bumps the containerd group with 1 update in the / directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /cmd directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).


Updates `github.com/containerd/containerd/v2` from 2.1.3 to 2.1.4
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.3...v2.1.4)

Updates `github.com/containerd/containerd/v2` from 2.1.3 to 2.1.4
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.3...v2.1.4)

Updates `github.com/containerd/containerd/v2` from 2.1.3 to 2.1.4
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.3...v2.1.4)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 20:58:05 +00:00
Kohei Tokunaga 555e167719
Merge pull request #2096 from containerd/dependabot/go_modules/gomod-f8c008d7c4
build(deps): bump the gomod group across 2 directories with 1 update
2025-07-30 10:00:29 +09:00
dependabot[bot] f72d3aecc8
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.3.2+incompatible to 28.3.3+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.3.2...v28.3.3)

Updates `github.com/docker/cli` from 28.3.2+incompatible to 28.3.3+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.3.2...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.3+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.3+incompatible
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-29 20:59:10 +00:00
Kohei Tokunaga 19a5bd5157
Merge pull request #2095 from wswsmao/main
Add FadvDontNeed option to avoid double pagecache consumption
2025-07-29 18:59:43 +09:00
abushwang f62679453f Add FadvDontNeed option to avoid double pagecache consumption
Signed-off-by: abushwang <abushwang@tencent.com>
2025-07-29 16:24:11 +08:00
Kohei Tokunaga 17134ee517
Merge pull request #2092 from wswsmao/main
docs: Add Unexpected restart handling
2025-07-26 16:44:47 +09:00
abushwang 420a03fa46 docs: Add Unexpected restart handling
Signed-off-by: abushwang <abushwang@tencent.com>
2025-07-24 19:29:13 +08:00
Kohei Tokunaga 3aa69eaac5
Merge pull request #2091 from wswsmao/main
Fix file exists error when restoring remote snapshot after unexpected…
2025-07-24 15:41:38 +09:00
abushwang b3743e7916 Fix file exists error when restoring remote snapshot after unexpected restart
Signed-off-by: abushwang <abushwang@tencent.com>
2025-07-23 20:57:24 +08:00
Kohei Tokunaga 4677721cfc
Merge pull request #2089 from containerd/dependabot/docker/kindest/node-v1.33.2
build(deps): bump kindest/node from v1.33.1 to v1.33.2
2025-07-23 10:32:09 +09:00
Kohei Tokunaga 9e6b9b72af
Merge pull request #2090 from containerd/dependabot/go_modules/google-golang-d7ee4b52d7
build(deps): bump the google-golang group across 3 directories with 1 update
2025-07-23 10:31:44 +09:00
dependabot[bot] cfa57c95a9
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.73.0 to 1.74.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2)

Updates `google.golang.org/grpc` from 1.73.0 to 1.74.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2)

Updates `google.golang.org/grpc` from 1.73.0 to 1.74.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.74.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.74.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.74.2
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-22 20:55:46 +00:00
dependabot[bot] 24e8a7858a
build(deps): bump kindest/node from v1.33.1 to v1.33.2
Bumps kindest/node from v1.33.1 to v1.33.2.

---
updated-dependencies:
- dependency-name: kindest/node
  dependency-version: v1.33.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-22 20:03:31 +00:00
Kohei Tokunaga 6f6aacb044
Merge pull request #2088 from ktock/prepare-v0.17.0
Prepare for v0.17.0
2025-07-22 15:57:12 +09:00
Kohei Tokunaga ff4141ab8a
Prepare for v0.17.0
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-22 14:03:22 +09:00
Kohei Tokunaga dfb9f43a00
Merge pull request #2087 from containerd/dependabot/go_modules/k8s-7ac0ac0c3e
build(deps): bump the k8s group across 2 directories with 4 updates
2025-07-17 21:36:26 +09:00
dependabot[bot] 6bffc90072
build(deps): bump the k8s group across 2 directories with 4 updates
Bumps the k8s group with 3 updates in the / directory: [k8s.io/api](https://github.com/kubernetes/api), [k8s.io/client-go](https://github.com/kubernetes/client-go) and [k8s.io/cri-api](https://github.com/kubernetes/cri-api).
Bumps the k8s group with 3 updates in the /cmd directory: [k8s.io/api](https://github.com/kubernetes/api), [k8s.io/client-go](https://github.com/kubernetes/client-go) and [k8s.io/cri-api](https://github.com/kubernetes/cri-api).


Updates `k8s.io/api` from 0.33.2 to 0.33.3
- [Commits](https://github.com/kubernetes/api/compare/v0.33.2...v0.33.3)

Updates `k8s.io/apimachinery` from 0.33.2 to 0.33.3
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.2...v0.33.3)

Updates `k8s.io/client-go` from 0.33.2 to 0.33.3
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.33.2...v0.33.3)

Updates `k8s.io/cri-api` from 0.33.2 to 0.33.3
- [Commits](https://github.com/kubernetes/cri-api/compare/v0.33.2...v0.33.3)

Updates `k8s.io/api` from 0.33.2 to 0.33.3
- [Commits](https://github.com/kubernetes/api/compare/v0.33.2...v0.33.3)

Updates `k8s.io/apimachinery` from 0.33.2 to 0.33.3
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.33.2...v0.33.3)

Updates `k8s.io/client-go` from 0.33.2 to 0.33.3
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.33.2...v0.33.3)

Updates `k8s.io/cri-api` from 0.33.2 to 0.33.3
- [Commits](https://github.com/kubernetes/cri-api/compare/v0.33.2...v0.33.3)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-version: 0.33.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/apimachinery
  dependency-version: 0.33.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/client-go
  dependency-version: 0.33.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/cri-api
  dependency-version: 0.33.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/api
  dependency-version: 0.33.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/apimachinery
  dependency-version: 0.33.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/client-go
  dependency-version: 0.33.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: k8s
- dependency-name: k8s.io/cri-api
  dependency-version: 0.33.3
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: k8s
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-16 21:08:21 +00:00
Akihiro Suda 56bb07c852
Merge pull request #2085 from ktock/dockerfilebumpup-a
Dockerfile: bump up dependencies
2025-07-16 18:01:24 +09:00
Kohei Tokunaga 71c6675ef2
Dockerfile: bump up dependencies
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 16:19:19 +09:00
Kohei Tokunaga 0aab392f46
Merge pull request #1914 from ktock/fuse-manager-tests
CI: test fuse manager
2025-07-16 16:18:36 +09:00
Kohei Tokunaga 020d3474b6
fuse manager: Ensure cleanup by moving it to the main routine
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:55 +09:00
Kohei Tokunaga 0270add8e1
Fix test to use listen_path field for FUSE manager
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:55 +09:00
Kohei Tokunaga b4db2b98bc
Enable CRI Keychain to configure the listening path
Add "listen_path" field to the CRI Keychain config to specify a custom socket
path for the CRI image service.

When the FUSE manager is disabled, this defaults to the containerd-stargz-grpc
path (`/run/containerd-stargz-grpc/containerd-stargz-grpc.sock`).

When the FUSE manager is enabled with CRI-based authentication, `listen_path` is
a mandatory field with some caveats:

- This path must be different from the FUSE manager's socket path
  (`/run/containerd-stargz-grpc/fuse-manager.sock`) because they have different
  lifecycle. Specifically, the CRI socket is recreted on each reload of the
  configuration to the FUSE manager.

- containerd-stargz-grpc's socket path
  (`/run/containerd-stargz-grpc/containerd-stargz-grpc.sock`) can't be used as
  `listen_path` because the CRI socket is served by the FUSE manager process
  (not containerd-stargz-grpc process).

Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:54 +09:00
Kohei Tokunaga 993d44a197
config: add JSON tags
Add JSON tag to configuration fields. This is needed to send configuration
to the fuse manager in JSON format. Without this change, some configuration
struct passed to the FUSE manager were incorrectly unmarshalled and caused
the test failure.

Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:54 +09:00
Kohei Tokunaga 26ee38d5c5
Add a socket cleanup and make sure it's correctly detected by the e flag
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:54 +09:00
Kohei Tokunaga 6e65bca4f5
Avoid opening bolt DB multiple times
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:53 +09:00
Kohei Tokunaga 32a679f130
Enable tests with fusemanager
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:53 +09:00
Kohei Tokunaga 5be16a5cfe
Move fusemanager configuration to the config file
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 15:21:53 +09:00
Kohei Tokunaga 7de6607e7f
Merge pull request #1893 from ktock/rootconfig
Fix GC failure of CRI plugin
2025-07-16 15:21:30 +09:00
Kohei Tokunaga dae086b594
README: remove an obsolete note
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 14:26:24 +09:00
Kohei Tokunaga d33d9332c4
tests: Add the root config
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 14:26:21 +09:00
Kohei Tokunaga 75435f7bb4
docs: Add the root config to avoid GC failure in CRI plugin
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 14:25:55 +09:00
Kohei Tokunaga fd445ac572
Merge pull request #2084 from ktock/transferservice
Add docs and tests for Transfer Service
2025-07-16 14:19:11 +09:00
Kohei Tokunaga b405072cb1
test: Add test for Transfer Service
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 13:24:37 +09:00
Kohei Tokunaga 51d84f2656
Dockerfile: update pause image to the version used in critest
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 13:24:37 +09:00
Kohei Tokunaga 4a050718c1
docs: add docs about how to use with Transfer Service
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-16 13:24:33 +09:00
Akihiro Suda 1b3ba8662f
Merge pull request #2083 from ktock/fusedev1
test: enable passthrough mode in all layer tests
2025-07-16 12:28:03 +09:00
Kohei Tokunaga 1e3ef72d1e
Merge pull request #2082 from containerd/dependabot/go_modules/gomod-eaa2222ecf
build(deps): bump the gomod group across 2 directories with 1 update
2025-07-11 13:21:42 +09:00
Kohei Tokunaga 73e08ea280
Merge pull request #2081 from containerd/dependabot/go_modules/golang-x-5c1d565794
build(deps): bump the golang-x group across 4 directories with 2 updates
2025-07-11 11:30:53 +09:00
Akihiro Suda acb3e9007c
Merge pull request #2077 from ktock/gracefulrestart-b
Make graceful restarting available in wider configurations
2025-07-11 07:20:09 +09:00
Kohei Tokunaga 82999f50f7
test: enable passthrough mode in all layer tests
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-11 00:05:34 +09:00
dependabot[bot] 7cbb501deb
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.3.1+incompatible to 28.3.2+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.3.1...v28.3.2)

Updates `github.com/docker/cli` from 28.3.1+incompatible to 28.3.2+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.3.1...v28.3.2)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.2+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.2+incompatible
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-09 20:51:51 +00:00
dependabot[bot] 3733c98749
build(deps): bump the golang-x group across 4 directories with 2 updates
Bumps the golang-x group with 2 updates in the / directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 2 updates in the /cmd directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 1 update in the /estargz directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 2 updates in the /ipfs directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sync` from 0.15.0 to 0.16.0
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

Updates `golang.org/x/sys` from 0.33.0 to 0.34.0
- [Commits](https://github.com/golang/sys/compare/v0.33.0...v0.34.0)

Updates `golang.org/x/sync` from 0.15.0 to 0.16.0
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

Updates `golang.org/x/sys` from 0.33.0 to 0.34.0
- [Commits](https://github.com/golang/sys/compare/v0.33.0...v0.34.0)

Updates `golang.org/x/sync` from 0.15.0 to 0.16.0
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

Updates `golang.org/x/sync` from 0.15.0 to 0.16.0
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

Updates `golang.org/x/sys` from 0.33.0 to 0.34.0
- [Commits](https://github.com/golang/sys/compare/v0.33.0...v0.34.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.34.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.34.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.34.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-09 20:51:35 +00:00
Kohei Tokunaga 5b78e51f73
Add docs about restart
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 16:27:35 +09:00
Kohei Tokunaga 9945490b14
Add SIGTERM restart test
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 16:27:35 +09:00
Kohei Tokunaga 64a898a3e3
Enable graceful restarting on SIGTERM and Fuse manager
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 16:27:35 +09:00
Akihiro Suda a744b5da80
Merge pull request #2076 from ktock/ttlcachefix
Fix TTLCache could't release resources just after layer creation
2025-07-09 15:52:03 +09:00
Kohei Tokunaga 6cd27f9a06
fix No such file or directory error during restoring snapshots
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 14:57:01 +09:00
Kohei Tokunaga 5fabcd2907
revert deleting of metadata DB
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 14:57:00 +09:00
Kohei Tokunaga e351aa9af1
Add tests of restarting snapshotter
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 14:56:56 +09:00
Kohei Tokunaga 22f7f7164a
Fix TTLCache could't release resources just after layer creation
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 14:54:12 +09:00
Akihiro Suda 8fb5e1d8fb
Merge pull request #2074 from ktock/test10
CI: enable FUSE passthrough in CI
2025-07-09 13:25:39 +09:00
Akihiro Suda 967f35a72c
Merge pull request #2078 from ktock/k8s-1.33
Bump up k8s to 1.33
2025-07-09 12:12:28 +09:00
Kohei Tokunaga 2173abf9dc
bump up k8s to 1.33
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-09 10:06:35 +09:00
Kohei Tokunaga e463a879bc
Bump up k3s to 1.32
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-05 23:09:32 +09:00
Kohei Tokunaga 26c7c2de60
CI: enable FUSE passthrough in CI
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-07-05 00:39:51 +09:00
Kohei Tokunaga 6b395b9c3a
Merge pull request #2073 from containerd/dependabot/go_modules/gomod-a8ae04838e
build(deps): bump the gomod group across 2 directories with 1 update
2025-07-04 17:37:02 +09:00
dependabot[bot] d826f0a8bb
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.3.0+incompatible to 28.3.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.3.0...v28.3.1)

Updates `github.com/docker/cli` from 28.3.0+incompatible to 28.3.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.3.0...v28.3.1)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.1+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.1+incompatible
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-03 21:02:43 +00:00
Kohei Tokunaga b90d85827a
Merge pull request #2070 from containerd/dependabot/go_modules/gomod-473739e4a2
build(deps): bump the gomod group across 2 directories with 2 updates
2025-07-01 11:10:29 +09:00
dependabot[bot] 22a56133de
build(deps): bump the gomod group across 2 directories with 2 updates
Bumps the gomod group with 2 updates in the / directory: [github.com/docker/cli](https://github.com/docker/cli) and [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt).
Bumps the gomod group with 2 updates in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli) and [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt).


Updates `github.com/docker/cli` from 28.2.2+incompatible to 28.3.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.2.2...v28.3.0)

Updates `go.etcd.io/bbolt` from 1.4.1 to 1.4.2
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.1...v1.4.2)

Updates `go.etcd.io/bbolt` from 1.4.1 to 1.4.2
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.1...v1.4.2)

Updates `github.com/docker/cli` from 28.2.2+incompatible to 28.3.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.2.2...v28.3.0)

Updates `go.etcd.io/bbolt` from 1.4.1 to 1.4.2
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.1...v1.4.2)

Updates `go.etcd.io/bbolt` from 1.4.1 to 1.4.2
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.0+incompatible
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-27 20:57:56 +00:00
Kohei Tokunaga 5a1b37f051
Merge pull request #2068 from wswsmao/main
fix panic when chunk size exceeds merge buffer size
2025-06-28 00:03:08 +09:00
abushwang 3c021f1403 fix panic when chunk size exceeds merge buffer size
Signed-off-by: abushwang <abushwang@tencent.com>
2025-06-26 10:51:02 +08:00
Akihiro Suda 1d2f153bc1
Merge pull request #2051 from ktock/golangci-lint-action-8
CI: bump up golangci-lint-action to v8.0.0
2025-06-26 03:58:53 +09:00
Akihiro Suda 20070f8ff0
Merge pull request #2066 from ktock/containerd-v2.1.2
Dockerfile: Bump up containerd to v2.1.2
2025-06-26 03:58:39 +09:00
Kohei Tokunaga ddf07e9290
Merge pull request #2067 from containerd/dependabot/go_modules/containerd-4b09323716
build(deps): bump the containerd group across 3 directories with 1 update
2025-06-21 20:42:56 +09:00
dependabot[bot] 147ac653e2
build(deps): bump the containerd group across 3 directories with 1 update
Bumps the containerd group with 1 update in the / directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /cmd directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).


Updates `github.com/containerd/containerd/v2` from 2.1.2 to 2.1.3
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.2...v2.1.3)

Updates `github.com/containerd/containerd/v2` from 2.1.2 to 2.1.3
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.2...v2.1.3)

Updates `github.com/containerd/containerd/v2` from 2.1.2 to 2.1.3
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.2...v2.1.3)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-20 21:00:38 +00:00
Kohei Tokunaga c577fcf339
Dockerfile: Bump up containerd to v2.1.2
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-06-19 09:48:22 +09:00
Kohei Tokunaga b1f8fcc115
Merge pull request #2065 from containerd/dependabot/go_modules/gomod-778ba813e8
build(deps): bump the gomod group across 2 directories with 1 update
2025-06-19 09:32:21 +09:00
dependabot[bot] 382512efc6
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp).


Updates `github.com/hashicorp/go-retryablehttp` from 0.7.7 to 0.7.8
- [Changelog](https://github.com/hashicorp/go-retryablehttp/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.7...v0.7.8)

Updates `github.com/hashicorp/go-retryablehttp` from 0.7.7 to 0.7.8
- [Changelog](https://github.com/hashicorp/go-retryablehttp/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.7...v0.7.8)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/go-retryablehttp
  dependency-version: 0.7.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/hashicorp/go-retryablehttp
  dependency-version: 0.7.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-18 20:59:22 +00:00
Kohei Tokunaga 7c7d78c4fc
Merge pull request #2062 from containerd/dependabot/go_modules/containerd-152b805ead
build(deps): bump the containerd group across 3 directories with 1 update
2025-06-18 22:37:59 +09:00
Kohei Tokunaga ba3491a6b6
Merge pull request #2064 from containerd/dependabot/go_modules/gomod-98b568163d
build(deps): bump the gomod group across 2 directories with 2 updates
2025-06-18 22:37:25 +09:00
dependabot[bot] 3bb341f386
build(deps): bump the containerd group across 3 directories with 1 update
Bumps the containerd group with 1 update in the / directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /cmd directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).


Updates `github.com/containerd/containerd/v2` from 2.1.1 to 2.1.2
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.1...v2.1.2)

Updates `github.com/containerd/containerd/v2` from 2.1.1 to 2.1.2
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.1...v2.1.2)

Updates `github.com/containerd/containerd/v2` from 2.1.1 to 2.1.2
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-16 20:39:43 +00:00
dependabot[bot] 61cec058ec
build(deps): bump the gomod group across 2 directories with 2 updates
Bumps the gomod group with 2 updates in the / directory: [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) and [github.com/urfave/cli/v2](https://github.com/urfave/cli).
Bumps the gomod group with 2 updates in the /cmd directory: [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) and [github.com/urfave/cli/v2](https://github.com/urfave/cli).


Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.1)

Updates `github.com/urfave/cli/v2` from 2.27.6 to 2.27.7
- [Release notes](https://github.com/urfave/cli/releases)
- [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md)
- [Commits](https://github.com/urfave/cli/compare/v2.27.6...v2.27.7)

Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.1)

Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.1)

Updates `github.com/urfave/cli/v2` from 2.27.6 to 2.27.7
- [Release notes](https://github.com/urfave/cli/releases)
- [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md)
- [Commits](https://github.com/urfave/cli/compare/v2.27.6...v2.27.7)

Updates `go.etcd.io/bbolt` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/etcd-io/bbolt/releases)
- [Commits](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/urfave/cli/v2
  dependency-version: 2.27.7
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/urfave/cli/v2
  dependency-version: 2.27.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: go.etcd.io/bbolt
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-15 01:26:02 +00:00
Kohei Tokunaga fd3e6ce33d
Merge pull request #2063 from wswsmao/main
Bump up github.com/hanwen/go-fuse to the latest
2025-06-15 10:24:26 +09:00
abushwang 24432e9f8c Bump up github.com/hanwen/go-fuse to the latest
Signed-off-by: abushwang <abushwang@tencent.com>
2025-06-13 18:34:08 +08:00
Kohei Tokunaga 6956955469
Merge pull request #2061 from soulshake/patch-1
Update overview.md
2025-06-13 01:54:08 +09:00
AJ Bowen 31f53f4ce7
Update overview.md
- Specify that the state directory is found in the container filesystem.
- Minor wording and formatting tweaks.

Signed-off-by: AJ Bowen <soulshake@users.noreply.github.com>
2025-06-12 05:39:49 -07:00
Kohei Tokunaga 1ce551bb21
Merge pull request #2057 from containerd/dependabot/go_modules/google-golang-f0e8a66639
build(deps): bump the google-golang group across 3 directories with 1 update
2025-06-10 15:36:05 +09:00
dependabot[bot] 4687f78aaf
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.72.2 to 1.73.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.2...v1.73.0)

Updates `google.golang.org/grpc` from 1.72.2 to 1.73.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.2...v1.73.0)

Updates `google.golang.org/grpc` from 1.72.2 to 1.73.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.2...v1.73.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.73.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.73.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.73.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-09 20:43:25 +00:00
Kohei Tokunaga a8c7561e92
Merge pull request #2058 from containerd/dependabot/go_modules/cmd/gomod-cf4833bac4
build(deps): bump the gomod group across 2 directories with 1 update
2025-06-08 20:29:52 +09:00
dependabot[bot] e02c1d9e5d
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the /cmd directory: [github.com/multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr).
Bumps the gomod group with 1 update in the /ipfs directory: [github.com/multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr).


Updates `github.com/multiformats/go-multiaddr` from 0.15.0 to 0.16.0
- [Release notes](https://github.com/multiformats/go-multiaddr/releases)
- [Commits](https://github.com/multiformats/go-multiaddr/compare/v0.15.0...v0.16.0)

Updates `github.com/multiformats/go-multiaddr` from 0.15.0 to 0.16.0
- [Release notes](https://github.com/multiformats/go-multiaddr/releases)
- [Commits](https://github.com/multiformats/go-multiaddr/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: github.com/multiformats/go-multiaddr
  dependency-version: 0.16.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/multiformats/go-multiaddr
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-06 21:08:43 +00:00
Kohei Tokunaga dbe654734c
Merge pull request #2056 from containerd/dependabot/go_modules/golang-x-ba73ebdbcd
build(deps): bump the golang-x group across 4 directories with 1 update
2025-06-06 22:43:47 +09:00
dependabot[bot] 7a5255aa87
build(deps): bump the golang-x group across 4 directories with 1 update
Bumps the golang-x group with 1 update in the / directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 1 update in the /cmd directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 1 update in the /estargz directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 1 update in the /ipfs directory: [golang.org/x/sync](https://github.com/golang/sync).


Updates `golang.org/x/sync` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/sync/compare/v0.14.0...v0.15.0)

Updates `golang.org/x/sync` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/sync/compare/v0.14.0...v0.15.0)

Updates `golang.org/x/sync` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/sync/compare/v0.14.0...v0.15.0)

Updates `golang.org/x/sync` from 0.14.0 to 0.15.0
- [Commits](https://github.com/golang/sync/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.15.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-05 20:12:07 +00:00
Kohei Tokunaga a88e80272d
Merge pull request #2055 from containerd/dependabot/go_modules/gomod-80c025b3d0
build(deps): bump the gomod group across 2 directories with 1 update
2025-06-05 21:27:09 +09:00
dependabot[bot] 448993b170
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.2.0+incompatible to 28.2.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.2.0...v28.2.1)

Updates `github.com/docker/cli` from 28.2.0+incompatible to 28.2.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.2.0...v28.2.1)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.2.1+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.2.1+incompatible
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-04 20:40:22 +00:00
Kohei Tokunaga 0790ac81af
Merge pull request #2045 from wswsmao/main
fix no such file error for zero size file in passthrough mode
2025-06-04 11:57:50 +09:00
Kohei Tokunaga 0b39089460
Merge pull request #2052 from containerd/dependabot/go_modules/google-golang-b4b5684aa4
build(deps): bump the google-golang group across 3 directories with 1 update
2025-06-03 23:18:36 +09:00
dependabot[bot] 56a5070e13
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.72.1 to 1.72.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.1...v1.72.2)

Updates `google.golang.org/grpc` from 1.72.1 to 1.72.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.1...v1.72.2)

Updates `google.golang.org/grpc` from 1.72.1 to 1.72.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.1...v1.72.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.2
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 20:14:05 +00:00
Kohei Tokunaga 908ead9eb9
Merge pull request #2053 from containerd/dependabot/github_actions/docker/build-push-action-6.18.0
build(deps): bump docker/build-push-action from 6.17.0 to 6.18.0
2025-06-01 20:49:11 +09:00
Kohei Tokunaga 3b84e3e6cc
Merge pull request #2054 from containerd/dependabot/go_modules/gomod-8773345f46
build(deps): bump the gomod group across 2 directories with 1 update
2025-05-29 23:03:33 +09:00
dependabot[bot] 07a4eeab9d
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.1.1+incompatible to 28.2.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.1.1...v28.2.0)

Updates `github.com/docker/cli` from 28.1.1+incompatible to 28.2.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.1.1...v28.2.0)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.2.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.2.0+incompatible
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-28 21:10:08 +00:00
dependabot[bot] bf4c6611c1
build(deps): bump docker/build-push-action from 6.17.0 to 6.18.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.17.0 to 6.18.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.17.0...v6.18.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-27 20:52:29 +00:00
Kohei Tokunaga f0b8fe69e1
CI: bump up golangci-lint-action to v8.0.0
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-05-24 21:10:01 +09:00
Akihiro Suda 09d0115ee0
Merge pull request #2049 from containerd/dependabot/go_modules/containerd-ecbf110260
build(deps): bump the containerd group across 3 directories with 2 updates
2025-05-21 03:21:16 +09:00
dependabot[bot] ddb9c189ba
build(deps): bump the containerd group across 3 directories with 2 updates
Bumps the containerd group with 2 updates in the / directory: [github.com/containerd/console](https://github.com/containerd/console) and [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 2 updates in the /cmd directory: [github.com/containerd/console](https://github.com/containerd/console) and [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).


Updates `github.com/containerd/console` from 1.0.4 to 1.0.5
- [Release notes](https://github.com/containerd/console/releases)
- [Commits](https://github.com/containerd/console/compare/v1.0.4...v1.0.5)

Updates `github.com/containerd/containerd/v2` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.0...v2.1.1)

Updates `github.com/containerd/console` from 1.0.4 to 1.0.5
- [Release notes](https://github.com/containerd/console/releases)
- [Commits](https://github.com/containerd/console/compare/v1.0.4...v1.0.5)

Updates `github.com/containerd/containerd/v2` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.0...v2.1.1)

Updates `github.com/containerd/containerd/v2` from 2.1.0 to 2.1.1
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.1.0...v2.1.1)

---
updated-dependencies:
- dependency-name: github.com/containerd/console
  dependency-version: 1.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/console
  dependency-version: 1.0.5
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-20 18:03:27 +00:00
Kohei Tokunaga a28797ad9e
Merge pull request #2047 from containerd/dependabot/github_actions/docker/build-push-action-6.17.0
build(deps): bump docker/build-push-action from 6.16.0 to 6.17.0
2025-05-17 10:05:54 +09:00
Kohei Tokunaga 93a7332a68
Merge pull request #2046 from containerd/dependabot/go_modules/google-golang-8d19ff2495
build(deps): bump the google-golang group across 3 directories with 1 update
2025-05-16 22:57:37 +09:00
dependabot[bot] 597f6736c8
build(deps): bump docker/build-push-action from 6.16.0 to 6.17.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.16.0 to 6.17.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.16.0...v6.17.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-15 20:12:40 +00:00
dependabot[bot] 4100e57e56
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.72.0 to 1.72.1
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.0...v1.72.1)

Updates `google.golang.org/grpc` from 1.72.0 to 1.72.1
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.0...v1.72.1)

Updates `google.golang.org/grpc` from 1.72.0 to 1.72.1
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.0...v1.72.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-14 20:40:44 +00:00
Kohei Tokunaga e9c84ab69e
Merge pull request #2044 from containerd/dependabot/go_modules/containerd-69917e2460
build(deps): bump the containerd group across 3 directories with 2 updates
2025-05-14 23:18:14 +09:00
dependabot[bot] 521cf2357b
build(deps): bump the containerd group across 3 directories with 2 updates
Bumps the containerd group with 1 update in the / directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /cmd directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).


Updates `github.com/containerd/containerd/v2` from 2.0.5 to 2.1.0
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.5...v2.1.0)

Updates `github.com/containerd/containerd/api` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/api/v1.8.0...api/v1.9.0)

Updates `github.com/containerd/containerd/v2` from 2.0.5 to 2.1.0
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.5...v2.1.0)

Updates `github.com/containerd/containerd/api` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/api/v1.8.0...api/v1.9.0)

Updates `github.com/containerd/containerd/v2` from 2.0.5 to 2.1.0
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.5...v2.1.0)

Updates `github.com/containerd/containerd/api` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/api/v1.8.0...api/v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/api
  dependency-version: 1.9.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/api
  dependency-version: 1.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/api
  dependency-version: 1.9.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-13 12:58:59 +00:00
Kohei Tokunaga c866f48a91
Merge pull request #2043 from containerd/dependabot/go_modules/golang-x-e42ebe3952
build(deps): bump the golang-x group across 4 directories with 2 updates
2025-05-13 21:57:25 +09:00
abushwang 476cca1bb9 fix no such file error for zero size file in passthrough mode
Signed-off-by: abushwang <abushwang@tencent.com>
2025-05-08 19:41:25 +08:00
dependabot[bot] 9bc4c0a90f
build(deps): bump the golang-x group across 4 directories with 2 updates
Bumps the golang-x group with 2 updates in the / directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 2 updates in the /cmd directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 1 update in the /estargz directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 2 updates in the /ipfs directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sync` from 0.13.0 to 0.14.0
- [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0)

Updates `golang.org/x/sys` from 0.32.0 to 0.33.0
- [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0)

Updates `golang.org/x/sync` from 0.13.0 to 0.14.0
- [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0)

Updates `golang.org/x/sys` from 0.32.0 to 0.33.0
- [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0)

Updates `golang.org/x/sync` from 0.13.0 to 0.14.0
- [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0)

Updates `golang.org/x/sync` from 0.13.0 to 0.14.0
- [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0)

Updates `golang.org/x/sys` from 0.32.0 to 0.33.0
- [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.14.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.33.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-07 20:21:48 +00:00
Akihiro Suda 64e2f1ca01
Merge pull request #2024 from wswsmao/main
Align the Maximum filename length with the running file system
2025-05-07 10:41:42 +09:00
abushwang d32e99f051 Align the Maximum filename length with the running file system
Signed-off-by: abushwang <abushwangs@gmail.com>
2025-05-06 20:23:44 +08:00
Akihiro Suda bd6fbed40e
Merge pull request #1983 from ktock/arm64image
Build arm64 images
2025-04-28 17:44:28 +09:00
Kohei Tokunaga 0695afcf9d
Merge pull request #2040 from containerd/dependabot/github_actions/docker/build-push-action-6.16.0
build(deps): bump docker/build-push-action from 6.15.0 to 6.16.0
2025-04-26 14:12:37 +09:00
dependabot[bot] 1cb2cbd87a
build(deps): bump docker/build-push-action from 6.15.0 to 6.16.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.15.0 to 6.16.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.15.0...v6.16.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-24 20:05:27 +00:00
Kohei Tokunaga 2f71f9ea81
Merge pull request #2038 from containerd/dependabot/go_modules/google-golang-6eb4c4764e
build(deps): bump the google-golang group across 3 directories with 1 update
2025-04-22 13:58:18 +09:00
dependabot[bot] f78cf735f1
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.71.1 to 1.72.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.0)

Updates `google.golang.org/grpc` from 1.71.1 to 1.72.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.0)

Updates `google.golang.org/grpc` from 1.71.1 to 1.72.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-21 21:00:35 +00:00
Kohei Tokunaga 20617610f3
Merge pull request #2037 from containerd/dependabot/go_modules/gomod-0bebf51544
build(deps): bump the gomod group across 2 directories with 1 update
2025-04-20 20:38:16 +09:00
dependabot[bot] 14d4229cc2
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.1.0+incompatible to 28.1.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.1.0...v28.1.1)

Updates `github.com/docker/cli` from 28.1.0+incompatible to 28.1.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.1.0...v28.1.1)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.1.1+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.1.1+incompatible
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-18 20:54:47 +00:00
Kohei Tokunaga 04aa66acfe
Merge pull request #2034 from containerd/dependabot/go_modules/containerd-a9795fb7e5
build(deps): bump the containerd group across 3 directories with 1 update
2025-04-18 16:03:18 +09:00
Kohei Tokunaga ee9a70f65b
Merge pull request #2035 from containerd/dependabot/go_modules/gomod-78e2cdb8b4
build(deps): bump the gomod group across 2 directories with 1 update
2025-04-18 16:02:56 +09:00
dependabot[bot] 21da82e333
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 28.0.4+incompatible to 28.1.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.0.4...v28.1.0)

Updates `github.com/docker/cli` from 28.0.4+incompatible to 28.1.0+incompatible
- [Commits](https://github.com/docker/cli/compare/v28.0.4...v28.1.0)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.1.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-version: 28.1.0+incompatible
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-17 20:32:38 +00:00
dependabot[bot] ff6d93ffe7
build(deps): bump the containerd group across 3 directories with 1 update
Bumps the containerd group with 1 update in the / directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /cmd directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/containerd/v2](https://github.com/containerd/containerd).


Updates `github.com/containerd/containerd/v2` from 2.0.4 to 2.0.5
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.4...v2.0.5)

Updates `github.com/containerd/containerd/v2` from 2.0.4 to 2.0.5
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.4...v2.0.5)

Updates `github.com/containerd/containerd/v2` from 2.0.4 to 2.0.5
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.4...v2.0.5)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/containerd/v2
  dependency-version: 2.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-17 20:32:25 +00:00
Kohei Tokunaga 5700835dc7
Merge pull request #2030 from containerd/dependabot/go_modules/gomod-6797de9c31
build(deps): bump the gomod group across 2 directories with 1 update
2025-04-15 23:15:25 +09:00
dependabot[bot] 571126430b
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang).


Updates `github.com/prometheus/client_golang` from 1.21.1 to 1.22.0
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.21.1...v1.22.0)

Updates `github.com/prometheus/client_golang` from 1.21.1 to 1.22.0
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.21.1...v1.22.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.22.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 20:36:45 +00:00
Kohei Tokunaga f64abb664e
Merge pull request #2029 from containerd/dependabot/go_modules/golang-x-535182bbee
build(deps): bump the golang-x group across 4 directories with 2 updates
2025-04-13 17:24:30 +09:00
dependabot[bot] acf9e82e65
build(deps): bump the golang-x group across 4 directories with 2 updates
Bumps the golang-x group with 2 updates in the / directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 2 updates in the /cmd directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 1 update in the /estargz directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 2 updates in the /ipfs directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sync` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/sync/compare/v0.12.0...v0.13.0)

Updates `golang.org/x/sys` from 0.31.0 to 0.32.0
- [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.32.0)

Updates `golang.org/x/sync` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/sync/compare/v0.12.0...v0.13.0)

Updates `golang.org/x/sys` from 0.31.0 to 0.32.0
- [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.32.0)

Updates `golang.org/x/sync` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/sync/compare/v0.12.0...v0.13.0)

Updates `golang.org/x/sync` from 0.12.0 to 0.13.0
- [Commits](https://github.com/golang/sync/compare/v0.12.0...v0.13.0)

Updates `golang.org/x/sys` from 0.31.0 to 0.32.0
- [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-version: 0.32.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-09 21:24:11 +00:00
Kohei Tokunaga 91c7a24718
Merge pull request #2011 from ktock/bump-a
Bump up dependencies
2025-04-09 13:43:59 +09:00
Akihiro Suda 54ff30096c
Merge pull request #2026 from ktock/golangci-lint-v2
bump golangci/golangci-lint-action from 6.5.2 to 7.0.0
2025-04-09 12:43:24 +09:00
Kohei Tokunaga 3d42bd31e1
Bump up dependencies
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-04-09 12:01:12 +09:00
Kohei Tokunaga 2b82fff1e2
Fix linter errors
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-04-09 10:03:41 +09:00
Kohei Tokunaga dff21ff05b
Test building images
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-04-08 18:21:05 +09:00
Kohei Tokunaga 72dd8cb40c
Build arm64 images
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-04-08 18:21:00 +09:00
Kohei Tokunaga 1c4bf94471
Merge pull request #2027 from containerd/dependabot/go_modules/google-golang-8b6a00ea23
build(deps): bump the google-golang group across 3 directories with 1 update
2025-04-05 17:35:26 +09:00
dependabot[bot] 6d55471940
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.71.0 to 1.71.1
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.0...v1.71.1)

Updates `google.golang.org/grpc` from 1.71.0 to 1.71.1
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.0...v1.71.1)

Updates `google.golang.org/grpc` from 1.71.0 to 1.71.1
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.0...v1.71.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.71.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.71.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-version: 1.71.1
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-01 20:31:51 +00:00
Kohei Tokunaga 01f4d46344
bump up golangci-lint-action to 7.0.0
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-30 23:20:31 +09:00
Kohei Tokunaga a9a70aa205
golangci-lint: migrate config to v2
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-30 23:20:11 +09:00
Akihiro Suda dbddc6d7d0
Merge pull request #2019 from ktock/bump-x-net
bump golang.org/x/net from 0.35.0 to 0.36.0
2025-03-19 19:29:40 +09:00
Akihiro Suda 83235b43f4
Merge pull request #2023 from ktock/containerd-v2.0.4
containerd v2.0.4
2025-03-19 19:29:25 +09:00
Kohei Tokunaga e31f542702
Merge pull request #2022 from containerd/dependabot/github_actions/golangci/golangci-lint-action-6.5.2
build(deps): bump golangci/golangci-lint-action from 6.5.1 to 6.5.2
2025-03-19 11:56:56 +09:00
Kohei Tokunaga 55a5b1e9fa
go.mod: containerd v2.0.4
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-19 11:39:24 +09:00
Kohei Tokunaga fb3d66a8c6
Dockerfile: containerd v2.0.4
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-19 11:38:24 +09:00
dependabot[bot] 6e4d8fe26e
build(deps): bump golangci/golangci-lint-action from 6.5.1 to 6.5.2
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.5.1 to 6.5.2.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.5.1...v6.5.2)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-18 20:10:19 +00:00
Kohei Tokunaga 95d84dc49d
bump golang.org/x/net from 0.35.0 to 0.36.0
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-15 17:14:47 +09:00
Akihiro Suda 3d4636757c
Merge pull request #2010 from ktock/containerd-2.0.3
containerd v2.0.3
2025-03-15 01:12:17 +09:00
Kohei Tokunaga a00b4ba202
Merge pull request #2012 from wswsmao/main
Add buffer validation and tests for passthrough concurrent file merging
2025-03-14 13:31:32 +09:00
Kohei Tokunaga c249f3b57d
Merge pull request #2017 from containerd/dependabot/github_actions/golangci/golangci-lint-action-6.5.1
build(deps): bump golangci/golangci-lint-action from 6.5.0 to 6.5.1
2025-03-13 13:55:43 +09:00
dependabot[bot] eb8709ad22
build(deps): bump golangci/golangci-lint-action from 6.5.0 to 6.5.1
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.5.0 to 6.5.1.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.5.0...v6.5.1)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-12 20:51:09 +00:00
abushwang 89dbb7ee26 Add buffer validation and tests for passthrough concurrent file merging
Signed-off-by: abushwang <abushwangs@gmail.com>
2025-03-12 17:28:45 +08:00
Kohei Tokunaga c60239ad5e
Merge pull request #1987 from wswsmao/main
concurrent file merging in passthrough mode to reduce initial pull time
2025-03-11 12:14:39 +09:00
Kohei Tokunaga 46b695d108
Dockerfile: containerd v2.0.3
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-10 23:56:29 +09:00
Kohei Tokunaga 1052f2b3ca
go.mod: containerd v2.0.3
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-03-10 23:56:25 +09:00
Kohei Tokunaga 485286846f
Merge pull request #2000 from containerd/dependabot/go_modules/google-golang-31beebe2df
build(deps): bump the google-golang group across 3 directories with 1 update
2025-03-08 14:01:10 +09:00
dependabot[bot] c09b2ca9cd
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.70.0 to 1.71.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.0)

Updates `google.golang.org/grpc` from 1.70.0 to 1.71.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.0)

Updates `google.golang.org/grpc` from 1.70.0 to 1.71.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-07 03:23:57 +00:00
Akihiro Suda 930e944ecb
Merge pull request #2004 from wswsmao/fixci
fix required kunalkushwaha error
2025-03-07 11:18:38 +09:00
abushwang b20254636f fix required kunalkushwaha error
Signed-off-by: abushwang <abushwangs@gmail.com>
2025-03-06 11:29:07 +08:00
abushwang 9133e6d667 concurrent file merging in passthrough mode to reduce initial pull time
Signed-off-by: abushwang <abushwangs@gmail.com>
2025-03-05 11:39:45 +08:00
Kohei Tokunaga e2cdd6b36a
Merge pull request #1998 from containerd/dependabot/go_modules/opencontainers-558ce3e790
build(deps): bump the opencontainers group across 3 directories with 1 update
2025-03-04 23:55:40 +09:00
dependabot[bot] 2cd3dc452b
build(deps): bump the opencontainers group across 3 directories with 1 update
Bumps the opencontainers group with 1 update in the / directory: [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec).
Bumps the opencontainers group with 1 update in the /cmd directory: [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec).
Bumps the opencontainers group with 1 update in the /ipfs directory: [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec).


Updates `github.com/opencontainers/image-spec` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0...v1.1.1)

Updates `github.com/opencontainers/image-spec` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0...v1.1.1)

Updates `github.com/opencontainers/image-spec` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/image-spec
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: opencontainers
- dependency-name: github.com/opencontainers/image-spec
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: opencontainers
- dependency-name: github.com/opencontainers/image-spec
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: opencontainers
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-03 20:27:13 +00:00
Kohei Tokunaga a215137b6f
Merge pull request #1996 from containerd/dependabot/go_modules/opencontainers-31e2eb4b79
build(deps): bump the opencontainers group across 3 directories with 1 update
2025-03-01 20:57:16 +09:00
dependabot[bot] 4e5823b998
build(deps): bump the opencontainers group across 3 directories with 1 update
Bumps the opencontainers group with 1 update in the / directory: [github.com/opencontainers/runtime-spec](https://github.com/opencontainers/runtime-spec).
Bumps the opencontainers group with 1 update in the /cmd directory: [github.com/opencontainers/runtime-spec](https://github.com/opencontainers/runtime-spec).
Bumps the opencontainers group with 1 update in the /ipfs directory: [github.com/opencontainers/runtime-spec](https://github.com/opencontainers/runtime-spec).


Updates `github.com/opencontainers/runtime-spec` from 1.2.0 to 1.2.1
- [Release notes](https://github.com/opencontainers/runtime-spec/releases)
- [Changelog](https://github.com/opencontainers/runtime-spec/blob/main/ChangeLog)
- [Commits](https://github.com/opencontainers/runtime-spec/compare/v1.2.0...v1.2.1)

Updates `github.com/opencontainers/runtime-spec` from 1.2.0 to 1.2.1
- [Release notes](https://github.com/opencontainers/runtime-spec/releases)
- [Changelog](https://github.com/opencontainers/runtime-spec/blob/main/ChangeLog)
- [Commits](https://github.com/opencontainers/runtime-spec/compare/v1.2.0...v1.2.1)

Updates `github.com/opencontainers/runtime-spec` from 1.2.0 to 1.2.1
- [Release notes](https://github.com/opencontainers/runtime-spec/releases)
- [Changelog](https://github.com/opencontainers/runtime-spec/blob/main/ChangeLog)
- [Commits](https://github.com/opencontainers/runtime-spec/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/runtime-spec
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: opencontainers
- dependency-name: github.com/opencontainers/runtime-spec
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: opencontainers
- dependency-name: github.com/opencontainers/runtime-spec
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: opencontainers
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-28 20:39:59 +00:00
Kohei Tokunaga d924a271df
Merge pull request #1993 from containerd/dependabot/github_actions/docker/build-push-action-6.15.0
build(deps): bump docker/build-push-action from 6.14.0 to 6.15.0
2025-02-28 07:33:46 +09:00
dependabot[bot] ca7d26e418
build(deps): bump docker/build-push-action from 6.14.0 to 6.15.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.14.0 to 6.15.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.14.0...v6.15.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-26 20:13:51 +00:00
Akihiro Suda f75681d180
Merge pull request #1991 from ktock/fix-argoci
CI: fix K3sArgoWorkflow failure
2025-02-26 15:10:20 +09:00
Akihiro Suda 0bbee9a5f2
Merge pull request #1982 from ktock/golangci-lint-action-6.5.0
Bump up golangci-lint action to 6.5.0
2025-02-26 15:10:02 +09:00
Kohei Tokunaga e0dbe544bf
CI: fix K3sArgoWorkflow failure
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-25 23:42:52 +09:00
Kohei Tokunaga 65f684de6a
Merge pull request #1984 from containerd/dependabot/github_actions/docker/build-push-action-6.14.0
build(deps): bump docker/build-push-action from 6.13.0 to 6.14.0
2025-02-20 16:15:08 +09:00
dependabot[bot] 6c371c72dd
build(deps): bump docker/build-push-action from 6.13.0 to 6.14.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.13.0 to 6.14.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.13.0...v6.14.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-19 20:41:25 +00:00
Kohei Tokunaga 39a7cc58b3
bump up goalngci-lint action to 6.5.0
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-18 12:10:21 +09:00
Kohei Tokunaga 0f84891c0a
golangci-lint: fix config
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-18 12:09:55 +09:00
Akihiro Suda 4441cbd94a
Merge pull request #1971 from ktock/golang-1.24
test with golang 1.24
2025-02-18 10:16:23 +09:00
Akihiro Suda f839d37b91
Merge pull request #1967 from ktock/limadocs
Add docs about how to use stargz-snapshotter on Lima
2025-02-18 10:16:06 +09:00
Kohei Tokunaga 3c943351d9
test with golang 1.24
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-14 13:01:13 +09:00
Kohei Tokunaga 921268fad5
Merge pull request #1977 from containerd/dependabot/github_actions/golangci/golangci-lint-action-6.3.3
build(deps): bump golangci/golangci-lint-action from 6.3.2 to 6.3.3
2025-02-14 12:59:32 +09:00
Kohei Tokunaga 56a5b82e12
Merge pull request #1975 from containerd/dependabot/docker/golang-1.24-bullseye
build(deps): bump golang from 1.23-bullseye to 1.24-bullseye
2025-02-14 12:26:32 +09:00
dependabot[bot] bef7113118
build(deps): bump golangci/golangci-lint-action from 6.3.2 to 6.3.3
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.3.2 to 6.3.3.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.3.2...v6.3.3)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 20:29:54 +00:00
Kohei Tokunaga 90f332866b
Add docs about how to use stargz-snapshotter on Lima
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-13 22:32:14 +09:00
Akihiro Suda 6378393321
Merge pull request #1955 from ktock/carrying-1948
[Carry 1948] fs/remote: Refactor blob code to make it more modular
2025-02-13 11:28:09 +09:00
dependabot[bot] 70195cecd2
build(deps): bump golang from 1.23-bullseye to 1.24-bullseye
Bumps golang from 1.23-bullseye to 1.24-bullseye.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-12 20:27:01 +00:00
Akihiro Suda d5f314b218
Merge pull request #1972 from ktock/golangci-lint-1.64.2
CI: golangci-lint 1.64.2
2025-02-12 13:19:04 +09:00
Akihiro Suda 6d1ee71694
Merge pull request #1973 from ktock/bump-golang-x-net
Bump up golang.org/x/net to v0.35.0
2025-02-12 13:18:49 +09:00
Kohei Tokunaga 20920f031e
golang.org/x/net v0.35.0
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-12 11:45:01 +09:00
Kohei Tokunaga 16ebb73438
CI: golangci-lint 1.64.2
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-02-12 10:55:28 +09:00
Kohei Tokunaga db01164bda
Merge pull request #1970 from containerd/dependabot/github_actions/golangci/golangci-lint-action-6.3.2
build(deps): bump golangci/golangci-lint-action from 6.3.0 to 6.3.2
2025-02-12 10:54:25 +09:00
dependabot[bot] c4e10c6e1d
build(deps): bump golangci/golangci-lint-action from 6.3.0 to 6.3.2
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.3.0 to 6.3.2.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.3.0...v6.3.2)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 20:48:10 +00:00
Kohei Tokunaga d270507e62
Merge pull request #1963 from containerd/dependabot/github_actions/golangci/golangci-lint-action-6.3.0
build(deps): bump golangci/golangci-lint-action from 6.2.0 to 6.3.0
2025-02-08 08:18:06 +09:00
Kohei Tokunaga 5fcb52981f
Merge pull request #1964 from containerd/dependabot/go_modules/golang-x-ad2494f695
build(deps): bump the golang-x group across 4 directories with 2 updates
2025-02-06 02:15:29 +09:00
dependabot[bot] 9fbffbc209
build(deps): bump the golang-x group across 4 directories with 2 updates
Bumps the golang-x group with 2 updates in the / directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 2 updates in the /cmd directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 1 update in the /estargz directory: [golang.org/x/sync](https://github.com/golang/sync).
Bumps the golang-x group with 2 updates in the /ipfs directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sync` from 0.10.0 to 0.11.0
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

Updates `golang.org/x/sys` from 0.29.0 to 0.30.0
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0)

Updates `golang.org/x/sync` from 0.10.0 to 0.11.0
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

Updates `golang.org/x/sys` from 0.29.0 to 0.30.0
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0)

Updates `golang.org/x/sync` from 0.10.0 to 0.11.0
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

Updates `golang.org/x/sync` from 0.10.0 to 0.11.0
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

Updates `golang.org/x/sys` from 0.29.0 to 0.30.0
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sync
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-04 21:01:20 +00:00
dependabot[bot] 0aeda7f1b4
build(deps): bump golangci/golangci-lint-action from 6.2.0 to 6.3.0
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.2.0...v6.3.0)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-04 20:42:28 +00:00
Kohei Tokunaga 8441124370
Merge pull request #1961 from containerd/dependabot/go_modules/gomod-cfc3e9b707
build(deps): bump the gomod group across 3 directories with 1 update
2025-02-01 14:28:09 +09:00
dependabot[bot] b07768ff1c
build(deps): bump the gomod group across 3 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/vbatts/tar-split](https://github.com/vbatts/tar-split).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/vbatts/tar-split](https://github.com/vbatts/tar-split).
Bumps the gomod group with 1 update in the /estargz directory: [github.com/vbatts/tar-split](https://github.com/vbatts/tar-split).


Updates `github.com/vbatts/tar-split` from 0.11.7 to 0.12.1
- [Release notes](https://github.com/vbatts/tar-split/releases)
- [Commits](https://github.com/vbatts/tar-split/compare/v0.11.7...v0.12.1)

Updates `github.com/vbatts/tar-split` from 0.11.7 to 0.12.1
- [Release notes](https://github.com/vbatts/tar-split/releases)
- [Commits](https://github.com/vbatts/tar-split/compare/v0.11.7...v0.12.1)

Updates `github.com/vbatts/tar-split` from 0.11.7 to 0.12.1
- [Release notes](https://github.com/vbatts/tar-split/releases)
- [Commits](https://github.com/vbatts/tar-split/compare/v0.11.7...v0.12.1)

---
updated-dependencies:
- dependency-name: github.com/vbatts/tar-split
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/vbatts/tar-split
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: gomod
- dependency-name: github.com/vbatts/tar-split
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-31 20:53:59 +00:00
Kohei Tokunaga bfb6cf34c4
Merge pull request #1958 from containerd/dependabot/go_modules/cmd/gomod-68871e6667
build(deps): bump github.com/goccy/go-json from 0.10.4 to 0.10.5 in /cmd in the gomod group across 1 directory
2025-01-31 15:07:17 +09:00
dependabot[bot] d925291d90
build(deps): bump github.com/goccy/go-json
Bumps the gomod group with 1 update in the /cmd directory: [github.com/goccy/go-json](https://github.com/goccy/go-json).


Updates `github.com/goccy/go-json` from 0.10.4 to 0.10.5
- [Release notes](https://github.com/goccy/go-json/releases)
- [Changelog](https://github.com/goccy/go-json/blob/master/CHANGELOG.md)
- [Commits](https://github.com/goccy/go-json/compare/v0.10.4...v0.10.5)

---
updated-dependencies:
- dependency-name: github.com/goccy/go-json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-28 21:14:55 +00:00
Kohei Tokunaga 1281fc2cd2
Merge pull request #1956 from containerd/dependabot/github_actions/docker/build-push-action-6.13.0
build(deps): bump docker/build-push-action from 6.12.0 to 6.13.0
2025-01-26 21:48:54 +09:00
dependabot[bot] cabe48b136
build(deps): bump docker/build-push-action from 6.12.0 to 6.13.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.12.0 to 6.13.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.12.0...v6.13.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-24 20:27:25 +00:00
Kohei Tokunaga 38aad330e7
Merge pull request #1952 from containerd/dependabot/go_modules/google-golang-7cbfbc0f6f
build(deps): bump the google-golang group across 3 directories with 1 update
2025-01-25 01:47:29 +09:00
Kohei Tokunaga 1645a0eb29
simplify readFromCache
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-01-24 19:52:40 +09:00
ChengyuZhu6 f13f534c8a fs/remote: Refactor blob code to make it more modular.
This commit refactors the blob handling code to improve code organization.
The changes include:

1. Extract chunk handling logic into separate functions:
   - prepareChunksForRead: Prepare chunks for reading
   - readFromCache: Handle cache reading
   - cacheChunkData: Handle chunk caching
   - handleSharedFetch: Handle shared fetch scenarios
   - copyFetchedChunks: Copy fetched chunks

2. Improve error handling:
   - Add more descriptive error messages
   - Consistent error wrapping using fmt.Errorf
   - Maintain same error handling behavior

3. Keep original behavior:
   - Maintain same data flow
   - Keep same concurrency control
   - No additional memory allocations
   - Same caching mechanism

4. Code organization improvements:
   - Single responsibility functions
   - Clear function names
   - Better code readability
   - Easier to maintain and test

Signed-off-by: ChengyuZhu6 <hudson@cyzhu.com>
2025-01-24 10:26:24 +08:00
dependabot[bot] d1083271a4
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.69.4 to 1.70.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.4...v1.70.0)

Updates `google.golang.org/grpc` from 1.69.4 to 1.70.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.4...v1.70.0)

Updates `google.golang.org/grpc` from 1.69.4 to 1.70.0
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.4...v1.70.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-23 21:12:51 +00:00
Kohei Tokunaga a76b90e438
Merge pull request #1950 from containerd/dependabot/go_modules/gomod-86efb2f1f2
build(deps): bump the gomod group across 2 directories with 1 update
2025-01-23 20:51:16 +09:00
dependabot[bot] 051fad67f9
build(deps): bump the gomod group across 2 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/docker/cli](https://github.com/docker/cli).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/docker/cli](https://github.com/docker/cli).


Updates `github.com/docker/cli` from 27.5.0+incompatible to 27.5.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v27.5.0...v27.5.1)

Updates `github.com/docker/cli` from 27.5.0+incompatible to 27.5.1+incompatible
- [Commits](https://github.com/docker/cli/compare/v27.5.0...v27.5.1)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/docker/cli
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-22 20:47:58 +00:00
Kohei Tokunaga 740078d5d4
Merge pull request #1949 from containerd/dependabot/go_modules/gomod-d26ddd1c32
build(deps): bump the gomod group across 3 directories with 1 update
2025-01-22 12:20:32 +09:00
dependabot[bot] b4b4cf9437
build(deps): bump the gomod group across 3 directories with 1 update
Bumps the gomod group with 1 update in the / directory: [github.com/vbatts/tar-split](https://github.com/vbatts/tar-split).
Bumps the gomod group with 1 update in the /cmd directory: [github.com/vbatts/tar-split](https://github.com/vbatts/tar-split).
Bumps the gomod group with 1 update in the /estargz directory: [github.com/vbatts/tar-split](https://github.com/vbatts/tar-split).


Updates `github.com/vbatts/tar-split` from 0.11.6 to 0.11.7
- [Release notes](https://github.com/vbatts/tar-split/releases)
- [Commits](https://github.com/vbatts/tar-split/compare/v0.11.6...v0.11.7)

Updates `github.com/vbatts/tar-split` from 0.11.6 to 0.11.7
- [Release notes](https://github.com/vbatts/tar-split/releases)
- [Commits](https://github.com/vbatts/tar-split/compare/v0.11.6...v0.11.7)

Updates `github.com/vbatts/tar-split` from 0.11.6 to 0.11.7
- [Release notes](https://github.com/vbatts/tar-split/releases)
- [Commits](https://github.com/vbatts/tar-split/compare/v0.11.6...v0.11.7)

---
updated-dependencies:
- dependency-name: github.com/vbatts/tar-split
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/vbatts/tar-split
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: gomod
- dependency-name: github.com/vbatts/tar-split
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 20:39:19 +00:00
Kohei Tokunaga 9d29bf446a
Merge pull request #1946 from containerd/dependabot/github_actions/golangci/golangci-lint-action-6.2.0
build(deps): bump golangci/golangci-lint-action from 6.1.1 to 6.2.0
2025-01-18 12:32:58 +09:00
Kohei Tokunaga e20fe9f673
Merge pull request #1943 from containerd/dependabot/github_actions/docker/build-push-action-6.12.0
build(deps): bump docker/build-push-action from 6.11.0 to 6.12.0
2025-01-17 12:09:31 +09:00
dependabot[bot] 4a2a710409
build(deps): bump golangci/golangci-lint-action from 6.1.1 to 6.2.0
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.1.1 to 6.2.0.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.1.1...v6.2.0)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-16 20:51:37 +00:00
dependabot[bot] 6c40179c93
build(deps): bump docker/build-push-action from 6.11.0 to 6.12.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.11.0 to 6.12.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.11.0...v6.12.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-15 15:15:28 +00:00
Kohei Tokunaga e1de8d4da6
Merge pull request #1941 from djdongjin/dependabot-go-fallback-group
Create a dependabot group for all go deps
2025-01-16 00:13:36 +09:00
Kohei Tokunaga c309defb0e
Merge pull request #1942 from thaJeztah/gomod_zero
*/go.mod: use go1.22.0
2025-01-15 23:07:53 +09:00
Sebastiaan van Stijn b05c75e8c9
*/go.mod: use go1.22.0
Noticed that 985b021b41 caused buildkit
to have to update its go.mod to go1.22.7, and we're trying to keep
it stable at 1.22.0 as minimum.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-15 13:19:06 +01:00
Jin Dong 9d2951d82c Create a dependabot group for all go deps
Dependabot seems to only update a dep in all go modoules,
if it belongs to a group.

This new group will cover all deps that are not part of
an existing group, so they get updated in all go.mod.

I think this will help avoid issues like
https://github.com/containerd/stargz-snapshotter/pull/1939

Signed-off-by: Jin Dong <djdongjin95@gmail.com>
2025-01-14 23:15:04 -05:00
Akihiro Suda 8c9ecb7cd3
Merge pull request #1938 from ktock/golangci-lint-1.63.4
CI: golangci-lint v1.63.4
2025-01-15 11:21:24 +09:00
Kohei Tokunaga 723f610ce0
Merge pull request #1939 from ktock/docker-cli-27.5.0
go.mod: bump github.com/docker/cli to 27.5.0+incompatible
2025-01-15 11:08:49 +09:00
Kohei Tokunaga c665b3a9a7
Merge pull request #1936 from thaJeztah/containerd_2.0.2_and_downgrade_diff
go.mod: update github.com/containerd/containerd v2.0.2
2025-01-15 11:08:26 +09:00
Kohei Tokunaga 26081a6bb6
golangci: disable redefines-builtin-id in revive
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-01-15 10:25:57 +09:00
Sebastiaan van Stijn 32573d2947
go.mod: update github.com/containerd/containerd v2.0.2
Also downgrade github.com/davecgh/go-spew and
github.com/pmezard/go-difflib back to tagged releases.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-15 02:14:35 +01:00
Kohei Tokunaga 8f249479bb
go.mod: bump github.com/docker/cli to 27.5.0+incompatible
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-01-15 10:10:51 +09:00
Kohei Tokunaga 7db3c42ff0
CI: golangci-lint v1.63.4
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-01-15 10:08:29 +09:00
Kohei Tokunaga 37a436d50c
Merge pull request #1933 from containerd/dependabot/go_modules/google-golang-1db3f4dd3b
build(deps): bump the google-golang group across 3 directories with 1 update
2025-01-14 10:34:48 +09:00
Kohei Tokunaga 5e3411769a
Merge pull request #1934 from containerd/dependabot/go_modules/containerd-897ab735bc
build(deps): bump the containerd group across 3 directories with 2 updates
2025-01-14 10:34:28 +09:00
dependabot[bot] cc90435e1b
build(deps): bump the containerd group across 3 directories with 2 updates
Bumps the containerd group with 2 updates in the / directory: [github.com/containerd/platforms](https://github.com/containerd/platforms) and [github.com/containerd/go-cni](https://github.com/containerd/go-cni).
Bumps the containerd group with 2 updates in the /cmd directory: [github.com/containerd/platforms](https://github.com/containerd/platforms) and [github.com/containerd/go-cni](https://github.com/containerd/go-cni).
Bumps the containerd group with 1 update in the /ipfs directory: [github.com/containerd/platforms](https://github.com/containerd/platforms).


Updates `github.com/containerd/platforms` from 1.0.0-rc.0 to 1.0.0-rc.1
- [Release notes](https://github.com/containerd/platforms/releases)
- [Commits](https://github.com/containerd/platforms/compare/v1.0.0-rc.0...v1.0.0-rc.1)

Updates `github.com/containerd/go-cni` from 1.1.11 to 1.1.12
- [Release notes](https://github.com/containerd/go-cni/releases)
- [Commits](https://github.com/containerd/go-cni/compare/v1.1.11...v1.1.12)

Updates `github.com/containerd/platforms` from 1.0.0-rc.0 to 1.0.0-rc.1
- [Release notes](https://github.com/containerd/platforms/releases)
- [Commits](https://github.com/containerd/platforms/compare/v1.0.0-rc.0...v1.0.0-rc.1)

Updates `github.com/containerd/go-cni` from 1.1.11 to 1.1.12
- [Release notes](https://github.com/containerd/go-cni/releases)
- [Commits](https://github.com/containerd/go-cni/compare/v1.1.11...v1.1.12)

Updates `github.com/containerd/platforms` from 1.0.0-rc.0 to 1.0.0-rc.1
- [Release notes](https://github.com/containerd/platforms/releases)
- [Commits](https://github.com/containerd/platforms/compare/v1.0.0-rc.0...v1.0.0-rc.1)

---
updated-dependencies:
- dependency-name: github.com/containerd/platforms
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/go-cni
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/platforms
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/go-cni
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
- dependency-name: github.com/containerd/platforms
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: containerd
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-13 20:39:01 +00:00
dependabot[bot] 0e94caea39
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.69.2 to 1.69.4
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.2...v1.69.4)

Updates `google.golang.org/grpc` from 1.69.2 to 1.69.4
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.2...v1.69.4)

Updates `google.golang.org/grpc` from 1.69.2 to 1.69.4
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.2...v1.69.4)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-13 20:38:51 +00:00
Kohei Tokunaga a17a103f00
Merge pull request #1927 from containerd/dependabot/go_modules/google-golang-779ae39496
build(deps): bump the google-golang group across 3 directories with 1 update
2025-01-13 23:56:01 +09:00
dependabot[bot] f7eaa739b0
build(deps): bump the google-golang group across 3 directories with 1 update
Bumps the google-golang group with 1 update in the / directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /cmd directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).
Bumps the google-golang group with 1 update in the /ipfs directory: [google.golang.org/grpc](https://github.com/grpc/grpc-go).


Updates `google.golang.org/grpc` from 1.68.0 to 1.69.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.68.0...v1.69.2)

Updates `google.golang.org/grpc` from 1.68.0 to 1.69.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.68.0...v1.69.2)

Updates `google.golang.org/grpc` from 1.68.0 to 1.69.2
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.68.0...v1.69.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: google-golang
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: google-golang
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-11 22:55:02 +00:00
Kohei Tokunaga 466a8f6e60
Merge pull request #1926 from containerd/dependabot/go_modules/golang-x-0255f1edc2
build(deps): bump the golang-x group across 3 directories with 1 update
2025-01-12 07:53:45 +09:00
Kohei Tokunaga 0aebed85a2
Merge pull request #1930 from containerd/dependabot/go_modules/ipfs/github.com/multiformats/go-multiaddr-0.14.0
build(deps): bump github.com/multiformats/go-multiaddr from 0.13.0 to 0.14.0 in /ipfs
2025-01-12 07:53:10 +09:00
Kohei Tokunaga e61da34ad6
Merge pull request #1932 from containerd/dependabot/github_actions/docker/build-push-action-6.11.0
build(deps): bump docker/build-push-action from 6.10.0 to 6.11.0
2025-01-11 21:06:49 +09:00
dependabot[bot] 620cbe15fd
build(deps): bump the golang-x group across 3 directories with 1 update
Bumps the golang-x group with 1 update in the / directory: [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 1 update in the /cmd directory: [golang.org/x/sys](https://github.com/golang/sys).
Bumps the golang-x group with 1 update in the /ipfs directory: [golang.org/x/sys](https://github.com/golang/sys).


Updates `golang.org/x/sys` from 0.28.0 to 0.29.0
- [Commits](https://github.com/golang/sys/compare/v0.28.0...v0.29.0)

Updates `golang.org/x/sys` from 0.28.0 to 0.29.0
- [Commits](https://github.com/golang/sys/compare/v0.28.0...v0.29.0)

Updates `golang.org/x/sys` from 0.28.0 to 0.29.0
- [Commits](https://github.com/golang/sys/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: golang-x
- dependency-name: golang.org/x/sys
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: golang-x
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-08 21:08:09 +00:00
dependabot[bot] b8a2960e50
build(deps): bump docker/build-push-action from 6.10.0 to 6.11.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.10.0 to 6.11.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.10.0...v6.11.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-08 20:04:15 +00:00
Kohei Tokunaga 6b0021f2b4
Merge pull request #1923 from wswsmao/passthrough
fuse passthrough: fix oom when running huge images
2025-01-08 16:15:56 +09:00
abushwang 331932408a fuse passthrough: fix oom when running huge images
Signed-off-by: abushwang <abushwangs@gmail.com>
2025-01-08 14:09:21 +08:00
Kohei Tokunaga 928a4dd771
Merge pull request #1905 from wswsmao/main
fusemanager: fix container fail after ttl timeout in detach mode
2025-01-07 14:36:25 +09:00
dependabot[bot] 5555c06cb0
build(deps): bump github.com/multiformats/go-multiaddr in /ipfs
Bumps [github.com/multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr) from 0.13.0 to 0.14.0.
- [Release notes](https://github.com/multiformats/go-multiaddr/releases)
- [Commits](https://github.com/multiformats/go-multiaddr/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: github.com/multiformats/go-multiaddr
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-07 01:48:05 +00:00
abushwang 61ed6ff62c fusemanager: fix container fail after ttl timeout in detach mode
Signed-off-by: abushwang <abushwangs@gmail.com>
2025-01-07 09:46:28 +08:00
Kohei Tokunaga 3cbe35f1c9
Merge pull request #1920 from djdongjin/update-dependabot
Update gomod dependabot to use directories
2025-01-07 10:46:15 +09:00
Jin Dong 24020d4d09 Update gomod dependabot to use directories
Signed-off-by: Jin Dong <djdongjin95@gmail.com>
2025-01-06 13:59:17 +00:00
Akihiro Suda db7c74e0d2
Merge pull request #1922 from ktock/fixci-a
CI: Fix some tests don't run
2025-01-06 21:47:09 +09:00
Kohei Tokunaga 054b5aee83
Ensure task is started before signal-related operations
This is needed to avoid a race on
github.com/containerd/containerd/v2/client.(*task).Pid()

Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-01-06 15:50:56 +09:00
Kohei Tokunaga fbdc6d36e2
CI: Fix some tests don't run
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2025-01-06 15:29:37 +09:00
Kohei Tokunaga d8470f9f90
Merge pull request #1921 from djdongjin/remove-hashicorp-multierror
replace harshicorp/multierror with errors.Join
2025-01-06 15:18:45 +09:00
Jin Dong d81ec67409 replace harshicorp/multierror with errors.Join
Signed-off-by: Jin Dong <djdongjin95@gmail.com>
2025-01-06 02:27:24 +00:00
Akihiro Suda 394fdcd073
Merge pull request #1913 from ktock/containerd-v2-test
CI: Re-enable builtin tests
2025-01-05 23:59:18 +09:00
Akihiro Suda a1c6c6f7ef
Merge pull request #1904 from ktock/deps202412
go.mod: bump up dependencies
2025-01-05 23:58:52 +09:00
Kohei Tokunaga 9241431348
test: use containerd client instead of transfer service
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-12-23 11:41:37 +09:00
Kohei Tokunaga c424276509
Merge pull request #1912 from wswsmao/fm_test
fuse-manager: add tests
2024-12-19 13:20:06 +09:00
abushwang 7efeccc83d fuse-manager: add tests
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-12-19 11:22:23 +08:00
Kohei Tokunaga 8556da2ddf
CI: Re-enable builtin tests
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-12-17 22:43:59 +09:00
Kohei Tokunaga 4ce034ffdf
go.mod: bump up dependencies
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-12-17 22:00:18 +09:00
Kohei Tokunaga 4e10317ed8
Merge pull request #1892 from wswsmao/main
Add fuse-manager
2024-12-13 21:07:09 +09:00
abushwang ce7fc7b103 Add fuse-manager
Signed-off-by: abushwang <abushwangs@gmail.com>
Co-authored-by: Zuti He <ilyeeelihe@gmail.com>
2024-12-13 17:07:54 +08:00
Kohei Tokunaga ff392c138a
Merge pull request #1875 from containerd/dependabot/github_actions/docker/build-push-action-6.10.0
build(deps): bump docker/build-push-action from 6.9.0 to 6.10.0
2024-12-06 10:11:48 +09:00
Akihiro Suda 02793c182d
Merge pull request #1885 from ktock/fix-zstd-error-carry
[Carry #1847] Fix zstd:chunked converter error on duplicated blobs
2024-12-04 23:56:43 +09:00
Kohei Tokunaga 61a30ba662
Rely on OpenWriter for retrying opening writer
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-12-04 10:44:46 +09:00
Kohei Tokunaga a24c5ab6e1
Rely on contaienrd's GC for cleanup of temporary content
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
Co-authored-by: apostasie <spam_blackhole@farcloser.world>
2024-12-04 10:44:27 +09:00
Kohei Tokunaga 06052fde24
Merge pull request #1884 from wswsmao/main
snapshots: add metadata.db for serve cleanup
2024-12-03 20:56:34 +09:00
abushwang 49aba3abb4 snapshots: add metadata.db for serve cleanup
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-12-03 15:33:05 +08:00
Kohei Tokunaga a6894ec3fb
Merge pull request #1881 from wswsmao/main
fuse passthrough: prefetchEntireFile just retry once to avoid exception stuck
2024-12-02 22:38:06 +09:00
abushwang 9b54e47bdd fuse passthrough: prefetchEntireFile just retry once to avoid exception stuck
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-12-02 15:31:58 +08:00
Kohei Tokunaga 56c7b0f27b
Merge pull request #1876 from wswsmao/main
fuse passthrough: fix cache files closed by lru in passthrough model
2024-11-27 21:34:06 +09:00
abushwang 1da63ca0fd fuse passthrough: fix cache files closed by lru in passthrough model
In passthough model, close will be toke over by go-fuse, so file.Close is unnecessary

Signed-off-by: abushwang <abushwangs@gmail.com>
2024-11-27 14:11:33 +08:00
dependabot[bot] d80a847063
build(deps): bump docker/build-push-action from 6.9.0 to 6.10.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.9.0 to 6.10.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6.9.0...v6.10.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-26 20:40:02 +00:00
Kohei Tokunaga efb9325299
Merge pull request #1874 from wswsmao/main
fuse passthrough: fix PassthroughFd return wrong num to go-fuse
2024-11-25 21:34:23 +09:00
abushwang a0de1966c9 fuse passthrough: fix PassthroughFd return wrong num in no passthrough model
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-11-25 17:49:13 +08:00
Kohei Tokunaga 1ce6fa7480
Merge pull request #1870 from wswsmao/doc
fuse passthrough: add doc to introduce its usage
2024-11-21 14:14:01 +09:00
abushwang bbd984f9f0 fuse passthrough: add doc to introduce its usage
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-11-21 11:56:25 +08:00
Kohei Tokunaga 2a280d6b2b
Merge pull request #1868 from wswsmao/passthrough
Add FUSE Passthrough Support in Stargz-Snapshotter #1867
2024-11-21 11:50:36 +09:00
abushwang d16d0655fd fuse passthrough: fix some review comments
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-11-21 09:40:29 +08:00
abushwang 39a2e55a8b fuse: add kernel fuse passthrough support check
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-11-19 13:02:52 +08:00
abushwang 71930d7767 fuse: support passthrough mode
Signed-off-by: abushwang <abushwangs@gmail.com>
2024-11-19 10:19:02 +08:00
Kohei Tokunaga 946a04dda7
Merge pull request #1860 from ktock/record-out-docs
docs: document `--record-out` of `ctr-remote optimize`
2024-11-14 11:26:23 +09:00
Kohei Tokunaga 7d3230e1f5
Merge pull request #1864 from ktock/prepare-v0.16.1
Prepare for  v0.16.1
2024-11-14 09:35:01 +09:00
Kohei Tokunaga 9f207c4bb0
Merge pull request #1863 from ktock/gomodversion
go.mod : prevernt go upgraded to 1.23
2024-11-14 09:10:49 +09:00
Kohei Tokunaga 96bea0a5b2
Prepare for v0.16.1
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-11-14 08:38:15 +09:00
Kohei Tokunaga 985b021b41
go.mod : prevernt go upgraded to 1.23
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-11-14 08:16:27 +09:00
Kohei Tokunaga dad51ec506
docs: document `--record-out` of `ctr-remote optimize`
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2024-11-14 03:56:29 +09:00
96 changed files with 5147 additions and 1450 deletions

View File

@ -3,30 +3,43 @@ updates:
# Automatic upgrade for go modules. # Automatic upgrade for go modules.
- package-ecosystem: "gomod" - package-ecosystem: "gomod"
directory: "/" directories:
- "/estargz"
- "/ipfs"
- "/"
- "/cmd"
schedule: schedule:
interval: "daily" interval: "daily"
ignore: ignore:
# We upgrade this manually on each release # We upgrade this manually on each release
- dependency-name: "github.com/containerd/stargz-snapshotter/estargz" - dependency-name: "github.com/containerd/stargz-snapshotter/estargz"
groups:
# Automatic upgrade for go modules of estargz package. golang-x:
- package-ecosystem: "gomod" patterns:
directory: "/estargz" - "golang.org/x/*"
schedule: google-golang:
interval: "daily" patterns:
- "google.golang.org/*"
# Automatic upgrade for go modules of ipfs package. containerd:
- package-ecosystem: "gomod" patterns:
directory: "/ipfs" - "github.com/containerd/*"
schedule: opencontainers:
interval: "daily" patterns:
- "github.com/opencontainers/*"
# Automatic upgrade for go modules of cmd package. k8s:
- package-ecosystem: "gomod" patterns:
directory: "/cmd" - "k8s.io/*"
schedule: gomod:
interval: "daily" # this pattern covers all go dependencies that are not in
# the above groups. dependabot doesn't seem to update sub-modules if
# a dependency doesn't belong to a group, so we define this group
# explicitly.
exclude-patterns:
- "golang.org/x/*"
- "google.golang.org/*"
- "github.com/containerd/*"
- "github.com/opencontainers/*"
- "k8s.io/*"
# Automatic upgrade for base images used in the Dockerfile # Automatic upgrade for base images used in the Dockerfile
- package-ecosystem: "docker" - package-ecosystem: "docker"

View File

@ -3,6 +3,7 @@ on:
push: push:
tags: tags:
- 'v*' - 'v*'
pull_request:
env: env:
REGISTRY: ghcr.io REGISTRY: ghcr.io
@ -32,10 +33,19 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
image: tonistiigi/binfmt:qemu-v7.0.0-28
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6.9.0 uses: docker/build-push-action@v6.18.0
with: with:
context: . context: .
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64

View File

@ -17,8 +17,7 @@ on:
env: env:
DOCKER_BUILDKIT: 1 DOCKER_BUILDKIT: 1
# Temporary disable contaienrd main branch test and migrate to containerd v2 after it's released. DOCKER_BUILD_ARGS: --build-arg=CONTAINERD_VERSION=main # do tests with the latest containerd
# DOCKER_BUILD_ARGS: --build-arg=CONTAINERD_VERSION=main # do tests with the latest containerd
jobs: jobs:
integration: integration:
@ -93,7 +92,7 @@ jobs:
steps: steps:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: '1.23.x' go-version: '1.24.x'
- name: Install k3d - name: Install k3d
run: | run: |
wget -q -O - https://raw.githubusercontent.com/rancher/k3d/v5.6.3/install.sh | bash wget -q -O - https://raw.githubusercontent.com/rancher/k3d/v5.6.3/install.sh | bash

View File

@ -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

View File

@ -38,11 +38,11 @@ jobs:
fetch-depth: '0' fetch-depth: '0'
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: '1.23.x' go-version: '1.24.x'
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v6.1.1 uses: golangci/golangci-lint-action@v8.0.0
with: with:
version: v1.61.0 version: v2.1
args: --verbose --timeout=10m args: --verbose --timeout=10m
working-directory: ${{ matrix.targetdir }} working-directory: ${{ matrix.targetdir }}
@ -52,18 +52,37 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Temporary disable containerd main branch test and migrate to containerd v2 after it's released. buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
# buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
buildargs: [""]
builtin: ["true", "false"] builtin: ["true", "false"]
metadata-store: ["memory", "db"] metadata-store: ["memory", "db"]
fuse-passthrough: ["true", "false"]
fuse-manager: ["true", "false"]
transfer-service: ["true", "false"]
exclude: exclude:
# - buildargs: "" - buildargs: ""
# builtin: "true" builtin: "true"
- metadata-store: "db" - metadata-store: "db"
builtin: "true" builtin: "true"
# - metadata-store: "db" - metadata-store: "db"
# buildargs: "--build-arg=CONTAINERD_VERSION=main" buildargs: "--build-arg=CONTAINERD_VERSION=main"
- fuse-passthrough: "true"
builtin: "true"
- fuse-passthrough: "true"
buildargs: "--build-arg=CONTAINERD_VERSION=main"
- fuse-passthrough: "true"
metadata-store: "db"
- fuse-manager: "true"
builtin: "true"
- fuse-manager: "true"
buildargs: "--build-arg=CONTAINERD_VERSION=main"
- transfer-service: "true"
buildargs: "--build-arg=CONTAINERD_VERSION=main"
- transfer-service: "true"
builtin: "true"
- transfer-service: "true"
metadata-store: "db"
- transfer-service: "true"
fuse-passthrough: "true"
steps: steps:
- name: Install htpasswd for setting up private registry - name: Install htpasswd for setting up private registry
run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils
@ -73,6 +92,9 @@ jobs:
DOCKER_BUILD_ARGS: ${{ matrix.buildargs }} DOCKER_BUILD_ARGS: ${{ matrix.buildargs }}
BUILTIN_SNAPSHOTTER: ${{ matrix.builtin }} BUILTIN_SNAPSHOTTER: ${{ matrix.builtin }}
METADATA_STORE: ${{ matrix.metadata-store }} METADATA_STORE: ${{ matrix.metadata-store }}
FUSE_PASSTHROUGH: ${{ matrix.fuse-passthrough }}
FUSE_MANAGER: ${{ matrix.fuse-manager }}
TRANSFER_SERVICE: ${{ matrix.transfer-service }}
run: make integration run: make integration
test-optimize: test-optimize:
@ -81,9 +103,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Temporary disable contaienrd main branch test and migrate to containerd v2 after it's released. buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
# buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
buildargs: [""]
steps: steps:
- name: Install htpasswd for setting up private registry - name: Install htpasswd for setting up private registry
run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils
@ -99,13 +119,11 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Temporary disable contaienrd main branch test and migrate to containerd v2 after it's released. buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
# buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
buildargs: [""]
builtin: ["true", "false"] builtin: ["true", "false"]
# exclude: exclude:
# - buildargs: "" - buildargs: ""
# builtin: "true" builtin: "true"
steps: steps:
- name: Install htpasswd for setting up private registry - name: Install htpasswd for setting up private registry
run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils
@ -122,13 +140,11 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Temporary disable contaienrd main branch test and migrate to containerd v2 after it's released. buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
# buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
buildargs: [""]
builtin: ["true", "false"] builtin: ["true", "false"]
# exclude: exclude:
# - buildargs: "" - buildargs: ""
# builtin: "true" builtin: "true"
steps: steps:
- name: Install htpasswd for setting up private registry - name: Install htpasswd for setting up private registry
run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils run: sudo apt-get update -y && sudo apt-get --no-install-recommends install -y apache2-utils
@ -145,18 +161,37 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Temporary disable contaienrd main branch test and migrate to containerd v2 after it's released. buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
# buildargs: ["", "--build-arg=CONTAINERD_VERSION=main"] # released version & main version
buildargs: [""]
builtin: ["true", "false"] builtin: ["true", "false"]
metadata-store: ["memory", "db"] metadata-store: ["memory", "db"]
fuse-passthrough: ["true", "false"]
fuse-manager: ["true", "false"]
transfer-service: ["true", "false"]
exclude: exclude:
# - buildargs: "" - buildargs: ""
# builtin: "true" builtin: "true"
- metadata-store: "db" - metadata-store: "db"
builtin: "true" builtin: "true"
# - metadata-store: "db" - metadata-store: "db"
# buildargs: "--build-arg=CONTAINERD_VERSION=main" buildargs: "--build-arg=CONTAINERD_VERSION=main"
- fuse-passthrough: "true"
builtin: "true"
- fuse-passthrough: "true"
buildargs: "--build-arg=CONTAINERD_VERSION=main"
- fuse-passthrough: "true"
metadata-store: "db"
- fuse-manager: "true"
builtin: "true"
- fuse-manager: "true"
buildargs: "--build-arg=CONTAINERD_VERSION=main"
- transfer-service: "true"
buildargs: "--build-arg=CONTAINERD_VERSION=main"
- transfer-service: "true"
builtin: "true"
- transfer-service: "true"
metadata-store: "db"
- transfer-service: "true"
fuse-passthrough: "true"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Validate containerd through CRI - name: Validate containerd through CRI
@ -164,6 +199,9 @@ jobs:
DOCKER_BUILD_ARGS: ${{ matrix.buildargs }} DOCKER_BUILD_ARGS: ${{ matrix.buildargs }}
BUILTIN_SNAPSHOTTER: ${{ matrix.builtin }} BUILTIN_SNAPSHOTTER: ${{ matrix.builtin }}
METADATA_STORE: ${{ matrix.metadata-store }} METADATA_STORE: ${{ matrix.metadata-store }}
FUSE_PASSTHROUGH: ${{ matrix.fuse-passthrough }}
FUSE_MANAGER: ${{ matrix.fuse-manager }}
TRANSFER_SERVICE: ${{ matrix.transfer-service }}
run: make test-cri-containerd run: make test-cri-containerd
test-cri-cri-o: test-cri-cri-o:
@ -203,7 +241,7 @@ jobs:
steps: steps:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: '1.23.x' go-version: '1.24.x'
- name: Install k3d - name: Install k3d
run: | run: |
wget -q -O - https://raw.githubusercontent.com/rancher/k3d/v5.6.3/install.sh | bash wget -q -O - https://raw.githubusercontent.com/rancher/k3d/v5.6.3/install.sh | bash
@ -233,7 +271,7 @@ jobs:
steps: steps:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: '1.23.x' go-version: '1.24.x'
- name: Install k3d - name: Install k3d
run: | run: |
wget -q -O - https://raw.githubusercontent.com/rancher/k3d/v5.6.3/install.sh | bash wget -q -O - https://raw.githubusercontent.com/rancher/k3d/v5.6.3/install.sh | bash
@ -278,14 +316,34 @@ jobs:
steps: steps:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: '1.23.x' go-version: '1.24.x'
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
path: src/github.com/containerd/stargz-snapshotter path: src/github.com/containerd/stargz-snapshotter
fetch-depth: 25 fetch-depth: 25
- uses: containerd/project-checks@v1.1.0 - uses: containerd/project-checks@v1.2.2
with: with:
working-directory: src/github.com/containerd/stargz-snapshotter working-directory: src/github.com/containerd/stargz-snapshotter
# go-licenses-ignore is set because go-licenses cannot correctly detect the license of the following packages:
# * estargz packages: Apache-2.0 and BSD-3-Clause dual license
# (https://github.com/containerd/stargz-snapshotter/blob/main/NOTICE.md)
#
# The list of the CNCF-approved licenses can be found here:
# https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md
#
# hashicorp packages: MPL-2.0
# (https://github.com/hashicorp/go-cleanhttp/blob/master/LICENSE,
# https://github.com/hashicorp/go-retryablehttp/blob/master/LICENSE)
# Note: MPL-2.0 is not in the CNCF-approved licenses list, but these packages are allowed as exceptions.
# See CNCF licensing exceptions:
# https://github.com/cncf/foundation/blob/main/license-exceptions/CNCF-licensing-exceptions.csv
go-licenses-ignore: |
github.com/containerd/stargz-snapshotter/estargz
github.com/containerd/stargz-snapshotter/estargz/errorutil
github.com/containerd/stargz-snapshotter/estargz/externaltoc
github.com/containerd/stargz-snapshotter/estargz/zstdchunked
github.com/hashicorp/go-cleanhttp
github.com/hashicorp/go-retryablehttp
- name: Check proto generated code - name: Check proto generated code
run: make validate-generated run: make validate-generated
working-directory: src/github.com/containerd/stargz-snapshotter working-directory: src/github.com/containerd/stargz-snapshotter

View File

@ -1,41 +1,54 @@
# This is applied to `estargz` submodule as well. version: "2"
# https://golangci-lint.run/usage/configuration#config-file
linters: linters:
enable: enable:
- depguard # Checks for imports that shouldn't be used. - depguard
- staticcheck
- unconvert
- gofmt
- goimports
- revive
- ineffassign
- govet
- unused
- misspell - misspell
- revive
- unconvert
disable: disable:
- errcheck - errcheck
settings:
linters-settings: depguard:
depguard: rules:
main:
deny:
- pkg: github.com/containerd/containerd/errdefs
desc: The containerd errdefs package was migrated to a separate module. Use github.com/containerd/errdefs instead.
- pkg: github.com/containerd/containerd/log
desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead.
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules: rules:
main: - linters:
deny: - revive
- pkg: "github.com/containerd/containerd/errdefs" text: unused-parameter
desc: The containerd errdefs package was migrated to a separate module. Use github.com/containerd/errdefs instead. - linters:
- pkg: "github.com/containerd/containerd/log" - revive
desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead. text: redefines-builtin-id
paths:
run: - docs
deadline: 4m - images
- out
issues: - script
exclude-rules: - third_party$
- linters: - builtin$
- revive - examples$
text: "unused-parameter" formatters:
exclude-dirs: enable:
- docs - gofmt
- images - goimports
- out exclusions:
- script generated: lax
paths:
- docs
- images
- out
- script
- third_party$
- builtin$
- examples$

View File

@ -12,46 +12,45 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
ARG CONTAINERD_VERSION=v2.0.0 ARG CONTAINERD_VERSION=v2.1.3
ARG RUNC_VERSION=v1.2.1 ARG RUNC_VERSION=v1.3.0
ARG CNI_PLUGINS_VERSION=v1.6.0 ARG CNI_PLUGINS_VERSION=v1.7.1
# TODO: support v2 ARG NERDCTL_VERSION=2.1.3
ARG NERDCTL_VERSION=1.7.7
ARG PODMAN_VERSION=v5.2.5 ARG PODMAN_VERSION=v5.5.2
ARG CRIO_VERSION=v1.31.2 ARG CRIO_VERSION=v1.33.2
ARG CONMON_VERSION=v2.1.12 ARG CONMON_VERSION=v2.1.13
ARG COMMON_VERSION=v0.61.0 ARG COMMON_VERSION=v0.63.0
ARG CRIO_TEST_PAUSE_IMAGE_NAME=registry.k8s.io/pause:3.6 ARG CRIO_TEST_PAUSE_IMAGE_NAME=registry.k8s.io/pause:3.6
ARG NETAVARK_VERSION=v1.13.0 ARG NETAVARK_VERSION=v1.15.2
ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1
ARG SLIRP4NETNS_VERSION=v1.3.1 ARG SLIRP4NETNS_VERSION=v1.3.3
ARG PAUSE_IMAGE_NAME_TEST=registry.k8s.io/pause:3.10 ARG PAUSE_IMAGE_NAME_TEST=registry.k8s.io/pause:3.10.1
# Used in CI # Used in CI
ARG CRI_TOOLS_VERSION=v1.30.0 ARG CRI_TOOLS_VERSION=v1.30.1
# Legacy builder that doesn't support TARGETARCH should set this explicitly using --build-arg. # Legacy builder that doesn't support TARGETARCH should set this explicitly using --build-arg.
# If TARGETARCH isn't supported by the builder, the default value is "amd64". # If TARGETARCH isn't supported by the builder, the default value is "amd64".
FROM golang:1.23-bullseye AS golang-base FROM golang:1.24-bullseye AS golang-base
# Build containerd # Build containerd
FROM golang-base AS containerd-dev FROM --platform=$BUILDPLATFORM golang:1.24-bullseye AS containerd-dev
ARG CONTAINERD_VERSION ARG CONTAINERD_VERSION
RUN apt-get update -y && apt-get install -y libbtrfs-dev libseccomp-dev && \ ARG TARGETARCH
git clone -b ${CONTAINERD_VERSION} --depth 1 \ RUN git clone -b ${CONTAINERD_VERSION} --depth 1 \
https://github.com/containerd/containerd $GOPATH/src/github.com/containerd/containerd && \ https://github.com/containerd/containerd $GOPATH/src/github.com/containerd/containerd && \
cd $GOPATH/src/github.com/containerd/containerd && \ cd $GOPATH/src/github.com/containerd/containerd && \
make && DESTDIR=/out/ PREFIX= make install GOARCH=$TARGETARCH make && DESTDIR=/out/ PREFIX= make install
# Build containerd with builtin stargz snapshotter # Build containerd with builtin stargz snapshotter
FROM golang-base AS containerd-snapshotter-dev FROM --platform=$BUILDPLATFORM golang:1.24-bullseye AS containerd-snapshotter-dev
ARG CONTAINERD_VERSION ARG CONTAINERD_VERSION
ARG TARGETARCH
COPY . $GOPATH/src/github.com/containerd/stargz-snapshotter COPY . $GOPATH/src/github.com/containerd/stargz-snapshotter
RUN apt-get update -y && apt-get install -y libbtrfs-dev libseccomp-dev && \ RUN git clone -b ${CONTAINERD_VERSION} --depth 1 \
git clone -b ${CONTAINERD_VERSION} --depth 1 \
https://github.com/containerd/containerd $GOPATH/src/github.com/containerd/containerd && \ https://github.com/containerd/containerd $GOPATH/src/github.com/containerd/containerd && \
cd $GOPATH/src/github.com/containerd/containerd && \ cd $GOPATH/src/github.com/containerd/containerd && \
echo 'require github.com/containerd/stargz-snapshotter v0.0.0' >> go.mod && \ echo 'require github.com/containerd/stargz-snapshotter v0.0.0' >> go.mod && \
@ -66,21 +65,11 @@ RUN apt-get update -y && apt-get install -y libbtrfs-dev libseccomp-dev && \
echo 'replace github.com/containerd/stargz-snapshotter => '$GOPATH'/src/github.com/containerd/stargz-snapshotter' >> integration/client/go.mod && \ echo 'replace github.com/containerd/stargz-snapshotter => '$GOPATH'/src/github.com/containerd/stargz-snapshotter' >> integration/client/go.mod && \
echo 'replace github.com/containerd/stargz-snapshotter/estargz => '$GOPATH'/src/github.com/containerd/stargz-snapshotter/estargz' >> integration/client/go.mod ; \ echo 'replace github.com/containerd/stargz-snapshotter/estargz => '$GOPATH'/src/github.com/containerd/stargz-snapshotter/estargz' >> integration/client/go.mod ; \
fi && \ fi && \
if [ "$(echo -n ${CONTAINERD_VERSION} | head -c 4)" = "v1.7" ] ; then \
# containerd v1.7 doesn't support cri-api >= v0.28 which adds RuntimeConfig API
echo 'replace k8s.io/cri-api => k8s.io/cri-api v0.27.1' >> go.mod ; \
if [ -f api/go.mod ] ; then \
echo 'replace k8s.io/cri-api => k8s.io/cri-api v0.27.1' >> api/go.mod ; \
fi ; \
if [ -f integration/client/go.mod ] ; then \
echo 'replace k8s.io/cri-api => k8s.io/cri-api v0.27.1' >> integration/client/go.mod ; \
fi ; \
fi && \
echo 'package main \nimport _ "github.com/containerd/stargz-snapshotter/service/plugin"' > cmd/containerd/builtins_stargz_snapshotter.go && \ echo 'package main \nimport _ "github.com/containerd/stargz-snapshotter/service/plugin"' > cmd/containerd/builtins_stargz_snapshotter.go && \
make vendor && make && DESTDIR=/out/ PREFIX= make install make vendor && GOARCH=$TARGETARCH make && DESTDIR=/out/ PREFIX= make install
# Build runc # Build runc
FROM golang:1.23-bullseye AS runc-dev FROM golang:1.24-bullseye AS runc-dev
ARG RUNC_VERSION ARG RUNC_VERSION
RUN apt-get update -y && apt-get install -y libseccomp-dev && \ RUN apt-get update -y && apt-get install -y libseccomp-dev && \
git clone -b ${RUNC_VERSION} --depth 1 \ git clone -b ${RUNC_VERSION} --depth 1 \
@ -89,7 +78,7 @@ RUN apt-get update -y && apt-get install -y libseccomp-dev && \
make && make install PREFIX=/out/ make && make install PREFIX=/out/
# Build stargz snapshotter # Build stargz snapshotter
FROM golang-base AS snapshotter-dev FROM --platform=$BUILDPLATFORM golang:1.24-bullseye AS snapshotter-dev
ARG TARGETARCH ARG TARGETARCH
ARG GOARM ARG GOARM
ARG SNAPSHOTTER_BUILD_FLAGS ARG SNAPSHOTTER_BUILD_FLAGS
@ -98,7 +87,8 @@ COPY . $GOPATH/src/github.com/containerd/stargz-snapshotter
ARG CGO_ENABLED ARG CGO_ENABLED
RUN cd $GOPATH/src/github.com/containerd/stargz-snapshotter && \ RUN cd $GOPATH/src/github.com/containerd/stargz-snapshotter && \
PREFIX=/out/ GOARCH=${TARGETARCH:-amd64} GO_BUILD_FLAGS=${SNAPSHOTTER_BUILD_FLAGS} make containerd-stargz-grpc && \ PREFIX=/out/ GOARCH=${TARGETARCH:-amd64} GO_BUILD_FLAGS=${SNAPSHOTTER_BUILD_FLAGS} make containerd-stargz-grpc && \
PREFIX=/out/ GOARCH=${TARGETARCH:-amd64} GO_BUILD_FLAGS=${CTR_REMOTE_BUILD_FLAGS} make ctr-remote PREFIX=/out/ GOARCH=${TARGETARCH:-amd64} GO_BUILD_FLAGS=${CTR_REMOTE_BUILD_FLAGS} make ctr-remote && \
PREFIX=/out/ GOARCH=${TARGETARCH:-amd64} GO_BUILD_FLAGS=${CTR_REMOTE_BUILD_FLAGS} make stargz-fuse-manager
# Build stargz store # Build stargz store
FROM golang-base AS stargz-store-dev FROM golang-base AS stargz-store-dev
@ -122,7 +112,7 @@ RUN apt-get update -y && apt-get install -y libseccomp-dev libgpgme-dev && \
# Build CRI-O # Build CRI-O
# FROM golang-base AS cri-o-dev # FROM golang-base AS cri-o-dev
FROM golang:1.23-bullseye AS cri-o-dev FROM golang:1.24-bullseye AS cri-o-dev
ARG CRIO_VERSION ARG CRIO_VERSION
RUN apt-get update -y && apt-get install -y libseccomp-dev libgpgme-dev && \ RUN apt-get update -y && apt-get install -y libseccomp-dev libgpgme-dev && \
git clone https://github.com/cri-o/cri-o $GOPATH/src/github.com/cri-o/cri-o && \ git clone https://github.com/cri-o/cri-o $GOPATH/src/github.com/cri-o/cri-o && \
@ -256,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.30.0 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/ /
@ -297,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.30.0 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/ /

View File

@ -24,7 +24,7 @@ REVISION=$(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet
GO_BUILD_LDFLAGS ?= -s -w GO_BUILD_LDFLAGS ?= -s -w
GO_LD_FLAGS=-ldflags '$(GO_BUILD_LDFLAGS) -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) $(GO_EXTRA_LDFLAGS)' GO_LD_FLAGS=-ldflags '$(GO_BUILD_LDFLAGS) -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) $(GO_EXTRA_LDFLAGS)'
CMD=containerd-stargz-grpc ctr-remote stargz-store CMD=containerd-stargz-grpc ctr-remote stargz-store stargz-fuse-manager
CMD_BINARIES=$(addprefix $(PREFIX),$(CMD)) CMD_BINARIES=$(addprefix $(PREFIX),$(CMD))
@ -48,6 +48,9 @@ stargz-store: FORCE
stargz-store-helper: FORCE stargz-store-helper: FORCE
cd cmd/ ; GO111MODULE=$(GO111MODULE_VALUE) go build -o $(PREFIX)$@ $(GO_BUILD_FLAGS) $(GO_LD_FLAGS) -v ./stargz-store/helper cd cmd/ ; GO111MODULE=$(GO111MODULE_VALUE) go build -o $(PREFIX)$@ $(GO_BUILD_FLAGS) $(GO_LD_FLAGS) -v ./stargz-store/helper
stargz-fuse-manager: FORCE
cd cmd/ ; GO111MODULE=$(GO111MODULE_VALUE) go build -o $(PREFIX)$@ $(GO_BUILD_FLAGS) $(GO_LD_FLAGS) -v ./stargz-fuse-manager
check: check:
@echo "$@" @echo "$@"
@GO111MODULE=$(GO111MODULE_VALUE) $(shell go env GOPATH)/bin/golangci-lint run @GO111MODULE=$(GO111MODULE_VALUE) $(shell go env GOPATH)/bin/golangci-lint run

View File

@ -62,6 +62,8 @@ version = 2
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
# Use stargz snapshotter through CRI # Use stargz snapshotter through CRI
[plugins."io.containerd.grpc.v1.cri".containerd] [plugins."io.containerd.grpc.v1.cri".containerd]
@ -69,8 +71,6 @@ version = 2
disable_snapshot_annotations = false disable_snapshot_annotations = false
``` ```
**Note that `disable_snapshot_annotations = false` is required since containerd > v1.4.2**
You can try our [prebuilt](/Dockerfile) [KinD](https://github.com/kubernetes-sigs/kind) node image that contains the above configuration. You can try our [prebuilt](/Dockerfile) [KinD](https://github.com/kubernetes-sigs/kind) node image that contains the above configuration.
```console ```console

View File

@ -225,6 +225,9 @@ func Analyze(ctx context.Context, client *containerd.Client, ref string, opts ..
successCount++ successCount++
} }
}() }()
if err := task.Start(ctx); err != nil {
return "", err
}
if aOpts.terminal { if aOpts.terminal {
if err := tasks.HandleConsoleResize(ctx, task, con); err != nil { if err := tasks.HandleConsoleResize(ctx, task, con); err != nil {
log.G(ctx).WithError(err).Error("failed to resize console") log.G(ctx).WithError(err).Error("failed to resize console")
@ -233,9 +236,6 @@ func Analyze(ctx context.Context, client *containerd.Client, ref string, opts ..
sigc := commands.ForwardAllSignals(ctx, task) sigc := commands.ForwardAllSignals(ctx, task)
defer commands.StopCatch(sigc) defer commands.StopCatch(sigc)
} }
if err := task.Start(ctx); err != nil {
return "", err
}
// Wait until the task exit // Wait until the task exit
var status containerd.ExitStatus var status containerd.ExitStatus

View File

@ -17,6 +17,7 @@
package fanotify package fanotify
import ( import (
"errors"
"fmt" "fmt"
"os/exec" "os/exec"
"sync" "sync"
@ -24,7 +25,6 @@ import (
"time" "time"
"github.com/containerd/stargz-snapshotter/analyzer/fanotify/conn" "github.com/containerd/stargz-snapshotter/analyzer/fanotify/conn"
"github.com/hashicorp/go-multierror"
) )
// Fanotifier monitors "/" mountpoint of a new mount namespace and notifies all // Fanotifier monitors "/" mountpoint of a new mount namespace and notifies all
@ -59,14 +59,15 @@ func SpawnFanotifier(fanotifierBin string) (*Fanotifier, error) {
// Connect to the spawned fanotifier over stdio // Connect to the spawned fanotifier over stdio
conn: conn.NewClient(notifyR, notifyW, cmd.Process.Pid, 5*time.Second), conn: conn.NewClient(notifyR, notifyW, cmd.Process.Pid, 5*time.Second),
closeFunc: func() (allErr error) { closeFunc: func() error {
var errs []error
if err := notifyR.Close(); err != nil { if err := notifyR.Close(); err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
} }
if err := notifyW.Close(); err != nil { if err := notifyW.Close(); err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
} }
return return errors.Join(errs...)
}, },
}, nil }, nil
} }

View File

@ -68,7 +68,7 @@ func Serve(target string, r io.Reader, w io.Writer) error {
return fmt.Errorf("read fanotify fd: %w", err) return fmt.Errorf("read fanotify fd: %w", err)
} }
if event.Vers != unix.FANOTIFY_METADATA_VERSION { if event.Vers != unix.FANOTIFY_METADATA_VERSION {
return fmt.Errorf("Fanotify version mismatch %d(got) != %d(want)", return fmt.Errorf("fanotify version mismatch %d(got) != %d(want)",
event.Vers, unix.FANOTIFY_METADATA_VERSION) event.Vers, unix.FANOTIFY_METADATA_VERSION)
} }
if event.Fd < 0 { if event.Fd < 0 {

View File

@ -151,7 +151,7 @@ func (r *ImageRecorder) Record(name string) error {
} }
whDir := cleanEntryName(path.Join(path.Dir("/"+name), whiteoutOpaqueDir)) whDir := cleanEntryName(path.Join(path.Dir("/"+name), whiteoutOpaqueDir))
if _, ok := r.index[i][whDir]; ok { if _, ok := r.index[i][whDir]; ok {
return fmt.Errorf("Parent dir of %q is a deleted directory", name) return fmt.Errorf("parent dir of %q is a deleted directory", name)
} }
} }
if index < 0 { if index < 0 {

79
cache/cache.go vendored
View File

@ -18,6 +18,7 @@ package cache
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -26,7 +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"
"github.com/hashicorp/go-multierror" "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.
@ -82,6 +86,9 @@ type BlobCache interface {
type Reader interface { type Reader interface {
io.ReaderAt io.ReaderAt
Close() error Close() error
// If a blob is backed by a file, it should return *os.File so that it can be used for FUSE passthrough
GetReaderAt() io.ReaderAt
} }
// Writer enables the client to cache byte data. Commit() must be // Writer enables the client to cache byte data. Commit() must be
@ -94,7 +101,8 @@ type Writer interface {
} }
type cacheOpt struct { type cacheOpt struct {
direct bool direct bool
passThrough bool
} }
type Option func(o *cacheOpt) *cacheOpt type Option func(o *cacheOpt) *cacheOpt
@ -110,6 +118,15 @@ func Direct() Option {
} }
} }
// PassThrough option indicates whether to enable FUSE passthrough mode
// to improve local file read performance.
func PassThrough() Option {
return func(o *cacheOpt) *cacheOpt {
o.passThrough = true
return o
}
}
func NewDirectoryCache(directory string, config DirectoryCacheConfig) (BlobCache, error) { func NewDirectoryCache(directory string, config DirectoryCacheConfig) (BlobCache, error) {
if !filepath.IsAbs(directory) { if !filepath.IsAbs(directory) {
return nil, fmt.Errorf("dir cache path must be an absolute path; got %q", directory) return nil, fmt.Errorf("dir cache path must be an absolute path; got %q", directory)
@ -160,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
@ -175,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
@ -229,8 +248,22 @@ func (dc *directoryCache) Get(key string, opts ...Option) (Reader, error) {
// that won't be accessed immediately. // that won't be accessed immediately.
if dc.direct || opt.direct { if dc.direct || opt.direct {
return &reader{ return &reader{
ReaderAt: file, ReaderAt: file,
closeFunc: func() error { return file.Close() }, 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
// If "passThrough" option is specified, "direct" option also will
// be specified, so adding this branch here is enough
if opt.passThrough {
return nil
}
return file.Close()
},
}, nil }, nil
} }
@ -273,13 +306,20 @@ func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) {
// Commit the cache contents // Commit the cache contents
c := dc.cachePath(key) c := dc.cachePath(key)
if err := os.MkdirAll(filepath.Dir(c), os.ModePerm); err != nil { if err := os.MkdirAll(filepath.Dir(c), os.ModePerm); err != nil {
var allErr error var errs []error
if err := os.Remove(wip.Name()); err != nil { if err := os.Remove(wip.Name()); err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
} }
return multierror.Append(allErr, errs = append(errs, fmt.Errorf("failed to create cache directory %q: %w", c, err))
fmt.Errorf("failed to create cache directory %q: %w", c, err)) 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 {
@ -384,7 +424,7 @@ func (mc *MemoryCache) Get(key string, opts ...Option) (Reader, error) {
defer mc.mu.Unlock() defer mc.mu.Unlock()
b, ok := mc.Membuf[key] b, ok := mc.Membuf[key]
if !ok { if !ok {
return nil, fmt.Errorf("Missed cache: %q", key) return nil, fmt.Errorf("missed cache: %q", key)
} }
return &reader{bytes.NewReader(b.Bytes()), func() error { return nil }}, nil return &reader{bytes.NewReader(b.Bytes()), func() error { return nil }}, nil
} }
@ -414,6 +454,10 @@ type reader struct {
func (r *reader) Close() error { return r.closeFunc() } func (r *reader) Close() error { return r.closeFunc() }
func (r *reader) GetReaderAt() io.ReaderAt {
return r.ReaderAt
}
type writer struct { type writer struct {
io.WriteCloser io.WriteCloser
commitFunc func() error commitFunc func() error
@ -438,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
}

View File

@ -35,10 +35,10 @@ import (
"github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz"
"github.com/containerd/stargz-snapshotter/metadata" "github.com/containerd/stargz-snapshotter/metadata"
"github.com/goccy/go-json" "github.com/goccy/go-json"
"github.com/hashicorp/go-multierror"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/rs/xid" "github.com/rs/xid"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
errbolt "go.etcd.io/bbolt/errors"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@ -99,7 +99,7 @@ func NewReader(db *bolt.DB, sr *io.SectionReader, opts ...metadata.Option) (meta
rOpts.Telemetry.GetFooterLatency(start) rOpts.Telemetry.GetFooterLatency(start)
} }
var allErr error var errs []error
var tocR io.ReadCloser var tocR io.ReadCloser
var decompressor metadata.Decompressor var decompressor metadata.Decompressor
for _, d := range decompressors { for _, d := range decompressors {
@ -108,7 +108,7 @@ func NewReader(db *bolt.DB, sr *io.SectionReader, opts ...metadata.Option) (meta
maybeTocBytes := footer[:fOffset] maybeTocBytes := footer[:fOffset]
_, tocOffset, tocSize, err := d.ParseFooter(footer[fOffset:]) _, tocOffset, tocSize, err := d.ParseFooter(footer[fOffset:])
if err != nil { if err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
continue continue
} }
if tocOffset >= 0 && tocSize <= 0 { if tocOffset >= 0 && tocSize <= 0 {
@ -119,12 +119,14 @@ func NewReader(db *bolt.DB, sr *io.SectionReader, opts ...metadata.Option) (meta
} }
tocR, err = decompressTOC(d, sr, tocOffset, tocSize, maybeTocBytes, rOpts) tocR, err = decompressTOC(d, sr, tocOffset, tocSize, maybeTocBytes, rOpts)
if err != nil { if err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
continue continue
} }
decompressor = d decompressor = d
break break
} }
allErr := errors.Join(errs...)
if tocR == nil { if tocR == nil {
if allErr == nil { if allErr == nil {
return nil, fmt.Errorf("failed to get the reader of TOC: unknown") return nil, fmt.Errorf("failed to get the reader of TOC: unknown")
@ -222,7 +224,7 @@ func (r *reader) init(decompressedR io.Reader, rOpts metadata.Options) (retErr e
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
fsID := xid.New().String() fsID := xid.New().String()
if err := r.initRootNode(fsID); err != nil { if err := r.initRootNode(fsID); err != nil {
if errors.Is(err, bolt.ErrBucketExists) { if errors.Is(err, errbolt.ErrBucketExists) {
continue // try with another id continue // try with another id
} }
return fmt.Errorf("failed to initialize root node %q: %w", fsID, err) return fmt.Errorf("failed to initialize root node %q: %w", fsID, err)
@ -238,20 +240,22 @@ func (r *reader) init(decompressedR io.Reader, rOpts metadata.Options) (retErr e
if err != nil { if err != nil {
return err return err
} }
closeFunc := func() (closeErr error) { closeFunc := func() error {
name := f.Name() name := f.Name()
var errs []error
if err := f.Close(); err != nil { if err := f.Close(); err != nil {
closeErr = multierror.Append(closeErr, err) errs = append(errs, err)
} }
if err := os.Remove(name); err != nil { if err := os.Remove(name); err != nil {
closeErr = multierror.Append(closeErr, err) errs = append(errs, err)
} }
return return errors.Join(errs...)
} }
defer func() { defer func() {
if retErr != nil { if retErr != nil {
if err := closeFunc(); err != nil { if err := closeFunc(); err != nil {
retErr = multierror.Append(retErr, err) retErr = errors.Join(retErr, err)
return
} }
} }
}() }()

View File

@ -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) {

View File

@ -0,0 +1,80 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fsopts
import (
"context"
"fmt"
"io"
"path/filepath"
"github.com/containerd/log"
dbmetadata "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/db"
ipfs "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/ipfs"
"github.com/containerd/stargz-snapshotter/fs"
"github.com/containerd/stargz-snapshotter/metadata"
memorymetadata "github.com/containerd/stargz-snapshotter/metadata/memory"
bolt "go.etcd.io/bbolt"
)
type Config struct {
EnableIpfs bool
MetadataStore string
OpenBoltDB func(string) (*bolt.DB, error)
}
const (
memoryMetadataType = "memory"
dbMetadataType = "db"
)
func ConfigFsOpts(ctx context.Context, rootDir string, config *Config) ([]fs.Option, error) {
fsOpts := []fs.Option{fs.WithMetricsLogLevel(log.InfoLevel)}
if config.EnableIpfs {
fsOpts = append(fsOpts, fs.WithResolveHandler("ipfs", new(ipfs.ResolveHandler)))
}
mt, err := getMetadataStore(rootDir, config)
if err != nil {
return nil, fmt.Errorf("failed to configure metadata store: %w", err)
}
fsOpts = append(fsOpts, fs.WithMetadataStore(mt))
return fsOpts, nil
}
func getMetadataStore(rootDir string, config *Config) (metadata.Store, error) {
switch config.MetadataStore {
case "", memoryMetadataType:
return memorymetadata.NewReader, nil
case dbMetadataType:
if config.OpenBoltDB == nil {
return nil, fmt.Errorf("bolt DB is not configured")
}
db, err := config.OpenBoltDB(filepath.Join(rootDir, "metadata.db"))
if err != nil {
return nil, err
}
return func(sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error) {
return dbmetadata.NewReader(db, sr, opts...)
}, nil
default:
return nil, fmt.Errorf("unknown metadata store type: %v; must be %v or %v",
config.MetadataStore, memoryMetadataType, dbMetadataType)
}
}

View File

@ -20,12 +20,12 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"io"
golog "log" golog "log"
"math/rand" "math/rand"
"net" "net"
"net/http" "net/http"
"os" "os"
"os/exec"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"time" "time"
@ -33,20 +33,13 @@ import (
snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1" snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1"
"github.com/containerd/containerd/v2/contrib/snapshotservice" "github.com/containerd/containerd/v2/contrib/snapshotservice"
"github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/dialer"
"github.com/containerd/containerd/v2/pkg/sys" "github.com/containerd/containerd/v2/pkg/sys"
"github.com/containerd/log" "github.com/containerd/log"
dbmetadata "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/db" "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/fsopts"
ipfs "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/ipfs" "github.com/containerd/stargz-snapshotter/fusemanager"
"github.com/containerd/stargz-snapshotter/fs"
"github.com/containerd/stargz-snapshotter/metadata"
memorymetadata "github.com/containerd/stargz-snapshotter/metadata/memory"
"github.com/containerd/stargz-snapshotter/service" "github.com/containerd/stargz-snapshotter/service"
"github.com/containerd/stargz-snapshotter/service/keychain/cri" "github.com/containerd/stargz-snapshotter/service/keychain/keychainconfig"
"github.com/containerd/stargz-snapshotter/service/keychain/dockerconfig" snbase "github.com/containerd/stargz-snapshotter/snapshot"
"github.com/containerd/stargz-snapshotter/service/keychain/kubeconfig"
"github.com/containerd/stargz-snapshotter/service/resolver"
"github.com/containerd/stargz-snapshotter/version" "github.com/containerd/stargz-snapshotter/version"
sddaemon "github.com/coreos/go-systemd/v22/daemon" sddaemon "github.com/coreos/go-systemd/v22/daemon"
metrics "github.com/docker/go-metrics" metrics "github.com/docker/go-metrics"
@ -54,9 +47,6 @@ import (
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
) )
const ( const (
@ -65,6 +55,8 @@ const (
defaultLogLevel = log.InfoLevel defaultLogLevel = log.InfoLevel
defaultRootDir = "/var/lib/containerd-stargz-grpc" defaultRootDir = "/var/lib/containerd-stargz-grpc"
defaultImageServiceAddress = "/run/containerd/containerd.sock" defaultImageServiceAddress = "/run/containerd/containerd.sock"
defaultFuseManagerAddress = "/run/containerd-stargz-grpc/fuse-manager.sock"
fuseManagerBin = "stargz-fuse-manager"
) )
var ( var (
@ -79,19 +71,33 @@ type snapshotterConfig struct {
service.Config service.Config
// MetricsAddress is address for the metrics API // MetricsAddress is address for the metrics API
MetricsAddress string `toml:"metrics_address"` MetricsAddress string `toml:"metrics_address" json:"metrics_address"`
// NoPrometheus is a flag to disable the emission of the metrics // NoPrometheus is a flag to disable the emission of the metrics
NoPrometheus bool `toml:"no_prometheus"` NoPrometheus bool `toml:"no_prometheus" json:"no_prometheus"`
// DebugAddress is a Unix domain socket address where the snapshotter exposes /debug/ endpoints. // DebugAddress is a Unix domain socket address where the snapshotter exposes /debug/ endpoints.
DebugAddress string `toml:"debug_address"` DebugAddress string `toml:"debug_address" json:"debug_address"`
// IPFS is a flag to enbale lazy pulling from IPFS. // IPFS is a flag to enbale lazy pulling from IPFS.
IPFS bool `toml:"ipfs"` IPFS bool `toml:"ipfs" json:"ipfs"`
// MetadataStore is the type of the metadata store to use. // MetadataStore is the type of the metadata store to use.
MetadataStore string `toml:"metadata_store" default:"memory"` MetadataStore string `toml:"metadata_store" default:"memory" json:"metadata_store"`
// FuseManagerConfig is configuration for fusemanager
FuseManagerConfig `toml:"fuse_manager" json:"fuse_manager"`
}
type FuseManagerConfig struct {
// Enable is whether detach fusemanager or not
Enable bool `toml:"enable" default:"false" json:"enable"`
// Address is address for the fusemanager's GRPC server (default: "/run/containerd-stargz-grpc/fuse-manager.sock")
Address string `toml:"address" json:"address"`
// Path is path to the fusemanager's executable (default: looking for a binary "stargz-fuse-manager")
Path string `toml:"path" json:"path"`
} }
func main() { func main() {
@ -118,7 +124,7 @@ func main() {
// Get configuration from specified file // Get configuration from specified file
tree, err := toml.LoadFile(*configPath) tree, err := toml.LoadFile(*configPath)
if err != nil && !(os.IsNotExist(err) && *configPath == defaultConfigPath) { if err != nil && (!os.IsNotExist(err) || *configPath != defaultConfigPath) {
log.G(ctx).WithError(err).Fatalf("failed to load config file %q", *configPath) log.G(ctx).WithError(err).Fatalf("failed to load config file %q", *configPath)
} }
if err := tree.Unmarshal(&config); err != nil { if err := tree.Unmarshal(&config); err != nil {
@ -132,45 +138,126 @@ func main() {
// Create a gRPC server // Create a gRPC server
rpc := grpc.NewServer() rpc := grpc.NewServer()
// Configure FUSE passthrough
// Always set Direct to true to ensure that
// *directoryCache.Get always return *os.File instead of buffer
if config.PassThrough {
config.Direct = true
}
// Configure keychain // Configure keychain
credsFuncs := []resolver.Credential{dockerconfig.NewDockerconfigKeychain(ctx)} keyChainConfig := keychainconfig.Config{
if config.Config.KubeconfigKeychainConfig.EnableKeychain { EnableKubeKeychain: config.KubeconfigKeychainConfig.EnableKeychain,
var opts []kubeconfig.Option EnableCRIKeychain: config.CRIKeychainConfig.EnableKeychain,
if kcp := config.Config.KubeconfigKeychainConfig.KubeconfigPath; kcp != "" { KubeconfigPath: config.KubeconfigPath,
opts = append(opts, kubeconfig.WithKubeconfigPath(kcp)) DefaultImageServiceAddress: defaultImageServiceAddress,
} ImageServicePath: config.ImageServicePath,
credsFuncs = append(credsFuncs, kubeconfig.NewKubeconfigKeychain(ctx, opts...))
} }
if config.Config.CRIKeychainConfig.EnableKeychain {
// connects to the backend CRI service (defaults to containerd socket) var rs snapshots.Snapshotter
criAddr := defaultImageServiceAddress fuseManagerConfig := config.FuseManagerConfig
if cp := config.CRIKeychainConfig.ImageServicePath; cp != "" { if fuseManagerConfig.Enable {
criAddr = cp fmPath := fuseManagerConfig.Path
} if fmPath == "" {
connectCRI := func() (runtime.ImageServiceClient, error) { var err error
conn, err := newCRIConn(criAddr) fmPath, err = exec.LookPath(fuseManagerBin)
if err != nil { if err != nil {
return nil, err log.G(ctx).WithError(err).Fatalf("failed to find fusemanager bin")
} }
return runtime.NewImageServiceClient(conn), nil
} }
f, criServer := cri.NewCRIKeychain(ctx, connectCRI) fmAddr := fuseManagerConfig.Address
runtime.RegisterImageServiceServer(rpc, criServer) if fmAddr == "" {
credsFuncs = append(credsFuncs, f) fmAddr = defaultFuseManagerAddress
} }
fsOpts := []fs.Option{fs.WithMetricsLogLevel(log.InfoLevel)}
if config.IPFS { if !filepath.IsAbs(fmAddr) {
fsOpts = append(fsOpts, fs.WithResolveHandler("ipfs", new(ipfs.ResolveHandler))) log.G(ctx).WithError(err).Fatalf("fuse manager address must be an absolute path: %s", fmAddr)
} }
mt, err := getMetadataStore(*rootDir, config) managerNewlyStarted, err := fusemanager.StartFuseManager(ctx, fmPath, fmAddr, filepath.Join(*rootDir, "fusestore.db"), *logLevel, filepath.Join(*rootDir, "stargz-fuse-manager.log"))
if err != nil { if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure metadata store") log.G(ctx).WithError(err).Fatalf("failed to start fusemanager")
} }
fsOpts = append(fsOpts, fs.WithMetadataStore(mt))
rs, err := service.NewStargzSnapshotterService(ctx, *rootDir, &config.Config, fuseManagerConfig := fusemanager.Config{
service.WithCredsFuncs(credsFuncs...), service.WithFilesystemOptions(fsOpts...)) Config: config.Config,
if err != nil { IPFS: config.IPFS,
log.G(ctx).WithError(err).Fatalf("failed to configure snapshotter") MetadataStore: config.MetadataStore,
DefaultImageServiceAddress: defaultImageServiceAddress,
}
fs, err := fusemanager.NewManagerClient(ctx, *rootDir, fmAddr, &fuseManagerConfig)
if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure fusemanager")
}
flags := []snbase.Opt{snbase.AsynchronousRemove}
// "managerNewlyStarted" being true indicates that the FUSE manager is newly started. To
// fully recover the snapshotter and the FUSE manager's state, we need to restore
// all snapshot mounts. If managerNewlyStarted is false, the existing FUSE manager maintains
// snapshot mounts so we don't need to restore them.
if !managerNewlyStarted {
flags = append(flags, snbase.NoRestore)
}
rs, err = snbase.NewSnapshotter(ctx, filepath.Join(*rootDir, "snapshotter"), fs, flags...)
if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure snapshotter")
}
log.G(ctx).Infof("Start snapshotter with fusemanager mode")
} else {
crirpc := rpc
// For CRI keychain, if listening path is different from stargz-snapshotter's socket, prepare for the dedicated grpc server and the socket.
serveCRISocket := config.CRIKeychainConfig.EnableKeychain && config.ListenPath != "" && config.ListenPath != *address
if serveCRISocket {
crirpc = grpc.NewServer()
}
credsFuncs, err := keychainconfig.ConfigKeychain(ctx, crirpc, &keyChainConfig)
if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure keychain")
}
if serveCRISocket {
addr := config.ListenPath
// Prepare the directory for the socket
if err := os.MkdirAll(filepath.Dir(addr), 0700); err != nil {
log.G(ctx).WithError(err).Fatalf("failed to create directory %q", filepath.Dir(addr))
}
// Try to remove the socket file to avoid EADDRINUSE
if err := os.RemoveAll(addr); err != nil {
log.G(ctx).WithError(err).Fatalf("failed to remove %q", addr)
}
// Listen and serve
l, err := net.Listen("unix", addr)
if err != nil {
log.G(ctx).WithError(err).Fatalf("error on listen socket %q", addr)
}
go func() {
if err := crirpc.Serve(l); err != nil {
log.G(ctx).WithError(err).Errorf("error on serving CRI via socket %q", addr)
}
}()
}
fsConfig := fsopts.Config{
EnableIpfs: config.IPFS,
MetadataStore: config.MetadataStore,
OpenBoltDB: func(p string) (*bolt.DB, error) {
return bolt.Open(p, 0600, &bolt.Options{
NoFreelistSync: true,
InitialMmapSize: 64 * 1024 * 1024,
FreelistType: bolt.FreelistMapType,
})
},
}
fsOpts, err := fsopts.ConfigFsOpts(ctx, *rootDir, &fsConfig)
if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure fs config")
}
rs, err = service.NewStargzSnapshotterService(ctx, *rootDir, &config.Config,
service.WithCredsFuncs(credsFuncs...), service.WithFilesystemOptions(fsOpts...))
if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure snapshotter")
}
} }
cleanup, err := serve(ctx, rpc, *address, rs, config) cleanup, err := serve(ctx, rpc, *address, rs, config)
@ -178,7 +265,18 @@ func main() {
log.G(ctx).WithError(err).Fatalf("failed to serve snapshotter") log.G(ctx).WithError(err).Fatalf("failed to serve snapshotter")
} }
if cleanup { // When FUSE manager is disabled, FUSE servers are goroutines in the
// contaienrd-stargz-grpc process. So killing containerd-stargz-grpc will
// result in all FUSE mount becoming unavailable with leaving all resources
// (e.g. temporary cache) on the node. To ensure graceful shutdown, we
// should always cleanup mounts and associated resources here.
//
// When FUSE manager is enabled, those mounts are still under the control by
// the FUSE manager so we need to avoid cleaning them up unless explicitly
// commanded via SIGINT. The user can use SIGINT to gracefully killing the FUSE
// manager before rebooting the node for ensuring that the all snapshots are
// unmounted with cleaning up associated temporary resources.
if cleanup || !fuseManagerConfig.Enable {
log.G(ctx).Debug("Closing the snapshotter") log.G(ctx).Debug("Closing the snapshotter")
rs.Close() rs.Close()
} }
@ -268,48 +366,3 @@ func serve(ctx context.Context, rpc *grpc.Server, addr string, rs snapshots.Snap
} }
return false, nil return false, nil
} }
const (
memoryMetadataType = "memory"
dbMetadataType = "db"
)
func getMetadataStore(rootDir string, config snapshotterConfig) (metadata.Store, error) {
switch config.MetadataStore {
case "", memoryMetadataType:
return memorymetadata.NewReader, nil
case dbMetadataType:
bOpts := bolt.Options{
NoFreelistSync: true,
InitialMmapSize: 64 * 1024 * 1024,
FreelistType: bolt.FreelistMapType,
}
db, err := bolt.Open(filepath.Join(rootDir, "metadata.db"), 0600, &bOpts)
if err != nil {
return nil, err
}
return func(sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error) {
return dbmetadata.NewReader(db, sr, opts...)
}, nil
default:
return nil, fmt.Errorf("unknown metadata store type: %v; must be %v or %v",
config.MetadataStore, memoryMetadataType, dbMetadataType)
}
}
func newCRIConn(criAddr string) (*grpc.ClientConn, error) {
// TODO: make gRPC options configurable from config.toml
backoffConfig := backoff.DefaultConfig
backoffConfig.MaxDelay = 3 * time.Second
connParams := grpc.ConnectParams{
Backoff: backoffConfig,
}
gopts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithConnectParams(connParams),
grpc.WithContextDialer(dialer.ContextDialer),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
}
return grpc.NewClient(dialer.DialAddress(criAddr), gopts...)
}

View File

@ -21,10 +21,12 @@ import (
gocontext "context" gocontext "context"
"encoding/csv" "encoding/csv"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"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"
@ -36,7 +38,6 @@ import (
"github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/pkg/oci"
gocni "github.com/containerd/go-cni" gocni "github.com/containerd/go-cni"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/hashicorp/go-multierror"
imagespec "github.com/opencontainers/image-spec/specs-go/v1" imagespec "github.com/opencontainers/image-spec/specs-go/v1"
runtimespec "github.com/opencontainers/runtime-spec/specs-go" runtimespec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/rs/xid" "github.com/rs/xid"
@ -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",
@ -129,13 +148,14 @@ var samplerFlags = []cli.Flag{
func getSpecOpts(clicontext *cli.Context) func(image containerd.Image, rootfs string) (opts []oci.SpecOpts, done func() error, rErr error) { func getSpecOpts(clicontext *cli.Context) func(image containerd.Image, rootfs string) (opts []oci.SpecOpts, done func() error, rErr error) {
return func(image containerd.Image, rootfs string) (opts []oci.SpecOpts, done func() error, rErr error) { return func(image containerd.Image, rootfs string) (opts []oci.SpecOpts, done func() error, rErr error) {
var cleanups []func() error var cleanups []func() error
done = func() (allErr error) { done = func() error {
var errs []error
for i := len(cleanups) - 1; i >= 0; i-- { for i := len(cleanups) - 1; i >= 0; i-- {
if err := cleanups[i](); err != nil { if err := cleanups[i](); err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
} }
} }
return return errors.Join(errs...)
} }
defer func() { defer func() {
if rErr != nil { if rErr != nil {
@ -212,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))
}
} }
} }
@ -265,13 +290,14 @@ func withEntrypointArgs(clicontext *cli.Context, image containerd.Image) (oci.Sp
func withCNI(clicontext *cli.Context) (specOpt oci.SpecOpts, done func() error, rErr error) { func withCNI(clicontext *cli.Context) (specOpt oci.SpecOpts, done func() error, rErr error) {
var cleanups []func() error var cleanups []func() error
done = func() (allErr error) { done = func() error {
var errs []error
for i := len(cleanups) - 1; i >= 0; i-- { for i := len(cleanups) - 1; i >= 0; i-- {
if err := cleanups[i](); err != nil { if err := cleanups[i](); err != nil {
allErr = multierror.Append(allErr, err) errs = append(errs, err)
} }
} }
return return errors.Join(errs...)
} }
defer func() { defer func() {
if rErr != nil { if rErr != nil {

View File

@ -1,91 +1,83 @@
module github.com/containerd/stargz-snapshotter/cmd module github.com/containerd/stargz-snapshotter/cmd
go 1.23.0 go 1.24.0
toolchain go1.23.2 toolchain go1.24.2
require ( require (
github.com/containerd/containerd/api v1.8.0 github.com/containerd/containerd/api v1.9.0
github.com/containerd/containerd/v2 v2.0.0 github.com/containerd/containerd/v2 v2.1.4
github.com/containerd/go-cni v1.1.10 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.0 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
github.com/containerd/stargz-snapshotter/estargz v0.16.0 github.com/containerd/stargz-snapshotter/estargz v0.17.0
github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240622031358-6405f362966d github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240622031358-6405f362966d
github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/go-systemd/v22 v22.5.0
github.com/docker/go-metrics v0.0.1 github.com/docker/go-metrics v0.0.1
github.com/goccy/go-json v0.10.3 github.com/goccy/go-json v0.10.5
github.com/hashicorp/go-multierror v1.1.1 github.com/klauspost/compress v1.18.0
github.com/klauspost/compress v1.17.11
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/image-spec v1.1.1
github.com/opencontainers/runtime-spec v1.2.0 github.com/opencontainers/runtime-spec v1.2.1
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/rs/xid v1.6.0 github.com/rs/xid v1.6.0
github.com/urfave/cli/v2 v2.27.5 github.com/urfave/cli/v2 v2.27.7
go.etcd.io/bbolt v1.3.11 go.etcd.io/bbolt v1.4.2
golang.org/x/sync v0.9.0 golang.org/x/sync v0.16.0
golang.org/x/sys v0.26.0 golang.org/x/sys v0.34.0
google.golang.org/grpc v1.68.0 google.golang.org/grpc v1.74.2
k8s.io/cri-api v0.32.0-beta.0
) )
require ( require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.9 // indirect github.com/Microsoft/hcsshim v0.13.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cilium/ebpf v0.11.0 // indirect github.com/cilium/ebpf v0.16.0 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect
github.com/containerd/console v1.0.4 // indirect github.com/containerd/console v1.0.5 // indirect
github.com/containerd/continuity v0.4.4 // indirect github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs v1.0.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-runc v1.1.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect
github.com/containerd/plugin v1.0.0 // indirect github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/ttrpc v1.2.6 // indirect github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.2 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/containernetworking/cni v1.2.3 // indirect github.com/containernetworking/cni v1.3.0 // indirect
github.com/containernetworking/plugins v1.5.1 // indirect github.com/containernetworking/plugins v1.7.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // 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 v27.3.1+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.7.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.19.6 // 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
github.com/go-openapi/swag v0.22.4 // indirect github.com/go-openapi/swag v0.23.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // 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
github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/hanwen/go-fuse/v2 v2.6.3 // indirect github.com/hanwen/go-fuse/v2 v2.8.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/intel/goresctrl v0.8.0 // indirect github.com/intel/goresctrl v0.8.0 // indirect
github.com/ipfs/go-cid v0.1.0 // indirect github.com/ipfs/go-cid v0.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.5.1 // indirect
github.com/mdlayher/vsock v1.2.1 // indirect github.com/mdlayher/vsock v1.2.1 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
@ -94,64 +86,69 @@ require (
github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/signal v0.7.1 // indirect github.com/moby/sys/signal v0.7.1 // indirect
github.com/moby/sys/symlink v0.3.0 // indirect github.com/moby/sys/symlink v0.3.0 // indirect
github.com/moby/sys/user v0.3.0 // indirect github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
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.14.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
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect
github.com/opencontainers/selinux v1.11.1 // indirect github.com/opencontainers/selinux v1.12.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // 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.20.5 // 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.55.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/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/vbatts/tar-split v0.11.6 // indirect github.com/vbatts/tar-split v0.12.1 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.31.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect
golang.org/x/crypto v0.28.0 // indirect go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect golang.org/x/crypto v0.38.0 // indirect
golang.org/x/mod v0.21.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/mod v0.24.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/term v0.25.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/text v0.19.0 // indirect golang.org/x/term v0.32.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/text v0.25.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect golang.org/x/time v0.9.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
google.golang.org/protobuf v1.36.6 // 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
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.31.2 // indirect k8s.io/api v0.33.3 // indirect
k8s.io/apimachinery v0.31.2 // indirect k8s.io/apimachinery v0.33.3 // indirect
k8s.io/client-go v0.31.2 // indirect k8s.io/client-go v0.33.3 // indirect
k8s.io/cri-api v0.33.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
lukechampine.com/blake3 v1.2.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect
tags.cncf.io/container-device-interface v0.8.0 // indirect tags.cncf.io/container-device-interface v1.0.1 // indirect
tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
) )
replace ( replace (

View File

@ -1,13 +1,11 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -19,48 +17,48 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.4/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=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
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.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= github.com/containerd/go-cni v1.1.13 h1:eFSGOKlhoYNxpJ51KRIMHZNlg5UgocXEIEBGkY7Hnis=
github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= 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=
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.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/lj+VJfhMDTIs=
github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@ -68,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 v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
github.com/docker/cli v27.3.1+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=
@ -86,32 +84,33 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
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/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.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 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
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=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@ -135,8 +134,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -144,38 +143,37 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hanwen/go-fuse/v2 v2.6.3 h1:tDcEkLRx93lXu4XyN1/j8Z74VWvhHDl6qU1kNnvFUqI= github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs=
github.com/hanwen/go-fuse/v2 v2.6.3/go.mod h1:ugNaD/iv5JYyS1Rcvi57Wz7/vrLQJo10mmketmoef48= github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/intel/goresctrl v0.8.0 h1:N3shVbS3kA1Hk2AmcbHv8805Hjbv+zqsCIZCGktxx50= github.com/intel/goresctrl v0.8.0 h1:N3shVbS3kA1Hk2AmcbHv8805Hjbv+zqsCIZCGktxx50=
github.com/intel/goresctrl v0.8.0/go.mod h1:T3ZZnuHSNouwELB5wvOoUJaB7l/4Rm23rJy/wuWJlr0= github.com/intel/goresctrl v0.8.0/go.mod h1:T3ZZnuHSNouwELB5wvOoUJaB7l/4Rm23rJy/wuWJlr0=
github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0= github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0=
github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o= github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -183,8 +181,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@ -206,8 +204,10 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE= github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
@ -227,8 +227,8 @@ github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0
github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU= github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU=
github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0= github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0=
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -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.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw=
github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= 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=
@ -262,26 +262,28 @@ github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOEL
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw=
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -291,58 +293,61 @@ 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.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 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.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= 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.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 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=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU=
github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@ -356,18 +361,26 @@ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGC
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
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/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=
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=
@ -376,18 +389,18 @@ 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.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -400,19 +413,19 @@ 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.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= 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.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -427,18 +440,18 @@ golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= 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.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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=
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=
@ -447,8 +460,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -458,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-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= 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=
@ -476,49 +489,51 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
k8s.io/cri-api v0.32.0-beta.0 h1:jEzxyqoSUuUn99naSmlRdepmSa38UGj0QNxZdQeGgMY= k8s.io/cri-api v0.33.3 h1:aQvK3UxsaVMul4z71lOiblMHdhw9ROaw3Cgg15xDrD4=
k8s.io/cri-api v0.32.0-beta.0/go.mod h1:rwEJEDa3cV0bT4AZ8en5LbBEAwghbAdDkLNHz//zwsk= k8s.io/cri-api v0.33.3/go.mod h1:OLQvT45OpIA+tv91ZrpuFIGY+Y2Ho23poS7n115Aocs=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc= tags.cncf.io/container-device-interface v1.0.1 h1:KqQDr4vIlxwfYh0Ed/uJGVgX+CHAkahrgabg6Q8GYxc=
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y= tags.cncf.io/container-device-interface v1.0.1/go.mod h1:JojJIOeW3hNbcnOH2q0NrWNha/JuHoDZcmYxAZwb2i0=
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA= tags.cncf.io/container-device-interface/specs-go v1.0.0 h1:8gLw29hH1ZQP9K1YtAzpvkHCjjyIxHZYzBAvlQ+0vD8=
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws= tags.cncf.io/container-device-interface/specs-go v1.0.0/go.mod h1:u86hoFWqnh3hWz3esofRFKbI261bUlvUfLKGrDhJkgQ=

View File

@ -0,0 +1,97 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"net"
"os"
"path/filepath"
"github.com/containerd/log"
"github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/fsopts"
fusemanager "github.com/containerd/stargz-snapshotter/fusemanager"
"github.com/containerd/stargz-snapshotter/service"
"github.com/containerd/stargz-snapshotter/service/keychain/keychainconfig"
"google.golang.org/grpc"
)
func init() {
fusemanager.RegisterConfigFunc(func(cc *fusemanager.ConfigContext) ([]service.Option, error) {
fsConfig := fsopts.Config{
EnableIpfs: cc.Config.IPFS,
MetadataStore: cc.Config.MetadataStore,
OpenBoltDB: cc.OpenBoltDB,
}
fsOpts, err := fsopts.ConfigFsOpts(cc.Ctx, cc.RootDir, &fsConfig)
if err != nil {
return nil, err
}
return []service.Option{service.WithFilesystemOptions(fsOpts...)}, nil
})
fusemanager.RegisterConfigFunc(func(cc *fusemanager.ConfigContext) ([]service.Option, error) {
keyChainConfig := keychainconfig.Config{
EnableKubeKeychain: cc.Config.Config.KubeconfigKeychainConfig.EnableKeychain,
EnableCRIKeychain: cc.Config.Config.CRIKeychainConfig.EnableKeychain,
KubeconfigPath: cc.Config.Config.KubeconfigPath,
DefaultImageServiceAddress: cc.Config.DefaultImageServiceAddress,
ImageServicePath: cc.Config.Config.ImageServicePath,
}
if cc.Config.Config.CRIKeychainConfig.EnableKeychain && cc.Config.Config.ListenPath == "" || cc.Config.Config.ListenPath == cc.Address {
return nil, fmt.Errorf("listen path of CRI server must be specified as a separated socket from FUSE manager server")
}
// For CRI keychain, if listening path is different from stargz-snapshotter's socket, prepare for the dedicated grpc server and the socket.
serveCRISocket := cc.Config.Config.CRIKeychainConfig.EnableKeychain && cc.Config.Config.ListenPath != "" && cc.Config.Config.ListenPath != cc.Address
if serveCRISocket {
cc.CRIServer = grpc.NewServer()
}
credsFuncs, err := keychainconfig.ConfigKeychain(cc.Ctx, cc.CRIServer, &keyChainConfig)
if err != nil {
return nil, err
}
if serveCRISocket {
addr := cc.Config.Config.ListenPath
// Prepare the directory for the socket
if err := os.MkdirAll(filepath.Dir(addr), 0700); err != nil {
return nil, fmt.Errorf("failed to create directory %q: %w", filepath.Dir(addr), err)
}
// Try to remove the socket file to avoid EADDRINUSE
if err := os.RemoveAll(addr); err != nil {
return nil, fmt.Errorf("failed to remove %q: %w", addr, err)
}
// Listen and serve
l, err := net.Listen("unix", addr)
if err != nil {
return nil, fmt.Errorf("error on listen socket %q: %w", addr, err)
}
go func() {
if err := cc.CRIServer.Serve(l); err != nil {
log.G(cc.Ctx).WithError(err).Errorf("error on serving CRI via socket %q", addr)
}
}()
}
return []service.Option{service.WithCredsFuncs(credsFuncs...)}, nil
})
}
func main() {
fusemanager.Run()
}

View File

@ -108,7 +108,7 @@ func main() {
// Get configuration from specified file // Get configuration from specified file
if *configPath != "" { if *configPath != "" {
tree, err := toml.LoadFile(*configPath) tree, err := toml.LoadFile(*configPath)
if err != nil && !(os.IsNotExist(err) && *configPath == defaultConfigPath) { if err != nil && (!os.IsNotExist(err) || *configPath != defaultConfigPath) {
log.G(ctx).WithError(err).Fatalf("failed to load config file %q", *configPath) log.G(ctx).WithError(err).Fatalf("failed to load config file %q", *configPath)
} }
if err := tree.Unmarshal(&config); err != nil { if err := tree.Unmarshal(&config); err != nil {
@ -122,9 +122,9 @@ func main() {
// Prepare kubeconfig-based keychain if required // Prepare kubeconfig-based keychain if required
credsFuncs := []resolver.Credential{sk.credentials} credsFuncs := []resolver.Credential{sk.credentials}
if config.KubeconfigKeychainConfig.EnableKeychain { if config.EnableKeychain {
var opts []kubeconfig.Option var opts []kubeconfig.Option
if kcp := config.KubeconfigKeychainConfig.KubeconfigPath; kcp != "" { if kcp := config.KubeconfigPath; kcp != "" {
opts = append(opts, kubeconfig.WithKubeconfigPath(kcp)) opts = append(opts, kubeconfig.WithKubeconfigPath(kcp))
} }
credsFuncs = append(credsFuncs, kubeconfig.NewKubeconfigKeychain(ctx, opts...)) credsFuncs = append(credsFuncs, kubeconfig.NewKubeconfigKeychain(ctx, opts...))
@ -140,7 +140,7 @@ func main() {
Fatalf("failed to prepare mountpoint %q", mountPoint) Fatalf("failed to prepare mountpoint %q", mountPoint)
} }
} }
if config.Config.DisableVerification { if config.DisableVerification {
log.G(ctx).Fatalf("content verification can't be disabled") log.G(ctx).Fatalf("content verification can't be disabled")
} }
mt, err := getMetadataStore(*rootDir, config) mt, err := getMetadataStore(*rootDir, config)
@ -151,7 +151,7 @@ func main() {
if err != nil { if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to prepare pool") log.G(ctx).WithError(err).Fatalf("failed to prepare pool")
} }
if err := store.Mount(ctx, mountPoint, layerManager, config.Config.Debug); err != nil { if err := store.Mount(ctx, mountPoint, layerManager, config.Debug); err != nil {
log.G(ctx).WithError(err).Fatalf("failed to mount fs at %q", mountPoint) log.G(ctx).WithError(err).Fatalf("failed to mount fs at %q", mountPoint)
} }
defer func() { defer func() {
@ -266,7 +266,7 @@ func (sk *storeKeychain) credentials(host string, refspec reference.Spec) (strin
if acfg, ok := sk.config[refspec.String()]; ok { if acfg, ok := sk.config[refspec.String()]; ok {
if acfg.IdentityToken != "" { if acfg.IdentityToken != "" {
return "", acfg.IdentityToken, nil return "", acfg.IdentityToken, nil
} else if !(acfg.Username == "" && acfg.Password == "") { } else if acfg.Username != "" || acfg.Password != "" {
return acfg.Username, acfg.Password, nil return acfg.Username, acfg.Password, nil
} }
} }

View File

@ -44,6 +44,8 @@ We assume that you are using containerd (> v1.4.2) as a CRI runtime.
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
``` ```
@ -145,6 +147,8 @@ We assume that you are using CRI-O newer than https://github.com/cri-o/cri-o/pul
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
``` ```
- Install fuse - Install fuse
@ -174,3 +178,7 @@ We assume that you are using CRI-O newer than https://github.com/cri-o/cri-o/pul
systemctl restart containerd systemctl restart containerd
systemctl restart docker systemctl restart docker
``` ```
## Using stargz-snapshotter on Lima
See [`./lima.md`](./lima.md)

View File

@ -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.
@ -268,3 +269,38 @@ ctr-remote image optimize --oci \
By default, when the source image is a multi-platform image, `ctr-remote` converts the image corresponding to the platform where `ctr-remote` runs. By default, when the source image is a multi-platform image, `ctr-remote` converts the image corresponding to the platform where `ctr-remote` runs.
Note that though the images specified by `--all-platform` and `--platform` are converted to eStargz, images that don't correspond to the current platform aren't *optimized*. That is, these images are lazily pulled but without prefetch. Note that though the images specified by `--all-platform` and `--platform` are converted to eStargz, images that don't correspond to the current platform aren't *optimized*. That is, these images are lazily pulled but without prefetch.
### Dump log of accessed files during optimization (`--record-out`)
You can dump the information of which files are accesssed during optimization, using `--record-out` flag.
For example, the following dumps logs of files accessed during running `ls` in `ubuntu:24.04`.
```
ctr-remote image pull docker.io/library/ubuntu:24.04
ctr-remote image optimize --record-out=/tmp/log.json \
--entrypoint='[ "/bin/bash", "-c" ]' --args='[ "ls" ]' \
docker.io/library/ubuntu:24.04 registry2:5000/ubuntu:24.04
```
The following is the contents of the log (`/tmp/log.json`):
```
{"path":"usr/bin/bash","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/bin/bash","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"etc/ld.so.cache","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/libtinfo.so.6.4","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/libc.so.6","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"etc/nsswitch.conf","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"etc/nsswitch.conf","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"etc/passwd","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/bin/ls","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"etc/ld.so.cache","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/libselinux.so.1","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/libc.so.6","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
{"path":"usr/lib/x86_64-linux-gnu/libpcre2-8.so.0.11.2","manifestDigest":"sha256:5d070ad5f7fe63623cbb99b4fc0fd997f5591303d4b03ccce50f403957d0ddc4","layerIndex":0}
```
For creating an optimized eStargz using this log, you can input this log into [`--estargz-record-in` or `--zstdchunked-record-in` of `nerdctl image convert`](https://github.com/containerd/nerdctl/blob/8b814ca7fe29cb505a02a3d85ba22860e63d15bf/docs/command-reference.md#nerd_face-nerdctl-image-convert) or the same flags for `ctr-remote image convert` .

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

52
docs/lima.md Normal file
View File

@ -0,0 +1,52 @@
# Getting started with Stargz Snapshotter on Lima
[Lima](https://github.com/lima-vm/lima) is a tool to manage Linux virtual machines on various hosts, including MacOS and Linux.
Lima can be used as an easy way to get started with Stargz Snapshotter as Lima provides a default VM image bundling [containerd](https://github.com/containerd/containerd), [nerdctl](https://github.com/containerd/nerdctl)(Docker-compatible CLI of containerd) and Stargz Snapshotter.
This document describes how to get started with Stargz Snapshotter on Lima.
## Enable Stargz Snapshotter using `--snapshotter=stargz` flag
nerdctl's `--snapshotter=stargz` flag enables stargz-snapshotter.
```
$ nerdctl.lima --snapshotter=stargz system info | grep stargz
Storage Driver: stargz
```
Using this flag, you can perform lazy pulling of a python eStargz image and run it.
```
$ nerdctl.lima --snapshotter=stargz run --rm -it --name python ghcr.io/stargz-containers/python:3.13-esgz
Python 3.13.2 (main, Feb 6 2025, 22:37:13) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
```
## Use Stargz Snapshotter as the default snapshotter
nerdctl recognizes an environment variable `CONTAINERD_SNAPSHOTTER` for the snapshotter to use.
You can add this environment variable to the VM by configuring Lima config as shown in the following:
```
$ cat <<EOF >> ~/.lima/_config/override.yaml
env:
CONTAINERD_SNAPSHOTTER: stargz
EOF
$ limactl stop
$ limactl start
$ nerdctl.lima system info | grep Storage
Storage Driver: stargz
```
> NOTE: `override.yaml` applies to all the instances of Lima
You can perform lazy pulling of eStargz using nerdctl, without any extra flags.
```
$ nerdctl.lima run --rm -it --name python ghcr.io/stargz-containers/python:3.13-esgz
Python 3.13.2 (main, Feb 6 2025, 22:37:13) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

View File

@ -1,22 +1,22 @@
# Containerd Stargz Snapshotter Plugin Overview # Containerd Stargz Snapshotter Plugin Overview
__Before get through this overview document, we recommend you to read [README](../README.md).__ __Before reading this overview document, we recommend you read [README](../README.md).__
Pulling image is one of the time-consuming steps in the container startup process. Pulling images is one of the most time-consuming steps in the container startup process.
In containerd community, we have had a lot of discussions to address this issue as the following, In the containerd community, we have had a lot of discussions to address this issue at the following:
- [#3731 Support remote snapshotter to speed up image pulling](https://github.com/containerd/containerd/issues/3731) - [#3731 Support remote snapshotter to speed up image pulling](https://github.com/containerd/containerd/issues/3731)
- [#2968 Support `Prepare` for existing snapshots in Snapshotter interface](https://github.com/containerd/containerd/issues/2968) - [#2968 Support `Prepare` for existing snapshots in Snapshotter interface](https://github.com/containerd/containerd/issues/2968)
- [#2943 remote filesystem snapshotter](https://github.com/containerd/containerd/issues/2943) - [#2943 remote filesystem snapshotter](https://github.com/containerd/containerd/issues/2943)
The solution for the fast image distribution is called *Remote Snapshotter* plugin. The solution for fast image distribution is called *Remote Snapshotter* plugin.
This prepares container's rootfs layers by directly mounting from remote stores instead of downloading and unpacking the entire image contents. This prepares the container's rootfs layers by directly mounting from remote stores instead of downloading and unpacking the entire image contents.
The actual image contents can be fetched *lazily* so runtimes can startup containers before the entire image contents to be locally available. The actual image contents can be fetched *lazily* so runtimes can start containers before the entire image contents are locally available.
We call these remotely mounted layers as *remote snapshots*. We call these remotely mounted layers *remote snapshots*.
*Stargz Snapshotter* is a remote snapshotter plugin implementation which supports standard compatible remote snapshots functionality. *Stargz Snapshotter* is a remote snapshotter plugin implementation which supports standard compatible remote snapshots functionality.
This snapshotter leverages [eStargz](/docs/stargz-estargz.md) image, which is lazily-pullable and still standard-compatible. This snapshotter leverages [eStargz](/docs/stargz-estargz.md) image, which is lazily-pullable and still standard-compatible.
Because of this compatibility, eStargz image can be pushed to and lazily pulled from [OCI](https://github.com/opencontainers/distribution-spec)/[Docker](https://docs.docker.com/registry/spec/api/) registries (e.g. ghcr.io). Because of this compatibility, eStargz images can be pushed to and lazily pulled from [OCI](https://github.com/opencontainers/distribution-spec)/[Docker](https://docs.docker.com/registry/spec/api/) registries (e.g. ghcr.io).
Furthermore, images can run even on eStargz-agnostic runtimes (e.g. Docker). Furthermore, images can run even on eStargz-agnostic runtimes (e.g. Docker).
When you run a container image and it is formatted by eStargz, stargz snapshotter prepares container's rootfs layers as remote snapshots by mounting layers from the registry to the node, instead of pulling the entire image contents. When you run a container image and it is formatted by eStargz, stargz snapshotter prepares container's rootfs layers as remote snapshots by mounting layers from the registry to the node, instead of pulling the entire image contents.
@ -27,10 +27,10 @@ This document gives you a high-level overview of stargz snapshotter.
## Stargz Snapshotter proxy plugin ## Stargz Snapshotter proxy plugin
Stargz snapshotter is implemented as a [proxy plugin](https://github.com/containerd/containerd/blob/04985039cede6aafbb7dfb3206c9c4d04e2f924d/PLUGINS.md#proxy-plugins) daemon (`containerd-stargz-grpc`) for containerd. Stargz snapshotter is implemented as a [proxy plugin](https://github.com/containerd/containerd/blob/04985039cede6aafbb7dfb3206c9c4d04e2f924d/PLUGINS.md#proxy-plugins) daemon (`containerd-stargz-grpc`) for containerd.
When containerd starts a container, it queries the rootfs snapshots to stargz snapshotter daemon through an unix socket. When containerd starts a container, it queries the rootfs snapshots to stargz snapshotter daemon through a unix socket.
This snapshotter remotely mounts queried eStargz layers from registries to the node and provides these mount points as remote snapshots to containerd. This snapshotter remotely mounts queried eStargz layers from registries to the node and provides these mount points as remote snapshots to containerd.
Containerd recognizes this plugin through an unix socket specified in the configuration file (e.g. `/etc/containerd/config.toml`). Containerd recognizes this plugin through a unix socket specified in the configuration file (e.g. `/etc/containerd/config.toml`).
Stargz snapshotter can also be used through Kubernetes CRI by specifying the snapshotter name in the CRI plugin configuration. Stargz snapshotter can also be used through Kubernetes CRI by specifying the snapshotter name in the CRI plugin configuration.
We assume that you are using containerd (> v1.4.2). We assume that you are using containerd (> v1.4.2).
@ -44,6 +44,8 @@ version = 2
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
# Use stargz snapshotter through CRI # Use stargz snapshotter through CRI
[plugins."io.containerd.grpc.v1.cri".containerd] [plugins."io.containerd.grpc.v1.cri".containerd]
@ -51,24 +53,26 @@ version = 2
disable_snapshot_annotations = false disable_snapshot_annotations = false
``` ```
> NOTE: `root` field of `proxy_plugins` is needed for the CRI plugin to recognize stargz snapshotter's root directory.
This repo contains [a Dockerfile as a KinD node image](/Dockerfile) which includes the above configuration. This repo contains [a Dockerfile as a KinD node image](/Dockerfile) which includes the above configuration.
## State directory ## State directory
Stargz snapshotter mounts eStargz layers from registries to the node using FUSE. Stargz snapshotter mounts eStargz layers from registries to the node using FUSE.
The all files metadata in the image are preserved on the filesystem and files contents are fetched from registries on demand. Metadata for all files in the image are preserved on the container filesystem and the file contents are fetched from registries on demand.
At the root of the filesystem, there is a *state directory* (`/.stargz-snapshotter`) for status monitoring for the filesystem. At the root of the container filesystem, there is a *state directory* (`/.stargz-snapshotter`) for status monitoring for the filesystem.
This directory is hidden from `getdents(2)` so you can't see this with `ls -a /`. This directory is hidden from `getdents(2)` so you can't see this with `ls -a /`.
Instead, you can directly access the directory by specifying the path (`/.stargz-snapshotter`). Instead, you can directly access the directory by specifying the path (`/.stargz-snapshotter`).
State directory contains JSON-formatted metadata files for each layer. The state directory contains JSON-formatted metadata files for each layer.
In the following example, metadata JSON files for overlayed 7 layers are visible. In the following example, metadata JSON files for overlayed 7 layers are visible.
In each metadata JSON file, the following fields are contained, In each metadata JSON file, the following fields are contained:
- `digest` contains the layer digest. This is the same value as that in the image's manifest. - `digest` contains the layer digest. This is the same value as that in the image's manifest.
- `size` is the size bytes of the layer. - `size` is the size bytes of the layer.
- `fetchedSize` and `fetchedPercent` indicate how many bytes have been fetched for this layer. Stargz snapshotter aggressively downloads this layer in the background - unless configured otherwise - so these values gradually increase. When `fetchedPercent` reaches to `100` percents, this layer has been fully downloaded on the node and no further access will occur for reading files. - `fetchedSize` and `fetchedPercent` indicate how many bytes have been fetched for this layer. Stargz snapshotter aggressively downloads this layer in the background - unless configured otherwise - so these values gradually increase. When `fetchedPercent` reaches `100` percent, this layer has been fully downloaded on the node and no further access will occur for reading files.
Note that the state directory layout and the metadata JSON structure are subject to change. Note that the state directory layout and the metadata JSON structure are subject to change.
@ -95,6 +99,59 @@ root@1d43741b8d29:/go# cat /.stargz-snapshotter/*
{"digest":"sha256:f077511be7d385c17ba88980379c5cd0aab7068844dffa7a1cefbf68cc3daea3","size":580,"fetchedSize":580,"fetchedPercent":100} {"digest":"sha256:f077511be7d385c17ba88980379c5cd0aab7068844dffa7a1cefbf68cc3daea3","size":580,"fetchedSize":580,"fetchedPercent":100}
``` ```
## Fuse Manager
The fuse manager is designed to maintain the availability of running containers by managing the lifecycle of FUSE mountpoints independently from the stargz snapshotter.
### Fuse Manager Overview
Remote snapshots are mounted using FUSE, and its filesystem processes are attached to the stargz snapshotter. If the stargz snapshotter restarts (due to configuration changes or crashes), all filesystem processes will be killed and restarted, which causes the remount of FUSE mountpoints, making running containers unavailable.
To avoid this, we use a fuse daemon called the fuse manager to handle filesystem processes. The fuse manager is responsible for mounting and unmounting remote snapshotters. Its process is detached from the stargz snapshotter main process to an independent one in a shim-like way during the snapshotter's startup. This design ensures that the restart of the snapshotter won't affect the filesystem processes it manages, keeping mountpoints and running containers available during the restart. However, it is important to note that the restart of the fuse manager itself triggers a remount, so it is recommended to keep the fuse manager running in a good state.
You can enable the fuse manager by adding the following configuration.
```toml
[fusem_anager]
enable = true
```
## Killing and restarting Stargz Snapshotter
Stargz Snapshotter works as a FUSE server for the snapshots.
When you stop Stargz Sanpshotter on the node, it takes the following behaviour depending on the configuration.
### FUSE manager mode is disabled
killing containerd-stargz-grpc will result in unmounting all snapshot mounts managed by Stargz Snapshotter.
When containerd-stargz-grpc is restarted, all those snapshots are mounted again by lazy pulling all layers.
If the snapshotter fails to mount one of the snapshots (e.g. because of lazy pulling failure) during this step, the behaviour differs depending on `allow_invalid_mounts_on_restart` flag in the config TOML.
- `allow_invalid_mounts_on_restart = true`: containerd-stargz-grpc leaves the failed snapshots as empty directories. The user needs to manually remove those snapshot via containerd (e.g. using `ctr snapshot rm` command). The name of those snapshots can be seen in the log with `failed to restore remote snapshot` message.
- `allow_invalid_mounts_on_restart = false`: containerd-stargz-grpc doesn't start. The user needs to manually recover this (e.g. by wiping snapshotter and containerd state).
### FUSE manager mode is enabled
Killing containerd-stargz-grpc using non-SIGINT signal (e.g. using SIGTERM) doesn't affect the snapshot mounts because the FUSE manager process detached from containerd-stargz-grpc keeps on serving FUSE mounts to the kernel.
This is useful when you reload the updated config TOML to Stargz Snapshotter without unmounting existing snapshots.
FUSE manager serves FUSE mounts of the snapshots so if you kill this process, all snapshot mounts will be unavailable.
When stopping FUSE manager for upgrading the binary or restarting the node, you can use SIGINT signal to trigger the graceful exit as shown in the following steps.
1. Stop containers that use Stargz Snapshotter. Stopping FUSE manager makes all snapshot mounts unavailable so containers can't keep working.
2. Stop containerd-stargz-grpc process using SIGINT. This signal triggers unmounting of all snapshots and cleaning up of the associated resources.
3. Kill the FUSE manager process (`stargz-fuse-manager`)
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.
### 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.
@ -129,6 +186,9 @@ The snapshotter acquires registry creds by scanning requests.
You must specify `--image-service-endpoint=unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock` option to kubelet. You must specify `--image-service-endpoint=unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock` option to kubelet.
You can specify the backing image service's socket using `image_service_path`.
The default is the containerd's socket (`/run/containerd/containerd.sock`).
```toml ```toml
# Stargz Snapshotter proxies CRI Image Service into containerd socket. # Stargz Snapshotter proxies CRI Image Service into containerd socket.
[cri_keychain] [cri_keychain]
@ -136,6 +196,13 @@ enable_keychain = true
image_service_path = "/run/containerd/containerd.sock" image_service_path = "/run/containerd/containerd.sock"
``` ```
The default path where containerd-stargz-grpc serves the CRI Image Service API is `unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock`.
You can also change this path using `listen_path` field.
> Note that if you enabled the FUSE manager and CRI-based authentication together, `listen_path` is a mandatory field with some caveats:
> - This path must be different from the FUSE manager's socket path (`/run/containerd-stargz-grpc/fuse-manager.sock`) because they have different lifecycle. Specifically, the CRI socket is recreted on each reload of the configuration to the FUSE manager.
> - containerd-stargz-grpc's socket path (`/run/containerd-stargz-grpc/containerd-stargz-grpc.sock`) can't be used as `listen_path` because the CRI socket is served by the FUSE manager process (not containerd-stargz-grpc process).
#### kubeconfig-based authentication #### kubeconfig-based authentication
This is another way to enable lazy pulling of private images on Kubernetes. This is another way to enable lazy pulling of private images on Kubernetes.

60
docs/passthrough.md Normal file
View File

@ -0,0 +1,60 @@
# Introduction
FUSE Passthrough has been introduced in the Linux kernel version 6.9 ([Linux Kernel Commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6ce8b2ce0d7e3a621cdc9eb66d74436ca7d0e66e)). This feature has shown significant performance improvements, as detailed in the following articles:
[Phoronix Article on FUSE Passthrough](https://www.phoronix.com/news/FUSE-Passthrough-In-6.9-Next)<br>
FUSE Passthrough allows performing read and write (also via memory maps) on a backing file without incurring the overhead of roundtrips to userspace.
![passhthrough feature](/docs/images/passthrough01.png)
Additionally, the `go-fuse` package, which Stargz-Snapshotter depends on, has also added support for this passthrough feature:
[go-fuse Commit 1](https://github.com/hanwen/go-fuse/commit/e0641a46c6cca7e5370fc135f78caf7cb7fc3aa8#diff-f830ac3db25844bf71102b09e4e02f7213e9cdb577b32745979d61d775462bd3R157)<br>
[go-fuse Commit 2](https://github.com/hanwen/go-fuse/commit/e0a0b09ae8287249c38033a27fd69a3593c7e235#diff-1521152f1fc3600273bda897c669523dc1e9fc9cbe24046838f043a8040f0d67R749)<br>
[go-fuse Commit 3](https://github.com/hanwen/go-fuse/commit/1a7d98b0360f945fca50ac79905332b7106c049f)
When a user-defined file implements the `FilePassthroughFder` interface, `go-fuse` will attempt to register the file `fd` from the file with the kernel.
# Configuration
## Basic Configuration
To enable FUSE passthrough mode, first verify that your host's kernel supports this feature. You can check this by running the following command:
```bash
$ cat /boot/config-$(uname -r) | grep "CONFIG_FUSE_PASSTHROUGH=y"
CONFIG_FUSE_PASSTHROUGH=y
```
Once you have confirmed kernel support, you need to enable passthrough mode in your `config.toml` file with the following configuration:
```toml
[fuse]
passthrough = true
```
After updating the configuration, specify the `config.toml` file when starting `containerd-stargz-grpc` and restart the service:
```bash
$ containerd-stargz-grpc -config config.toml
```
## Advanced Configuration
In passthrough mode, the initial pull of an image requires merging chunks into a file. This process can be time-consuming, especially for large files.
To optimize the time taken for the initial image pull, you can use the `merge_buffer_size` and `merge_worker_count` configuration options. The `merge_buffer_size` specifies the size of the buffer used for reading the image, with a default value of 400MB. The `merge_worker_count` determines the level of concurrency for reading the image, with a default value of 10.
By concurrently reading chunks and caching them for batch writing, you can significantly enhance the performance of the initial image pull in passthrough mode.
# Important Considerations
When passthrough mode is enabled, the following configuration is applied by default, even if it is set to false in the configuration file:
```toml
[directory_cache]
direct = true
```
This is because, in passthrough mode, read operations after opening a file are handled directly by the kernel.

99
docs/transfer.md Normal file
View File

@ -0,0 +1,99 @@
# Enabling Stargz Snapshotter With Transfer Service
Transfer Service is a containerd component which is used for image management in contianerd (e.g. pulling and pushing images).
For details about Transfer Service, refer to [the official document in the containerd repo](https://github.com/containerd/containerd/blob/6af7c07905a317d4c343a49255e2392f4c8569f9/docs/transfer.md).
To use Stargz Snapshotter on containerd with enabling Transfer Service, additional configurations is needed.
## Availability of Transfer Service
Transfer Service is available since v1.7.
And this is enabled in different settings depending on the containerd version.
|containerd version|`ctr`|CRI|
---|---|---
|containerd >= v1.7 and < v2.0|Disabled by default. Enabled by `--local=false`|Disabled|
|containerd >= v2.0 and < v2.1|Enabled by default. Disabled by `--local`|Disabled|
|containerd >= v2.1|Enabled by default. Disabled by `--local`|Enabled by default. Disabled when conditions described in [containerd's CRI document](https://github.com/containerd/containerd/blob/v2.1.0/docs/cri/config.md#image-pull-configuration-since-containerd-v21) are met|
### Note about containerd v2.1
Before containerd v2.1, `disable_snapshot_annotations = false` in containerd's config TOML was a mandatory field to enable Stargz Snapshotter in CRI.
In containerd v2.1, `disable_snapshot_annotations = false` field can still be used to enable Stargz Snapshotter and containerd disables Transfer Service when this field is detected.
If you want to enable Transfer Service, you need to remove `disable_snapshot_annotations = false` field and apply the configuration explaind in this document.
## How to enable Stargz Snapshotter when Transfer Service is enabled?
In containerd v2.1, Transfer Service added support for remote snapshotters like Stargz Snapshotter.
### For ctr and other non-CRI clients
To enable Stargz Snapshotter with Transfer Service, you need to start containerd-stargz-grpc on the node and add the following configuration to contianerd's config TOML file.
Note that you need to add a field `enable_remote_snapshot_annotations = "true"` in `proxy_plugins.stargz.exports` so that containerd can correctly pass image-related information to Stargz Snapshotter.
```toml
version = 2
# Enable Stargz Snapshotter in Transfer Service
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "linux"
snapshotter = "stargz"
# Plugin Stargz Snapshotter
[proxy_plugins]
[proxy_plugins.stargz]
type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
enable_remote_snapshot_annotations = "true"
```
#### Example client command
When you enable Transfer Service with Stargz Snapshotter, you can perform lazy pulling using the normal `ctr` command. (of course, `ctr-remote` can still be used)
```
# ctr image pull --snapshotter=stargz ghcr.io/stargz-containers/ubuntu:24.04-esgz
```
Then `mount | grep stargz` prints stargz mounts on the node.
### For CRI
To enable Stargz Snapshotter with Transfer Service, you need to start containerd-stargz-grpc on the node and add the following configuration to contianerd's config TOML file.
```toml
version = 2
# Basic CRI configuration with enabling Stargz Snapshotter
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
snapshotter = "stargz"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
# Enable Stargz Snapshotter in Transfer Service
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "linux"
snapshotter = "stargz"
# Plugin Stargz Snapshotter
[proxy_plugins]
[proxy_plugins.stargz]
type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
enable_remote_snapshot_annotations = "true"
```
#### Example client command
You can quickly check the behaviour using `crictl` command.
```
# crictl image pull ghcr.io/stargz-containers/ubuntu:24.04-esgz
```
Then `mount | grep stargz` prints stargz mounts on the node.

View File

@ -408,11 +408,11 @@ func readerFromEntries(entries ...*entry) io.Reader {
defer tw.Close() defer tw.Close()
for _, entry := range entries { for _, entry := range entries {
if err := tw.WriteHeader(entry.header); err != nil { if err := tw.WriteHeader(entry.header); err != nil {
pw.CloseWithError(fmt.Errorf("Failed to write tar header: %v", err)) pw.CloseWithError(fmt.Errorf("failed to write tar header: %v", err))
return return
} }
if _, err := io.Copy(tw, entry.payload); err != nil { if _, err := io.Copy(tw, entry.payload); err != nil {
pw.CloseWithError(fmt.Errorf("Failed to write tar payload: %v", err)) pw.CloseWithError(fmt.Errorf("failed to write tar payload: %v", err))
return return
} }
} }
@ -627,12 +627,12 @@ func (cr *countReadSeeker) Seek(offset int64, whence int) (int64, error) {
switch whence { switch whence {
default: default:
return 0, fmt.Errorf("Unknown whence: %v", whence) return 0, fmt.Errorf("unknown whence: %v", whence)
case io.SeekStart: case io.SeekStart:
case io.SeekCurrent: case io.SeekCurrent:
offset += *cr.cPos offset += *cr.cPos
case io.SeekEnd: case io.SeekEnd:
return 0, fmt.Errorf("Unsupported whence: %v", whence) return 0, fmt.Errorf("unsupported whence: %v", whence)
} }
if offset < 0 { if offset < 0 {

View File

@ -81,7 +81,7 @@ func TestChunkEntryForOffset(t *testing.T) {
if ok != te.wantOk { if ok != te.wantOk {
t.Errorf("ok = %v; want (%v)", ok, te.wantOk) t.Errorf("ok = %v; want (%v)", ok, te.wantOk)
} else if ok { } else if ok {
if !(ce.ChunkOffset == te.wantChunkOffset && ce.ChunkSize == te.wantChunkSize) { if ce.ChunkOffset != te.wantChunkOffset || ce.ChunkSize != te.wantChunkSize {
t.Errorf("chunkOffset = %d, ChunkSize = %d; want (chunkOffset = %d, chunkSize = %d)", t.Errorf("chunkOffset = %d, ChunkSize = %d; want (chunkOffset = %d, chunkSize = %d)",
ce.ChunkOffset, ce.ChunkSize, te.wantChunkOffset, te.wantChunkSize) ce.ChunkOffset, ce.ChunkSize, te.wantChunkOffset, te.wantChunkSize)
} }

View File

@ -135,7 +135,7 @@ func gzipFooterBytes() ([]byte, error) {
header[0], header[1] = 'S', 'G' header[0], header[1] = 'S', 'G'
subfield := "STARGZEXTERNALTOC" // len("STARGZEXTERNALTOC") = 17 subfield := "STARGZEXTERNALTOC" // len("STARGZEXTERNALTOC") = 17
binary.LittleEndian.PutUint16(header[2:4], uint16(len(subfield))) // little-endian per RFC1952 binary.LittleEndian.PutUint16(header[2:4], uint16(len(subfield))) // little-endian per RFC1952
gz.Header.Extra = append(header, []byte(subfield)...) gz.Extra = append(header, []byte(subfield)...)
if err := gz.Close(); err != nil { if err := gz.Close(); err != nil {
return nil, err return nil, err
} }
@ -204,7 +204,7 @@ func (gz *GzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOffset, t
return 0, 0, 0, err return 0, 0, 0, err
} }
defer zr.Close() defer zr.Close()
extra := zr.Header.Extra extra := zr.Extra
si1, si2, subfieldlen, subfield := extra[0], extra[1], extra[2:4], extra[4:] si1, si2, subfieldlen, subfield := extra[0], extra[1], extra[2:4], extra[4:]
if si1 != 'S' || si2 != 'G' { if si1 != 'S' || si2 != 'G' {
return 0, 0, 0, fmt.Errorf("invalid subfield IDs: %q, %q; want E, S", si1, si2) return 0, 0, 0, fmt.Errorf("invalid subfield IDs: %q, %q; want E, S", si1, si2)

View File

@ -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),
@ -56,15 +71,15 @@ type gzipController struct {
} }
func (gc *gzipController) String() string { func (gc *gzipController) String() string {
return fmt.Sprintf("externaltoc_gzip_compression_level=%v", gc.GzipCompressor.compressionLevel) return fmt.Sprintf("externaltoc_gzip_compression_level=%v", gc.compressionLevel)
} }
// 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)
} }

View File

@ -1,10 +1,10 @@
module github.com/containerd/stargz-snapshotter/estargz module github.com/containerd/stargz-snapshotter/estargz
go 1.22.0 go 1.23.0
require ( require (
github.com/klauspost/compress v1.17.11 github.com/klauspost/compress v1.18.0
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/vbatts/tar-split v0.11.6 github.com/vbatts/tar-split v0.12.1
golang.org/x/sync v0.9.0 golang.org/x/sync v0.16.0
) )

View File

@ -1,8 +1,8 @@
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=

View File

@ -109,7 +109,7 @@ func gzipFooterBytes(tocOff int64) []byte {
header[0], header[1] = 'S', 'G' header[0], header[1] = 'S', 'G'
subfield := fmt.Sprintf("%016xSTARGZ", tocOff) subfield := fmt.Sprintf("%016xSTARGZ", tocOff)
binary.LittleEndian.PutUint16(header[2:4], uint16(len(subfield))) // little-endian per RFC1952 binary.LittleEndian.PutUint16(header[2:4], uint16(len(subfield))) // little-endian per RFC1952
gz.Header.Extra = append(header, []byte(subfield)...) gz.Extra = append(header, []byte(subfield)...)
gz.Close() gz.Close()
if buf.Len() != FooterSize { if buf.Len() != FooterSize {
panic(fmt.Sprintf("footer buffer = %d, not %d", buf.Len(), FooterSize)) panic(fmt.Sprintf("footer buffer = %d, not %d", buf.Len(), FooterSize))
@ -136,7 +136,7 @@ func (gz *GzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOffset, t
return 0, 0, 0, err return 0, 0, 0, err
} }
defer zr.Close() defer zr.Close()
extra := zr.Header.Extra extra := zr.Extra
si1, si2, subfieldlen, subfield := extra[0], extra[1], extra[2:4], extra[4:] si1, si2, subfieldlen, subfield := extra[0], extra[1], extra[2:4], extra[4:]
if si1 != 'S' || si2 != 'G' { if si1 != 'S' || si2 != 'G' {
return 0, 0, 0, fmt.Errorf("invalid subfield IDs: %q, %q; want E, S", si1, si2) return 0, 0, 0, fmt.Errorf("invalid subfield IDs: %q, %q; want E, S", si1, si2)
@ -181,7 +181,7 @@ func (gz *LegacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOff
return 0, 0, 0, fmt.Errorf("legacy: failed to get footer gzip reader: %w", err) return 0, 0, 0, fmt.Errorf("legacy: failed to get footer gzip reader: %w", err)
} }
defer zr.Close() defer zr.Close()
extra := zr.Header.Extra extra := zr.Extra
if len(extra) != 16+len("STARGZ") { if len(extra) != 16+len("STARGZ") {
return 0, 0, 0, fmt.Errorf("legacy: invalid stargz's extra field size") return 0, 0, 0, fmt.Errorf("legacy: invalid stargz's extra field size")
} }

View File

@ -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),
@ -52,15 +67,15 @@ type gzipController struct {
} }
func (gc *gzipController) String() string { func (gc *gzipController) String() string {
return fmt.Sprintf("gzip_compression_level=%v", gc.GzipCompressor.compressionLevel) return fmt.Sprintf("gzip_compression_level=%v", gc.compressionLevel)
} }
// 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)
} }
@ -106,7 +121,7 @@ func checkLegacyFooter(t *testing.T, off int64) {
func legacyFooterBytes(tocOff int64) []byte { func legacyFooterBytes(tocOff int64) []byte {
buf := bytes.NewBuffer(make([]byte, 0, legacyFooterSize)) buf := bytes.NewBuffer(make([]byte, 0, legacyFooterSize))
gz, _ := gzip.NewWriterLevel(buf, gzip.NoCompression) gz, _ := gzip.NewWriterLevel(buf, gzip.NoCompression)
gz.Header.Extra = []byte(fmt.Sprintf("%016xSTARGZ", tocOff)) gz.Extra = []byte(fmt.Sprintf("%016xSTARGZ", tocOff))
gz.Close() gz.Close()
if buf.Len() != legacyFooterSize { if buf.Len() != legacyFooterSize {
panic(fmt.Sprintf("footer buffer = %d, not %d", buf.Len(), legacyFooterSize)) panic(fmt.Sprintf("footer buffer = %d, not %d", buf.Len(), legacyFooterSize))

View File

@ -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,18 +384,19 @@ 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
if srcCompression == gzipType { switch srcCompression {
case gzipType:
w = gzip.NewWriter(buf) w = gzip.NewWriter(buf)
} else if srcCompression == zstdType { case zstdType:
w, err = zstd.NewWriter(buf) w, err = zstd.NewWriter(buf)
if err != nil { if err != nil {
t.Fatalf("failed to init zstd writer: %v", err) t.Fatalf("failed to init zstd writer: %v", err)
} }
} else { default:
return src return src
} }
src.Seek(0, io.SeekStart) src.Seek(0, io.SeekStart)
@ -386,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)
@ -445,7 +477,7 @@ func contains(t *testing.T, a, b stargzEntry) bool {
bbytes, bnext, bok := readOffset(t, bf, nr, b) bbytes, bnext, bok := readOffset(t, bf, nr, b)
if !aok && !bok { if !aok && !bok {
break break
} else if !(aok && bok) || anext != bnext { } else if !aok || !bok || anext != bnext {
t.Logf("%q != %q (offset=%d): chunk existence a=%v vs b=%v, anext=%v vs bnext=%v", t.Logf("%q != %q (offset=%d): chunk existence a=%v vs b=%v, anext=%v vs bnext=%v",
ae.Name, be.Name, nr, aok, bok, anext, bnext) ae.Name, be.Name, nr, aok, bok, anext, bnext)
return false return false
@ -497,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
@ -516,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)
@ -530,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/"),
) )
@ -558,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),
@ -582,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),
@ -606,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),
@ -653,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)
@ -689,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),
@ -800,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),
@ -881,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 {
@ -901,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
@ -928,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 {
@ -957,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 {
@ -989,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))),
@ -1046,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)
@ -1119,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"
@ -1463,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())
@ -1627,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")
} }
@ -1647,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")
@ -1672,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)
@ -1694,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" {
@ -1710,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" {
@ -1737,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)
@ -1749,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
@ -1796,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)
@ -1813,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)
@ -1857,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)
@ -1876,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" {
@ -1890,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" {
@ -1908,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 {
@ -1923,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" {
@ -1939,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)
@ -1952,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)
@ -1966,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 {
@ -2038,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) {
@ -2247,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")
} }
@ -2317,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
} }
@ -2346,8 +2377,8 @@ func CheckGzipHasStreams(t *testing.T, b []byte, streams []int64) {
t.Fatalf("countStreams(gzip), Copy: %v", err) t.Fatalf("countStreams(gzip), Copy: %v", err)
} }
var extra string var extra string
if len(zr.Header.Extra) > 0 { if len(zr.Extra) > 0 {
extra = fmt.Sprintf("; extra=%q", zr.Header.Extra) extra = fmt.Sprintf("; extra=%q", zr.Extra)
} }
t.Logf(" [%d] at %d in stargz, uncompressed length %d%s", numStreams, zoff, n, extra) t.Logf(" [%d] at %d in stargz, uncompressed length %d%s", numStreams, zoff, n, extra)
delete(wants, int64(zoff)) delete(wants, int64(zoff))
@ -2355,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 {

View File

@ -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),
@ -50,12 +65,12 @@ type zstdController struct {
} }
func (zc *zstdController) String() string { func (zc *zstdController) String() string {
return fmt.Sprintf("zstd_compression_level=%v", zc.Compressor.CompressionLevel) return fmt.Sprintf("zstd_compression_level=%v", zc.CompressionLevel)
} }
// 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 {

View File

@ -37,115 +37,127 @@ const (
type Config struct { type Config struct {
// Type of cache for compressed contents fetched from the registry. "memory" stores them on memory. // Type of cache for compressed contents fetched from the registry. "memory" stores them on memory.
// Other values default to cache them on disk. // Other values default to cache them on disk.
HTTPCacheType string `toml:"http_cache_type"` HTTPCacheType string `toml:"http_cache_type" json:"http_cache_type"`
// Type of cache for uncompressed files contents. "memory" stores them on memory. Other values // Type of cache for uncompressed files contents. "memory" stores them on memory. Other values
// default to cache them on disk. // default to cache them on disk.
FSCacheType string `toml:"filesystem_cache_type"` FSCacheType string `toml:"filesystem_cache_type" json:"filesystem_cache_type"`
// ResolveResultEntryTTLSec is TTL (in sec) to cache resolved layers for // ResolveResultEntryTTLSec is TTL (in sec) to cache resolved layers for
// future use. (default 120s) // future use. (default 120s)
ResolveResultEntryTTLSec int `toml:"resolve_result_entry_ttl_sec"` ResolveResultEntryTTLSec int `toml:"resolve_result_entry_ttl_sec" json:"resolve_result_entry_ttl_sec"`
// PrefetchSize is the default size (in bytes) to prefetch when mounting a layer. Default is 0. Stargz-snapshotter still // PrefetchSize is the default size (in bytes) to prefetch when mounting a layer. Default is 0. Stargz-snapshotter still
// uses the value specified by the image using "containerd.io/snapshot/remote/stargz.prefetch" or the landmark file. // uses the value specified by the image using "containerd.io/snapshot/remote/stargz.prefetch" or the landmark file.
PrefetchSize int64 `toml:"prefetch_size"` PrefetchSize int64 `toml:"prefetch_size" json:"prefetch_size"`
// PrefetchTimeoutSec is the default timeout (in seconds) when the prefetching takes long. Default is 10s. // PrefetchTimeoutSec is the default timeout (in seconds) when the prefetching takes long. Default is 10s.
PrefetchTimeoutSec int64 `toml:"prefetch_timeout_sec"` PrefetchTimeoutSec int64 `toml:"prefetch_timeout_sec" json:"prefetch_timeout_sec"`
// NoPrefetch disables prefetching. Default is false. // NoPrefetch disables prefetching. Default is false.
NoPrefetch bool `toml:"noprefetch"` NoPrefetch bool `toml:"noprefetch" json:"noprefetch"`
// NoBackgroundFetch disables the behaviour of fetching the entire layer contents in background. Default is false. // NoBackgroundFetch disables the behaviour of fetching the entire layer contents in background. Default is false.
NoBackgroundFetch bool `toml:"no_background_fetch"` NoBackgroundFetch bool `toml:"no_background_fetch" json:"no_background_fetch"`
// Debug enables filesystem debug log. // Debug enables filesystem debug log.
Debug bool `toml:"debug"` Debug bool `toml:"debug" json:"debug"`
// AllowNoVerification allows mouting images without verification. Default is false. // AllowNoVerification allows mouting images without verification. Default is false.
AllowNoVerification bool `toml:"allow_no_verification"` AllowNoVerification bool `toml:"allow_no_verification" json:"allow_no_verification"`
// DisableVerification disables verifying layer contents. Default is false. // DisableVerification disables verifying layer contents. Default is false.
DisableVerification bool `toml:"disable_verification"` DisableVerification bool `toml:"disable_verification" json:"disable_verification"`
// MaxConcurrency is max number of concurrent background tasks for fetching layer contents. Default is 2. // MaxConcurrency is max number of concurrent background tasks for fetching layer contents. Default is 2.
MaxConcurrency int64 `toml:"max_concurrency"` MaxConcurrency int64 `toml:"max_concurrency" json:"max_concurrency"`
// NoPrometheus disables exposing filesystem-related metrics. Default is false. // NoPrometheus disables exposing filesystem-related metrics. Default is false.
NoPrometheus bool `toml:"no_prometheus"` NoPrometheus bool `toml:"no_prometheus" json:"no_prometheus"`
// BlobConfig is config for layer blob management. // BlobConfig is config for layer blob management.
BlobConfig `toml:"blob"` BlobConfig `toml:"blob" json:"blob"`
// DirectoryCacheConfig is config for directory-based cache. // DirectoryCacheConfig is config for directory-based cache.
DirectoryCacheConfig `toml:"directory_cache"` DirectoryCacheConfig `toml:"directory_cache" json:"directory_cache"`
// FuseConfig is configurations for FUSE fs. // FuseConfig is configurations for FUSE fs.
FuseConfig `toml:"fuse"` FuseConfig `toml:"fuse" json:"fuse"`
// ResolveResultEntry is a deprecated field. // ResolveResultEntry is a deprecated field.
ResolveResultEntry int `toml:"resolve_result_entry"` // deprecated ResolveResultEntry int `toml:"resolve_result_entry" json:"resolve_result_entry"` // deprecated
} }
// BlobConfig is configuration for the logic to fetching blobs. // BlobConfig is configuration for the logic to fetching blobs.
type BlobConfig struct { type BlobConfig struct {
// ValidInterval specifies a duration (in seconds) during which the layer can be reused without // ValidInterval specifies a duration (in seconds) during which the layer can be reused without
// checking the connection to the registry. Default is 60. // checking the connection to the registry. Default is 60.
ValidInterval int64 `toml:"valid_interval"` ValidInterval int64 `toml:"valid_interval" json:"valid_interval"`
// CheckAlways overwrites ValidInterval to 0 if it's true. Default is false. // CheckAlways overwrites ValidInterval to 0 if it's true. Default is false.
CheckAlways bool `toml:"check_always"` CheckAlways bool `toml:"check_always" json:"check_always"`
// ChunkSize is the granularity (in bytes) at which background fetch and on-demand reads // ChunkSize is the granularity (in bytes) at which background fetch and on-demand reads
// are fetched from the remote registry. Default is 50000. // are fetched from the remote registry. Default is 50000.
ChunkSize int64 `toml:"chunk_size"` ChunkSize int64 `toml:"chunk_size" json:"chunk_size"`
// FetchTimeoutSec is a timeout duration (in seconds) for fetching chunks from the registry. Default is 300. // FetchTimeoutSec is a timeout duration (in seconds) for fetching chunks from the registry. Default is 300.
FetchTimeoutSec int64 `toml:"fetching_timeout_sec"` FetchTimeoutSec int64 `toml:"fetching_timeout_sec" json:"fetching_tieout_sec"`
// ForceSingleRangeMode disables using of multiple ranges in a Range Request and always specifies one larger // ForceSingleRangeMode disables using of multiple ranges in a Range Request and always specifies one larger
// region that covers them. Default is false. // region that covers them. Default is false.
ForceSingleRangeMode bool `toml:"force_single_range_mode"` ForceSingleRangeMode bool `toml:"force_single_range_mode" json:"force_single_range_mode"`
// PrefetchChunkSize is the maximum bytes transferred per http GET from remote registry // PrefetchChunkSize is the maximum bytes transferred per http GET from remote registry
// during prefetch. It is recommended to have PrefetchChunkSize > ChunkSize. // during prefetch. It is recommended to have PrefetchChunkSize > ChunkSize.
// If PrefetchChunkSize < ChunkSize prefetch bytes will be fetched as a single http GET, // If PrefetchChunkSize < ChunkSize prefetch bytes will be fetched as a single http GET,
// else total GET requests for prefetch = ceil(PrefetchSize / PrefetchChunkSize). // else total GET requests for prefetch = ceil(PrefetchSize / PrefetchChunkSize).
// Default is 0. // Default is 0.
PrefetchChunkSize int64 `toml:"prefetch_chunk_size"` PrefetchChunkSize int64 `toml:"prefetch_chunk_size" json:"prefetch_chunk_size"`
// MaxRetries is a max number of reries of a HTTP request. Default is 5. // MaxRetries is a max number of reries of a HTTP request. Default is 5.
MaxRetries int `toml:"max_retries"` MaxRetries int `toml:"max_retries" json:"max_retries"`
// MinWaitMSec is minimal delay (in seconds) for the next retrying after a request failure. Default is 30. // MinWaitMSec is minimal delay (in seconds) for the next retrying after a request failure. Default is 30.
MinWaitMSec int `toml:"min_wait_msec"` MinWaitMSec int `toml:"min_wait_msec" json:"min_wait_msec"`
// MinWaitMSec is maximum delay (in seconds) for the next retrying after a request failure. Default is 30. // MinWaitMSec is maximum delay (in seconds) for the next retrying after a request failure. Default is 30.
MaxWaitMSec int `toml:"max_wait_msec"` MaxWaitMSec int `toml:"max_wait_msec" json:"max_wait_msec"`
} }
// DirectoryCacheConfig is configuration for the disk-based cache. // DirectoryCacheConfig is configuration for the disk-based cache.
type DirectoryCacheConfig struct { type DirectoryCacheConfig struct {
// MaxLRUCacheEntry is the number of entries of LRU cache to cache data on memory. Default is 10. // MaxLRUCacheEntry is the number of entries of LRU cache to cache data on memory. Default is 10.
MaxLRUCacheEntry int `toml:"max_lru_cache_entry"` MaxLRUCacheEntry int `toml:"max_lru_cache_entry" json:"max_lru_cache_entry"`
// MaxCacheFds is the number of entries of LRU cache to hold fds of files of cached contents. Default is 10. // MaxCacheFds is the number of entries of LRU cache to hold fds of files of cached contents. Default is 10.
MaxCacheFds int `toml:"max_cache_fds"` MaxCacheFds int `toml:"max_cache_fds" json:"max_cache_fds"`
// SyncAdd being true means that each adding of data to the cache blocks until the data is fully written to the // SyncAdd being true means that each adding of data to the cache blocks until the data is fully written to the
// cache directory. Default is false. // cache directory. Default is false.
SyncAdd bool `toml:"sync_add"` SyncAdd bool `toml:"sync_add" json:"sync_add"`
// 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"` 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.
type FuseConfig struct { type FuseConfig struct {
// AttrTimeout defines overall timeout attribute for a file system in seconds. // AttrTimeout defines overall timeout attribute for a file system in seconds.
AttrTimeout int64 `toml:"attr_timeout"` AttrTimeout int64 `toml:"attr_timeout" json:"attr_timeout"`
// EntryTimeout defines TTL for directory, name lookup in seconds. // EntryTimeout defines TTL for directory, name lookup in seconds.
EntryTimeout int64 `toml:"entry_timeout"` EntryTimeout int64 `toml:"entry_timeout" json:"entry_timeout"`
// PassThrough indicates whether to enable FUSE passthrough mode to improve local file read performance. Default is false.
PassThrough bool `toml:"passthrough" default:"false" json:"passthrough"`
// MergeBufferSize is the size of the buffer to merge chunks (in bytes) for passthrough mode. Default is 400MB.
MergeBufferSize int64 `toml:"merge_buffer_size" default:"419430400" json:"merge_buffer_size"`
// MergeWorkerCount is the number of workers to merge chunks for passthrough mode. Default is 10.
MergeWorkerCount int `toml:"merge_worker_count" default:"10" json:"merge_worker_count"`
} }

View File

@ -72,6 +72,12 @@ const (
) )
var fusermountBin = []string{"fusermount", "fusermount3"} var fusermountBin = []string{"fusermount", "fusermount3"}
var (
nsLock = sync.Mutex{}
ns *metrics.Namespace
metricsCtr *layermetrics.Controller
)
type Option func(*options) type Option func(*options)
@ -133,12 +139,12 @@ func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snapshot.F
maxConcurrency = defaultMaxConcurrency maxConcurrency = defaultMaxConcurrency
} }
attrTimeout := time.Duration(cfg.FuseConfig.AttrTimeout) * time.Second attrTimeout := time.Duration(cfg.AttrTimeout) * time.Second
if attrTimeout == 0 { if attrTimeout == 0 {
attrTimeout = defaultFuseTimeout attrTimeout = defaultFuseTimeout
} }
entryTimeout := time.Duration(cfg.FuseConfig.EntryTimeout) * time.Second entryTimeout := time.Duration(cfg.EntryTimeout) * time.Second
if entryTimeout == 0 { if entryTimeout == 0 {
entryTimeout = defaultFuseTimeout entryTimeout = defaultFuseTimeout
} }
@ -160,18 +166,20 @@ func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snapshot.F
return nil, fmt.Errorf("failed to setup resolver: %w", err) return nil, fmt.Errorf("failed to setup resolver: %w", err)
} }
var ns *metrics.Namespace nsLock.Lock()
if !cfg.NoPrometheus { defer nsLock.Unlock()
if !cfg.NoPrometheus && ns == nil {
ns = metrics.NewNamespace("stargz", "fs", nil) ns = metrics.NewNamespace("stargz", "fs", nil)
logLevel := log.DebugLevel logLevel := log.DebugLevel
if fsOpts.metricsLogLevel != nil { if fsOpts.metricsLogLevel != nil {
logLevel = *fsOpts.metricsLogLevel logLevel = *fsOpts.metricsLogLevel
} }
commonmetrics.Register(logLevel) // Register common metrics. This will happen only once. commonmetrics.Register(logLevel) // Register common metrics. This will happen only once.
metrics.Register(ns) // Register layer metrics.
} }
c := layermetrics.NewLayerMetrics(ns) if metricsCtr == nil {
if ns != nil { metricsCtr = layermetrics.NewLayerMetrics(ns)
metrics.Register(ns) // Register layer metrics.
} }
return &filesystem{ return &filesystem{
@ -185,7 +193,7 @@ func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snapshot.F
backgroundTaskManager: tm, backgroundTaskManager: tm,
allowNoVerification: cfg.AllowNoVerification, allowNoVerification: cfg.AllowNoVerification,
disableVerification: cfg.DisableVerification, disableVerification: cfg.DisableVerification,
metricsController: c, metricsController: metricsCtr,
attrTimeout: attrTimeout, attrTimeout: attrTimeout,
entryTimeout: entryTimeout, entryTimeout: entryTimeout,
}, nil }, nil
@ -442,8 +450,10 @@ func (fs *filesystem) Unmount(ctx context.Context, mountpoint string) error {
fs.layerMu.Unlock() fs.layerMu.Unlock()
return fmt.Errorf("specified path %q isn't a mountpoint", mountpoint) return fmt.Errorf("specified path %q isn't a mountpoint", mountpoint)
} }
delete(fs.layer, mountpoint) // unregisters the corresponding layer delete(fs.layer, mountpoint) // unregisters the corresponding layer
l.Done() if err := l.Close(); err != nil { // Cleanup associated resources
log.G(ctx).WithError(err).Warn("failed to release resources of the layer")
}
fs.layerMu.Unlock() fs.layerMu.Unlock()
fs.metricsController.Remove(mountpoint) fs.metricsController.Remove(mountpoint)

View File

@ -91,4 +91,5 @@ func (l *breakableLayer) Refresh(ctx context.Context, hosts source.RegistryHosts
} }
return nil return nil
} }
func (l *breakableLayer) Done() {} func (l *breakableLayer) Done() {}
func (l *breakableLayer) Close() error { return nil }

View File

@ -59,6 +59,18 @@ const (
memoryCacheType = "memory" memoryCacheType = "memory"
) )
// passThroughConfig contains configuration for FUSE passthrough mode
type passThroughConfig struct {
// enable indicates whether to enable FUSE passthrough mode
enable bool
// mergeBufferSize is the size of the buffer to merge chunks (in bytes)
mergeBufferSize int64
// mergeWorkerCount is the number of workers to merge chunks
mergeWorkerCount int
}
// Layer represents a layer. // Layer represents a layer.
type Layer interface { type Layer interface {
// Info returns the information of this layer. // Info returns the information of this layer.
@ -98,6 +110,10 @@ type Layer interface {
// Done releases the reference to this layer. The resources related to this layer will be // Done releases the reference to this layer. The resources related to this layer will be
// discarded sooner or later. Queries after calling this function won't be serviced. // discarded sooner or later. Queries after calling this function won't be serviced.
Done() Done()
// Close is the same as Done. But this evicts the resources related to this Layer immediately.
// This can be used for cleaning up resources on unmount.
Close() error
} }
// Info is the current status of a layer. // Info is the current status of a layer.
@ -219,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,
}, },
) )
} }
@ -249,7 +266,7 @@ func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refs
return &layerRef{l, done}, nil return &layerRef{l, done}, nil
} }
// Cached layer is invalid // Cached layer is invalid
done() done(true)
r.layerCacheMu.Lock() r.layerCacheMu.Lock()
r.layerCache.Remove(name) r.layerCache.Remove(name)
r.layerCacheMu.Unlock() r.layerCacheMu.Unlock()
@ -264,7 +281,7 @@ func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refs
} }
defer func() { defer func() {
if retErr != nil { if retErr != nil {
blobR.done() blobR.done(true)
} }
}() }()
@ -315,7 +332,11 @@ func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refs
} }
// Combine layer information together and cache it. // Combine layer information together and cache it.
l := newLayer(r, desc, blobR, vr) l := newLayer(r, desc, blobR, vr, passThroughConfig{
enable: r.config.PassThrough,
mergeBufferSize: r.config.MergeBufferSize,
mergeWorkerCount: r.config.MergeWorkerCount,
})
r.layerCacheMu.Lock() r.layerCacheMu.Lock()
cachedL, done2, added := r.layerCache.Add(name, l) cachedL, done2, added := r.layerCache.Add(name, l)
r.layerCacheMu.Unlock() r.layerCacheMu.Unlock()
@ -340,7 +361,7 @@ func (r *Resolver) resolveBlob(ctx context.Context, hosts source.RegistryHosts,
return &blobRef{blob, done}, nil return &blobRef{blob, done}, nil
} }
// invalid blob. discard this. // invalid blob. discard this.
done() done(true)
r.blobCacheMu.Lock() r.blobCacheMu.Lock()
r.blobCache.Remove(name) r.blobCache.Remove(name)
r.blobCacheMu.Unlock() r.blobCacheMu.Unlock()
@ -375,6 +396,7 @@ func newLayer(
desc ocispec.Descriptor, desc ocispec.Descriptor,
blob *blobRef, blob *blobRef,
vr *reader.VerifiableReader, vr *reader.VerifiableReader,
pth passThroughConfig,
) *layer { ) *layer {
return &layer{ return &layer{
resolver: resolver, resolver: resolver,
@ -382,6 +404,7 @@ func newLayer(
blob: blob, blob: blob,
verifiableReader: vr, verifiableReader: vr,
prefetchWaiter: newWaiter(), prefetchWaiter: newWaiter(),
passThrough: pth,
} }
} }
@ -402,6 +425,7 @@ type layer struct {
prefetchOnce sync.Once prefetchOnce sync.Once
backgroundFetchOnce sync.Once backgroundFetchOnce sync.Once
passThrough passThroughConfig
} }
func (l *layer) Info() Info { func (l *layer) Info() Info {
@ -573,7 +597,12 @@ func (l *layer) backgroundFetch(ctx context.Context) error {
} }
func (l *layerRef) Done() { func (l *layerRef) Done() {
l.done() l.done(false) // leave chances to reuse this
}
func (l *layerRef) Close() error {
l.done(true) // evict this from the cache
return nil
} }
func (l *layer) RootNode(baseInode uint32) (fusefs.InodeEmbedder, error) { func (l *layer) RootNode(baseInode uint32) (fusefs.InodeEmbedder, error) {
@ -583,7 +612,7 @@ func (l *layer) RootNode(baseInode uint32) (fusefs.InodeEmbedder, error) {
if l.r == nil { if l.r == nil {
return nil, fmt.Errorf("layer hasn't been verified yet") return nil, fmt.Errorf("layer hasn't been verified yet")
} }
return newNode(l.desc.Digest, l.r, l.blob, baseInode, l.resolver.overlayOpaqueType) return newNode(l.desc.Digest, l.r, l.blob, baseInode, l.resolver.overlayOpaqueType, l.passThrough)
} }
func (l *layer) ReadAt(p []byte, offset int64, opts ...remote.Option) (int, error) { func (l *layer) ReadAt(p []byte, offset int64, opts ...remote.Option) (int, error) {
@ -597,7 +626,7 @@ func (l *layer) close() error {
return nil return nil
} }
l.closed = true l.closed = true
defer l.blob.done() // Close reader first, then close the blob defer l.blob.done(true) // Close reader first, then close the blob
l.verifiableReader.Close() l.verifiableReader.Close()
if l.r != nil { if l.r != nil {
return l.r.Close() return l.r.Close()
@ -617,7 +646,7 @@ func (l *layer) isClosed() bool {
// to this blob will be discarded. // to this blob will be discarded.
type blobRef struct { type blobRef struct {
remote.Blob remote.Blob
done func() done func(bool)
} }
// layerRef is a reference to the layer in the cache. Calling `Done` or `done` decreases the // layerRef is a reference to the layer in the cache. Calling `Done` or `done` decreases the
@ -625,7 +654,7 @@ type blobRef struct {
// cache, resources bound to this layer will be discarded. // cache, resources bound to this layer will be discarded.
type layerRef struct { type layerRef struct {
*layer *layer
done func() done func(bool)
} }
func newWaiter() *waiter { func newWaiter() *waiter {

View File

@ -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) {

View File

@ -76,7 +76,7 @@ var opaqueXattrs = map[OverlayOpaqueType][]string{
OverlayOpaqueUser: {"user.overlay.opaque"}, OverlayOpaqueUser: {"user.overlay.opaque"},
} }
func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob, baseInode uint32, opaque OverlayOpaqueType) (fusefs.InodeEmbedder, error) { func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob, baseInode uint32, opaque OverlayOpaqueType, pth passThroughConfig) (fusefs.InodeEmbedder, error) {
rootID := r.Metadata().RootID() rootID := r.Metadata().RootID()
rootAttr, err := r.Metadata().GetAttr(rootID) rootAttr, err := r.Metadata().GetAttr(rootID)
if err != nil { if err != nil {
@ -84,7 +84,7 @@ func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob, baseIno
} }
opq, ok := opaqueXattrs[opaque] opq, ok := opaqueXattrs[opaque]
if !ok { if !ok {
return nil, fmt.Errorf("Unknown overlay opaque type") return nil, fmt.Errorf("unknown overlay opaque type")
} }
ffs := &fs{ ffs := &fs{
r: r, r: r,
@ -92,6 +92,7 @@ func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob, baseIno
baseInode: baseInode, baseInode: baseInode,
rootID: rootID, rootID: rootID,
opaqueXattrs: opq, opaqueXattrs: opq,
passThrough: pth,
} }
ffs.s = ffs.newState(layerDgst, blob) ffs.s = ffs.newState(layerDgst, blob)
return &node{ return &node{
@ -109,6 +110,7 @@ type fs struct {
baseInode uint32 baseInode uint32
rootID uint32 rootID uint32
opaqueXattrs []string opaqueXattrs []string
passThrough passThroughConfig
} }
func (fs *fs) inodeOfState() uint64 { func (fs *fs) inodeOfState() uint64 {
@ -344,10 +346,26 @@ func (n *node) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fu
n.fs.s.report(fmt.Errorf("node.Open: %v", err)) n.fs.s.report(fmt.Errorf("node.Open: %v", err))
return nil, 0, syscall.EIO return nil, 0, syscall.EIO
} }
return &file{
f := &file{
n: n, n: n,
ra: ra, ra: ra,
}, fuse.FOPEN_KEEP_CACHE, 0 fd: -1,
}
if n.fs.passThrough.enable {
if getter, ok := ra.(reader.PassthroughFdGetter); ok {
fd, err := getter.GetPassthroughFd(n.fs.passThrough.mergeBufferSize, n.fs.passThrough.mergeWorkerCount)
if err != nil {
n.fs.s.report(fmt.Errorf("passThrough model failed due to node.Open: %v", err))
n.fs.passThrough.enable = false
} else {
f.InitFd(int(fd))
}
}
}
return f, fuse.FOPEN_KEEP_CACHE, 0
} }
var _ = (fusefs.NodeGetattrer)((*node)(nil)) var _ = (fusefs.NodeGetattrer)((*node)(nil))
@ -424,6 +442,7 @@ func (n *node) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
type file struct { type file struct {
n *node n *node
ra io.ReaderAt ra io.ReaderAt
fd int
} }
var _ = (fusefs.FileReader)((*file)(nil)) var _ = (fusefs.FileReader)((*file)(nil))
@ -451,6 +470,20 @@ func (f *file) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
return 0 return 0
} }
// Implement PassthroughFd to enable go-fuse passthrough
var _ = (fusefs.FilePassthroughFder)((*file)(nil))
func (f *file) PassthroughFd() (int, bool) {
if f.fd <= 0 {
return -1, false
}
return f.fd, true
}
func (f *file) InitFd(fd int) {
f.fd = fd
}
// whiteout is a whiteout abstraction compliant to overlayfs. // whiteout is a whiteout abstraction compliant to overlayfs.
type whiteout struct { type whiteout struct {
fusefs.Inode fusefs.Inode
@ -799,7 +832,7 @@ func defaultStatfs(stat *fuse.StatfsOut) {
stat.Files = 0 // dummy stat.Files = 0 // dummy
stat.Ffree = 0 stat.Ffree = 0
stat.Bsize = blockSize stat.Bsize = blockSize
stat.NameLen = 1<<32 - 1 stat.NameLen = 255 // Standard max filename length for most filesystems (ext4, etc.) for compatibility
stat.Frsize = blockSize stat.Frsize = blockSize
stat.Padding = 0 stat.Padding = 0
stat.Spare = [6]uint32{} stat.Spare = [6]uint32{}

View File

@ -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"
@ -71,18 +70,86 @@ var srcCompressions = map[string]tutil.CompressionFactory{
"externaltoc-gzip-bestspeed": tutil.ExternalTOCGzipCompressionWithLevel(gzip.BestSpeed), "externaltoc-gzip-bestspeed": tutil.ExternalTOCGzipCompressionWithLevel(gzip.BestSpeed),
} }
func TestSuiteLayer(t *testing.T, store metadata.Store) { type layerConfig struct {
testPrefetch(t, store) name string
testNodeRead(t, store) passThroughConfig passThroughConfig
testNodes(t, 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{
{
name: "default",
passThroughConfig: passThroughConfig{
enable: false,
},
},
{
name: "passthrough",
passThroughConfig: passThroughConfig{
enable: true,
mergeBufferSize: 419430400,
mergeWorkerCount: 10,
},
},
{
name: "passthorough without concorrency",
passThroughConfig: passThroughConfig{
enable: true,
mergeBufferSize: 419430400,
mergeWorkerCount: 1,
},
},
{
name: "passthorough with small buffer",
passThroughConfig: passThroughConfig{
enable: true,
mergeBufferSize: 1,
mergeWorkerCount: 10,
},
},
} {
testPrefetch(t, store, lc)
testNodeRead(t, store, lc)
testNodes(t, store, lc)
}
} }
var testStateLayerDigest = digest.FromString("dummy") var testStateLayerDigest = digest.FromString("dummy")
func testPrefetch(t *testing.T, factory metadata.Store) { 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")
} }
@ -102,7 +169,7 @@ func testPrefetch(t *testing.T, factory metadata.Store) {
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
}{ }{
{ {
@ -180,7 +247,7 @@ func testPrefetch(t *testing.T, factory metadata.Store) {
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, 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
@ -216,8 +283,9 @@ func testPrefetch(t *testing.T, factory metadata.Store) {
backgroundTaskManager: task.NewBackgroundTaskManager(10, 5*time.Second), backgroundTaskManager: task.NewBackgroundTaskManager(10, 5*time.Second),
}, },
ocispec.Descriptor{Digest: testStateLayerDigest}, ocispec.Descriptor{Digest: testStateLayerDigest},
&blobRef{blob, func() {}}, &blobRef{blob, func(bool) {}},
vr, vr,
lc.passThroughConfig,
) )
if err := l.Verify(dgst); err != nil { if err := l.Verify(dgst); err != nil {
t.Errorf("failed to verify reader: %v", err) t.Errorf("failed to verify reader: %v", err)
@ -306,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,
@ -314,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
@ -379,7 +447,7 @@ const (
lastChunkOffset1 = sampleChunkSize * (int64(len(sampleData1)) / sampleChunkSize) lastChunkOffset1 = sampleChunkSize * (int64(len(sampleData1)) / sampleChunkSize)
) )
func testNodeRead(t *testing.T, factory metadata.Store) { 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,
@ -404,7 +472,7 @@ func testNodeRead(t *testing.T, factory metadata.Store) {
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", sn, in, bo, fn), 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")
} }
@ -428,7 +496,7 @@ func testNodeRead(t *testing.T, factory metadata.Store) {
} }
// data we get from the file node. // data we get from the file node.
f, closeFn := makeNodeReader(t, []byte(sampleData1)[:filesize], sampleChunkSize, factory, cl) f, closeFn := makeNodeReader(t, []byte(sampleData1)[:filesize], sampleChunkSize, factory, cl, lc)
defer closeFn() defer closeFn()
tmpbuf := make([]byte, size) // fuse library can request bigger than remain tmpbuf := make([]byte, size) // fuse library can request bigger than remain
rr, errno := f.Read(context.Background(), tmpbuf, offset) rr, errno := f.Read(context.Background(), tmpbuf, offset)
@ -459,7 +527,7 @@ func testNodeRead(t *testing.T, factory metadata.Store) {
} }
} }
func makeNodeReader(t *testing.T, contents []byte, chunkSize int, factory metadata.Store, cl tutil.Compression) (_ *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))},
@ -472,7 +540,7 @@ func makeNodeReader(t *testing.T, contents []byte, chunkSize int, factory metada
if err != nil { if err != nil {
t.Fatalf("failed to create reader: %v", err) t.Fatalf("failed to create reader: %v", err)
} }
rootNode := getRootNode(t, r, OverlayOpaqueAll, tocDgst, cache.NewMemoryCache()) rootNode := getRootNode(t, r, OverlayOpaqueAll, tocDgst, cache.NewMemoryCache(), lc)
var eo fuse.EntryOut var eo fuse.EntryOut
inode, errno := rootNode.Lookup(context.Background(), testName, &eo) inode, errno := rootNode.Lookup(context.Background(), testName, &eo)
if errno != 0 { if errno != 0 {
@ -487,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) { 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) testNodesWithOpaque(t, factory, o, lc)
} }
} }
func testNodesWithOpaque(t *testing.T, factory metadata.Store, opaque OverlayOpaqueType) { 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)
} }
@ -702,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, 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)),
} }
@ -724,7 +796,7 @@ func testNodesWithOpaque(t *testing.T, factory metadata.Store, opaque OverlayOpa
} }
defer r.Close() defer r.Close()
mcache := cache.NewMemoryCache() mcache := cache.NewMemoryCache()
rootNode := getRootNode(t, r, opaque, tocDgst, mcache) rootNode := getRootNode(t, r, opaque, tocDgst, mcache, lc)
for _, want := range tt.want { for _, want := range tt.want {
want(t, rootNode, mcache, testR) want(t, rootNode, mcache, testR)
} }
@ -733,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) *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)
@ -742,7 +814,7 @@ func getRootNode(t *testing.T, r metadata.Reader, opaque OverlayOpaqueType, tocD
if err != nil { if err != nil {
t.Fatalf("failed to verify reader: %v", err) t.Fatalf("failed to verify reader: %v", err)
} }
rootNode, err := newNode(testStateLayerDigest, rr, &testBlobState{10, 5}, 100, opaque) rootNode, err := newNode(testStateLayerDigest, rr, &testBlobState{10, 5}, 100, opaque, lc.passThroughConfig)
if err != nil { if err != nil {
t.Fatalf("failed to get root node: %v", err) t.Fatalf("failed to get root node: %v", err)
} }
@ -767,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)
} }
@ -778,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)
@ -807,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)
@ -816,14 +888,14 @@ func hasSize(name string, size int) check {
if errno := n.Operations().(fusefs.NodeGetattrer).Getattr(context.Background(), nil, &ao); errno != 0 { if errno := n.Operations().(fusefs.NodeGetattrer).Getattr(context.Background(), nil, &ao); errno != 0 {
t.Fatalf("failed to get attributes of node %q: %v", name, errno) t.Fatalf("failed to get attributes of node %q: %v", name, errno)
} }
if ao.Attr.Size != uint64(size) { if ao.Size != uint64(size) {
t.Fatalf("got size = %d, want %d", ao.Attr.Size, size) t.Fatalf("got size = %d, want %d", ao.Size, size)
} }
} }
} }
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)
@ -842,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)
@ -878,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)
@ -919,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 {
@ -932,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())
@ -1030,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.
@ -1106,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))
@ -1128,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) {
@ -1150,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)

View File

@ -27,10 +27,12 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"runtime" "runtime"
"sort"
"sync" "sync"
"time" "time"
@ -38,7 +40,6 @@ import (
"github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz"
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common" commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
"github.com/containerd/stargz-snapshotter/metadata" "github.com/containerd/stargz-snapshotter/metadata"
"github.com/hashicorp/go-multierror"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
@ -53,6 +54,10 @@ type Reader interface {
LastOnDemandReadTime() time.Time LastOnDemandReadTime() time.Time
} }
type PassthroughFdGetter interface {
GetPassthroughFd(mergeBufferSize int64, mergeWorkerCount int) (uintptr, error)
}
// VerifiableReader produces a Reader with a given verifier. // VerifiableReader produces a Reader with a given verifier.
type VerifiableReader struct { type VerifiableReader struct {
r *reader r *reader
@ -386,20 +391,21 @@ func (gr *reader) OpenFile(id uint32) (io.ReaderAt, error) {
}, nil }, nil
} }
func (gr *reader) Close() (retErr error) { func (gr *reader) Close() error {
gr.closedMu.Lock() gr.closedMu.Lock()
defer gr.closedMu.Unlock() defer gr.closedMu.Unlock()
if gr.closed { if gr.closed {
return nil return nil
} }
gr.closed = true gr.closed = true
var errs []error
if err := gr.cache.Close(); err != nil { if err := gr.cache.Close(); err != nil {
retErr = multierror.Append(retErr, err) errs = append(errs, err)
} }
if err := gr.r.Close(); err != nil { if err := gr.r.Close(); err != nil {
retErr = multierror.Append(retErr, err) errs = append(errs, err)
} }
return return errors.Join(errs...)
} }
func (gr *reader) isClosed() bool { func (gr *reader) isClosed() bool {
@ -490,18 +496,316 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
return nr, nil return nr, nil
} }
func (gr *reader) verifyAndCache(entryID uint32, ip []byte, chunkDigestStr string, cacheID string) error { type chunkData struct {
// We can end up doing on demand registry fetch when aligning the chunk offset int64
commonmetrics.IncOperationCount(commonmetrics.OnDemandRemoteRegistryFetchCount, gr.layerSha) // increment the number of on demand file fetches from remote registry size int64
commonmetrics.AddBytesCount(commonmetrics.OnDemandBytesFetched, gr.layerSha, int64(len(ip))) // record total bytes fetched digestStr string
gr.setLastReadTime(time.Now()) bufferPos int64
}
// Verify this chunk func (sf *file) GetPassthroughFd(mergeBufferSize int64, mergeWorkerCount int) (uintptr, error) {
var (
offset int64
firstChunkOffset int64
totalSize int64
hasLargeChunk bool
)
var chunks []chunkData
for {
chunkOffset, chunkSize, digestStr, ok := sf.fr.ChunkEntryForOffset(offset)
if !ok {
break
}
// Check if any chunk size exceeds merge buffer size to avoid bounds out of range
if chunkSize > mergeBufferSize {
hasLargeChunk = true
}
chunks = append(chunks, chunkData{
offset: chunkOffset,
size: chunkSize,
digestStr: digestStr,
})
totalSize += chunkSize
offset = chunkOffset + chunkSize
}
id := genID(sf.id, firstChunkOffset, totalSize)
// cache.PassThrough() is necessary to take over files
r, err := sf.gr.cache.Get(id, cache.PassThrough())
if err != nil {
if hasLargeChunk {
if err := sf.prefetchEntireFileSequential(id); err != nil {
return 0, err
}
} else {
if err := sf.prefetchEntireFile(id, chunks, totalSize, mergeBufferSize, mergeWorkerCount); err != nil {
return 0, err
}
}
// just retry once to avoid exception stuck
r, err = sf.gr.cache.Get(id, cache.PassThrough())
if err != nil {
return 0, err
}
}
readerAt := r.GetReaderAt()
file, ok := readerAt.(*os.File)
if !ok {
r.Close()
return 0, fmt.Errorf("the cached ReaderAt is not of type *os.File, fd obtain failed")
}
fd := file.Fd()
r.Close()
return fd, nil
}
// prefetchEntireFileSequential uses the legacy sequential approach for processing chunks
// when chunk size exceeds merge buffer size to avoid slice bounds out of range panic
func (sf *file) prefetchEntireFileSequential(entireCacheID string) error {
w, err := sf.gr.cache.Add(entireCacheID)
if err != nil {
return fmt.Errorf("failed to create cache writer: %w", err)
}
defer w.Close()
var offset int64
for {
chunkOffset, chunkSize, chunkDigestStr, ok := sf.fr.ChunkEntryForOffset(offset)
if !ok {
break
}
id := genID(sf.id, chunkOffset, chunkSize)
b := sf.gr.bufPool.Get().(*bytes.Buffer)
b.Reset()
b.Grow(int(chunkSize))
ip := b.Bytes()[:chunkSize]
if r, err := sf.gr.cache.Get(id); err == nil {
n, err := r.ReadAt(ip, 0)
if (err == nil || err == io.EOF) && int64(n) == chunkSize {
if _, err := w.Write(ip[:n]); err != nil {
r.Close()
sf.gr.putBuffer(b)
w.Abort()
return fmt.Errorf("failed to write cached data: %w", err)
}
offset = chunkOffset + int64(n)
r.Close()
sf.gr.putBuffer(b)
continue
}
r.Close()
}
if _, err := sf.fr.ReadAt(ip, chunkOffset); err != nil && err != io.EOF {
sf.gr.putBuffer(b)
w.Abort()
return fmt.Errorf("failed to read data: %w", err)
}
if err := sf.gr.verifyOneChunk(sf.id, ip, chunkDigestStr); err != nil {
sf.gr.putBuffer(b)
w.Abort()
return err
}
if _, err := w.Write(ip); err != nil {
sf.gr.putBuffer(b)
w.Abort()
return fmt.Errorf("failed to write fetched data: %w", err)
}
offset = chunkOffset + chunkSize
sf.gr.putBuffer(b)
}
return w.Commit()
}
type batchWorkerArgs struct {
workerID int
chunks []chunkData
buffer []byte
workerCount int
readInfos []chunkReadInfo
}
func (sf *file) prefetchEntireFile(entireCacheID string, chunks []chunkData, totalSize int64, bufferSize int64, workerCount int) error {
w, err := sf.gr.cache.Add(entireCacheID)
if err != nil {
return fmt.Errorf("failed to create cache writer: %w", err)
}
defer w.Close()
batchCount := (totalSize + bufferSize - 1) / bufferSize
for batchIdx := int64(0); batchIdx < batchCount; batchIdx++ {
batchStart := batchIdx * bufferSize
batchEnd := (batchIdx + 1) * bufferSize
if batchEnd > totalSize {
batchEnd = totalSize
}
var batchChunks []chunkData
var batchOffset int64
for i := range chunks {
chunkStart := chunks[i].offset
chunkEnd := chunkStart + chunks[i].size
if chunkEnd <= batchStart {
continue
}
if chunkStart >= batchEnd {
break
}
chunks[i].bufferPos = batchOffset
batchOffset += chunks[i].size
batchChunks = append(batchChunks, chunks[i])
}
batchSize := batchEnd - batchStart
buffer := make([]byte, batchSize)
eg := errgroup.Group{}
allReadInfos := make([][]chunkReadInfo, workerCount)
for i := 0; i < workerCount && i < len(batchChunks); i++ {
workerID := i
args := &batchWorkerArgs{
workerID: workerID,
chunks: batchChunks,
buffer: buffer,
workerCount: workerCount,
}
eg.Go(func() error {
err := sf.processBatchChunks(args)
if err == nil && len(args.readInfos) > 0 {
allReadInfos[args.workerID] = args.readInfos
}
return err
})
}
if err := eg.Wait(); err != nil {
w.Abort()
return err
}
var mergedReadInfos []chunkReadInfo
for _, infos := range allReadInfos {
mergedReadInfos = append(mergedReadInfos, infos...)
}
if err := sf.checkHoles(mergedReadInfos, batchSize); err != nil {
w.Abort()
return fmt.Errorf("hole check failed: %w", err)
}
n, err := w.Write(buffer)
if err != nil {
w.Abort()
return fmt.Errorf("failed to write batch data: %w", err)
}
if int64(n) != batchSize {
w.Abort()
return fmt.Errorf("incomplete write: expected %d bytes, wrote %d bytes", batchSize, n)
}
}
return w.Commit()
}
type chunkReadInfo struct {
offset int64
size int64
}
func (sf *file) checkHoles(readInfos []chunkReadInfo, totalSize int64) error {
if len(readInfos) == 0 {
return nil
}
sort.Slice(readInfos, func(i, j int) bool {
return readInfos[i].offset < readInfos[j].offset
})
end := readInfos[0].offset
for _, info := range readInfos {
if info.offset < end {
return fmt.Errorf("overlapping read detected: previous end %d, current start %d", end, info.offset)
} else if info.offset > end {
return fmt.Errorf("hole detected in read: previous end %d, current start %d", end, info.offset)
}
end = info.offset + info.size
}
if end != totalSize {
return fmt.Errorf("incomplete read: expected total size %d, actual end %d", totalSize, end)
}
return nil
}
func (sf *file) processBatchChunks(args *batchWorkerArgs) error {
var readInfos []chunkReadInfo
for chunkIdx := args.workerID; chunkIdx < len(args.chunks); chunkIdx += args.workerCount {
chunk := args.chunks[chunkIdx]
bufStart := args.buffer[chunk.bufferPos : chunk.bufferPos+chunk.size]
id := genID(sf.id, chunk.offset, chunk.size)
if r, err := sf.gr.cache.Get(id); err == nil {
n, err := r.ReadAt(bufStart, 0)
r.Close()
if err == nil || err == io.EOF {
if int64(n) == chunk.size {
readInfos = append(readInfos, chunkReadInfo{
offset: chunk.bufferPos,
size: int64(n),
})
continue
}
}
}
n, err := sf.fr.ReadAt(bufStart, chunk.offset)
if err != nil && err != io.EOF {
return fmt.Errorf("failed to read data at offset %d: %w", chunk.offset, err)
}
readInfos = append(readInfos, chunkReadInfo{
offset: chunk.bufferPos,
size: int64(n),
})
if err := sf.gr.verifyOneChunk(sf.id, bufStart, chunk.digestStr); err != nil {
return fmt.Errorf("chunk verification failed at offset %d: %w", chunk.offset, err)
}
}
args.readInfos = readInfos
return nil
}
func (gr *reader) verifyOneChunk(entryID uint32, ip []byte, chunkDigestStr string) error {
// We can end up doing on demand registry fetch when aligning the chunk
commonmetrics.IncOperationCount(commonmetrics.OnDemandRemoteRegistryFetchCount, gr.layerSha)
commonmetrics.AddBytesCount(commonmetrics.OnDemandBytesFetched, gr.layerSha, int64(len(ip)))
gr.setLastReadTime(time.Now())
if err := gr.verifyChunk(entryID, ip, chunkDigestStr); err != nil { if err := gr.verifyChunk(entryID, ip, chunkDigestStr); err != nil {
return fmt.Errorf("invalid chunk: %w", err) return fmt.Errorf("invalid chunk: %w", err)
} }
return nil
}
// Cache this chunk func (gr *reader) cacheData(ip []byte, cacheID string) {
if w, err := gr.cache.Add(cacheID); err == nil { if w, err := gr.cache.Add(cacheID); err == nil {
if cn, err := w.Write(ip); err != nil || cn != len(ip) { if cn, err := w.Write(ip); err != nil || cn != len(ip) {
w.Abort() w.Abort()
@ -510,7 +814,13 @@ func (gr *reader) verifyAndCache(entryID uint32, ip []byte, chunkDigestStr strin
} }
w.Close() w.Close()
} }
}
func (gr *reader) verifyAndCache(entryID uint32, ip []byte, chunkDigestStr string, cacheID string) error {
if err := gr.verifyOneChunk(entryID, ip, chunkDigestStr); err != nil {
return err
}
gr.cacheData(ip, cacheID)
return nil return nil
} }

View File

@ -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)
} }

View File

@ -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"
@ -59,14 +58,47 @@ var srcCompressions = map[string]tutil.CompressionFactory{
"externaltoc-gzip-bestspeed": tutil.ExternalTOCGzipCompressionWithLevel(gzip.BestSpeed), "externaltoc-gzip-bestspeed": tutil.ExternalTOCGzipCompressionWithLevel(gzip.BestSpeed),
} }
func TestSuiteReader(t *testing.T, store metadata.Store) { // MockReadAtOutput defines the default output size for mocked read operations
var (
MockReadAtOutput = 4194304
)
// 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)
testPreReader(t, store) testPreReader(t, store)
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,
@ -103,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")
} }
@ -193,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 {
@ -205,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) {
@ -219,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)),
@ -259,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} {
@ -267,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"),
@ -477,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{
@ -589,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
@ -660,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)),
} }
@ -699,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
@ -709,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)
@ -744,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)
@ -819,3 +855,183 @@ func (b longBytesView) String() string {
} }
return string(b[:50]) + "...(omit)..." + string(b[len(b)-50:]) return string(b[:50]) + "...(omit)..." + string(b[len(b)-50:])
} }
func makeMockFile(id uint32) *file {
mockCache := &mockCache{
getError: fmt.Errorf("mock cache get error"),
}
mockFile := &mockFile{}
gr := &reader{
cache: mockCache,
}
return &file{
id: id,
fr: mockFile,
gr: gr,
}
}
type mockCache struct {
getError error
}
func (c *mockCache) Add(key string, opts ...cache.Option) (cache.Writer, error) {
return nil, fmt.Errorf("not implemented")
}
func (c *mockCache) Get(key string, opts ...cache.Option) (cache.Reader, error) {
return nil, c.getError
}
func (c *mockCache) Close() error {
return nil
}
type mockFile struct{}
func (f *mockFile) ChunkEntryForOffset(offset int64) (off int64, size int64, dgst string, ok bool) {
return 0, 0, "", true
}
func (f *mockFile) ReadAt(p []byte, offset int64) (int, error) {
return MockReadAtOutput, nil
}
func testProcessBatchChunks(t *TestRunner) {
type testCase struct {
name string
setupMock func()
createChunks func(chunkSize int64, totalChunks int) []chunkData
expectErrorInHoles bool
}
runTest := func(t TestingT, tc testCase) {
if tc.setupMock != nil {
tc.setupMock()
}
sf := makeMockFile(1)
const (
bufferSize int64 = 400 * 1024 * 1024
chunkSize int64 = 4 * 1024 * 1024
workerCount int = 10
totalChunks int = 100
)
chunks := tc.createChunks(chunkSize, totalChunks)
buffer := make([]byte, bufferSize)
allReadInfos := make([][]chunkReadInfo, workerCount)
eg := errgroup.Group{}
for i := 0; i < workerCount && i < len(chunks); i++ {
workerID := i
args := &batchWorkerArgs{
workerID: workerID,
chunks: chunks,
buffer: buffer,
workerCount: workerCount,
}
eg.Go(func() error {
err := sf.processBatchChunks(args)
if err == nil && len(args.readInfos) > 0 {
allReadInfos[args.workerID] = args.readInfos
}
return err
})
}
if err := eg.Wait(); err != nil {
t.Fatalf("processBatchChunks failed: %v", err)
}
var mergedReadInfos []chunkReadInfo
for _, infos := range allReadInfos {
mergedReadInfos = append(mergedReadInfos, infos...)
}
err := sf.checkHoles(mergedReadInfos, bufferSize)
if tc.expectErrorInHoles {
if err == nil {
t.Fatalf("checkHoles should have detected issues but didn't")
}
t.Logf("Expected error detected: %v", err)
} else {
if err != nil {
t.Fatalf("checkHoles failed: %v", err)
}
}
}
createNormalChunks := func(chunkSize int64, totalChunks int) []chunkData {
var chunks []chunkData
for i := 0; i < totalChunks; i++ {
chunks = append(chunks, chunkData{
offset: int64(i) * chunkSize,
size: chunkSize,
digestStr: fmt.Sprintf("sha256:%d", i),
bufferPos: int64(i) * chunkSize,
})
}
return chunks
}
createOverlappingChunks := func(chunkSize int64, totalChunks int) []chunkData {
chunks := createNormalChunks(chunkSize, totalChunks)
for i := 0; i < totalChunks; i++ {
if i > 0 && i%10 == 0 {
chunks = append(chunks, chunkData{
offset: int64(i)*chunkSize - chunkSize/2,
size: chunkSize,
digestStr: fmt.Sprintf("sha256:overlap-%d", i),
bufferPos: int64(i) * chunkSize,
})
if i < totalChunks-1 {
chunks = append(chunks, chunkData{
offset: int64(i+1)*chunkSize + chunkSize/2,
size: chunkSize,
digestStr: fmt.Sprintf("sha256:gap-%d", i),
bufferPos: int64(i+2) * chunkSize,
})
}
}
}
return chunks
}
tests := []testCase{
{
name: "test_process_batch_chunks_and_check_holes",
createChunks: createNormalChunks,
expectErrorInHoles: false,
},
{
name: "test_process_batch_chunks_with_holes",
setupMock: func() {
originalMockReadAtOutput := MockReadAtOutput
MockReadAtOutput = MockReadAtOutput / 2
t.Cleanup(func() {
MockReadAtOutput = originalMockReadAtOutput
})
},
createChunks: createNormalChunks,
expectErrorInHoles: true,
},
{
name: "test_process_batch_chunks_with_overlapping",
createChunks: createOverlappingChunks,
expectErrorInHoles: true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *TestRunner) {
runTest(t, tc)
})
}
}

View File

@ -120,7 +120,7 @@ func (b *blob) Refresh(ctx context.Context, hosts source.RegistryHosts, refspec
return err return err
} }
if newSize != b.size { if newSize != b.size {
return fmt.Errorf("Invalid size of new blob %d; want %d", newSize, b.size) return fmt.Errorf("invalid size of new blob %d; want %d", newSize, b.size)
} }
// update the blob's fetcher with new one // update the blob's fetcher with new one
@ -259,13 +259,23 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) {
o(&readAtOpts) o(&readAtOpts)
} }
// Fetcher can be suddenly updated so we take and use the snapshot of it for fr := b.getFetcher()
// consistency.
b.fetcherMu.Lock()
fr := b.fetcher
b.fetcherMu.Unlock()
b.walkChunks(allRegion, func(chunk region) error { if err := b.prepareChunksForRead(allRegion, offset, p, fr, allData, &readAtOpts); err != nil {
return 0, err
}
// Read required data
if err := b.fetchRange(allData, &readAtOpts); err != nil {
return 0, err
}
return b.adjustBufferSize(p, offset), nil
}
// prepareChunksForRead prepares chunks for reading by checking cache and setting up writers
func (b *blob) prepareChunksForRead(allRegion region, offset int64, p []byte, fr fetcher, allData map[region]io.Writer, opts *options) error {
return b.walkChunks(allRegion, func(chunk region) error {
var ( var (
base = positive(chunk.b - offset) base = positive(chunk.b - offset)
lowerUnread = positive(offset - chunk.b) lowerUnread = positive(offset - chunk.b)
@ -273,14 +283,9 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) {
expectedSize = chunk.size() - upperUnread - lowerUnread expectedSize = chunk.size() - upperUnread - lowerUnread
) )
// Check if the content exists in the cache // Try to read from cache first
r, err := b.cache.Get(fr.genID(chunk), readAtOpts.cacheOpts...) if err := b.readFromCache(chunk, p[base:base+expectedSize], lowerUnread, fr, opts); err == nil {
if err == nil { return nil
defer r.Close()
n, err := r.ReadAt(p[base:base+expectedSize], lowerUnread)
if (err == nil || err == io.EOF) && int64(n) == expectedSize {
return nil
}
} }
// We missed cache. Take it from remote registry. // We missed cache. Take it from remote registry.
@ -289,21 +294,23 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) {
allData[chunk] = newBytesWriter(p[base:base+expectedSize], lowerUnread) allData[chunk] = newBytesWriter(p[base:base+expectedSize], lowerUnread)
return nil return nil
}) })
}
// Read required data // readFromCache attempts to read chunk data from cache
if err := b.fetchRange(allData, &readAtOpts); err != nil { func (b *blob) readFromCache(chunk region, dest []byte, offset int64, fr fetcher, opts *options) error {
return 0, err r, err := b.cache.Get(fr.genID(chunk), opts.cacheOpts...)
if err != nil {
return err
} }
defer r.Close()
// Adjust the buffer size according to the blob size n, err := r.ReadAt(dest, offset)
if remain := b.size - offset; int64(len(p)) >= remain { if err != nil && err != io.EOF {
if remain < 0 { return err
remain = 0
}
p = p[:remain]
} }
if n != len(dest) {
return len(p), nil return fmt.Errorf("incomplete read from cache: read %d bytes, expected %d bytes", n, len(dest))
}
return nil
} }
// fetchRegions fetches all specified chunks from remote blob and puts it in the local cache. // fetchRegions fetches all specified chunks from remote blob and puts it in the local cache.
@ -313,11 +320,7 @@ func (b *blob) fetchRegions(allData map[region]io.Writer, fetched map[region]boo
return nil return nil
} }
// Fetcher can be suddenly updated so we take and use the snapshot of it for fr := b.getFetcher()
// consistency.
b.fetcherMu.Lock()
fr := b.fetcher
b.fetcherMu.Unlock()
// request missed regions // request missed regions
var req []region var req []region
@ -332,7 +335,6 @@ func (b *blob) fetchRegions(allData map[region]io.Writer, fetched map[region]boo
fetchCtx = opts.ctx fetchCtx = opts.ctx
} }
mr, err := fr.fetch(fetchCtx, req, true) mr, err := fr.fetch(fetchCtx, req, true)
if err != nil { if err != nil {
return err return err
} }
@ -353,35 +355,9 @@ func (b *blob) fetchRegions(allData map[region]io.Writer, fetched map[region]boo
return fmt.Errorf("failed to read multipart resp: %w", err) return fmt.Errorf("failed to read multipart resp: %w", err)
} }
if err := b.walkChunks(reg, func(chunk region) (retErr error) { if err := b.walkChunks(reg, func(chunk region) (retErr error) {
id := fr.genID(chunk) if err := b.cacheChunkData(chunk, p, fr, allData, fetched, opts); err != nil {
cw, err := b.cache.Add(id, opts.cacheOpts...)
if err != nil {
return err return err
} }
defer cw.Close()
w := io.Writer(cw)
// If this chunk is one of the targets, write the content to the
// passed reader too.
if _, ok := fetched[chunk]; ok {
w = io.MultiWriter(w, allData[chunk])
}
// Copy the target chunk
if _, err := io.CopyN(w, p, chunk.size()); err != nil {
cw.Abort()
return err
}
// Add the target chunk to the cache
if err := cw.Commit(); err != nil {
return err
}
b.fetchedRegionSetMu.Lock()
b.fetchedRegionSet.add(chunk)
b.fetchedRegionSetMu.Unlock()
fetched[chunk] = true
return nil return nil
}); err != nil { }); err != nil {
return fmt.Errorf("failed to get chunks: %w", err) return fmt.Errorf("failed to get chunks: %w", err)
@ -408,9 +384,6 @@ func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error {
return nil return nil
} }
// We build a key based on regions we need to fetch and pass it to singleflightGroup.Do(...)
// to block simultaneous same requests. Once the request is finished and the data is ready,
// all blocked callers will be unblocked and that same data will be returned by all blocked callers.
key := makeSyncKey(allData) key := makeSyncKey(allData)
fetched := make(map[region]bool) fetched := make(map[region]bool)
_, err, shared := b.fetchedRegionGroup.Do(key, func() (interface{}, error) { _, err, shared := b.fetchedRegionGroup.Do(key, func() (interface{}, error) {
@ -420,46 +393,66 @@ func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error {
// When unblocked try to read from cache in case if there were no errors // When unblocked try to read from cache in case if there were no errors
// If we fail reading from cache, fetch from remote registry again // If we fail reading from cache, fetch from remote registry again
if err == nil && shared { if err == nil && shared {
for reg := range allData { if err := b.handleSharedFetch(allData, fetched, opts); err != nil {
if _, ok := fetched[reg]; ok { return b.fetchRange(allData, opts) // retry on error
continue
}
err = b.walkChunks(reg, func(chunk region) error {
b.fetcherMu.Lock()
fr := b.fetcher
b.fetcherMu.Unlock()
// Check if the content exists in the cache
// And if exists, read from cache
r, err := b.cache.Get(fr.genID(chunk), opts.cacheOpts...)
if err != nil {
return err
}
defer r.Close()
rr := io.NewSectionReader(r, 0, chunk.size())
// Copy the target chunk
b.fetchedRegionCopyMu.Lock()
defer b.fetchedRegionCopyMu.Unlock()
if _, err := io.CopyN(allData[chunk], rr, chunk.size()); err != nil {
return err
}
return nil
})
if err != nil {
break
}
}
// if we cannot read the data from cache, do fetch again
if err != nil {
return b.fetchRange(allData, opts)
} }
} }
return err return err
} }
// handleSharedFetch handles the case when multiple goroutines share the same fetch result
func (b *blob) handleSharedFetch(allData map[region]io.Writer, fetched map[region]bool, opts *options) error {
for reg := range allData {
if _, ok := fetched[reg]; ok {
continue
}
if err := b.copyFetchedChunks(reg, allData, opts); err != nil {
return err
}
}
return nil
}
// copyFetchedChunks copies fetched chunks from cache to target writer
func (b *blob) copyFetchedChunks(reg region, allData map[region]io.Writer, opts *options) error {
return b.walkChunks(reg, func(chunk region) error {
fr := b.getFetcher()
r, err := b.cache.Get(fr.genID(chunk), opts.cacheOpts...)
if err != nil {
return err
}
defer r.Close()
b.fetchedRegionCopyMu.Lock()
defer b.fetchedRegionCopyMu.Unlock()
if _, err := io.CopyN(allData[chunk], io.NewSectionReader(r, 0, chunk.size()), chunk.size()); err != nil {
return err
}
return nil
})
}
// getFetcher safely gets the current fetcher
// Fetcher can be suddenly updated so we take and use the snapshot of it for consistency.
func (b *blob) getFetcher() fetcher {
b.fetcherMu.Lock()
defer b.fetcherMu.Unlock()
return b.fetcher
}
// adjustBufferSize adjusts buffer size according to the blob size
func (b *blob) adjustBufferSize(p []byte, offset int64) int {
if remain := b.size - offset; int64(len(p)) >= remain {
if remain < 0 {
remain = 0
}
p = p[:remain]
}
return len(p)
}
type walkFunc func(reg region) error type walkFunc func(reg region) error
// walkChunks walks chunks from begin to end in order in the specified region. // walkChunks walks chunks from begin to end in order in the specified region.
@ -533,3 +526,34 @@ func positive(n int64) int64 {
} }
return n return n
} }
// cacheChunkData handles caching of chunk data
func (b *blob) cacheChunkData(chunk region, r io.Reader, fr fetcher, allData map[region]io.Writer, fetched map[region]bool, opts *options) error {
id := fr.genID(chunk)
cw, err := b.cache.Add(id, opts.cacheOpts...)
if err != nil {
return fmt.Errorf("failed to create cache writer: %w", err)
}
defer cw.Close()
w := io.Writer(cw)
if _, ok := fetched[chunk]; ok {
w = io.MultiWriter(w, allData[chunk])
}
if _, err := io.CopyN(w, r, chunk.size()); err != nil {
cw.Abort()
return fmt.Errorf("failed to write chunk data: %w", err)
}
if err := cw.Commit(); err != nil {
return fmt.Errorf("failed to commit chunk: %w", err)
}
b.fetchedRegionSetMu.Lock()
b.fetchedRegionSet.add(chunk)
b.fetchedRegionSetMu.Unlock()
fetched[chunk] = true
return nil
}

View File

@ -609,7 +609,7 @@ func TestCheckInterval(t *testing.T) {
if !tr.called { if !tr.called {
return b.lastCheck, false return b.lastCheck, false
} }
if !(b.lastCheck.After(beforeUpdate) && b.lastCheck.Before(afterUpdate)) { if !b.lastCheck.After(beforeUpdate) || !b.lastCheck.Before(afterUpdate) {
t.Errorf("%q: updated time must be after %q and before %q but %q", name, beforeUpdate, afterUpdate, b.lastCheck) t.Errorf("%q: updated time must be after %q and before %q but %q", name, beforeUpdate, afterUpdate, b.lastCheck)
} }

View File

@ -26,6 +26,7 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"errors"
"fmt" "fmt"
"io" "io"
"math/big" "math/big"
@ -46,7 +47,6 @@ import (
"github.com/containerd/stargz-snapshotter/fs/config" "github.com/containerd/stargz-snapshotter/fs/config"
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common" commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
"github.com/containerd/stargz-snapshotter/fs/source" "github.com/containerd/stargz-snapshotter/fs/source"
"github.com/hashicorp/go-multierror"
rhttp "github.com/hashicorp/go-retryablehttp" rhttp "github.com/hashicorp/go-retryablehttp"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -122,19 +122,19 @@ func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refs
func (r *Resolver) resolveFetcher(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (f fetcher, size int64, err error) { func (r *Resolver) resolveFetcher(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (f fetcher, size int64, err error) {
blobConfig := &r.blobConfig blobConfig := &r.blobConfig
fc := &fetcherConfig{ fc := &fetcherConfig{
hosts: hosts, hosts: hosts,
refspec: refspec, refspec: refspec,
desc: desc, desc: desc,
maxRetries: blobConfig.MaxRetries, maxRetries: blobConfig.MaxRetries,
minWaitMSec: time.Duration(blobConfig.MinWaitMSec) * time.Millisecond, minWait: time.Duration(blobConfig.MinWaitMSec) * time.Millisecond,
maxWaitMSec: time.Duration(blobConfig.MaxWaitMSec) * time.Millisecond, maxWait: time.Duration(blobConfig.MaxWaitMSec) * time.Millisecond,
} }
var handlersErr error var errs []error
for name, p := range r.handlers { for name, p := range r.handlers {
// TODO: allow to configure the selection of readers based on the hostname in refspec // TODO: allow to configure the selection of readers based on the hostname in refspec
r, size, err := p.Handle(ctx, desc) r, size, err := p.Handle(ctx, desc)
if err != nil { if err != nil {
handlersErr = multierror.Append(handlersErr, err) errs = append(errs, err)
continue continue
} }
log.G(ctx).WithField("handler name", name).WithField("ref", refspec.String()).WithField("digest", desc.Digest). log.G(ctx).WithField("handler name", name).WithField("ref", refspec.String()).WithField("digest", desc.Digest).
@ -142,6 +142,8 @@ func (r *Resolver) resolveFetcher(ctx context.Context, hosts source.RegistryHost
return &remoteFetcher{r}, size, nil return &remoteFetcher{r}, size, nil
} }
handlersErr := errors.Join(errs...)
log.G(ctx).WithError(handlersErr).WithField("ref", refspec.String()).WithField("digest", desc.Digest).Debugf("using default handler") log.G(ctx).WithError(handlersErr).WithField("ref", refspec.String()).WithField("digest", desc.Digest).Debugf("using default handler")
hf, size, err := newHTTPFetcher(ctx, fc) hf, size, err := newHTTPFetcher(ctx, fc)
if err != nil { if err != nil {
@ -154,12 +156,12 @@ func (r *Resolver) resolveFetcher(ctx context.Context, hosts source.RegistryHost
} }
type fetcherConfig struct { type fetcherConfig struct {
hosts source.RegistryHosts hosts source.RegistryHosts
refspec reference.Spec refspec reference.Spec
desc ocispec.Descriptor desc ocispec.Descriptor
maxRetries int maxRetries int
minWaitMSec time.Duration minWait time.Duration
maxWaitMSec time.Duration maxWait time.Duration
} }
func jitter(duration time.Duration) time.Duration { func jitter(duration time.Duration) time.Duration {
@ -200,7 +202,7 @@ func newHTTPFetcher(ctx context.Context, fc *fetcherConfig) (*httpFetcher, int64
} }
desc := fc.desc desc := fc.desc
if desc.Digest.String() == "" { if desc.Digest.String() == "" {
return nil, 0, fmt.Errorf("Digest is mandatory in layer descriptor") return nil, 0, fmt.Errorf("digest is mandatory in layer descriptor")
} }
digest := desc.Digest digest := desc.Digest
pullScope, err := docker.RepositoryScope(fc.refspec, false) pullScope, err := docker.RepositoryScope(fc.refspec, false)
@ -223,8 +225,8 @@ func newHTTPFetcher(ctx context.Context, fc *fetcherConfig) (*httpFetcher, int64
timeout := host.Client.Timeout timeout := host.Client.Timeout
if rt, ok := tr.(*rhttp.RoundTripper); ok { if rt, ok := tr.(*rhttp.RoundTripper); ok {
rt.Client.RetryMax = fc.maxRetries rt.Client.RetryMax = fc.maxRetries
rt.Client.RetryWaitMin = fc.minWaitMSec rt.Client.RetryWaitMin = fc.minWait
rt.Client.RetryWaitMax = fc.maxWaitMSec rt.Client.RetryWaitMax = fc.maxWait
rt.Client.Backoff = backoffStrategy rt.Client.Backoff = backoffStrategy
rt.Client.CheckRetry = retryStrategy rt.Client.CheckRetry = retryStrategy
timeout = rt.Client.HTTPClient.Timeout timeout = rt.Client.HTTPClient.Timeout
@ -406,9 +408,10 @@ func getSize(ctx context.Context, url string, tr http.RoundTripper, timeout time
res.Body.Close() res.Body.Close()
}() }()
if res.StatusCode == http.StatusOK { switch res.StatusCode {
case http.StatusOK:
return strconv.ParseInt(res.Header.Get("Content-Length"), 10, 64) return strconv.ParseInt(res.Header.Get("Content-Length"), 10, 64)
} else if res.StatusCode == http.StatusPartialContent { case http.StatusPartialContent:
_, size, err := parseRange(res.Header.Get("Content-Range")) _, size, err := parseRange(res.Header.Get("Content-Range"))
return size, err return size, err
} }
@ -556,9 +559,10 @@ func (f *httpFetcher) check() error {
io.Copy(io.Discard, res.Body) io.Copy(io.Discard, res.Body)
res.Body.Close() res.Body.Close()
}() }()
if res.StatusCode == http.StatusOK || res.StatusCode == http.StatusPartialContent { switch res.StatusCode {
case http.StatusOK, http.StatusPartialContent:
return nil return nil
} else if res.StatusCode == http.StatusForbidden { case http.StatusForbidden:
// Try to re-redirect this blob // Try to re-redirect this blob
rCtx := context.Background() rCtx := context.Background()
if f.timeout > 0 { if f.timeout > 0 {

566
fusemanager/api/api.pb.go Normal file
View File

@ -0,0 +1,566 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: api.proto
package api
import (
context "context"
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type StatusRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StatusRequest) Reset() { *m = StatusRequest{} }
func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
func (*StatusRequest) ProtoMessage() {}
func (*StatusRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{0}
}
func (m *StatusRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusRequest.Unmarshal(m, b)
}
func (m *StatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StatusRequest.Marshal(b, m, deterministic)
}
func (m *StatusRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_StatusRequest.Merge(m, src)
}
func (m *StatusRequest) XXX_Size() int {
return xxx_messageInfo_StatusRequest.Size(m)
}
func (m *StatusRequest) XXX_DiscardUnknown() {
xxx_messageInfo_StatusRequest.DiscardUnknown(m)
}
var xxx_messageInfo_StatusRequest proto.InternalMessageInfo
type InitRequest struct {
Root string `protobuf:"bytes,1,opt,name=root,proto3" json:"root,omitempty"`
Config []byte `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *InitRequest) Reset() { *m = InitRequest{} }
func (m *InitRequest) String() string { return proto.CompactTextString(m) }
func (*InitRequest) ProtoMessage() {}
func (*InitRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{1}
}
func (m *InitRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InitRequest.Unmarshal(m, b)
}
func (m *InitRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_InitRequest.Marshal(b, m, deterministic)
}
func (m *InitRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_InitRequest.Merge(m, src)
}
func (m *InitRequest) XXX_Size() int {
return xxx_messageInfo_InitRequest.Size(m)
}
func (m *InitRequest) XXX_DiscardUnknown() {
xxx_messageInfo_InitRequest.DiscardUnknown(m)
}
var xxx_messageInfo_InitRequest proto.InternalMessageInfo
func (m *InitRequest) GetRoot() string {
if m != nil {
return m.Root
}
return ""
}
func (m *InitRequest) GetConfig() []byte {
if m != nil {
return m.Config
}
return nil
}
type MountRequest struct {
Mountpoint string `protobuf:"bytes,1,opt,name=mountpoint,proto3" json:"mountpoint,omitempty"`
Labels map[string]string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MountRequest) Reset() { *m = MountRequest{} }
func (m *MountRequest) String() string { return proto.CompactTextString(m) }
func (*MountRequest) ProtoMessage() {}
func (*MountRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{2}
}
func (m *MountRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MountRequest.Unmarshal(m, b)
}
func (m *MountRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_MountRequest.Marshal(b, m, deterministic)
}
func (m *MountRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_MountRequest.Merge(m, src)
}
func (m *MountRequest) XXX_Size() int {
return xxx_messageInfo_MountRequest.Size(m)
}
func (m *MountRequest) XXX_DiscardUnknown() {
xxx_messageInfo_MountRequest.DiscardUnknown(m)
}
var xxx_messageInfo_MountRequest proto.InternalMessageInfo
func (m *MountRequest) GetMountpoint() string {
if m != nil {
return m.Mountpoint
}
return ""
}
func (m *MountRequest) GetLabels() map[string]string {
if m != nil {
return m.Labels
}
return nil
}
type CheckRequest struct {
Mountpoint string `protobuf:"bytes,1,opt,name=mountpoint,proto3" json:"mountpoint,omitempty"`
Labels map[string]string `protobuf:"bytes,2,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CheckRequest) Reset() { *m = CheckRequest{} }
func (m *CheckRequest) String() string { return proto.CompactTextString(m) }
func (*CheckRequest) ProtoMessage() {}
func (*CheckRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{3}
}
func (m *CheckRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CheckRequest.Unmarshal(m, b)
}
func (m *CheckRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CheckRequest.Marshal(b, m, deterministic)
}
func (m *CheckRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CheckRequest.Merge(m, src)
}
func (m *CheckRequest) XXX_Size() int {
return xxx_messageInfo_CheckRequest.Size(m)
}
func (m *CheckRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CheckRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CheckRequest proto.InternalMessageInfo
func (m *CheckRequest) GetMountpoint() string {
if m != nil {
return m.Mountpoint
}
return ""
}
func (m *CheckRequest) GetLabels() map[string]string {
if m != nil {
return m.Labels
}
return nil
}
type UnmountRequest struct {
Mountpoint string `protobuf:"bytes,1,opt,name=mountpoint,proto3" json:"mountpoint,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *UnmountRequest) Reset() { *m = UnmountRequest{} }
func (m *UnmountRequest) String() string { return proto.CompactTextString(m) }
func (*UnmountRequest) ProtoMessage() {}
func (*UnmountRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{4}
}
func (m *UnmountRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UnmountRequest.Unmarshal(m, b)
}
func (m *UnmountRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UnmountRequest.Marshal(b, m, deterministic)
}
func (m *UnmountRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_UnmountRequest.Merge(m, src)
}
func (m *UnmountRequest) XXX_Size() int {
return xxx_messageInfo_UnmountRequest.Size(m)
}
func (m *UnmountRequest) XXX_DiscardUnknown() {
xxx_messageInfo_UnmountRequest.DiscardUnknown(m)
}
var xxx_messageInfo_UnmountRequest proto.InternalMessageInfo
func (m *UnmountRequest) GetMountpoint() string {
if m != nil {
return m.Mountpoint
}
return ""
}
type StatusResponse struct {
Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StatusResponse) Reset() { *m = StatusResponse{} }
func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
func (*StatusResponse) ProtoMessage() {}
func (*StatusResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{5}
}
func (m *StatusResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusResponse.Unmarshal(m, b)
}
func (m *StatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StatusResponse.Marshal(b, m, deterministic)
}
func (m *StatusResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_StatusResponse.Merge(m, src)
}
func (m *StatusResponse) XXX_Size() int {
return xxx_messageInfo_StatusResponse.Size(m)
}
func (m *StatusResponse) XXX_DiscardUnknown() {
xxx_messageInfo_StatusResponse.DiscardUnknown(m)
}
var xxx_messageInfo_StatusResponse proto.InternalMessageInfo
func (m *StatusResponse) GetStatus() int32 {
if m != nil {
return m.Status
}
return 0
}
type Response struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) {
return fileDescriptor_00212fb1f9d3bf1c, []int{6}
}
func (m *Response) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Response.Unmarshal(m, b)
}
func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Response.Marshal(b, m, deterministic)
}
func (m *Response) XXX_Merge(src proto.Message) {
xxx_messageInfo_Response.Merge(m, src)
}
func (m *Response) XXX_Size() int {
return xxx_messageInfo_Response.Size(m)
}
func (m *Response) XXX_DiscardUnknown() {
xxx_messageInfo_Response.DiscardUnknown(m)
}
var xxx_messageInfo_Response proto.InternalMessageInfo
func init() {
proto.RegisterType((*StatusRequest)(nil), "fusemanager.StatusRequest")
proto.RegisterType((*InitRequest)(nil), "fusemanager.InitRequest")
proto.RegisterType((*MountRequest)(nil), "fusemanager.MountRequest")
proto.RegisterMapType((map[string]string)(nil), "fusemanager.MountRequest.LabelsEntry")
proto.RegisterType((*CheckRequest)(nil), "fusemanager.CheckRequest")
proto.RegisterMapType((map[string]string)(nil), "fusemanager.CheckRequest.LabelsEntry")
proto.RegisterType((*UnmountRequest)(nil), "fusemanager.UnmountRequest")
proto.RegisterType((*StatusResponse)(nil), "fusemanager.StatusResponse")
proto.RegisterType((*Response)(nil), "fusemanager.Response")
}
func init() { proto.RegisterFile("api.proto", fileDescriptor_00212fb1f9d3bf1c) }
var fileDescriptor_00212fb1f9d3bf1c = []byte{
// 386 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x53, 0x51, 0x4b, 0xf3, 0x30,
0x14, 0xa5, 0xdd, 0xd6, 0xef, 0xdb, 0xed, 0x9c, 0x12, 0x54, 0x6a, 0x05, 0x19, 0x05, 0xa1, 0x2f,
0x6b, 0x65, 0x3e, 0xe8, 0x84, 0x3d, 0xa8, 0x28, 0x08, 0xee, 0xa5, 0xc3, 0x17, 0xdf, 0xb2, 0x92,
0x75, 0x65, 0x6b, 0x52, 0x9b, 0x74, 0x30, 0x7f, 0x91, 0xff, 0xc5, 0x3f, 0x25, 0xcd, 0xba, 0x91,
0x8a, 0x13, 0x84, 0xbd, 0xe5, 0x24, 0xf7, 0xdc, 0x9e, 0x7b, 0xcf, 0x29, 0x34, 0x71, 0x1a, 0x7b,
0x69, 0xc6, 0x04, 0x43, 0xe6, 0x24, 0xe7, 0x24, 0xc1, 0x14, 0x47, 0x24, 0x73, 0xf6, 0x61, 0x6f,
0x24, 0xb0, 0xc8, 0x79, 0x40, 0xde, 0x72, 0xc2, 0x85, 0xd3, 0x07, 0xf3, 0x89, 0xc6, 0xa2, 0x84,
0x08, 0x41, 0x3d, 0x63, 0x4c, 0x58, 0x5a, 0x47, 0x73, 0x9b, 0x81, 0x3c, 0xa3, 0x63, 0x30, 0x42,
0x46, 0x27, 0x71, 0x64, 0xe9, 0x1d, 0xcd, 0x6d, 0x05, 0x25, 0x72, 0x3e, 0x34, 0x68, 0x0d, 0x59,
0x4e, 0x37, 0xe4, 0x33, 0x80, 0xa4, 0xc0, 0x29, 0x8b, 0xe9, 0xba, 0x85, 0x72, 0x83, 0x06, 0x60,
0xcc, 0xf1, 0x98, 0xcc, 0xb9, 0xa5, 0x77, 0x6a, 0xae, 0xd9, 0x3b, 0xf7, 0x14, 0x69, 0x9e, 0xda,
0xca, 0x7b, 0x96, 0x75, 0x0f, 0x54, 0x64, 0xcb, 0xa0, 0x24, 0xd9, 0x7d, 0x30, 0x95, 0x6b, 0x74,
0x00, 0xb5, 0x19, 0x59, 0x96, 0x9f, 0x29, 0x8e, 0xe8, 0x10, 0x1a, 0x0b, 0x3c, 0xcf, 0x89, 0xd4,
0xd9, 0x0c, 0x56, 0xe0, 0x46, 0xbf, 0xd6, 0xa4, 0xd4, 0xfb, 0x29, 0x09, 0x67, 0xbb, 0x91, 0xaa,
0xb6, 0xda, 0xb5, 0xd4, 0x0b, 0x68, 0xbf, 0xd0, 0xe4, 0x0f, 0x6b, 0x75, 0x5c, 0x68, 0xaf, 0x3d,
0xe5, 0x29, 0xa3, 0x9c, 0x14, 0x8e, 0x71, 0x79, 0x23, 0xab, 0x1b, 0x41, 0x89, 0x1c, 0x80, 0xff,
0xeb, 0x9a, 0xde, 0xa7, 0x0e, 0xd6, 0x48, 0xe0, 0x2c, 0x7a, 0x7f, 0xcc, 0x39, 0x19, 0xae, 0x26,
0x1b, 0x91, 0x6c, 0x11, 0x87, 0x04, 0xdd, 0x82, 0xb1, 0x6a, 0x89, 0xec, 0xca, 0xe0, 0x95, 0xec,
0xd8, 0xa7, 0x3f, 0xbe, 0x95, 0x1a, 0xae, 0xa0, 0x5e, 0x04, 0x0b, 0x59, 0x95, 0x22, 0x25, 0x6b,
0xf6, 0x51, 0xe5, 0x65, 0x43, 0xec, 0x43, 0x43, 0x46, 0x01, 0x9d, 0x6c, 0x8d, 0xc7, 0x2f, 0x54,
0x69, 0xcd, 0x37, 0xaa, 0x6a, 0xd7, 0x36, 0xea, 0x00, 0xfe, 0x95, 0x6b, 0x47, 0xd5, 0xb1, 0xaa,
0x66, 0x6c, 0xa1, 0xdf, 0xf9, 0xaf, 0xdd, 0x28, 0x16, 0xd3, 0x7c, 0xec, 0x85, 0x2c, 0xf1, 0xb9,
0xdc, 0x6b, 0x97, 0x53, 0x9c, 0xf2, 0x29, 0x13, 0x82, 0x64, 0xbe, 0xc2, 0xf2, 0x71, 0x1a, 0x8f,
0x0d, 0xf9, 0x73, 0x5e, 0x7e, 0x05, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x24, 0xe1, 0x41, 0xa9, 0x03,
0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// StargzFuseManagerServiceClient is the client API for StargzFuseManagerService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type StargzFuseManagerServiceClient interface {
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error)
Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*Response, error)
Mount(ctx context.Context, in *MountRequest, opts ...grpc.CallOption) (*Response, error)
Check(ctx context.Context, in *CheckRequest, opts ...grpc.CallOption) (*Response, error)
Unmount(ctx context.Context, in *UnmountRequest, opts ...grpc.CallOption) (*Response, error)
}
type stargzFuseManagerServiceClient struct {
cc *grpc.ClientConn
}
func NewStargzFuseManagerServiceClient(cc *grpc.ClientConn) StargzFuseManagerServiceClient {
return &stargzFuseManagerServiceClient{cc}
}
func (c *stargzFuseManagerServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) {
out := new(StatusResponse)
err := c.cc.Invoke(ctx, "/fusemanager.StargzFuseManagerService/Status", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *stargzFuseManagerServiceClient) Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/fusemanager.StargzFuseManagerService/Init", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *stargzFuseManagerServiceClient) Mount(ctx context.Context, in *MountRequest, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/fusemanager.StargzFuseManagerService/Mount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *stargzFuseManagerServiceClient) Check(ctx context.Context, in *CheckRequest, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/fusemanager.StargzFuseManagerService/Check", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *stargzFuseManagerServiceClient) Unmount(ctx context.Context, in *UnmountRequest, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := c.cc.Invoke(ctx, "/fusemanager.StargzFuseManagerService/Unmount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// StargzFuseManagerServiceServer is the server API for StargzFuseManagerService service.
type StargzFuseManagerServiceServer interface {
Status(context.Context, *StatusRequest) (*StatusResponse, error)
Init(context.Context, *InitRequest) (*Response, error)
Mount(context.Context, *MountRequest) (*Response, error)
Check(context.Context, *CheckRequest) (*Response, error)
Unmount(context.Context, *UnmountRequest) (*Response, error)
}
// UnimplementedStargzFuseManagerServiceServer can be embedded to have forward compatible implementations.
type UnimplementedStargzFuseManagerServiceServer struct {
}
func (*UnimplementedStargzFuseManagerServiceServer) Status(ctx context.Context, req *StatusRequest) (*StatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Status not implemented")
}
func (*UnimplementedStargzFuseManagerServiceServer) Init(ctx context.Context, req *InitRequest) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Init not implemented")
}
func (*UnimplementedStargzFuseManagerServiceServer) Mount(ctx context.Context, req *MountRequest) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Mount not implemented")
}
func (*UnimplementedStargzFuseManagerServiceServer) Check(ctx context.Context, req *CheckRequest) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Check not implemented")
}
func (*UnimplementedStargzFuseManagerServiceServer) Unmount(ctx context.Context, req *UnmountRequest) (*Response, error) {
return nil, status.Errorf(codes.Unimplemented, "method Unmount not implemented")
}
func RegisterStargzFuseManagerServiceServer(s *grpc.Server, srv StargzFuseManagerServiceServer) {
s.RegisterService(&_StargzFuseManagerService_serviceDesc, srv)
}
func _StargzFuseManagerService_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(StatusRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StargzFuseManagerServiceServer).Status(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/fusemanager.StargzFuseManagerService/Status",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StargzFuseManagerServiceServer).Status(ctx, req.(*StatusRequest))
}
return interceptor(ctx, in, info, handler)
}
func _StargzFuseManagerService_Init_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(InitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StargzFuseManagerServiceServer).Init(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/fusemanager.StargzFuseManagerService/Init",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StargzFuseManagerServiceServer).Init(ctx, req.(*InitRequest))
}
return interceptor(ctx, in, info, handler)
}
func _StargzFuseManagerService_Mount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StargzFuseManagerServiceServer).Mount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/fusemanager.StargzFuseManagerService/Mount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StargzFuseManagerServiceServer).Mount(ctx, req.(*MountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _StargzFuseManagerService_Check_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CheckRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StargzFuseManagerServiceServer).Check(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/fusemanager.StargzFuseManagerService/Check",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StargzFuseManagerServiceServer).Check(ctx, req.(*CheckRequest))
}
return interceptor(ctx, in, info, handler)
}
func _StargzFuseManagerService_Unmount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UnmountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StargzFuseManagerServiceServer).Unmount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/fusemanager.StargzFuseManagerService/Unmount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StargzFuseManagerServiceServer).Unmount(ctx, req.(*UnmountRequest))
}
return interceptor(ctx, in, info, handler)
}
var _StargzFuseManagerService_serviceDesc = grpc.ServiceDesc{
ServiceName: "fusemanager.StargzFuseManagerService",
HandlerType: (*StargzFuseManagerServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Status",
Handler: _StargzFuseManagerService_Status_Handler,
},
{
MethodName: "Init",
Handler: _StargzFuseManagerService_Init_Handler,
},
{
MethodName: "Mount",
Handler: _StargzFuseManagerService_Mount_Handler,
},
{
MethodName: "Check",
Handler: _StargzFuseManagerService_Check_Handler,
},
{
MethodName: "Unmount",
Handler: _StargzFuseManagerService_Unmount_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api.proto",
}

58
fusemanager/api/api.proto Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
syntax = "proto3";
option go_package = "github.com/stargz-snapshotter/fusemanager/api";
package fusemanager;
service StargzFuseManagerService {
rpc Status (StatusRequest) returns (StatusResponse);
rpc Init (InitRequest) returns (Response);
rpc Mount (MountRequest) returns (Response);
rpc Check (CheckRequest) returns (Response);
rpc Unmount (UnmountRequest) returns (Response);
}
message StatusRequest {
}
message InitRequest {
string root = 1;
bytes config = 2;
}
message MountRequest {
string mountpoint = 1;
map<string, string> labels = 2;
}
message CheckRequest {
string mountpoint = 1;
map<string, string> labels = 2;
}
message UnmountRequest {
string mountpoint = 1;
}
message StatusResponse {
int32 status = 1;
}
message Response {
}

View File

@ -0,0 +1,19 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package api
//go:generate protoc --gogo_out=paths=source_relative,plugins=grpc:. api.proto

141
fusemanager/client.go Normal file
View File

@ -0,0 +1,141 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fusemanager
import (
"context"
"encoding/json"
"fmt"
"github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/dialer"
"github.com/containerd/log"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
pb "github.com/containerd/stargz-snapshotter/fusemanager/api"
"github.com/containerd/stargz-snapshotter/snapshot"
)
type Client struct {
client pb.StargzFuseManagerServiceClient
}
func NewManagerClient(ctx context.Context, root, socket string, config *Config) (snapshot.FileSystem, error) {
grpcCli, err := newClient(socket)
if err != nil {
return nil, err
}
client := &Client{
client: grpcCli,
}
err = client.init(ctx, root, config)
if err != nil {
return nil, err
}
return client, nil
}
func newClient(socket string) (pb.StargzFuseManagerServiceClient, error) {
connParams := grpc.ConnectParams{
Backoff: backoff.DefaultConfig,
}
gopts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithConnectParams(connParams),
grpc.WithContextDialer(dialer.ContextDialer),
grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize),
grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize),
),
}
conn, err := grpc.NewClient(fmt.Sprintf("unix://%s", socket), gopts...)
if err != nil {
return nil, err
}
return pb.NewStargzFuseManagerServiceClient(conn), nil
}
func (cli *Client) init(ctx context.Context, root string, config *Config) error {
configBytes, err := json.Marshal(config)
if err != nil {
return err
}
req := &pb.InitRequest{
Root: root,
Config: configBytes,
}
_, err = cli.client.Init(ctx, req)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to call Init")
return err
}
return nil
}
func (cli *Client) Mount(ctx context.Context, mountpoint string, labels map[string]string) error {
req := &pb.MountRequest{
Mountpoint: mountpoint,
Labels: labels,
}
_, err := cli.client.Mount(ctx, req)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to call Mount")
return err
}
return nil
}
func (cli *Client) Check(ctx context.Context, mountpoint string, labels map[string]string) error {
req := &pb.CheckRequest{
Mountpoint: mountpoint,
Labels: labels,
}
_, err := cli.client.Check(ctx, req)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to call Check")
return err
}
return nil
}
func (cli *Client) Unmount(ctx context.Context, mountpoint string) error {
req := &pb.UnmountRequest{
Mountpoint: mountpoint,
}
_, err := cli.client.Unmount(ctx, req)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to call Unmount")
return err
}
return nil
}

259
fusemanager/fusemanager.go Normal file
View File

@ -0,0 +1,259 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fusemanager
import (
"context"
"flag"
"fmt"
golog "log"
"net"
"os"
"os/exec"
"os/signal"
"path/filepath"
"syscall"
"github.com/containerd/log"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
"google.golang.org/grpc"
pb "github.com/containerd/stargz-snapshotter/fusemanager/api"
"github.com/containerd/stargz-snapshotter/version"
)
var (
debugFlag bool
versionFlag bool
fuseStoreAddr string
address string
logLevel string
logPath string
action string
)
func parseFlags() {
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
flag.BoolVar(&versionFlag, "v", false, "show the fusemanager version and exit")
flag.StringVar(&action, "action", "", "action of fusemanager")
flag.StringVar(&fuseStoreAddr, "fusestore-path", "/var/lib/containerd-stargz-grpc/fusestore.db", "address for the fusemanager's store")
flag.StringVar(&address, "address", "/run/containerd-stargz-grpc/fuse-manager.sock", "address for the fusemanager's gRPC socket")
flag.StringVar(&logLevel, "log-level", logrus.InfoLevel.String(), "set the logging level [trace, debug, info, warn, error, fatal, panic]")
flag.StringVar(&logPath, "log-path", "", "path to fusemanager's logs, no log recorded if empty")
flag.Parse()
}
func Run() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "failed to run fusemanager: %v", err)
os.Exit(1)
}
}
func run() error {
parseFlags()
if versionFlag {
fmt.Printf("%s:\n", os.Args[0])
fmt.Println(" Version: ", version.Version)
fmt.Println(" Revision:", version.Revision)
fmt.Println("")
return nil
}
if fuseStoreAddr == "" || address == "" {
return fmt.Errorf("fusemanager fusestore and socket path cannot be empty")
}
ctx := log.WithLogger(context.Background(), log.L)
switch action {
case "start":
return startNew(ctx, logPath, address, fuseStoreAddr, logLevel)
default:
return runFuseManager(ctx)
}
}
func startNew(ctx context.Context, logPath, address, fusestore, logLevel string) error {
self, err := os.Executable()
if err != nil {
return err
}
cwd, err := os.Getwd()
if err != nil {
return err
}
args := []string{
"-address", address,
"-fusestore-path", fusestore,
"-log-level", logLevel,
}
// we use shim-like approach to start new fusemanager process by self-invoking in the background
// and detach it from parent
cmd := exec.CommandContext(ctx, self, args...)
cmd.Dir = cwd
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
if logPath != "" {
err := os.Remove(logPath)
if err != nil && !os.IsNotExist(err) {
return err
}
file, err := os.Create(logPath)
if err != nil {
return err
}
cmd.Stdout = file
cmd.Stderr = file
}
if err := cmd.Start(); err != nil {
return err
}
go cmd.Wait()
if ready, err := waitUntilReady(ctx); err != nil || !ready {
if err != nil {
return fmt.Errorf("failed to start new fusemanager: %w", err)
}
if !ready {
return fmt.Errorf("failed to start new fusemanager, fusemanager not ready")
}
}
return nil
}
// waitUntilReady waits until fusemanager is ready to accept requests
func waitUntilReady(ctx context.Context) (bool, error) {
grpcCli, err := newClient(address)
if err != nil {
return false, err
}
resp, err := grpcCli.Status(ctx, &pb.StatusRequest{})
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to call Status")
return false, err
}
if resp.Status == FuseManagerNotReady {
return false, nil
}
return true, nil
}
func runFuseManager(ctx context.Context) error {
lvl, err := logrus.ParseLevel(logLevel)
if err != nil {
return fmt.Errorf("failed to prepare logger: %w", err)
}
logrus.SetLevel(lvl)
logrus.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: log.RFC3339NanoFixed,
})
golog.SetOutput(log.G(ctx).WriterLevel(logrus.DebugLevel))
// Prepare the directory for the socket
if err := os.MkdirAll(filepath.Dir(address), 0700); err != nil {
return fmt.Errorf("failed to create directory %s: %w", filepath.Dir(address), err)
}
// Try to remove the socket file to avoid EADDRINUSE
if err := os.Remove(address); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to remove old socket file: %w", err)
}
l, err := net.Listen("unix", address)
if err != nil {
return fmt.Errorf("failed to listen socket: %w", err)
}
server := grpc.NewServer()
fm, err := NewFuseManager(ctx, l, server, fuseStoreAddr, address)
if err != nil {
return fmt.Errorf("failed to configure manager server: %w", err)
}
pb.RegisterStargzFuseManagerServiceServer(server, fm)
errCh := make(chan error, 1)
go func() {
if err := server.Serve(l); err != nil {
errCh <- fmt.Errorf("error on serving via socket %q: %w", address, err)
}
}()
var s os.Signal
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, unix.SIGINT, unix.SIGTERM)
select {
case s = <-sigCh:
log.G(ctx).Infof("Got %v", s)
case err := <-errCh:
log.G(ctx).WithError(err).Warnf("error during running the server")
}
server.Stop()
if err = fm.Close(ctx); err != nil {
return fmt.Errorf("failed to close fuse manager: %w", err)
}
return nil
}
func StartFuseManager(ctx context.Context, executable, address, fusestore, logLevel, logPath string) (newlyStarted bool, err error) {
// if socket exists, do not start it
if _, err := os.Stat(address); err == nil {
return false, nil
} else if !os.IsNotExist(err) {
return false, err
}
if _, err := os.Stat(executable); err != nil {
return false, fmt.Errorf("failed to stat fusemanager binary: %q", executable)
}
args := []string{
"-action", "start",
"-address", address,
"-fusestore-path", fusestore,
"-log-level", logLevel,
"-log-path", logPath,
}
cmd := exec.Command(executable, args...)
if err := cmd.Start(); err != nil {
return false, err
}
if err := cmd.Wait(); err != nil {
return false, err
}
return true, nil
}

View File

@ -0,0 +1,235 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fusemanager
import (
"context"
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
"testing"
pb "github.com/containerd/stargz-snapshotter/fusemanager/api"
"github.com/containerd/stargz-snapshotter/service"
"google.golang.org/grpc"
)
// mockFileSystem implements snapshot.FileSystem for testing
type mockFileSystem struct {
t *testing.T
mountErr error
checkErr error
unmountErr error
mountPoints map[string]bool
checkCalled bool
mountCalled bool
unmountCalled bool
}
func newMockFileSystem(t *testing.T) *mockFileSystem {
return &mockFileSystem{
t: t,
mountPoints: make(map[string]bool),
}
}
func (fs *mockFileSystem) Mount(ctx context.Context, mountpoint string, labels map[string]string) error {
fs.mountCalled = true
if fs.mountErr != nil {
return fs.mountErr
}
fs.mountPoints[mountpoint] = true
return nil
}
func (fs *mockFileSystem) Check(ctx context.Context, mountpoint string, labels map[string]string) error {
fs.checkCalled = true
if fs.checkErr != nil {
return fs.checkErr
}
if _, ok := fs.mountPoints[mountpoint]; !ok {
return fmt.Errorf("mountpoint %s not found", mountpoint)
}
return nil
}
func (fs *mockFileSystem) Unmount(ctx context.Context, mountpoint string) error {
fs.unmountCalled = true
if fs.unmountErr != nil {
return fs.unmountErr
}
delete(fs.mountPoints, mountpoint)
return nil
}
// mockServer embeds Server struct and overrides Init method
type mockServer struct {
*Server
initCalled bool
initErr error
}
func newMockServer(ctx context.Context, listener net.Listener, server *grpc.Server, fuseStoreAddr, serverAddr string) (*mockServer, error) {
s, err := NewFuseManager(ctx, listener, server, fuseStoreAddr, serverAddr)
if err != nil {
return nil, err
}
return &mockServer{Server: s}, nil
}
// Init overrides Server.Init to avoid actual initialization
func (s *mockServer) Init(ctx context.Context, req *pb.InitRequest) (*pb.Response, error) {
s.initCalled = true
if s.initErr != nil {
return nil, s.initErr
}
// Set only required fields
s.root = req.Root
config := &Config{}
if err := json.Unmarshal(req.Config, config); err != nil {
return nil, err
}
s.config = config
s.status = FuseManagerReady
return &pb.Response{}, nil
}
func TestFuseManager(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "fusemanager-test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
socketPath := filepath.Join(tmpDir, "test.sock")
fuseStorePath := filepath.Join(tmpDir, "fusestore.db")
fuseManagerSocketPath := filepath.Join(tmpDir, "test-fusemanager.sock")
l, err := net.Listen("unix", socketPath)
if err != nil {
t.Fatalf("failed to listen: %v", err)
}
defer l.Close()
// Create server with mock
grpcServer := grpc.NewServer()
mockFs := newMockFileSystem(t)
fm, err := newMockServer(context.Background(), l, grpcServer, fuseStorePath, fuseManagerSocketPath)
if err != nil {
t.Fatalf("failed to create fuse manager: %v", err)
}
defer fm.Close(context.Background())
pb.RegisterStargzFuseManagerServiceServer(grpcServer, fm)
// Set mock filesystem
fm.curFs = mockFs
go grpcServer.Serve(l)
defer grpcServer.Stop()
// Test cases to verify Init, Mount, Check and Unmount operations
testCases := []struct {
name string
mountpoint string
labels map[string]string
initErr error
mountErr error
checkErr error
unmountErr error
wantErr bool
}{
{
name: "successful init and mount",
mountpoint: filepath.Join(tmpDir, "mount1"),
labels: map[string]string{"key": "value"},
},
{
name: "init error",
mountpoint: filepath.Join(tmpDir, "mount2"),
initErr: fmt.Errorf("init error"),
wantErr: true,
},
{
name: "mount error",
mountpoint: filepath.Join(tmpDir, "mount3"),
mountErr: fmt.Errorf("mount error"),
wantErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mockFs.mountErr = tc.mountErr
mockFs.checkErr = tc.checkErr
mockFs.unmountErr = tc.unmountErr
mockFs.mountCalled = false
mockFs.checkCalled = false
mockFs.unmountCalled = false
fm.initErr = tc.initErr
fm.initCalled = false
config := &Config{
Config: service.Config{},
}
client, err := NewManagerClient(context.Background(), tmpDir, socketPath, config)
if err != nil {
if !tc.wantErr {
t.Fatalf("failed to create client: %v", err)
}
return
}
if !fm.initCalled {
t.Error("Init() was not called")
}
if !tc.wantErr {
// Test Mount
err = client.Mount(context.Background(), tc.mountpoint, tc.labels)
if err != nil {
t.Errorf("Mount() error = %v", err)
}
if !mockFs.mountCalled {
t.Error("Mount() was not called on filesystem")
}
// Test Check
err = client.Check(context.Background(), tc.mountpoint, tc.labels)
if err != nil {
t.Errorf("Check() error = %v", err)
}
if !mockFs.checkCalled {
t.Error("Check() was not called on filesystem")
}
// Test Unmount
err = client.Unmount(context.Background(), tc.mountpoint)
if err != nil {
t.Errorf("Unmount() error = %v", err)
}
if !mockFs.unmountCalled {
t.Error("Unmount() was not called on filesystem")
}
}
})
}
}

99
fusemanager/fusestore.go Normal file
View File

@ -0,0 +1,99 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fusemanager
import (
"context"
"encoding/json"
bolt "go.etcd.io/bbolt"
"github.com/containerd/stargz-snapshotter/service"
)
var (
fuseInfoBucket = []byte("fuse-info-bucket")
)
type fuseInfo struct {
Root string
Mountpoint string
Labels map[string]string
Config service.Config
}
func (fm *Server) storeFuseInfo(fuseInfo *fuseInfo) error {
return fm.ms.Update(func(tx *bolt.Tx) error {
bucket, err := tx.CreateBucketIfNotExists(fuseInfoBucket)
if err != nil {
return err
}
key := []byte(fuseInfo.Mountpoint)
val, err := json.Marshal(fuseInfo)
if err != nil {
return err
}
err = bucket.Put(key, val)
if err != nil {
return err
}
return nil
})
}
func (fm *Server) removeFuseInfo(fuseInfo *fuseInfo) error {
return fm.ms.Update(func(tx *bolt.Tx) error {
bucket, err := tx.CreateBucketIfNotExists(fuseInfoBucket)
if err != nil {
return err
}
key := []byte(fuseInfo.Mountpoint)
err = bucket.Delete(key)
if err != nil {
return err
}
return nil
})
}
// restoreFuseInfo restores fuseInfo when Init is called, it will skip mounted
// layers whose mountpoint can be found in fsMap
func (fm *Server) restoreFuseInfo(ctx context.Context) error {
return fm.ms.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(fuseInfoBucket)
if bucket == nil {
return nil
}
return bucket.ForEach(func(_, v []byte) error {
mi := &fuseInfo{}
err := json.Unmarshal(v, mi)
if err != nil {
return err
}
return fm.mount(ctx, mi.Mountpoint, mi.Labels)
})
})
}

358
fusemanager/service.go Normal file
View File

@ -0,0 +1,358 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fusemanager
import (
"context"
"encoding/json"
"fmt"
"net"
"os"
"path/filepath"
"sync"
"time"
"github.com/containerd/log"
"github.com/moby/sys/mountinfo"
bolt "go.etcd.io/bbolt"
"google.golang.org/grpc"
pb "github.com/containerd/stargz-snapshotter/fusemanager/api"
"github.com/containerd/stargz-snapshotter/service"
"github.com/containerd/stargz-snapshotter/snapshot"
)
const (
FuseManagerNotReady = iota
FuseManagerWaitInit
FuseManagerReady
)
type Config struct {
Config service.Config
IPFS bool `toml:"ipfs" json:"ipfs"`
MetadataStore string `toml:"metadata_store" default:"memory" json:"metadata_store"`
DefaultImageServiceAddress string `json:"default_image_service_address"`
}
type ConfigContext struct {
Ctx context.Context
Config *Config
RootDir string
Server *grpc.Server
OpenBoltDB func(string) (*bolt.DB, error)
Address string
CRIServer *grpc.Server
}
var (
configFuncs []ConfigFunc
configMu sync.Mutex
)
type ConfigFunc func(cc *ConfigContext) ([]service.Option, error)
func RegisterConfigFunc(f ConfigFunc) {
configMu.Lock()
defer configMu.Unlock()
configFuncs = append(configFuncs, f)
}
// Opens bolt DB with avoiding opening the same DB multiple times
type dbOpener struct {
mu sync.Mutex
handles map[string]*bolt.DB
}
func (o *dbOpener) openBoltDB(p string) (*bolt.DB, error) {
o.mu.Lock()
defer o.mu.Unlock()
if db, ok := o.handles[p]; ok && db != nil {
// we opened it before. avoid trying to open this again.
return db, nil
}
db, err := bolt.Open(p, 0600, &bolt.Options{
NoFreelistSync: true,
InitialMmapSize: 64 * 1024 * 1024,
FreelistType: bolt.FreelistMapType,
})
if err != nil {
return nil, err
}
if o.handles == nil {
o.handles = make(map[string]*bolt.DB)
}
o.handles[p] = db
return db, nil
}
type Server struct {
pb.UnimplementedStargzFuseManagerServiceServer
lock sync.RWMutex
status int32
listener net.Listener
server *grpc.Server
// root is the latest root passed from containerd-stargz-grpc
root string
// config is the latest config passed from containerd-stargz-grpc
config *Config
// fsMap maps mountpoint to its filesystem instance to ensure Mount/Check/Unmount
// call the proper filesystem
fsMap sync.Map
// curFs is filesystem created by latest config
curFs snapshot.FileSystem
ms *bolt.DB
fuseStoreAddr string
dbOpener *dbOpener
serverAddr string
curCRIServer *grpc.Server
}
func NewFuseManager(ctx context.Context, listener net.Listener, server *grpc.Server, fuseStoreAddr string, serverAddr string) (*Server, error) {
if err := os.MkdirAll(filepath.Dir(fuseStoreAddr), 0700); err != nil {
return nil, fmt.Errorf("failed to create directory %q: %w", filepath.Dir(fuseStoreAddr), err)
}
db, err := bolt.Open(fuseStoreAddr, 0666, &bolt.Options{Timeout: 10 * time.Second, ReadOnly: false})
if err != nil {
return nil, fmt.Errorf("failed to configure fusestore: %w", err)
}
fm := &Server{
status: FuseManagerWaitInit,
lock: sync.RWMutex{},
fsMap: sync.Map{},
ms: db,
listener: listener,
server: server,
fuseStoreAddr: fuseStoreAddr,
dbOpener: &dbOpener{},
serverAddr: serverAddr,
}
return fm, nil
}
func (fm *Server) Status(ctx context.Context, _ *pb.StatusRequest) (*pb.StatusResponse, error) {
fm.lock.RLock()
defer fm.lock.RUnlock()
return &pb.StatusResponse{
Status: fm.status,
}, nil
}
func (fm *Server) Init(ctx context.Context, req *pb.InitRequest) (*pb.Response, error) {
fm.lock.Lock()
fm.status = FuseManagerWaitInit
defer func() {
fm.status = FuseManagerReady
fm.lock.Unlock()
}()
ctx = log.WithLogger(ctx, log.G(ctx))
config := &Config{}
err := json.Unmarshal(req.Config, config)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to get config")
return &pb.Response{}, err
}
fm.root = req.Root
fm.config = config
if fm.curCRIServer != nil {
fm.curCRIServer.Stop()
fm.curCRIServer = nil
}
cc := &ConfigContext{
Ctx: ctx,
Config: fm.config,
RootDir: fm.root,
Server: fm.server,
OpenBoltDB: fm.dbOpener.openBoltDB,
Address: fm.serverAddr,
}
var opts []service.Option
for _, configFunc := range configFuncs {
funcOpts, err := configFunc(cc)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to apply config function")
return &pb.Response{}, err
}
opts = append(opts, funcOpts...)
}
fm.curCRIServer = cc.CRIServer
fs, err := service.NewFileSystem(ctx, fm.root, &fm.config.Config, opts...)
if err != nil {
return &pb.Response{}, err
}
fm.curFs = fs
err = fm.restoreFuseInfo(ctx)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to restore fuse info")
return &pb.Response{}, err
}
return &pb.Response{}, nil
}
func (fm *Server) Mount(ctx context.Context, req *pb.MountRequest) (*pb.Response, error) {
fm.lock.RLock()
defer fm.lock.RUnlock()
if fm.status != FuseManagerReady {
return &pb.Response{}, fmt.Errorf("fuse manager not ready")
}
ctx = log.WithLogger(ctx, log.G(ctx).WithField("mountpoint", req.Mountpoint))
err := fm.mount(ctx, req.Mountpoint, req.Labels)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to mount stargz")
return &pb.Response{}, err
}
fm.storeFuseInfo(&fuseInfo{
Root: fm.root,
Mountpoint: req.Mountpoint,
Labels: req.Labels,
Config: fm.config.Config,
})
return &pb.Response{}, nil
}
func (fm *Server) Check(ctx context.Context, req *pb.CheckRequest) (*pb.Response, error) {
fm.lock.RLock()
defer fm.lock.RUnlock()
if fm.status != FuseManagerReady {
return &pb.Response{}, fmt.Errorf("fuse manager not ready")
}
ctx = log.WithLogger(ctx, log.G(ctx).WithField("mountpoint", req.Mountpoint))
obj, found := fm.fsMap.Load(req.Mountpoint)
if !found {
err := fmt.Errorf("failed to find filesystem of mountpoint %s", req.Mountpoint)
log.G(ctx).WithError(err).Errorf("failed to check filesystem")
return &pb.Response{}, err
}
fs := obj.(snapshot.FileSystem)
err := fs.Check(ctx, req.Mountpoint, req.Labels)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to check filesystem")
return &pb.Response{}, err
}
return &pb.Response{}, nil
}
func (fm *Server) Unmount(ctx context.Context, req *pb.UnmountRequest) (*pb.Response, error) {
fm.lock.RLock()
defer fm.lock.RUnlock()
if fm.status != FuseManagerReady {
return &pb.Response{}, fmt.Errorf("fuse manager not ready")
}
ctx = log.WithLogger(ctx, log.G(ctx).WithField("mountpoint", req.Mountpoint))
obj, found := fm.fsMap.Load(req.Mountpoint)
if !found {
// check whether already unmounted
mounts, err := mountinfo.GetMounts(func(info *mountinfo.Info) (skip, stop bool) {
if info.Mountpoint == req.Mountpoint {
return false, true
}
return true, false
})
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to get mount info")
return &pb.Response{}, err
}
if len(mounts) <= 0 {
return &pb.Response{}, nil
}
err = fmt.Errorf("failed to find filesystem of mountpoint %s", req.Mountpoint)
log.G(ctx).WithError(err).Errorf("failed to unmount filesystem")
return &pb.Response{}, err
}
fs := obj.(snapshot.FileSystem)
err := fs.Unmount(ctx, req.Mountpoint)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to unmount filesystem")
return &pb.Response{}, err
}
fm.fsMap.Delete(req.Mountpoint)
fm.removeFuseInfo(&fuseInfo{
Mountpoint: req.Mountpoint,
})
return &pb.Response{}, nil
}
func (fm *Server) Close(ctx context.Context) error {
fm.lock.Lock()
defer fm.lock.Unlock()
fm.status = FuseManagerNotReady
err := fm.ms.Close()
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to close fusestore")
return err
}
if err := os.Remove(fm.fuseStoreAddr); err != nil {
log.G(ctx).WithError(err).Errorf("failed to remove fusestore file %s", fm.fuseStoreAddr)
return err
}
return nil
}
func (fm *Server) mount(ctx context.Context, mountpoint string, labels map[string]string) error {
// mountpoint in fsMap means layer is already mounted, skip it
if _, found := fm.fsMap.Load(mountpoint); found {
return nil
}
err := fm.curFs.Mount(ctx, mountpoint, labels)
if err != nil {
log.G(ctx).WithError(err).Errorf("failed to mount stargz")
return err
}
fm.fsMap.Store(mountpoint, fm.curFs)
return nil
}

160
go.mod
View File

@ -1,132 +1,138 @@
module github.com/containerd/stargz-snapshotter module github.com/containerd/stargz-snapshotter
go 1.23.0 go 1.24.0
toolchain go1.23.2 toolchain go1.24.2
require ( require (
github.com/containerd/console v1.0.4 github.com/containerd/console v1.0.5
github.com/containerd/containerd/v2 v2.0.0 github.com/containerd/containerd/v2 v2.1.4
github.com/containerd/continuity v0.4.4 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
github.com/containerd/platforms v1.0.0-rc.0 github.com/containerd/platforms v1.0.0-rc.1
github.com/containerd/plugin v1.0.0 github.com/containerd/plugin v1.0.0
github.com/containerd/stargz-snapshotter/estargz v0.16.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 v27.3.1+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
github.com/hanwen/go-fuse/v2 v2.6.3 github.com/hanwen/go-fuse/v2 v2.8.0
github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-retryablehttp v0.7.8
github.com/hashicorp/go-retryablehttp v0.7.7 github.com/klauspost/compress v1.18.0
github.com/klauspost/compress v1.17.11
github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/mountinfo v0.7.2
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/image-spec v1.1.1
github.com/opencontainers/runtime-spec v1.2.0 github.com/opencontainers/runtime-spec v1.2.1
github.com/prometheus/client_golang v1.20.5 github.com/prometheus/client_golang v1.23.0
github.com/rs/xid v1.6.0 github.com/rs/xid v1.6.0
golang.org/x/sync v0.9.0 github.com/sirupsen/logrus v1.9.3
golang.org/x/sys v0.26.0 go.etcd.io/bbolt v1.4.2
google.golang.org/grpc v1.68.0 golang.org/x/sync v0.16.0
k8s.io/api v0.31.2 golang.org/x/sys v0.34.0
k8s.io/apimachinery v0.31.2 google.golang.org/grpc v1.74.2
k8s.io/client-go v0.31.2 k8s.io/api v0.33.3
k8s.io/cri-api v0.32.0-beta.0 k8s.io/apimachinery v0.33.3
k8s.io/client-go v0.33.3
k8s.io/cri-api v0.33.3
) )
require ( require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.9 // indirect github.com/Microsoft/hcsshim v0.13.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect
github.com/containerd/containerd/api v1.8.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.10 // indirect github.com/containerd/go-cni v1.1.13 // indirect
github.com/containerd/ttrpc v1.2.6 // indirect github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.2 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/containernetworking/cni v1.2.3 // indirect github.com/containernetworking/cni v1.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // 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.1 // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/docker-credential-helpers v0.7.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.7.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.19.6 // 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
github.com/go-openapi/swag v0.22.4 // indirect github.com/go-openapi/swag v0.23.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/locker v1.0.1 // indirect github.com/moby/locker v1.0.1 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/signal v0.7.1 // indirect github.com/moby/sys/signal v0.7.1 // indirect
github.com/moby/sys/user v0.3.0 // indirect github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opencontainers/selinux v1.11.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // 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.1-0.20181226105442-5d4384ee4fb2 // 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.55.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/sirupsen/logrus v1.9.3 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/stretchr/testify v1.9.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/urfave/cli/v2 v2.27.7 // indirect
github.com/urfave/cli/v2 v2.27.5 // indirect github.com/vbatts/tar-split v0.12.1 // indirect
github.com/vbatts/tar-split v0.11.6 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.etcd.io/bbolt v1.3.11 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.31.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect
golang.org/x/mod v0.21.0 // indirect go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/term v0.25.0 // indirect golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.19.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.9.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
google.golang.org/protobuf v1.35.1 // indirect google.golang.org/protobuf v1.36.6 // 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
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.0 // indirect gotest.tools/v3 v3.5.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect
tags.cncf.io/container-device-interface v0.8.0 // indirect
tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect
) )
// Import local package for estargz. // Import local package for estargz.
replace github.com/containerd/stargz-snapshotter/estargz => ./estargz replace github.com/containerd/stargz-snapshotter/estargz => ./estargz
exclude (
// These dependencies were updated to "master" in some modules we depend on,
// but have no code-changes since their last release. Unfortunately, this also
// causes a ripple effect, forcing all users of the containerd module to also
// update these dependencies to an unrelease / un-tagged version.
//
// Both these dependencies will unlikely do a new release in the near future,
// so exclude these versions so that we can downgrade to the current release.
//
// For additional details, see this PR and links mentioned in that PR:
// https://github.com/kubernetes-sigs/kustomize/pull/5830#issuecomment-2569960859
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
)

319
go.sum
View File

@ -1,67 +1,62 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.4/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=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
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.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= github.com/containerd/go-cni v1.1.13 h1:eFSGOKlhoYNxpJ51KRIMHZNlg5UgocXEIEBGkY7Hnis=
github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= 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.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
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 v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
github.com/docker/cli v27.3.1+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=
@ -76,25 +71,24 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
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/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.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 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
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=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
@ -118,8 +112,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -127,32 +121,22 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hanwen/go-fuse/v2 v2.6.3 h1:tDcEkLRx93lXu4XyN1/j8Z74VWvhHDl6qU1kNnvFUqI= github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs=
github.com/hanwen/go-fuse/v2 v2.6.3/go.mod h1:ugNaD/iv5JYyS1Rcvi57Wz7/vrLQJo10mmketmoef48= github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -162,8 +146,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@ -182,7 +166,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
@ -191,8 +174,8 @@ github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7z
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -202,65 +185,62 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw=
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 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.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= 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.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 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=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU=
github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@ -273,42 +253,40 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I=
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
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/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=
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -319,8 +297,6 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -332,40 +308,38 @@ 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.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= 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.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= 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.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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=
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=
@ -374,8 +348,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -385,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-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= 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=
@ -403,47 +377,44 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
k8s.io/cri-api v0.32.0-beta.0 h1:jEzxyqoSUuUn99naSmlRdepmSa38UGj0QNxZdQeGgMY= k8s.io/cri-api v0.33.3 h1:aQvK3UxsaVMul4z71lOiblMHdhw9ROaw3Cgg15xDrD4=
k8s.io/cri-api v0.32.0-beta.0/go.mod h1:rwEJEDa3cV0bT4AZ8en5LbBEAwghbAdDkLNHz//zwsk= k8s.io/cri-api v0.33.3/go.mod h1:OLQvT45OpIA+tv91ZrpuFIGY+Y2Ho23poS7n115Aocs=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=
sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc=
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA=
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws=

View File

@ -1,49 +1,46 @@
module github.com/containerd/stargz-snapshotter/ipfs module github.com/containerd/stargz-snapshotter/ipfs
go 1.22.7 go 1.23.0
toolchain go1.23.2 toolchain go1.24.1
require ( require (
github.com/containerd/containerd/v2 v2.0.0 github.com/containerd/containerd/v2 v2.1.4
github.com/containerd/platforms v1.0.0-rc.0 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.13.0 github.com/multiformats/go-multiaddr v0.16.1
github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/image-spec v1.1.1
) )
require ( require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.9 // indirect github.com/Microsoft/hcsshim v0.13.0 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/cgroups/v3 v3.0.5 // indirect
github.com/containerd/containerd/api v1.8.0 // indirect github.com/containerd/containerd/api v1.9.0 // indirect
github.com/containerd/continuity v0.4.4 // indirect github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs v1.0.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/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
github.com/containerd/plugin v1.0.0 // indirect github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/ttrpc v1.2.6 // indirect github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.2 // 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/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/logr v1.4.2 // 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
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/ipfs/go-cid v0.0.7 // indirect github.com/ipfs/go-cid v0.0.7 // indirect
github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
github.com/moby/locker v1.0.1 // indirect github.com/moby/locker v1.0.1 // indirect
github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/signal v0.7.1 // indirect github.com/moby/sys/signal v0.7.1 // indirect
github.com/moby/sys/user v0.3.0 // indirect github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect
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
@ -52,30 +49,25 @@ require (
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
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opencontainers/runtime-spec v1.2.1 // indirect
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/opencontainers/selinux v1.12.0 // indirect
github.com/opencontainers/selinux v1.11.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.31.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect
golang.org/x/crypto v0.28.0 // indirect go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect golang.org/x/crypto v0.38.0 // indirect
golang.org/x/mod v0.21.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/net v0.30.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.26.0 // indirect golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.19.0 // indirect golang.org/x/text v0.25.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
google.golang.org/grpc v1.68.0 // indirect google.golang.org/grpc v1.74.2 // indirect
google.golang.org/protobuf v1.35.1 // indirect google.golang.org/protobuf v1.36.6 // indirect
lukechampine.com/blake3 v1.2.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
tags.cncf.io/container-device-interface v0.8.0 // indirect
tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect
) )

View File

@ -1,26 +1,22 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= github.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= github.com/containerd/containerd/v2 v2.1.4 h1:/hXWjiSFd6ftrBOBGfAZ6T30LJcx1dBjdKEeI8xucKQ=
github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= github.com/containerd/containerd/v2 v2.1.4/go.mod h1:8C5QV9djwsYDNhxfTCFjWtTBZrqjditQ4/ghHSYjnHM=
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.4/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=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
@ -29,18 +25,17 @@ 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/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.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -49,11 +44,9 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
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/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
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=
@ -80,21 +73,17 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY= github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY=
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
@ -103,7 +92,6 @@ github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dz
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
@ -112,23 +100,22 @@ github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7z
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
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.13.0 h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ= github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw=
github.com/multiformats/go-multiaddr v0.13.0/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= 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=
@ -140,16 +127,12 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8=
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -158,7 +141,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
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/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
@ -166,52 +148,44 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
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.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= 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-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -221,30 +195,28 @@ 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.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= 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=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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=
@ -262,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-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= 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=
@ -280,11 +252,9 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@ -292,9 +262,3 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc=
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA=
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws=

View File

@ -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) {

View File

@ -18,6 +18,7 @@ package testutil
import ( import (
"compress/gzip" "compress/gzip"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -25,13 +26,11 @@ import (
"path/filepath" "path/filepath"
"reflect" "reflect"
"strings" "strings"
"testing"
"time" "time"
"github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz"
"github.com/containerd/stargz-snapshotter/metadata" "github.com/containerd/stargz-snapshotter/metadata"
tutil "github.com/containerd/stargz-snapshotter/util/testutil" tutil "github.com/containerd/stargz-snapshotter/util/testutil"
"github.com/hashicorp/go-multierror"
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
) )
@ -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 {
@ -412,21 +442,21 @@ func newCalledTelemetry() (telemetry *metadata.Telemetry, check func() error) {
GetTocLatency: func(time.Time) { getTocLatencyCalled = true }, GetTocLatency: func(time.Time) { getTocLatencyCalled = true },
DeserializeTocLatency: func(time.Time) { deserializeTocLatencyCalled = true }, DeserializeTocLatency: func(time.Time) { deserializeTocLatencyCalled = true },
}, func() error { }, func() error {
var allErr error var errs []error
if !getFooterLatencyCalled { if !getFooterLatencyCalled {
allErr = multierror.Append(allErr, fmt.Errorf("metrics GetFooterLatency isn't called")) errs = append(errs, fmt.Errorf("metrics GetFooterLatency isn't called"))
} }
if !getTocLatencyCalled { if !getTocLatencyCalled {
allErr = multierror.Append(allErr, fmt.Errorf("metrics GetTocLatency isn't called")) errs = append(errs, fmt.Errorf("metrics GetTocLatency isn't called"))
} }
if !deserializeTocLatencyCalled { if !deserializeTocLatencyCalled {
allErr = multierror.Append(allErr, fmt.Errorf("metrics DeserializeTocLatency isn't called")) errs = append(errs, fmt.Errorf("metrics DeserializeTocLatency isn't called"))
} }
return allErr return errors.Join(errs...)
} }
} }
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)

View File

@ -109,11 +109,6 @@ func LayerConvertFuncWithCompressionLevel(compressionLevel zstd.EncoderLevel, op
if uncompressedDesc == nil { if uncompressedDesc == nil {
return nil, fmt.Errorf("unexpectedly got the same blob after compression (%s, %q)", desc.Digest, desc.MediaType) return nil, fmt.Errorf("unexpectedly got the same blob after compression (%s, %q)", desc.Digest, desc.MediaType)
} }
defer func() {
if err := cs.Delete(ctx, uncompressedDesc.Digest); err != nil {
log.G(ctx).WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer")
}
}()
log.G(ctx).Debugf("zstdchunked: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest) log.G(ctx).Debugf("zstdchunked: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest)
} }
@ -146,7 +141,7 @@ func LayerConvertFuncWithCompressionLevel(compressionLevel zstd.EncoderLevel, op
} }
defer blob.Close() defer blob.Close()
ref := fmt.Sprintf("convert-zstdchunked-from-%s", desc.Digest) ref := fmt.Sprintf("convert-zstdchunked-from-%s", desc.Digest)
w, err := cs.Writer(ctx, content.WithRef(ref)) w, err := content.OpenWriter(ctx, cs, content.WithRef(ref))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,3 +4,5 @@ version = 2
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"

View File

@ -55,7 +55,7 @@ function kill_all {
function cleanup { function cleanup {
rm -rf "${CONTAINERD_ROOT}"* rm -rf "${CONTAINERD_ROOT}"*
if [ -f "${REMOTE_SNAPSHOTTER_SOCKET}" ] ; then if [ -e "${REMOTE_SNAPSHOTTER_SOCKET}" ] ; then
rm "${REMOTE_SNAPSHOTTER_SOCKET}" rm "${REMOTE_SNAPSHOTTER_SOCKET}"
fi fi
if [ -d "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" ] ; then if [ -d "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" ] ; then

View File

@ -22,3 +22,5 @@ version = 2
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"

View File

@ -0,0 +1,26 @@
version = 2
# Basic CRI configuration with enabling Stargz Snapshotter
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
snapshotter = "stargz"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
# Enable Stargz Snapshotter in Transfer Service
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "linux"
snapshotter = "stargz"
# Enable overlayfs in Transfer Service
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "linux"
snapshotter = "overlayfs"
# Plugin Stargz Snapshotter
[proxy_plugins]
[proxy_plugins.stargz]
type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
enable_remote_snapshot_annotations = "true"

View File

@ -19,7 +19,10 @@ set -euo pipefail
CONTEXT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/" CONTEXT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/"
REPO="${CONTEXT}../../" REPO="${CONTEXT}../../"
CONTAINERD_SOCK=unix:///run/containerd/containerd.sock CONTAINERD_SOCK=unix:///run/containerd/containerd.sock
SNAPSHOTTER_SOCK=unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock IMAGE_ENDPOINT_SOCK=unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock
if [ "${FUSE_MANAGER:-}" == "true" ] ; then
IMAGE_ENDPOINT_SOCK=unix:///run/containerd-stargz-grpc/cri.sock
fi
source "${CONTEXT}/const.sh" source "${CONTEXT}/const.sh"
source "${REPO}/script/util/utils.sh" source "${REPO}/script/util/utils.sh"
@ -62,7 +65,11 @@ if [ "${FAIL}" == "" ] ; then
docker exec "${TEST_NODE_ID}" runc --version && \ docker exec "${TEST_NODE_ID}" runc --version && \
docker exec "${TEST_NODE_ID}" containerd --version && \ docker exec "${TEST_NODE_ID}" containerd --version && \
echo "===============================" && \ echo "===============================" && \
docker exec -i "${TEST_NODE_ID}" /go/bin/critest --runtime-endpoint=${CONTAINERD_SOCK} --image-endpoint=${SNAPSHOTTER_SOCK} # FIXME: remove the skip flag once kind adds support for the user namespace
# See also https://github.com/kubernetes-sigs/kind/issues/3436
docker exec -i "${TEST_NODE_ID}" /go/bin/critest \
--runtime-endpoint=${CONTAINERD_SOCK} --image-endpoint=${IMAGE_ENDPOINT_SOCK} \
--ginkgo.skip 'runtime should support NamespaceMode_POD'
) ; then ) ; then
FAIL=true FAIL=true
fi fi

View File

@ -22,7 +22,10 @@ REPO="${CONTEXT}../../"
REGISTRY_HOST="cri-registry" REGISTRY_HOST="cri-registry"
TEST_NODE_NAME="cri-testenv-container" TEST_NODE_NAME="cri-testenv-container"
CONTAINERD_SOCK=unix:///run/containerd/containerd.sock CONTAINERD_SOCK=unix:///run/containerd/containerd.sock
SNAPSHOTTER_SOCK=unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock IMAGE_ENDPOINT_SOCK=unix:///run/containerd-stargz-grpc/containerd-stargz-grpc.sock
if [ "${FUSE_MANAGER:-}" == "true" ] ; then
IMAGE_ENDPOINT_SOCK=unix:///run/containerd-stargz-grpc/cri.sock
fi
PREPARE_NODE_NAME="cri-prepare-node" PREPARE_NODE_NAME="cri-prepare-node"
source "${CONTEXT}/const.sh" source "${CONTEXT}/const.sh"
@ -115,11 +118,16 @@ docker exec "${PREPARE_NODE_NAME}" /bin/bash /tools/mirror.sh
# Configure mirror registries for containerd and snapshotter # Configure mirror registries for containerd and snapshotter
docker exec "${TEST_NODE_NAME}" cat /etc/containerd/config.toml > "${CONTAINERD_CONFIG}" docker exec "${TEST_NODE_NAME}" cat /etc/containerd/config.toml > "${CONTAINERD_CONFIG}"
docker exec "${TEST_NODE_NAME}" cat /etc/containerd-stargz-grpc/config.toml > "${SNAPSHOTTER_CONFIG}" docker exec "${TEST_NODE_NAME}" cat /etc/containerd-stargz-grpc/config.toml > "${SNAPSHOTTER_CONFIG}"
docker exec "${TEST_NODE_NAME}" mkdir -p "/etc/containerd/certs.d"
cat <<EOF >> "${CONTAINERD_CONFIG}"
[plugins."io.containerd.cri.v1.images".registry]
config_path = "/etc/containerd/certs.d"
EOF
cat "${IMAGE_LIST}" | sed -E 's/^([^/]*).*/\1/g' | sort | uniq | while read DOMAIN ; do cat "${IMAGE_LIST}" | sed -E 's/^([^/]*).*/\1/g' | sort | uniq | while read DOMAIN ; do
echo "Adding mirror config: ${DOMAIN}" echo "Adding mirror config: ${DOMAIN}"
cat <<EOF >> "${CONTAINERD_CONFIG}" docker exec "${TEST_NODE_NAME}" mkdir -p "/etc/containerd/certs.d/${DOMAIN}/"
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."${DOMAIN}"] cat <<EOF | docker exec -i "${TEST_NODE_NAME}" tee -a "/etc/containerd/certs.d/${DOMAIN}/hosts.toml"
endpoint = ["http://${REGISTRY_HOST}:5000"] server = "http://${REGISTRY_HOST}:5000"
EOF EOF
if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then
cat <<EOF >> "${CONTAINERD_CONFIG}" cat <<EOF >> "${CONTAINERD_CONFIG}"
@ -182,7 +190,12 @@ echo "===== VERSION INFORMATION ====="
docker exec "${TEST_NODE_NAME}" runc --version docker exec "${TEST_NODE_NAME}" runc --version
docker exec "${TEST_NODE_NAME}" containerd --version docker exec "${TEST_NODE_NAME}" containerd --version
echo "===============================" echo "==============================="
docker exec "${TEST_NODE_NAME}" /go/bin/critest --runtime-endpoint=${CONTAINERD_SOCK} --image-endpoint=${SNAPSHOTTER_SOCK}
# FIXME: remove the skip flag once kind adds support for the user namespace
# See also https://github.com/kubernetes-sigs/kind/issues/3436
docker exec "${TEST_NODE_NAME}" /go/bin/critest \
--runtime-endpoint=${CONTAINERD_SOCK} --image-endpoint=${IMAGE_ENDPOINT_SOCK} \
--ginkgo.skip 'runtime should support NamespaceMode_POD'
echo "Check if stargz snapshotter is working" echo "Check if stargz snapshotter is working"
docker exec "${TEST_NODE_NAME}" \ docker exec "${TEST_NODE_NAME}" \

View File

@ -50,7 +50,7 @@ function cleanup {
} }
trap 'cleanup "$?"' EXIT SIGHUP SIGINT SIGQUIT SIGTERM trap 'cleanup "$?"' EXIT SIGHUP SIGINT SIGQUIT SIGTERM
BUILTIN_HACK_INST= ADDITIONAL_INST=
if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then
# Special configuration for CRI containerd + builtin stargz snapshotter # Special configuration for CRI containerd + builtin stargz snapshotter
cat <<EOF > "${TMP_CONTEXT}/containerd.hack.toml" cat <<EOF > "${TMP_CONTEXT}/containerd.hack.toml"
@ -75,7 +75,7 @@ metadata_store = "memory"
[plugins."io.containerd.snapshotter.v1.stargz".cri_keychain] [plugins."io.containerd.snapshotter.v1.stargz".cri_keychain]
enable_keychain = true enable_keychain = true
EOF EOF
BUILTIN_HACK_INST="COPY containerd.hack.toml /etc/containerd/config.toml" ADDITIONAL_INST="COPY containerd.hack.toml /etc/containerd/config.toml"
fi fi
cat <<EOF > "${TMP_CONTEXT}/test.conflist" cat <<EOF > "${TMP_CONTEXT}/test.conflist"
@ -114,11 +114,33 @@ if [ "${METADATA_STORE:-}" != "" ] ; then
USE_METADATA_STORE="${METADATA_STORE}" USE_METADATA_STORE="${METADATA_STORE}"
fi fi
FUSE_MANAGER_CONFIG=""
if [ "${FUSE_MANAGER:-}" == "true" ] ; then
FUSE_MANAGER_CONFIG='listen_path = "/run/containerd-stargz-grpc/cri.sock"
[fuse_manager]
enable = true'
fi
SNAPSHOTTER_CONFIG_FILE=/etc/containerd-stargz-grpc/config.toml SNAPSHOTTER_CONFIG_FILE=/etc/containerd-stargz-grpc/config.toml
if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then
SNAPSHOTTER_CONFIG_FILE=/etc/containerd/config.toml SNAPSHOTTER_CONFIG_FILE=/etc/containerd/config.toml
fi fi
USE_FUSE_PASSTHROUGH="false"
if [ "${FUSE_PASSTHROUGH:-}" != "" ] ; then
USE_FUSE_PASSTHROUGH="${FUSE_PASSTHROUGH}"
if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] && [ "${FUSE_PASSTHROUGH}" == "true" ] ; then
echo "builtin snapshotter + fuse passthrough test is unsupported"
exit 1
fi
fi
if [ "${TRANSFER_SERVICE:-}" == "true" ] ; then
cp "${CONTEXT}/config.containerd.transfer.toml" "${TMP_CONTEXT}/"
ADDITIONAL_INST="${ADDITIONAL_INST}
COPY config.containerd.transfer.toml /etc/containerd/config.toml"
fi
# Prepare the testing node # Prepare the testing node
cat <<EOF > "${TMP_CONTEXT}/Dockerfile" cat <<EOF > "${TMP_CONTEXT}/Dockerfile"
# Legacy builder that doesn't support TARGETARCH should set this explicitly using --build-arg. # Legacy builder that doesn't support TARGETARCH should set this explicitly using --build-arg.
@ -131,7 +153,7 @@ ENV PATH=$PATH:/usr/local/go/bin
ENV GOPATH=/go ENV GOPATH=/go
# Do not install git and its dependencies here which will cause failure of building the image # Do not install git and its dependencies here which will cause failure of building the image
RUN apt-get update && apt-get install -y --no-install-recommends make && \ RUN apt-get update && apt-get install -y --no-install-recommends make && \
curl -Ls https://dl.google.com/go/go1.23.0.linux-\${TARGETARCH:-amd64}.tar.gz | tar -C /usr/local -xz && \ curl -Ls https://dl.google.com/go/go1.24.0.linux-\${TARGETARCH:-amd64}.tar.gz | tar -C /usr/local -xz && \
go install github.com/onsi/ginkgo/ginkgo@${GINKGO_VERSION} && \ go install github.com/onsi/ginkgo/ginkgo@${GINKGO_VERSION} && \
mkdir -p \${GOPATH}/src/github.com/kubernetes-sigs/cri-tools /tmp/cri-tools && \ mkdir -p \${GOPATH}/src/github.com/kubernetes-sigs/cri-tools /tmp/cri-tools && \
curl -sL https://github.com/kubernetes-sigs/cri-tools/archive/refs/tags/v${CRI_TOOLS_VERSION}.tar.gz | tar -C /tmp/cri-tools -xz && \ curl -sL https://github.com/kubernetes-sigs/cri-tools/archive/refs/tags/v${CRI_TOOLS_VERSION}.tar.gz | tar -C /tmp/cri-tools -xz && \
@ -143,9 +165,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends make && \
COPY ./test.conflist /etc/cni/net.d/test.conflist COPY ./test.conflist /etc/cni/net.d/test.conflist
${BUILTIN_HACK_INST} ${ADDITIONAL_INST}
RUN sed -i 's/^metadata_store.*/metadata_store = "${USE_METADATA_STORE}"/g' "${SNAPSHOTTER_CONFIG_FILE}" RUN <<EEE
cat <<EOT >> "${SNAPSHOTTER_CONFIG_FILE}"
${FUSE_MANAGER_CONFIG}
EOT
EEE
RUN if [ "${BUILTIN_SNAPSHOTTER:-}" != "true" ] ; then \
sed -i '1imetadata_store = "${USE_METADATA_STORE}"' "${SNAPSHOTTER_CONFIG_FILE}" && \
echo '[fuse]' >> "${SNAPSHOTTER_CONFIG_FILE}" && \
echo "passthrough = ${USE_FUSE_PASSTHROUGH}" >> "${SNAPSHOTTER_CONFIG_FILE}" ; \
fi
ENTRYPOINT [ "/usr/local/bin/entrypoint", "/sbin/init" ] ENTRYPOINT [ "/usr/local/bin/entrypoint", "/sbin/init" ]
EOF EOF

View File

@ -66,7 +66,7 @@ ENV PATH=$PATH:/usr/local/go/bin
ENV GOPATH=/go ENV GOPATH=/go
# Do not install git and its dependencies here which will cause failure of building the image # Do not install git and its dependencies here which will cause failure of building the image
RUN apt-get update && apt-get install -y --no-install-recommends make && \ RUN apt-get update && apt-get install -y --no-install-recommends make && \
curl -Ls https://dl.google.com/go/go1.23.0.linux-\${TARGETARCH:-amd64}.tar.gz | tar -C /usr/local -xz && \ curl -Ls https://dl.google.com/go/go1.24.0.linux-\${TARGETARCH:-amd64}.tar.gz | tar -C /usr/local -xz && \
go install github.com/onsi/ginkgo/ginkgo@${GINKGO_VERSION} && \ go install github.com/onsi/ginkgo/ginkgo@${GINKGO_VERSION} && \
mkdir -p \${GOPATH}/src/github.com/kubernetes-sigs/cri-tools /tmp/cri-tools && \ mkdir -p \${GOPATH}/src/github.com/kubernetes-sigs/cri-tools /tmp/cri-tools && \
curl -sL https://github.com/kubernetes-sigs/cri-tools/archive/refs/tags/v${CRI_TOOLS_VERSION}.tar.gz | tar -C /tmp/cri-tools -xz && \ curl -sL https://github.com/kubernetes-sigs/cri-tools/archive/refs/tags/v${CRI_TOOLS_VERSION}.tar.gz | tar -C /tmp/cri-tools -xz && \

View File

@ -4,3 +4,5 @@ version = 2
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"

View File

@ -46,13 +46,14 @@ function retry {
function kill_all { function kill_all {
if [ "${1}" != "" ] ; then if [ "${1}" != "" ] ; then
ps aux | grep "${1}" | grep -v grep | sed -E 's/ +/ /g' | cut -f 2 -d ' ' | xargs -I{} kill -9 {} || true S="${2:-SIGKILL}"
ps aux | grep "${1} " | grep -v grep | sed -E 's/ +/ /g' | cut -f 2 -d ' ' | xargs -I{} kill -s $S {} || true
fi fi
} }
function cleanup { function cleanup {
rm -rf "${CONTAINERD_ROOT}"* rm -rf "${CONTAINERD_ROOT}"*
if [ -f "${REMOTE_SNAPSHOTTER_SOCKET}" ] ; then if [ -e "${REMOTE_SNAPSHOTTER_SOCKET}" ] ; then
rm "${REMOTE_SNAPSHOTTER_SOCKET}" rm "${REMOTE_SNAPSHOTTER_SOCKET}"
fi fi
if [ -d "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" ] ; then if [ -d "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" ] ; then
@ -71,6 +72,7 @@ mkdir -p "${CONTAINERD_CONFIG_DIR}" "${REMOTE_SNAPSHOTTER_CONFIG_DIR}" "${CNI_CO
echo "cleaning up the environment..." echo "cleaning up the environment..."
kill_all "containerd" kill_all "containerd"
kill_all "containerd-stargz-grpc" kill_all "containerd-stargz-grpc"
kill_all "stargz-fuse-manager" SIGTERM
cleanup cleanup
echo "preparing commands..." echo "preparing commands..."

View File

@ -10,3 +10,13 @@ check_always = true
[plugins."io.containerd.snapshotter.v1.stargz".registry.mirrors."registry-integration.test"] [plugins."io.containerd.snapshotter.v1.stargz".registry.mirrors."registry-integration.test"]
endpoint = ["http://registry-alt.test:5000"] endpoint = ["http://registry-alt.test:5000"]
# Enable Stargz Snapshotter in Transfer Service
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "linux"
snapshotter = "stargz"
# Enable overlayfs in Transfer Service
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "linux"
snapshotter = "overlayfs"

View File

@ -1,6 +1,9 @@
metadata_store = "memory" metadata_store = "memory"
ipfs = true ipfs = true
[fuse]
passthrough = false
[blob] [blob]
check_always = true check_always = true
max_retries = 1 max_retries = 1

View File

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
set -euo pipefail set -eux -o pipefail
# NOTE: The entire contents of containerd/stargz-snapshotter are located in # NOTE: The entire contents of containerd/stargz-snapshotter are located in
# the testing container so utils.sh is visible from this script during runtime. # the testing container so utils.sh is visible from this script during runtime.
@ -28,6 +28,8 @@ REGISTRY_ALT_HOST=registry-alt.test
DUMMYUSER=dummyuser DUMMYUSER=dummyuser
DUMMYPASS=dummypass DUMMYPASS=dummypass
FUSE_MANAGER_LOG="Start snapshotter with fusemanager mode"
USR_ORG=$(mktemp -d) USR_ORG=$(mktemp -d)
USR_MIRROR=$(mktemp -d) USR_MIRROR=$(mktemp -d)
USR_REFRESH=$(mktemp -d) USR_REFRESH=$(mktemp -d)
@ -93,22 +95,32 @@ function retry {
function kill_all { function kill_all {
if [ "${1}" != "" ] ; then if [ "${1}" != "" ] ; then
ps aux | grep "${1}" | grep -v grep | grep -v $(basename ${0}) | sed -E 's/ +/ /g' | cut -f 2 -d ' ' | xargs -I{} kill -9 {} || true TARGET_SIGNAL="-s ${2:-SIGKILL}"
ps aux | grep "${1} " | grep -v grep | grep -v $(basename ${0}) | sed -E 's/ +/ /g' | cut -f 2 -d ' ' | xargs -I{} kill ${TARGET_SIGNAL} {} || true
fi fi
} }
function wait_all {
while ps aux | grep -v grep | grep -v $(basename ${0}) | grep "${1} " ; do sleep 3 ; done
}
CONTAINERD_ROOT=/var/lib/containerd/ CONTAINERD_ROOT=/var/lib/containerd/
CONTAINERD_STATUS=/run/containerd/ CONTAINERD_STATUS=/run/containerd/
REMOTE_SNAPSHOTTER_SOCKET=/run/containerd-stargz-grpc/containerd-stargz-grpc.sock REMOTE_SNAPSHOTTER_SOCKET=/run/containerd-stargz-grpc/containerd-stargz-grpc.sock
REMOTE_SNAPSHOTTER_ROOT=/var/lib/containerd-stargz-grpc/ REMOTE_SNAPSHOTTER_ROOT=/var/lib/containerd-stargz-grpc/
REMOTE_SNAPSHOTTER_FUSE_MANAGER_SOCKET=/run/containerd-stargz-grpc/fuse-manager.sock
function reboot_containerd { function reboot_containerd {
kill_all "containerd" kill_all "containerd"
kill_all "containerd-stargz-grpc" kill_all "containerd-stargz-grpc"
kill_all "stargz-fuse-manager" SIGTERM
rm -rf "${CONTAINERD_STATUS}"* rm -rf "${CONTAINERD_STATUS}"*
rm -rf "${CONTAINERD_ROOT}"* rm -rf "${CONTAINERD_ROOT}"*
if [ -f "${REMOTE_SNAPSHOTTER_SOCKET}" ] ; then if [ -e "${REMOTE_SNAPSHOTTER_SOCKET}" ] ; then
rm "${REMOTE_SNAPSHOTTER_SOCKET}" rm "${REMOTE_SNAPSHOTTER_SOCKET}"
fi fi
if [ -e "${REMOTE_SNAPSHOTTER_FUSE_MANAGER_SOCKET}" ] ; then
rm "${REMOTE_SNAPSHOTTER_FUSE_MANAGER_SOCKET}"
fi
if [ -d "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" ] ; then if [ -d "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" ] ; then
find "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" \ find "${REMOTE_SNAPSHOTTER_ROOT}snapshotter/snapshots/" \
-maxdepth 1 -mindepth 1 -type d -exec umount "{}/fs" \; -maxdepth 1 -mindepth 1 -type d -exec umount "{}/fs" \;
@ -133,6 +145,19 @@ function reboot_containerd {
fi fi
retry ls "${REMOTE_SNAPSHOTTER_SOCKET}" retry ls "${REMOTE_SNAPSHOTTER_SOCKET}"
containerd --log-level debug --config=/etc/containerd/config.toml & containerd --log-level debug --config=/etc/containerd/config.toml &
if [ "${NO_FUSE_MANAGER_CHECK:-}" != "true" ] ; then
if cat "${LOG_FILE}" | grep "${FUSE_MANAGER_LOG}" ; then
if [ "${FUSE_MANAGER}" != "true" ] ; then
echo "fuse manager should not be enabled"
exit 1
fi
else
if [ "${FUSE_MANAGER}" == "true" ] ; then
echo "fuse manager should be enabled"
exit 1
fi
fi
fi
fi fi
# Makes sure containerd and containerd-stargz-grpc are up-and-running. # Makes sure containerd and containerd-stargz-grpc are up-and-running.
@ -171,9 +196,9 @@ function convert {
function copy { function copy {
local SRC="${1}" local SRC="${1}"
local DST="${2}" local DST="${2}"
ctr-remote i pull --all-platforms "${SRC}" ctr-remote image pull --all-platforms "${SRC}"
ctr-remote i tag "${SRC}" "${DST}" ctr-remote image tag "${SRC}" "${DST}"
ctr-remote i push -u "${DUMMYUSER}:${DUMMYPASS}" "${DST}" ctr-remote image push -u "${DUMMYUSER}:${DUMMYPASS}" "${DST}"
} }
function copy_out_dir { function copy_out_dir {
@ -191,6 +216,11 @@ function copy_out_dir {
rm "${TMPFILE}" rm "${TMPFILE}"
} }
RPULL_COMMAND="rpull"
if [ "${USE_TRANSFER_SERVICE}" == "true" ] ; then
RPULL_COMMAND="pull --snapshotter=stargz"
fi
function dump_dir { function dump_dir {
local IMAGE="${1}" local IMAGE="${1}"
local TARGETDIR="${2}" local TARGETDIR="${2}"
@ -200,9 +230,9 @@ function dump_dir {
reboot_containerd reboot_containerd
if [ "${REMOTE}" == "true" ] ; then if [ "${REMOTE}" == "true" ] ; then
run_and_check_remote_snapshots ctr-remote images rpull --user "${DUMMYUSER}:${DUMMYPASS}" "${IMAGE}" run_and_check_remote_snapshots ctr-remote images ${RPULL_COMMAND} --user "${DUMMYUSER}:${DUMMYPASS}" "${IMAGE}"
else else
ctr-remote images pull --snapshotter="${SNAPSHOTTER}" --user "${DUMMYUSER}:${DUMMYPASS}" "${IMAGE}" ctr-remote image pull --snapshotter="${SNAPSHOTTER}" --user "${DUMMYUSER}:${DUMMYPASS}" "${IMAGE}"
fi fi
copy_out_dir "${IMAGE}" "${TARGETDIR}" "${DEST}" "${SNAPSHOTTER}" copy_out_dir "${IMAGE}" "${TARGETDIR}" "${DEST}" "${SNAPSHOTTER}"
} }
@ -243,6 +273,9 @@ if [ "${BUILTIN_SNAPSHOTTER}" != "true" ] ; then
[proxy_plugins.stargz] [proxy_plugins.stargz]
type = "snapshot" type = "snapshot"
address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock"
[proxy_plugins.stargz.exports]
root = "/var/lib/containerd-stargz-grpc/"
enable_remote_snapshot_annotations = "true"
EOF EOF
fi fi
@ -276,9 +309,9 @@ optimize "${REGISTRY_HOST}/alpine:3.15.3" "${REGISTRY_ALT_HOST}:5000/alpine:esgz
# TODO: support external TOC suffix other than "-esgztoc" # TODO: support external TOC suffix other than "-esgztoc"
optimize "${REGISTRY_HOST}/ubuntu:22.04" "${REGISTRY_HOST}/ubuntu:esgz-50000" "false" --estargz-min-chunk-size=50000 optimize "${REGISTRY_HOST}/ubuntu:22.04" "${REGISTRY_HOST}/ubuntu:esgz-50000" "false" --estargz-min-chunk-size=50000
optimize "${REGISTRY_HOST}/ubuntu:22.04" "${REGISTRY_HOST}/ubuntu:esgz-ex" "false" --estargz-external-toc optimize "${REGISTRY_HOST}/ubuntu:22.04" "${REGISTRY_HOST}/ubuntu:esgz-ex" "false" --estargz-external-toc
ctr-remote i push -u "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:esgz-ex-esgztoc" ctr-remote image push -u "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:esgz-ex-esgztoc"
convert "${REGISTRY_HOST}/ubuntu:22.04" "${REGISTRY_HOST}/ubuntu:esgz-ex-keep-diff-id" "false" --estargz --estargz-external-toc --estargz-keep-diff-id convert "${REGISTRY_HOST}/ubuntu:22.04" "${REGISTRY_HOST}/ubuntu:esgz-ex-keep-diff-id" "false" --estargz --estargz-external-toc --estargz-keep-diff-id
ctr-remote i push -u "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:esgz-ex-keep-diff-id-esgztoc" ctr-remote image push -u "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:esgz-ex-keep-diff-id-esgztoc"
if [ "${BUILTIN_SNAPSHOTTER}" != "true" ] ; then if [ "${BUILTIN_SNAPSHOTTER}" != "true" ] ; then
@ -294,21 +327,21 @@ if [ "${BUILTIN_SNAPSHOTTER}" != "true" ] ; then
retry curl -X POST localhost:5001/api/v0/version >/dev/null 2>&1 # wait for up retry curl -X POST localhost:5001/api/v0/version >/dev/null 2>&1 # wait for up
# stargz snapshotter (default labels) # stargz snapshotter (default labels)
ctr-remote i pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:22.04" ctr-remote image pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:22.04"
CID=$(ctr-remote i ipfs-push "${REGISTRY_HOST}/ubuntu:22.04") CID=$(ctr-remote i ipfs-push "${REGISTRY_HOST}/ubuntu:22.04")
reboot_containerd reboot_containerd
run_and_check_remote_snapshots ctr-remote i rpull --ipfs "${CID}" run_and_check_remote_snapshots ctr-remote i rpull --ipfs "${CID}"
copy_out_dir "${CID}" "/usr" "${USR_STARGZSN_IPFS}" "stargz" copy_out_dir "${CID}" "/usr" "${USR_STARGZSN_IPFS}" "stargz"
# stargz snapshotter (containerd labels) # stargz snapshotter (containerd labels)
ctr-remote i pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:22.04" ctr-remote image pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:22.04"
CID=$(ctr-remote i ipfs-push "${REGISTRY_HOST}/ubuntu:22.04") CID=$(ctr-remote i ipfs-push "${REGISTRY_HOST}/ubuntu:22.04")
reboot_containerd reboot_containerd
run_and_check_remote_snapshots ctr-remote i rpull --use-containerd-labels --ipfs "${CID}" run_and_check_remote_snapshots ctr-remote i rpull --use-containerd-labels --ipfs "${CID}"
copy_out_dir "${CID}" "/usr" "${USR_STARGZSN_CTD_IPFS}" "stargz" copy_out_dir "${CID}" "/usr" "${USR_STARGZSN_CTD_IPFS}" "stargz"
# overlayfs snapshotter # overlayfs snapshotter
ctr-remote i pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:22.04" ctr-remote image pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/ubuntu:22.04"
CID=$(ctr-remote i ipfs-push --estargz=false "${REGISTRY_HOST}/ubuntu:22.04") CID=$(ctr-remote i ipfs-push --estargz=false "${REGISTRY_HOST}/ubuntu:22.04")
reboot_containerd reboot_containerd
ctr-remote i rpull --snapshotter=overlayfs --ipfs "${CID}" ctr-remote i rpull --snapshotter=overlayfs --ipfs "${CID}"
@ -329,11 +362,11 @@ echo "Testing refreshing and mirror..."
reboot_containerd reboot_containerd
echo "Getting image with normal snapshotter..." echo "Getting image with normal snapshotter..."
ctr-remote images pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/alpine:esgz" ctr-remote image pull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/alpine:esgz"
copy_out_dir "${REGISTRY_HOST}/alpine:esgz" "/usr" "${USR_ORG}" "overlayfs" copy_out_dir "${REGISTRY_HOST}/alpine:esgz" "/usr" "${USR_ORG}" "overlayfs"
echo "Getting image with stargz snapshotter..." echo "Getting image with stargz snapshotter..."
run_and_check_remote_snapshots ctr-remote images rpull --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/alpine:esgz" run_and_check_remote_snapshots ctr-remote images ${RPULL_COMMAND} --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/alpine:esgz"
REGISTRY_HOST_IP=$(getent hosts "${REGISTRY_HOST}" | awk '{ print $1 }') REGISTRY_HOST_IP=$(getent hosts "${REGISTRY_HOST}" | awk '{ print $1 }')
REGISTRY_ALT_HOST_IP=$(getent hosts "${REGISTRY_ALT_HOST}" | awk '{ print $1 }') REGISTRY_ALT_HOST_IP=$(getent hosts "${REGISTRY_ALT_HOST}" | awk '{ print $1 }')
@ -473,13 +506,62 @@ diff --no-dereference -qr "${USR_NORMALSN_PLAIN_STARGZ}/" "${USR_STARGZSN_PLAIN_
############ ############
# Try to pull this image from different namespace. # Try to pull this image from different namespace.
ctr-remote --namespace=dummy images rpull --user "${DUMMYUSER}:${DUMMYPASS}" \ ctr-remote --namespace=dummy images ${RPULL_COMMAND} --user "${DUMMYUSER}:${DUMMYPASS}" \
"${REGISTRY_HOST}/ubuntu:esgz" "${REGISTRY_HOST}/ubuntu:esgz"
############ ############
# Test for starting when no configuration file. # Test for starting when no configuration file.
mv /etc/containerd-stargz-grpc/config.toml /etc/containerd-stargz-grpc/config.toml_rm mv /etc/containerd-stargz-grpc/config.toml /etc/containerd-stargz-grpc/config.toml_rm
reboot_containerd NO_FUSE_MANAGER_CHECK=true reboot_containerd
mv /etc/containerd-stargz-grpc/config.toml_rm /etc/containerd-stargz-grpc/config.toml mv /etc/containerd-stargz-grpc/config.toml_rm /etc/containerd-stargz-grpc/config.toml
############
# Test graceful restart
function check_cache_empty {
TARGET_DIRS=("${REMOTE_SNAPSHOTTER_ROOT}stargz/httpcache/" "${REMOTE_SNAPSHOTTER_ROOT}stargz/fscache/")
for D in "${TARGET_DIRS[@]}" ; do
test -z "$( ls -A $D )"
done
}
reboot_containerd
if [ "${BUILTIN_SNAPSHOTTER}" != "true" ] ; then
# Snapshots should be available even after restarting the snapshotter with a signal
run_and_check_remote_snapshots ctr-remote images ${RPULL_COMMAND} --user "${DUMMYUSER}:${DUMMYPASS}" "${REGISTRY_HOST}/alpine:esgz"
ctr-remote run --rm --snapshotter=stargz "${REGISTRY_HOST}/alpine:esgz" test echo hi
TARGET_SIGNALS=(SIGINT SIGTERM)
for S in "${TARGET_SIGNALS[@]}" ; do
# Kill the snapshotter
kill_all containerd-stargz-grpc "$S"
# wait until stargz snapshotter is finished
wait_all containerd-stargz-grpc
if [ "$S" == "SIGINT" ] ; then
# On SIGINT, fuse manager mode also performs graceful shutdown so test this behaviour.
if [ "${FUSE_MANAGER}" == "true" ] ; then
kill_all stargz-fuse-manager "$S"
wait_all stargz-fuse-manager
fi
# Check if resource are cleaned up
check_cache_empty
else
if [ "${FUSE_MANAGER}" != "true" ] ; then
# If this is not FUSE manager mode, check if resource are cleaned up
check_cache_empty
fi
fi
# Restart the snapshotter without additional operation
containerd-stargz-grpc --log-level=debug --address="${REMOTE_SNAPSHOTTER_SOCKET}" 2>&1 | tee -a "${LOG_FILE}" & # Dump all log
retry nc -z -U "${REMOTE_SNAPSHOTTER_SOCKET}"
sleep 3 # FIXME: Additional wait; sometimes snapshotter is still unavailable after the socket ready
# Check if the snapshotter is still usable
ctr-remote run --rm --snapshotter=stargz "${REGISTRY_HOST}/alpine:esgz" test echo hi
done
fi
exit 0 exit 0

View File

@ -55,11 +55,31 @@ if [ "${METADATA_STORE:-}" != "" ] ; then
USE_METADATA_STORE="${METADATA_STORE}" USE_METADATA_STORE="${METADATA_STORE}"
fi fi
FUSE_MANAGER_CONFIG=""
if [ "${FUSE_MANAGER:-}" == "true" ] ; then
FUSE_MANAGER_CONFIG="[fuse_manager]
enable = true"
fi
SNAPSHOTTER_CONFIG_FILE=/etc/containerd-stargz-grpc/config.toml SNAPSHOTTER_CONFIG_FILE=/etc/containerd-stargz-grpc/config.toml
if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] ; then
SNAPSHOTTER_CONFIG_FILE=/etc/containerd/config.toml SNAPSHOTTER_CONFIG_FILE=/etc/containerd/config.toml
fi fi
USE_FUSE_PASSTHROUGH="false"
if [ "${FUSE_PASSTHROUGH:-}" != "" ] ; then
USE_FUSE_PASSTHROUGH="${FUSE_PASSTHROUGH}"
if [ "${BUILTIN_SNAPSHOTTER:-}" == "true" ] && [ "${FUSE_PASSTHROUGH}" == "true" ] ; then
echo "builtin snapshotter + fuse passthrough test is unsupported"
exit 1
fi
fi
USE_TRANSFER_SERVICE=false
if [ "${TRANSFER_SERVICE:-}" == "true" ] ; then
USE_TRANSFER_SERVICE=true
fi
DOCKER_COMPOSE_YAML=$(mktemp) DOCKER_COMPOSE_YAML=$(mktemp)
AUTH_DIR=$(mktemp -d) AUTH_DIR=$(mktemp -d)
SS_ROOT_DIR=$(mktemp -d) SS_ROOT_DIR=$(mktemp -d)
@ -81,7 +101,7 @@ cat <<EOF > "${TMP_CONTEXT}/Dockerfile"
FROM ${INTEGRATION_BASE_IMAGE_NAME} FROM ${INTEGRATION_BASE_IMAGE_NAME}
RUN apt-get update -y && \ RUN apt-get update -y && \
apt-get --no-install-recommends install -y iptables jq && \ apt-get --no-install-recommends install -y iptables jq netcat && \
go install github.com/google/crfs/stargz/stargzify@71d77da419c90be7b05d12e59945ac7a8c94a543 && \ go install github.com/google/crfs/stargz/stargzify@71d77da419c90be7b05d12e59945ac7a8c94a543 && \
wget https://dist.ipfs.io/go-ipfs/${IPFS_VERSION}/go-ipfs_${IPFS_VERSION}_linux-amd64.tar.gz && \ wget https://dist.ipfs.io/go-ipfs/${IPFS_VERSION}/go-ipfs_${IPFS_VERSION}_linux-amd64.tar.gz && \
tar -xvzf go-ipfs_${IPFS_VERSION}_linux-amd64.tar.gz && \ tar -xvzf go-ipfs_${IPFS_VERSION}_linux-amd64.tar.gz && \
@ -92,10 +112,19 @@ COPY ./containerd/config.containerd.toml /etc/containerd/config.toml
COPY ./containerd/config.stargz.toml /etc/containerd-stargz-grpc/config.toml COPY ./containerd/config.stargz.toml /etc/containerd-stargz-grpc/config.toml
COPY ./containerd/entrypoint.sh ./utils.sh / COPY ./containerd/entrypoint.sh ./utils.sh /
RUN sed -i 's/^metadata_store.*/metadata_store = "${USE_METADATA_STORE}"/g' "${SNAPSHOTTER_CONFIG_FILE}" RUN if [ "${BUILTIN_SNAPSHOTTER:-}" != "true" ] ; then \
sed -i 's/^metadata_store.*/metadata_store = "${USE_METADATA_STORE}"/g' "${SNAPSHOTTER_CONFIG_FILE}" && \
sed -i 's/^passthrough.*/passthrough = ${USE_FUSE_PASSTHROUGH}/g' "${SNAPSHOTTER_CONFIG_FILE}" ; \
fi
RUN <<EEE
cat <<EOT >> "${SNAPSHOTTER_CONFIG_FILE}"
${FUSE_MANAGER_CONFIG}
EOT
EEE
ENV CONTAINERD_SNAPSHOTTER="" ENV CONTAINERD_SNAPSHOTTER=""
ENV USE_TRANSFER_SERVICE="${USE_TRANSFER_SERVICE}"
ENTRYPOINT [ "/entrypoint.sh" ] ENTRYPOINT [ "/entrypoint.sh" ]
EOF EOF
docker build ${DOCKER_BUILD_ARGS:-} -t "${INTEGRATION_TEST_IMAGE_NAME}" ${DOCKER_BUILD_ARGS:-} "${TMP_CONTEXT}" docker build ${DOCKER_BUILD_ARGS:-} -t "${INTEGRATION_TEST_IMAGE_NAME}" ${DOCKER_BUILD_ARGS:-} "${TMP_CONTEXT}"
@ -118,6 +147,7 @@ services:
- http_proxy=${http_proxy:-} - http_proxy=${http_proxy:-}
- https_proxy=${https_proxy:-} - https_proxy=${https_proxy:-}
- BUILTIN_SNAPSHOTTER=${BUILTIN_SNAPSHOTTER:-} - BUILTIN_SNAPSHOTTER=${BUILTIN_SNAPSHOTTER:-}
- FUSE_MANAGER=${FUSE_MANAGER:-}
tmpfs: tmpfs:
- /tmp:exec,mode=777 - /tmp:exec,mode=777
volumes: volumes:

View File

@ -22,6 +22,7 @@ REPO="${CONTEXT}../../"
K3S_VERSION=master K3S_VERSION=master
K3S_REPO=https://github.com/k3s-io/k3s K3S_REPO=https://github.com/k3s-io/k3s
K3S_CONTAINERD_REPO=https://github.com/k3s-io/containerd K3S_CONTAINERD_REPO=https://github.com/k3s-io/containerd
ARGO_VERSION=v3.6.4
K3S_NODE_REPO=ghcr.io/stargz-containers K3S_NODE_REPO=ghcr.io/stargz-containers
K3S_NODE_IMAGE_NAME=k3s K3S_NODE_IMAGE_NAME=k3s
@ -86,7 +87,33 @@ function run {
--k3s-arg='--snapshotter='"${SNAPSHOTTER}"'@server:*;agent:*' --k3s-arg='--snapshotter='"${SNAPSHOTTER}"'@server:*;agent:*'
kubectl create ns argo kubectl create ns argo
kubectl apply -n argo -f "${CUSTOM_ARGOYAML}" kubectl apply -n argo -f "${CUSTOM_ARGOYAML}"
# workaround for argo failing to list namespaces
cat <<EOF | kubectl -n argo apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argo-namespace-access-cr
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argo-namespace-access-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-namespace-access-cr
subjects:
- kind: ServiceAccount
name: argo
namespace: argo
EOF
# Wait for the cluster is ready # Wait for the cluster is ready
local RETRYNUM=30 local RETRYNUM=30
local RETRYINTERVAL=1 local RETRYINTERVAL=1
@ -122,7 +149,7 @@ if [ "${RESULT_FILE}" == "" ] ; then
fi fi
echo "result to ${RESULT_FILE}" echo "result to ${RESULT_FILE}"
wget -O "${ORG_ARGOYAML}" https://raw.githubusercontent.com/argoproj/argo-workflows/v3.4.3/manifests/quick-start-minimal.yaml wget -O "${ORG_ARGOYAML}" https://raw.githubusercontent.com/argoproj/argo-workflows/${ARGO_VERSION}/manifests/quick-start-minimal.yaml
git clone -b ${K3S_VERSION} --depth 1 "${K3S_REPO}" "${TMP_K3S_REPO}" git clone -b ${K3S_VERSION} --depth 1 "${K3S_REPO}" "${TMP_K3S_REPO}"
sed -i "s|github.com/k3s-io/stargz-snapshotter .*$|$(realpath ${REPO})|g" "${TMP_K3S_REPO}/go.mod" sed -i "s|github.com/k3s-io/stargz-snapshotter .*$|$(realpath ${REPO})|g" "${TMP_K3S_REPO}/go.mod"

View File

@ -204,9 +204,7 @@ echo "Checking optimized image..."
WORKING_DIR=$(mktemp -d) WORKING_DIR=$(mktemp -d)
git config --global --add safe.directory '/go/src/github.com/containerd/stargz-snapshotter' git config --global --add safe.directory '/go/src/github.com/containerd/stargz-snapshotter'
PREFIX=/tmp/out/ make clean PREFIX=/tmp/out/ make clean
# temporary disable -race flag to run test with statically built binaries PREFIX=/tmp/out/ GO_BUILD_FLAGS="-race" make ctr-remote # Check data race
# PREFIX=/tmp/out/ GO_BUILD_FLAGS="-race" make ctr-remote # Check data race
PREFIX=/tmp/out/ make ctr-remote
/tmp/out/ctr-remote ${OPTIMIZE_COMMAND} -entrypoint='[ "/accessor" ]' "${ORG_IMAGE_TAG}" "${OPT_IMAGE_TAG}" /tmp/out/ctr-remote ${OPTIMIZE_COMMAND} -entrypoint='[ "/accessor" ]' "${ORG_IMAGE_TAG}" "${OPT_IMAGE_TAG}"
nerdctl push "${OPT_IMAGE_TAG}" || true nerdctl push "${OPT_IMAGE_TAG}" || true
cat <<EOF > "${WORKING_DIR}/0-want" cat <<EOF > "${WORKING_DIR}/0-want"

View File

@ -26,35 +26,38 @@ type Config struct {
config.Config config.Config
// KubeconfigKeychainConfig is config for kubeconfig-based keychain. // KubeconfigKeychainConfig is config for kubeconfig-based keychain.
KubeconfigKeychainConfig `toml:"kubeconfig_keychain"` KubeconfigKeychainConfig `toml:"kubeconfig_keychain" json:"kubeconfig_keychain"`
// CRIKeychainConfig is config for CRI-based keychain. // CRIKeychainConfig is config for CRI-based keychain.
CRIKeychainConfig `toml:"cri_keychain"` CRIKeychainConfig `toml:"cri_keychain" json:"cri_keychain"`
// ResolverConfig is config for resolving registries. // ResolverConfig is config for resolving registries.
ResolverConfig `toml:"resolver"` ResolverConfig `toml:"resolver" json:"resolver"`
// SnapshotterConfig is snapshotter-related config. // SnapshotterConfig is snapshotter-related config.
SnapshotterConfig `toml:"snapshotter"` SnapshotterConfig `toml:"snapshotter" json:"snapshotter"`
} }
// KubeconfigKeychainConfig is config for kubeconfig-based keychain. // KubeconfigKeychainConfig is config for kubeconfig-based keychain.
type KubeconfigKeychainConfig struct { type KubeconfigKeychainConfig struct {
// EnableKeychain enables kubeconfig-based keychain // EnableKeychain enables kubeconfig-based keychain
EnableKeychain bool `toml:"enable_keychain"` EnableKeychain bool `toml:"enable_keychain" json:"enable_keychain"`
// KubeconfigPath is the path to kubeconfig which can be used to sync // KubeconfigPath is the path to kubeconfig which can be used to sync
// secrets on the cluster into this snapshotter. // secrets on the cluster into this snapshotter.
KubeconfigPath string `toml:"kubeconfig_path"` KubeconfigPath string `toml:"kubeconfig_path" json:"kubeconfig_path"`
} }
// CRIKeychainConfig is config for CRI-based keychain. // CRIKeychainConfig is config for CRI-based keychain.
type CRIKeychainConfig struct { type CRIKeychainConfig struct {
// EnableKeychain enables CRI-based keychain // EnableKeychain enables CRI-based keychain
EnableKeychain bool `toml:"enable_keychain"` EnableKeychain bool `toml:"enable_keychain" json:"enable_keychain"`
// ImageServicePath is the path to the unix socket of backing CRI Image Service (e.g. containerd CRI plugin) // ImageServicePath is the path to the unix socket of backing CRI Image Service (e.g. containerd CRI plugin)
ImageServicePath string `toml:"image_service_path"` ImageServicePath string `toml:"image_service_path" json:"image_service_path"`
// ListenPath is the path to the unix socket to listen
ListenPath string `toml:"listen_path" json:"listen_path"`
} }
// ResolverConfig is config for resolving registries. // ResolverConfig is config for resolving registries.
@ -66,5 +69,5 @@ type SnapshotterConfig struct {
// data source when restarting the snapshotter. // data source when restarting the snapshotter.
// NOTE: User needs to manually remove the snapshots from containerd's metadata store using // NOTE: User needs to manually remove the snapshots from containerd's metadata store using
// ctr (e.g. `ctr snapshot rm`). // ctr (e.g. `ctr snapshot rm`).
AllowInvalidMountsOnRestart bool `toml:"allow_invalid_mounts_on_restart"` AllowInvalidMountsOnRestart bool `toml:"allow_invalid_mounts_on_restart" json:"allow_invalid_mounts_on_restart"`
} }

View File

@ -0,0 +1,88 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package keychainconfig
import (
"context"
"time"
"github.com/containerd/containerd/v2/defaults"
"github.com/containerd/containerd/v2/pkg/dialer"
"github.com/containerd/stargz-snapshotter/service/keychain/cri"
"github.com/containerd/stargz-snapshotter/service/keychain/dockerconfig"
"github.com/containerd/stargz-snapshotter/service/keychain/kubeconfig"
"github.com/containerd/stargz-snapshotter/service/resolver"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
)
type Config struct {
EnableKubeKeychain bool
EnableCRIKeychain bool
KubeconfigPath string
DefaultImageServiceAddress string
ImageServicePath string
}
func ConfigKeychain(ctx context.Context, rpc *grpc.Server, config *Config) ([]resolver.Credential, error) {
credsFuncs := []resolver.Credential{dockerconfig.NewDockerconfigKeychain(ctx)}
if config.EnableKubeKeychain {
var opts []kubeconfig.Option
if kcp := config.KubeconfigPath; kcp != "" {
opts = append(opts, kubeconfig.WithKubeconfigPath(kcp))
}
credsFuncs = append(credsFuncs, kubeconfig.NewKubeconfigKeychain(ctx, opts...))
}
if config.EnableCRIKeychain {
// connects to the backend CRI service (defaults to containerd socket)
criAddr := config.DefaultImageServiceAddress
if cp := config.ImageServicePath; cp != "" {
criAddr = cp
}
connectCRI := func() (runtime.ImageServiceClient, error) {
conn, err := newCRIConn(criAddr)
if err != nil {
return nil, err
}
return runtime.NewImageServiceClient(conn), nil
}
f, criServer := cri.NewCRIKeychain(ctx, connectCRI)
runtime.RegisterImageServiceServer(rpc, criServer)
credsFuncs = append(credsFuncs, f)
}
return credsFuncs, nil
}
func newCRIConn(criAddr string) (*grpc.ClientConn, error) {
// TODO: make gRPC options configurable from config.toml
backoffConfig := backoff.DefaultConfig
backoffConfig.MaxDelay = 3 * time.Second
connParams := grpc.ConnectParams{
Backoff: backoffConfig,
}
gopts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithConnectParams(connParams),
grpc.WithContextDialer(dialer.ContextDialer),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
}
return grpc.NewClient(dialer.DialAddress(criAddr), gopts...)
}

View File

@ -146,7 +146,7 @@ func (kc *keychain) credentials(host string, refspec reference.Spec) (string, st
if acfg, err := cfg.GetAuthConfig(host); err == nil { if acfg, err := cfg.GetAuthConfig(host); err == nil {
if acfg.IdentityToken != "" { if acfg.IdentityToken != "" {
return "", acfg.IdentityToken, nil return "", acfg.IdentityToken, nil
} else if !(acfg.Username == "" && acfg.Password == "") { } else if acfg.Username != "" || acfg.Password != "" {
return acfg.Username, acfg.Password, nil return acfg.Username, acfg.Password, nil
} }
} }
@ -204,7 +204,7 @@ func (kc *keychain) startSyncSecrets(ctx context.Context, client kubernetes.Inte
}) })
go informer.Run(ctx.Done()) go informer.Run(ctx.Done())
if !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) { if !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) {
return fmt.Errorf("Timed out for syncing cache") return fmt.Errorf("timed out for syncing cache")
} }
// get informer and queue // get informer and queue

View File

@ -78,17 +78,17 @@ func RegisterPlugin() {
// Configure keychain // Configure keychain
credsFuncs := []resolver.Credential{dockerconfig.NewDockerconfigKeychain(ctx)} credsFuncs := []resolver.Credential{dockerconfig.NewDockerconfigKeychain(ctx)}
if config.Config.KubeconfigKeychainConfig.EnableKeychain { if config.KubeconfigKeychainConfig.EnableKeychain {
var opts []kubeconfig.Option var opts []kubeconfig.Option
if kcp := config.Config.KubeconfigKeychainConfig.KubeconfigPath; kcp != "" { if kcp := config.KubeconfigPath; kcp != "" {
opts = append(opts, kubeconfig.WithKubeconfigPath(kcp)) opts = append(opts, kubeconfig.WithKubeconfigPath(kcp))
} }
credsFuncs = append(credsFuncs, kubeconfig.NewKubeconfigKeychain(ctx, opts...)) credsFuncs = append(credsFuncs, kubeconfig.NewKubeconfigKeychain(ctx, opts...))
} }
if addr := config.CRIKeychainImageServicePath; config.Config.CRIKeychainConfig.EnableKeychain && addr != "" { if addr := config.CRIKeychainImageServicePath; config.CRIKeychainConfig.EnableKeychain && addr != "" {
// connects to the backend CRI service (defaults to containerd socket) // connects to the backend CRI service (defaults to containerd socket)
criAddr := ic.Properties[ctdplugins.PropertyGRPCAddress] criAddr := ic.Properties[ctdplugins.PropertyGRPCAddress]
if cp := config.Config.CRIKeychainConfig.ImageServicePath; cp != "" { if cp := config.ImageServicePath; cp != "" {
criAddr = cp criAddr = cp
} }
if criAddr == "" { if criAddr == "" {

View File

@ -31,28 +31,28 @@ const defaultRequestTimeoutSec = 30
// Config is config for resolving registries. // Config is config for resolving registries.
type Config struct { type Config struct {
Host map[string]HostConfig `toml:"host"` Host map[string]HostConfig `toml:"host" json:"host"`
} }
type HostConfig struct { type HostConfig struct {
Mirrors []MirrorConfig `toml:"mirrors"` Mirrors []MirrorConfig `toml:"mirrors" json:"mirrors"`
} }
type MirrorConfig struct { type MirrorConfig struct {
// Host is the hostname of the host. // Host is the hostname of the host.
Host string `toml:"host"` Host string `toml:"host" json:"host"`
// Insecure is true means use http scheme instead of https. // Insecure is true means use http scheme instead of https.
Insecure bool `toml:"insecure"` Insecure bool `toml:"insecure" json:"insecure"`
// RequestTimeoutSec is timeout seconds of each request to the registry. // RequestTimeoutSec is timeout seconds of each request to the registry.
// RequestTimeoutSec == 0 indicates the default timeout (defaultRequestTimeoutSec). // RequestTimeoutSec == 0 indicates the default timeout (defaultRequestTimeoutSec).
// RequestTimeoutSec < 0 indicates no timeout. // RequestTimeoutSec < 0 indicates no timeout.
RequestTimeoutSec int `toml:"request_timeout_sec"` RequestTimeoutSec int `toml:"request_timeout_sec" json:"request_timeout_sec"`
// Header are additional headers to send to the server // Header are additional headers to send to the server
Header map[string]interface{} `toml:"header"` Header map[string]interface{} `toml:"header" json:"header"`
} }
type Credential func(string, reference.Spec) (string, string, error) type Credential func(string, reference.Spec) (string, string, error)
@ -120,7 +120,7 @@ func multiCredsFuncs(ref reference.Spec, credsFuncs ...Credential) func(string)
for _, f := range credsFuncs { for _, f := range credsFuncs {
if username, secret, err := f(host, ref); err != nil { if username, secret, err := f(host, ref); err != nil {
return "", "", err return "", "", err
} else if !(username == "" && secret == "") { } else if username != "" || secret != "" {
return username, secret, nil return username, secret, nil
} }
} }

View File

@ -18,6 +18,8 @@ package service
import ( import (
"context" "context"
"errors"
"fmt"
"path/filepath" "path/filepath"
"github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/containerd/v2/core/snapshots"
@ -30,8 +32,7 @@ import (
"github.com/containerd/stargz-snapshotter/metadata" "github.com/containerd/stargz-snapshotter/metadata"
esgzexternaltoc "github.com/containerd/stargz-snapshotter/nativeconverter/estargz/externaltoc" esgzexternaltoc "github.com/containerd/stargz-snapshotter/nativeconverter/estargz/externaltoc"
"github.com/containerd/stargz-snapshotter/service/resolver" "github.com/containerd/stargz-snapshotter/service/resolver"
snbase "github.com/containerd/stargz-snapshotter/snapshot" "github.com/containerd/stargz-snapshotter/snapshot"
"github.com/hashicorp/go-multierror"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
@ -66,6 +67,27 @@ func WithFilesystemOptions(opts ...stargzfs.Option) Option {
// NewStargzSnapshotterService returns stargz snapshotter. // NewStargzSnapshotterService returns stargz snapshotter.
func NewStargzSnapshotterService(ctx context.Context, root string, config *Config, opts ...Option) (snapshots.Snapshotter, error) { func NewStargzSnapshotterService(ctx context.Context, root string, config *Config, opts ...Option) (snapshots.Snapshotter, error) {
fs, err := NewFileSystem(ctx, root, config, opts...)
if err != nil {
return nil, fmt.Errorf("failed to configure filesystem: %w", err)
}
var snapshotter snapshots.Snapshotter
snOpts := []snapshot.Opt{snapshot.AsynchronousRemove}
if config.AllowInvalidMountsOnRestart {
snOpts = append(snOpts, snapshot.AllowInvalidMountsOnRestart)
}
snapshotter, err = snapshot.NewSnapshotter(ctx, snapshotterRoot(root), fs, snOpts...)
if err != nil {
return nil, fmt.Errorf("failed to create new snapshotter: %w", err)
}
return snapshotter, nil
}
func NewFileSystem(ctx context.Context, root string, config *Config, opts ...Option) (snapshot.FileSystem, error) {
var sOpts options var sOpts options
for _, o := range opts { for _, o := range opts {
o(&sOpts) o(&sOpts)
@ -97,22 +119,10 @@ func NewStargzSnapshotterService(ctx context.Context, root string, config *Confi
) )
fs, err := stargzfs.NewFilesystem(fsRoot(root), config.Config, fsOpts...) fs, err := stargzfs.NewFilesystem(fsRoot(root), config.Config, fsOpts...)
if err != nil { if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to configure filesystem") return nil, err
} }
var snapshotter snapshots.Snapshotter return fs, nil
snOpts := []snbase.Opt{snbase.AsynchronousRemove}
if config.SnapshotterConfig.AllowInvalidMountsOnRestart {
snOpts = append(snOpts, snbase.AllowInvalidMountsOnRestart)
}
snapshotter, err = snbase.NewSnapshotter(ctx, snapshotterRoot(root), fs, snOpts...)
if err != nil {
log.G(ctx).WithError(err).Fatalf("failed to create new snapshotter")
}
return snapshotter, err
} }
func snapshotterRoot(root string) string { func snapshotterRoot(root string) string {
@ -125,14 +135,15 @@ func fsRoot(root string) string {
func sources(ps ...source.GetSources) source.GetSources { func sources(ps ...source.GetSources) source.GetSources {
return func(labels map[string]string) (source []source.Source, allErr error) { return func(labels map[string]string) (source []source.Source, allErr error) {
var errs []error
for _, p := range ps { for _, p := range ps {
src, err := p(labels) src, err := p(labels)
if err == nil { if err == nil {
return src, nil return src, nil
} }
allErr = multierror.Append(allErr, err) errs = append(errs, err)
} }
return return nil, errors.Join(errs...)
} }
} }

View File

@ -115,7 +115,7 @@ type snapshotter struct {
// the root as same as overlayfs snapshotter. // the root as same as overlayfs snapshotter.
func NewSnapshotter(ctx context.Context, root string, targetFs FileSystem, opts ...Opt) (snapshots.Snapshotter, error) { func NewSnapshotter(ctx context.Context, root string, targetFs FileSystem, opts ...Opt) (snapshots.Snapshotter, error) {
if targetFs == nil { if targetFs == nil {
return nil, fmt.Errorf("Specify filesystem to use") return nil, fmt.Errorf("specify filesystem to use")
} }
var config SnapshotterConfig var config SnapshotterConfig
@ -658,6 +658,7 @@ func (o *snapshotter) Close() error {
if err := o.cleanup(ctx, cleanupCommitted); err != nil { if err := o.cleanup(ctx, cleanupCommitted); err != nil {
log.G(ctx).WithError(err).Warn("failed to cleanup") log.G(ctx).WithError(err).Warn("failed to cleanup")
} }
return o.ms.Close() return o.ms.Close()
} }
@ -722,6 +723,10 @@ func (o *snapshotter) checkAvailability(ctx context.Context, key string) bool {
} }
func (o *snapshotter) restoreRemoteSnapshot(ctx context.Context) error { func (o *snapshotter) restoreRemoteSnapshot(ctx context.Context) error {
if o.noRestore {
return nil
}
mounts, err := mountinfo.GetMounts(nil) mounts, err := mountinfo.GetMounts(nil)
if err != nil { if err != nil {
return err return err
@ -734,10 +739,6 @@ func (o *snapshotter) restoreRemoteSnapshot(ctx context.Context) error {
} }
} }
if o.noRestore {
return nil
}
var task []snapshots.Info var task []snapshots.Info
if err := o.Walk(ctx, func(ctx context.Context, info snapshots.Info) error { if err := o.Walk(ctx, func(ctx context.Context, info snapshots.Info) error {
if _, ok := info.Labels[remoteLabel]; ok { if _, ok := info.Labels[remoteLabel]; ok {
@ -748,6 +749,27 @@ func (o *snapshotter) restoreRemoteSnapshot(ctx context.Context) error {
return err return err
} }
for _, info := range task { for _, info := range task {
// First, prepare the snapshot directory
if err := func() error {
ctx, t, err := o.ms.TransactionContext(ctx, false)
if err != nil {
return err
}
defer t.Rollback()
id, _, _, err := storage.GetInfo(ctx, info.Name)
if err != nil {
return err
}
if err := os.Mkdir(filepath.Join(o.root, "snapshots", id), 0700); err != nil && !os.IsExist(err) {
return err
}
if err := os.Mkdir(o.upperPath(id), 0755); err != nil && !os.IsExist(err) {
return err
}
return nil
}(); err != nil {
return fmt.Errorf("failed to create remote snapshot directory: %s: %w", info.Name, err)
}
if err := o.prepareRemoteSnapshot(ctx, info.Name, info.Labels); err != nil { if err := o.prepareRemoteSnapshot(ctx, info.Name, info.Labels); err != nil {
if o.allowInvalidMountsOnRestart { if o.allowInvalidMountsOnRestart {
log.G(ctx).WithError(err).Warnf("failed to restore remote snapshot %s; remove this snapshot manually", info.Name) log.G(ctx).WithError(err).Warnf("failed to restore remote snapshot %s; remove this snapshot manually", info.Name)

View File

@ -56,7 +56,7 @@ const (
) )
func Mount(ctx context.Context, mountpoint string, layerManager *LayerManager, debug bool) error { func Mount(ctx context.Context, mountpoint string, layerManager *LayerManager, debug bool) error {
timeSec := time.Second t := time.Second
rawFS := fusefs.NewNodeFS(&rootnode{ rawFS := fusefs.NewNodeFS(&rootnode{
fs: &fs{ fs: &fs{
layerManager: layerManager, layerManager: layerManager,
@ -64,8 +64,8 @@ func Mount(ctx context.Context, mountpoint string, layerManager *LayerManager, d
layerMap: new(idMap), layerMap: new(idMap),
}, },
}, &fusefs.Options{ }, &fusefs.Options{
AttrTimeout: &timeSec, AttrTimeout: &t,
EntryTimeout: &timeSec, EntryTimeout: &t,
NullPermissions: true, NullPermissions: true,
}) })
mountOpts := &fuse.MountOptions{ mountOpts := &fuse.MountOptions{
@ -135,7 +135,7 @@ func (n *rootnode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
log.G(ctx).Warn("rootnode.Lookup: uknown node type detected") log.G(ctx).Warn("rootnode.Lookup: uknown node type detected")
return nil, syscall.EIO return nil, syscall.EIO
} }
out.Attr.Ino = cn.StableAttr().Ino out.Ino = cn.StableAttr().Ino
return cn, 0 return cn, 0
} }
switch name { switch name {
@ -145,7 +145,7 @@ func (n *rootnode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
cn := &MemSymlinkOnForget{fusefs.MemSymlink{Data: []byte(n.fs.layerManager.refPool.root())}, n.fs, fattr} cn := &MemSymlinkOnForget{fusefs.MemSymlink{Data: []byte(n.fs.layerManager.refPool.root())}, n.fs, fattr}
copyAttr(cn.attr, &out.Attr) copyAttr(cn.attr, &out.Attr)
return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder { return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder {
out.Attr.Ino = uint64(ino) out.Ino = uint64(ino)
cn.attr.Ino = uint64(ino) cn.attr.Ino = uint64(ino)
sAttr.Ino = uint64(ino) sAttr.Ino = uint64(ino)
fattr.Ino = uint64(ino) fattr.Ino = uint64(ino)
@ -170,7 +170,7 @@ func (n *rootnode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
} }
copyAttr(&cn.attr, &out.Attr) copyAttr(&cn.attr, &out.Attr)
return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder { return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder {
out.Attr.Ino = uint64(ino) out.Ino = uint64(ino)
cn.attr.Ino = uint64(ino) cn.attr.Ino = uint64(ino)
sAttr.Ino = uint64(ino) sAttr.Ino = uint64(ino)
return n.NewPersistentInode(ctx, cn, sAttr) return n.NewPersistentInode(ctx, cn, sAttr)
@ -207,7 +207,7 @@ func (n *refnode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (
log.G(ctx).Warn("refnode.Lookup: uknown node type detected") log.G(ctx).Warn("refnode.Lookup: uknown node type detected")
return nil, syscall.EIO return nil, syscall.EIO
} }
out.Attr.Ino = cn.StableAttr().Ino out.Ino = cn.StableAttr().Ino
return cn, 0 return cn, 0
} }
targetDigest, err := digest.Parse(name) targetDigest, err := digest.Parse(name)
@ -223,7 +223,7 @@ func (n *refnode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (
} }
copyAttr(&cn.attr, &out.Attr) copyAttr(&cn.attr, &out.Attr)
return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder { return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder {
out.Attr.Ino = uint64(ino) out.Ino = uint64(ino)
cn.attr.Ino = uint64(ino) cn.attr.Ino = uint64(ino)
sAttr.Ino = uint64(ino) sAttr.Ino = uint64(ino)
return n.NewPersistentInode(ctx, cn, sAttr) return n.NewPersistentInode(ctx, cn, sAttr)
@ -321,7 +321,7 @@ func (n *layernode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
log.G(ctx).Warn("layernode.Lookup: uknown node type detected") log.G(ctx).Warn("layernode.Lookup: uknown node type detected")
return nil, syscall.EIO return nil, syscall.EIO
} }
out.Attr.Ino = cn.StableAttr().Ino out.Ino = cn.StableAttr().Ino
return cn, 0 return cn, 0
} }
switch name { switch name {
@ -342,7 +342,7 @@ func (n *layernode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
cn := &MemRegularFileOnForget{fusefs.MemRegularFile{Data: infoData}, n.fs, &fattr} cn := &MemRegularFileOnForget{fusefs.MemRegularFile{Data: infoData}, n.fs, &fattr}
copyAttr(cn.attr, &out.Attr) copyAttr(cn.attr, &out.Attr)
return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder { return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder {
out.Attr.Ino = uint64(ino) out.Ino = uint64(ino)
cn.attr.Ino = uint64(ino) cn.attr.Ino = uint64(ino)
sAttr.Ino = uint64(ino) sAttr.Ino = uint64(ino)
fattr.Ino = uint64(ino) fattr.Ino = uint64(ino)
@ -381,7 +381,7 @@ func (n *layernode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
cn := &blobnode{l: l, fs: n.fs} cn := &blobnode{l: l, fs: n.fs}
copyAttr(&cn.attr, &out.Attr) copyAttr(&cn.attr, &out.Attr)
return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder { return n.fs.newInodeWithID(ctx, func(ino uint32) fusefs.InodeEmbedder {
out.Attr.Ino = uint64(ino) out.Ino = uint64(ino)
cn.attr.Ino = uint64(ino) cn.attr.Ino = uint64(ino)
sAttr.Ino = uint64(ino) sAttr.Ino = uint64(ino)
return n.NewPersistentInode(ctx, cn, sAttr) return n.NewPersistentInode(ctx, cn, sAttr)
@ -408,8 +408,8 @@ func (n *layernode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
copyAttr(&out.Attr, &ao.Attr) copyAttr(&out.Attr, &ao.Attr)
cn = n.NewPersistentInode(ctx, root, fusefs.StableAttr{ cn = n.NewPersistentInode(ctx, root, fusefs.StableAttr{
Mode: out.Attr.Mode, Mode: out.Mode,
Ino: out.Attr.Ino, Ino: out.Ino,
}) })
return nil return nil
}() }()

View File

@ -100,10 +100,7 @@ func (ts *BackgroundTaskManager) DonePrioritizedTask() {
func (ts *BackgroundTaskManager) InvokeBackgroundTask(do func(context.Context), timeout time.Duration) { func (ts *BackgroundTaskManager) InvokeBackgroundTask(do func(context.Context), timeout time.Duration) {
for { for {
// Wait until all prioritized tasks are done // Wait until all prioritized tasks are done
for { for atomic.LoadInt64(&ts.prioritizedTasks) > 0 {
if atomic.LoadInt64(&ts.prioritizedTasks) <= 0 {
break
}
// waits until a prioritized task is done // waits until a prioritized task is done
ts.prioritizedTaskDoneCond.L.Lock() ts.prioritizedTaskDoneCond.L.Lock()

View File

@ -44,7 +44,7 @@ func NewTTLCache(ttl time.Duration) *TTLCache {
// Get retrieves the specified object from the cache and increments the reference counter of the // Get retrieves the specified object from the cache and increments the reference counter of the
// target content. Client must call `done` callback to decrease the reference count when the value // target content. Client must call `done` callback to decrease the reference count when the value
// will no longer be used. // will no longer be used.
func (c *TTLCache) Get(key string) (value interface{}, done func(), ok bool) { func (c *TTLCache) Get(key string) (value interface{}, done func(bool), ok bool) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
rc, ok := c.m[key] rc, ok := c.m[key]
@ -59,7 +59,7 @@ func (c *TTLCache) Get(key string) (value interface{}, done func(), ok bool) {
// If the specified content already exists in the cache, this sets `added` to false and returns // If the specified content already exists in the cache, this sets `added` to false and returns
// "already cached" content (i.e. doesn't replace the content with the new one). Client must call // "already cached" content (i.e. doesn't replace the content with the new one). Client must call
// `done` callback to decrease the counter when the value will no longer be used. // `done` callback to decrease the counter when the value will no longer be used.
func (c *TTLCache) Add(key string, value interface{}) (cachedValue interface{}, done func(), added bool) { func (c *TTLCache) Add(key string, value interface{}) (cachedValue interface{}, done func(bool), added bool) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
if rc, ok := c.m[key]; ok { if rc, ok := c.m[key]; ok {
@ -100,12 +100,20 @@ func (c *TTLCache) evictLocked(key string) {
} }
} }
func (c *TTLCache) decreaseOnceFunc(rc *refCounterWithTimer) func() { func (c *TTLCache) decreaseOnceFunc(rc *refCounterWithTimer) func(bool) {
var once sync.Once var once sync.Once
return func() { return func(evict bool) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
once.Do(func() { rc.dec() }) once.Do(func() { rc.dec() })
if evict {
rc.t.Stop()
rc.finalize()
key := rc.key
if cachedRc, ok := c.m[key]; ok && cachedRc == rc {
delete(c.m, key)
}
}
} }
} }

View File

@ -78,12 +78,12 @@ func TestTTLRemove(t *testing.T) {
t.Fatalf("no content must be evicted after remove") t.Fatalf("no content must be evicted after remove")
} }
done1() done1(false)
if len(evicted) != 0 { if len(evicted) != 0 {
t.Fatalf("no content must be evicted until all reference are discarded") t.Fatalf("no content must be evicted until all reference are discarded")
} }
done12() done12(false)
if len(evicted) != 1 { if len(evicted) != 1 {
t.Fatalf("content must be evicted") t.Fatalf("content must be evicted")
} }
@ -101,7 +101,7 @@ func TestTTLRemoveOverwritten(t *testing.T) {
} }
key1, value1 := "key1", "abcd1" key1, value1 := "key1", "abcd1"
_, done1, _ := c.Add(key1, value1) _, done1, _ := c.Add(key1, value1)
done1() done1(false)
c.Remove(key1) // remove key1 as soon as possible c.Remove(key1) // remove key1 as soon as possible
// add another content with a new key // add another content with a new key
@ -120,8 +120,8 @@ func TestTTLRemoveOverwritten(t *testing.T) {
} }
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
done122() done122(false)
done12() done12(false)
// spent 4 sec since the new key1 was added. This should be expierd. // spent 4 sec since the new key1 was added. This should be expierd.
if _, _, ok := c.Get(key1); ok { if _, _, ok := c.Get(key1); ok {
t.Fatalf("%q must be expierd but remaining", key1) t.Fatalf("%q must be expierd but remaining", key1)
@ -143,7 +143,7 @@ func TestTTLEviction(t *testing.T) {
key1, value1 := "key1", "abcd1" key1, value1 := "key1", "abcd1"
key2, value2 := "key2", "abcd2" key2, value2 := "key2", "abcd2"
_, done1, _ := c.Add(key1, value1) _, done1, _ := c.Add(key1, value1)
done1() // evict key1 on expiering ttl done1(false) // evict key1 on expiering ttl
_, done2, _ := c.Add(key2, value2) _, done2, _ := c.Add(key2, value2)
_, done22, _ := c.Get(key2) // hold reference of key2 to prevent eviction _, done22, _ := c.Get(key2) // hold reference of key2 to prevent eviction
time.Sleep(3 * time.Second) // wait until elements reach ttl time.Sleep(3 * time.Second) // wait until elements reach ttl
@ -157,16 +157,16 @@ func TestTTLEviction(t *testing.T) {
} }
evictedMu.Unlock() evictedMu.Unlock()
done2() // effective done2(false) // effective
done2() // ignored done2(false) // ignored
done2() // ignored done2(false) // ignored
evictedMu.Lock() evictedMu.Lock()
if len(evicted) != 1 { if len(evicted) != 1 {
t.Fatalf("only 1 content must be evicted") t.Fatalf("only 1 content must be evicted")
} }
evictedMu.Unlock() evictedMu.Unlock()
done22() done22(false)
evictedMu.Lock() evictedMu.Lock()
if len(evicted) != 2 { if len(evicted) != 2 {
t.Fatalf("2 contents must be evicted") t.Fatalf("2 contents must be evicted")
@ -176,3 +176,29 @@ func TestTTLEviction(t *testing.T) {
} }
evictedMu.Unlock() evictedMu.Unlock()
} }
// TestTTLQuickDone tests the case where "done" with the explicit evict
// is called before TTL
func TestTTLQuickDone(t *testing.T) {
var evicted []string
c := NewTTLCache(time.Hour)
c.OnEvicted = func(key string, value interface{}) {
evicted = append(evicted, key)
}
key1, value1 := "key1", "abcd1"
_, done1, _ := c.Add(key1, value1)
_, done12, _ := c.Get(key1)
done1(false)
if len(evicted) != 0 {
t.Fatalf("no content must be evicted until all reference are discarded")
}
done12(true)
if len(evicted) != 1 {
t.Fatalf("content must be evicted on an explicit evict before TTL")
}
if evicted[0] != key1 {
t.Fatalf("1st content %q must be evicted but got %q", key1, evicted[0])
}
}

View File

@ -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
} }