mirror of
https://git.vectorsigma.ru/public/k3s.git
synced 2026-07-28 21:49:29 +00:00
Build standalone containerd
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
committed by
Brad Davidson
parent
8737e2e13f
commit
6f4217a340
@@ -182,13 +182,13 @@ func getAssetAndDir(dataDir string) (string, string) {
|
||||
func extract(dataDir string) (string, error) {
|
||||
// first look for global asset folder so we don't create a HOME version if not needed
|
||||
_, dir := getAssetAndDir(datadir.DefaultDataDir)
|
||||
if _, err := os.Stat(filepath.Join(dir, "bin", "containerd")); err == nil {
|
||||
if _, err := os.Stat(filepath.Join(dir, "bin", "k3s")); err == nil {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
asset, dir := getAssetAndDir(dataDir)
|
||||
// check if target content already exists
|
||||
if _, err := os.Stat(filepath.Join(dir, "bin", "containerd")); err == nil {
|
||||
if _, err := os.Stat(filepath.Join(dir, "bin", "k3s")); err == nil {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
|
||||
26
go.mod
26
go.mod
@@ -5,17 +5,7 @@ go 1.16
|
||||
replace (
|
||||
github.com/Microsoft/hcsshim => github.com/Microsoft/hcsshim v0.8.20
|
||||
github.com/benmoss/go-powershell => github.com/k3s-io/go-powershell v0.0.0-20201118222746-51f4c451fbd7
|
||||
github.com/containerd/aufs => github.com/containerd/aufs v1.0.0
|
||||
github.com/containerd/btrfs => github.com/containerd/btrfs v1.0.0
|
||||
github.com/containerd/cgroups => github.com/containerd/cgroups v1.0.1
|
||||
github.com/containerd/console => github.com/containerd/console v1.0.2
|
||||
github.com/containerd/containerd => github.com/k3s-io/containerd v1.5.8-k3s1 // k3s-release/1.5
|
||||
github.com/containerd/continuity => github.com/k3s-io/continuity v0.0.0-20210309170710-f93269e0d5c1
|
||||
github.com/containerd/fifo => github.com/containerd/fifo v1.0.0
|
||||
github.com/containerd/go-runc => github.com/containerd/go-runc v1.0.0
|
||||
github.com/containerd/ttrpc => github.com/containerd/ttrpc v1.0.2
|
||||
github.com/containerd/typeurl => github.com/containerd/typeurl v1.0.2
|
||||
github.com/containerd/zfs => github.com/containerd/zfs v1.0.0
|
||||
github.com/containerd/containerd => github.com/k3s-io/containerd v1.5.8-k3s2 // k3s-release/1.5
|
||||
github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||
github.com/docker/distribution => github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/docker => github.com/docker/docker v20.10.2+incompatible
|
||||
@@ -25,7 +15,6 @@ replace (
|
||||
github.com/juju/errors => github.com/k3s-io/nocode v0.0.0-20200630202308-cb097102c09f
|
||||
github.com/kubernetes-sigs/cri-tools => github.com/k3s-io/cri-tools v1.21.0-k3s1
|
||||
github.com/matryer/moq => github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009
|
||||
// LOOK TO scripts/download FOR THE VERSION OF runc THAT WE ARE BUILDING/SHIPPING
|
||||
github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.3
|
||||
github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210316141917-a8c4a9ee0f6b
|
||||
github.com/rancher/k3s/pkg/data => ./pkg/data
|
||||
@@ -77,9 +66,9 @@ replace (
|
||||
require (
|
||||
github.com/Microsoft/hcsshim v0.8.23
|
||||
github.com/containerd/cgroups v1.0.1
|
||||
github.com/containerd/containerd v1.5.8
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.3
|
||||
github.com/containerd/stargz-snapshotter v0.8.0
|
||||
github.com/containerd/containerd v1.6.0-beta.2.0.20211117185425-a776a27af54a
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.4
|
||||
github.com/containerd/stargz-snapshotter v0.10.1
|
||||
github.com/coreos/go-iptables v0.5.0
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
|
||||
github.com/docker/docker v20.10.10+incompatible
|
||||
@@ -102,7 +91,6 @@ require (
|
||||
github.com/natefinch/lumberjack v2.0.0+incompatible
|
||||
github.com/onsi/ginkgo v1.16.4
|
||||
github.com/onsi/gomega v1.11.0
|
||||
// LOOK TO scripts/download FOR THE VERSION OF runc THAT WE ARE BUILDING/SHIPPING
|
||||
github.com/opencontainers/runc v1.0.3
|
||||
github.com/opencontainers/selinux v1.8.2
|
||||
github.com/otiai10/copy v1.6.0
|
||||
@@ -125,8 +113,8 @@ require (
|
||||
go.etcd.io/etcd/server/v3 v3.5.0
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||
golang.org/x/net v0.0.0-20211005215030-d2e5035098b3
|
||||
golang.org/x/sys v0.0.0-20211004093028-2c5d950f24ef
|
||||
google.golang.org/grpc v1.41.0
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
|
||||
google.golang.org/grpc v1.42.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
inet.af/tcpproxy v0.0.0-20200125044825-b6bb9b5b8252
|
||||
k8s.io/api v0.22.4
|
||||
@@ -136,7 +124,7 @@ require (
|
||||
k8s.io/cloud-provider v0.22.4
|
||||
k8s.io/component-base v0.22.4
|
||||
k8s.io/controller-manager v0.22.4 // indirect
|
||||
k8s.io/cri-api v0.22.4
|
||||
k8s.io/cri-api v0.23.0-alpha.4
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/klog/v2 v2.9.0
|
||||
k8s.io/kubectl v0.22.4
|
||||
|
||||
59
go.sum
59
go.sum
@@ -1,4 +1,5 @@
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
|
||||
bitbucket.org/bertimus9/systemstat v0.0.0-20180207000608-0eeff89b0690/go.mod h1:Ulb78X89vxKYgdL24HMTiXYHlyHEvruOj1ZPlqeNEZM=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
@@ -181,12 +182,18 @@ github.com/containerd/btrfs v1.0.0 h1:osn1exbzdub9L5SouXO5swW4ea/xVdJZ3wokxN5Grn
|
||||
github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss=
|
||||
github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
|
||||
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
||||
github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=
|
||||
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
||||
github.com/containerd/continuity v0.2.1 h1:/EeEo2EtN3umhbbgCveyjifoMYg0pS+nMMEemaYw634=
|
||||
github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg=
|
||||
github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU=
|
||||
github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.3 h1:eKLaaYhywg13uXYP7d1gH95b3w6SdQFuu0wxpzzhroc=
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.3/go.mod h1:qRtosYylg3OWvie15wMmyaOh/n5+BCW59J0tMH5R+F0=
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.4 h1:UKlk0rhAq1NW5UEmu9/4f3m9v+O/0+F0as+QeK1UmCM=
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.4/go.mod h1:UPFCs/OiJHa4MoghjGZdPaOBcZEhATfYG1gSutAZTvE=
|
||||
github.com/containerd/go-cni v1.0.2 h1:YbJAhpTevL2v6u8JC1NhCYRwf+3Vzxcc5vGnYoJ7VeE=
|
||||
github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
|
||||
github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0=
|
||||
@@ -195,13 +202,15 @@ github.com/containerd/imgcrypt v1.1.1 h1:LBwiTfoUsdiEGAR1TpvxE+Gzt7469oVu87iR3mv
|
||||
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
||||
github.com/containerd/nri v0.1.0 h1:6QioHRlThlKh2RkRTR4kIT3PKAcrLo3gIWnjkM4dQmQ=
|
||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||
github.com/containerd/stargz-snapshotter v0.8.0 h1:dpcv7te4ef8dNQMgN6zzbd4IP1puSFIXqFbqZlKFvd4=
|
||||
github.com/containerd/stargz-snapshotter v0.8.0/go.mod h1:1BffdxelEfp8ct4oI7uy2mfmvMDE2o3SPe32AtFyYXk=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.8.0/go.mod h1:mwIwuwb+D8FX2t45Trwi0hmWmZm5VW7zPP/rekwhWQU=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.9.0 h1:PkB6BSTfOKX23erT2GkoUKkJEcXfNcyKskIViK770v8=
|
||||
github.com/containerd/stargz-snapshotter v0.10.1 h1:A4nCRPWZmlYGpPNTmmktREqca1WM2IevonzQcIjCZwM=
|
||||
github.com/containerd/stargz-snapshotter v0.10.1/go.mod h1:F/5gQZTyx18Kj+4VnE4Kcwg7BtESs7L/V29jamTI43k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.9.0/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
|
||||
github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9U=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
|
||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||
github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI=
|
||||
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
||||
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
|
||||
github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY=
|
||||
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
|
||||
github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
|
||||
@@ -260,9 +269,9 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
|
||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/cli v20.10.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v20.10.9+incompatible h1:OJ7YkwQA+k2Oi51lmCojpjiygKpi76P7bg91b2eJxYU=
|
||||
github.com/docker/cli v20.10.9+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v20.10.10+incompatible h1:kcbwdgWbrBOH8QwQzaJmyriHwF7XIl4HT1qh0HTRys4=
|
||||
github.com/docker/cli v20.10.10+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v20.10.2+incompatible h1:vFgEHPqWBTp4pTjdLwjAA4bSo3gvIGOYwuJTlEjVBCw=
|
||||
@@ -397,6 +406,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/goccy/go-json v0.7.10 h1:ulhbuNe1JqE68nMRXXTJRrUu0uhouf0VevLINxQq4Ec=
|
||||
github.com/goccy/go-json v0.7.10/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c h1:RBUpb2b14UnmRHNd2uHz20ZHLDK+SW5Us/vWF5IHRaY=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@@ -522,20 +533,23 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hanwen/go-fuse v1.0.0 h1:GxS9Zrn6c35/BnfiVsZVWmsG803xwE7eVRDvcf/BEVc=
|
||||
github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok=
|
||||
github.com/hanwen/go-fuse/v2 v2.1.0 h1:+32ffteETaLYClUj0a3aHjZ1hOPxxaNEHiZiujuDaek=
|
||||
github.com/hanwen/go-fuse/v2 v2.1.0/go.mod h1:oRyA5eK+pvJyv5otpO/DgccS8y/RvYMaO00GgRLGryc=
|
||||
github.com/hanwen/go-fuse/v2 v2.1.1-0.20210825171523-3ab5d95a30ae h1:4CB6T4YTUVvnro5ba8ju1QCbOuyGAeF3vvKlo50EJ4k=
|
||||
github.com/hanwen/go-fuse/v2 v2.1.1-0.20210825171523-3ab5d95a30ae/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
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/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
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-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
@@ -593,10 +607,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/k3s-io/containerd v1.5.8-k3s1 h1:1w0neoAPwO9Dounkdgi2GMCJc48iKcXgxu1vN0YUigQ=
|
||||
github.com/k3s-io/containerd v1.5.8-k3s1/go.mod h1:DltFRoJAo5exp9diH/w/hyg8ZGej9AJ61qVi4ZQqShc=
|
||||
github.com/k3s-io/continuity v0.0.0-20210309170710-f93269e0d5c1 h1:KEz2rd9IDbrQT8w6RibEYlwfTXiu0P6hQDE+6O4IJdI=
|
||||
github.com/k3s-io/continuity v0.0.0-20210309170710-f93269e0d5c1/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||
github.com/k3s-io/containerd v1.5.8-k3s2 h1:zqiSObegytSfZnkY6ZO0NZJDT27zNNwuwxoszGvWw5s=
|
||||
github.com/k3s-io/containerd v1.5.8-k3s2/go.mod h1:mPi6aT1rbxG3ilLkj0fmZDn9VpSW/PUR615wfPqRCqc=
|
||||
github.com/k3s-io/cri-tools v1.21.0-k3s1 h1:MWQtAsx4HCNXenqU/B4V9eU6HMyafkd1PnW6d4HCfos=
|
||||
github.com/k3s-io/cri-tools v1.21.0-k3s1/go.mod h1:Qsz54zxINPR+WVWX9Kc3CTmuDFB1dNLCNV8jE8lUbtU=
|
||||
github.com/k3s-io/etcd/api/v3 v3.5.0-k3s2 h1:56a/c/Mo75uU1k3erdgWk1C7dGUL5rSpNdL2B6zftKo=
|
||||
@@ -672,8 +684,6 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
@@ -769,8 +779,9 @@ 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/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM=
|
||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
|
||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||
github.com/moby/sys/symlink v0.1.0 h1:MTFZ74KtNI6qQQpuBxU+uKCim4WtOMokr03hCfJcazE=
|
||||
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
|
||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
@@ -857,9 +868,9 @@ github.com/paulmach/orb v0.1.3/go.mod h1:VFlX/8C+IQ1p6FTRRKzKoOPJnvEtA5G0Veuqwbu
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A=
|
||||
@@ -1016,6 +1027,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||
github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY=
|
||||
github.com/ugorji/go v0.0.0-20170107133203-ded73eae5db7/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
@@ -1423,7 +1435,6 @@ k8s.io/system-validators v1.5.0/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6g
|
||||
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
|
||||
|
||||
@@ -4,9 +4,6 @@ COPY build/out/data.tar.zst /
|
||||
RUN mkdir -p /image/etc/ssl/certs /image/run /image/var/run /image/tmp /image/lib/modules /image/lib/firmware && \
|
||||
tar -xa -C /image -f /data.tar.zst && \
|
||||
cp /etc/ssl/certs/ca-certificates.crt /image/etc/ssl/certs/ca-certificates.crt
|
||||
RUN cd image/bin && \
|
||||
rm -f k3s && \
|
||||
ln -s k3s-server k3s
|
||||
|
||||
FROM scratch
|
||||
ARG VERSION="dev"
|
||||
|
||||
@@ -22,9 +22,9 @@ import (
|
||||
_ "github.com/containerd/containerd/metrics/cgroups"
|
||||
_ "github.com/containerd/containerd/runtime/v2"
|
||||
_ "github.com/containerd/containerd/runtime/v2/runc/options"
|
||||
_ "github.com/containerd/containerd/snapshots/btrfs/plugin"
|
||||
_ "github.com/containerd/containerd/snapshots/native/plugin"
|
||||
_ "github.com/containerd/containerd/snapshots/overlay/plugin"
|
||||
_ "github.com/containerd/containerd/snapshots/btrfs/plugin"
|
||||
_ "github.com/containerd/fuse-overlayfs-snapshotter/plugin"
|
||||
_ "github.com/containerd/stargz-snapshotter/service/plugin"
|
||||
)
|
||||
|
||||
@@ -8,7 +8,10 @@ fi
|
||||
|
||||
. ./scripts/version.sh
|
||||
|
||||
MAX_BINARY_SIZE=61000000
|
||||
# Try to keep the K3s binary under 64 megabytes.
|
||||
# "64M ought to be enough for anybody"
|
||||
MAX_BINARY_MB=64
|
||||
MAX_BINARY_SIZE=$((MAX_BINARY_MB * 1024 * 1024))
|
||||
BIN_SUFFIX="-${ARCH}"
|
||||
if [ ${ARCH} = amd64 ]; then
|
||||
BIN_SUFFIX=""
|
||||
@@ -20,9 +23,9 @@ CMD_NAME="dist/artifacts/k3s${BIN_SUFFIX}"
|
||||
SIZE=$(stat -c '%s' ${CMD_NAME})
|
||||
|
||||
if [ ${SIZE} -gt ${MAX_BINARY_SIZE} ]; then
|
||||
echo "k3s binary ${CMD_NAME} size ${SIZE} exceeds max acceptable size of ${MAX_BINARY_SIZE} bytes"
|
||||
exit 1
|
||||
echo "k3s binary ${CMD_NAME} size ${SIZE} exceeds max acceptable size of ${MAX_BINARY_SIZE} bytes (${MAX_BINARY_MB} MiB)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "k3s binary ${CMD_NAME} size ${SIZE} is less than max acceptable size of ${MAX_BINARY_SIZE} bytes"
|
||||
echo "k3s binary ${CMD_NAME} size ${SIZE} is less than max acceptable size of ${MAX_BINARY_SIZE} bytes (${MAX_BINARY_MB} MiB)"
|
||||
exit 0
|
||||
|
||||
@@ -10,7 +10,7 @@ GO=${GO-go}
|
||||
PKG="github.com/rancher/k3s"
|
||||
PKG_CONTAINERD="github.com/containerd/containerd"
|
||||
PKG_K3S_CONTAINERD="github.com/k3s-io/containerd"
|
||||
PKG_CRICTL="github.com/kubernetes-sigs/cri-tools"
|
||||
PKG_CRICTL="github.com/kubernetes-sigs/cri-tools/pkg"
|
||||
PKG_K8S_BASE="k8s.io/component-base"
|
||||
PKG_K8S_CLIENT="k8s.io/client-go/pkg"
|
||||
|
||||
@@ -35,7 +35,9 @@ VERSIONFLAGS="
|
||||
|
||||
-X ${VENDOR_PREFIX}${PKG_CONTAINERD}/version.Version=${VERSION_CONTAINERD}
|
||||
-X ${VENDOR_PREFIX}${PKG_CONTAINERD}/version.Package=${PKG_K3S_CONTAINERD}
|
||||
-X ${VENDOR_PREFIX}${PKG_CRICTL}/pkg/version.Version=${VERSION_CRICTL}
|
||||
|
||||
-X ${PKG_CONTAINERD}/version.Version=${VERSION_CONTAINERD}
|
||||
-X ${PKG_CONTAINERD}/version.Package=${PKG_K3S_CONTAINERD}
|
||||
"
|
||||
LDFLAGS="
|
||||
-w -s"
|
||||
@@ -43,7 +45,7 @@ LDFLAGS="
|
||||
STATIC="
|
||||
-extldflags '-static -lm -ldl -lz -lpthread'
|
||||
"
|
||||
TAGS="ctrd apparmor seccomp netcgo osusergo providerless"
|
||||
TAGS="apparmor seccomp netcgo osusergo providerless"
|
||||
RUNC_TAGS="apparmor seccomp"
|
||||
RUNC_STATIC="static"
|
||||
|
||||
@@ -101,22 +103,29 @@ if [ ! -x ${INSTALLBIN}/cni ]; then
|
||||
fi
|
||||
|
||||
echo Building k3s
|
||||
CGO_ENABLED=1 "${GO}" build -tags "$TAGS" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/containerd ./cmd/server/main.go
|
||||
ln -s containerd ./bin/k3s-agent
|
||||
ln -s containerd ./bin/k3s-server
|
||||
ln -s containerd ./bin/k3s-etcd-snapshot
|
||||
ln -s containerd ./bin/k3s-secrets-encrypt
|
||||
ln -s containerd ./bin/k3s-certificate
|
||||
ln -s containerd ./bin/kubectl
|
||||
ln -s containerd ./bin/crictl
|
||||
ln -s containerd ./bin/ctr
|
||||
CGO_ENABLED=1 "${GO}" build -tags "$TAGS" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/k3s ./cmd/server/main.go
|
||||
ln -s k3s ./bin/k3s-agent
|
||||
ln -s k3s ./bin/k3s-server
|
||||
ln -s k3s ./bin/k3s-etcd-snapshot
|
||||
ln -s k3s ./bin/k3s-secrets-encrypt
|
||||
ln -s k3s ./bin/k3s-certificate
|
||||
ln -s k3s ./bin/kubectl
|
||||
ln -s k3s ./bin/crictl
|
||||
ln -s k3s ./bin/ctr
|
||||
|
||||
export GOPATH=$(pwd)/build
|
||||
|
||||
echo Building containerd
|
||||
pushd ./build/src/github.com/containerd/containerd
|
||||
TAGS="${TAGS/netcgo/netgo}"
|
||||
CGO_ENABLED=1 "${GO}" build -tags "$TAGS" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/containerd ./cmd/containerd
|
||||
CGO_ENABLED=1 "${GO}" build -tags "$TAGS" -ldflags "$VERSIONFLAGS $LDFLAGS $STATIC" -o bin/containerd-shim-runc-v2 ./cmd/containerd-shim-runc-v2
|
||||
popd
|
||||
cp -vf ./build/src/github.com/containerd/containerd/bin/* ./bin/
|
||||
|
||||
echo Building runc
|
||||
rm -f ./build/src/github.com/opencontainers/runc/runc
|
||||
make GOPATH=$(pwd)/build EXTRA_LDFLAGS="-w -s" BUILDTAGS="$RUNC_TAGS" -C ./build/src/github.com/opencontainers/runc $RUNC_STATIC
|
||||
cp -f ./build/src/github.com/opencontainers/runc/runc ./bin/runc
|
||||
|
||||
echo Building containerd-shim-runc-v2
|
||||
rm -f ./vendor/github.com/containerd/containerd/bin/containerd-shim-runc-v2
|
||||
make -C ./vendor/github.com/containerd/containerd bin/containerd-shim-runc-v2
|
||||
cp -f ./vendor/github.com/containerd/containerd/bin/containerd-shim-runc-v2 ./bin/containerd-shim-runc-v2
|
||||
pushd ./build/src/github.com/opencontainers/runc
|
||||
rm -f runc
|
||||
make EXTRA_LDFLAGS="-w -s" BUILDTAGS="$RUNC_TAGS" $RUNC_STATIC
|
||||
popd
|
||||
cp -vf ./build/src/github.com/opencontainers/runc/runc ./bin/
|
||||
|
||||
@@ -13,12 +13,14 @@ TRAEFIK_CRD_FILE=traefik-crd-${TRAEFIK_CHART_VERSION}${TRAEFIK_PACKAGE_VERSION}.
|
||||
TRAEFIK_URL=https://helm.traefik.io/traefik/traefik-${TRAEFIK_CHART_VERSION}.tgz
|
||||
CHARTS_DIR=build/static/charts
|
||||
RUNC_DIR=build/src/github.com/opencontainers/runc
|
||||
CONTAINERD_DIR=build/src/github.com/containerd/containerd
|
||||
DATA_DIR=build/data
|
||||
export TZ=UTC
|
||||
|
||||
umask 022
|
||||
rm -rf ${CHARTS_DIR}
|
||||
rm -rf ${RUNC_DIR}
|
||||
rm -rf ${CONTAINERD_DIR}
|
||||
mkdir -p ${CHARTS_DIR}
|
||||
mkdir -p ${DATA_DIR}
|
||||
|
||||
@@ -26,6 +28,8 @@ curl --compressed -sfL https://github.com/k3s-io/k3s-root/releases/download/${VE
|
||||
|
||||
git clone --single-branch --branch=${VERSION_RUNC} --depth=1 https://github.com/opencontainers/runc ${RUNC_DIR}
|
||||
|
||||
git clone --single-branch --branch=${VERSION_CONTAINERD} --depth=1 https://github.com/k3s-io/containerd ${CONTAINERD_DIR}
|
||||
|
||||
setup_tmp() {
|
||||
TMP_DIR=$(mktemp -d --tmpdir=${CHARTS_DIR})
|
||||
cleanup() {
|
||||
|
||||
@@ -7,9 +7,9 @@ cd $(dirname $0)/..
|
||||
|
||||
GO=${GO-go}
|
||||
|
||||
for i in crictl kubectl k3s-agent k3s-server k3s-etcd-snapshot k3s-secrets-encrypt k3s-certificate k3s ; do
|
||||
for i in crictl kubectl k3s-agent k3s-server k3s-etcd-snapshot k3s-secrets-encrypt k3s-certificate; do
|
||||
rm -f bin/$i
|
||||
ln -s containerd bin/$i
|
||||
ln -s k3s bin/$i
|
||||
done
|
||||
|
||||
for i in bridge flannel host-local loopback portmap; do
|
||||
|
||||
10
vendor/github.com/containerd/console/console_windows.go
generated
vendored
10
vendor/github.com/containerd/console/console_windows.go
generated
vendored
@@ -17,10 +17,10 @@
|
||||
package console
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@@ -103,7 +103,7 @@ func (m *master) Reset() error {
|
||||
{m.err, m.errMode},
|
||||
} {
|
||||
if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
|
||||
return errors.Wrap(err, "unable to restore console mode")
|
||||
return fmt.Errorf("unable to restore console mode: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func (m *master) Size() (WinSize, error) {
|
||||
var info windows.ConsoleScreenBufferInfo
|
||||
err := windows.GetConsoleScreenBufferInfo(m.out, &info)
|
||||
if err != nil {
|
||||
return WinSize{}, errors.Wrap(err, "unable to get console info")
|
||||
return WinSize{}, fmt.Errorf("unable to get console info: %w", err)
|
||||
}
|
||||
|
||||
winsize := WinSize{
|
||||
@@ -139,7 +139,7 @@ func (m *master) DisableEcho() error {
|
||||
mode |= windows.ENABLE_LINE_INPUT
|
||||
|
||||
if err := windows.SetConsoleMode(m.in, mode); err != nil {
|
||||
return errors.Wrap(err, "unable to set console to disable echo")
|
||||
return fmt.Errorf("unable to set console to disable echo: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -192,7 +192,7 @@ func makeInputRaw(fd windows.Handle, mode uint32) error {
|
||||
}
|
||||
|
||||
if err := windows.SetConsoleMode(fd, mode); err != nil {
|
||||
return errors.Wrap(err, "unable to set console to raw mode")
|
||||
return fmt.Errorf("unable to set console to raw mode: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
163
vendor/github.com/containerd/console/console_zos.go
generated
vendored
Normal file
163
vendor/github.com/containerd/console/console_zos.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// +build zos
|
||||
|
||||
/*
|
||||
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 console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// NewPty creates a new pty pair
|
||||
// The master is returned as the first console and a string
|
||||
// with the path to the pty slave is returned as the second
|
||||
func NewPty() (Console, string, error) {
|
||||
var f File
|
||||
var err error
|
||||
var slave string
|
||||
for i := 0;; i++ {
|
||||
ptyp := fmt.Sprintf("/dev/ptyp%04d", i)
|
||||
f, err = os.OpenFile(ptyp, os.O_RDWR, 0600)
|
||||
if err == nil {
|
||||
slave = fmt.Sprintf("/dev/ttyp%04d", i)
|
||||
break
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return nil, "", err
|
||||
}
|
||||
// else probably Resource Busy
|
||||
}
|
||||
m, err := newMaster(f)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return m, slave, nil
|
||||
}
|
||||
|
||||
type master struct {
|
||||
f File
|
||||
original *unix.Termios
|
||||
}
|
||||
|
||||
func (m *master) Read(b []byte) (int, error) {
|
||||
return m.f.Read(b)
|
||||
}
|
||||
|
||||
func (m *master) Write(b []byte) (int, error) {
|
||||
return m.f.Write(b)
|
||||
}
|
||||
|
||||
func (m *master) Close() error {
|
||||
return m.f.Close()
|
||||
}
|
||||
|
||||
func (m *master) Resize(ws WinSize) error {
|
||||
return tcswinsz(m.f.Fd(), ws)
|
||||
}
|
||||
|
||||
func (m *master) ResizeFrom(c Console) error {
|
||||
ws, err := c.Size()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.Resize(ws)
|
||||
}
|
||||
|
||||
func (m *master) Reset() error {
|
||||
if m.original == nil {
|
||||
return nil
|
||||
}
|
||||
return tcset(m.f.Fd(), m.original)
|
||||
}
|
||||
|
||||
func (m *master) getCurrent() (unix.Termios, error) {
|
||||
var termios unix.Termios
|
||||
if err := tcget(m.f.Fd(), &termios); err != nil {
|
||||
return unix.Termios{}, err
|
||||
}
|
||||
return termios, nil
|
||||
}
|
||||
|
||||
func (m *master) SetRaw() error {
|
||||
rawState, err := m.getCurrent()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawState = cfmakeraw(rawState)
|
||||
rawState.Oflag = rawState.Oflag | unix.OPOST
|
||||
return tcset(m.f.Fd(), &rawState)
|
||||
}
|
||||
|
||||
func (m *master) DisableEcho() error {
|
||||
rawState, err := m.getCurrent()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawState.Lflag = rawState.Lflag &^ unix.ECHO
|
||||
return tcset(m.f.Fd(), &rawState)
|
||||
}
|
||||
|
||||
func (m *master) Size() (WinSize, error) {
|
||||
return tcgwinsz(m.f.Fd())
|
||||
}
|
||||
|
||||
func (m *master) Fd() uintptr {
|
||||
return m.f.Fd()
|
||||
}
|
||||
|
||||
func (m *master) Name() string {
|
||||
return m.f.Name()
|
||||
}
|
||||
|
||||
// checkConsole checks if the provided file is a console
|
||||
func checkConsole(f File) error {
|
||||
var termios unix.Termios
|
||||
if tcget(f.Fd(), &termios) != nil {
|
||||
return ErrNotAConsole
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func newMaster(f File) (Console, error) {
|
||||
m := &master{
|
||||
f: f,
|
||||
}
|
||||
t, err := m.getCurrent()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.original = &t
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
|
||||
// created by us acts normally. In particular, a not-very-well-known default of
|
||||
// Linux unix98 ptys is that they have +onlcr by default. While this isn't a
|
||||
// problem for terminal emulators, because we relay data from the terminal we
|
||||
// also relay that funky line discipline.
|
||||
func ClearONLCR(fd uintptr) error {
|
||||
return setONLCR(fd, false)
|
||||
}
|
||||
|
||||
// SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
|
||||
// created by us acts as intended for a terminal emulator.
|
||||
func SetONLCR(fd uintptr) error {
|
||||
return setONLCR(fd, true)
|
||||
}
|
||||
5
vendor/github.com/containerd/console/go.mod
generated
vendored
5
vendor/github.com/containerd/console/go.mod
generated
vendored
@@ -2,7 +2,4 @@ module github.com/containerd/console
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/pkg/errors v0.9.1
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
)
|
||||
require golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
|
||||
2
vendor/github.com/containerd/console/go.sum
generated
vendored
2
vendor/github.com/containerd/console/go.sum
generated
vendored
@@ -1,4 +1,2 @@
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
2
vendor/github.com/containerd/console/tc_unix.go
generated
vendored
2
vendor/github.com/containerd/console/tc_unix.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build darwin freebsd linux netbsd openbsd solaris
|
||||
// +build darwin freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
26
vendor/github.com/containerd/console/tc_zos.go
generated
vendored
Normal file
26
vendor/github.com/containerd/console/tc_zos.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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 console
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTcGet = unix.TCGETS
|
||||
cmdTcSet = unix.TCSETS
|
||||
)
|
||||
42
vendor/github.com/containerd/containerd/go.mod
generated
vendored
42
vendor/github.com/containerd/containerd/go.mod
generated
vendored
@@ -8,13 +8,15 @@ require (
|
||||
github.com/containerd/aufs v1.0.0
|
||||
github.com/containerd/btrfs v1.0.0
|
||||
github.com/containerd/cgroups v1.0.1
|
||||
github.com/containerd/console v1.0.2
|
||||
github.com/containerd/continuity v0.1.0
|
||||
github.com/containerd/console v1.0.3
|
||||
github.com/containerd/continuity v0.2.1
|
||||
github.com/containerd/fifo v1.0.0
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.4
|
||||
github.com/containerd/go-cni v1.0.2
|
||||
github.com/containerd/go-runc v1.0.0
|
||||
github.com/containerd/imgcrypt v1.1.1
|
||||
github.com/containerd/nri v0.1.0
|
||||
github.com/containerd/stargz-snapshotter v0.10.1
|
||||
github.com/containerd/ttrpc v1.1.0
|
||||
github.com/containerd/typeurl v1.0.2
|
||||
github.com/containerd/zfs v1.0.0
|
||||
@@ -31,41 +33,40 @@ require (
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
github.com/hashicorp/go-multierror v1.0.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/klauspost/compress v1.11.13
|
||||
github.com/klauspost/compress v1.13.6
|
||||
github.com/moby/locker v1.0.1
|
||||
github.com/moby/sys/mountinfo v0.4.1
|
||||
github.com/moby/sys/mountinfo v0.5.0
|
||||
github.com/moby/sys/symlink v0.1.0
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.0.1
|
||||
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283
|
||||
github.com/opencontainers/runc v1.0.2
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/opencontainers/selinux v1.8.2
|
||||
github.com/pelletier/go-toml v1.8.1
|
||||
github.com/pelletier/go-toml v1.9.4
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/procfs v0.6.0 // indirect; temporarily force v0.6.0, which was previously defined in imgcrypt as explicit version
|
||||
github.com/satori/go.uuid v1.2.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tchap/go-patricia v2.2.6+incompatible
|
||||
github.com/urfave/cli v1.22.2
|
||||
github.com/urfave/cli v1.22.4
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
|
||||
google.golang.org/grpc v1.38.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359
|
||||
google.golang.org/grpc v1.42.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gotest.tools/v3 v3.0.3
|
||||
k8s.io/api v0.22.0
|
||||
k8s.io/apimachinery v0.22.0
|
||||
k8s.io/apiserver v0.22.0
|
||||
k8s.io/client-go v0.22.0
|
||||
k8s.io/component-base v0.22.0
|
||||
k8s.io/cri-api v0.22.0
|
||||
k8s.io/api v0.22.4
|
||||
k8s.io/apimachinery v0.22.4
|
||||
k8s.io/apiserver v0.22.4
|
||||
k8s.io/client-go v0.22.4
|
||||
k8s.io/component-base v0.22.4
|
||||
k8s.io/cri-api v0.23.0-alpha.4
|
||||
k8s.io/klog/v2 v2.9.0
|
||||
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a
|
||||
)
|
||||
|
||||
// When updating replace rules, make sure to also update the rules in integration/client/go.mod
|
||||
@@ -77,4 +78,5 @@ replace (
|
||||
// urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
||||
github.com/urfave/cli => github.com/urfave/cli v1.22.1
|
||||
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
|
||||
k8s.io/cri-api => k8s.io/cri-api v0.22.4
|
||||
)
|
||||
|
||||
115
vendor/github.com/containerd/containerd/go.sum
generated
vendored
115
vendor/github.com/containerd/containerd/go.sum
generated
vendored
@@ -1,4 +1,5 @@
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
@@ -72,6 +73,7 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
@@ -90,6 +92,10 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ
|
||||
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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
|
||||
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
|
||||
@@ -101,13 +107,17 @@ github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTF
|
||||
github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
|
||||
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
||||
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
||||
github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=
|
||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||
github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8=
|
||||
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
||||
github.com/containerd/continuity v0.2.1 h1:/EeEo2EtN3umhbbgCveyjifoMYg0pS+nMMEemaYw634=
|
||||
github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg=
|
||||
github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU=
|
||||
github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.4 h1:UKlk0rhAq1NW5UEmu9/4f3m9v+O/0+F0as+QeK1UmCM=
|
||||
github.com/containerd/fuse-overlayfs-snapshotter v1.0.4/go.mod h1:UPFCs/OiJHa4MoghjGZdPaOBcZEhATfYG1gSutAZTvE=
|
||||
github.com/containerd/go-cni v1.0.2 h1:YbJAhpTevL2v6u8JC1NhCYRwf+3Vzxcc5vGnYoJ7VeE=
|
||||
github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk=
|
||||
github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||
@@ -117,6 +127,10 @@ github.com/containerd/imgcrypt v1.1.1 h1:LBwiTfoUsdiEGAR1TpvxE+Gzt7469oVu87iR3mv
|
||||
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
||||
github.com/containerd/nri v0.1.0 h1:6QioHRlThlKh2RkRTR4kIT3PKAcrLo3gIWnjkM4dQmQ=
|
||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||
github.com/containerd/stargz-snapshotter v0.10.1 h1:A4nCRPWZmlYGpPNTmmktREqca1WM2IevonzQcIjCZwM=
|
||||
github.com/containerd/stargz-snapshotter v0.10.1/go.mod h1:F/5gQZTyx18Kj+4VnE4Kcwg7BtESs7L/V29jamTI43k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.10.1 h1:hd1EoVjI2Ax8Cr64tdYqnJ4i4pZU49FkEf5kU8KxQng=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.10.1/go.mod h1:aE5PCyhFMwR8sbrErO5eM2GcvkyXTTJremG883D4qF0=
|
||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||
github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI=
|
||||
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
||||
@@ -156,11 +170,18 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
|
||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
|
||||
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
|
||||
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
|
||||
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docker/cli v20.10.10+incompatible h1:kcbwdgWbrBOH8QwQzaJmyriHwF7XIl4HT1qh0HTRys4=
|
||||
github.com/docker/cli v20.10.10+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
|
||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
|
||||
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
@@ -179,6 +200,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@@ -211,6 +233,8 @@ github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.7.10 h1:ulhbuNe1JqE68nMRXXTJRrUu0uhouf0VevLINxQq4Ec=
|
||||
github.com/goccy/go-json v0.7.10/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c h1:RBUpb2b14UnmRHNd2uHz20ZHLDK+SW5Us/vWF5IHRaY=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@@ -262,6 +286,7 @@ 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.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
@@ -283,6 +308,7 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
@@ -294,15 +320,23 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hanwen/go-fuse/v2 v2.1.1-0.20210825171523-3ab5d95a30ae h1:4CB6T4YTUVvnro5ba8ju1QCbOuyGAeF3vvKlo50EJ4k=
|
||||
github.com/hanwen/go-fuse/v2 v2.1.1-0.20210825171523-3ab5d95a30ae/go.mod h1:B1nGE/6RBFyBRC1RRnf23UpwCdyJ31eukw34oAKukAc=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
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/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
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-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
@@ -341,8 +375,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4=
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -355,6 +389,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@@ -383,8 +419,9 @@ 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/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM=
|
||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
|
||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||
github.com/moby/sys/symlink v0.1.0 h1:MTFZ74KtNI6qQQpuBxU+uKCim4WtOMokr03hCfJcazE=
|
||||
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
|
||||
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
|
||||
@@ -400,7 +437,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
@@ -418,8 +454,9 @@ github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
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/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283 h1:TVzvdjOalkJBNkbpPVMAr4KV9QRf2IjfxdyxwAK78Gs=
|
||||
github.com/opencontainers/image-spec v1.0.2-0.20210819154149-5ad6f50d6283/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
@@ -431,8 +468,8 @@ github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xA
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -473,6 +510,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
@@ -528,9 +567,12 @@ github.com/tchap/go-patricia v2.2.6+incompatible h1:JvoDL7JSoIP2HDE8AbDH3zC8QBPx
|
||||
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
|
||||
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
@@ -554,8 +596,9 @@ go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvS
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
|
||||
@@ -645,12 +688,14 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/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-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -692,6 +737,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -717,6 +763,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -725,8 +772,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
@@ -818,8 +865,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -829,16 +877,17 @@ 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.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
@@ -875,25 +924,29 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/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.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.22.0 h1:elCpMZ9UE8dLdYxr55E06TmSeji9I3KH494qH70/y+c=
|
||||
k8s.io/api v0.22.0/go.mod h1:0AoXXqst47OI/L0oGKq9DG61dvGRPXs7X4/B7KyjBCU=
|
||||
k8s.io/apimachinery v0.22.0 h1:CqH/BdNAzZl+sr3tc0D3VsK3u6ARVSo3GWyLmfIjbP0=
|
||||
k8s.io/apimachinery v0.22.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||
k8s.io/apiserver v0.22.0 h1:KZh2asnRBjawLLfPOi6qiD+A2jaNt31HCnZG6AX3Qcs=
|
||||
k8s.io/apiserver v0.22.0/go.mod h1:04kaIEzIQrTGJ5syLppQWvpkLJXQtJECHmae+ZGc/nc=
|
||||
k8s.io/client-go v0.22.0 h1:sD6o9O6tCwUKCENw8v+HFsuAbq2jCu8cWC61/ydwA50=
|
||||
k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg=
|
||||
k8s.io/component-base v0.22.0 h1:ZTmX8hUqH9T9gc0mM42O+KDgtwTYbVTt2MwmLP0eK8A=
|
||||
k8s.io/component-base v0.22.0/go.mod h1:SXj6Z+V6P6GsBhHZVbWCw9hFjUdUYnJerlhhPnYCBCg=
|
||||
k8s.io/cri-api v0.22.0 h1:YECUji0xxCTCWFO/TUkrL1b44Ip6mZJbiqP6Us/+Vys=
|
||||
k8s.io/cri-api v0.22.0/go.mod h1:mj5DGUtElRyErU5AZ8EM0ahxbElYsaLAMTPhLPQ40Eg=
|
||||
k8s.io/api v0.22.3/go.mod h1:azgiXFiXqiWyLCfI62/eYBOu19rj2LKmIhFPP4+33fs=
|
||||
k8s.io/api v0.22.4 h1:UvyHW0ezB2oIgHAxlYoo6UJQObYXU7awuNarwoHEOjw=
|
||||
k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk=
|
||||
k8s.io/apimachinery v0.22.3/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
|
||||
k8s.io/apimachinery v0.22.4 h1:9uwcvPpukBw/Ri0EUmWz+49cnFtaoiyEhQTK+xOe7Ck=
|
||||
k8s.io/apimachinery v0.22.4/go.mod h1:yU6oA6Gnax9RrxGzVvPFFJ+mpnW6PBSqp0sx0I0HHW0=
|
||||
k8s.io/apiserver v0.22.4 h1:L+220cy+94UWmyBl1kiVTklBXrBtKsbjlPV60eL2u6s=
|
||||
k8s.io/apiserver v0.22.4/go.mod h1:38WmcUZiiy41A7Aty8/VorWRa8vDGqoUzDf2XYlku0E=
|
||||
k8s.io/client-go v0.22.3/go.mod h1:ElDjYf8gvZsKDYexmsmnMQ0DYO8W9RwBjfQ1PI53yow=
|
||||
k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg=
|
||||
k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA=
|
||||
k8s.io/component-base v0.22.4 h1:7qwLJnua2ppGNZrRGDQ0vhsFebI39VGbZ4zdR5ArViI=
|
||||
k8s.io/component-base v0.22.4/go.mod h1:MrSaQy4a3tFVViff8TZL6JHYSewNCLshZCwHYM58v5A=
|
||||
k8s.io/cri-api v0.22.4 h1:Do7gPZ74mDjSxT1Ux0wWIQ5MMG17uPqT/TKd2yrIwNo=
|
||||
k8s.io/cri-api v0.22.4/go.mod h1:mj5DGUtElRyErU5AZ8EM0ahxbElYsaLAMTPhLPQ40Eg=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM=
|
||||
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9 h1:imL9YgXQ9p7xmPzHFm/vVd/cF78jad+n4wK1ABwYtMM=
|
||||
k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g=
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
||||
6
vendor/github.com/containerd/continuity/AUTHORS
generated
vendored
6
vendor/github.com/containerd/continuity/AUTHORS
generated
vendored
@@ -12,8 +12,11 @@ Darren Stahl <darst@microsoft.com>
|
||||
Derek McGowan <derek@mcg.dev>
|
||||
Derek McGowan <derek@mcgstyle.net>
|
||||
Edward Pilatowicz <edward.pilatowicz@oracle.com>
|
||||
Fu Wei <fuweid89@gmail.com>
|
||||
Hajime Tazaki <thehajime@gmail.com>
|
||||
Ian Campbell <ijc@docker.com>
|
||||
Ivan Markin <sw@nogoegst.net>
|
||||
Jacob Blain Christen <jacob@rancher.com>
|
||||
Justin Cormack <justin.cormack@docker.com>
|
||||
Justin Cummins <sul3n3t@gmail.com>
|
||||
Kasper Fabæch Brandt <poizan@poizan.dk>
|
||||
@@ -23,10 +26,11 @@ Michael Crosby <michael@thepasture.io>
|
||||
Michael Wan <zirenwan@gmail.com>
|
||||
Mike Brown <brownwm@us.ibm.com>
|
||||
Niels de Vos <ndevos@redhat.com>
|
||||
Phil Estes <estesp@amazon.com>
|
||||
Phil Estes <estesp@gmail.com>
|
||||
Phil Estes <estesp@linux.vnet.ibm.com>
|
||||
Samuel Karp <me@samuelkarp.com>
|
||||
Sam Whited <sam@samwhited.com>
|
||||
Samuel Karp <me@samuelkarp.com>
|
||||
Sebastiaan van Stijn <github@gone.nl>
|
||||
Shengjing Zhu <zhsj@debian.org>
|
||||
Stephen J Day <stephen.day@docker.com>
|
||||
|
||||
8
vendor/github.com/containerd/continuity/README.md
generated
vendored
8
vendor/github.com/containerd/continuity/README.md
generated
vendored
@@ -1,7 +1,7 @@
|
||||
# continuity
|
||||
|
||||
[](https://godoc.org/github.com/containerd/continuity)
|
||||
[](https://travis-ci.org/containerd/continuity)
|
||||
[](https://travis-ci.org/containerd/continuity)
|
||||
|
||||
A transport-agnostic, filesystem metadata manifest system
|
||||
|
||||
@@ -81,8 +81,8 @@ $ go generate ./proto
|
||||
|
||||
continuity is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
||||
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
|
||||
1
vendor/github.com/containerd/continuity/devices/devices_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/devices/devices_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin || freebsd || solaris
|
||||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
|
||||
5
vendor/github.com/containerd/continuity/devices/devices_windows.go
generated
vendored
5
vendor/github.com/containerd/continuity/devices/devices_windows.go
generated
vendored
@@ -17,11 +17,10 @@
|
||||
package devices
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func DeviceInfo(fi os.FileInfo) (uint64, uint64, error) {
|
||||
return 0, 0, errors.Wrap(ErrNotSupported, "cannot get device info on windows")
|
||||
return 0, 0, fmt.Errorf("cannot get device info on windows: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
1
vendor/github.com/containerd/continuity/devices/mknod_freebsd.go
generated
vendored
1
vendor/github.com/containerd/continuity/devices/mknod_freebsd.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/devices/mknod_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/devices/mknod_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin || solaris
|
||||
// +build linux darwin solaris
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/driver/driver_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/driver/driver_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin || freebsd || solaris
|
||||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/driver/driver_windows.go
generated
vendored
1
vendor/github.com/containerd/continuity/driver/driver_windows.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build go1.13
|
||||
// +build go1.13
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/driver/lchmod_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/driver/lchmod_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build darwin || freebsd || solaris
|
||||
// +build darwin freebsd solaris
|
||||
|
||||
/*
|
||||
|
||||
41
vendor/github.com/containerd/continuity/fs/copy.go
generated
vendored
41
vendor/github.com/containerd/continuity/fs/copy.go
generated
vendored
@@ -17,12 +17,11 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var bufferPool = &sync.Pool{
|
||||
@@ -92,35 +91,35 @@ func CopyDir(dst, src string, opts ...CopyDirOpt) error {
|
||||
func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) error {
|
||||
stat, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to stat %s", src)
|
||||
return fmt.Errorf("failed to stat %s: %w", src, err)
|
||||
}
|
||||
if !stat.IsDir() {
|
||||
return errors.Errorf("source %s is not directory", src)
|
||||
return fmt.Errorf("source %s is not directory", src)
|
||||
}
|
||||
|
||||
if st, err := os.Stat(dst); err != nil {
|
||||
if err := os.Mkdir(dst, stat.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to mkdir %s", dst)
|
||||
return fmt.Errorf("failed to mkdir %s: %w", dst, err)
|
||||
}
|
||||
} else if !st.IsDir() {
|
||||
return errors.Errorf("cannot copy to non-directory: %s", dst)
|
||||
return fmt.Errorf("cannot copy to non-directory: %s", dst)
|
||||
} else {
|
||||
if err := os.Chmod(dst, stat.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to chmod on %s", dst)
|
||||
return fmt.Errorf("failed to chmod on %s: %w", dst, err)
|
||||
}
|
||||
}
|
||||
|
||||
fis, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read %s", src)
|
||||
return fmt.Errorf("failed to read %s: %w", src, err)
|
||||
}
|
||||
|
||||
if err := copyFileInfo(stat, dst); err != nil {
|
||||
return errors.Wrapf(err, "failed to copy file info for %s", dst)
|
||||
return fmt.Errorf("failed to copy file info for %s: %w", dst, err)
|
||||
}
|
||||
|
||||
if err := copyXAttrs(dst, src, o.xex, o.xeh); err != nil {
|
||||
return errors.Wrap(err, "failed to copy xattrs")
|
||||
return fmt.Errorf("failed to copy xattrs: %w", err)
|
||||
}
|
||||
|
||||
for _, fi := range fis {
|
||||
@@ -136,37 +135,37 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
|
||||
case (fi.Mode() & os.ModeType) == 0:
|
||||
link, err := getLinkSource(target, fi, inodes)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get hardlink")
|
||||
return fmt.Errorf("failed to get hardlink: %w", err)
|
||||
}
|
||||
if link != "" {
|
||||
if err := os.Link(link, target); err != nil {
|
||||
return errors.Wrap(err, "failed to create hard link")
|
||||
return fmt.Errorf("failed to create hard link: %w", err)
|
||||
}
|
||||
} else if err := CopyFile(target, source); err != nil {
|
||||
return errors.Wrap(err, "failed to copy files")
|
||||
return fmt.Errorf("failed to copy files: %w", err)
|
||||
}
|
||||
case (fi.Mode() & os.ModeSymlink) == os.ModeSymlink:
|
||||
link, err := os.Readlink(source)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read link: %s", source)
|
||||
return fmt.Errorf("failed to read link: %s: %w", source, err)
|
||||
}
|
||||
if err := os.Symlink(link, target); err != nil {
|
||||
return errors.Wrapf(err, "failed to create symlink: %s", target)
|
||||
return fmt.Errorf("failed to create symlink: %s: %w", target, err)
|
||||
}
|
||||
case (fi.Mode() & os.ModeDevice) == os.ModeDevice:
|
||||
if err := copyDevice(target, fi); err != nil {
|
||||
return errors.Wrapf(err, "failed to create device")
|
||||
return fmt.Errorf("failed to create device: %w", err)
|
||||
}
|
||||
default:
|
||||
// TODO: Support pipes and sockets
|
||||
return errors.Wrapf(err, "unsupported mode %s", fi.Mode())
|
||||
return fmt.Errorf("unsupported mode %s: %w", fi.Mode(), err)
|
||||
}
|
||||
if err := copyFileInfo(fi, target); err != nil {
|
||||
return errors.Wrap(err, "failed to copy file info")
|
||||
return fmt.Errorf("failed to copy file info: %w", err)
|
||||
}
|
||||
|
||||
if err := copyXAttrs(target, source, o.xex, o.xeh); err != nil {
|
||||
return errors.Wrap(err, "failed to copy xattrs")
|
||||
return fmt.Errorf("failed to copy xattrs: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,12 +177,12 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er
|
||||
func CopyFile(target, source string) error {
|
||||
src, err := os.Open(source)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to open source %s", source)
|
||||
return fmt.Errorf("failed to open source %s: %w", source, err)
|
||||
}
|
||||
defer src.Close()
|
||||
tgt, err := os.Create(target)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to open target %s", target)
|
||||
return fmt.Errorf("failed to open target %s: %w", target, err)
|
||||
}
|
||||
defer tgt.Close()
|
||||
|
||||
|
||||
43
vendor/github.com/containerd/continuity/fs/copy_darwin.go
generated
vendored
Normal file
43
vendor/github.com/containerd/continuity/fs/copy_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func copyDevice(dst string, fi os.FileInfo) error {
|
||||
st, ok := fi.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
return errors.New("unsupported stat type")
|
||||
}
|
||||
return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev))
|
||||
}
|
||||
|
||||
func utimesNano(name string, atime, mtime syscall.Timespec) error {
|
||||
at := unix.NsecToTimespec(atime.Nano())
|
||||
mt := unix.NsecToTimespec(mtime.Nano())
|
||||
utimes := [2]unix.Timespec{at, mt}
|
||||
return unix.UtimesNanoAt(unix.AT_FDCWD, name, utimes[0:], unix.AT_SYMLINK_NOFOLLOW)
|
||||
}
|
||||
3
vendor/github.com/containerd/continuity/fs/copy_freebsd.go
generated
vendored
3
vendor/github.com/containerd/continuity/fs/copy_freebsd.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
/*
|
||||
@@ -19,10 +20,10 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
|
||||
24
vendor/github.com/containerd/continuity/fs/copy_linux.go
generated
vendored
24
vendor/github.com/containerd/continuity/fs/copy_linux.go
generated
vendored
@@ -17,12 +17,13 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -41,13 +42,13 @@ func copyFileInfo(fi os.FileInfo, name string) error {
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to chown %s", name)
|
||||
return fmt.Errorf("failed to chown %s: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
|
||||
if err := os.Chmod(name, fi.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to chmod %s", name)
|
||||
return fmt.Errorf("failed to chmod %s: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ func copyFileInfo(fi os.FileInfo, name string) error {
|
||||
unix.NsecToTimespec(syscall.TimespecToNsec(StatMtime(st))),
|
||||
}
|
||||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
||||
return errors.Wrapf(err, "failed to utime %s", name)
|
||||
return fmt.Errorf("failed to utime %s: %w", name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -67,7 +68,7 @@ const maxSSizeT = int64(^uint(0) >> 1)
|
||||
func copyFileContent(dst, src *os.File) error {
|
||||
st, err := src.Stat()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to stat source")
|
||||
return fmt.Errorf("unable to stat source: %w", err)
|
||||
}
|
||||
|
||||
size := st.Size()
|
||||
@@ -88,13 +89,16 @@ func copyFileContent(dst, src *os.File) error {
|
||||
n, err := unix.CopyFileRange(srcFd, nil, dstFd, nil, copySize, 0)
|
||||
if err != nil {
|
||||
if (err != unix.ENOSYS && err != unix.EXDEV) || !first {
|
||||
return errors.Wrap(err, "copy file range failed")
|
||||
return fmt.Errorf("copy file range failed: %w", err)
|
||||
}
|
||||
|
||||
buf := bufferPool.Get().(*[]byte)
|
||||
_, err = io.CopyBuffer(dst, src, *buf)
|
||||
bufferPool.Put(buf)
|
||||
return errors.Wrap(err, "userspace copy failed")
|
||||
if err != nil {
|
||||
return fmt.Errorf("userspace copy failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
first = false
|
||||
@@ -107,7 +111,7 @@ func copyFileContent(dst, src *os.File) error {
|
||||
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
|
||||
xattrKeys, err := sysx.LListxattr(src)
|
||||
if err != nil {
|
||||
e := errors.Wrapf(err, "failed to list xattrs on %s", src)
|
||||
e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
|
||||
if errorHandler != nil {
|
||||
e = errorHandler(dst, src, "", e)
|
||||
}
|
||||
@@ -119,7 +123,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt
|
||||
}
|
||||
data, err := sysx.LGetxattr(src, xattr)
|
||||
if err != nil {
|
||||
e := errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)
|
||||
e := fmt.Errorf("failed to get xattr %q on %s: %w", xattr, src, err)
|
||||
if errorHandler != nil {
|
||||
if e = errorHandler(dst, src, xattr, e); e == nil {
|
||||
continue
|
||||
@@ -128,7 +132,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt
|
||||
return e
|
||||
}
|
||||
if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil {
|
||||
e := errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)
|
||||
e := fmt.Errorf("failed to set xattr %q on %s: %w", xattr, dst, err)
|
||||
if errorHandler != nil {
|
||||
if e = errorHandler(dst, src, xattr, e); e == nil {
|
||||
continue
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// +build darwin openbsd solaris
|
||||
//go:build openbsd || solaris
|
||||
// +build openbsd solaris
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
@@ -19,10 +20,10 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
15
vendor/github.com/containerd/continuity/fs/copy_unix.go
generated
vendored
15
vendor/github.com/containerd/continuity/fs/copy_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build darwin || freebsd || openbsd || solaris
|
||||
// +build darwin freebsd openbsd solaris
|
||||
|
||||
/*
|
||||
@@ -19,12 +20,12 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func copyFileInfo(fi os.FileInfo, name string) error {
|
||||
@@ -42,18 +43,18 @@ func copyFileInfo(fi os.FileInfo, name string) error {
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to chown %s", name)
|
||||
return fmt.Errorf("failed to chown %s: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
|
||||
if err := os.Chmod(name, fi.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to chmod %s", name)
|
||||
return fmt.Errorf("failed to chmod %s: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := utimesNano(name, StatAtime(st), StatMtime(st)); err != nil {
|
||||
return errors.Wrapf(err, "failed to utime %s", name)
|
||||
return fmt.Errorf("failed to utime %s: %w", name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -70,7 +71,7 @@ func copyFileContent(dst, src *os.File) error {
|
||||
func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
|
||||
xattrKeys, err := sysx.LListxattr(src)
|
||||
if err != nil {
|
||||
e := errors.Wrapf(err, "failed to list xattrs on %s", src)
|
||||
e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
|
||||
if errorHandler != nil {
|
||||
e = errorHandler(dst, src, "", e)
|
||||
}
|
||||
@@ -82,7 +83,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt
|
||||
}
|
||||
data, err := sysx.LGetxattr(src, xattr)
|
||||
if err != nil {
|
||||
e := errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)
|
||||
e := fmt.Errorf("failed to get xattr %q on %s: %w", xattr, src, err)
|
||||
if errorHandler != nil {
|
||||
if e = errorHandler(dst, src, xattr, e); e == nil {
|
||||
continue
|
||||
@@ -91,7 +92,7 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt
|
||||
return e
|
||||
}
|
||||
if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil {
|
||||
e := errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)
|
||||
e := fmt.Errorf("failed to set xattr %q on %s: %w", xattr, dst, err)
|
||||
if errorHandler != nil {
|
||||
if e = errorHandler(dst, src, xattr, e); e == nil {
|
||||
continue
|
||||
|
||||
6
vendor/github.com/containerd/continuity/fs/copy_windows.go
generated
vendored
6
vendor/github.com/containerd/continuity/fs/copy_windows.go
generated
vendored
@@ -17,15 +17,15 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func copyFileInfo(fi os.FileInfo, name string) error {
|
||||
if err := os.Chmod(name, fi.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to chmod %s", name)
|
||||
return fmt.Errorf("failed to chmod %s: %w", name, err)
|
||||
}
|
||||
|
||||
// TODO: copy windows specific metadata
|
||||
|
||||
7
vendor/github.com/containerd/continuity/fs/diff_unix.go
generated
vendored
7
vendor/github.com/containerd/continuity/fs/diff_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
@@ -20,11 +21,11 @@ package fs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// detectDirDiff returns diff dir options if a directory could
|
||||
@@ -56,11 +57,11 @@ func compareSysStat(s1, s2 interface{}) (bool, error) {
|
||||
func compareCapabilities(p1, p2 string) (bool, error) {
|
||||
c1, err := sysx.LGetxattr(p1, "security.capability")
|
||||
if err != nil && err != sysx.ENODATA {
|
||||
return false, errors.Wrapf(err, "failed to get xattr for %s", p1)
|
||||
return false, fmt.Errorf("failed to get xattr for %s: %w", p1, err)
|
||||
}
|
||||
c2, err := sysx.LGetxattr(p2, "security.capability")
|
||||
if err != nil && err != sysx.ENODATA {
|
||||
return false, errors.Wrapf(err, "failed to get xattr for %s", p2)
|
||||
return false, fmt.Errorf("failed to get xattr for %s: %w", p2, err)
|
||||
}
|
||||
return bytes.Equal(c1, c2), nil
|
||||
}
|
||||
|
||||
1
vendor/github.com/containerd/continuity/fs/dtype_linux.go
generated
vendored
1
vendor/github.com/containerd/continuity/fs/dtype_linux.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
|
||||
7
vendor/github.com/containerd/continuity/fs/du_unix.go
generated
vendored
7
vendor/github.com/containerd/continuity/fs/du_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
@@ -41,10 +42,8 @@ type inode struct {
|
||||
|
||||
func newInode(stat *syscall.Stat_t) inode {
|
||||
return inode{
|
||||
// Dev is uint32 on darwin/bsd, uint64 on linux/solaris/freebsd
|
||||
dev: uint64(stat.Dev), // nolint: unconvert
|
||||
// Ino is uint32 on bsd, uint64 on darwin/linux/solaris/freebsd
|
||||
ino: uint64(stat.Ino), // nolint: unconvert
|
||||
dev: uint64(stat.Dev), //nolint: unconvert // dev is uint32 on darwin/bsd, uint64 on linux/solaris/freebsd
|
||||
ino: uint64(stat.Ino), //nolint: unconvert // ino is uint32 on bsd, uint64 on darwin/linux/solaris/freebsd
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
vendor/github.com/containerd/continuity/fs/du_windows.go
generated
vendored
1
vendor/github.com/containerd/continuity/fs/du_windows.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
|
||||
4
vendor/github.com/containerd/continuity/fs/hardlink_unix.go
generated
vendored
4
vendor/github.com/containerd/continuity/fs/hardlink_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
@@ -29,6 +30,5 @@ func getLinkInfo(fi os.FileInfo) (uint64, bool) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Ino is uint32 on bsd, uint64 on darwin/linux/solaris
|
||||
return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1 // nolint: unconvert
|
||||
return uint64(s.Ino), !fi.IsDir() && s.Nlink > 1 //nolint: unconvert // ino is uint32 on bsd, uint64 on darwin/linux/solaris
|
||||
}
|
||||
|
||||
3
vendor/github.com/containerd/continuity/fs/path.go
generated
vendored
3
vendor/github.com/containerd/continuity/fs/path.go
generated
vendored
@@ -19,11 +19,10 @@ package fs
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// +build darwin freebsd
|
||||
//go:build darwin || freebsd || netbsd
|
||||
// +build darwin freebsd netbsd
|
||||
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
@@ -40,5 +41,5 @@ func StatMtime(st *syscall.Stat_t) syscall.Timespec {
|
||||
|
||||
// StatATimeAsTime returns the access time as a time.Time
|
||||
func StatATimeAsTime(st *syscall.Stat_t) time.Time {
|
||||
return time.Unix(int64(st.Atimespec.Sec), int64(st.Atimespec.Nsec)) // nolint: unconvert
|
||||
return time.Unix(int64(st.Atimespec.Sec), int64(st.Atimespec.Nsec)) //nolint: unconvert // int64 conversions ensure the line compiles for 32-bit systems as well.
|
||||
}
|
||||
4
vendor/github.com/containerd/continuity/fs/stat_linuxopenbsd.go
generated
vendored
4
vendor/github.com/containerd/continuity/fs/stat_linuxopenbsd.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || openbsd
|
||||
// +build linux openbsd
|
||||
|
||||
/*
|
||||
@@ -40,6 +41,5 @@ func StatMtime(st *syscall.Stat_t) syscall.Timespec {
|
||||
|
||||
// StatATimeAsTime returns st.Atim as a time.Time
|
||||
func StatATimeAsTime(st *syscall.Stat_t) time.Time {
|
||||
// The int64 conversions ensure the line compiles for 32-bit systems as well.
|
||||
return time.Unix(int64(st.Atim.Sec), int64(st.Atim.Nsec)) // nolint: unconvert
|
||||
return time.Unix(int64(st.Atim.Sec), int64(st.Atim.Nsec)) //nolint: unconvert // int64 conversions ensure the line compiles for 32-bit systems as well.
|
||||
}
|
||||
|
||||
17
vendor/github.com/containerd/continuity/go.mod
generated
vendored
17
vendor/github.com/containerd/continuity/go.mod
generated
vendored
@@ -3,17 +3,14 @@ module github.com/containerd/continuity
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898
|
||||
// 5883e5a4b512fe2e32f915b1c66a1ddfef81cb3f is the last version to support macOS
|
||||
// see https://github.com/bazil/fuse/commit/60eaf8f021ce00e5c52529cdcba1067e13c1c2c2
|
||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/golang/protobuf v1.2.0
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/golang/protobuf v1.3.5
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95 // indirect
|
||||
github.com/stretchr/testify v1.4.0 // indirect
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd // indirect
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3
|
||||
github.com/spf13/cobra v1.0.0
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
)
|
||||
|
||||
150
vendor/github.com/containerd/continuity/go.sum
generated
vendored
150
vendor/github.com/containerd/continuity/go.sum
generated
vendored
@@ -1,38 +1,148 @@
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898 h1:SC+c6A1qTFstO9qmB86mPV2IpYme/2ZoEQ0hrP+wo+Q=
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512 h1:SRsZGA7aFnCZETmov57jwPrWuTmaZK6+4R4v5FUe1/c=
|
||||
bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
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/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
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/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee h1:GQkkv3XSnxhAMjdq2wLfEnptEVr+2BNvmHizILHn+d4=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95 h1:j8jxLbQ0+T1DFggy6XoGvyUnrJWPR/JybflPvu5rwS4=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
|
||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
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-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
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-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-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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-20181107165924-66b7b1311ac8/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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
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/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
1
vendor/github.com/containerd/continuity/hardlinks_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/hardlinks_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin || freebsd || solaris
|
||||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
|
||||
10
vendor/github.com/containerd/continuity/manifest.go
generated
vendored
10
vendor/github.com/containerd/continuity/manifest.go
generated
vendored
@@ -75,7 +75,7 @@ func MarshalText(w io.Writer, m *Manifest) error {
|
||||
// BuildManifest creates the manifest for the given context
|
||||
func BuildManifest(ctx Context) (*Manifest, error) {
|
||||
resourcesByPath := map[string]Resource{}
|
||||
hardlinks := newHardlinkManager()
|
||||
hardLinks := newHardlinkManager()
|
||||
|
||||
if err := ctx.Walk(func(p string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
@@ -97,7 +97,7 @@ func BuildManifest(ctx Context) (*Manifest, error) {
|
||||
}
|
||||
|
||||
// add to the hardlink manager
|
||||
if err := hardlinks.Add(fi, resource); err == nil {
|
||||
if err := hardLinks.Add(fi, resource); err == nil {
|
||||
// Resource has been accepted by hardlink manager so we don't add
|
||||
// it to the resourcesByPath until we merge at the end.
|
||||
return nil
|
||||
@@ -114,14 +114,12 @@ func BuildManifest(ctx Context) (*Manifest, error) {
|
||||
}
|
||||
|
||||
// merge and post-process the hardlinks.
|
||||
// nolint:misspell
|
||||
hardlinked, err := hardlinks.Merge()
|
||||
hardLinked, err := hardLinks.Merge()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// nolint:misspell
|
||||
for _, resource := range hardlinked {
|
||||
for _, resource := range hardLinked {
|
||||
resourcesByPath[resource.Path()] = resource
|
||||
}
|
||||
|
||||
|
||||
117
vendor/github.com/containerd/continuity/proto/manifest.pb.go
generated
vendored
117
vendor/github.com/containerd/continuity/proto/manifest.pb.go
generated
vendored
@@ -1,6 +1,5 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: manifest.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
@@ -97,6 +96,83 @@ func (m *Resource) String() string { return proto1.CompactTextString(
|
||||
func (*Resource) ProtoMessage() {}
|
||||
func (*Resource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Resource) GetPath() []string {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Resource) GetUid() int64 {
|
||||
if m != nil {
|
||||
return m.Uid
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Resource) GetGid() int64 {
|
||||
if m != nil {
|
||||
return m.Gid
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Resource) GetUser() string {
|
||||
if m != nil {
|
||||
return m.User
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Resource) GetGroup() string {
|
||||
if m != nil {
|
||||
return m.Group
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Resource) GetMode() uint32 {
|
||||
if m != nil {
|
||||
return m.Mode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Resource) GetSize() uint64 {
|
||||
if m != nil {
|
||||
return m.Size
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Resource) GetDigest() []string {
|
||||
if m != nil {
|
||||
return m.Digest
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Resource) GetTarget() string {
|
||||
if m != nil {
|
||||
return m.Target
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Resource) GetMajor() uint64 {
|
||||
if m != nil {
|
||||
return m.Major
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Resource) GetMinor() uint64 {
|
||||
if m != nil {
|
||||
return m.Minor
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Resource) GetXattr() []*XAttr {
|
||||
if m != nil {
|
||||
return m.Xattr
|
||||
@@ -124,6 +200,20 @@ func (m *XAttr) String() string { return proto1.CompactTextString(m)
|
||||
func (*XAttr) ProtoMessage() {}
|
||||
func (*XAttr) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *XAttr) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *XAttr) GetData() []byte {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ADSEntry encodes information for a Windows Alternate Data Stream.
|
||||
type ADSEntry struct {
|
||||
// Name specifices the stream name.
|
||||
@@ -147,6 +237,27 @@ func (m *ADSEntry) String() string { return proto1.CompactTextString(
|
||||
func (*ADSEntry) ProtoMessage() {}
|
||||
func (*ADSEntry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *ADSEntry) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ADSEntry) GetData() []byte {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ADSEntry) GetDigest() string {
|
||||
if m != nil {
|
||||
return m.Digest
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*Manifest)(nil), "proto.Manifest")
|
||||
proto1.RegisterType((*Resource)(nil), "proto.Resource")
|
||||
@@ -158,7 +269,7 @@ func init() { proto1.RegisterFile("manifest.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 317 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x90, 0x4f, 0x4b, 0xf3, 0x40,
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0x4f, 0x4b, 0xf3, 0x40,
|
||||
0x10, 0xc6, 0x49, 0x93, 0xf4, 0x4d, 0xa7, 0xed, 0xab, 0x2c, 0x52, 0xe6, 0x18, 0x73, 0x0a, 0x08,
|
||||
0x15, 0xf4, 0xe0, 0xb9, 0xa2, 0x17, 0xc1, 0xcb, 0x7a, 0xf1, 0xba, 0xba, 0x6b, 0x5c, 0x21, 0xd9,
|
||||
0xb0, 0xd9, 0x80, 0xfa, 0xe5, 0xfc, 0x6a, 0x32, 0xb3, 0x69, 0xd1, 0x9b, 0xa7, 0x3c, 0xcf, 0x6f,
|
||||
|
||||
1
vendor/github.com/containerd/continuity/resource_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/resource_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin || freebsd || solaris
|
||||
// +build linux darwin freebsd solaris
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/sysx/nodata_unix.go
generated
vendored
1
vendor/github.com/containerd/continuity/sysx/nodata_unix.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build darwin || freebsd || openbsd
|
||||
// +build darwin freebsd openbsd
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/sysx/xattr.go
generated
vendored
1
vendor/github.com/containerd/continuity/sysx/xattr.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin
|
||||
// +build linux darwin
|
||||
|
||||
/*
|
||||
|
||||
1
vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
generated
vendored
1
vendor/github.com/containerd/continuity/sysx/xattr_unsupported.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build !linux && !darwin
|
||||
// +build !linux,!darwin
|
||||
|
||||
/*
|
||||
|
||||
10
vendor/github.com/containerd/fuse-overlayfs-snapshotter/Dockerfile
generated
vendored
10
vendor/github.com/containerd/fuse-overlayfs-snapshotter/Dockerfile
generated
vendored
@@ -13,12 +13,12 @@
|
||||
# limitations under the License.
|
||||
|
||||
ARG FUSEOVERLAYFS_COMMIT=master
|
||||
ARG ROOTLESSKIT_COMMIT=v0.14.0
|
||||
ARG SHADOW_COMMIT=4.8.1
|
||||
ARG ROOTLESSKIT_COMMIT=v0.14.6
|
||||
ARG SHADOW_COMMIT=4.9
|
||||
|
||||
ARG GO_VERSION=1.16
|
||||
ARG DEBIAN_VERSION=10
|
||||
ARG ALPINE_VERSION=3.13
|
||||
ARG GO_VERSION=1.17
|
||||
ARG DEBIAN_VERSION=11
|
||||
ARG ALPINE_VERSION=3.14
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine AS containerd-fuse-overlayfs-test
|
||||
COPY . /go/src/github.com/containerd/fuse-overlayfs-snapshotter
|
||||
|
||||
2
vendor/github.com/containerd/fuse-overlayfs-snapshotter/README.md
generated
vendored
2
vendor/github.com/containerd/fuse-overlayfs-snapshotter/README.md
generated
vendored
@@ -5,8 +5,6 @@ Unlike `overlayfs`, `fuse-overlayfs` can be used as a non-root user on almost al
|
||||
You do NOT need this `fuse-overlayfs` plugin on the following environments, because they support the real `overlayfs` for non-root users:
|
||||
- [kernel >= 5.11](https://github.com/torvalds/linux/commit/459c7c565ac36ba09ffbf24231147f408fde4203)
|
||||
- [Ubuntu kernel, since circa 2015](https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/commit/fs/overlayfs?id=3b7da90f28fe1ed4b79ef2d994c81efbc58f1144)
|
||||
- [Debian 10 kernel](https://salsa.debian.org/kernel-team/linux/blob/283390e7feb21b47779b48e0c8eb0cc409d2c815/debian/patches/debian/overlayfs-permit-mounts-in-userns.patch)
|
||||
- Debian 10 needs `sudo modprobe overlay permit_mounts_in_userns=1`. Future release of Debian with kernel >= 5.11 will not need this `modprobe` hack.
|
||||
|
||||
fuse-overlayfs-snapshotter is a **non-core** sub-project of containerd.
|
||||
|
||||
|
||||
8
vendor/github.com/containerd/fuse-overlayfs-snapshotter/check.go
generated
vendored
8
vendor/github.com/containerd/fuse-overlayfs-snapshotter/check.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
@@ -27,7 +28,6 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// supportsReadonlyMultipleLowerDir checks if read-only multiple lowerdirs can be mounted with fuse-overlayfs.
|
||||
@@ -57,7 +57,7 @@ func supportsReadonlyMultipleLowerDir(d string) error {
|
||||
}
|
||||
dest := filepath.Join(td, "merged")
|
||||
if err := m.Mount(dest); err != nil {
|
||||
return errors.Wrapf(err, "failed to mount fuse-overlayfs (%+v) on %s", m, dest)
|
||||
return fmt.Errorf("failed to mount fuse-overlayfs (%+v) on %s: %w", m, dest, err)
|
||||
}
|
||||
if err := mount.UnmountAll(dest, 0); err != nil {
|
||||
log.L.WithError(err).Warnf("Failed to unmount check directory %v", dest)
|
||||
@@ -70,13 +70,13 @@ func supportsReadonlyMultipleLowerDir(d string) error {
|
||||
// this snapshotter as a library.
|
||||
func Supported(root string) error {
|
||||
if _, err := exec.LookPath(fuseoverlayfsBinary); err != nil {
|
||||
return errors.Wrapf(err, "%s not installed", fuseoverlayfsBinary)
|
||||
return fmt.Errorf("%s not installed: %w", fuseoverlayfsBinary, err)
|
||||
}
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := supportsReadonlyMultipleLowerDir(root); err != nil {
|
||||
return errors.Wrap(err, "fuse-overlayfs not functional, make sure running with kernel >= 4.18")
|
||||
return fmt.Errorf("fuse-overlayfs not functional, make sure running with kernel >= 4.18: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
26
vendor/github.com/containerd/fuse-overlayfs-snapshotter/fuseoverlayfs.go
generated
vendored
26
vendor/github.com/containerd/fuse-overlayfs-snapshotter/fuseoverlayfs.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
@@ -32,7 +33,6 @@ import (
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
"github.com/containerd/containerd/snapshots/storage"
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -186,7 +186,7 @@ func (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er
|
||||
_, info, _, err := storage.GetInfo(ctx, key)
|
||||
t.Rollback()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get active mount")
|
||||
return nil, fmt.Errorf("failed to get active mount: %w", err)
|
||||
}
|
||||
return o.mounts(s, info), nil
|
||||
}
|
||||
@@ -217,7 +217,7 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
|
||||
}
|
||||
|
||||
if _, err = storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil {
|
||||
return errors.Wrap(err, "failed to commit snapshot")
|
||||
return fmt.Errorf("failed to commit snapshot: %w", err)
|
||||
}
|
||||
return t.Commit()
|
||||
}
|
||||
@@ -240,14 +240,14 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) {
|
||||
|
||||
_, _, err = storage.Remove(ctx, key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to remove")
|
||||
return fmt.Errorf("failed to remove: %w", err)
|
||||
}
|
||||
|
||||
if !o.asyncRemove {
|
||||
var removals []string
|
||||
removals, err = o.getCleanupDirectories(ctx, t)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to get directories for removal")
|
||||
return fmt.Errorf("unable to get directories for removal: %w", err)
|
||||
}
|
||||
|
||||
// Remove directories after the transaction is closed, failures must not
|
||||
@@ -353,7 +353,7 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
|
||||
if path != "" {
|
||||
if err1 := os.RemoveAll(path); err1 != nil {
|
||||
log.G(ctx).WithError(err1).WithField("path", path).Error("failed to reclaim snapshot directory, directory may need removal")
|
||||
err = errors.Wrapf(err, "failed to remove path: %v", err1)
|
||||
err = fmt.Errorf("failed to remove path: %v: %w", err1, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -365,7 +365,7 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
|
||||
if rerr := t.Rollback(); rerr != nil {
|
||||
log.G(ctx).WithError(rerr).Warn("failed to rollback transaction")
|
||||
}
|
||||
return nil, errors.Wrap(err, "failed to create prepare snapshot dir")
|
||||
return nil, fmt.Errorf("failed to create prepare snapshot dir: %w", err)
|
||||
}
|
||||
rollback := true
|
||||
defer func() {
|
||||
@@ -378,13 +378,13 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
|
||||
|
||||
s, err := storage.CreateSnapshot(ctx, kind, key, parent, opts...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create snapshot")
|
||||
return nil, fmt.Errorf("failed to create snapshot: %w", err)
|
||||
}
|
||||
|
||||
if len(s.ParentIDs) > 0 {
|
||||
st, err := os.Stat(o.upperPath(s.ParentIDs[0]))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to stat parent")
|
||||
return nil, fmt.Errorf("failed to stat parent: %w", err)
|
||||
}
|
||||
|
||||
stat := st.Sys().(*syscall.Stat_t)
|
||||
@@ -393,13 +393,13 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
|
||||
if rerr := t.Rollback(); rerr != nil {
|
||||
log.G(ctx).WithError(rerr).Warn("failed to rollback transaction")
|
||||
}
|
||||
return nil, errors.Wrap(err, "failed to chown")
|
||||
return nil, fmt.Errorf("failed to chown: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
path = filepath.Join(snapshotDir, s.ID)
|
||||
if err = os.Rename(td, path); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to rename")
|
||||
return nil, fmt.Errorf("failed to rename: %w", err)
|
||||
}
|
||||
td = ""
|
||||
|
||||
@@ -407,7 +407,7 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
|
||||
|
||||
rollback = false
|
||||
if err = t.Commit(); err != nil {
|
||||
return nil, errors.Wrap(err, "commit failed")
|
||||
return nil, fmt.Errorf("commit failed: %w", err)
|
||||
}
|
||||
|
||||
return o.mounts(s, info), nil
|
||||
@@ -416,7 +416,7 @@ func (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, k
|
||||
func (o *snapshotter) prepareDirectory(ctx context.Context, snapshotDir string, kind snapshots.Kind) (string, error) {
|
||||
td, err := ioutil.TempDir(snapshotDir, "new-")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to create temp dir")
|
||||
return "", fmt.Errorf("failed to create temp dir: %w", err)
|
||||
}
|
||||
|
||||
if err := os.Mkdir(filepath.Join(td, "fs"), 0755); err != nil {
|
||||
|
||||
10
vendor/github.com/containerd/fuse-overlayfs-snapshotter/go.mod
generated
vendored
10
vendor/github.com/containerd/fuse-overlayfs-snapshotter/go.mod
generated
vendored
@@ -3,13 +3,9 @@ module github.com/containerd/fuse-overlayfs-snapshotter
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/containerd/containerd v1.5.2
|
||||
github.com/containerd/containerd v1.5.8
|
||||
github.com/containerd/continuity v0.1.0
|
||||
github.com/coreos/go-systemd/v22 v22.1.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/coreos/go-systemd/v22 v22.3.2
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
google.golang.org/grpc v1.33.2
|
||||
)
|
||||
|
||||
// replace grpc to match https://github.com/containerd/containerd/blob/v1.5.2/go.mod
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.27.1
|
||||
|
||||
66
vendor/github.com/containerd/fuse-overlayfs-snapshotter/go.sum
generated
vendored
66
vendor/github.com/containerd/fuse-overlayfs-snapshotter/go.sum
generated
vendored
@@ -1,4 +1,5 @@
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
@@ -50,8 +51,9 @@ github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEY
|
||||
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
|
||||
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||
github.com/Microsoft/hcsshim v0.8.16 h1:8/auA4LFIZFTGrqfKhGBSXwM6/4X1fHa/xniyEHu8ac=
|
||||
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
||||
github.com/Microsoft/hcsshim v0.8.23 h1:47MSwtKGXet80aIn+7h4YI6fwPmwIghAnsx2aOUrG2M=
|
||||
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
@@ -73,6 +75,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
@@ -81,10 +84,12 @@ github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -92,6 +97,9 @@ github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmE
|
||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
||||
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
||||
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
||||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||
@@ -121,12 +129,13 @@ github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX
|
||||
github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ=
|
||||
github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU=
|
||||
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
||||
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
|
||||
github.com/containerd/containerd v1.5.2 h1:MG/Bg1pbmMb61j3wHCFWPxESXHieiKr2xG64px/k8zQ=
|
||||
github.com/containerd/containerd v1.5.2/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
|
||||
github.com/containerd/containerd v1.5.8 h1:NmkCC1/QxyZFBny8JogwLpOy2f+VEbO/f6bV2Mqtwuw=
|
||||
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
@@ -159,8 +168,9 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
|
||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8=
|
||||
github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||
github.com/containerd/ttrpc v1.0.2 h1:2/O3oTZN36q2xRolk0a2WWGgh7/Vf/liElg5hFYLX9U=
|
||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||
github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI=
|
||||
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
|
||||
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
|
||||
@@ -191,8 +201,9 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
@@ -228,7 +239,9 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@@ -262,6 +275,7 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -271,7 +285,6 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -297,8 +310,9 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@@ -308,8 +322,9 @@ 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.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
@@ -351,6 +366,7 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
@@ -440,14 +456,17 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
@@ -502,8 +521,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
@@ -601,6 +621,7 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -619,6 +640,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
||||
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/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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -667,6 +689,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -724,8 +747,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -742,6 +766,7 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/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-20181030221726-6c7e314b6563/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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
@@ -791,6 +816,7 @@ google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
@@ -819,8 +845,21 @@ google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfG
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8=
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -830,8 +869,11 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
1
vendor/github.com/containerd/fuse-overlayfs-snapshotter/plugin/plugin.go
generated
vendored
1
vendor/github.com/containerd/fuse-overlayfs-snapshotter/plugin/plugin.go
generated
vendored
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
|
||||
11
vendor/github.com/containerd/stargz-snapshotter/cache/cache.go
generated
vendored
11
vendor/github.com/containerd/stargz-snapshotter/cache/cache.go
generated
vendored
@@ -132,6 +132,7 @@ func NewDirectoryCache(directory string, config DirectoryCacheConfig) (BlobCache
|
||||
}
|
||||
dataCache = lrucache.New(maxEntry)
|
||||
dataCache.OnEvicted = func(key string, value interface{}) {
|
||||
value.(*bytes.Buffer).Reset()
|
||||
bufPool.Put(value)
|
||||
}
|
||||
}
|
||||
@@ -296,7 +297,6 @@ func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) {
|
||||
}
|
||||
|
||||
b := dc.bufPool.Get().(*bytes.Buffer)
|
||||
b.Reset()
|
||||
memW := &writer{
|
||||
WriteCloser: nopWriteCloser(io.Writer(b)),
|
||||
commitFunc: func() error {
|
||||
@@ -306,7 +306,7 @@ func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) {
|
||||
}
|
||||
cached, done, added := dc.cache.Add(key, b)
|
||||
if !added {
|
||||
dc.bufPool.Put(b) // already exists in the cache. abort it.
|
||||
dc.putBuffer(b) // already exists in the cache. abort it.
|
||||
}
|
||||
commit := func() error {
|
||||
defer done()
|
||||
@@ -331,7 +331,7 @@ func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) {
|
||||
abortFunc: func() error {
|
||||
defer w.Close()
|
||||
defer w.Abort()
|
||||
dc.bufPool.Put(b) // abort it.
|
||||
dc.putBuffer(b) // abort it.
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -339,6 +339,11 @@ func (dc *directoryCache) Add(key string, opts ...Option) (Writer, error) {
|
||||
return memW, nil
|
||||
}
|
||||
|
||||
func (dc *directoryCache) putBuffer(b *bytes.Buffer) {
|
||||
b.Reset()
|
||||
dc.bufPool.Put(b)
|
||||
}
|
||||
|
||||
func (dc *directoryCache) Close() error {
|
||||
dc.closedMu.Lock()
|
||||
defer dc.closedMu.Unlock()
|
||||
|
||||
34
vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
generated
vendored
34
vendor/github.com/containerd/stargz-snapshotter/estargz/estargz.go
generated
vendored
@@ -118,7 +118,7 @@ func Open(sr *io.SectionReader, opt ...OpenOption) (*Reader, error) {
|
||||
}
|
||||
}
|
||||
|
||||
gzipCompressors := []Decompressor{new(GzipDecompressor), new(legacyGzipDecompressor)}
|
||||
gzipCompressors := []Decompressor{new(GzipDecompressor), new(LegacyGzipDecompressor)}
|
||||
decompressors := append(gzipCompressors, opts.decompressors...)
|
||||
|
||||
// Determine the size to fetch. Try to fetch as many bytes as possible.
|
||||
@@ -184,7 +184,7 @@ func OpenFooter(sr *io.SectionReader) (tocOffset int64, footerSize int64, rErr e
|
||||
return 0, 0, fmt.Errorf("error reading footer: %v", err)
|
||||
}
|
||||
var allErr []error
|
||||
for _, d := range []Decompressor{new(GzipDecompressor), new(legacyGzipDecompressor)} {
|
||||
for _, d := range []Decompressor{new(GzipDecompressor), new(LegacyGzipDecompressor)} {
|
||||
fSize := d.FooterSize()
|
||||
fOffset := positive(int64(len(footer)) - fSize)
|
||||
_, tocOffset, _, err := d.ParseFooter(footer[fOffset:])
|
||||
@@ -279,12 +279,12 @@ func (r *Reader) initFields() error {
|
||||
pdir := r.getOrCreateDir(pdirName)
|
||||
ent.NumLink++ // at least one name(ent.Name) references this entry.
|
||||
if ent.Type == "hardlink" {
|
||||
if org, ok := r.m[cleanEntryName(ent.LinkName)]; ok {
|
||||
org.NumLink++ // original entry is referenced by this ent.Name.
|
||||
ent = org
|
||||
} else {
|
||||
return fmt.Errorf("%q is a hardlink but the linkname %q isn't found", ent.Name, ent.LinkName)
|
||||
org, err := r.getSource(ent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
org.NumLink++ // original entry is referenced by this ent.Name.
|
||||
ent = org
|
||||
}
|
||||
pdir.addChild(path.Base(name), ent)
|
||||
}
|
||||
@@ -303,6 +303,20 @@ func (r *Reader) initFields() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Reader) getSource(ent *TOCEntry) (_ *TOCEntry, err error) {
|
||||
if ent.Type == "hardlink" {
|
||||
org, ok := r.m[cleanEntryName(ent.LinkName)]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%q is a hardlink but the linkname %q isn't found", ent.Name, ent.LinkName)
|
||||
}
|
||||
ent, err = r.getSource(org)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return ent, nil
|
||||
}
|
||||
|
||||
func parentDir(p string) string {
|
||||
dir, _ := path.Split(p)
|
||||
return strings.TrimSuffix(dir, "/")
|
||||
@@ -464,7 +478,11 @@ func (r *Reader) Lookup(path string) (e *TOCEntry, ok bool) {
|
||||
}
|
||||
e, ok = r.m[path]
|
||||
if ok && e.Type == "hardlink" {
|
||||
e, ok = r.m[e.LinkName]
|
||||
var err error
|
||||
e, err = r.getSource(e)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
70
vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go
generated
vendored
70
vendor/github.com/containerd/stargz-snapshotter/estargz/gzip.go
generated
vendored
@@ -38,30 +38,34 @@ import (
|
||||
)
|
||||
|
||||
type gzipCompression struct {
|
||||
*gzipCompressor
|
||||
*GzipCompressor
|
||||
*GzipDecompressor
|
||||
}
|
||||
|
||||
func newGzipCompressionWithLevel(level int) Compression {
|
||||
return &gzipCompression{
|
||||
&gzipCompressor{level},
|
||||
&GzipCompressor{level},
|
||||
&GzipDecompressor{},
|
||||
}
|
||||
}
|
||||
|
||||
func NewGzipCompressorWithLevel(level int) Compressor {
|
||||
return &gzipCompressor{level}
|
||||
func NewGzipCompressor() *GzipCompressor {
|
||||
return &GzipCompressor{gzip.BestCompression}
|
||||
}
|
||||
|
||||
type gzipCompressor struct {
|
||||
func NewGzipCompressorWithLevel(level int) *GzipCompressor {
|
||||
return &GzipCompressor{level}
|
||||
}
|
||||
|
||||
type GzipCompressor struct {
|
||||
compressionLevel int
|
||||
}
|
||||
|
||||
func (gc *gzipCompressor) Writer(w io.Writer) (io.WriteCloser, error) {
|
||||
func (gc *GzipCompressor) Writer(w io.Writer) (io.WriteCloser, error) {
|
||||
return gzip.NewWriterLevel(w, gc.compressionLevel)
|
||||
}
|
||||
|
||||
func (gc *gzipCompressor) WriteTOCAndFooter(w io.Writer, off int64, toc *JTOC, diffHash hash.Hash) (digest.Digest, error) {
|
||||
func (gc *GzipCompressor) WriteTOCAndFooter(w io.Writer, off int64, toc *JTOC, diffHash hash.Hash) (digest.Digest, error) {
|
||||
tocJSON, err := json.MarshalIndent(toc, "", "\t")
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -155,17 +159,21 @@ func (gz *GzipDecompressor) FooterSize() int64 {
|
||||
return FooterSize
|
||||
}
|
||||
|
||||
type legacyGzipDecompressor struct{}
|
||||
func (gz *GzipDecompressor) DecompressTOC(r io.Reader) (tocJSON io.ReadCloser, err error) {
|
||||
return decompressTOCEStargz(r)
|
||||
}
|
||||
|
||||
func (gz *legacyGzipDecompressor) Reader(r io.Reader) (io.ReadCloser, error) {
|
||||
type LegacyGzipDecompressor struct{}
|
||||
|
||||
func (gz *LegacyGzipDecompressor) Reader(r io.Reader) (io.ReadCloser, error) {
|
||||
return gzip.NewReader(r)
|
||||
}
|
||||
|
||||
func (gz *legacyGzipDecompressor) ParseTOC(r io.Reader) (toc *JTOC, tocDgst digest.Digest, err error) {
|
||||
func (gz *LegacyGzipDecompressor) ParseTOC(r io.Reader) (toc *JTOC, tocDgst digest.Digest, err error) {
|
||||
return parseTOCEStargz(r)
|
||||
}
|
||||
|
||||
func (gz *legacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOffset, tocSize int64, err error) {
|
||||
func (gz *LegacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOffset, tocSize int64, err error) {
|
||||
if len(p) != legacyFooterSize {
|
||||
return 0, 0, 0, fmt.Errorf("legacy: invalid length %d cannot be parsed", len(p))
|
||||
}
|
||||
@@ -188,29 +196,43 @@ func (gz *legacyGzipDecompressor) ParseFooter(p []byte) (blobPayloadSize, tocOff
|
||||
return tocOffset, tocOffset, 0, nil
|
||||
}
|
||||
|
||||
func (gz *legacyGzipDecompressor) FooterSize() int64 {
|
||||
func (gz *LegacyGzipDecompressor) FooterSize() int64 {
|
||||
return legacyFooterSize
|
||||
}
|
||||
|
||||
func (gz *LegacyGzipDecompressor) DecompressTOC(r io.Reader) (tocJSON io.ReadCloser, err error) {
|
||||
return decompressTOCEStargz(r)
|
||||
}
|
||||
|
||||
func parseTOCEStargz(r io.Reader) (toc *JTOC, tocDgst digest.Digest, err error) {
|
||||
zr, err := gzip.NewReader(r)
|
||||
tr, err := decompressTOCEStargz(r)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("malformed TOC gzip header: %v", err)
|
||||
}
|
||||
defer zr.Close()
|
||||
zr.Multistream(false)
|
||||
tr := tar.NewReader(zr)
|
||||
h, err := tr.Next()
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("failed to find tar header in TOC gzip stream: %v", err)
|
||||
}
|
||||
if h.Name != TOCTarName {
|
||||
return nil, "", fmt.Errorf("TOC tar entry had name %q; expected %q", h.Name, TOCTarName)
|
||||
return nil, "", err
|
||||
}
|
||||
dgstr := digest.Canonical.Digester()
|
||||
toc = new(JTOC)
|
||||
if err := json.NewDecoder(io.TeeReader(tr, dgstr.Hash())).Decode(&toc); err != nil {
|
||||
return nil, "", fmt.Errorf("error decoding TOC JSON: %v", err)
|
||||
}
|
||||
if err := tr.Close(); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return toc, dgstr.Digest(), nil
|
||||
}
|
||||
|
||||
func decompressTOCEStargz(r io.Reader) (tocJSON io.ReadCloser, err error) {
|
||||
zr, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("malformed TOC gzip header: %v", err)
|
||||
}
|
||||
zr.Multistream(false)
|
||||
tr := tar.NewReader(zr)
|
||||
h, err := tr.Next()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find tar header in TOC gzip stream: %v", err)
|
||||
}
|
||||
if h.Name != TOCTarName {
|
||||
return nil, fmt.Errorf("TOC tar entry had name %q; expected %q", h.Name, TOCTarName)
|
||||
}
|
||||
return readCloser{tr, zr.Close}, nil
|
||||
}
|
||||
|
||||
20
vendor/github.com/containerd/stargz-snapshotter/estargz/zstdchunked/zstdchunked.go
generated
vendored
20
vendor/github.com/containerd/stargz-snapshotter/estargz/zstdchunked/zstdchunked.go
generated
vendored
@@ -17,6 +17,7 @@
|
||||
package zstdchunked
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
@@ -88,6 +89,25 @@ func (zz *Decompressor) FooterSize() int64 {
|
||||
return FooterSize
|
||||
}
|
||||
|
||||
func (zz *Decompressor) DecompressTOC(r io.Reader) (tocJSON io.ReadCloser, err error) {
|
||||
decoder, err := zstd.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
br := bufio.NewReader(decoder)
|
||||
if _, err := br.Peek(1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &reader{br, decoder.Close}, nil
|
||||
}
|
||||
|
||||
type reader struct {
|
||||
io.Reader
|
||||
closeFunc func()
|
||||
}
|
||||
|
||||
func (r *reader) Close() error { r.closeFunc(); return nil }
|
||||
|
||||
type zstdReadCloser struct{ *zstd.Decoder }
|
||||
|
||||
func (z *zstdReadCloser) Close() error {
|
||||
|
||||
7
vendor/github.com/containerd/stargz-snapshotter/fs/config/config.go
generated
vendored
7
vendor/github.com/containerd/stargz-snapshotter/fs/config/config.go
generated
vendored
@@ -46,6 +46,7 @@ type Config struct {
|
||||
DisableVerification bool `toml:"disable_verification"`
|
||||
MaxConcurrency int64 `toml:"max_concurrency"`
|
||||
NoPrometheus bool `toml:"no_prometheus"`
|
||||
MetadataStore string `toml:"metadata_store" default:"memory"`
|
||||
|
||||
// BlobConfig is config for layer blob management.
|
||||
BlobConfig `toml:"blob"`
|
||||
@@ -69,13 +70,17 @@ type BlobConfig struct {
|
||||
// If PrefetchChunkSize < ChunkSize prefetch bytes will be fetched as a single http GET,
|
||||
// else total GET requests for prefetch = ceil(PrefetchSize / PrefetchChunkSize).
|
||||
PrefetchChunkSize int64 `toml:"prefetch_chunk_size"`
|
||||
|
||||
MaxRetries int `toml:"max_retries"`
|
||||
MinWaitMSec int `toml:"min_wait_msec"`
|
||||
MaxWaitMSec int `toml:"max_wait_msec"`
|
||||
}
|
||||
|
||||
type DirectoryCacheConfig struct {
|
||||
MaxLRUCacheEntry int `toml:"max_lru_cache_entry"`
|
||||
MaxCacheFds int `toml:"max_cache_fds"`
|
||||
SyncAdd bool `toml:"sync_add"`
|
||||
Direct bool `toml:"direct"`
|
||||
Direct bool `toml:"direct" default:"true"`
|
||||
}
|
||||
|
||||
type FuseConfig struct {
|
||||
|
||||
95
vendor/github.com/containerd/stargz-snapshotter/fs/fs.go
generated
vendored
95
vendor/github.com/containerd/stargz-snapshotter/fs/fs.go
generated
vendored
@@ -53,6 +53,7 @@ import (
|
||||
"github.com/containerd/stargz-snapshotter/fs/layer"
|
||||
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
|
||||
layermetrics "github.com/containerd/stargz-snapshotter/fs/metrics/layer"
|
||||
"github.com/containerd/stargz-snapshotter/fs/remote"
|
||||
"github.com/containerd/stargz-snapshotter/fs/source"
|
||||
"github.com/containerd/stargz-snapshotter/snapshot"
|
||||
"github.com/containerd/stargz-snapshotter/task"
|
||||
@@ -73,7 +74,8 @@ const (
|
||||
type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
getSources source.GetSources
|
||||
getSources source.GetSources
|
||||
resolveHandlers map[string]remote.Handler
|
||||
}
|
||||
|
||||
func WithGetSources(s source.GetSources) Option {
|
||||
@@ -82,6 +84,15 @@ func WithGetSources(s source.GetSources) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithResolveHandler(name string, handler remote.Handler) Option {
|
||||
return func(opts *options) {
|
||||
if opts.resolveHandlers == nil {
|
||||
opts.resolveHandlers = make(map[string]remote.Handler)
|
||||
}
|
||||
opts.resolveHandlers[name] = handler
|
||||
}
|
||||
}
|
||||
|
||||
func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snapshot.FileSystem, err error) {
|
||||
var fsOpts options
|
||||
for _, o := range opts {
|
||||
@@ -109,7 +120,7 @@ func NewFilesystem(root string, cfg config.Config, opts ...Option) (_ snapshot.F
|
||||
})
|
||||
}
|
||||
tm := task.NewBackgroundTaskManager(maxConcurrency, 5*time.Second)
|
||||
r, err := layer.NewResolver(root, tm, cfg)
|
||||
r, err := layer.NewResolver(root, tm, cfg, fsOpts.resolveHandlers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to setup resolver")
|
||||
}
|
||||
@@ -177,6 +188,13 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s
|
||||
return fmt.Errorf("source must be passed")
|
||||
}
|
||||
|
||||
defaultPrefetchSize := fs.prefetchSize
|
||||
if psStr, ok := labels[config.TargetPrefetchSizeLabel]; ok {
|
||||
if ps, err := strconv.ParseInt(psStr, 10, 64); err == nil {
|
||||
defaultPrefetchSize = ps
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the target layer
|
||||
var (
|
||||
resultChan = make(chan layer.Layer)
|
||||
@@ -188,10 +206,10 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s
|
||||
l, err := fs.resolver.Resolve(ctx, s.Hosts, s.Name, s.Target)
|
||||
if err == nil {
|
||||
resultChan <- l
|
||||
fs.prefetch(ctx, l, defaultPrefetchSize, start)
|
||||
return
|
||||
}
|
||||
rErr = errors.Wrapf(rErr, "failed to resolve layer %q from %q: %v",
|
||||
s.Target.Digest, s.Name, err)
|
||||
rErr = errors.Wrapf(rErr, "failed to resolve layer %q from %q: %v", s.Target.Digest, s.Name, err)
|
||||
}
|
||||
errChan <- rErr
|
||||
}()
|
||||
@@ -202,12 +220,17 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s
|
||||
desc := desc
|
||||
go func() {
|
||||
// Avoids to get canceled by client.
|
||||
ctx := log.WithLogger(context.Background(),
|
||||
log.G(ctx).WithField("mountpoint", mountpoint))
|
||||
err := fs.resolver.Cache(ctx, preResolve.Hosts, preResolve.Name, desc)
|
||||
ctx := log.WithLogger(context.Background(), log.G(ctx).WithField("mountpoint", mountpoint))
|
||||
l, err := fs.resolver.Resolve(ctx, preResolve.Hosts, preResolve.Name, desc)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Debug("failed to pre-resolve")
|
||||
return
|
||||
}
|
||||
fs.prefetch(ctx, l, defaultPrefetchSize, start)
|
||||
|
||||
// Release this layer because this isn't target and we don't use it anymore here.
|
||||
// However, this will remain on the resolver cache until eviction.
|
||||
l.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -255,7 +278,7 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s
|
||||
// Verification must be done. Don't mount this layer.
|
||||
return fmt.Errorf("digest of TOC JSON must be passed")
|
||||
}
|
||||
node, err := l.RootNode()
|
||||
node, err := l.RootNode(0)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("Failed to get root node")
|
||||
return errors.Wrapf(err, "failed to get root node")
|
||||
@@ -263,7 +286,7 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s
|
||||
|
||||
// Measuring duration of Mount operation for resolved layer.
|
||||
digest := l.Info().Digest // get layer sha
|
||||
defer commonmetrics.MeasureLatency(commonmetrics.Mount, digest, start)
|
||||
defer commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.Mount, digest, start)
|
||||
|
||||
// Register the mountpoint layer
|
||||
fs.layerMu.Lock()
|
||||
@@ -271,41 +294,6 @@ func (fs *filesystem) Mount(ctx context.Context, mountpoint string, labels map[s
|
||||
fs.layerMu.Unlock()
|
||||
fs.metricsController.Add(mountpoint, l)
|
||||
|
||||
// Prefetch this layer. We prefetch several layers in parallel. The first
|
||||
// Check() for this layer waits for the prefetch completion.
|
||||
if !fs.noprefetch {
|
||||
prefetchSize := fs.prefetchSize
|
||||
if psStr, ok := labels[config.TargetPrefetchSizeLabel]; ok {
|
||||
if ps, err := strconv.ParseInt(psStr, 10, 64); err == nil {
|
||||
prefetchSize = ps
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
fs.backgroundTaskManager.DoPrioritizedTask()
|
||||
defer fs.backgroundTaskManager.DonePrioritizedTask()
|
||||
if err := l.Prefetch(prefetchSize); err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("failed to prefetch layer=%v", digest)
|
||||
return
|
||||
}
|
||||
log.G(ctx).Debug("completed to prefetch")
|
||||
}()
|
||||
}
|
||||
|
||||
// Fetch whole layer aggressively in background. We use background
|
||||
// reader for this so prioritized tasks(Mount, Check, etc...) can
|
||||
// interrupt the reading. This can avoid disturbing prioritized tasks
|
||||
// about NW traffic.
|
||||
if !fs.noBackgroundFetch {
|
||||
go func() {
|
||||
if err := l.BackgroundFetch(); err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("failed to fetch whole layer=%v", digest)
|
||||
return
|
||||
}
|
||||
commonmetrics.LogLatencyForLastOnDemandFetch(ctx, digest, start, l.Info().ReadTime) // write log record for the latency between mount start and last on demand fetch
|
||||
log.G(ctx).Debug("completed to fetch all layer data in background")
|
||||
}()
|
||||
}
|
||||
|
||||
// mount the node to the specified mountpoint
|
||||
// TODO: bind mount the state directory as a read-only fs on snapshotter's side
|
||||
rawFS := fusefs.NewNodeFS(node, &fusefs.Options{
|
||||
@@ -341,7 +329,7 @@ func (fs *filesystem) Check(ctx context.Context, mountpoint string, labels map[s
|
||||
fs.backgroundTaskManager.DoPrioritizedTask()
|
||||
defer fs.backgroundTaskManager.DonePrioritizedTask()
|
||||
|
||||
defer commonmetrics.MeasureLatency(commonmetrics.PrefetchesCompleted, digest.FromString(""), time.Now()) // measuring the time the container launch is blocked on prefetch to complete
|
||||
defer commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.PrefetchesCompleted, digest.FromString(""), time.Now()) // measuring the time the container launch is blocked on prefetch to complete
|
||||
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("mountpoint", mountpoint))
|
||||
|
||||
@@ -422,6 +410,23 @@ func (fs *filesystem) Unmount(ctx context.Context, mountpoint string) error {
|
||||
return syscall.Unmount(mountpoint, syscall.MNT_FORCE)
|
||||
}
|
||||
|
||||
func (fs *filesystem) prefetch(ctx context.Context, l layer.Layer, defaultPrefetchSize int64, start time.Time) {
|
||||
// Prefetch a layer. The first Check() for this layer waits for the prefetch completion.
|
||||
if !fs.noprefetch {
|
||||
go l.Prefetch(defaultPrefetchSize)
|
||||
}
|
||||
|
||||
// Fetch whole layer aggressively in background.
|
||||
if !fs.noBackgroundFetch {
|
||||
go func() {
|
||||
if err := l.BackgroundFetch(); err == nil {
|
||||
// write log record for the latency between mount start and last on demand fetch
|
||||
commonmetrics.LogLatencyForLastOnDemandFetch(ctx, l.Info().Digest, start, l.Info().ReadTime)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// neighboringLayers returns layer descriptors except the `target` layer in the specified manifest.
|
||||
func neighboringLayers(manifest ocispec.Manifest, target ocispec.Descriptor) (descs []ocispec.Descriptor) {
|
||||
for _, desc := range manifest.Layers {
|
||||
|
||||
166
vendor/github.com/containerd/stargz-snapshotter/fs/layer/layer.go
generated
vendored
166
vendor/github.com/containerd/stargz-snapshotter/fs/layer/layer.go
generated
vendored
@@ -37,11 +37,15 @@ import (
|
||||
"github.com/containerd/containerd/reference"
|
||||
"github.com/containerd/stargz-snapshotter/cache"
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
"github.com/containerd/stargz-snapshotter/estargz/zstdchunked"
|
||||
"github.com/containerd/stargz-snapshotter/fs/config"
|
||||
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
|
||||
"github.com/containerd/stargz-snapshotter/fs/reader"
|
||||
"github.com/containerd/stargz-snapshotter/fs/remote"
|
||||
"github.com/containerd/stargz-snapshotter/fs/source"
|
||||
"github.com/containerd/stargz-snapshotter/metadata"
|
||||
dbmetadata "github.com/containerd/stargz-snapshotter/metadata/db"
|
||||
memorymetadata "github.com/containerd/stargz-snapshotter/metadata/memory"
|
||||
"github.com/containerd/stargz-snapshotter/task"
|
||||
"github.com/containerd/stargz-snapshotter/util/lrucache"
|
||||
"github.com/containerd/stargz-snapshotter/util/namedmutex"
|
||||
@@ -50,6 +54,7 @@ import (
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -58,6 +63,8 @@ const (
|
||||
defaultMaxCacheFds = 10
|
||||
defaultPrefetchTimeoutSec = 10
|
||||
memoryCacheType = "memory"
|
||||
memoryMetadataType = "memory"
|
||||
dbMetadataType = "db"
|
||||
)
|
||||
|
||||
// Layer represents a layer.
|
||||
@@ -66,7 +73,7 @@ type Layer interface {
|
||||
Info() Info
|
||||
|
||||
// RootNode returns the root node of this layer.
|
||||
RootNode() (fusefs.InodeEmbedder, error)
|
||||
RootNode(baseInode uint32) (fusefs.InodeEmbedder, error)
|
||||
|
||||
// Check checks if the layer is still connectable.
|
||||
Check() error
|
||||
@@ -75,14 +82,15 @@ type Layer interface {
|
||||
Refresh(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error
|
||||
|
||||
// Verify verifies this layer using the passed TOC Digest.
|
||||
// Nop if Verify() or SkipVerify() was already called.
|
||||
Verify(tocDigest digest.Digest) (err error)
|
||||
|
||||
// SkipVerify skips verification for this layer.
|
||||
// Nop if Verify() or SkipVerify() was already called.
|
||||
SkipVerify()
|
||||
|
||||
// Prefetch prefetches the specified size. If the layer is eStargz and contains landmark files,
|
||||
// the range indicated by these files is respected.
|
||||
// Calling this function before calling Verify or SkipVerify will fail.
|
||||
Prefetch(prefetchSize int64) error
|
||||
|
||||
// ReadAt reads this layer.
|
||||
@@ -93,7 +101,6 @@ type Layer interface {
|
||||
|
||||
// BackgroundFetch fetches the entire layer contents to the cache.
|
||||
// Fetching contents is done as a background task.
|
||||
// Calling this function before calling Verify or SkipVerify will fail.
|
||||
BackgroundFetch() error
|
||||
|
||||
// Done releases the reference to this layer. The resources related to this layer will be
|
||||
@@ -122,10 +129,11 @@ type Resolver struct {
|
||||
backgroundTaskManager *task.BackgroundTaskManager
|
||||
resolveLock *namedmutex.NamedMutex
|
||||
config config.Config
|
||||
newMetadataReader func(sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error)
|
||||
}
|
||||
|
||||
// NewResolver returns a new layer resolver.
|
||||
func NewResolver(root string, backgroundTaskManager *task.BackgroundTaskManager, cfg config.Config) (*Resolver, error) {
|
||||
func NewResolver(root string, backgroundTaskManager *task.BackgroundTaskManager, cfg config.Config, resolveHandlers map[string]remote.Handler) (*Resolver, error) {
|
||||
resolveResultEntry := cfg.ResolveResultEntry
|
||||
if resolveResultEntry == 0 {
|
||||
resolveResultEntry = defaultResolveResultEntry
|
||||
@@ -158,15 +166,42 @@ func NewResolver(root string, backgroundTaskManager *task.BackgroundTaskManager,
|
||||
logrus.WithField("key", key).Debugf("cleaned up blob")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(root, 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var newReader func(sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error)
|
||||
switch cfg.MetadataStore {
|
||||
case "", memoryMetadataType:
|
||||
newReader = memorymetadata.NewReader
|
||||
case dbMetadataType:
|
||||
bOpts := bolt.Options{
|
||||
NoFreelistSync: true,
|
||||
InitialMmapSize: 64 * 1024 * 1024,
|
||||
FreelistType: bolt.FreelistMapType,
|
||||
}
|
||||
db, err := bolt.Open(filepath.Join(root, "metadata.db"), 0600, &bOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newReader = func(sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error) {
|
||||
return dbmetadata.NewReader(db, sr, opts...)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown metadata store type: %v; must be %v or %v",
|
||||
cfg.MetadataStore, memoryMetadataType, dbMetadataType)
|
||||
}
|
||||
|
||||
return &Resolver{
|
||||
rootDir: root,
|
||||
resolver: remote.NewResolver(cfg.BlobConfig),
|
||||
resolver: remote.NewResolver(cfg.BlobConfig, resolveHandlers),
|
||||
layerCache: layerCache,
|
||||
blobCache: blobCache,
|
||||
prefetchTimeout: prefetchTimeout,
|
||||
backgroundTaskManager: backgroundTaskManager,
|
||||
config: cfg,
|
||||
resolveLock: new(namedmutex.NamedMutex),
|
||||
newMetadataReader: newReader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -192,6 +227,7 @@ func newCache(root string, cacheType string, cfg config.Config) (cache.BlobCache
|
||||
}
|
||||
dCache, fCache := lrucache.New(maxDataEntry), lrucache.New(maxFdEntry)
|
||||
dCache.OnEvicted = func(key string, value interface{}) {
|
||||
value.(*bytes.Buffer).Reset()
|
||||
bufPool.Put(value)
|
||||
}
|
||||
fCache.OnEvicted = func(key string, value interface{}) {
|
||||
@@ -218,7 +254,7 @@ func newCache(root string, cacheType string, cfg config.Config) (cache.BlobCache
|
||||
}
|
||||
|
||||
// Resolve resolves a layer based on the passed layer blob information.
|
||||
func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor, esgzOpts ...estargz.OpenOption) (_ Layer, retErr error) {
|
||||
func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor, esgzOpts ...metadata.Option) (_ Layer, retErr error) {
|
||||
name := refspec.String() + "/" + desc.Digest.String()
|
||||
|
||||
// Wait if resolving this layer is already running. The result
|
||||
@@ -277,18 +313,23 @@ func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refs
|
||||
return blobR.ReadAt(p, offset)
|
||||
}), 0, blobR.Size())
|
||||
// define telemetry hooks to measure latency metrics inside estargz package
|
||||
telemetry := estargz.Telemetry{
|
||||
telemetry := metadata.Telemetry{
|
||||
GetFooterLatency: func(start time.Time) {
|
||||
commonmetrics.MeasureLatency(commonmetrics.StargzFooterGet, desc.Digest, start)
|
||||
commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.StargzFooterGet, desc.Digest, start)
|
||||
},
|
||||
GetTocLatency: func(start time.Time) {
|
||||
commonmetrics.MeasureLatency(commonmetrics.StargzTocGet, desc.Digest, start)
|
||||
commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.StargzTocGet, desc.Digest, start)
|
||||
},
|
||||
DeserializeTocLatency: func(start time.Time) {
|
||||
commonmetrics.MeasureLatency(commonmetrics.DeserializeTocJSON, desc.Digest, start)
|
||||
commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.DeserializeTocJSON, desc.Digest, start)
|
||||
},
|
||||
}
|
||||
vr, err := reader.NewReader(sr, fsCache, desc.Digest, &telemetry, esgzOpts...)
|
||||
meta, err := r.newMetadataReader(sr,
|
||||
append(esgzOpts, metadata.WithTelemetry(&telemetry), metadata.WithDecompressors(new(zstdchunked.Decompressor)))...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vr, err := reader.NewReader(meta, fsCache, desc.Digest)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read layer")
|
||||
}
|
||||
@@ -349,18 +390,6 @@ func (r *Resolver) resolveBlob(ctx context.Context, hosts source.RegistryHosts,
|
||||
return &blobRef{cachedB.(remote.Blob), done}, nil
|
||||
}
|
||||
|
||||
// Cache is similar to Resolve but the result isn't returned. Instead, it'll be stored in the cache.
|
||||
func (r *Resolver) Cache(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) error {
|
||||
l, err := r.Resolve(ctx, hosts, refspec, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Release this layer. However, this will remain on the cache until eviction.
|
||||
// Until then, the client can reuse this (already pre-resolved) layer.
|
||||
l.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
func newLayer(
|
||||
resolver *Resolver,
|
||||
desc ocispec.Descriptor,
|
||||
@@ -390,15 +419,22 @@ type layer struct {
|
||||
|
||||
closed bool
|
||||
closedMu sync.Mutex
|
||||
|
||||
prefetchOnce sync.Once
|
||||
backgroundFetchOnce sync.Once
|
||||
}
|
||||
|
||||
func (l *layer) Info() Info {
|
||||
var readTime time.Time
|
||||
if l.r != nil {
|
||||
readTime = l.r.LastOnDemandReadTime()
|
||||
}
|
||||
return Info{
|
||||
Digest: l.desc.Digest,
|
||||
Size: l.blob.Size(),
|
||||
FetchedSize: l.blob.FetchedSize(),
|
||||
PrefetchSize: l.prefetchedSize(),
|
||||
ReadTime: l.r.LastOnDemandReadTime(),
|
||||
ReadTime: readTime,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,36 +463,57 @@ func (l *layer) Verify(tocDigest digest.Digest) (err error) {
|
||||
if l.isClosed() {
|
||||
return fmt.Errorf("layer is already closed")
|
||||
}
|
||||
if l.r != nil {
|
||||
return nil
|
||||
}
|
||||
l.r, err = l.verifiableReader.VerifyTOC(tocDigest)
|
||||
return
|
||||
}
|
||||
|
||||
func (l *layer) SkipVerify() {
|
||||
if l.r != nil {
|
||||
return
|
||||
}
|
||||
l.r = l.verifiableReader.SkipVerify()
|
||||
}
|
||||
|
||||
func (l *layer) Prefetch(prefetchSize int64) error {
|
||||
func (l *layer) Prefetch(prefetchSize int64) (err error) {
|
||||
l.prefetchOnce.Do(func() {
|
||||
ctx := context.Background()
|
||||
l.resolver.backgroundTaskManager.DoPrioritizedTask()
|
||||
defer l.resolver.backgroundTaskManager.DonePrioritizedTask()
|
||||
err = l.prefetch(ctx, prefetchSize)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("failed to prefetch layer=%v", l.desc.Digest)
|
||||
return
|
||||
}
|
||||
log.G(ctx).Debug("completed to prefetch")
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (l *layer) prefetch(ctx context.Context, prefetchSize int64) error {
|
||||
defer l.prefetchWaiter.done() // Notify the completion
|
||||
ctx := context.Background()
|
||||
// Measuring the total time to complete prefetch (use defer func() because l.Info().PrefetchSize is set later)
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
commonmetrics.WriteLatencyWithBytesLogValue(ctx, l.Info().Digest, commonmetrics.PrefetchTotal, start, commonmetrics.PrefetchSize, l.Info().PrefetchSize)
|
||||
commonmetrics.WriteLatencyWithBytesLogValue(ctx, l.desc.Digest, commonmetrics.PrefetchTotal, start, commonmetrics.PrefetchSize, l.prefetchedSize())
|
||||
}()
|
||||
|
||||
if l.isClosed() {
|
||||
return fmt.Errorf("layer is already closed")
|
||||
}
|
||||
if l.r == nil {
|
||||
return fmt.Errorf("layer hasn't been verified yet")
|
||||
}
|
||||
lr := l.r
|
||||
if _, ok := lr.Lookup(estargz.NoPrefetchLandmark); ok {
|
||||
rootID := l.verifiableReader.Metadata().RootID()
|
||||
if _, _, err := l.verifiableReader.Metadata().GetChild(rootID, estargz.NoPrefetchLandmark); err == nil {
|
||||
// do not prefetch this layer
|
||||
return nil
|
||||
} else if e, ok := lr.Lookup(estargz.PrefetchLandmark); ok {
|
||||
} else if id, _, err := l.verifiableReader.Metadata().GetChild(rootID, estargz.PrefetchLandmark); err == nil {
|
||||
offset, err := l.verifiableReader.Metadata().GetOffset(id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get offset of prefetch landmark")
|
||||
}
|
||||
// override the prefetch size with optimized value
|
||||
prefetchSize = e.Offset
|
||||
prefetchSize = offset
|
||||
} else if prefetchSize > l.blob.Size() {
|
||||
// adjust prefetch size not to exceed the whole layer size
|
||||
prefetchSize = l.blob.Size()
|
||||
@@ -465,7 +522,7 @@ func (l *layer) Prefetch(prefetchSize int64) error {
|
||||
// Fetch the target range
|
||||
downloadStart := time.Now()
|
||||
err := l.blob.Cache(0, prefetchSize)
|
||||
commonmetrics.WriteLatencyLogValue(ctx, l.Info().Digest, commonmetrics.PrefetchDownload, downloadStart) // time to download prefetch data
|
||||
commonmetrics.WriteLatencyLogValue(ctx, l.desc.Digest, commonmetrics.PrefetchDownload, downloadStart) // time to download prefetch data
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to prefetch layer")
|
||||
@@ -478,11 +535,10 @@ func (l *layer) Prefetch(prefetchSize int64) error {
|
||||
|
||||
// Cache uncompressed contents of the prefetched range
|
||||
decompressStart := time.Now()
|
||||
err = lr.Cache(reader.WithFilter(func(e *estargz.TOCEntry) bool {
|
||||
return e.Offset < prefetchSize // Cache only prefetch target
|
||||
err = l.verifiableReader.Cache(reader.WithFilter(func(offset int64) bool {
|
||||
return offset < prefetchSize // Cache only prefetch target
|
||||
}))
|
||||
commonmetrics.WriteLatencyLogValue(ctx, l.Info().Digest, commonmetrics.PrefetchDecompress, decompressStart) // time to decompress prefetch data
|
||||
|
||||
commonmetrics.WriteLatencyLogValue(ctx, l.desc.Digest, commonmetrics.PrefetchDecompress, decompressStart) // time to decompress prefetch data
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to cache prefetched layer")
|
||||
}
|
||||
@@ -497,20 +553,28 @@ func (l *layer) WaitForPrefetchCompletion() error {
|
||||
return l.prefetchWaiter.wait(l.resolver.prefetchTimeout)
|
||||
}
|
||||
|
||||
func (l *layer) BackgroundFetch() error {
|
||||
ctx := context.Background()
|
||||
defer commonmetrics.WriteLatencyLogValue(ctx, l.Info().Digest, commonmetrics.BackgroundFetchTotal, time.Now())
|
||||
func (l *layer) BackgroundFetch() (err error) {
|
||||
l.backgroundFetchOnce.Do(func() {
|
||||
ctx := context.Background()
|
||||
err = l.backgroundFetch(ctx)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("failed to fetch whole layer=%v", l.desc.Digest)
|
||||
return
|
||||
}
|
||||
log.G(ctx).Debug("completed to fetch all layer data in background")
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (l *layer) backgroundFetch(ctx context.Context) error {
|
||||
defer commonmetrics.WriteLatencyLogValue(ctx, l.desc.Digest, commonmetrics.BackgroundFetchTotal, time.Now())
|
||||
if l.isClosed() {
|
||||
return fmt.Errorf("layer is already closed")
|
||||
}
|
||||
if l.r == nil {
|
||||
return fmt.Errorf("layer hasn't been verified yet")
|
||||
}
|
||||
lr := l.r
|
||||
br := io.NewSectionReader(readerAtFunc(func(p []byte, offset int64) (retN int, retErr error) {
|
||||
l.resolver.backgroundTaskManager.InvokeBackgroundTask(func(ctx context.Context) {
|
||||
// Measuring the time to download background fetch data (in milliseconds)
|
||||
defer commonmetrics.MeasureLatency(commonmetrics.BackgroundFetchDownload, l.Info().Digest, time.Now()) // time to download background fetch data
|
||||
defer commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.BackgroundFetchDownload, l.Info().Digest, time.Now()) // time to download background fetch data
|
||||
retN, retErr = l.blob.ReadAt(
|
||||
p,
|
||||
offset,
|
||||
@@ -520,8 +584,8 @@ func (l *layer) BackgroundFetch() error {
|
||||
}, 120*time.Second)
|
||||
return
|
||||
}), 0, l.blob.Size())
|
||||
defer commonmetrics.WriteLatencyLogValue(ctx, l.Info().Digest, commonmetrics.BackgroundFetchDecompress, time.Now()) // time to decompress background fetch data (in milliseconds)
|
||||
return lr.Cache(
|
||||
defer commonmetrics.WriteLatencyLogValue(ctx, l.desc.Digest, commonmetrics.BackgroundFetchDecompress, time.Now()) // time to decompress background fetch data (in milliseconds)
|
||||
return l.verifiableReader.Cache(
|
||||
reader.WithReader(br), // Read contents in background
|
||||
reader.WithCacheOpts(cache.Direct()), // Do not pollute mem cache
|
||||
)
|
||||
@@ -531,14 +595,14 @@ func (l *layerRef) Done() {
|
||||
l.done()
|
||||
}
|
||||
|
||||
func (l *layer) RootNode() (fusefs.InodeEmbedder, error) {
|
||||
func (l *layer) RootNode(baseInode uint32) (fusefs.InodeEmbedder, error) {
|
||||
if l.isClosed() {
|
||||
return nil, fmt.Errorf("layer is already closed")
|
||||
}
|
||||
if l.r == nil {
|
||||
return nil, fmt.Errorf("layer hasn't been verified yet")
|
||||
}
|
||||
return newNode(l.desc.Digest, l.r, l.blob)
|
||||
return newNode(l.desc.Digest, l.r, l.blob, baseInode)
|
||||
}
|
||||
|
||||
func (l *layer) ReadAt(p []byte, offset int64, opts ...remote.Option) (int, error) {
|
||||
|
||||
353
vendor/github.com/containerd/stargz-snapshotter/fs/layer/node.go
generated
vendored
353
vendor/github.com/containerd/stargz-snapshotter/fs/layer/node.go
generated
vendored
@@ -26,6 +26,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -34,15 +35,17 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
|
||||
"github.com/containerd/stargz-snapshotter/fs/reader"
|
||||
"github.com/containerd/stargz-snapshotter/fs/remote"
|
||||
"github.com/containerd/stargz-snapshotter/metadata"
|
||||
fusefs "github.com/hanwen/go-fuse/v2/fs"
|
||||
"github.com/hanwen/go-fuse/v2/fuse"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -58,27 +61,70 @@ const (
|
||||
|
||||
var opaqueXattrs = []string{"trusted.overlay.opaque", "user.overlay.opaque"}
|
||||
|
||||
func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob) (fusefs.InodeEmbedder, error) {
|
||||
root, ok := r.Lookup("")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to get a TOCEntry of the root")
|
||||
func newNode(layerDgst digest.Digest, r reader.Reader, blob remote.Blob, baseInode uint32) (fusefs.InodeEmbedder, error) {
|
||||
rootID := r.Metadata().RootID()
|
||||
rootAttr, err := r.Metadata().GetAttr(rootID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ffs := &fs{
|
||||
r: r,
|
||||
layerDigest: layerDgst,
|
||||
baseInode: baseInode,
|
||||
rootID: rootID,
|
||||
}
|
||||
ffs.s = ffs.newState(layerDgst, blob)
|
||||
return &node{
|
||||
r: r,
|
||||
e: root,
|
||||
s: newState(layerDgst, blob),
|
||||
layerSha: layerDgst,
|
||||
id: rootID,
|
||||
attr: rootAttr,
|
||||
fs: ffs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// fs contains global metadata used by nodes
|
||||
type fs struct {
|
||||
r reader.Reader
|
||||
s *state
|
||||
layerDigest digest.Digest
|
||||
baseInode uint32
|
||||
rootID uint32
|
||||
}
|
||||
|
||||
func (fs *fs) inodeOfState() uint64 {
|
||||
return (uint64(fs.baseInode) << 32) | 1 // reserved
|
||||
}
|
||||
|
||||
func (fs *fs) inodeOfStatFile() uint64 {
|
||||
return (uint64(fs.baseInode) << 32) | 2 // reserved
|
||||
}
|
||||
|
||||
func (fs *fs) inodeOfID(id uint32) (uint64, error) {
|
||||
// 0 is reserved by go-fuse 1 and 2 are reserved by the state dir
|
||||
if id > ^uint32(0)-3 {
|
||||
return 0, fmt.Errorf("too many inodes")
|
||||
}
|
||||
return (uint64(fs.baseInode) << 32) | uint64(3+id), nil
|
||||
}
|
||||
|
||||
// node is a filesystem inode abstraction.
|
||||
type node struct {
|
||||
fusefs.Inode
|
||||
r reader.Reader
|
||||
e *estargz.TOCEntry
|
||||
s *state
|
||||
layerSha digest.Digest
|
||||
opaque bool // true if this node is an overlayfs opaque directory
|
||||
fs *fs
|
||||
id uint32
|
||||
attr metadata.Attr
|
||||
ents []fuse.DirEntry
|
||||
entsCached bool
|
||||
}
|
||||
|
||||
func (n *node) isRootNode() bool {
|
||||
return n.id == n.fs.rootID
|
||||
}
|
||||
|
||||
func (n *node) isOpaque() bool {
|
||||
if _, _, err := n.fs.r.Metadata().GetChild(n.id, whiteoutOpaqueDir); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var _ = (fusefs.InodeEmbedder)((*node)(nil))
|
||||
@@ -86,47 +132,75 @@ var _ = (fusefs.InodeEmbedder)((*node)(nil))
|
||||
var _ = (fusefs.NodeReaddirer)((*node)(nil))
|
||||
|
||||
func (n *node) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) {
|
||||
// Measure how long node_readdir operation takes.
|
||||
ents, errno := n.readdir()
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
return fusefs.NewListDirStream(ents), 0
|
||||
}
|
||||
|
||||
func (n *node) readdir() ([]fuse.DirEntry, syscall.Errno) {
|
||||
// Measure how long node_readdir operation takes (in microseconds).
|
||||
start := time.Now() // set start time
|
||||
defer commonmetrics.MeasureLatency(commonmetrics.NodeReaddir, n.layerSha, start)
|
||||
defer commonmetrics.MeasureLatencyInMicroseconds(commonmetrics.NodeReaddir, n.fs.layerDigest, start)
|
||||
|
||||
if n.entsCached {
|
||||
return n.ents, 0
|
||||
}
|
||||
|
||||
isRoot := n.isRootNode()
|
||||
|
||||
var ents []fuse.DirEntry
|
||||
whiteouts := map[string]*estargz.TOCEntry{}
|
||||
whiteouts := map[string]uint32{}
|
||||
normalEnts := map[string]bool{}
|
||||
n.e.ForeachChild(func(baseName string, ent *estargz.TOCEntry) bool {
|
||||
var lastErr error
|
||||
if err := n.fs.r.Metadata().ForeachChild(n.id, func(name string, id uint32, mode os.FileMode) bool {
|
||||
|
||||
// We don't want to show prefetch landmarks in "/".
|
||||
if n.e.Name == "" && (baseName == estargz.PrefetchLandmark || baseName == estargz.NoPrefetchLandmark) {
|
||||
if isRoot && (name == estargz.PrefetchLandmark || name == estargz.NoPrefetchLandmark) {
|
||||
return true
|
||||
}
|
||||
|
||||
// We don't want to show whiteouts.
|
||||
if strings.HasPrefix(baseName, whiteoutPrefix) {
|
||||
if baseName == whiteoutOpaqueDir {
|
||||
if strings.HasPrefix(name, whiteoutPrefix) {
|
||||
if name == whiteoutOpaqueDir {
|
||||
return true
|
||||
}
|
||||
// Add the overlayfs-compiant whiteout later.
|
||||
whiteouts[baseName] = ent
|
||||
whiteouts[name] = id
|
||||
return true
|
||||
}
|
||||
|
||||
// This is a normal entry.
|
||||
normalEnts[baseName] = true
|
||||
normalEnts[name] = true
|
||||
ino, err := n.fs.inodeOfID(id)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
return false
|
||||
}
|
||||
ents = append(ents, fuse.DirEntry{
|
||||
Mode: modeOfEntry(ent),
|
||||
Name: baseName,
|
||||
Ino: inodeOfEnt(ent),
|
||||
Mode: fileModeToSystemMode(mode),
|
||||
Name: name,
|
||||
Ino: ino,
|
||||
})
|
||||
return true
|
||||
})
|
||||
}); err != nil || lastErr != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Readdir: err = %v; lastErr = %v", err, lastErr))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
|
||||
// Append whiteouts if no entry replaces the target entry in the lower layer.
|
||||
for w, ent := range whiteouts {
|
||||
for w, id := range whiteouts {
|
||||
if !normalEnts[w[len(whiteoutPrefix):]] {
|
||||
ino, err := n.fs.inodeOfID(id)
|
||||
if err != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Readdir: err = %v; lastErr = %v", err, lastErr))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
ents = append(ents, fuse.DirEntry{
|
||||
Mode: syscall.S_IFCHR,
|
||||
Name: w[len(whiteoutPrefix):],
|
||||
Ino: inodeOfEnt(ent),
|
||||
Ino: ino,
|
||||
})
|
||||
|
||||
}
|
||||
@@ -136,15 +210,19 @@ func (n *node) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) {
|
||||
sort.Slice(ents, func(i, j int) bool {
|
||||
return ents[i].Name < ents[j].Name
|
||||
})
|
||||
n.ents, n.entsCached = ents, true // cache it
|
||||
|
||||
return fusefs.NewListDirStream(ents), 0
|
||||
return ents, 0
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeLookuper)((*node)(nil))
|
||||
|
||||
func (n *node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fusefs.Inode, syscall.Errno) {
|
||||
|
||||
isRoot := n.isRootNode()
|
||||
|
||||
// We don't want to show prefetch landmarks in "/".
|
||||
if n.e.Name == "" && (name == estargz.PrefetchLandmark || name == estargz.NoPrefetchLandmark) {
|
||||
if isRoot && (name == estargz.PrefetchLandmark || name == estargz.NoPrefetchLandmark) {
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
@@ -154,63 +232,111 @@ func (n *node) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fu
|
||||
}
|
||||
|
||||
// state directory
|
||||
if n.e.Name == "" && name == stateDirName {
|
||||
return n.NewInode(ctx, n.s, stateToAttr(n.s, &out.Attr)), 0
|
||||
if isRoot && name == stateDirName {
|
||||
return n.NewInode(ctx, n.fs.s, n.fs.stateToAttr(&out.Attr)), 0
|
||||
}
|
||||
|
||||
// lookup stargz TOCEntry
|
||||
ce, ok := n.e.LookupChild(name)
|
||||
if !ok {
|
||||
// If the entry exists as a whiteout, show an overlayfs-styled whiteout node.
|
||||
if wh, ok := n.e.LookupChild(fmt.Sprintf("%s%s", whiteoutPrefix, name)); ok {
|
||||
return n.NewInode(ctx, &whiteout{
|
||||
e: wh,
|
||||
}, entryToWhAttr(wh, &out.Attr)), 0
|
||||
// lookup on memory nodes
|
||||
if cn := n.GetChild(name); cn != nil {
|
||||
switch tn := cn.Operations().(type) {
|
||||
case *node:
|
||||
ino, err := n.fs.inodeOfID(tn.id)
|
||||
if err != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Lookup: %v", err))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
entryToAttr(ino, tn.attr, &out.Attr)
|
||||
case *whiteout:
|
||||
ino, err := n.fs.inodeOfID(tn.id)
|
||||
if err != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Lookup: %v", err))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
entryToAttr(ino, tn.attr, &out.Attr)
|
||||
default:
|
||||
n.fs.s.report(fmt.Errorf("node.Lookup: uknown node type detected"))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
return cn, 0
|
||||
}
|
||||
|
||||
// early return if this entry doesn't exist
|
||||
if n.entsCached {
|
||||
var found bool
|
||||
for _, e := range n.ents {
|
||||
if e.Name == name {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
}
|
||||
|
||||
id, ce, err := n.fs.r.Metadata().GetChild(n.id, name)
|
||||
if err != nil {
|
||||
// If the entry exists as a whiteout, show an overlayfs-styled whiteout node.
|
||||
if whID, wh, err := n.fs.r.Metadata().GetChild(n.id, fmt.Sprintf("%s%s", whiteoutPrefix, name)); err == nil {
|
||||
ino, err := n.fs.inodeOfID(whID)
|
||||
if err != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Lookup: %v", err))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
return n.NewInode(ctx, &whiteout{
|
||||
id: whID,
|
||||
fs: n.fs,
|
||||
attr: wh,
|
||||
}, entryToWhAttr(ino, wh, &out.Attr)), 0
|
||||
}
|
||||
n.readdir() // This code path is very expensive. Cache child entries here so that the next call don't reach here.
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
var opaque bool
|
||||
if _, ok := ce.LookupChild(whiteoutOpaqueDir); ok {
|
||||
// This entry is an opaque directory so make it recognizable for overlayfs.
|
||||
opaque = true
|
||||
}
|
||||
|
||||
ino, err := n.fs.inodeOfID(id)
|
||||
if err != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Lookup: %v", err))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
return n.NewInode(ctx, &node{
|
||||
r: n.r,
|
||||
e: ce,
|
||||
s: n.s,
|
||||
layerSha: n.layerSha,
|
||||
opaque: opaque,
|
||||
}, entryToAttr(ce, &out.Attr)), 0
|
||||
id: id,
|
||||
fs: n.fs,
|
||||
attr: ce,
|
||||
}, entryToAttr(ino, ce, &out.Attr)), 0
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeOpener)((*node)(nil))
|
||||
|
||||
func (n *node) Open(ctx context.Context, flags uint32) (fh fusefs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
|
||||
ra, err := n.r.OpenFile(n.e.Name)
|
||||
ra, err := n.fs.r.OpenFile(n.id)
|
||||
if err != nil {
|
||||
n.s.report(fmt.Errorf("failed to open node: %v", err))
|
||||
n.fs.s.report(fmt.Errorf("node.Open: %v", err))
|
||||
return nil, 0, syscall.EIO
|
||||
}
|
||||
return &file{
|
||||
n: n,
|
||||
e: n.e,
|
||||
ra: ra,
|
||||
}, 0, 0
|
||||
}, fuse.FOPEN_KEEP_CACHE, 0
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeGetattrer)((*node)(nil))
|
||||
|
||||
func (n *node) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
||||
entryToAttr(n.e, &out.Attr)
|
||||
ino, err := n.fs.inodeOfID(n.id)
|
||||
if err != nil {
|
||||
n.fs.s.report(fmt.Errorf("node.Getattr: %v", err))
|
||||
return syscall.EIO
|
||||
}
|
||||
entryToAttr(ino, n.attr, &out.Attr)
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeGetxattrer)((*node)(nil))
|
||||
|
||||
func (n *node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
|
||||
ent := n.attr
|
||||
opq := n.isOpaque()
|
||||
for _, opaqueXattr := range opaqueXattrs {
|
||||
if attr == opaqueXattr && n.opaque {
|
||||
if attr == opaqueXattr && opq {
|
||||
// This node is an opaque directory so give overlayfs-compliant indicator.
|
||||
if len(dest) < len(opaqueXattrValue) {
|
||||
return uint32(len(opaqueXattrValue)), syscall.ERANGE
|
||||
@@ -218,7 +344,7 @@ func (n *node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32,
|
||||
return uint32(copy(dest, opaqueXattrValue)), 0
|
||||
}
|
||||
}
|
||||
if v, ok := n.e.Xattrs[attr]; ok {
|
||||
if v, ok := ent.Xattrs[attr]; ok {
|
||||
if len(dest) < len(v) {
|
||||
return uint32(len(v)), syscall.ERANGE
|
||||
}
|
||||
@@ -230,14 +356,16 @@ func (n *node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32,
|
||||
var _ = (fusefs.NodeListxattrer)((*node)(nil))
|
||||
|
||||
func (n *node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
|
||||
ent := n.attr
|
||||
opq := n.isOpaque()
|
||||
var attrs []byte
|
||||
if n.opaque {
|
||||
if opq {
|
||||
// This node is an opaque directory so add overlayfs-compliant indicator.
|
||||
for _, opaqueXattr := range opaqueXattrs {
|
||||
attrs = append(attrs, []byte(opaqueXattr+"\x00")...)
|
||||
}
|
||||
}
|
||||
for k := range n.e.Xattrs {
|
||||
for k := range ent.Xattrs {
|
||||
attrs = append(attrs, []byte(k+"\x00")...)
|
||||
}
|
||||
if len(dest) < len(attrs) {
|
||||
@@ -249,7 +377,8 @@ func (n *node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errn
|
||||
var _ = (fusefs.NodeReadlinker)((*node)(nil))
|
||||
|
||||
func (n *node) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
|
||||
return []byte(n.e.LinkName), 0
|
||||
ent := n.attr
|
||||
return []byte(ent.LinkName), 0
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeStatfser)((*node)(nil))
|
||||
@@ -262,18 +391,17 @@ func (n *node) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
|
||||
// file is a file abstraction which implements file handle in go-fuse.
|
||||
type file struct {
|
||||
n *node
|
||||
e *estargz.TOCEntry
|
||||
ra io.ReaderAt
|
||||
}
|
||||
|
||||
var _ = (fusefs.FileReader)((*file)(nil))
|
||||
|
||||
func (f *file) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
|
||||
defer commonmetrics.MeasureLatency(commonmetrics.ReadOnDemand, f.n.layerSha, time.Now()) // measure time for on-demand file reads (in milliseconds)
|
||||
defer commonmetrics.IncOperationCount(commonmetrics.OnDemandReadAccessCount, f.n.layerSha) // increment the counter for on-demand file accesses
|
||||
defer commonmetrics.MeasureLatencyInMicroseconds(commonmetrics.ReadOnDemand, f.n.fs.layerDigest, time.Now()) // measure time for on-demand file reads (in microseconds)
|
||||
defer commonmetrics.IncOperationCount(commonmetrics.OnDemandReadAccessCount, f.n.fs.layerDigest) // increment the counter for on-demand file accesses
|
||||
n, err := f.ra.ReadAt(dest, off)
|
||||
if err != nil && err != io.EOF {
|
||||
f.n.s.report(fmt.Errorf("failed to read node: %v", err))
|
||||
f.n.fs.s.report(fmt.Errorf("file.Read: %v", err))
|
||||
return nil, syscall.EIO
|
||||
}
|
||||
return fuse.ReadResultData(dest[:n]), 0
|
||||
@@ -282,20 +410,32 @@ func (f *file) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResul
|
||||
var _ = (fusefs.FileGetattrer)((*file)(nil))
|
||||
|
||||
func (f *file) Getattr(ctx context.Context, out *fuse.AttrOut) syscall.Errno {
|
||||
entryToAttr(f.e, &out.Attr)
|
||||
ino, err := f.n.fs.inodeOfID(f.n.id)
|
||||
if err != nil {
|
||||
f.n.fs.s.report(fmt.Errorf("file.Getattr: %v", err))
|
||||
return syscall.EIO
|
||||
}
|
||||
entryToAttr(ino, f.n.attr, &out.Attr)
|
||||
return 0
|
||||
}
|
||||
|
||||
// whiteout is a whiteout abstraction compliant to overlayfs.
|
||||
type whiteout struct {
|
||||
fusefs.Inode
|
||||
e *estargz.TOCEntry
|
||||
id uint32
|
||||
fs *fs
|
||||
attr metadata.Attr
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeGetattrer)((*whiteout)(nil))
|
||||
|
||||
func (w *whiteout) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
||||
entryToWhAttr(w.e, &out.Attr)
|
||||
ino, err := w.fs.inodeOfID(w.id)
|
||||
if err != nil {
|
||||
w.fs.s.report(fmt.Errorf("whiteout.Getattr: %v", err))
|
||||
return syscall.EIO
|
||||
}
|
||||
entryToWhAttr(ino, w.attr, &out.Attr)
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -308,7 +448,7 @@ func (w *whiteout) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errn
|
||||
|
||||
// newState provides new state directory node.
|
||||
// It creates statFile at the same time to give it stable inode number.
|
||||
func newState(layerDigest digest.Digest, blob remote.Blob) *state {
|
||||
func (fs *fs) newState(layerDigest digest.Digest, blob remote.Blob) *state {
|
||||
return &state{
|
||||
statFile: &statFile{
|
||||
name: layerDigest.String() + ".json",
|
||||
@@ -317,7 +457,9 @@ func newState(layerDigest digest.Digest, blob remote.Blob) *state {
|
||||
Size: blob.Size(),
|
||||
},
|
||||
blob: blob,
|
||||
fs: fs,
|
||||
},
|
||||
fs: fs,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,6 +470,7 @@ func newState(layerDigest digest.Digest, blob remote.Blob) *state {
|
||||
type state struct {
|
||||
fusefs.Inode
|
||||
statFile *statFile
|
||||
fs *fs
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeReaddirer)((*state)(nil))
|
||||
@@ -337,7 +480,7 @@ func (s *state) Readdir(ctx context.Context) (fusefs.DirStream, syscall.Errno) {
|
||||
{
|
||||
Mode: statFileMode,
|
||||
Name: s.statFile.name,
|
||||
Ino: inodeOfStatFile(s.statFile),
|
||||
Ino: s.fs.inodeOfStatFile(),
|
||||
},
|
||||
}), 0
|
||||
}
|
||||
@@ -358,7 +501,7 @@ func (s *state) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*f
|
||||
var _ = (fusefs.NodeGetattrer)((*state)(nil))
|
||||
|
||||
func (s *state) Getattr(ctx context.Context, f fusefs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
||||
stateToAttr(s, &out.Attr)
|
||||
s.fs.stateToAttr(&out.Attr)
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -392,6 +535,7 @@ type statFile struct {
|
||||
blob remote.Blob
|
||||
statJSON statJSON
|
||||
mu sync.Mutex
|
||||
fs *fs
|
||||
}
|
||||
|
||||
var _ = (fusefs.NodeOpener)((*statFile)(nil))
|
||||
@@ -430,10 +574,22 @@ func (sf *statFile) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Err
|
||||
return 0
|
||||
}
|
||||
|
||||
// logContents puts the contents of statFile in the log
|
||||
// to keep that information accessible for troubleshooting.
|
||||
// The entries naming is kept to be consistend with the field naming in statJSON.
|
||||
func (sf *statFile) logContents() {
|
||||
ctx := context.Background()
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"digest": sf.statJSON.Digest, "size": sf.statJSON.Size,
|
||||
"fetchedSize": sf.statJSON.FetchedSize, "fetchedPercent": sf.statJSON.FetchedPercent,
|
||||
}).WithError(errors.New(sf.statJSON.Error)).Error("statFile error")
|
||||
}
|
||||
|
||||
func (sf *statFile) report(err error) {
|
||||
sf.mu.Lock()
|
||||
defer sf.mu.Unlock()
|
||||
sf.statJSON.Error = err.Error()
|
||||
sf.logContents()
|
||||
}
|
||||
|
||||
func (sf *statFile) attr(out *fuse.Attr) (fusefs.StableAttr, syscall.Errno) {
|
||||
@@ -445,7 +601,7 @@ func (sf *statFile) attr(out *fuse.Attr) (fusefs.StableAttr, syscall.Errno) {
|
||||
return fusefs.StableAttr{}, syscall.EIO
|
||||
}
|
||||
|
||||
return statFileToAttr(sf, uint64(len(st)), out), 0
|
||||
return sf.fs.statFileToAttr(uint64(len(st)), out), 0
|
||||
}
|
||||
|
||||
func (sf *statFile) updateStatUnlocked() ([]byte, error) {
|
||||
@@ -459,24 +615,18 @@ func (sf *statFile) updateStatUnlocked() ([]byte, error) {
|
||||
return j, nil
|
||||
}
|
||||
|
||||
// inodeOfEnt calculates the inode number which is one-to-one correspondence
|
||||
// with the TOCEntry instance.
|
||||
func inodeOfEnt(e *estargz.TOCEntry) uint64 {
|
||||
return uint64(uintptr(unsafe.Pointer(e)))
|
||||
}
|
||||
|
||||
// entryToAttr converts stargz's TOCEntry to go-fuse's Attr.
|
||||
func entryToAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = inodeOfEnt(e)
|
||||
// entryToAttr converts metadata.Attr to go-fuse's Attr.
|
||||
func entryToAttr(ino uint64, e metadata.Attr, out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = ino
|
||||
out.Size = uint64(e.Size)
|
||||
out.Blksize = blockSize
|
||||
out.Blocks = out.Size / uint64(out.Blksize)
|
||||
if out.Size%uint64(out.Blksize) > 0 {
|
||||
out.Blocks++
|
||||
}
|
||||
mtime := e.ModTime()
|
||||
mtime := e.ModTime
|
||||
out.SetTimes(nil, &mtime, nil)
|
||||
out.Mode = modeOfEntry(e)
|
||||
out.Mode = fileModeToSystemMode(e.Mode)
|
||||
out.Owner = fuse.Owner{Uid: uint32(e.UID), Gid: uint32(e.GID)}
|
||||
out.Rdev = uint32(unix.Mkdev(uint32(e.DevMajor), uint32(e.DevMinor)))
|
||||
out.Nlink = uint32(e.NumLink)
|
||||
@@ -494,14 +644,13 @@ func entryToAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr {
|
||||
}
|
||||
}
|
||||
|
||||
// entryToWhAttr converts stargz's TOCEntry to go-fuse's Attr of whiteouts.
|
||||
func entryToWhAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr {
|
||||
fi := e.Stat()
|
||||
out.Ino = inodeOfEnt(e)
|
||||
// entryToWhAttr converts metadata.Attr to go-fuse's Attr of whiteouts.
|
||||
func entryToWhAttr(ino uint64, e metadata.Attr, out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = ino
|
||||
out.Size = 0
|
||||
out.Blksize = blockSize
|
||||
out.Blocks = 0
|
||||
mtime := fi.ModTime()
|
||||
mtime := e.ModTime
|
||||
out.SetTimes(nil, &mtime, nil)
|
||||
out.Mode = syscall.S_IFCHR
|
||||
out.Owner = fuse.Owner{Uid: 0, Gid: 0}
|
||||
@@ -518,15 +667,9 @@ func entryToWhAttr(e *estargz.TOCEntry, out *fuse.Attr) fusefs.StableAttr {
|
||||
}
|
||||
}
|
||||
|
||||
// inodeOfState calculates the inode number which is one-to-one correspondence
|
||||
// with the state directory instance which was created on mount.
|
||||
func inodeOfState(s *state) uint64 {
|
||||
return uint64(uintptr(unsafe.Pointer(s)))
|
||||
}
|
||||
|
||||
// stateToAttr converts state directory to go-fuse's Attr.
|
||||
func stateToAttr(s *state, out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = inodeOfState(s)
|
||||
func (fs *fs) stateToAttr(out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = fs.inodeOfState()
|
||||
out.Size = 0
|
||||
out.Blksize = blockSize
|
||||
out.Blocks = 0
|
||||
@@ -551,15 +694,10 @@ func stateToAttr(s *state, out *fuse.Attr) fusefs.StableAttr {
|
||||
}
|
||||
}
|
||||
|
||||
// inodeOfStatFile calculates the inode number which is one-to-one correspondence
|
||||
// with the stat file instance which was created on mount.
|
||||
func inodeOfStatFile(s *statFile) uint64 {
|
||||
return uint64(uintptr(unsafe.Pointer(s)))
|
||||
}
|
||||
|
||||
// statFileToAttr converts stat file to go-fuse's Attr.
|
||||
func statFileToAttr(sf *statFile, size uint64, out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = inodeOfStatFile(sf)
|
||||
// func statFileToAttr(id uint64, sf *statFile, size uint64, out *fuse.Attr) fusefs.StableAttr {
|
||||
func (fs *fs) statFileToAttr(size uint64, out *fuse.Attr) fusefs.StableAttr {
|
||||
out.Ino = fs.inodeOfStatFile()
|
||||
out.Size = size
|
||||
out.Blksize = blockSize
|
||||
out.Blocks = out.Size / uint64(out.Blksize)
|
||||
@@ -584,10 +722,7 @@ func statFileToAttr(sf *statFile, size uint64, out *fuse.Attr) fusefs.StableAttr
|
||||
}
|
||||
}
|
||||
|
||||
// modeOfEntry gets system's mode bits from TOCEntry
|
||||
func modeOfEntry(e *estargz.TOCEntry) uint32 {
|
||||
m := e.Stat().Mode()
|
||||
|
||||
func fileModeToSystemMode(m os.FileMode) uint32 {
|
||||
// Permission bits
|
||||
res := uint32(m & os.ModePerm)
|
||||
|
||||
|
||||
60
vendor/github.com/containerd/stargz-snapshotter/fs/metrics/common/metrics.go
generated
vendored
60
vendor/github.com/containerd/stargz-snapshotter/fs/metrics/common/metrics.go
generated
vendored
@@ -27,8 +27,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// OperationLatencyKey is the key for stargz operation latency metrics.
|
||||
OperationLatencyKey = "operation_duration"
|
||||
// OperationLatencyKeyMilliseconds is the key for stargz operation latency metrics in milliseconds.
|
||||
OperationLatencyKeyMilliseconds = "operation_duration_milliseconds"
|
||||
|
||||
// OperationLatencyKeyMicroseconds is the key for stargz operation latency metrics in microseconds.
|
||||
OperationLatencyKeyMicroseconds = "operation_duration_microseconds"
|
||||
|
||||
// OperationCountKey is the key for stargz operation count metrics.
|
||||
OperationCountKey = "operation_count"
|
||||
@@ -71,18 +74,32 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// Buckets for OperationLatency metric in milliseconds.
|
||||
latencyBuckets = []float64{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384} // in milliseconds
|
||||
// Buckets for OperationLatency metrics.
|
||||
latencyBucketsMilliseconds = []float64{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384} // in milliseconds
|
||||
latencyBucketsMicroseconds = []float64{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024} // in microseconds
|
||||
|
||||
// operationLatency collects operation latency numbers by operation
|
||||
// type and layer digest.
|
||||
operationLatency = prometheus.NewHistogramVec(
|
||||
// operationLatencyMilliseconds collects operation latency numbers in milliseconds grouped by
|
||||
// operation, type and layer digest.
|
||||
operationLatencyMilliseconds = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: OperationLatencyKey,
|
||||
Name: OperationLatencyKeyMilliseconds,
|
||||
Help: "Latency in milliseconds of stargz snapshotter operations. Broken down by operation type and layer sha.",
|
||||
Buckets: latencyBuckets,
|
||||
Buckets: latencyBucketsMilliseconds,
|
||||
},
|
||||
[]string{"operation_type", "layer"},
|
||||
)
|
||||
|
||||
// operationLatencyMicroseconds collects operation latency numbers in microseconds grouped by
|
||||
// operation, type and layer digest.
|
||||
operationLatencyMicroseconds = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: OperationLatencyKeyMicroseconds,
|
||||
Help: "Latency in microseconds of stargz snapshotter operations. Broken down by operation type and layer sha.",
|
||||
Buckets: latencyBucketsMicroseconds,
|
||||
},
|
||||
[]string{"operation_type", "layer"},
|
||||
)
|
||||
@@ -120,22 +137,39 @@ func sinceInMilliseconds(start time.Time) float64 {
|
||||
return float64(time.Since(start).Nanoseconds()) / 1e6
|
||||
}
|
||||
|
||||
// sinceInMicroseconds gets the time since the specified start in microseconds.
|
||||
// The division by 1e3 is made to have the microseconds value as floating point number, since the native method
|
||||
// .Microseconds() returns an integer value and you can lost a precision for sub-microsecond values.
|
||||
func sinceInMicroseconds(start time.Time) float64 {
|
||||
return float64(time.Since(start).Nanoseconds()) / 1e3
|
||||
}
|
||||
|
||||
// Register registers metrics. This is always called only once.
|
||||
func Register() {
|
||||
register.Do(func() {
|
||||
prometheus.MustRegister(operationLatency)
|
||||
prometheus.MustRegister(operationLatencyMilliseconds)
|
||||
prometheus.MustRegister(operationLatencyMicroseconds)
|
||||
prometheus.MustRegister(operationCount)
|
||||
prometheus.MustRegister(bytesCount)
|
||||
})
|
||||
}
|
||||
|
||||
// MeasureLatency wraps the labels attachment as well as calling Observe into a single method.
|
||||
// MeasureLatencyInMilliseconds wraps the labels attachment as well as calling Observe into a single method.
|
||||
// Right now we attach the operation and layer digest, so it's possible to see the breakdown for latency
|
||||
// by operation and individual layers.
|
||||
// If you want this to be layer agnostic, just pass the digest from empty string, e.g.
|
||||
// layerDigest := digest.FromString("")
|
||||
func MeasureLatency(operation string, layer digest.Digest, start time.Time) {
|
||||
operationLatency.WithLabelValues(operation, layer.String()).Observe(sinceInMilliseconds(start))
|
||||
func MeasureLatencyInMilliseconds(operation string, layer digest.Digest, start time.Time) {
|
||||
operationLatencyMilliseconds.WithLabelValues(operation, layer.String()).Observe(sinceInMilliseconds(start))
|
||||
}
|
||||
|
||||
// MeasureLatencyInMicroseconds wraps the labels attachment as well as calling Observe into a single method.
|
||||
// Right now we attach the operation and layer digest, so it's possible to see the breakdown for latency
|
||||
// by operation and individual layers.
|
||||
// If you want this to be layer agnostic, just pass the digest from empty string, e.g.
|
||||
// layerDigest := digest.FromString("")
|
||||
func MeasureLatencyInMicroseconds(operation string, layer digest.Digest, start time.Time) {
|
||||
operationLatencyMicroseconds.WithLabelValues(operation, layer.String()).Observe(sinceInMicroseconds(start))
|
||||
}
|
||||
|
||||
// IncOperationCount wraps the labels attachment as well as calling Inc into a single method.
|
||||
|
||||
527
vendor/github.com/containerd/stargz-snapshotter/fs/reader/reader.go
generated
vendored
527
vendor/github.com/containerd/stargz-snapshotter/fs/reader/reader.go
generated
vendored
@@ -29,15 +29,18 @@ import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/cache"
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
"github.com/containerd/stargz-snapshotter/estargz/zstdchunked"
|
||||
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
|
||||
"github.com/containerd/stargz-snapshotter/metadata"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -47,9 +50,8 @@ import (
|
||||
const maxWalkDepth = 10000
|
||||
|
||||
type Reader interface {
|
||||
OpenFile(name string) (io.ReaderAt, error)
|
||||
Lookup(name string) (*estargz.TOCEntry, bool)
|
||||
Cache(opts ...CacheOption) error
|
||||
OpenFile(id uint32) (io.ReaderAt, error)
|
||||
Metadata() metadata.Reader
|
||||
Close() error
|
||||
LastOnDemandReadTime() time.Time
|
||||
}
|
||||
@@ -57,82 +59,263 @@ type Reader interface {
|
||||
// VerifiableReader produces a Reader with a given verifier.
|
||||
type VerifiableReader struct {
|
||||
r *reader
|
||||
|
||||
lastVerifyErr atomic.Value
|
||||
prohibitVerifyFailure bool
|
||||
prohibitVerifyFailureMu sync.RWMutex
|
||||
|
||||
closed bool
|
||||
closedMu sync.Mutex
|
||||
|
||||
verifier func(uint32, string) (digest.Verifier, error)
|
||||
}
|
||||
|
||||
func (vr *VerifiableReader) SkipVerify() Reader {
|
||||
vr.r.verifier = nopTOCEntryVerifier{}
|
||||
return vr.r
|
||||
}
|
||||
|
||||
func (vr *VerifiableReader) VerifyTOC(tocDigest digest.Digest) (Reader, error) {
|
||||
v, err := vr.r.r.VerifyTOC(tocDigest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if vr.isClosed() {
|
||||
return nil, fmt.Errorf("reader is already closed")
|
||||
}
|
||||
vr.r.verifier = v
|
||||
vr.prohibitVerifyFailureMu.Lock()
|
||||
vr.prohibitVerifyFailure = true
|
||||
lastVerifyErr := vr.lastVerifyErr.Load()
|
||||
vr.prohibitVerifyFailureMu.Unlock()
|
||||
if err := lastVerifyErr; err != nil {
|
||||
return nil, errors.Wrapf(err.(error), "content error occures during caching contents")
|
||||
}
|
||||
if actual := vr.r.r.TOCDigest(); actual != tocDigest {
|
||||
return nil, fmt.Errorf("invalid TOC JSON %q; want %q", actual, tocDigest)
|
||||
}
|
||||
vr.r.verify = true
|
||||
return vr.r, nil
|
||||
}
|
||||
|
||||
func (vr *VerifiableReader) Metadata() metadata.Reader {
|
||||
// TODO: this shouldn't be called before verified
|
||||
return vr.r.r
|
||||
}
|
||||
|
||||
func (vr *VerifiableReader) Cache(opts ...CacheOption) (err error) {
|
||||
if vr.isClosed() {
|
||||
return fmt.Errorf("reader is already closed")
|
||||
}
|
||||
|
||||
var cacheOpts cacheOptions
|
||||
for _, o := range opts {
|
||||
o(&cacheOpts)
|
||||
}
|
||||
|
||||
gr := vr.r
|
||||
r := gr.r
|
||||
if cacheOpts.reader != nil {
|
||||
r, err = r.Clone(cacheOpts.reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
rootID := r.RootID()
|
||||
|
||||
filter := func(int64) bool {
|
||||
return true
|
||||
}
|
||||
if cacheOpts.filter != nil {
|
||||
filter = cacheOpts.filter
|
||||
}
|
||||
|
||||
eg, egCtx := errgroup.WithContext(context.Background())
|
||||
eg.Go(func() error {
|
||||
return vr.cacheWithReader(egCtx,
|
||||
0, eg, semaphore.NewWeighted(int64(runtime.GOMAXPROCS(0))),
|
||||
rootID, r, filter, cacheOpts.cacheOpts...)
|
||||
})
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func (vr *VerifiableReader) cacheWithReader(ctx context.Context, currentDepth int, eg *errgroup.Group, sem *semaphore.Weighted, dirID uint32, r metadata.Reader, filter func(int64) bool, opts ...cache.Option) (rErr error) {
|
||||
if currentDepth > maxWalkDepth {
|
||||
return fmt.Errorf("tree is too deep (depth:%d)", currentDepth)
|
||||
}
|
||||
gr := vr.r
|
||||
rootID := r.RootID()
|
||||
r.ForeachChild(dirID, func(name string, id uint32, mode os.FileMode) bool {
|
||||
e, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
if mode.IsDir() {
|
||||
// Walk through all files on this stargz file.
|
||||
|
||||
// Ignore the entry of "./" (formated as "" by stargz lib) on root directory
|
||||
// because this points to the root directory itself.
|
||||
if dirID == rootID && name == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
if err := vr.cacheWithReader(ctx, currentDepth+1, eg, sem, id, r, filter, opts...); err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else if !mode.IsRegular() {
|
||||
// Only cache regular files
|
||||
return true
|
||||
} else if dirID == rootID && name == estargz.TOCTarName {
|
||||
// We don't need to cache TOC json file
|
||||
return true
|
||||
}
|
||||
|
||||
offset, err := r.GetOffset(id)
|
||||
if err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
if !filter(offset) {
|
||||
// This entry need to be filtered out
|
||||
return true
|
||||
}
|
||||
|
||||
fr, err := r.OpenFile(id)
|
||||
if err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
|
||||
var nr int64
|
||||
for nr < e.Size {
|
||||
chunkOffset, chunkSize, chunkDigestStr, ok := fr.ChunkEntryForOffset(nr)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
nr += chunkSize
|
||||
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
|
||||
eg.Go(func() (retErr error) {
|
||||
defer sem.Release(1)
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
vr.lastVerifyErr.Store(retErr)
|
||||
}
|
||||
}()
|
||||
|
||||
// Check if the target chunks exists in the cache
|
||||
cacheID := genID(id, chunkOffset, chunkSize)
|
||||
if r, err := gr.cache.Get(cacheID, opts...); err == nil {
|
||||
return r.Close()
|
||||
}
|
||||
|
||||
// missed cache, needs to fetch and add it to the cache
|
||||
br := bufio.NewReaderSize(io.NewSectionReader(fr, chunkOffset, chunkSize), int(chunkSize))
|
||||
if _, err := br.Peek(int(chunkSize)); err != nil {
|
||||
return fmt.Errorf("cacheWithReader.peek: %v", err)
|
||||
}
|
||||
w, err := gr.cache.Add(cacheID, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
v, err := vr.verifier(id, chunkDigestStr)
|
||||
if err != nil {
|
||||
vr.prohibitVerifyFailureMu.RLock()
|
||||
if vr.prohibitVerifyFailure {
|
||||
vr.prohibitVerifyFailureMu.RUnlock()
|
||||
return errors.Wrapf(err, "verifier not found %q(off:%d,size:%d)", name, chunkOffset, chunkSize)
|
||||
}
|
||||
vr.lastVerifyErr.Store(err)
|
||||
vr.prohibitVerifyFailureMu.RUnlock()
|
||||
}
|
||||
tee := ioutil.Discard
|
||||
if v != nil {
|
||||
tee = io.Writer(v) // verification is required
|
||||
}
|
||||
if _, err := io.CopyN(w, io.TeeReader(br, tee), chunkSize); err != nil {
|
||||
w.Abort()
|
||||
return errors.Wrapf(err,
|
||||
"failed to cache file payload of %q (offset:%d,size:%d)",
|
||||
name, chunkOffset, chunkSize)
|
||||
}
|
||||
if v != nil && !v.Verified() {
|
||||
err := fmt.Errorf("invalid chunk %q (offset:%d,size:%d)", name, chunkOffset, chunkSize)
|
||||
vr.prohibitVerifyFailureMu.RLock()
|
||||
if vr.prohibitVerifyFailure {
|
||||
vr.prohibitVerifyFailureMu.RUnlock()
|
||||
w.Abort()
|
||||
return err
|
||||
}
|
||||
vr.lastVerifyErr.Store(err)
|
||||
vr.prohibitVerifyFailureMu.RUnlock()
|
||||
}
|
||||
|
||||
return w.Commit()
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (vr *VerifiableReader) Close() error {
|
||||
vr.closedMu.Lock()
|
||||
defer vr.closedMu.Unlock()
|
||||
if vr.closed {
|
||||
return nil
|
||||
}
|
||||
vr.closed = true
|
||||
return vr.r.Close()
|
||||
}
|
||||
|
||||
type nopTOCEntryVerifier struct{}
|
||||
|
||||
func (nev nopTOCEntryVerifier) Verifier(ce *estargz.TOCEntry) (digest.Verifier, error) {
|
||||
return nopVerifier{}, nil
|
||||
}
|
||||
|
||||
type nopVerifier struct{}
|
||||
|
||||
func (nv nopVerifier) Write(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (nv nopVerifier) Verified() bool {
|
||||
return true
|
||||
func (vr *VerifiableReader) isClosed() bool {
|
||||
vr.closedMu.Lock()
|
||||
closed := vr.closed
|
||||
vr.closedMu.Unlock()
|
||||
return closed
|
||||
}
|
||||
|
||||
// NewReader creates a Reader based on the given stargz blob and cache implementation.
|
||||
// It returns VerifiableReader so the caller must provide a estargz.TOCEntryVerifier
|
||||
// It returns VerifiableReader so the caller must provide a metadata.ChunkVerifier
|
||||
// to use for verifying file or chunk contained in this stargz blob.
|
||||
func NewReader(sr *io.SectionReader, cache cache.BlobCache, layerSha digest.Digest, telemetry *estargz.Telemetry, esgzOpts ...estargz.OpenOption) (*VerifiableReader, error) {
|
||||
r, err := estargz.Open(sr, append(esgzOpts, estargz.WithTelemetry(telemetry), estargz.WithDecompressors(new(zstdchunked.Decompressor)))...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse stargz")
|
||||
}
|
||||
|
||||
func NewReader(r metadata.Reader, cache cache.BlobCache, layerSha digest.Digest) (*VerifiableReader, error) {
|
||||
vr := &reader{
|
||||
r: r,
|
||||
sr: sr,
|
||||
cache: cache,
|
||||
bufPool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
layerSha: layerSha,
|
||||
telemetry: telemetry,
|
||||
layerSha: layerSha,
|
||||
verifier: digestVerifier,
|
||||
}
|
||||
|
||||
return &VerifiableReader{vr}, nil
|
||||
return &VerifiableReader{r: vr, verifier: digestVerifier}, nil
|
||||
}
|
||||
|
||||
type reader struct {
|
||||
r *estargz.Reader
|
||||
sr *io.SectionReader
|
||||
cache cache.BlobCache
|
||||
bufPool sync.Pool
|
||||
verifier estargz.TOCEntryVerifier
|
||||
layerSha digest.Digest
|
||||
r metadata.Reader
|
||||
cache cache.BlobCache
|
||||
bufPool sync.Pool
|
||||
|
||||
telemetry *estargz.Telemetry
|
||||
layerSha digest.Digest
|
||||
|
||||
lastReadTime time.Time
|
||||
lastReadTimeMu sync.Mutex
|
||||
|
||||
closed bool
|
||||
closedMu sync.Mutex
|
||||
|
||||
verify bool
|
||||
verifier func(uint32, string) (digest.Verifier, error)
|
||||
}
|
||||
|
||||
func (gr *reader) Metadata() metadata.Reader {
|
||||
return gr.r
|
||||
}
|
||||
|
||||
func (gr *reader) setLastReadTime(lastReadTime time.Time) {
|
||||
@@ -148,82 +331,36 @@ func (gr *reader) LastOnDemandReadTime() time.Time {
|
||||
return t
|
||||
}
|
||||
|
||||
func (gr *reader) OpenFile(name string) (io.ReaderAt, error) {
|
||||
func (gr *reader) OpenFile(id uint32) (io.ReaderAt, error) {
|
||||
if gr.isClosed() {
|
||||
return nil, fmt.Errorf("reader is already closed")
|
||||
}
|
||||
|
||||
sr, err := gr.r.OpenFile(name)
|
||||
var fr metadata.File
|
||||
fr, err := gr.r.OpenFile(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e, ok := gr.r.Lookup(name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to get TOCEntry %q", name)
|
||||
return nil, errors.Wrapf(err, "failed to open file %d", id)
|
||||
}
|
||||
return &file{
|
||||
name: name,
|
||||
digest: e.Digest,
|
||||
r: gr.r,
|
||||
cache: gr.cache,
|
||||
ra: sr,
|
||||
gr: gr,
|
||||
id: id,
|
||||
fr: fr,
|
||||
gr: gr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (gr *reader) Lookup(name string) (*estargz.TOCEntry, bool) {
|
||||
return gr.r.Lookup(name)
|
||||
}
|
||||
|
||||
func (gr *reader) Cache(opts ...CacheOption) (err error) {
|
||||
if gr.isClosed() {
|
||||
return fmt.Errorf("reader is already closed")
|
||||
}
|
||||
|
||||
var cacheOpts cacheOptions
|
||||
for _, o := range opts {
|
||||
o(&cacheOpts)
|
||||
}
|
||||
|
||||
r := gr.r
|
||||
if cacheOpts.reader != nil {
|
||||
if r, err = estargz.Open(cacheOpts.reader,
|
||||
// TODO: apply other options used in NewReader when needed.
|
||||
estargz.WithTelemetry(gr.telemetry),
|
||||
estargz.WithDecompressors(new(zstdchunked.Decompressor)),
|
||||
); err != nil {
|
||||
return errors.Wrap(err, "failed to parse stargz")
|
||||
}
|
||||
}
|
||||
root, ok := r.Lookup("")
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get a TOCEntry of the root")
|
||||
}
|
||||
|
||||
filter := func(*estargz.TOCEntry) bool {
|
||||
return true
|
||||
}
|
||||
if cacheOpts.filter != nil {
|
||||
filter = cacheOpts.filter
|
||||
}
|
||||
|
||||
eg, egCtx := errgroup.WithContext(context.Background())
|
||||
eg.Go(func() error {
|
||||
return gr.cacheWithReader(egCtx,
|
||||
0, eg, semaphore.NewWeighted(int64(runtime.GOMAXPROCS(0))),
|
||||
root, r, filter, cacheOpts.cacheOpts...)
|
||||
})
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func (gr *reader) Close() error {
|
||||
func (gr *reader) Close() (retErr error) {
|
||||
gr.closedMu.Lock()
|
||||
defer gr.closedMu.Unlock()
|
||||
if gr.closed {
|
||||
return nil
|
||||
}
|
||||
gr.closed = true
|
||||
return gr.cache.Close()
|
||||
if err := gr.cache.Close(); err != nil {
|
||||
retErr = multierror.Append(retErr, err)
|
||||
}
|
||||
if err := gr.r.Close(); err != nil {
|
||||
retErr = multierror.Append(retErr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (gr *reader) isClosed() bool {
|
||||
@@ -233,115 +370,15 @@ func (gr *reader) isClosed() bool {
|
||||
return closed
|
||||
}
|
||||
|
||||
func (gr *reader) cacheWithReader(ctx context.Context, currentDepth int, eg *errgroup.Group, sem *semaphore.Weighted, dir *estargz.TOCEntry, r *estargz.Reader, filter func(*estargz.TOCEntry) bool, opts ...cache.Option) (rErr error) {
|
||||
if currentDepth > maxWalkDepth {
|
||||
return fmt.Errorf("TOCEntry tree is too deep (depth:%d)", currentDepth)
|
||||
}
|
||||
dir.ForeachChild(func(_ string, e *estargz.TOCEntry) bool {
|
||||
if e.Type == "dir" {
|
||||
// Walk through all files on this stargz file.
|
||||
|
||||
// Ignore a TOCEntry of "./" (formated as "" by stargz lib) on root directory
|
||||
// because this points to the root directory itself.
|
||||
if e.Name == "" && dir.Name == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Make sure the entry is the immediate child for avoiding loop.
|
||||
if filepath.Dir(filepath.Clean(e.Name)) != filepath.Clean(dir.Name) {
|
||||
rErr = fmt.Errorf("invalid child path %q; must be child of %q",
|
||||
e.Name, dir.Name)
|
||||
return false
|
||||
}
|
||||
if err := gr.cacheWithReader(ctx, currentDepth+1, eg, sem, e, r, filter, opts...); err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else if e.Type != "reg" {
|
||||
// Only cache regular files
|
||||
return true
|
||||
} else if !filter(e) {
|
||||
// This entry need to be filtered out
|
||||
return true
|
||||
} else if e.Name == estargz.TOCTarName {
|
||||
// We don't need to cache TOC json file
|
||||
return true
|
||||
}
|
||||
|
||||
sr, err := r.OpenFile(e.Name)
|
||||
if err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
|
||||
var nr int64
|
||||
for nr < e.Size {
|
||||
ce, ok := r.ChunkEntryForOffset(e.Name, nr)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
nr += ce.ChunkSize
|
||||
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
rErr = err
|
||||
return false
|
||||
}
|
||||
|
||||
eg.Go(func() (retErr error) {
|
||||
defer sem.Release(1)
|
||||
|
||||
// Check if the target chunks exists in the cache
|
||||
id := genID(e.Digest, ce.ChunkOffset, ce.ChunkSize)
|
||||
if r, err := gr.cache.Get(id, opts...); err == nil {
|
||||
return r.Close()
|
||||
}
|
||||
|
||||
// missed cache, needs to fetch and add it to the cache
|
||||
cr := io.NewSectionReader(sr, ce.ChunkOffset, ce.ChunkSize)
|
||||
v, err := gr.verifier.Verifier(ce)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "verifier not found %q(off:%d,size:%d)",
|
||||
e.Name, ce.ChunkOffset, ce.ChunkSize)
|
||||
}
|
||||
br := bufio.NewReaderSize(io.TeeReader(cr, v), int(ce.ChunkSize))
|
||||
if _, err := br.Peek(int(ce.ChunkSize)); err != nil {
|
||||
return fmt.Errorf("cacheWithReader.peek: %v", err)
|
||||
}
|
||||
w, err := gr.cache.Add(id, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer w.Close()
|
||||
if _, err := io.CopyN(w, br, ce.ChunkSize); err != nil {
|
||||
w.Abort()
|
||||
return errors.Wrapf(err,
|
||||
"failed to cache file payload of %q (offset:%d,size:%d)",
|
||||
e.Name, ce.ChunkOffset, ce.ChunkSize)
|
||||
}
|
||||
if !v.Verified() {
|
||||
w.Abort()
|
||||
return fmt.Errorf("invalid chunk %q (offset:%d,size:%d)",
|
||||
e.Name, ce.ChunkOffset, ce.ChunkSize)
|
||||
}
|
||||
|
||||
return w.Commit()
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return
|
||||
func (gr *reader) putBuffer(b *bytes.Buffer) {
|
||||
b.Reset()
|
||||
gr.bufPool.Put(b)
|
||||
}
|
||||
|
||||
type file struct {
|
||||
name string
|
||||
digest string
|
||||
ra io.ReaderAt
|
||||
r *estargz.Reader
|
||||
cache cache.BlobCache
|
||||
gr *reader
|
||||
id uint32
|
||||
fr metadata.File
|
||||
gr *reader
|
||||
}
|
||||
|
||||
// ReadAt reads chunks from the stargz file with trying to fetch as many chunks
|
||||
@@ -349,19 +386,19 @@ type file struct {
|
||||
func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
nr := 0
|
||||
for nr < len(p) {
|
||||
ce, ok := sf.r.ChunkEntryForOffset(sf.name, offset+int64(nr))
|
||||
chunkOffset, chunkSize, chunkDigestStr, ok := sf.fr.ChunkEntryForOffset(offset + int64(nr))
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
var (
|
||||
id = genID(sf.digest, ce.ChunkOffset, ce.ChunkSize)
|
||||
lowerDiscard = positive(offset - ce.ChunkOffset)
|
||||
upperDiscard = positive(ce.ChunkOffset + ce.ChunkSize - (offset + int64(len(p))))
|
||||
expectedSize = ce.ChunkSize - upperDiscard - lowerDiscard
|
||||
id = genID(sf.id, chunkOffset, chunkSize)
|
||||
lowerDiscard = positive(offset - chunkOffset)
|
||||
upperDiscard = positive(chunkOffset + chunkSize - (offset + int64(len(p))))
|
||||
expectedSize = chunkSize - upperDiscard - lowerDiscard
|
||||
)
|
||||
|
||||
// Check if the content exists in the cache
|
||||
if r, err := sf.cache.Get(id); err == nil {
|
||||
if r, err := sf.gr.cache.Get(id); err == nil {
|
||||
n, err := r.ReadAt(p[nr:int64(nr)+expectedSize], lowerDiscard)
|
||||
if (err == nil || err == io.EOF) && int64(n) == expectedSize {
|
||||
nr += n
|
||||
@@ -376,8 +413,8 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
// reads against neighboring chunks can take the data without decmpression.
|
||||
if lowerDiscard == 0 && upperDiscard == 0 {
|
||||
// We can directly store the result to the given buffer
|
||||
ip := p[nr : int64(nr)+ce.ChunkSize]
|
||||
n, err := sf.ra.ReadAt(ip, ce.ChunkOffset)
|
||||
ip := p[nr : int64(nr)+chunkSize]
|
||||
n, err := sf.fr.ReadAt(ip, chunkOffset)
|
||||
if err != nil && err != io.EOF {
|
||||
return 0, errors.Wrap(err, "failed to read data")
|
||||
}
|
||||
@@ -387,12 +424,12 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
sf.gr.setLastReadTime(time.Now())
|
||||
|
||||
// Verify this chunk
|
||||
if err := sf.verify(ip, ce); err != nil {
|
||||
if err := sf.verify(sf.id, ip, chunkDigestStr); err != nil {
|
||||
return 0, errors.Wrap(err, "invalid chunk")
|
||||
}
|
||||
|
||||
// Cache this chunk
|
||||
if w, err := sf.cache.Add(id); err == nil {
|
||||
if w, err := sf.gr.cache.Add(id); err == nil {
|
||||
if cn, err := w.Write(ip); err != nil || cn != len(ip) {
|
||||
w.Abort()
|
||||
} else {
|
||||
@@ -407,10 +444,10 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
// Use temporally buffer for aligning this chunk
|
||||
b := sf.gr.bufPool.Get().(*bytes.Buffer)
|
||||
b.Reset()
|
||||
b.Grow(int(ce.ChunkSize))
|
||||
ip := b.Bytes()[:ce.ChunkSize]
|
||||
if _, err := sf.ra.ReadAt(ip, ce.ChunkOffset); err != nil && err != io.EOF {
|
||||
sf.gr.bufPool.Put(b)
|
||||
b.Grow(int(chunkSize))
|
||||
ip := b.Bytes()[:chunkSize]
|
||||
if _, err := sf.fr.ReadAt(ip, chunkOffset); err != nil && err != io.EOF {
|
||||
sf.gr.putBuffer(b)
|
||||
return 0, errors.Wrap(err, "failed to read data")
|
||||
}
|
||||
|
||||
@@ -420,13 +457,13 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
sf.gr.setLastReadTime(time.Now())
|
||||
|
||||
// Verify this chunk
|
||||
if err := sf.verify(ip, ce); err != nil {
|
||||
sf.gr.bufPool.Put(b)
|
||||
if err := sf.verify(sf.id, ip, chunkDigestStr); err != nil {
|
||||
sf.gr.putBuffer(b)
|
||||
return 0, errors.Wrap(err, "invalid chunk")
|
||||
}
|
||||
|
||||
// Cache this chunk
|
||||
if w, err := sf.cache.Add(id); err == nil {
|
||||
if w, err := sf.gr.cache.Add(id); err == nil {
|
||||
if cn, err := w.Write(ip); err != nil || cn != len(ip) {
|
||||
w.Abort()
|
||||
} else {
|
||||
@@ -434,8 +471,8 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
}
|
||||
w.Close()
|
||||
}
|
||||
n := copy(p[nr:], ip[lowerDiscard:ce.ChunkSize-upperDiscard])
|
||||
sf.gr.bufPool.Put(b)
|
||||
n := copy(p[nr:], ip[lowerDiscard:chunkSize-upperDiscard])
|
||||
sf.gr.putBuffer(b)
|
||||
if int64(n) != expectedSize {
|
||||
return 0, fmt.Errorf("unexpected final data size %d; want %d", n, expectedSize)
|
||||
}
|
||||
@@ -447,26 +484,26 @@ func (sf *file) ReadAt(p []byte, offset int64) (int, error) {
|
||||
return nr, nil
|
||||
}
|
||||
|
||||
func (sf *file) verify(p []byte, ce *estargz.TOCEntry) error {
|
||||
v, err := sf.gr.verifier.Verifier(ce)
|
||||
func (sf *file) verify(id uint32, p []byte, chunkDigestStr string) error {
|
||||
if !sf.gr.verify {
|
||||
return nil // verification is not required
|
||||
}
|
||||
v, err := sf.gr.verifier(id, chunkDigestStr)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "verifier not found %q (offset:%d,size:%d)",
|
||||
ce.Name, ce.ChunkOffset, ce.ChunkSize)
|
||||
return errors.Wrapf(err, "invalid chunk")
|
||||
}
|
||||
if _, err := v.Write(p); err != nil {
|
||||
return errors.Wrapf(err, "failed to verify %q (offset:%d,size:%d)",
|
||||
ce.Name, ce.ChunkOffset, ce.ChunkSize)
|
||||
return errors.Wrap(err, "invalid chunk: failed to write to verifier")
|
||||
}
|
||||
if !v.Verified() {
|
||||
return fmt.Errorf("invalid chunk %q (offset:%d,size:%d)",
|
||||
ce.Name, ce.ChunkOffset, ce.ChunkSize)
|
||||
return fmt.Errorf("invalid chunk: not verified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func genID(digest string, offset, size int64) string {
|
||||
sum := sha256.Sum256([]byte(fmt.Sprintf("%s-%d-%d", digest, offset, size)))
|
||||
func genID(id uint32, offset, size int64) string {
|
||||
sum := sha256.Sum256([]byte(fmt.Sprintf("%d-%d-%d", id, offset, size)))
|
||||
return fmt.Sprintf("%x", sum)
|
||||
}
|
||||
|
||||
@@ -481,7 +518,7 @@ type CacheOption func(*cacheOptions)
|
||||
|
||||
type cacheOptions struct {
|
||||
cacheOpts []cache.Option
|
||||
filter func(*estargz.TOCEntry) bool
|
||||
filter func(int64) bool
|
||||
reader *io.SectionReader
|
||||
}
|
||||
|
||||
@@ -491,7 +528,7 @@ func WithCacheOpts(cacheOpts ...cache.Option) CacheOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithFilter(filter func(*estargz.TOCEntry) bool) CacheOption {
|
||||
func WithFilter(filter func(int64) bool) CacheOption {
|
||||
return func(opts *cacheOptions) {
|
||||
opts.filter = filter
|
||||
}
|
||||
@@ -502,3 +539,11 @@ func WithReader(sr *io.SectionReader) CacheOption {
|
||||
opts.reader = sr
|
||||
}
|
||||
}
|
||||
|
||||
func digestVerifier(id uint32, chunkDigestStr string) (digest.Verifier, error) {
|
||||
chunkDigest, err := digest.Parse(chunkDigestStr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid chunk: no digset is recorded")
|
||||
}
|
||||
return chunkDigest.Verifier(), nil
|
||||
}
|
||||
|
||||
120
vendor/github.com/containerd/stargz-snapshotter/fs/remote/blob.go
generated
vendored
120
vendor/github.com/containerd/stargz-snapshotter/fs/remote/blob.go
generated
vendored
@@ -28,6 +28,8 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -37,6 +39,7 @@ import (
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
var contentRangeRegexp = regexp.MustCompile(`bytes ([0-9]+)-([0-9]+)/([0-9]+|\\*)`)
|
||||
@@ -52,7 +55,7 @@ type Blob interface {
|
||||
}
|
||||
|
||||
type blob struct {
|
||||
fetcher *fetcher
|
||||
fetcher fetcher
|
||||
fetcherMu sync.Mutex
|
||||
|
||||
size int64
|
||||
@@ -64,8 +67,10 @@ type blob struct {
|
||||
checkInterval time.Duration
|
||||
fetchTimeout time.Duration
|
||||
|
||||
fetchedRegionSet regionSet
|
||||
fetchedRegionSetMu sync.Mutex
|
||||
fetchedRegionSet regionSet
|
||||
fetchedRegionSetMu sync.Mutex
|
||||
fetchedRegionGroup singleflight.Group
|
||||
fetchedRegionCopyMu sync.Mutex
|
||||
|
||||
resolver *Resolver
|
||||
|
||||
@@ -73,6 +78,22 @@ type blob struct {
|
||||
closedMu sync.Mutex
|
||||
}
|
||||
|
||||
func makeBlob(fetcher fetcher, size int64, chunkSize int64, prefetchChunkSize int64,
|
||||
blobCache cache.BlobCache, lastCheck time.Time, checkInterval time.Duration,
|
||||
r *Resolver, fetchTimeout time.Duration) *blob {
|
||||
return &blob{
|
||||
fetcher: fetcher,
|
||||
size: size,
|
||||
chunkSize: chunkSize,
|
||||
prefetchChunkSize: prefetchChunkSize,
|
||||
cache: blobCache,
|
||||
lastCheck: lastCheck,
|
||||
checkInterval: checkInterval,
|
||||
resolver: r,
|
||||
fetchTimeout: fetchTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *blob) Close() error {
|
||||
b.closedMu.Lock()
|
||||
defer b.closedMu.Unlock()
|
||||
@@ -96,16 +117,17 @@ func (b *blob) Refresh(ctx context.Context, hosts source.RegistryHosts, refspec
|
||||
}
|
||||
|
||||
// refresh the fetcher
|
||||
new, newSize, err := newFetcher(ctx, hosts, refspec, desc)
|
||||
f, newSize, err := b.resolver.resolveFetcher(ctx, hosts, refspec, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if newSize != b.size {
|
||||
}
|
||||
if 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
|
||||
b.fetcherMu.Lock()
|
||||
b.fetcher = new
|
||||
b.fetcher = f
|
||||
b.fetcherMu.Unlock()
|
||||
b.lastCheckMu.Lock()
|
||||
b.lastCheck = time.Now()
|
||||
@@ -153,7 +175,18 @@ func (b *blob) FetchedSize() int64 {
|
||||
return sz
|
||||
}
|
||||
|
||||
func (b *blob) cacheAt(offset int64, size int64, fr *fetcher, cacheOpts *options) error {
|
||||
func makeSyncKey(allData map[region]io.Writer) string {
|
||||
keys := make([]string, len(allData))
|
||||
keysIndex := 0
|
||||
for key := range allData {
|
||||
keys[keysIndex] = fmt.Sprintf("[%d,%d]", key.b, key.e)
|
||||
keysIndex++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return strings.Join(keys, ",")
|
||||
}
|
||||
|
||||
func (b *blob) cacheAt(offset int64, size int64, fr fetcher, cacheOpts *options) error {
|
||||
fetchReg := region{floor(offset, b.chunkSize), ceil(offset+size-1, b.chunkSize) - 1}
|
||||
discard := make(map[region]io.Writer)
|
||||
|
||||
@@ -275,8 +308,9 @@ func (b *blob) ReadAt(p []byte, offset int64, opts ...Option) (int, error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// fetchRange fetches all specified chunks from local cache and remote blob.
|
||||
func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error {
|
||||
// fetchRegions fetches all specified chunks from remote blob and puts it in the local cache.
|
||||
// It must be called from within fetchRange and need to ensure that it is inside the singleflight `Do` operation.
|
||||
func (b *blob) fetchRegions(allData map[region]io.Writer, fetched map[region]bool, opts *options) error {
|
||||
if len(allData) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -289,14 +323,18 @@ func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error {
|
||||
|
||||
// request missed regions
|
||||
var req []region
|
||||
fetched := make(map[region]bool)
|
||||
for reg := range allData {
|
||||
req = append(req, reg)
|
||||
fetched[reg] = false
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), b.fetchTimeout)
|
||||
|
||||
fetchCtx, cancel := context.WithTimeout(context.Background(), b.fetchTimeout)
|
||||
defer cancel()
|
||||
mr, err := fr.fetch(ctx, req, true, opts)
|
||||
if opts.ctx != nil {
|
||||
fetchCtx = opts.ctx
|
||||
}
|
||||
mr, err := fr.fetch(fetchCtx, req, true)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -366,6 +404,64 @@ func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetchRange fetches all specified chunks from local cache and remote blob.
|
||||
func (b *blob) fetchRange(allData map[region]io.Writer, opts *options) error {
|
||||
if len(allData) == 0 {
|
||||
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)
|
||||
fetched := make(map[region]bool)
|
||||
_, err, shared := b.fetchedRegionGroup.Do(key, func() (interface{}, error) {
|
||||
return nil, b.fetchRegions(allData, fetched, opts)
|
||||
})
|
||||
|
||||
// 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 err == nil && shared {
|
||||
for reg := range allData {
|
||||
if _, ok := fetched[reg]; ok {
|
||||
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
|
||||
}
|
||||
|
||||
type walkFunc func(reg region) error
|
||||
|
||||
// walkChunks walks chunks from begin to end in order in the specified region.
|
||||
|
||||
233
vendor/github.com/containerd/stargz-snapshotter/fs/remote/resolver.go
generated
vendored
233
vendor/github.com/containerd/stargz-snapshotter/fs/remote/resolver.go
generated
vendored
@@ -28,6 +28,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
@@ -46,18 +47,25 @@ import (
|
||||
"github.com/containerd/stargz-snapshotter/fs/config"
|
||||
commonmetrics "github.com/containerd/stargz-snapshotter/fs/metrics/common"
|
||||
"github.com/containerd/stargz-snapshotter/fs/source"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
rhttp "github.com/hashicorp/go-retryablehttp"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultChunkSize = 50000
|
||||
defaultValidIntervalSec = 60
|
||||
defaultFetchTimeoutSec = 300
|
||||
|
||||
defaultMaxRetries = 5
|
||||
defaultMinWaitMSec = 30
|
||||
defaultMaxWaitMSec = 300000
|
||||
)
|
||||
|
||||
func NewResolver(cfg config.BlobConfig) *Resolver {
|
||||
func NewResolver(cfg config.BlobConfig, handlers map[string]Handler) *Resolver {
|
||||
if cfg.ChunkSize == 0 { // zero means "use default chunk size"
|
||||
cfg.ChunkSize = defaultChunkSize
|
||||
}
|
||||
@@ -70,48 +78,131 @@ func NewResolver(cfg config.BlobConfig) *Resolver {
|
||||
if cfg.FetchTimeoutSec == 0 {
|
||||
cfg.FetchTimeoutSec = defaultFetchTimeoutSec
|
||||
}
|
||||
if cfg.MaxRetries == 0 {
|
||||
cfg.MaxRetries = defaultMaxRetries
|
||||
}
|
||||
if cfg.MinWaitMSec == 0 {
|
||||
cfg.MinWaitMSec = defaultMinWaitMSec
|
||||
}
|
||||
if cfg.MaxWaitMSec == 0 {
|
||||
cfg.MaxWaitMSec = defaultMaxWaitMSec
|
||||
}
|
||||
|
||||
return &Resolver{
|
||||
blobConfig: cfg,
|
||||
handlers: handlers,
|
||||
}
|
||||
}
|
||||
|
||||
type Resolver struct {
|
||||
blobConfig config.BlobConfig
|
||||
handlers map[string]Handler
|
||||
}
|
||||
|
||||
type fetcher interface {
|
||||
fetch(ctx context.Context, rs []region, retry bool) (multipartReadCloser, error)
|
||||
check() error
|
||||
genID(reg region) string
|
||||
}
|
||||
|
||||
func (r *Resolver) Resolve(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor, blobCache cache.BlobCache) (Blob, error) {
|
||||
fetcher, size, err := newFetcher(ctx, hosts, refspec, desc)
|
||||
f, size, err := r.resolveFetcher(ctx, hosts, refspec, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if r.blobConfig.ForceSingleRangeMode {
|
||||
fetcher.singleRangeMode()
|
||||
}
|
||||
return &blob{
|
||||
fetcher: fetcher,
|
||||
size: size,
|
||||
chunkSize: r.blobConfig.ChunkSize,
|
||||
prefetchChunkSize: r.blobConfig.PrefetchChunkSize,
|
||||
cache: blobCache,
|
||||
lastCheck: time.Now(),
|
||||
checkInterval: time.Duration(r.blobConfig.ValidInterval) * time.Second,
|
||||
resolver: r,
|
||||
fetchTimeout: time.Duration(r.blobConfig.FetchTimeoutSec) * time.Second,
|
||||
}, nil
|
||||
blobConfig := &r.blobConfig
|
||||
return makeBlob(f,
|
||||
size,
|
||||
blobConfig.ChunkSize,
|
||||
blobConfig.PrefetchChunkSize,
|
||||
blobCache,
|
||||
time.Now(),
|
||||
time.Duration(blobConfig.ValidInterval)*time.Second,
|
||||
r,
|
||||
time.Duration(blobConfig.FetchTimeoutSec)*time.Second), nil
|
||||
}
|
||||
|
||||
func newFetcher(ctx context.Context, hosts source.RegistryHosts, refspec reference.Spec, desc ocispec.Descriptor) (*fetcher, int64, error) {
|
||||
reghosts, err := hosts(refspec)
|
||||
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
|
||||
fc := &fetcherConfig{
|
||||
hosts: hosts,
|
||||
refspec: refspec,
|
||||
desc: desc,
|
||||
maxRetries: blobConfig.MaxRetries,
|
||||
minWaitMSec: time.Duration(blobConfig.MinWaitMSec) * time.Millisecond,
|
||||
maxWaitMSec: time.Duration(blobConfig.MaxWaitMSec) * time.Millisecond,
|
||||
}
|
||||
var handlersErr error
|
||||
for name, p := range r.handlers {
|
||||
// TODO: allow to configure the selection of readers based on the hostname in refspec
|
||||
r, size, err := p.Handle(ctx, desc)
|
||||
if err != nil {
|
||||
handlersErr = multierror.Append(handlersErr, err)
|
||||
continue
|
||||
}
|
||||
log.G(ctx).WithField("handler name", name).WithField("ref", refspec.String).WithField("digest", desc.Digest).
|
||||
Debugf("contents is provided by a handler")
|
||||
return &remoteFetcher{r}, size, nil
|
||||
}
|
||||
|
||||
log.G(ctx).WithError(handlersErr).WithField("ref", refspec.String).WithField("digest", desc.Digest).Debugf("using default handler")
|
||||
hf, size, err := newHTTPFetcher(ctx, fc)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if blobConfig.ForceSingleRangeMode {
|
||||
hf.singleRangeMode()
|
||||
}
|
||||
return hf, size, err
|
||||
}
|
||||
|
||||
type fetcherConfig struct {
|
||||
hosts source.RegistryHosts
|
||||
refspec reference.Spec
|
||||
desc ocispec.Descriptor
|
||||
maxRetries int
|
||||
minWaitMSec time.Duration
|
||||
maxWaitMSec time.Duration
|
||||
}
|
||||
|
||||
func jitter(duration time.Duration) time.Duration {
|
||||
return time.Duration(rand.Int63n(int64(duration)) + int64(duration))
|
||||
}
|
||||
|
||||
// backoffStrategy extends retryablehttp's DefaultBackoff to add a random jitter to avoid overwhelming the repository
|
||||
// when it comes back online
|
||||
// DefaultBackoff either tries to parse the 'Retry-After' header of the response; or, it uses an exponential backoff
|
||||
// 2 ^ numAttempts, limited by max
|
||||
func backoffStrategy(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
|
||||
delayTime := rhttp.DefaultBackoff(min, max, attemptNum, resp)
|
||||
return jitter(delayTime)
|
||||
}
|
||||
|
||||
// retryStrategy extends retryablehttp's DefaultRetryPolicy to log the error and response when retrying
|
||||
// DefaultRetryPolicy retries whenever err is non-nil (except for some url errors) or if returned
|
||||
// status code is 429 or 5xx (except 501)
|
||||
func retryStrategy(ctx context.Context, resp *http.Response, err error) (bool, error) {
|
||||
retry, err2 := rhttp.DefaultRetryPolicy(ctx, resp, err)
|
||||
if retry {
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
"error": err,
|
||||
"response": resp,
|
||||
}).Infof("Retrying request")
|
||||
}
|
||||
return retry, err2
|
||||
}
|
||||
|
||||
func newHTTPFetcher(ctx context.Context, fc *fetcherConfig) (*httpFetcher, int64, error) {
|
||||
reghosts, err := fc.hosts(fc.refspec)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
desc := fc.desc
|
||||
if desc.Digest.String() == "" {
|
||||
return nil, 0, fmt.Errorf("Digest is mandatory in layer descriptor")
|
||||
}
|
||||
digest := desc.Digest
|
||||
pullScope, err := repositoryScope(refspec, false)
|
||||
pullScope, err := repositoryScope(fc.refspec, false)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -121,13 +212,22 @@ func newFetcher(ctx context.Context, hosts source.RegistryHosts, refspec referen
|
||||
for _, host := range reghosts {
|
||||
if host.Host == "" || strings.Contains(host.Host, "/") {
|
||||
rErr = errors.Wrapf(rErr, "invalid destination (host %q, ref:%q, digest:%q)",
|
||||
host.Host, refspec, digest)
|
||||
host.Host, fc.refspec, digest)
|
||||
continue // Try another
|
||||
|
||||
}
|
||||
|
||||
// Prepare transport with authorization functionality
|
||||
tr := host.Client.Transport
|
||||
|
||||
if rt, ok := tr.(*rhttp.RoundTripper); ok {
|
||||
rt.Client.RetryMax = fc.maxRetries
|
||||
rt.Client.RetryWaitMin = fc.minWaitMSec
|
||||
rt.Client.RetryWaitMax = fc.maxWaitMSec
|
||||
rt.Client.Backoff = backoffStrategy
|
||||
rt.Client.CheckRetry = retryStrategy
|
||||
}
|
||||
|
||||
timeout := host.Client.Timeout
|
||||
if host.Authorizer != nil {
|
||||
tr = &transport{
|
||||
@@ -141,12 +241,12 @@ func newFetcher(ctx context.Context, hosts source.RegistryHosts, refspec referen
|
||||
blobURL := fmt.Sprintf("%s://%s/%s/blobs/%s",
|
||||
host.Scheme,
|
||||
path.Join(host.Host, host.Path),
|
||||
strings.TrimPrefix(refspec.Locator, refspec.Hostname()+"/"),
|
||||
strings.TrimPrefix(fc.refspec.Locator, fc.refspec.Hostname()+"/"),
|
||||
digest)
|
||||
url, err := redirect(ctx, blobURL, tr, timeout)
|
||||
if err != nil {
|
||||
rErr = errors.Wrapf(rErr, "failed to redirect (host %q, ref:%q, digest:%q): %v",
|
||||
host.Host, refspec, digest, err)
|
||||
host.Host, fc.refspec, digest, err)
|
||||
continue // Try another
|
||||
}
|
||||
|
||||
@@ -154,15 +254,15 @@ func newFetcher(ctx context.Context, hosts source.RegistryHosts, refspec referen
|
||||
// TODO: we should try to use the Size field in the descriptor here.
|
||||
start := time.Now() // start time before getting layer header
|
||||
size, err := getSize(ctx, url, tr, timeout)
|
||||
commonmetrics.MeasureLatency(commonmetrics.StargzHeaderGet, digest, start) // time to get layer header
|
||||
commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.StargzHeaderGet, digest, start) // time to get layer header
|
||||
if err != nil {
|
||||
rErr = errors.Wrapf(rErr, "failed to get size (host %q, ref:%q, digest:%q): %v",
|
||||
host.Host, refspec, digest, err)
|
||||
host.Host, fc.refspec, digest, err)
|
||||
continue // Try another
|
||||
}
|
||||
|
||||
// Hit one destination
|
||||
return &fetcher{
|
||||
return &httpFetcher{
|
||||
url: url,
|
||||
tr: tr,
|
||||
blobURL: blobURL,
|
||||
@@ -302,7 +402,7 @@ func getSize(ctx context.Context, url string, tr http.RoundTripper, timeout time
|
||||
headStatusCode, res.StatusCode)
|
||||
}
|
||||
|
||||
type fetcher struct {
|
||||
type httpFetcher struct {
|
||||
url string
|
||||
urlMu sync.Mutex
|
||||
tr http.RoundTripper
|
||||
@@ -318,7 +418,7 @@ type multipartReadCloser interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *options) (multipartReadCloser, error) {
|
||||
func (f *httpFetcher) fetch(ctx context.Context, rs []region, retry bool) (multipartReadCloser, error) {
|
||||
if len(rs) == 0 {
|
||||
return nil, fmt.Errorf("no request queried")
|
||||
}
|
||||
@@ -328,13 +428,6 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti
|
||||
singleRangeMode = f.isSingleRangeMode()
|
||||
)
|
||||
|
||||
if opts.ctx != nil {
|
||||
ctx = opts.ctx
|
||||
}
|
||||
if opts.tr != nil {
|
||||
tr = opts.tr
|
||||
}
|
||||
|
||||
// squash requesting chunks for reducing the total size of request header
|
||||
// (servers generally have limits for the size of headers)
|
||||
// TODO: when our request has too many ranges, we need to divide it into
|
||||
@@ -368,7 +461,7 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti
|
||||
// Recording the roundtrip latency for remote registry GET operation.
|
||||
start := time.Now()
|
||||
res, err := tr.RoundTrip(req) // NOT DefaultClient; don't want redirects
|
||||
commonmetrics.MeasureLatency(commonmetrics.RemoteRegistryGet, f.digest, start)
|
||||
commonmetrics.MeasureLatencyInMilliseconds(commonmetrics.RemoteRegistryGet, f.digest, start)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -378,7 +471,7 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse Content-Length")
|
||||
}
|
||||
return singlePartReader(region{0, size - 1}, res.Body), nil
|
||||
return newSinglePartReader(region{0, size - 1}, res.Body), nil
|
||||
} else if res.StatusCode == http.StatusPartialContent {
|
||||
mediaType, params, err := mime.ParseMediaType(res.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
@@ -386,7 +479,7 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti
|
||||
}
|
||||
if strings.HasPrefix(mediaType, "multipart/") {
|
||||
// We are getting a set of chunks as a multipart body.
|
||||
return multiPartReader(res.Body, params["boundary"]), nil
|
||||
return newMultiPartReader(res.Body, params["boundary"]), nil
|
||||
}
|
||||
|
||||
// We are getting single range
|
||||
@@ -394,7 +487,7 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse Content-Range")
|
||||
}
|
||||
return singlePartReader(reg, res.Body), nil
|
||||
return newSinglePartReader(reg, res.Body), nil
|
||||
} else if retry && res.StatusCode == http.StatusForbidden {
|
||||
log.G(ctx).Infof("Received status code: %v. Refreshing URL and retrying...", res.Status)
|
||||
|
||||
@@ -402,19 +495,19 @@ func (f *fetcher) fetch(ctx context.Context, rs []region, retry bool, opts *opti
|
||||
if err := f.refreshURL(ctx); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to refresh URL on %v", res.Status)
|
||||
}
|
||||
return f.fetch(ctx, rs, false, opts)
|
||||
return f.fetch(ctx, rs, false)
|
||||
} else if retry && res.StatusCode == http.StatusBadRequest && !singleRangeMode {
|
||||
log.G(ctx).Infof("Received status code: %v. Setting single range mode and retrying...", res.Status)
|
||||
|
||||
// gcr.io (https://storage.googleapis.com) returns 400 on multi-range request (2020 #81)
|
||||
f.singleRangeMode() // fallbacks to singe range request mode
|
||||
return f.fetch(ctx, rs, false, opts) // retries with the single range mode
|
||||
f.singleRangeMode() // fallbacks to singe range request mode
|
||||
return f.fetch(ctx, rs, false) // retries with the single range mode
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unexpected status code: %v", res.Status)
|
||||
}
|
||||
|
||||
func (f *fetcher) check() error {
|
||||
func (f *httpFetcher) check() error {
|
||||
ctx := context.Background()
|
||||
if f.timeout > 0 {
|
||||
var cancel context.CancelFunc
|
||||
@@ -457,7 +550,7 @@ func (f *fetcher) check() error {
|
||||
return fmt.Errorf("unexpected status code %v", res.StatusCode)
|
||||
}
|
||||
|
||||
func (f *fetcher) refreshURL(ctx context.Context) error {
|
||||
func (f *httpFetcher) refreshURL(ctx context.Context) error {
|
||||
newURL, err := redirect(ctx, f.blobURL, f.tr, f.timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -468,25 +561,25 @@ func (f *fetcher) refreshURL(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fetcher) genID(reg region) string {
|
||||
func (f *httpFetcher) genID(reg region) string {
|
||||
sum := sha256.Sum256([]byte(fmt.Sprintf("%s-%d-%d", f.blobURL, reg.b, reg.e)))
|
||||
return fmt.Sprintf("%x", sum)
|
||||
}
|
||||
|
||||
func (f *fetcher) singleRangeMode() {
|
||||
func (f *httpFetcher) singleRangeMode() {
|
||||
f.singleRangeMu.Lock()
|
||||
f.singleRange = true
|
||||
f.singleRangeMu.Unlock()
|
||||
}
|
||||
|
||||
func (f *fetcher) isSingleRangeMode() bool {
|
||||
func (f *httpFetcher) isSingleRangeMode() bool {
|
||||
f.singleRangeMu.Lock()
|
||||
r := f.singleRange
|
||||
f.singleRangeMu.Unlock()
|
||||
return r
|
||||
}
|
||||
|
||||
func singlePartReader(reg region, rc io.ReadCloser) multipartReadCloser {
|
||||
func newSinglePartReader(reg region, rc io.ReadCloser) multipartReadCloser {
|
||||
return &singlepartReader{
|
||||
r: rc,
|
||||
Closer: rc,
|
||||
@@ -509,7 +602,7 @@ func (sr *singlepartReader) Next() (region, io.Reader, error) {
|
||||
return region{}, nil, io.EOF
|
||||
}
|
||||
|
||||
func multiPartReader(rc io.ReadCloser, boundary string) multipartReadCloser {
|
||||
func newMultiPartReader(rc io.ReadCloser, boundary string) multipartReadCloser {
|
||||
return &multipartReader{
|
||||
m: multipart.NewReader(rc, boundary),
|
||||
Closer: rc,
|
||||
@@ -558,7 +651,6 @@ type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
ctx context.Context
|
||||
tr http.RoundTripper
|
||||
cacheOpts []cache.Option
|
||||
}
|
||||
|
||||
@@ -568,12 +660,6 @@ func WithContext(ctx context.Context) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithRoundTripper(tr http.RoundTripper) Option {
|
||||
return func(opts *options) {
|
||||
opts.tr = tr
|
||||
}
|
||||
}
|
||||
|
||||
func WithCacheOpts(cacheOpts ...cache.Option) Option {
|
||||
return func(opts *options) {
|
||||
opts.cacheOpts = cacheOpts
|
||||
@@ -597,3 +683,38 @@ func repositoryScope(refspec reference.Spec, push bool) (string, error) {
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type remoteFetcher struct {
|
||||
r Fetcher
|
||||
}
|
||||
|
||||
func (r *remoteFetcher) fetch(ctx context.Context, rs []region, retry bool) (multipartReadCloser, error) {
|
||||
var s regionSet
|
||||
for _, reg := range rs {
|
||||
s.add(reg)
|
||||
}
|
||||
reg := superRegion(s.rs)
|
||||
rc, err := r.r.Fetch(ctx, reg.b, reg.size())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newSinglePartReader(reg, rc), nil
|
||||
}
|
||||
|
||||
func (r *remoteFetcher) check() error {
|
||||
return r.r.Check()
|
||||
}
|
||||
|
||||
func (r *remoteFetcher) genID(reg region) string {
|
||||
return r.r.GenID(reg.b, reg.size())
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
Handle(ctx context.Context, desc ocispec.Descriptor) (fetcher Fetcher, size int64, err error)
|
||||
}
|
||||
|
||||
type Fetcher interface {
|
||||
Fetch(ctx context.Context, off int64, size int64) (io.ReadCloser, error)
|
||||
Check() error
|
||||
GenID(off int64, size int64) string
|
||||
}
|
||||
|
||||
52
vendor/github.com/containerd/stargz-snapshotter/fs/source/source.go
generated
vendored
52
vendor/github.com/containerd/stargz-snapshotter/fs/source/source.go
generated
vendored
@@ -70,6 +70,14 @@ const (
|
||||
// targetImageLayersLabel is a label which contains layer digests contained in
|
||||
// the target image.
|
||||
targetImageLayersLabel = "containerd.io/snapshot/remote/stargz.layers"
|
||||
|
||||
// targetImageURLsLabelPrefix is a label prefix which constructs a map from the layer index to
|
||||
// urls of the layer descriptor.
|
||||
targetImageURLsLabelPrefix = "containerd.io/snapshot/remote/urls."
|
||||
|
||||
// targetURsLLabel is a label which contains layer URL. This is only used to pass URL from containerd
|
||||
// to snapshotter.
|
||||
targetURLsLabel = "containerd.io/snapshot/remote/urls"
|
||||
)
|
||||
|
||||
// FromDefaultLabels returns a function for converting snapshot labels to
|
||||
@@ -94,31 +102,38 @@ func FromDefaultLabels(hosts RegistryHosts) GetSources {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var layersDgst []digest.Digest
|
||||
var neighboringLayers []ocispec.Descriptor
|
||||
if l, ok := labels[targetImageLayersLabel]; ok {
|
||||
layersStr := strings.Split(l, ",")
|
||||
for _, l := range layersStr {
|
||||
for i, l := range layersStr {
|
||||
d, err := digest.Parse(l)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.String() != target.String() {
|
||||
layersDgst = append(layersDgst, d)
|
||||
desc := ocispec.Descriptor{Digest: d}
|
||||
if urls, ok := labels[targetImageURLsLabelPrefix+fmt.Sprintf("%d", i)]; ok {
|
||||
desc.URLs = strings.Split(urls, ",")
|
||||
}
|
||||
neighboringLayers = append(neighboringLayers, desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var layers []ocispec.Descriptor
|
||||
for _, dgst := range append([]digest.Digest{target}, layersDgst...) {
|
||||
layers = append(layers, ocispec.Descriptor{Digest: dgst})
|
||||
targetDesc := ocispec.Descriptor{
|
||||
Digest: target,
|
||||
Annotations: labels,
|
||||
}
|
||||
if targetURLs, ok := labels[targetURLsLabel]; ok {
|
||||
targetDesc.URLs = append(targetDesc.URLs, strings.Split(targetURLs, ",")...)
|
||||
}
|
||||
|
||||
return []Source{
|
||||
{
|
||||
Hosts: hosts,
|
||||
Name: refspec,
|
||||
Target: ocispec.Descriptor{Digest: target},
|
||||
Manifest: ocispec.Manifest{Layers: layers},
|
||||
Target: targetDesc,
|
||||
Manifest: ocispec.Manifest{Layers: append([]ocispec.Descriptor{targetDesc}, neighboringLayers...)},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -146,7 +161,7 @@ func AppendDefaultLabelsHandlerWrapper(ref string, prefetchSize int64) func(f im
|
||||
c.Annotations[targetRefLabel] = ref
|
||||
c.Annotations[targetDigestLabel] = c.Digest.String()
|
||||
var layers string
|
||||
for _, l := range children[i:] {
|
||||
for i, l := range children[i:] {
|
||||
if images.IsLayerType(l.MediaType) {
|
||||
ls := fmt.Sprintf("%s,", l.Digest.String())
|
||||
// This avoids the label hits the size limitation.
|
||||
@@ -155,10 +170,17 @@ func AppendDefaultLabelsHandlerWrapper(ref string, prefetchSize int64) func(f im
|
||||
break
|
||||
}
|
||||
layers += ls
|
||||
|
||||
// Store URLs of the neighbouring layer as well.
|
||||
urlsKey := targetImageURLsLabelPrefix + fmt.Sprintf("%d", i)
|
||||
c.Annotations[urlsKey] = appendWithValidation(urlsKey, l.URLs)
|
||||
}
|
||||
}
|
||||
c.Annotations[targetImageLayersLabel] = strings.TrimSuffix(layers, ",")
|
||||
c.Annotations[config.TargetPrefetchSizeLabel] = fmt.Sprintf("%d", prefetchSize)
|
||||
|
||||
// store URL in annotation to let containerd to pass it to the snapshotter
|
||||
c.Annotations[targetURLsLabel] = appendWithValidation(targetURLsLabel, c.URLs)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,3 +188,15 @@ func AppendDefaultLabelsHandlerWrapper(ref string, prefetchSize int64) func(f im
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func appendWithValidation(key string, values []string) string {
|
||||
var v string
|
||||
for _, u := range values {
|
||||
s := fmt.Sprintf("%s,", u)
|
||||
if err := labels.Validate(key, v+s); err != nil {
|
||||
break
|
||||
}
|
||||
v += s
|
||||
}
|
||||
return strings.TrimSuffix(v, ",")
|
||||
}
|
||||
|
||||
476
vendor/github.com/containerd/stargz-snapshotter/metadata/db/db.go
generated
vendored
Normal file
476
vendor/github.com/containerd/stargz-snapshotter/metadata/db/db.go
generated
vendored
Normal file
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
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 db
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/metadata"
|
||||
"github.com/pkg/errors"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
// Metadata package stores filesystem metadata in the following schema.
|
||||
//
|
||||
// - filesystems
|
||||
// - *filesystem id* : bucket for each filesystem keyed by a unique string.
|
||||
// - nodes
|
||||
// - *node id* : bucket for each node keyed by a uniqe uint64.
|
||||
// - size : <varint> : size of the regular node.
|
||||
// - modtime : <varint> : modification time of the node.
|
||||
// - linkName : <string> : link target of symlink
|
||||
// - mode : <uvarint> : permission and mode bits (os.FileMode).
|
||||
// - uid : <varint> : uid of the owner.
|
||||
// - gid : <varint> : gid of the owner.
|
||||
// - devMajor : <varint> : the major device number for device
|
||||
// - devMinor : <varint> : the minor device number for device
|
||||
// - xattrKey : <string> : key of the first extended attribute.
|
||||
// - xattrValue : <string> : value of the first extended attribute
|
||||
// - xattrsExtra : 2nd and the following extended attribute.
|
||||
// - *key* : <string> : map of key to value string
|
||||
// - numLink : <varint> : the number of links pointing to this node.
|
||||
// - metadata
|
||||
// - *node id* : bucket for each node keyed by a uniqe uint64.
|
||||
// - childName : <string> : base name of the first child
|
||||
// - childID : <node id> : id of the first child
|
||||
// - childrenExtra : 2nd and following child nodes of directory.
|
||||
// - *basename* : <node id> : map of basename string to the child node id
|
||||
// - chunk : <encoded> : information of the first chunkn
|
||||
// - chunksExtra : 2nd and following chunks (this is rarely used so we can avoid the cost of creating the bucket)
|
||||
// - *offset* : <encoded> : keyed by gzip header offset (varint) in the estargz file to the chunk.
|
||||
// - nextOffset : <varint> : the offset of the next node with a non-zero offset.
|
||||
|
||||
var (
|
||||
bucketKeyFilesystems = []byte("filesystems")
|
||||
|
||||
bucketKeyNodes = []byte("nodes")
|
||||
bucketKeySize = []byte("size")
|
||||
bucketKeyModTime = []byte("modtime")
|
||||
bucketKeyLinkName = []byte("linkName")
|
||||
bucketKeyMode = []byte("mode")
|
||||
bucketKeyUID = []byte("uid")
|
||||
bucketKeyGID = []byte("gid")
|
||||
bucketKeyDevMajor = []byte("devMajor")
|
||||
bucketKeyDevMinor = []byte("devMinor")
|
||||
bucketKeyXattrKey = []byte("xattrKey")
|
||||
bucketKeyXattrValue = []byte("xattrValue")
|
||||
bucketKeyXattrsExtra = []byte("xattrsExtra")
|
||||
bucketKeyNumLink = []byte("numLink")
|
||||
|
||||
bucketKeyMetadata = []byte("metadata")
|
||||
bucketKeyChildName = []byte("childName")
|
||||
bucketKeyChildID = []byte("childID")
|
||||
bucketKeyChildrenExtra = []byte("childrenExtra")
|
||||
bucketKeyChunk = []byte("chunk")
|
||||
bucketKeyChunksExtra = []byte("chunksExtra")
|
||||
bucketKeyNextOffset = []byte("nextOffset")
|
||||
)
|
||||
|
||||
type childEntry struct {
|
||||
base string
|
||||
id uint32
|
||||
}
|
||||
|
||||
type chunkEntry struct {
|
||||
offset int64
|
||||
chunkOffset int64
|
||||
chunkSize int64
|
||||
chunkDigest string
|
||||
}
|
||||
|
||||
type metadataEntry struct {
|
||||
children map[string]childEntry
|
||||
chunks []chunkEntry
|
||||
nextOffset int64
|
||||
}
|
||||
|
||||
func getNodes(tx *bolt.Tx, fsID string) (*bolt.Bucket, error) {
|
||||
filesystems := tx.Bucket(bucketKeyFilesystems)
|
||||
if filesystems == nil {
|
||||
return nil, fmt.Errorf("fs %q not found: no fs is registered", fsID)
|
||||
}
|
||||
lbkt := filesystems.Bucket([]byte(fsID))
|
||||
if lbkt == nil {
|
||||
return nil, fmt.Errorf("fs bucket for %q not found", fsID)
|
||||
}
|
||||
nodes := lbkt.Bucket(bucketKeyNodes)
|
||||
if nodes == nil {
|
||||
return nil, fmt.Errorf("nodes bucket for %q not found", fsID)
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func getMetadata(tx *bolt.Tx, fsID string) (*bolt.Bucket, error) {
|
||||
filesystems := tx.Bucket(bucketKeyFilesystems)
|
||||
if filesystems == nil {
|
||||
return nil, fmt.Errorf("fs %q not found: no fs is registered", fsID)
|
||||
}
|
||||
lbkt := filesystems.Bucket([]byte(fsID))
|
||||
if lbkt == nil {
|
||||
return nil, fmt.Errorf("fs bucket for %q not found", fsID)
|
||||
}
|
||||
md := lbkt.Bucket(bucketKeyMetadata)
|
||||
if md == nil {
|
||||
return nil, fmt.Errorf("metadata bucket for fs %q not found", fsID)
|
||||
}
|
||||
return md, nil
|
||||
}
|
||||
|
||||
func getNodeBucketByID(nodes *bolt.Bucket, id uint32) (*bolt.Bucket, error) {
|
||||
b := nodes.Bucket(encodeID(id))
|
||||
if b == nil {
|
||||
return nil, fmt.Errorf("node bucket for %d not found", id)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func getMetadataBucketByID(md *bolt.Bucket, id uint32) (*bolt.Bucket, error) {
|
||||
b := md.Bucket(encodeID(id))
|
||||
if b == nil {
|
||||
return nil, fmt.Errorf("metadata bucket for %d not found", id)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func writeAttr(b *bolt.Bucket, attr *metadata.Attr) error {
|
||||
for _, v := range []struct {
|
||||
key []byte
|
||||
val int64
|
||||
}{
|
||||
{bucketKeySize, attr.Size},
|
||||
{bucketKeyUID, int64(attr.UID)},
|
||||
{bucketKeyGID, int64(attr.GID)},
|
||||
{bucketKeyDevMajor, int64(attr.DevMajor)},
|
||||
{bucketKeyDevMinor, int64(attr.DevMinor)},
|
||||
{bucketKeyNumLink, int64(attr.NumLink - 1)}, // numLink = 0 means num link = 1 in DB
|
||||
} {
|
||||
if v.val != 0 {
|
||||
val, err := encodeInt(v.val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.Put(v.key, val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if !attr.ModTime.IsZero() {
|
||||
te, err := attr.ModTime.GobEncode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.Put(bucketKeyModTime, te); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(attr.LinkName) > 0 {
|
||||
if err := b.Put(bucketKeyLinkName, []byte(attr.LinkName)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if attr.Mode != 0 {
|
||||
val, err := encodeUint(uint64(attr.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.Put(bucketKeyMode, val); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(attr.Xattrs) > 0 {
|
||||
var firstK string
|
||||
var firstV []byte
|
||||
for k, v := range attr.Xattrs {
|
||||
firstK, firstV = k, v
|
||||
break
|
||||
}
|
||||
if err := b.Put(bucketKeyXattrKey, []byte(firstK)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.Put(bucketKeyXattrValue, firstV); err != nil {
|
||||
return err
|
||||
}
|
||||
var xbkt *bolt.Bucket
|
||||
for k, v := range attr.Xattrs {
|
||||
if k == firstK || len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
if xbkt == nil {
|
||||
if xbkt := b.Bucket(bucketKeyXattrsExtra); xbkt != nil {
|
||||
// Reset
|
||||
if err := b.DeleteBucket(bucketKeyXattrsExtra); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var err error
|
||||
xbkt, err = b.CreateBucket(bucketKeyXattrsExtra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := xbkt.Put([]byte(k), v); err != nil {
|
||||
return errors.Wrapf(err, "failed to set xattr %q=%q", k, string(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readAttr(b *bolt.Bucket, attr *metadata.Attr) error {
|
||||
return b.ForEach(func(k, v []byte) error {
|
||||
switch string(k) {
|
||||
case string(bucketKeySize):
|
||||
attr.Size, _ = binary.Varint(v)
|
||||
case string(bucketKeyModTime):
|
||||
if err := (&attr.ModTime).GobDecode(v); err != nil {
|
||||
return err
|
||||
}
|
||||
case string(bucketKeyLinkName):
|
||||
attr.LinkName = string(v)
|
||||
case string(bucketKeyMode):
|
||||
mode, _ := binary.Uvarint(v)
|
||||
attr.Mode = os.FileMode(uint32(mode))
|
||||
case string(bucketKeyUID):
|
||||
i, _ := binary.Varint(v)
|
||||
attr.UID = int(i)
|
||||
case string(bucketKeyGID):
|
||||
i, _ := binary.Varint(v)
|
||||
attr.GID = int(i)
|
||||
case string(bucketKeyDevMajor):
|
||||
i, _ := binary.Varint(v)
|
||||
attr.DevMajor = int(i)
|
||||
case string(bucketKeyDevMinor):
|
||||
i, _ := binary.Varint(v)
|
||||
attr.DevMinor = int(i)
|
||||
case string(bucketKeyNumLink):
|
||||
i, _ := binary.Varint(v)
|
||||
attr.NumLink = int(i) + 1 // numLink = 0 means num link = 1 in DB
|
||||
case string(bucketKeyXattrKey):
|
||||
if attr.Xattrs == nil {
|
||||
attr.Xattrs = make(map[string][]byte)
|
||||
}
|
||||
attr.Xattrs[string(v)] = b.Get(bucketKeyXattrValue)
|
||||
case string(bucketKeyXattrsExtra):
|
||||
if err := b.Bucket(k).ForEach(func(k, v []byte) error {
|
||||
if attr.Xattrs == nil {
|
||||
attr.Xattrs = make(map[string][]byte)
|
||||
}
|
||||
attr.Xattrs[string(k)] = v
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func readNumLink(b *bolt.Bucket) int {
|
||||
// numLink = 0 means num link = 1 in BD
|
||||
numLink, _ := binary.Varint(b.Get(bucketKeyNumLink))
|
||||
return int(numLink) + 1
|
||||
}
|
||||
|
||||
func readChunks(b *bolt.Bucket, size int64) (chunks []chunkEntry, err error) {
|
||||
if chunk := b.Get(bucketKeyChunk); len(chunk) > 0 {
|
||||
e, err := decodeChunkEntry(chunk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chunks = append(chunks, e)
|
||||
}
|
||||
if chbkt := b.Bucket(bucketKeyChunksExtra); chbkt != nil {
|
||||
if err := chbkt.ForEach(func(_, v []byte) error {
|
||||
e, err := decodeChunkEntry(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chunks = append(chunks, e)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sort.Slice(chunks, func(i, j int) bool {
|
||||
return chunks[i].chunkOffset < chunks[j].chunkOffset
|
||||
})
|
||||
}
|
||||
nextOffset := size
|
||||
for i := len(chunks) - 1; i >= 0; i-- {
|
||||
chunks[i].chunkSize = nextOffset - chunks[i].chunkOffset
|
||||
nextOffset = chunks[i].chunkOffset
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func readChild(md *bolt.Bucket, base string) (uint32, error) {
|
||||
if base == string(md.Get(bucketKeyChildName)) {
|
||||
return decodeID(md.Get(bucketKeyChildID)), nil
|
||||
}
|
||||
cbkt := md.Bucket(bucketKeyChildrenExtra)
|
||||
if cbkt == nil {
|
||||
return 0, fmt.Errorf("extra children not found")
|
||||
}
|
||||
eid := cbkt.Get([]byte(base))
|
||||
if len(eid) == 0 {
|
||||
return 0, fmt.Errorf("children %q not found", base)
|
||||
}
|
||||
return decodeID(eid), nil
|
||||
}
|
||||
|
||||
func writeMetadataEntry(md *bolt.Bucket, m *metadataEntry) error {
|
||||
if len(m.children) > 0 {
|
||||
var firstChildName string
|
||||
var firstChild childEntry
|
||||
for name, child := range m.children {
|
||||
firstChildName, firstChild = name, child
|
||||
break
|
||||
}
|
||||
if err := md.Put(bucketKeyChildID, encodeID(firstChild.id)); err != nil {
|
||||
return errors.Wrapf(err, "failed to put id of first child %q", firstChildName)
|
||||
}
|
||||
if err := md.Put(bucketKeyChildName, []byte(firstChildName)); err != nil {
|
||||
return errors.Wrapf(err, "failed to put name first child %q", firstChildName)
|
||||
}
|
||||
if len(m.children) > 1 {
|
||||
var cbkt *bolt.Bucket
|
||||
for k, c := range m.children {
|
||||
if k == firstChildName {
|
||||
continue
|
||||
}
|
||||
if cbkt == nil {
|
||||
if cbkt := md.Bucket(bucketKeyChildrenExtra); cbkt != nil {
|
||||
// Reset
|
||||
if err := md.DeleteBucket(bucketKeyChildrenExtra); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var err error
|
||||
cbkt, err = md.CreateBucket(bucketKeyChildrenExtra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := cbkt.Put([]byte(c.base), encodeID(c.id)); err != nil {
|
||||
return errors.Wrapf(err, "failed to add child ID %q", c.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(m.chunks) > 0 {
|
||||
first := m.chunks[0]
|
||||
if err := md.Put(bucketKeyChunk, encodeChunkEntry(first)); err != nil {
|
||||
return errors.Wrapf(err, "failed to set chunk %q", first.offset)
|
||||
}
|
||||
var cbkt *bolt.Bucket
|
||||
for _, e := range m.chunks[1:] {
|
||||
if cbkt == nil {
|
||||
if cbkt := md.Bucket(bucketKeyChunksExtra); cbkt != nil {
|
||||
// Reset
|
||||
if err := md.DeleteBucket(bucketKeyChunksExtra); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var err error
|
||||
cbkt, err = md.CreateBucket(bucketKeyChunksExtra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
eoff, err := encodeInt(e.offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cbkt.Put(eoff, encodeChunkEntry(e)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if m.nextOffset > 0 {
|
||||
if err := putInt(md, bucketKeyNextOffset, m.nextOffset); err != nil {
|
||||
return errors.Wrapf(err, "failed to set next offset value %d", m.nextOffset)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeChunkEntry(e chunkEntry) []byte {
|
||||
eb := make([]byte, 16+len([]byte(e.chunkDigest)))
|
||||
binary.BigEndian.PutUint64(eb[0:8], uint64(e.chunkOffset))
|
||||
binary.BigEndian.PutUint64(eb[8:16], uint64(e.offset))
|
||||
copy(eb[16:], []byte(e.chunkDigest))
|
||||
return eb
|
||||
}
|
||||
|
||||
func decodeChunkEntry(d []byte) (e chunkEntry, _ error) {
|
||||
if len(d) < 16 {
|
||||
return e, fmt.Errorf("mulformed chunk entry (len:%d)", len(d))
|
||||
}
|
||||
e.chunkOffset = int64(binary.BigEndian.Uint64(d[0:8]))
|
||||
e.offset = int64(binary.BigEndian.Uint64(d[8:16]))
|
||||
if len(d) > 16 {
|
||||
e.chunkDigest = string(d[16:])
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func putInt(b *bolt.Bucket, k []byte, v int64) error {
|
||||
i, err := encodeInt(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.Put(k, i)
|
||||
}
|
||||
|
||||
func encodeID(id uint32) []byte {
|
||||
b := [4]byte{}
|
||||
binary.BigEndian.PutUint32(b[:], id)
|
||||
return b[:]
|
||||
}
|
||||
|
||||
func decodeID(b []byte) uint32 {
|
||||
return binary.BigEndian.Uint32(b)
|
||||
}
|
||||
|
||||
func encodeInt(i int64) ([]byte, error) {
|
||||
var (
|
||||
buf [binary.MaxVarintLen64]byte
|
||||
iEncoded = buf[:]
|
||||
)
|
||||
iEncoded = iEncoded[:binary.PutVarint(iEncoded, i)]
|
||||
|
||||
if len(iEncoded) == 0 {
|
||||
return nil, fmt.Errorf("failed encoding integer = %v", i)
|
||||
}
|
||||
return iEncoded, nil
|
||||
}
|
||||
|
||||
func encodeUint(i uint64) ([]byte, error) {
|
||||
var (
|
||||
buf [binary.MaxVarintLen64]byte
|
||||
iEncoded = buf[:]
|
||||
)
|
||||
iEncoded = iEncoded[:binary.PutUvarint(iEncoded, i)]
|
||||
|
||||
if len(iEncoded) == 0 {
|
||||
return nil, fmt.Errorf("failed encoding integer = %v", i)
|
||||
}
|
||||
return iEncoded, nil
|
||||
}
|
||||
985
vendor/github.com/containerd/stargz-snapshotter/metadata/db/reader.go
generated
vendored
Normal file
985
vendor/github.com/containerd/stargz-snapshotter/metadata/db/reader.go
generated
vendored
Normal file
@@ -0,0 +1,985 @@
|
||||
/*
|
||||
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 db
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
"github.com/containerd/stargz-snapshotter/metadata"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/xid"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// reader stores filesystem metadata parsed from eStargz to metadata DB
|
||||
// and provides methods to read them.
|
||||
type reader struct {
|
||||
db *bolt.DB
|
||||
fsID string
|
||||
rootID uint32
|
||||
tocDigest digest.Digest
|
||||
sr *io.SectionReader
|
||||
|
||||
curID uint32
|
||||
curIDMu sync.Mutex
|
||||
initG *errgroup.Group
|
||||
|
||||
decompressor metadata.Decompressor
|
||||
}
|
||||
|
||||
func (r *reader) nextID() (uint32, error) {
|
||||
r.curIDMu.Lock()
|
||||
defer r.curIDMu.Unlock()
|
||||
if r.curID == math.MaxUint32 {
|
||||
return 0, fmt.Errorf("sequence id too large")
|
||||
}
|
||||
r.curID++
|
||||
return r.curID, nil
|
||||
}
|
||||
|
||||
// NewReader parses an eStargz and stores filesystem metadata to
|
||||
// the provided DB.
|
||||
func NewReader(db *bolt.DB, sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error) {
|
||||
var rOpts metadata.Options
|
||||
for _, o := range opts {
|
||||
if err := o(&rOpts); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to apply option")
|
||||
}
|
||||
}
|
||||
|
||||
gzipCompressors := []metadata.Decompressor{new(estargz.GzipDecompressor), new(estargz.LegacyGzipDecompressor)}
|
||||
decompressors := append(gzipCompressors, rOpts.Decompressors...)
|
||||
|
||||
// Determine the size to fetch. Try to fetch as many bytes as possible.
|
||||
fetchSize := maxFooterSize(sr.Size(), decompressors...)
|
||||
if maybeTocOffset := rOpts.TOCOffset; maybeTocOffset > fetchSize {
|
||||
if maybeTocOffset > sr.Size() {
|
||||
return nil, fmt.Errorf("blob size %d is smaller than the toc offset", sr.Size())
|
||||
}
|
||||
fetchSize = sr.Size() - maybeTocOffset
|
||||
}
|
||||
|
||||
start := time.Now() // before getting layer footer
|
||||
footer := make([]byte, fetchSize)
|
||||
if _, err := sr.ReadAt(footer, sr.Size()-fetchSize); err != nil {
|
||||
return nil, fmt.Errorf("error reading footer: %v", err)
|
||||
}
|
||||
if rOpts.Telemetry != nil && rOpts.Telemetry.GetFooterLatency != nil {
|
||||
rOpts.Telemetry.GetFooterLatency(start)
|
||||
}
|
||||
|
||||
var allErr error
|
||||
var tocR io.ReadCloser
|
||||
var decompressor metadata.Decompressor
|
||||
for _, d := range decompressors {
|
||||
fSize := d.FooterSize()
|
||||
fOffset := positive(int64(len(footer)) - fSize)
|
||||
maybeTocBytes := footer[:fOffset]
|
||||
_, tocOffset, tocSize, err := d.ParseFooter(footer[fOffset:])
|
||||
if err != nil {
|
||||
allErr = multierror.Append(allErr, err)
|
||||
continue
|
||||
}
|
||||
if tocSize <= 0 {
|
||||
tocSize = sr.Size() - tocOffset - fSize
|
||||
}
|
||||
if tocSize < int64(len(maybeTocBytes)) {
|
||||
maybeTocBytes = maybeTocBytes[:tocSize]
|
||||
}
|
||||
tocR, err = decompressTOC(d, sr, tocOffset, tocSize, maybeTocBytes, rOpts)
|
||||
if err != nil {
|
||||
allErr = multierror.Append(allErr, err)
|
||||
continue
|
||||
}
|
||||
decompressor = d
|
||||
break
|
||||
}
|
||||
if tocR == nil {
|
||||
if allErr == nil {
|
||||
return nil, fmt.Errorf("failed to get the reader of TOC: unknown")
|
||||
}
|
||||
return nil, errors.Wrapf(allErr, "failed to get the reader of TOC")
|
||||
}
|
||||
defer tocR.Close()
|
||||
r := &reader{sr: sr, db: db, initG: new(errgroup.Group), decompressor: decompressor}
|
||||
if err := r.init(tocR, rOpts); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to initialize matadata")
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func maxFooterSize(blobSize int64, decompressors ...metadata.Decompressor) (res int64) {
|
||||
for _, d := range decompressors {
|
||||
if s := d.FooterSize(); res < s && s <= blobSize {
|
||||
res = s
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func decompressTOC(d metadata.Decompressor, sr *io.SectionReader, tocOff, tocSize int64, tocBytes []byte, opts metadata.Options) (io.ReadCloser, error) {
|
||||
if len(tocBytes) > 0 {
|
||||
start := time.Now() // before getting TOC
|
||||
tocR, err := d.DecompressTOC(bytes.NewReader(tocBytes))
|
||||
if err == nil {
|
||||
if opts.Telemetry != nil && opts.Telemetry.GetTocLatency != nil {
|
||||
opts.Telemetry.GetTocLatency(start)
|
||||
}
|
||||
return tocR, nil
|
||||
}
|
||||
}
|
||||
|
||||
start := time.Now() // before getting TOC
|
||||
tocBytes = make([]byte, tocSize)
|
||||
if _, err := sr.ReadAt(tocBytes, tocOff); err != nil {
|
||||
return nil, fmt.Errorf("error reading %d byte TOC targz: %v", len(tocBytes), err)
|
||||
}
|
||||
r, err := d.DecompressTOC(bytes.NewReader(tocBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.Telemetry != nil && opts.Telemetry.GetTocLatency != nil {
|
||||
opts.Telemetry.GetTocLatency(start)
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// RootID returns ID of the root node.
|
||||
func (r *reader) RootID() uint32 {
|
||||
return r.rootID
|
||||
}
|
||||
|
||||
func (r *reader) TOCDigest() digest.Digest {
|
||||
return r.tocDigest
|
||||
}
|
||||
|
||||
// Clone returns a new reader identical to the current reader
|
||||
// but uses the provided section reader for retrieving file paylaods.
|
||||
func (r *reader) Clone(sr *io.SectionReader) (metadata.Reader, error) {
|
||||
if err := r.waitInit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &reader{
|
||||
db: r.db,
|
||||
fsID: r.fsID,
|
||||
rootID: r.rootID,
|
||||
sr: sr,
|
||||
initG: new(errgroup.Group),
|
||||
decompressor: r.decompressor,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *reader) init(decompressedR io.Reader, rOpts metadata.Options) (retErr error) {
|
||||
start := time.Now() // before parsing TOC JSON
|
||||
|
||||
// Initialize root node
|
||||
var ok bool
|
||||
for i := 0; i < 100; i++ {
|
||||
fsID := xid.New().String()
|
||||
if err := r.initRootNode(fsID); err != nil {
|
||||
if errors.Is(err, bolt.ErrBucketExists) {
|
||||
continue // try with another id
|
||||
}
|
||||
return errors.Wrapf(err, "failed to initialize root node %q", fsID)
|
||||
}
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get a unique id for metadata reader")
|
||||
}
|
||||
|
||||
f, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
closeFunc := func() (closeErr error) {
|
||||
name := f.Name()
|
||||
if err := f.Close(); err != nil {
|
||||
closeErr = multierror.Append(closeErr, err)
|
||||
}
|
||||
if err := os.Remove(name); err != nil {
|
||||
closeErr = multierror.Append(closeErr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
if err := closeFunc(); err != nil {
|
||||
retErr = multierror.Append(retErr, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if err := f.Chmod(0600); err != nil {
|
||||
return err
|
||||
}
|
||||
dgstr := digest.Canonical.Digester()
|
||||
if _, err := io.Copy(f, io.TeeReader(decompressedR, dgstr.Hash())); err != nil {
|
||||
return errors.Wrapf(err, "failed to read TOC")
|
||||
}
|
||||
r.tocDigest = dgstr.Digest()
|
||||
|
||||
// Initialize file metadata in background. All operations refer to these metadata must wait
|
||||
// until this initialization ends.
|
||||
r.initG.Go(func() error {
|
||||
defer closeFunc()
|
||||
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.initNodes(f); err != nil {
|
||||
return err
|
||||
}
|
||||
if rOpts.Telemetry != nil && rOpts.Telemetry.DeserializeTocLatency != nil {
|
||||
rOpts.Telemetry.DeserializeTocLatency(start)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *reader) initRootNode(fsID string) error {
|
||||
return r.db.Batch(func(tx *bolt.Tx) (err error) {
|
||||
filesystems, err := tx.CreateBucketIfNotExists(bucketKeyFilesystems)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lbkt, err := filesystems.CreateBucket([]byte(fsID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.fsID = fsID
|
||||
if _, err := lbkt.CreateBucket(bucketKeyMetadata); err != nil {
|
||||
return err
|
||||
}
|
||||
nodes, err := lbkt.CreateBucket(bucketKeyNodes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootID, err := r.nextID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootBucket, err := nodes.CreateBucket(encodeID(rootID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeAttr(rootBucket, &metadata.Attr{
|
||||
Mode: os.ModeDir | 0755,
|
||||
NumLink: 2, // The directory itself(.) and the parent link to this directory.
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
r.rootID = rootID
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (r *reader) initNodes(tr io.Reader) error {
|
||||
dec := json.NewDecoder(tr)
|
||||
for {
|
||||
t, err := dec.Token()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get JSON token")
|
||||
}
|
||||
if ele, ok := t.(string); ok {
|
||||
if ele == "version" {
|
||||
continue
|
||||
}
|
||||
if ele == "entries" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if de, ok := t.(json.Delim); ok {
|
||||
if de.String() == "[" {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
md := make(map[uint32]*metadataEntry)
|
||||
if err := r.db.Batch(func(tx *bolt.Tx) (err error) {
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nodes.FillPercent = 1.0 // we only do sequential write to this bucket
|
||||
var wantNextOffsetID uint32
|
||||
var lastEntBucketID uint32
|
||||
var lastEntSize int64
|
||||
var attr metadata.Attr
|
||||
var ent estargz.TOCEntry
|
||||
for dec.More() {
|
||||
resetEnt(&ent)
|
||||
if err := dec.Decode(&ent); err != nil {
|
||||
return err
|
||||
}
|
||||
ent.Name = cleanEntryName(ent.Name)
|
||||
if ent.Type == "chunk" {
|
||||
if lastEntBucketID == 0 {
|
||||
return fmt.Errorf("chunk entry must not be the topmost")
|
||||
}
|
||||
if ent.ChunkSize == 0 { // last chunk in this file
|
||||
ent.ChunkSize = lastEntSize - ent.ChunkOffset
|
||||
}
|
||||
}
|
||||
if ent.ChunkSize == 0 && ent.Size != 0 {
|
||||
ent.ChunkSize = ent.Size
|
||||
}
|
||||
if ent.Type != "chunk" {
|
||||
var id uint32
|
||||
var b *bolt.Bucket
|
||||
if ent.Type == "hardlink" {
|
||||
id, err = getIDByName(md, ent.LinkName, r.rootID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "%q is a hardlink but cannot get link destination %q", ent.Name, ent.LinkName)
|
||||
}
|
||||
b, err = getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "cannot get hardlink destination %q ==> %q (%d)", ent.Name, ent.LinkName, id)
|
||||
}
|
||||
numLink, _ := binary.Varint(b.Get(bucketKeyNumLink))
|
||||
if err := putInt(b, bucketKeyNumLink, numLink+1); err != nil {
|
||||
return errors.Wrapf(err, "cannot put NumLink of %q ==> %q", ent.Name, ent.LinkName)
|
||||
}
|
||||
} else {
|
||||
// Write node bucket
|
||||
var found bool
|
||||
if ent.Type == "dir" {
|
||||
// Check if this directory is already created, if so overwrite it.
|
||||
id, err = getIDByName(md, ent.Name, r.rootID)
|
||||
if err == nil {
|
||||
b, err = getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get directory bucket %d", id)
|
||||
}
|
||||
found = true
|
||||
ent.NumLink = readNumLink(b)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// No existing node. Create a new one.
|
||||
id, err = r.nextID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err = nodes.CreateBucket(encodeID(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ent.NumLink = 1 // at least the parent dir references this directory.
|
||||
if ent.Type == "dir" {
|
||||
ent.NumLink++ // at least "." references this directory.
|
||||
}
|
||||
}
|
||||
if err := writeAttr(b, attrFromTOCEntry(&ent, &attr)); err != nil {
|
||||
return errors.Wrapf(err, "failed to set attr to %d(%q)", id, ent.Name)
|
||||
}
|
||||
}
|
||||
|
||||
pdirName := parentDir(ent.Name)
|
||||
pid, pb, err := r.getOrCreateDir(nodes, md, pdirName, r.rootID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to create parent directory %q of %q", pdirName, ent.Name)
|
||||
}
|
||||
if err := setChild(md, pb, pid, path.Base(ent.Name), id, ent.Type == "dir"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ent.Offset > 0 && wantNextOffsetID > 0 {
|
||||
if md[wantNextOffsetID] == nil {
|
||||
md[wantNextOffsetID] = &metadataEntry{}
|
||||
}
|
||||
md[wantNextOffsetID].nextOffset = ent.Offset
|
||||
}
|
||||
if ent.Type == "reg" && ent.Size > 0 {
|
||||
wantNextOffsetID = id
|
||||
}
|
||||
|
||||
lastEntSize = ent.Size
|
||||
lastEntBucketID = id
|
||||
}
|
||||
if (ent.Type == "reg" && ent.Size > 0) || (ent.Type == "chunk" && ent.ChunkSize > 0) {
|
||||
if md[lastEntBucketID] == nil {
|
||||
md[lastEntBucketID] = &metadataEntry{}
|
||||
}
|
||||
ce := chunkEntry{ent.Offset, ent.ChunkOffset, ent.ChunkSize, ent.ChunkDigest}
|
||||
md[lastEntBucketID].chunks = append(md[lastEntBucketID].chunks, ce)
|
||||
}
|
||||
}
|
||||
if wantNextOffsetID > 0 {
|
||||
if md[wantNextOffsetID] == nil {
|
||||
md[wantNextOffsetID] = &metadataEntry{}
|
||||
}
|
||||
md[wantNextOffsetID].nextOffset = r.sr.Size()
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addendum := make([]struct {
|
||||
id []byte
|
||||
md *metadataEntry
|
||||
}, len(md))
|
||||
i := 0
|
||||
for id, d := range md {
|
||||
addendum[i].id, addendum[i].md = encodeID(id), d
|
||||
i++
|
||||
}
|
||||
sort.Slice(addendum, func(i, j int) bool {
|
||||
return bytes.Compare(addendum[i].id, addendum[j].id) < 0
|
||||
})
|
||||
if err := r.db.Batch(func(tx *bolt.Tx) (err error) {
|
||||
meta, err := getMetadata(tx, r.fsID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
meta.FillPercent = 1.0 // we only do sequential write to this bucket
|
||||
for _, m := range addendum {
|
||||
md, err := meta.CreateBucket(m.id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeMetadataEntry(md, m.md); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *reader) getOrCreateDir(nodes *bolt.Bucket, md map[uint32]*metadataEntry, d string, rootID uint32) (id uint32, b *bolt.Bucket, err error) {
|
||||
id, err = getIDByName(md, d, rootID)
|
||||
if err != nil {
|
||||
id, err = r.nextID()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
b, err = nodes.CreateBucket(encodeID(id))
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
attr := &metadata.Attr{
|
||||
Mode: os.ModeDir | 0755,
|
||||
NumLink: 2, // The directory itself(.) and the parent link to this directory.
|
||||
}
|
||||
if err := writeAttr(b, attr); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if d != "" {
|
||||
pid, pb, err := r.getOrCreateDir(nodes, md, parentDir(d), rootID)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if err := setChild(md, pb, pid, path.Base(d), id, true); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
b, err = getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return 0, nil, errors.Wrapf(err, "failed to get dir bucket %d", id)
|
||||
}
|
||||
}
|
||||
return id, b, nil
|
||||
}
|
||||
|
||||
func (r *reader) waitInit() error {
|
||||
// TODO: add timeout
|
||||
return errors.Wrapf(r.initG.Wait(), "initialization failed")
|
||||
}
|
||||
|
||||
func (r *reader) view(fn func(tx *bolt.Tx) error) error {
|
||||
if err := r.waitInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.db.View(func(tx *bolt.Tx) error {
|
||||
return fn(tx)
|
||||
})
|
||||
}
|
||||
|
||||
func (r *reader) update(fn func(tx *bolt.Tx) error) error {
|
||||
if err := r.waitInit(); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.db.Batch(func(tx *bolt.Tx) error {
|
||||
return fn(tx)
|
||||
})
|
||||
}
|
||||
|
||||
// Close closes this reader. This removes underlying filesystem metadata as well.
|
||||
func (r *reader) Close() error {
|
||||
return r.update(func(tx *bolt.Tx) (err error) {
|
||||
filesystems := tx.Bucket(bucketKeyFilesystems)
|
||||
if filesystems == nil {
|
||||
return nil
|
||||
}
|
||||
return filesystems.DeleteBucket([]byte(r.fsID))
|
||||
})
|
||||
}
|
||||
|
||||
// GetOffset returns an offset of a node.
|
||||
func (r *reader) GetOffset(id uint32) (offset int64, _ error) {
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
metadataEntries, err := getMetadata(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "metadata bucket of %q not found for searching offset of %d", r.fsID, id)
|
||||
}
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
size, _ := binary.Varint(b.Get(bucketKeySize))
|
||||
if md, err := getMetadataBucketByID(metadataEntries, id); err == nil {
|
||||
chunks, err := readChunks(md, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(chunks) > 0 {
|
||||
offset = chunks[0].offset
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetAttr returns file attribute of specified node.
|
||||
func (r *reader) GetAttr(id uint32) (attr metadata.Attr, _ error) {
|
||||
if r.rootID == id { // no need to wait for root dir
|
||||
if err := r.db.View(func(tx *bolt.Tx) error {
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for sarching attr %d", r.fsID, id)
|
||||
}
|
||||
b, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get attr bucket %d", id)
|
||||
}
|
||||
return readAttr(b, &attr)
|
||||
}); err != nil {
|
||||
return metadata.Attr{}, err
|
||||
}
|
||||
return attr, nil
|
||||
}
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for sarching attr %d", r.fsID, id)
|
||||
}
|
||||
b, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get attr bucket %d", id)
|
||||
}
|
||||
return readAttr(b, &attr)
|
||||
}); err != nil {
|
||||
return metadata.Attr{}, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetChild returns a child node that has the specified base name.
|
||||
func (r *reader) GetChild(pid uint32, base string) (id uint32, attr metadata.Attr, _ error) {
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
metadataEntries, err := getMetadata(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "metadata bucket of %q not found for getting child of %d", r.fsID, pid)
|
||||
}
|
||||
md, err := getMetadataBucketByID(metadataEntries, pid)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get parent metadata %d", pid)
|
||||
}
|
||||
id, err = readChild(md, base)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read child %q of %d", base, pid)
|
||||
}
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for getting child of %d", r.fsID, pid)
|
||||
}
|
||||
child, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get child bucket %d", id)
|
||||
}
|
||||
return readAttr(child, &attr)
|
||||
}); err != nil {
|
||||
return 0, metadata.Attr{}, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ForeachChild calls the specified callback function for each child node.
|
||||
// When the callback returns non-nil error, this stops the iteration.
|
||||
func (r *reader) ForeachChild(id uint32, f func(name string, id uint32, mode os.FileMode) bool) error {
|
||||
type childInfo struct {
|
||||
id uint32
|
||||
mode os.FileMode
|
||||
}
|
||||
children := make(map[string]childInfo)
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
metadataEntries, err := getMetadata(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for getting child of %d", r.fsID, id)
|
||||
}
|
||||
md, err := getMetadataBucketByID(metadataEntries, id)
|
||||
if err != nil {
|
||||
return nil // no child
|
||||
}
|
||||
|
||||
var nodes *bolt.Bucket
|
||||
firstName := md.Get(bucketKeyChildName)
|
||||
if len(firstName) != 0 {
|
||||
firstID := decodeID(md.Get(bucketKeyChildID))
|
||||
if nodes == nil {
|
||||
nodes, err = getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for getting children of %d", r.fsID, id)
|
||||
}
|
||||
}
|
||||
firstChild, err := getNodeBucketByID(nodes, firstID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get first child bucket %d", firstID)
|
||||
}
|
||||
mode, _ := binary.Uvarint(firstChild.Get(bucketKeyMode))
|
||||
children[string(firstName)] = childInfo{firstID, os.FileMode(uint32(mode))}
|
||||
}
|
||||
|
||||
cbkt := md.Bucket(bucketKeyChildrenExtra)
|
||||
if cbkt == nil {
|
||||
return nil // no child
|
||||
}
|
||||
if nodes == nil {
|
||||
nodes, err = getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for getting children of %d", r.fsID, id)
|
||||
}
|
||||
}
|
||||
return cbkt.ForEach(func(k, v []byte) error {
|
||||
id := decodeID(v)
|
||||
child, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get child bucket %d", id)
|
||||
}
|
||||
mode, _ := binary.Uvarint(child.Get(bucketKeyMode))
|
||||
children[string(k)] = childInfo{id, os.FileMode(uint32(mode))}
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
for k, e := range children {
|
||||
if !f(k, e.id, e.mode) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenFile returns a section reader of the specified node.
|
||||
func (r *reader) OpenFile(id uint32) (metadata.File, error) {
|
||||
var chunks []chunkEntry
|
||||
var size int64
|
||||
|
||||
var nextOffset int64
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "nodes bucket of %q not found for opening %d", r.fsID, id)
|
||||
}
|
||||
b, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get file bucket %d", id)
|
||||
}
|
||||
size, _ = binary.Varint(b.Get(bucketKeySize))
|
||||
m, _ := binary.Uvarint(b.Get(bucketKeyMode))
|
||||
if !os.FileMode(uint32(m)).IsRegular() {
|
||||
return fmt.Errorf("%q is not a regular file", id)
|
||||
}
|
||||
|
||||
metadataEntries, err := getMetadata(tx, r.fsID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "metadata bucket of %q not found for opening %d", r.fsID, id)
|
||||
}
|
||||
if md, err := getMetadataBucketByID(metadataEntries, id); err == nil {
|
||||
chunks, err = readChunks(md, size)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get chunks")
|
||||
}
|
||||
nextOffset, _ = binary.Varint(md.Get(bucketKeyNextOffset))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fr := &fileReader{
|
||||
r: r,
|
||||
size: size,
|
||||
ents: chunks,
|
||||
nextOffset: nextOffset,
|
||||
}
|
||||
return &file{io.NewSectionReader(fr, 0, size), chunks}, nil
|
||||
}
|
||||
|
||||
type file struct {
|
||||
io.ReaderAt
|
||||
ents []chunkEntry
|
||||
}
|
||||
|
||||
func (fr *file) ChunkEntryForOffset(offset int64) (off int64, size int64, dgst string, ok bool) {
|
||||
i := sort.Search(len(fr.ents), func(i int) bool {
|
||||
e := fr.ents[i]
|
||||
return e.chunkOffset >= offset || (offset > e.chunkOffset && offset < e.chunkOffset+e.chunkSize)
|
||||
})
|
||||
if i == len(fr.ents) {
|
||||
return 0, 0, "", false
|
||||
}
|
||||
ci := fr.ents[i]
|
||||
return ci.chunkOffset, ci.chunkSize, ci.chunkDigest, true
|
||||
}
|
||||
|
||||
type fileReader struct {
|
||||
r *reader
|
||||
size int64
|
||||
ents []chunkEntry
|
||||
nextOffset int64
|
||||
}
|
||||
|
||||
// ReadAt reads file payload of this file.
|
||||
func (fr *fileReader) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
if off >= fr.size {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if off < 0 {
|
||||
return 0, errors.New("invalid offset")
|
||||
}
|
||||
|
||||
var ent chunkEntry
|
||||
switch len(fr.ents) {
|
||||
case 0:
|
||||
return 0, errors.New("no chunk is registered")
|
||||
case 1:
|
||||
ent = fr.ents[0]
|
||||
if ent.chunkOffset > off {
|
||||
return 0, fmt.Errorf("no chunk coveres offset %d", off)
|
||||
}
|
||||
default:
|
||||
i := sort.Search(len(fr.ents), func(i int) bool {
|
||||
return fr.ents[i].chunkOffset > off
|
||||
})
|
||||
if i == 0 {
|
||||
return 0, fmt.Errorf("no chunk coveres offset %d", off)
|
||||
}
|
||||
ent = fr.ents[i-1]
|
||||
}
|
||||
|
||||
compressedBytesRemain := fr.nextOffset - ent.offset
|
||||
bufSize := int(2 << 20)
|
||||
if bufSize > int(compressedBytesRemain) {
|
||||
bufSize = int(compressedBytesRemain)
|
||||
}
|
||||
|
||||
br := bufio.NewReaderSize(io.NewSectionReader(fr.r.sr, ent.offset, compressedBytesRemain), bufSize)
|
||||
if _, err := br.Peek(bufSize); err != nil {
|
||||
return 0, fmt.Errorf("failed to peek read file payload: %v", err)
|
||||
}
|
||||
dr, err := fr.r.decompressor.Reader(br)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("fileReader.ReadAt.decompressor.Reader: %v", err)
|
||||
}
|
||||
defer dr.Close()
|
||||
base := off - ent.chunkOffset
|
||||
if n, err := io.CopyN(ioutil.Discard, dr, base); n != base || err != nil {
|
||||
return 0, fmt.Errorf("discard of %d bytes = %v, %v", base, n, err)
|
||||
}
|
||||
return io.ReadFull(dr, p)
|
||||
}
|
||||
|
||||
// TODO: share it with memory pkg
|
||||
func attrFromTOCEntry(src *estargz.TOCEntry, dst *metadata.Attr) *metadata.Attr {
|
||||
dst.Size = src.Size
|
||||
dst.ModTime, _ = time.Parse(time.RFC3339, src.ModTime3339)
|
||||
dst.LinkName = src.LinkName
|
||||
dst.Mode = src.Stat().Mode()
|
||||
dst.UID = src.UID
|
||||
dst.GID = src.GID
|
||||
dst.DevMajor = src.DevMajor
|
||||
dst.DevMinor = src.DevMinor
|
||||
dst.Xattrs = src.Xattrs
|
||||
dst.NumLink = src.NumLink
|
||||
return dst
|
||||
}
|
||||
|
||||
func getIDByName(md map[uint32]*metadataEntry, name string, rootID uint32) (uint32, error) {
|
||||
name = cleanEntryName(name)
|
||||
if name == "" {
|
||||
return rootID, nil
|
||||
}
|
||||
dir, base := filepath.Split(name)
|
||||
pid, err := getIDByName(md, dir, rootID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if md[pid] == nil {
|
||||
return 0, fmt.Errorf("not found metadata of %d", pid)
|
||||
}
|
||||
if md[pid].children == nil {
|
||||
return 0, fmt.Errorf("not found children of %q", pid)
|
||||
}
|
||||
c, ok := md[pid].children[base]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("not found child %q in %d", base, pid)
|
||||
}
|
||||
return c.id, nil
|
||||
}
|
||||
|
||||
func setChild(md map[uint32]*metadataEntry, pb *bolt.Bucket, pid uint32, base string, id uint32, isDir bool) error {
|
||||
if md[pid] == nil {
|
||||
md[pid] = &metadataEntry{}
|
||||
}
|
||||
if md[pid].children == nil {
|
||||
md[pid].children = make(map[string]childEntry)
|
||||
}
|
||||
md[pid].children[base] = childEntry{base, id}
|
||||
if isDir {
|
||||
numLink, _ := binary.Varint(pb.Get(bucketKeyNumLink))
|
||||
if err := putInt(pb, bucketKeyNumLink, numLink+1); err != nil {
|
||||
return errors.Wrapf(err, "cannot add numlink for children")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parentDir(p string) string {
|
||||
dir, _ := path.Split(p)
|
||||
return strings.TrimSuffix(dir, "/")
|
||||
}
|
||||
|
||||
func cleanEntryName(name string) string {
|
||||
// Use path.Clean to consistently deal with path separators across platforms.
|
||||
return strings.TrimPrefix(path.Clean("/"+name), "/")
|
||||
}
|
||||
|
||||
func resetEnt(ent *estargz.TOCEntry) {
|
||||
ent.Name = ""
|
||||
ent.Type = ""
|
||||
ent.Size = 0
|
||||
ent.ModTime3339 = ""
|
||||
ent.LinkName = ""
|
||||
ent.Mode = 0
|
||||
ent.UID = 0
|
||||
ent.GID = 0
|
||||
ent.Uname = ""
|
||||
ent.Gname = ""
|
||||
ent.Offset = 0
|
||||
ent.DevMajor = 0
|
||||
ent.DevMinor = 0
|
||||
ent.NumLink = 0
|
||||
ent.Xattrs = nil
|
||||
ent.Digest = ""
|
||||
ent.ChunkOffset = 0
|
||||
ent.ChunkSize = 0
|
||||
ent.ChunkDigest = ""
|
||||
}
|
||||
|
||||
func positive(n int64) int64 {
|
||||
if n < 0 {
|
||||
return 0
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (r *reader) NumOfNodes() (i int, _ error) {
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nodes.ForEach(func(k, v []byte) error {
|
||||
b := nodes.Bucket(k)
|
||||
if b == nil {
|
||||
return fmt.Errorf("entry bucket for %q not found", string(k))
|
||||
}
|
||||
var attr metadata.Attr
|
||||
if err := readAttr(b, &attr); err != nil {
|
||||
return err
|
||||
}
|
||||
i++
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *reader) NumOfChunks(id uint32) (i int, _ error) {
|
||||
if err := r.view(func(tx *bolt.Tx) error {
|
||||
metadataEntries, err := getMetadata(tx, r.fsID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
md, err := getMetadataBucketByID(metadataEntries, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nodes, err := getNodes(tx, r.fsID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := getNodeBucketByID(nodes, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
size, _ := binary.Varint(b.Get(bucketKeySize))
|
||||
chunks, err := readChunks(md, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i = len(chunks)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return
|
||||
}
|
||||
281
vendor/github.com/containerd/stargz-snapshotter/metadata/memory/reader.go
generated
vendored
Normal file
281
vendor/github.com/containerd/stargz-snapshotter/metadata/memory/reader.go
generated
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
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 memory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
"github.com/containerd/stargz-snapshotter/metadata"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type reader struct {
|
||||
r *estargz.Reader
|
||||
rootID uint32
|
||||
|
||||
idMap map[uint32]*estargz.TOCEntry
|
||||
idOfEntry map[*estargz.TOCEntry]uint32
|
||||
mu sync.Mutex
|
||||
|
||||
curID uint32
|
||||
curIDMu sync.Mutex
|
||||
|
||||
opts *metadata.Options
|
||||
}
|
||||
|
||||
func (r *reader) nextID() (uint32, error) {
|
||||
r.curIDMu.Lock()
|
||||
defer r.curIDMu.Unlock()
|
||||
if r.curID == math.MaxUint32 {
|
||||
return 0, fmt.Errorf("sequence id too large")
|
||||
}
|
||||
r.curID++
|
||||
return r.curID, nil
|
||||
}
|
||||
|
||||
func NewReader(sr *io.SectionReader, opts ...metadata.Option) (metadata.Reader, error) {
|
||||
var rOpts metadata.Options
|
||||
for _, o := range opts {
|
||||
if err := o(&rOpts); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to apply option")
|
||||
}
|
||||
}
|
||||
|
||||
telemetry := &estargz.Telemetry{}
|
||||
if rOpts.Telemetry != nil {
|
||||
telemetry.GetFooterLatency = estargz.MeasureLatencyHook(rOpts.Telemetry.GetFooterLatency)
|
||||
telemetry.GetTocLatency = estargz.MeasureLatencyHook(rOpts.Telemetry.GetTocLatency)
|
||||
telemetry.DeserializeTocLatency = estargz.MeasureLatencyHook(rOpts.Telemetry.DeserializeTocLatency)
|
||||
}
|
||||
var decompressors []estargz.Decompressor
|
||||
for _, d := range rOpts.Decompressors {
|
||||
decompressors = append(decompressors, d)
|
||||
}
|
||||
er, err := estargz.Open(sr,
|
||||
estargz.WithTOCOffset(rOpts.TOCOffset),
|
||||
estargz.WithTelemetry(telemetry),
|
||||
estargz.WithDecompressors(decompressors...),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
root, ok := er.Lookup("")
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to get root node")
|
||||
}
|
||||
r := &reader{r: er, idMap: make(map[uint32]*estargz.TOCEntry), idOfEntry: make(map[*estargz.TOCEntry]uint32), opts: &rOpts}
|
||||
rootID, err := r.initID(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.rootID = rootID
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *reader) initID(e *estargz.TOCEntry) (id uint32, err error) {
|
||||
var ok bool
|
||||
r.mu.Lock()
|
||||
id, ok = r.idOfEntry[e]
|
||||
if !ok {
|
||||
id, err = r.nextID()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
r.idMap[id] = e
|
||||
r.idOfEntry[e] = id
|
||||
}
|
||||
r.mu.Unlock()
|
||||
|
||||
e.ForeachChild(func(_ string, ent *estargz.TOCEntry) bool {
|
||||
if ent.Type == "hardlink" {
|
||||
var ok bool
|
||||
ent, ok = r.r.Lookup(ent.Name)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
_, err = r.initID(ent)
|
||||
return err == nil
|
||||
})
|
||||
return id, err
|
||||
}
|
||||
|
||||
func (r *reader) RootID() uint32 {
|
||||
return r.rootID
|
||||
}
|
||||
|
||||
func (r *reader) TOCDigest() digest.Digest {
|
||||
return r.r.TOCDigest()
|
||||
}
|
||||
|
||||
func (r *reader) GetOffset(id uint32) (offset int64, err error) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
e, ok := r.idMap[id]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("entry %d not found", id)
|
||||
}
|
||||
return e.Offset, nil
|
||||
}
|
||||
|
||||
func (r *reader) GetAttr(id uint32) (attr metadata.Attr, err error) {
|
||||
r.mu.Lock()
|
||||
e, ok := r.idMap[id]
|
||||
r.mu.Unlock()
|
||||
if !ok {
|
||||
err = fmt.Errorf("entry %d not found", id)
|
||||
return
|
||||
}
|
||||
// TODO: zero copy
|
||||
attrFromTOCEntry(e, &attr)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *reader) GetChild(pid uint32, base string) (id uint32, attr metadata.Attr, err error) {
|
||||
r.mu.Lock()
|
||||
e, ok := r.idMap[pid]
|
||||
r.mu.Unlock()
|
||||
if !ok {
|
||||
err = fmt.Errorf("parent entry %d not found", pid)
|
||||
return
|
||||
}
|
||||
child, ok := e.LookupChild(base)
|
||||
if !ok {
|
||||
err = fmt.Errorf("child %q of entry %d not found", base, pid)
|
||||
return
|
||||
}
|
||||
if child.Type == "hardlink" {
|
||||
child, ok = r.r.Lookup(child.Name)
|
||||
if !ok {
|
||||
err = fmt.Errorf("child %q ()hardlink of entry %d not found", base, pid)
|
||||
return
|
||||
}
|
||||
}
|
||||
cid, ok := r.idOfEntry[child]
|
||||
if !ok {
|
||||
err = fmt.Errorf("id of entry %q not found", base)
|
||||
return
|
||||
}
|
||||
// TODO: zero copy
|
||||
attrFromTOCEntry(child, &attr)
|
||||
return cid, attr, nil
|
||||
}
|
||||
|
||||
func (r *reader) ForeachChild(id uint32, f func(name string, id uint32, mode os.FileMode) bool) error {
|
||||
r.mu.Lock()
|
||||
e, ok := r.idMap[id]
|
||||
r.mu.Unlock()
|
||||
if !ok {
|
||||
return fmt.Errorf("parent entry %d not found", id)
|
||||
}
|
||||
var err error
|
||||
e.ForeachChild(func(baseName string, ent *estargz.TOCEntry) bool {
|
||||
if ent.Type == "hardlink" {
|
||||
var ok bool
|
||||
ent, ok = r.r.Lookup(ent.Name)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
r.mu.Lock()
|
||||
id, ok := r.idOfEntry[ent]
|
||||
r.mu.Unlock()
|
||||
if !ok {
|
||||
err = fmt.Errorf("id of child entry %q not found", baseName)
|
||||
return false
|
||||
}
|
||||
return f(baseName, id, ent.Stat().Mode())
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *reader) OpenFile(id uint32) (metadata.File, error) {
|
||||
r.mu.Lock()
|
||||
e, ok := r.idMap[id]
|
||||
r.mu.Unlock()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("entry %d not found", id)
|
||||
}
|
||||
sr, err := r.r.OpenFile(e.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &file{r, e, sr}, nil
|
||||
}
|
||||
|
||||
func (r *reader) Clone(sr *io.SectionReader) (metadata.Reader, error) {
|
||||
return NewReader(sr,
|
||||
metadata.WithTOCOffset(r.opts.TOCOffset),
|
||||
metadata.WithTelemetry(r.opts.Telemetry),
|
||||
metadata.WithDecompressors(r.opts.Decompressors...),
|
||||
)
|
||||
}
|
||||
|
||||
func (r *reader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type file struct {
|
||||
r *reader
|
||||
e *estargz.TOCEntry
|
||||
sr *io.SectionReader
|
||||
}
|
||||
|
||||
func (r *file) ChunkEntryForOffset(offset int64) (off int64, size int64, dgst string, ok bool) {
|
||||
e, ok := r.r.r.ChunkEntryForOffset(r.e.Name, offset)
|
||||
if !ok {
|
||||
return 0, 0, "", false
|
||||
}
|
||||
dgst = e.Digest
|
||||
if e.ChunkDigest != "" {
|
||||
// NOTE* "reg" also can contain ChunkDigest (e.g. when "reg" is the first entry of
|
||||
// chunked file)
|
||||
dgst = e.ChunkDigest
|
||||
}
|
||||
return e.ChunkOffset, e.ChunkSize, dgst, true
|
||||
}
|
||||
|
||||
func (r *file) ReadAt(p []byte, off int64) (n int, err error) {
|
||||
return r.sr.ReadAt(p, off)
|
||||
}
|
||||
|
||||
func (r *reader) NumOfNodes() (i int, _ error) {
|
||||
return len(r.idMap), nil
|
||||
}
|
||||
|
||||
// TODO: share it with db pkg
|
||||
func attrFromTOCEntry(src *estargz.TOCEntry, dst *metadata.Attr) *metadata.Attr {
|
||||
dst.Size = src.Size
|
||||
dst.ModTime, _ = time.Parse(time.RFC3339, src.ModTime3339)
|
||||
dst.LinkName = src.LinkName
|
||||
dst.Mode = src.Stat().Mode()
|
||||
dst.UID = src.UID
|
||||
dst.GID = src.GID
|
||||
dst.DevMajor = src.DevMajor
|
||||
dst.DevMinor = src.DevMinor
|
||||
dst.Xattrs = src.Xattrs
|
||||
dst.NumLink = src.NumLink
|
||||
return dst
|
||||
}
|
||||
131
vendor/github.com/containerd/stargz-snapshotter/metadata/metadata.go
generated
vendored
Normal file
131
vendor/github.com/containerd/stargz-snapshotter/metadata/metadata.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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 metadata
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// Attr reprensents the attributes of a node.
|
||||
type Attr struct {
|
||||
// Size, for regular files, is the logical size of the file.
|
||||
Size int64
|
||||
|
||||
// ModTime is the modification time of the node.
|
||||
ModTime time.Time
|
||||
|
||||
// LinkName, for symlinks, is the link target.
|
||||
LinkName string
|
||||
|
||||
// Mode is the permission and mode bits.
|
||||
Mode os.FileMode
|
||||
|
||||
// UID is the user ID of the owner.
|
||||
UID int
|
||||
|
||||
// GID is the group ID of the owner.
|
||||
GID int
|
||||
|
||||
// DevMajor is the major device number for device.
|
||||
DevMajor int
|
||||
|
||||
// DevMinor is the major device number for device.
|
||||
DevMinor int
|
||||
|
||||
// Xattrs are the extended attribute for the node.
|
||||
Xattrs map[string][]byte
|
||||
|
||||
// NumLink is the number of names pointing to this node.
|
||||
NumLink int
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
type Reader interface {
|
||||
RootID() uint32
|
||||
TOCDigest() digest.Digest
|
||||
|
||||
GetOffset(id uint32) (offset int64, err error)
|
||||
GetAttr(id uint32) (attr Attr, err error)
|
||||
GetChild(pid uint32, base string) (id uint32, attr Attr, err error)
|
||||
ForeachChild(id uint32, f func(name string, id uint32, mode os.FileMode) bool) error
|
||||
OpenFile(id uint32) (File, error)
|
||||
|
||||
Clone(sr *io.SectionReader) (Reader, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
type File interface {
|
||||
ChunkEntryForOffset(offset int64) (off int64, size int64, dgst string, ok bool)
|
||||
ReadAt(p []byte, off int64) (n int, err error)
|
||||
}
|
||||
|
||||
type Decompressor interface {
|
||||
estargz.Decompressor
|
||||
|
||||
// DecompressTOC decompresses the passed blob and returns a reader of TOC JSON.
|
||||
DecompressTOC(io.Reader) (tocJSON io.ReadCloser, err error)
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
TOCOffset int64
|
||||
Telemetry *Telemetry
|
||||
Decompressors []Decompressor
|
||||
}
|
||||
|
||||
// Option is an option to configure the behaviour of reader.
|
||||
type Option func(o *Options) error
|
||||
|
||||
// WithTOCOffset option specifies the offset of TOC
|
||||
func WithTOCOffset(tocOffset int64) Option {
|
||||
return func(o *Options) error {
|
||||
o.TOCOffset = tocOffset
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithTelemetry option specifies the telemetry hooks
|
||||
func WithTelemetry(telemetry *Telemetry) Option {
|
||||
return func(o *Options) error {
|
||||
o.Telemetry = telemetry
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDecompressors option specifies decompressors to use.
|
||||
// Default is gzip-based decompressor.
|
||||
func WithDecompressors(decompressors ...Decompressor) Option {
|
||||
return func(o *Options) error {
|
||||
o.Decompressors = decompressors
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// A func which takes start time and records the diff
|
||||
type MeasureLatencyHook func(time.Time)
|
||||
|
||||
// A struct which defines telemetry hooks. By implementing these hooks you should be able to record
|
||||
// the latency metrics of the respective steps of estargz open operation.
|
||||
type Telemetry struct {
|
||||
GetFooterLatency MeasureLatencyHook // measure time to get stargz footer (in milliseconds)
|
||||
GetTocLatency MeasureLatencyHook // measure time to GET TOC JSON (in milliseconds)
|
||||
DeserializeTocLatency MeasureLatencyHook // measure time to deserialize TOC JSON (in milliseconds)
|
||||
}
|
||||
659
vendor/github.com/containerd/stargz-snapshotter/metadata/testutil.go
generated
vendored
Normal file
659
vendor/github.com/containerd/stargz-snapshotter/metadata/testutil.go
generated
vendored
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
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 metadata
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
"github.com/containerd/stargz-snapshotter/estargz/zstdchunked"
|
||||
"github.com/containerd/stargz-snapshotter/util/testutil"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/klauspost/compress/zstd"
|
||||
)
|
||||
|
||||
var allowedPrefix = [4]string{"", "./", "/", "../"}
|
||||
|
||||
type compression interface {
|
||||
estargz.Compressor
|
||||
Decompressor
|
||||
}
|
||||
|
||||
var srcCompressions = map[string]compression{
|
||||
"zstd-fastest": zstdCompressionWithLevel(zstd.SpeedFastest),
|
||||
"zstd-default": zstdCompressionWithLevel(zstd.SpeedDefault),
|
||||
"zstd-bettercompression": zstdCompressionWithLevel(zstd.SpeedBetterCompression),
|
||||
"gzip-nocompression": gzipCompressionWithLevel(gzip.NoCompression),
|
||||
"gzip-bestspeed": gzipCompressionWithLevel(gzip.BestSpeed),
|
||||
"gzip-bestcompression": gzipCompressionWithLevel(gzip.BestCompression),
|
||||
"gzip-defaultcompression": gzipCompressionWithLevel(gzip.DefaultCompression),
|
||||
"gzip-huffmanonly": gzipCompressionWithLevel(gzip.HuffmanOnly),
|
||||
}
|
||||
|
||||
type zstdCompression struct {
|
||||
*zstdchunked.Compressor
|
||||
*zstdchunked.Decompressor
|
||||
}
|
||||
|
||||
func zstdCompressionWithLevel(compressionLevel zstd.EncoderLevel) compression {
|
||||
return &zstdCompression{&zstdchunked.Compressor{CompressionLevel: compressionLevel}, &zstdchunked.Decompressor{}}
|
||||
}
|
||||
|
||||
type gzipCompression struct {
|
||||
*estargz.GzipCompressor
|
||||
*estargz.GzipDecompressor
|
||||
}
|
||||
|
||||
func gzipCompressionWithLevel(compressionLevel int) compression {
|
||||
return gzipCompression{estargz.NewGzipCompressorWithLevel(compressionLevel), &estargz.GzipDecompressor{}}
|
||||
}
|
||||
|
||||
type ReaderFactory func(sr *io.SectionReader, opts ...Option) (r TestableReader, done func() error, err error)
|
||||
|
||||
type TestableReader interface {
|
||||
Reader
|
||||
NumOfNodes() (i int, _ error)
|
||||
}
|
||||
|
||||
// TestReader tests Reader returns correct file metadata.
|
||||
func TestReader(t *testing.T, factory ReaderFactory) {
|
||||
sampleTime := time.Now().Truncate(time.Second)
|
||||
sampleText := "qwer" + "tyui" + "opas" + "dfgh" + "jk"
|
||||
tests := []struct {
|
||||
name string
|
||||
chunkSize int
|
||||
in []testutil.TarEntry
|
||||
want []check
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
in: []testutil.TarEntry{},
|
||||
want: []check{
|
||||
numOfNodes(2), // root dir + prefetch landmark
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "files",
|
||||
in: []testutil.TarEntry{
|
||||
testutil.File("foo", "foofoo", testutil.WithFileMode(0644|os.ModeSetuid)),
|
||||
testutil.Dir("bar/"),
|
||||
testutil.File("bar/baz.txt", "bazbazbaz", testutil.WithFileOwner(1000, 1000)),
|
||||
testutil.File("xxx.txt", "xxxxx", testutil.WithFileModTime(sampleTime)),
|
||||
testutil.File("y.txt", "", testutil.WithFileXattrs(map[string]string{"testkey": "testval"})),
|
||||
},
|
||||
want: []check{
|
||||
numOfNodes(7), // root dir + prefetch landmark + 1 dir + 4 files
|
||||
hasFile("foo", "foofoo", 6),
|
||||
hasMode("foo", 0644|os.ModeSetuid),
|
||||
hasFile("bar/baz.txt", "bazbazbaz", 9),
|
||||
hasOwner("bar/baz.txt", 1000, 1000),
|
||||
hasFile("xxx.txt", "xxxxx", 5),
|
||||
hasModTime("xxx.txt", sampleTime),
|
||||
hasFile("y.txt", "", 0),
|
||||
hasXattrs("y.txt", map[string]string{"testkey": "testval"}),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dirs",
|
||||
in: []testutil.TarEntry{
|
||||
testutil.Dir("foo/", testutil.WithDirMode(os.ModeDir|0600|os.ModeSticky)),
|
||||
testutil.Dir("foo/bar/", testutil.WithDirOwner(1000, 1000)),
|
||||
testutil.File("foo/bar/baz.txt", "testtest"),
|
||||
testutil.File("foo/bar/xxxx", "x"),
|
||||
testutil.File("foo/bar/yyy", "yyy"),
|
||||
testutil.Dir("foo/a/", testutil.WithDirModTime(sampleTime)),
|
||||
testutil.Dir("foo/a/1/", testutil.WithDirXattrs(map[string]string{"testkey": "testval"})),
|
||||
testutil.File("foo/a/1/2", "1111111111"),
|
||||
},
|
||||
want: []check{
|
||||
numOfNodes(10), // root dir + prefetch landmark + 4 dirs + 4 files
|
||||
hasDirChildren("foo", "bar", "a"),
|
||||
hasDirChildren("foo/bar", "baz.txt", "xxxx", "yyy"),
|
||||
hasDirChildren("foo/a", "1"),
|
||||
hasDirChildren("foo/a/1", "2"),
|
||||
hasMode("foo", os.ModeDir|0600|os.ModeSticky),
|
||||
hasOwner("foo/bar", 1000, 1000),
|
||||
hasModTime("foo/a", sampleTime),
|
||||
hasXattrs("foo/a/1", map[string]string{"testkey": "testval"}),
|
||||
hasFile("foo/bar/baz.txt", "testtest", 8),
|
||||
hasFile("foo/bar/xxxx", "x", 1),
|
||||
hasFile("foo/bar/yyy", "yyy", 3),
|
||||
hasFile("foo/a/1/2", "1111111111", 10),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "hardlinks",
|
||||
in: []testutil.TarEntry{
|
||||
testutil.File("foo", "foofoo", testutil.WithFileOwner(1000, 1000)),
|
||||
testutil.Dir("bar/"),
|
||||
testutil.Link("bar/foolink", "foo"),
|
||||
testutil.Link("bar/foolink2", "bar/foolink"),
|
||||
testutil.Dir("bar/1/"),
|
||||
testutil.File("bar/1/baz.txt", "testtest"),
|
||||
testutil.Link("barlink", "bar/1/baz.txt"),
|
||||
testutil.Symlink("foosym", "bar/foolink2"),
|
||||
},
|
||||
want: []check{
|
||||
numOfNodes(7), // root dir + prefetch landmark + 2 dirs + 1 flie(linked) + 1 file(linked) + 1 symlink
|
||||
hasFile("foo", "foofoo", 6),
|
||||
hasOwner("foo", 1000, 1000),
|
||||
hasFile("bar/foolink", "foofoo", 6),
|
||||
hasOwner("bar/foolink", 1000, 1000),
|
||||
hasFile("bar/foolink2", "foofoo", 6),
|
||||
hasOwner("bar/foolink2", 1000, 1000),
|
||||
hasFile("bar/1/baz.txt", "testtest", 8),
|
||||
hasFile("barlink", "testtest", 8),
|
||||
hasDirChildren("bar", "foolink", "foolink2", "1"),
|
||||
hasDirChildren("bar/1", "baz.txt"),
|
||||
sameNodes("foo", "bar/foolink", "bar/foolink2"),
|
||||
sameNodes("bar/1/baz.txt", "barlink"),
|
||||
linkName("foosym", "bar/foolink2"),
|
||||
hasNumLink("foo", 3), // parent dir + 2 links
|
||||
hasNumLink("barlink", 2), // parent dir + 1 link
|
||||
hasNumLink("bar", 3), // parent + "." + child's ".."
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "various files",
|
||||
in: []testutil.TarEntry{
|
||||
testutil.Dir("bar/"),
|
||||
testutil.File("bar/../bar///////////////////foo", ""),
|
||||
testutil.Chardev("bar/cdev", 10, 11),
|
||||
testutil.Blockdev("bar/bdev", 100, 101),
|
||||
testutil.Fifo("bar/fifo"),
|
||||
},
|
||||
want: []check{
|
||||
numOfNodes(7), // root dir + prefetch landmark + 1 file + 1 dir + 1 cdev + 1 bdev + 1 fifo
|
||||
hasFile("bar/foo", "", 0),
|
||||
hasChardev("bar/cdev", 10, 11),
|
||||
hasBlockdev("bar/bdev", 100, 101),
|
||||
hasFifo("bar/fifo"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "chunks",
|
||||
chunkSize: 4,
|
||||
in: []testutil.TarEntry{
|
||||
testutil.Dir("foo/"),
|
||||
testutil.File("foo/small", sampleText[:2]),
|
||||
testutil.File("foo/large", sampleText),
|
||||
},
|
||||
want: []check{
|
||||
numOfNodes(5), // root dir + prefetch landmark + 1 dir + 2 files
|
||||
numOfChunks("foo/large", 1+(len(sampleText)/4)),
|
||||
hasFileContentsOffset("foo/small", 0, sampleText[:2]),
|
||||
hasFileContentsOffset("foo/large", 0, sampleText[0:]),
|
||||
hasFileContentsOffset("foo/large", 1, sampleText[1:]),
|
||||
hasFileContentsOffset("foo/large", 2, sampleText[2:]),
|
||||
hasFileContentsOffset("foo/large", 3, sampleText[3:]),
|
||||
hasFileContentsOffset("foo/large", 4, sampleText[4:]),
|
||||
hasFileContentsOffset("foo/large", 5, sampleText[5:]),
|
||||
hasFileContentsOffset("foo/large", 6, sampleText[6:]),
|
||||
hasFileContentsOffset("foo/large", 7, sampleText[7:]),
|
||||
hasFileContentsOffset("foo/large", 8, sampleText[8:]),
|
||||
hasFileContentsOffset("foo/large", 9, sampleText[9:]),
|
||||
hasFileContentsOffset("foo/large", 10, sampleText[10:]),
|
||||
hasFileContentsOffset("foo/large", 11, sampleText[11:]),
|
||||
hasFileContentsOffset("foo/large", 12, sampleText[12:]),
|
||||
hasFileContentsOffset("foo/large", int64(len(sampleText)-1), ""),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
for _, prefix := range allowedPrefix {
|
||||
prefix := prefix
|
||||
for srcCompresionName, srcCompression := range srcCompressions {
|
||||
srcCompression := srcCompression
|
||||
t.Run(tt.name+"-"+srcCompresionName, func(t *testing.T) {
|
||||
opts := []testutil.BuildEStargzOption{
|
||||
testutil.WithBuildTarOptions(testutil.WithPrefix(prefix)),
|
||||
testutil.WithEStargzOptions(estargz.WithCompression(srcCompression)),
|
||||
}
|
||||
if tt.chunkSize > 0 {
|
||||
opts = append(opts, testutil.WithEStargzOptions(estargz.WithChunkSize(tt.chunkSize)))
|
||||
}
|
||||
esgz, _, err := testutil.BuildEStargz(tt.in, opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to build sample eStargz: %v", err)
|
||||
}
|
||||
|
||||
telemetry, checkCalled := newCalledTelemetry()
|
||||
r, done, err := factory(esgz,
|
||||
WithDecompressors(new(zstdchunked.Decompressor)), WithTelemetry(telemetry))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create new reader: %v", err)
|
||||
}
|
||||
defer done()
|
||||
t.Logf("vvvvv Node tree vvvvv")
|
||||
t.Logf("[%d] ROOT", r.RootID())
|
||||
dumpNodes(t, r, r.RootID(), 1)
|
||||
t.Logf("^^^^^^^^^^^^^^^^^^^^^")
|
||||
for _, want := range tt.want {
|
||||
want(t, r)
|
||||
}
|
||||
if err := checkCalled(); err != nil {
|
||||
t.Errorf("telemetry failure: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newCalledTelemetry() (telemetry *Telemetry, check func() error) {
|
||||
var getFooterLatencyCalled bool
|
||||
var getTocLatencyCalled bool
|
||||
var deserializeTocLatencyCalled bool
|
||||
return &Telemetry{
|
||||
func(time.Time) { getFooterLatencyCalled = true },
|
||||
func(time.Time) { getTocLatencyCalled = true },
|
||||
func(time.Time) { deserializeTocLatencyCalled = true },
|
||||
}, func() error {
|
||||
var allErr error
|
||||
if !getFooterLatencyCalled {
|
||||
allErr = multierror.Append(allErr, fmt.Errorf("metrics GetFooterLatency isn't called"))
|
||||
}
|
||||
if !getTocLatencyCalled {
|
||||
allErr = multierror.Append(allErr, fmt.Errorf("metrics GetTocLatency isn't called"))
|
||||
}
|
||||
if !deserializeTocLatencyCalled {
|
||||
allErr = multierror.Append(allErr, fmt.Errorf("metrics DeserializeTocLatency isn't called"))
|
||||
}
|
||||
return allErr
|
||||
}
|
||||
}
|
||||
|
||||
func dumpNodes(t *testing.T, r TestableReader, id uint32, level int) {
|
||||
if err := r.ForeachChild(id, func(name string, id uint32, mode os.FileMode) bool {
|
||||
ind := ""
|
||||
for i := 0; i < level; i++ {
|
||||
ind += " "
|
||||
}
|
||||
t.Logf("%v+- [%d] %q : %v", ind, id, name, mode)
|
||||
dumpNodes(t, r, id, level+1)
|
||||
return true
|
||||
}); err != nil {
|
||||
t.Errorf("failed to dump nodes %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type check func(*testing.T, TestableReader)
|
||||
|
||||
func numOfNodes(want int) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
i, err := r.NumOfNodes()
|
||||
if err != nil {
|
||||
t.Errorf("num of nodes: %v", err)
|
||||
}
|
||||
if want != i {
|
||||
t.Errorf("unexpected num of nodes %d; want %d", i, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func numOfChunks(name string, num int) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
nr, ok := r.(interface {
|
||||
NumOfChunks(id uint32) (i int, _ error)
|
||||
})
|
||||
if !ok {
|
||||
return // skip
|
||||
}
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
i, err := nr.NumOfChunks(id)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get num of chunks of %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if i != num {
|
||||
t.Errorf("unexpected num of chunk of %q : %d want %d", name, i, num)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sameNodes(n string, nodes ...string) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, n)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", n, err)
|
||||
return
|
||||
}
|
||||
for _, en := range nodes {
|
||||
eid, err := lookup(r, en)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", en, err)
|
||||
return
|
||||
}
|
||||
if eid != id {
|
||||
t.Errorf("unexpected ID of %q: %d want %d", en, eid, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func linkName(name string, linkName string) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get attr of %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.Mode&os.ModeSymlink == 0 {
|
||||
t.Errorf("%q is not a symlink: %v", name, attr.Mode)
|
||||
return
|
||||
}
|
||||
if attr.LinkName != linkName {
|
||||
t.Errorf("unexpected link name of %q : %q want %q", name, attr.LinkName, linkName)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasNumLink(name string, numLink int) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get attr of %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.NumLink != numLink {
|
||||
t.Errorf("unexpected numLink of %q: %d want %d", name, attr.NumLink, numLink)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasDirChildren(name string, children ...string) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get attr of %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if !attr.Mode.IsDir() {
|
||||
t.Errorf("%q is not directory: %v", name, attr.Mode)
|
||||
return
|
||||
}
|
||||
found := map[string]struct{}{}
|
||||
if err := r.ForeachChild(id, func(name string, id uint32, mode os.FileMode) bool {
|
||||
found[name] = struct{}{}
|
||||
return true
|
||||
}); err != nil {
|
||||
t.Errorf("failed to see children %v", err)
|
||||
return
|
||||
}
|
||||
if len(found) != len(children) {
|
||||
t.Errorf("unexpected number of children of %q : %d want %d", name, len(found), len(children))
|
||||
}
|
||||
for _, want := range children {
|
||||
if _, ok := found[want]; !ok {
|
||||
t.Errorf("expected child %q not found in %q", want, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasChardev(name string, maj, min int) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find chardev %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of chardev %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.Mode&os.ModeDevice == 0 || attr.Mode&os.ModeCharDevice == 0 {
|
||||
t.Errorf("file %q is not a chardev: %v", name, attr.Mode)
|
||||
return
|
||||
}
|
||||
if attr.DevMajor != maj || attr.DevMinor != min {
|
||||
t.Errorf("unexpected major/minor of chardev %q: %d/%d want %d/%d", name, attr.DevMajor, attr.DevMinor, maj, min)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasBlockdev(name string, maj, min int) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find blockdev %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of blockdev %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.Mode&os.ModeDevice == 0 || attr.Mode&os.ModeCharDevice != 0 {
|
||||
t.Errorf("file %q is not a blockdev: %v", name, attr.Mode)
|
||||
return
|
||||
}
|
||||
if attr.DevMajor != maj || attr.DevMinor != min {
|
||||
t.Errorf("unexpected major/minor of blockdev %q: %d/%d want %d/%d", name, attr.DevMajor, attr.DevMinor, maj, min)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasFifo(name string) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find blockdev %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of blockdev %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.Mode&os.ModeNamedPipe == 0 {
|
||||
t.Errorf("file %q is not a fifo: %v", name, attr.Mode)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasFile(name, content string, size int64) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if !attr.Mode.IsRegular() {
|
||||
t.Errorf("file %q is not a regular file: %v", name, attr.Mode)
|
||||
return
|
||||
}
|
||||
sr, err := r.OpenFile(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot open file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
data, err := ioutil.ReadAll(io.NewSectionReader(sr, 0, attr.Size))
|
||||
if err != nil {
|
||||
t.Errorf("cannot read file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.Size != size {
|
||||
t.Errorf("unexpected size of file %q : %d (%q) want %d (%q)", name, attr.Size, string(data), size, content)
|
||||
return
|
||||
}
|
||||
if string(data) != content {
|
||||
t.Errorf("unexpected content of %q: %q want %q", name, string(data), content)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasFileContentsOffset(name string, off int64, contents string) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("failed to lookup %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
fr, err := r.OpenFile(id)
|
||||
if err != nil {
|
||||
t.Errorf("failed to open file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
buf := make([]byte, len(contents))
|
||||
n, err := fr.ReadAt(buf, off)
|
||||
if err != nil && err != io.EOF {
|
||||
t.Errorf("failed to read file %q (off:%d, want:%q): %v", name, off, contents, err)
|
||||
return
|
||||
}
|
||||
if n != len(contents) {
|
||||
t.Errorf("failed to read contents %q (off:%d, want:%q) got %q", name, off, contents, string(buf))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasMode(name string, mode os.FileMode) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.Mode != mode {
|
||||
t.Errorf("unexpected mode of %q: %v want %v", name, attr.Mode, mode)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasOwner(name string, uid, gid int) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if attr.UID != uid || attr.GID != gid {
|
||||
t.Errorf("unexpected owner of %q: (%d:%d) want (%d:%d)", name, attr.UID, attr.GID, uid, gid)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasModTime(name string, modTime time.Time) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attrModTime := attr.ModTime
|
||||
if attrModTime.Before(modTime) || attrModTime.After(modTime) {
|
||||
t.Errorf("unexpected time of %q: %v; want %v", name, attrModTime, modTime)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasXattrs(name string, xattrs map[string]string) check {
|
||||
return func(t *testing.T, r TestableReader) {
|
||||
id, err := lookup(r, name)
|
||||
if err != nil {
|
||||
t.Errorf("cannot find file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
attr, err := r.GetAttr(id)
|
||||
if err != nil {
|
||||
t.Errorf("cannot get attr of file %q: %v", name, err)
|
||||
return
|
||||
}
|
||||
if len(attr.Xattrs) != len(xattrs) {
|
||||
t.Errorf("unexpected size of xattr of %q: %d want %d", name, len(attr.Xattrs), len(xattrs))
|
||||
return
|
||||
}
|
||||
for k, v := range attr.Xattrs {
|
||||
if xattrs[k] != string(v) {
|
||||
t.Errorf("unexpected xattr of %q: %q=%q want %q=%q", name, k, string(v), k, xattrs[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lookup(r TestableReader, name string) (uint32, error) {
|
||||
name = strings.TrimPrefix(path.Clean("/"+name), "/")
|
||||
if name == "" {
|
||||
return r.RootID(), nil
|
||||
}
|
||||
dir, base := filepath.Split(name)
|
||||
pid, err := lookup(r, dir)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
id, _, err := r.GetChild(pid, base)
|
||||
return id, err
|
||||
}
|
||||
19
vendor/github.com/containerd/stargz-snapshotter/service/resolver/cri.go
generated
vendored
19
vendor/github.com/containerd/stargz-snapshotter/service/resolver/cri.go
generated
vendored
@@ -40,6 +40,7 @@ import (
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
dconfig "github.com/containerd/containerd/remotes/docker/config"
|
||||
"github.com/containerd/stargz-snapshotter/fs/source"
|
||||
rhttp "github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/pkg/errors"
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||
)
|
||||
@@ -136,18 +137,24 @@ func RegistryHostsFromCRIConfig(ctx context.Context, config Registry, credsFuncs
|
||||
}
|
||||
|
||||
var (
|
||||
transport = http.DefaultTransport.(*http.Transport).Clone()
|
||||
client = &http.Client{Transport: transport}
|
||||
config = config.Configs[u.Host]
|
||||
rclient = rhttp.NewClient()
|
||||
config = config.Configs[u.Host]
|
||||
)
|
||||
|
||||
rclient.Logger = nil // disable logging every request
|
||||
|
||||
if config.TLS != nil {
|
||||
transport.TLSClientConfig, err = getTLSConfig(*config.TLS)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get TLSConfig for registry %q", e)
|
||||
if tr, ok := rclient.HTTPClient.Transport.(*http.Transport); ok {
|
||||
tr.TLSClientConfig, err = getTLSConfig(*config.TLS)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get TLSConfig for registry %q", e)
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("TLS config cannot be applied; Client.Transport is not *http.Transport")
|
||||
}
|
||||
}
|
||||
|
||||
client := rclient.StandardClient()
|
||||
authorizer := docker.NewDockerAuthorizer(
|
||||
docker.WithAuthClient(client),
|
||||
docker.WithAuthCreds(multiCredsFuncs(ref, credsFuncs...)))
|
||||
|
||||
6
vendor/github.com/containerd/stargz-snapshotter/service/resolver/registry.go
generated
vendored
6
vendor/github.com/containerd/stargz-snapshotter/service/resolver/registry.go
generated
vendored
@@ -17,12 +17,12 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/reference"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/containerd/stargz-snapshotter/fs/source"
|
||||
rhttp "github.com/hashicorp/go-retryablehttp"
|
||||
)
|
||||
|
||||
const defaultRequestTimeoutSec = 30
|
||||
@@ -59,7 +59,9 @@ func RegistryHostsFromConfig(cfg Config, credsFuncs ...Credential) source.Regist
|
||||
for _, h := range append(cfg.Host[host].Mirrors, MirrorConfig{
|
||||
Host: host,
|
||||
}) {
|
||||
tr := &http.Client{Transport: http.DefaultTransport.(*http.Transport).Clone()}
|
||||
client := rhttp.NewClient()
|
||||
client.Logger = nil // disable logging every request
|
||||
tr := client.StandardClient()
|
||||
if h.RequestTimeoutSec >= 0 {
|
||||
if h.RequestTimeoutSec == 0 {
|
||||
tr.Timeout = defaultRequestTimeoutSec * time.Second
|
||||
|
||||
20
vendor/github.com/containerd/stargz-snapshotter/service/service.go
generated
vendored
20
vendor/github.com/containerd/stargz-snapshotter/service/service.go
generated
vendored
@@ -35,6 +35,7 @@ type Option func(*options)
|
||||
type options struct {
|
||||
credsFuncs []resolver.Credential
|
||||
registryHosts source.RegistryHosts
|
||||
fsOpts []stargzfs.Option
|
||||
}
|
||||
|
||||
// WithCredsFuncs specifies credsFuncs to be used for connecting to the registries.
|
||||
@@ -51,6 +52,13 @@ func WithCustomRegistryHosts(hosts source.RegistryHosts) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithFilesystemOptions allowes to pass filesystem-related configuration.
|
||||
func WithFilesystemOptions(opts ...stargzfs.Option) Option {
|
||||
return func(o *options) {
|
||||
o.fsOpts = opts
|
||||
}
|
||||
}
|
||||
|
||||
// NewStargzSnapshotterService returns stargz snapshotter.
|
||||
func NewStargzSnapshotterService(ctx context.Context, root string, config *Config, opts ...Option) (snapshots.Snapshotter, error) {
|
||||
var sOpts options
|
||||
@@ -65,13 +73,11 @@ func NewStargzSnapshotterService(ctx context.Context, root string, config *Confi
|
||||
}
|
||||
|
||||
// Configure filesystem and snapshotter
|
||||
fs, err := stargzfs.NewFilesystem(fsRoot(root),
|
||||
config.Config,
|
||||
stargzfs.WithGetSources(sources(
|
||||
sourceFromCRILabels(hosts), // provides source info based on CRI labels
|
||||
source.FromDefaultLabels(hosts), // provides source info based on default labels
|
||||
)),
|
||||
)
|
||||
fsOpts := append(sOpts.fsOpts, stargzfs.WithGetSources(sources(
|
||||
sourceFromCRILabels(hosts), // provides source info based on CRI labels
|
||||
source.FromDefaultLabels(hosts), // provides source info based on default labels
|
||||
)))
|
||||
fs, err := stargzfs.NewFilesystem(fsRoot(root), config.Config, fsOpts...)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Fatalf("failed to configure filesystem")
|
||||
}
|
||||
|
||||
19
vendor/github.com/containerd/stargz-snapshotter/snapshot/snapshot.go
generated
vendored
19
vendor/github.com/containerd/stargz-snapshotter/snapshot/snapshot.go
generated
vendored
@@ -251,7 +251,7 @@ func (o *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...s
|
||||
WithError(err).Warn("failed to prepare remote snapshot")
|
||||
} else {
|
||||
base.Labels[remoteLabel] = remoteLabelVal // Mark this snapshot as remote
|
||||
err := o.Commit(ctx, target, key, append(opts, snapshots.WithLabels(base.Labels))...)
|
||||
err := o.commit(ctx, true, target, key, append(opts, snapshots.WithLabels(base.Labels))...)
|
||||
if err == nil || errdefs.IsAlreadyExists(err) {
|
||||
// count also AlreadyExists as "success"
|
||||
log.G(lCtx).WithField(remoteSnapshotLogKey, prepareSucceeded).Debug("prepared remote snapshot")
|
||||
@@ -293,6 +293,10 @@ func (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er
|
||||
}
|
||||
|
||||
func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {
|
||||
return o.commit(ctx, false, name, key, opts...)
|
||||
}
|
||||
|
||||
func (o *snapshotter) commit(ctx context.Context, isRemote bool, name, key string, opts ...snapshots.Opt) error {
|
||||
ctx, t, err := o.ms.TransactionContext(ctx, true)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -307,17 +311,20 @@ func (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
|
||||
}()
|
||||
|
||||
// grab the existing id
|
||||
id, _, _, err := storage.GetInfo(ctx, key)
|
||||
id, _, usage, err := storage.GetInfo(ctx, key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
usage, err := fs.DiskUsage(ctx, o.upperPath(id))
|
||||
if err != nil {
|
||||
return err
|
||||
if !isRemote { // skip diskusage for remote snapshots for allowing lazy preparation of nodes
|
||||
du, err := fs.DiskUsage(ctx, o.upperPath(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
usage = snapshots.Usage(du)
|
||||
}
|
||||
|
||||
if _, err = storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil {
|
||||
if _, err = storage.CommitActive(ctx, key, name, usage, opts...); err != nil {
|
||||
return errors.Wrap(err, "failed to commit snapshot")
|
||||
}
|
||||
|
||||
|
||||
80
vendor/github.com/containerd/stargz-snapshotter/util/testutil/ensurehello.go
generated
vendored
Normal file
80
vendor/github.com/containerd/stargz-snapshotter/util/testutil/ensurehello.go
generated
vendored
Normal 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 testutil
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/content/local"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
// HelloArchiveURL points to an OCI archive of `hello-world`.
|
||||
// Exported from `docker.io/library/hello-world@sha256:1a523af650137b8accdaed439c17d684df61ee4d74feac151b5b337bd29e7eec` .
|
||||
// See https://github.com/AkihiroSuda/test-oci-archives/releases/tag/v20210101
|
||||
HelloArchiveURL = "https://github.com/AkihiroSuda/test-oci-archives/releases/download/v20210101/hello-world.tar.gz"
|
||||
// HelloArchiveDigest is the digest of the archive.
|
||||
HelloArchiveDigest = "sha256:5aa022621c4de0e941ab2a30d4569c403e156b4ba2de2ec32e382ae8679f40e1"
|
||||
)
|
||||
|
||||
// EnsureHello creates a temp content store and ensures `hello-world` image from HelloArchiveURL into the store.
|
||||
func EnsureHello(ctx context.Context) (*ocispec.Descriptor, content.Store, error) {
|
||||
// Pulling an image without the daemon is a mess, so we use OCI archive here.
|
||||
resp, err := http.Get(HelloArchiveURL)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
sha256Digester := digest.SHA256.Digester()
|
||||
sha256Hasher := sha256Digester.Hash()
|
||||
tr := io.TeeReader(resp.Body, sha256Hasher)
|
||||
gzReader, err := gzip.NewReader(tr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
tempDir, err := ioutil.TempDir("", "test-estargz")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
cs, err := local.NewStore(tempDir)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
desc, err := archive.ImportIndex(ctx, cs, gzReader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resp.Body.Close()
|
||||
if d := sha256Digester.Digest().String(); d != HelloArchiveDigest {
|
||||
err = errors.Errorf("expected digest of %q to be %q, got %q", HelloArchiveURL, HelloArchiveDigest, d)
|
||||
return nil, nil, err
|
||||
}
|
||||
return &desc, cs, nil
|
||||
}
|
||||
74
vendor/github.com/containerd/stargz-snapshotter/util/testutil/estargz.go
generated
vendored
Normal file
74
vendor/github.com/containerd/stargz-snapshotter/util/testutil/estargz.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 testutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/containerd/stargz-snapshotter/estargz"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
type buildEStargzOptions struct {
|
||||
estargzOptions []estargz.Option
|
||||
buildTarOptions []BuildTarOption
|
||||
}
|
||||
|
||||
type BuildEStargzOption func(o *buildEStargzOptions) error
|
||||
|
||||
// WithEStargzOptions specifies options for estargz lib
|
||||
func WithEStargzOptions(eo ...estargz.Option) BuildEStargzOption {
|
||||
return func(o *buildEStargzOptions) error {
|
||||
o.estargzOptions = eo
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithBuildTarOptions option specifies the options for tar creation
|
||||
func WithBuildTarOptions(to ...BuildTarOption) BuildEStargzOption {
|
||||
return func(o *buildEStargzOptions) error {
|
||||
o.buildTarOptions = to
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func BuildEStargz(ents []TarEntry, opts ...BuildEStargzOption) (*io.SectionReader, digest.Digest, error) {
|
||||
var beOpts buildEStargzOptions
|
||||
for _, o := range opts {
|
||||
o(&beOpts)
|
||||
}
|
||||
tarBuf := new(bytes.Buffer)
|
||||
if _, err := io.Copy(tarBuf, BuildTar(ents, beOpts.buildTarOptions...)); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
tarData := tarBuf.Bytes()
|
||||
rc, err := estargz.Build(
|
||||
io.NewSectionReader(bytes.NewReader(tarData), 0, int64(len(tarData))),
|
||||
beOpts.estargzOptions...)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
defer rc.Close()
|
||||
vsb := new(bytes.Buffer)
|
||||
if _, err := io.Copy(vsb, rc); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
vsbb := vsb.Bytes()
|
||||
|
||||
return io.NewSectionReader(bytes.NewReader(vsbb), 0, int64(len(vsbb))), rc.TOCDigest(), nil
|
||||
}
|
||||
310
vendor/github.com/containerd/stargz-snapshotter/util/testutil/tar.go
generated
vendored
Normal file
310
vendor/github.com/containerd/stargz-snapshotter/util/testutil/tar.go
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
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 testutil
|
||||
|
||||
// This utility helps test codes to generate sample tar blobs.
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TarEntry is an entry of tar.
|
||||
type TarEntry interface {
|
||||
AppendTar(tw *tar.Writer, opts BuildTarOptions) error
|
||||
}
|
||||
|
||||
// BuildTarOptions is a set of options used during building blob.
|
||||
type BuildTarOptions struct {
|
||||
|
||||
// Prefix is the prefix string need to be added to each file name (e.g. "./", "/", etc.)
|
||||
Prefix string
|
||||
}
|
||||
|
||||
// BuildTarOption is an option used during building blob.
|
||||
type BuildTarOption func(o *BuildTarOptions)
|
||||
|
||||
// WithPrefix is an option to add a prefix string to each file name (e.g. "./", "/", etc.)
|
||||
func WithPrefix(prefix string) BuildTarOption {
|
||||
return func(o *BuildTarOptions) {
|
||||
o.Prefix = prefix
|
||||
}
|
||||
}
|
||||
|
||||
// BuildTar builds a tar blob
|
||||
func BuildTar(ents []TarEntry, opts ...BuildTarOption) io.Reader {
|
||||
var bo BuildTarOptions
|
||||
for _, o := range opts {
|
||||
o(&bo)
|
||||
}
|
||||
pr, pw := io.Pipe()
|
||||
go func() {
|
||||
tw := tar.NewWriter(pw)
|
||||
for _, ent := range ents {
|
||||
if err := ent.AppendTar(tw, bo); err != nil {
|
||||
pw.CloseWithError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
pw.CloseWithError(err)
|
||||
return
|
||||
}
|
||||
pw.Close()
|
||||
}()
|
||||
return pr
|
||||
}
|
||||
|
||||
type tarEntryFunc func(*tar.Writer, BuildTarOptions) error
|
||||
|
||||
func (f tarEntryFunc) AppendTar(tw *tar.Writer, opts BuildTarOptions) error { return f(tw, opts) }
|
||||
|
||||
// DirectoryBuildTarOption is an option for a directory entry.
|
||||
type DirectoryBuildTarOption func(o *dirOpts)
|
||||
|
||||
type dirOpts struct {
|
||||
uid int
|
||||
gid int
|
||||
xattrs map[string]string
|
||||
mode *os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
// WithFileModTime specifies the modtime of the dir.
|
||||
func WithDirModTime(modTime time.Time) DirectoryBuildTarOption {
|
||||
return func(o *dirOpts) {
|
||||
o.modTime = modTime
|
||||
}
|
||||
}
|
||||
|
||||
// WithDirOwner specifies the owner of the directory.
|
||||
func WithDirOwner(uid, gid int) DirectoryBuildTarOption {
|
||||
return func(o *dirOpts) {
|
||||
o.uid = uid
|
||||
o.gid = gid
|
||||
}
|
||||
}
|
||||
|
||||
// WithDirXattrs specifies the extended attributes of the directory.
|
||||
func WithDirXattrs(xattrs map[string]string) DirectoryBuildTarOption {
|
||||
return func(o *dirOpts) {
|
||||
o.xattrs = xattrs
|
||||
}
|
||||
}
|
||||
|
||||
// WithDirMode specifies the mode of the directory.
|
||||
func WithDirMode(mode os.FileMode) DirectoryBuildTarOption {
|
||||
return func(o *dirOpts) {
|
||||
o.mode = &mode
|
||||
}
|
||||
}
|
||||
|
||||
// Dir is a directory entry
|
||||
func Dir(name string, opts ...DirectoryBuildTarOption) TarEntry {
|
||||
return tarEntryFunc(func(tw *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
var dOpts dirOpts
|
||||
for _, o := range opts {
|
||||
o(&dOpts)
|
||||
}
|
||||
if !strings.HasSuffix(name, "/") {
|
||||
panic(fmt.Sprintf("missing trailing slash in dir %q ", name))
|
||||
}
|
||||
var mode int64 = 0755
|
||||
if dOpts.mode != nil {
|
||||
mode = permAndExtraMode2TarMode(*dOpts.mode)
|
||||
}
|
||||
return tw.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeDir,
|
||||
Name: buildOpts.Prefix + name,
|
||||
Mode: mode,
|
||||
ModTime: dOpts.modTime,
|
||||
Xattrs: dOpts.xattrs,
|
||||
Uid: dOpts.uid,
|
||||
Gid: dOpts.gid,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// FileBuildTarOption is an option for a file entry.
|
||||
type FileBuildTarOption func(o *fileOpts)
|
||||
|
||||
type fileOpts struct {
|
||||
uid int
|
||||
gid int
|
||||
xattrs map[string]string
|
||||
mode *os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
// WithFileOwner specifies the owner of the file.
|
||||
func WithFileOwner(uid, gid int) FileBuildTarOption {
|
||||
return func(o *fileOpts) {
|
||||
o.uid = uid
|
||||
o.gid = gid
|
||||
}
|
||||
}
|
||||
|
||||
// WithFileXattrs specifies the extended attributes of the file.
|
||||
func WithFileXattrs(xattrs map[string]string) FileBuildTarOption {
|
||||
return func(o *fileOpts) {
|
||||
o.xattrs = xattrs
|
||||
}
|
||||
}
|
||||
|
||||
// WithFileModTime specifies the modtime of the file.
|
||||
func WithFileModTime(modTime time.Time) FileBuildTarOption {
|
||||
return func(o *fileOpts) {
|
||||
o.modTime = modTime
|
||||
}
|
||||
}
|
||||
|
||||
// WithFileMode specifies the mode of the file.
|
||||
func WithFileMode(mode os.FileMode) FileBuildTarOption {
|
||||
return func(o *fileOpts) {
|
||||
o.mode = &mode
|
||||
}
|
||||
}
|
||||
|
||||
// File is a regilar file entry
|
||||
func File(name, contents string, opts ...FileBuildTarOption) TarEntry {
|
||||
return tarEntryFunc(func(tw *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
var fOpts fileOpts
|
||||
for _, o := range opts {
|
||||
o(&fOpts)
|
||||
}
|
||||
if strings.HasSuffix(name, "/") {
|
||||
return fmt.Errorf("bogus trailing slash in file %q", name)
|
||||
}
|
||||
var mode int64 = 0644
|
||||
if fOpts.mode != nil {
|
||||
mode = permAndExtraMode2TarMode(*fOpts.mode)
|
||||
}
|
||||
if err := tw.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeReg,
|
||||
Name: buildOpts.Prefix + name,
|
||||
Mode: mode,
|
||||
ModTime: fOpts.modTime,
|
||||
Xattrs: fOpts.xattrs,
|
||||
Size: int64(len(contents)),
|
||||
Uid: fOpts.uid,
|
||||
Gid: fOpts.gid,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.WriteString(tw, contents)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// Symlink is a symlink entry
|
||||
func Symlink(name, target string) TarEntry {
|
||||
return tarEntryFunc(func(tw *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
return tw.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeSymlink,
|
||||
Name: buildOpts.Prefix + name,
|
||||
Linkname: target,
|
||||
Mode: 0644,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Link is a hard-link entry
|
||||
func Link(name, linkname string) TarEntry {
|
||||
now := time.Now()
|
||||
return tarEntryFunc(func(w *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
return w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeLink,
|
||||
Name: buildOpts.Prefix + name,
|
||||
Linkname: linkname,
|
||||
ModTime: now,
|
||||
AccessTime: now,
|
||||
ChangeTime: now,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Chardev is a character device entry
|
||||
func Chardev(name string, major, minor int64) TarEntry {
|
||||
now := time.Now()
|
||||
return tarEntryFunc(func(w *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
return w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeChar,
|
||||
Name: buildOpts.Prefix + name,
|
||||
Devmajor: major,
|
||||
Devminor: minor,
|
||||
ModTime: now,
|
||||
AccessTime: now,
|
||||
ChangeTime: now,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Blockdev is a block device entry
|
||||
func Blockdev(name string, major, minor int64) TarEntry {
|
||||
now := time.Now()
|
||||
return tarEntryFunc(func(w *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
return w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeBlock,
|
||||
Name: buildOpts.Prefix + name,
|
||||
Devmajor: major,
|
||||
Devminor: minor,
|
||||
ModTime: now,
|
||||
AccessTime: now,
|
||||
ChangeTime: now,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Fifo is a fifo entry
|
||||
func Fifo(name string) TarEntry {
|
||||
now := time.Now()
|
||||
return tarEntryFunc(func(w *tar.Writer, buildOpts BuildTarOptions) error {
|
||||
return w.WriteHeader(&tar.Header{
|
||||
Typeflag: tar.TypeFifo,
|
||||
Name: buildOpts.Prefix + name,
|
||||
ModTime: now,
|
||||
AccessTime: now,
|
||||
ChangeTime: now,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// suid, guid, sticky bits for archive/tar
|
||||
// https://github.com/golang/go/blob/release-branch.go1.13/src/archive/tar/common.go#L607-L609
|
||||
const (
|
||||
cISUID = 04000 // Set uid
|
||||
cISGID = 02000 // Set gid
|
||||
cISVTX = 01000 // Save text (sticky bit)
|
||||
)
|
||||
|
||||
func permAndExtraMode2TarMode(fm os.FileMode) (tm int64) {
|
||||
tm = int64(fm & os.ModePerm)
|
||||
if fm&os.ModeSetuid != 0 {
|
||||
tm |= cISUID
|
||||
}
|
||||
if fm&os.ModeSetgid != 0 {
|
||||
tm |= cISGID
|
||||
}
|
||||
if fm&os.ModeSticky != 0 {
|
||||
tm |= cISVTX
|
||||
}
|
||||
return
|
||||
}
|
||||
3
vendor/github.com/containerd/ttrpc/.gitignore
generated
vendored
3
vendor/github.com/containerd/ttrpc/.gitignore
generated
vendored
@@ -9,6 +9,3 @@
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
||||
|
||||
24
vendor/github.com/containerd/ttrpc/.travis.yml
generated
vendored
24
vendor/github.com/containerd/ttrpc/.travis.yml
generated
vendored
@@ -1,24 +0,0 @@
|
||||
dist: bionic
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.13.x"
|
||||
- "1.15.x"
|
||||
|
||||
install:
|
||||
# Don't change local go.{mod, sum} by go get tools.
|
||||
#
|
||||
# ref: https://github.com/golang/go/issues/27643
|
||||
- pushd ..; go get -u github.com/vbatts/git-validation; popd
|
||||
- pushd ..; go get -u github.com/kunalkushwaha/ltag; popd
|
||||
|
||||
before_script:
|
||||
- pushd ..; git clone https://github.com/containerd/project; popd
|
||||
|
||||
script:
|
||||
- DCO_VERBOSITY=-q ../project/script/validate/dco
|
||||
- ../project/script/validate/fileheader ../project/
|
||||
- go test -v -race -covermode=atomic -coverprofile=coverage.txt ./...
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
14
vendor/github.com/containerd/ttrpc/README.md
generated
vendored
14
vendor/github.com/containerd/ttrpc/README.md
generated
vendored
@@ -1,6 +1,7 @@
|
||||
# ttrpc
|
||||
|
||||
[](https://travis-ci.org/containerd/ttrpc)
|
||||
[](https://github.com/containerd/ttrpc/actions?query=workflow%3ACI)
|
||||
[](https://codecov.io/gh/containerd/ttrpc)
|
||||
|
||||
GRPC for low-memory environments.
|
||||
|
||||
@@ -40,13 +41,8 @@ directly, if required.
|
||||
|
||||
# Status
|
||||
|
||||
Very new. YMMV.
|
||||
|
||||
TODO:
|
||||
|
||||
- [X] Plumb error codes and GRPC status
|
||||
- [X] Remove use of any type and dependency on typeurl package
|
||||
- [X] Ensure that protocol can support streaming in the future
|
||||
- [ ] Document protocol layout
|
||||
- [ ] Add testing under concurrent load to ensure
|
||||
- [ ] Verify connection error handling
|
||||
@@ -55,8 +51,8 @@ TODO:
|
||||
|
||||
ttrpc is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
||||
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
|
||||
6
vendor/github.com/containerd/ttrpc/channel.go
generated
vendored
6
vendor/github.com/containerd/ttrpc/channel.go
generated
vendored
@@ -19,11 +19,11 @@ package ttrpc
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -105,7 +105,7 @@ func (ch *channel) recv() (messageHeader, []byte, error) {
|
||||
|
||||
if mh.Length > uint32(messageLengthMax) {
|
||||
if _, err := ch.br.Discard(int(mh.Length)); err != nil {
|
||||
return mh, nil, errors.Wrapf(err, "failed to discard after receiving oversized message")
|
||||
return mh, nil, fmt.Errorf("failed to discard after receiving oversized message: %w", err)
|
||||
}
|
||||
|
||||
return mh, nil, status.Errorf(codes.ResourceExhausted, "message length %v exceed maximum message size of %v", mh.Length, messageLengthMax)
|
||||
@@ -113,7 +113,7 @@ func (ch *channel) recv() (messageHeader, []byte, error) {
|
||||
|
||||
p := ch.getmbuf(int(mh.Length))
|
||||
if _, err := io.ReadFull(ch.br, p); err != nil {
|
||||
return messageHeader{}, nil, errors.Wrapf(err, "failed reading message")
|
||||
return messageHeader{}, nil, fmt.Errorf("failed reading message: %w", err)
|
||||
}
|
||||
|
||||
return mh, p, nil
|
||||
|
||||
201
vendor/github.com/containerd/ttrpc/client.go
generated
vendored
201
vendor/github.com/containerd/ttrpc/client.go
generated
vendored
@@ -18,6 +18,7 @@ package ttrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
@@ -27,7 +28,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -194,72 +194,131 @@ type message struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type receiver struct {
|
||||
wg *sync.WaitGroup
|
||||
messages chan *message
|
||||
err error
|
||||
// callMap provides access to a map of active calls, guarded by a mutex.
|
||||
type callMap struct {
|
||||
m sync.Mutex
|
||||
activeCalls map[uint32]*callRequest
|
||||
closeErr error
|
||||
}
|
||||
|
||||
func (r *receiver) run(ctx context.Context, c *channel) {
|
||||
defer r.wg.Done()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
r.err = ctx.Err()
|
||||
return
|
||||
default:
|
||||
mh, p, err := c.recv()
|
||||
if err != nil {
|
||||
_, ok := status.FromError(err)
|
||||
if !ok {
|
||||
// treat all errors that are not an rpc status as terminal.
|
||||
// all others poison the connection.
|
||||
r.err = filterCloseErr(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
select {
|
||||
case r.messages <- &message{
|
||||
messageHeader: mh,
|
||||
p: p[:mh.Length],
|
||||
err: err,
|
||||
}:
|
||||
case <-ctx.Done():
|
||||
r.err = ctx.Err()
|
||||
return
|
||||
}
|
||||
}
|
||||
// newCallMap returns a new callMap with an empty set of active calls.
|
||||
func newCallMap() *callMap {
|
||||
return &callMap{
|
||||
activeCalls: make(map[uint32]*callRequest),
|
||||
}
|
||||
}
|
||||
|
||||
// set adds a call entry to the map with the given streamID key.
|
||||
func (cm *callMap) set(streamID uint32, cr *callRequest) error {
|
||||
cm.m.Lock()
|
||||
defer cm.m.Unlock()
|
||||
if cm.closeErr != nil {
|
||||
return cm.closeErr
|
||||
}
|
||||
cm.activeCalls[streamID] = cr
|
||||
return nil
|
||||
}
|
||||
|
||||
// get looks up the call entry for the given streamID key, then removes it
|
||||
// from the map and returns it.
|
||||
func (cm *callMap) get(streamID uint32) (cr *callRequest, ok bool, err error) {
|
||||
cm.m.Lock()
|
||||
defer cm.m.Unlock()
|
||||
if cm.closeErr != nil {
|
||||
return nil, false, cm.closeErr
|
||||
}
|
||||
cr, ok = cm.activeCalls[streamID]
|
||||
if ok {
|
||||
delete(cm.activeCalls, streamID)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// abort sends the given error to each active call, and clears the map.
|
||||
// Once abort has been called, any subsequent calls to the callMap will return the error passed to abort.
|
||||
func (cm *callMap) abort(err error) error {
|
||||
cm.m.Lock()
|
||||
defer cm.m.Unlock()
|
||||
if cm.closeErr != nil {
|
||||
return cm.closeErr
|
||||
}
|
||||
for streamID, call := range cm.activeCalls {
|
||||
call.errs <- err
|
||||
delete(cm.activeCalls, streamID)
|
||||
}
|
||||
cm.closeErr = err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) run() {
|
||||
var (
|
||||
streamID uint32 = 1
|
||||
waiters = make(map[uint32]*callRequest)
|
||||
calls = c.calls
|
||||
incoming = make(chan *message)
|
||||
receiversDone = make(chan struct{})
|
||||
wg sync.WaitGroup
|
||||
waiters = newCallMap()
|
||||
receiverDone = make(chan struct{})
|
||||
)
|
||||
|
||||
// broadcast the shutdown error to the remaining waiters.
|
||||
abortWaiters := func(wErr error) {
|
||||
for _, waiter := range waiters {
|
||||
waiter.errs <- wErr
|
||||
}
|
||||
}
|
||||
recv := &receiver{
|
||||
wg: &wg,
|
||||
messages: incoming,
|
||||
}
|
||||
wg.Add(1)
|
||||
|
||||
// Sender goroutine
|
||||
// Receives calls from dispatch, adds them to the set of active calls, and sends them
|
||||
// to the server.
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(receiversDone)
|
||||
var streamID uint32 = 1
|
||||
for {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
return
|
||||
case call := <-c.calls:
|
||||
id := streamID
|
||||
streamID += 2 // enforce odd client initiated request ids
|
||||
if err := waiters.set(id, call); err != nil {
|
||||
call.errs <- err // errs is buffered so should not block.
|
||||
continue
|
||||
}
|
||||
if err := c.send(id, messageTypeRequest, call.req); err != nil {
|
||||
call.errs <- err // errs is buffered so should not block.
|
||||
waiters.get(id) // remove from waiters set
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Receiver goroutine
|
||||
// Receives responses from the server, looks up the call info in the set of active calls,
|
||||
// and notifies the caller of the response.
|
||||
go func() {
|
||||
defer close(receiverDone)
|
||||
for {
|
||||
select {
|
||||
case <-c.ctx.Done():
|
||||
c.setError(c.ctx.Err())
|
||||
return
|
||||
default:
|
||||
mh, p, err := c.channel.recv()
|
||||
if err != nil {
|
||||
_, ok := status.FromError(err)
|
||||
if !ok {
|
||||
// treat all errors that are not an rpc status as terminal.
|
||||
// all others poison the connection.
|
||||
c.setError(filterCloseErr(err))
|
||||
return
|
||||
}
|
||||
}
|
||||
msg := &message{
|
||||
messageHeader: mh,
|
||||
p: p[:mh.Length],
|
||||
err: err,
|
||||
}
|
||||
call, ok, err := waiters.get(mh.StreamID)
|
||||
if err != nil {
|
||||
logrus.Errorf("ttrpc: failed to look up active call: %s", err)
|
||||
continue
|
||||
}
|
||||
if !ok {
|
||||
logrus.Errorf("ttrpc: received message for unknown channel %v", mh.StreamID)
|
||||
continue
|
||||
}
|
||||
call.errs <- c.recv(call.resp, msg)
|
||||
}
|
||||
}
|
||||
}()
|
||||
go recv.run(c.ctx, c.channel)
|
||||
|
||||
defer func() {
|
||||
c.conn.Close()
|
||||
@@ -269,32 +328,14 @@ func (c *Client) run() {
|
||||
|
||||
for {
|
||||
select {
|
||||
case call := <-calls:
|
||||
if err := c.send(streamID, messageTypeRequest, call.req); err != nil {
|
||||
call.errs <- err
|
||||
continue
|
||||
}
|
||||
|
||||
waiters[streamID] = call
|
||||
streamID += 2 // enforce odd client initiated request ids
|
||||
case msg := <-incoming:
|
||||
call, ok := waiters[msg.StreamID]
|
||||
if !ok {
|
||||
logrus.Errorf("ttrpc: received message for unknown channel %v", msg.StreamID)
|
||||
continue
|
||||
}
|
||||
|
||||
call.errs <- c.recv(call.resp, msg)
|
||||
delete(waiters, msg.StreamID)
|
||||
case <-receiversDone:
|
||||
// all the receivers have exited
|
||||
if recv.err != nil {
|
||||
c.setError(recv.err)
|
||||
}
|
||||
case <-receiverDone:
|
||||
// The receiver has exited.
|
||||
// don't return out, let the close of the context trigger the abort of waiters
|
||||
c.Close()
|
||||
case <-c.ctx.Done():
|
||||
abortWaiters(c.error())
|
||||
// Abort all active calls. This will also prevent any new calls from being added
|
||||
// to waiters.
|
||||
waiters.abort(c.error())
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -347,7 +388,7 @@ func filterCloseErr(err error) error {
|
||||
return nil
|
||||
case err == io.EOF:
|
||||
return ErrClosed
|
||||
case errors.Cause(err) == io.EOF:
|
||||
case errors.Is(err, io.EOF):
|
||||
return ErrClosed
|
||||
case strings.Contains(err.Error(), "use of closed network connection"):
|
||||
return ErrClosed
|
||||
|
||||
7
vendor/github.com/containerd/ttrpc/codec.go
generated
vendored
7
vendor/github.com/containerd/ttrpc/codec.go
generated
vendored
@@ -17,8 +17,9 @@
|
||||
package ttrpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type codec struct{}
|
||||
@@ -28,7 +29,7 @@ func (c codec) Marshal(msg interface{}) ([]byte, error) {
|
||||
case proto.Message:
|
||||
return proto.Marshal(v)
|
||||
default:
|
||||
return nil, errors.Errorf("ttrpc: cannot marshal unknown type: %T", msg)
|
||||
return nil, fmt.Errorf("ttrpc: cannot marshal unknown type: %T", msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +38,6 @@ func (c codec) Unmarshal(p []byte, msg interface{}) error {
|
||||
case proto.Message:
|
||||
return proto.Unmarshal(p, v)
|
||||
default:
|
||||
return errors.Errorf("ttrpc: cannot unmarshal into unknown type: %T", msg)
|
||||
return fmt.Errorf("ttrpc: cannot unmarshal into unknown type: %T", msg)
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/github.com/containerd/ttrpc/config.go
generated
vendored
2
vendor/github.com/containerd/ttrpc/config.go
generated
vendored
@@ -16,7 +16,7 @@
|
||||
|
||||
package ttrpc
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
import "errors"
|
||||
|
||||
type serverConfig struct {
|
||||
handshaker Handshaker
|
||||
|
||||
15
vendor/github.com/containerd/ttrpc/go.mod
generated
vendored
15
vendor/github.com/containerd/ttrpc/go.mod
generated
vendored
@@ -3,12 +3,11 @@ module github.com/containerd/ttrpc
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479
|
||||
google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24
|
||||
google.golang.org/grpc v1.26.0
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/prometheus/procfs v0.6.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
|
||||
google.golang.org/grpc v1.27.1
|
||||
google.golang.org/protobuf v1.27.1
|
||||
)
|
||||
|
||||
90
vendor/github.com/containerd/ttrpc/go.sum
generated
vendored
90
vendor/github.com/containerd/ttrpc/go.sum
generated
vendored
@@ -6,80 +6,94 @@ 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/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1 h1:Lo6mRUjdS99f3zxYOUalftWHUoOGaDRqFk1+j0Q57/I=
|
||||
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU=
|
||||
golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479 h1:LhLiKguPgZL+Tglay4GhVtfF0kb8cvOJ0dHTCBO8YNI=
|
||||
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
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-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 h1:4rNOqY4ULrKzS6twXa619uQgI7h9PaVd4ZhjFQ7C5zs=
|
||||
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24 h1:wDju+RU97qa0FZT0QnZDg9Uc2dH0Ql513kFvHocz+WM=
|
||||
google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
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=
|
||||
|
||||
2
vendor/github.com/containerd/ttrpc/server.go
generated
vendored
2
vendor/github.com/containerd/ttrpc/server.go
generated
vendored
@@ -18,6 +18,7 @@ package ttrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -25,7 +26,6 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
9
vendor/github.com/containerd/ttrpc/services.go
generated
vendored
9
vendor/github.com/containerd/ttrpc/services.go
generated
vendored
@@ -18,13 +18,14 @@ package ttrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"unsafe"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
@@ -51,7 +52,7 @@ func newServiceSet(interceptor UnaryServerInterceptor) *serviceSet {
|
||||
|
||||
func (s *serviceSet) register(name string, methods map[string]Method) {
|
||||
if _, ok := s.services[name]; ok {
|
||||
panic(errors.Errorf("duplicate service %v registered", name))
|
||||
panic(fmt.Errorf("duplicate service %v registered", name))
|
||||
}
|
||||
|
||||
s.services[name] = ServiceDesc{
|
||||
@@ -116,12 +117,12 @@ func (s *serviceSet) dispatch(ctx context.Context, serviceName, methodName strin
|
||||
func (s *serviceSet) resolve(service, method string) (Method, error) {
|
||||
srv, ok := s.services[service]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "service %v", service)
|
||||
return nil, status.Errorf(codes.Unimplemented, "service %v", service)
|
||||
}
|
||||
|
||||
mthd, ok := srv.Methods[method]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "method %v", method)
|
||||
return nil, status.Errorf(codes.Unimplemented, "method %v", method)
|
||||
}
|
||||
|
||||
return mthd, nil
|
||||
|
||||
15
vendor/github.com/containerd/ttrpc/unixcreds_linux.go
generated
vendored
15
vendor/github.com/containerd/ttrpc/unixcreds_linux.go
generated
vendored
@@ -18,11 +18,12 @@ package ttrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -31,12 +32,12 @@ type UnixCredentialsFunc func(*unix.Ucred) error
|
||||
func (fn UnixCredentialsFunc) Handshake(ctx context.Context, conn net.Conn) (net.Conn, interface{}, error) {
|
||||
uc, err := requireUnixSocket(conn)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "ttrpc.UnixCredentialsFunc: require unix socket")
|
||||
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: require unix socket: %w", err)
|
||||
}
|
||||
|
||||
rs, err := uc.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "ttrpc.UnixCredentialsFunc: (net.UnixConn).SyscallConn failed")
|
||||
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: (net.UnixConn).SyscallConn failed: %w", err)
|
||||
}
|
||||
var (
|
||||
ucred *unix.Ucred
|
||||
@@ -45,15 +46,15 @@ func (fn UnixCredentialsFunc) Handshake(ctx context.Context, conn net.Conn) (net
|
||||
if err := rs.Control(func(fd uintptr) {
|
||||
ucred, ucredErr = unix.GetsockoptUcred(int(fd), unix.SOL_SOCKET, unix.SO_PEERCRED)
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "ttrpc.UnixCredentialsFunc: (*syscall.RawConn).Control failed")
|
||||
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: (*syscall.RawConn).Control failed: %w", err)
|
||||
}
|
||||
|
||||
if ucredErr != nil {
|
||||
return nil, nil, errors.Wrapf(err, "ttrpc.UnixCredentialsFunc: failed to retrieve socket peer credentials")
|
||||
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: failed to retrieve socket peer credentials: %w", err)
|
||||
}
|
||||
|
||||
if err := fn(ucred); err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "ttrpc.UnixCredentialsFunc: credential check failed")
|
||||
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: credential check failed: %w", err)
|
||||
}
|
||||
|
||||
return uc, ucred, nil
|
||||
@@ -93,7 +94,7 @@ func requireRoot(ucred *unix.Ucred) error {
|
||||
|
||||
func requireUidGid(ucred *unix.Ucred, uid, gid int) error {
|
||||
if (uid != -1 && uint32(uid) != ucred.Uid) || (gid != -1 && uint32(gid) != ucred.Gid) {
|
||||
return errors.Wrap(syscall.EPERM, "ttrpc: invalid credentials")
|
||||
return fmt.Errorf("ttrpc: invalid credentials: %v", syscall.EPERM)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
32
vendor/github.com/goccy/go-json/.codecov.yml
generated
vendored
Normal file
32
vendor/github.com/goccy/go-json/.codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
codecov:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 70%
|
||||
threshold: 2%
|
||||
patch: off
|
||||
changes: no
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "header,diff"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
|
||||
ignore:
|
||||
- internal/encoder/vm_color
|
||||
- internal/encoder/vm_color_indent
|
||||
2
vendor/github.com/goccy/go-json/.gitignore
generated
vendored
Normal file
2
vendor/github.com/goccy/go-json/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
cover.html
|
||||
cover.out
|
||||
75
vendor/github.com/goccy/go-json/.golangci.yml
generated
vendored
Normal file
75
vendor/github.com/goccy/go-json/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
run:
|
||||
skip-files:
|
||||
- encode_optype.go
|
||||
- ".*_test\\.go$"
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- shadow
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- dogsled
|
||||
- dupl
|
||||
- exhaustive
|
||||
- exhaustivestruct
|
||||
- errorlint
|
||||
- forbidigo
|
||||
- funlen
|
||||
- gci
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocognit
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godot
|
||||
- godox
|
||||
- goerr113
|
||||
- gofumpt
|
||||
- gomnd
|
||||
- gosec
|
||||
- ifshort
|
||||
- lll
|
||||
- makezero
|
||||
- nakedret
|
||||
- nestif
|
||||
- nlreturn
|
||||
- paralleltest
|
||||
- testpackage
|
||||
- thelper
|
||||
- wrapcheck
|
||||
- interfacer
|
||||
- lll
|
||||
- nakedret
|
||||
- nestif
|
||||
- nlreturn
|
||||
- testpackage
|
||||
- wsl
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# not needed
|
||||
- path: /*.go
|
||||
text: "ST1003: should not use underscores in package names"
|
||||
linters:
|
||||
- stylecheck
|
||||
- path: /*.go
|
||||
text: "don't use an underscore in package name"
|
||||
linters:
|
||||
- golint
|
||||
- path: rtype.go
|
||||
linters:
|
||||
- golint
|
||||
- stylecheck
|
||||
- path: error.go
|
||||
linters:
|
||||
- staticcheck
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-issues-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
||||
268
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
Normal file
268
vendor/github.com/goccy/go-json/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
# v0.7.10 - 2021/10/16
|
||||
|
||||
* Fix conversion from pointer to uint64 ( #294 )
|
||||
|
||||
# v0.7.9 - 2021/09/28
|
||||
|
||||
* Fix encoding of nil value about interface type that has method ( #291 )
|
||||
|
||||
# v0.7.8 - 2021/09/01
|
||||
|
||||
* Fix mapassign_faststr for indirect struct type ( #283 )
|
||||
* Fix encoding of not empty interface type ( #284 )
|
||||
* Fix encoding of empty struct interface type ( #286 )
|
||||
|
||||
# v0.7.7 - 2021/08/25
|
||||
|
||||
* Fix invalid utf8 on stream decoder ( #279 )
|
||||
* Fix buffer length bug on string stream decoder ( #280 )
|
||||
|
||||
Thank you @orisano !!
|
||||
|
||||
# v0.7.6 - 2021/08/13
|
||||
|
||||
* Fix nil slice assignment ( #276 )
|
||||
* Improve error message ( #277 )
|
||||
|
||||
# v0.7.5 - 2021/08/12
|
||||
|
||||
* Fix encoding of embedded struct with tags ( #265 )
|
||||
* Fix encoding of embedded struct that isn't first field ( #272 )
|
||||
* Fix decoding of binary type with escaped char ( #273 )
|
||||
|
||||
# v0.7.4 - 2021/07/06
|
||||
|
||||
* Fix encoding of indirect layout structure ( #264 )
|
||||
|
||||
# v0.7.3 - 2021/06/29
|
||||
|
||||
* Fix encoding of pointer type in empty interface ( #262 )
|
||||
|
||||
# v0.7.2 - 2021/06/26
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Add decoder for func type to fix decoding of nil function value ( #257 )
|
||||
* Fix stream decoding of []byte type ( #258 )
|
||||
|
||||
### Performance
|
||||
|
||||
* Improve decoding performance of map[string]interface{} type ( use `mapassign_faststr` ) ( #256 )
|
||||
* Improve encoding performance of empty interface type ( remove recursive calling of `vm.Run` ) ( #259 )
|
||||
|
||||
### Benchmark
|
||||
|
||||
* Add bytedance/sonic as benchmark target ( #254 )
|
||||
|
||||
# v0.7.1 - 2021/06/18
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix error when unmarshal empty array ( #253 )
|
||||
|
||||
# v0.7.0 - 2021/06/12
|
||||
|
||||
### Support context for MarshalJSON and UnmarshalJSON ( #248 )
|
||||
|
||||
* json.MarshalContext(context.Context, interface{}, ...json.EncodeOption) ([]byte, error)
|
||||
* json.NewEncoder(io.Writer).EncodeContext(context.Context, interface{}, ...json.EncodeOption) error
|
||||
* json.UnmarshalContext(context.Context, []byte, interface{}, ...json.DecodeOption) error
|
||||
* json.NewDecoder(io.Reader).DecodeContext(context.Context, interface{}) error
|
||||
|
||||
```go
|
||||
type MarshalerContext interface {
|
||||
MarshalJSON(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
type UnmarshalerContext interface {
|
||||
UnmarshalJSON(context.Context, []byte) error
|
||||
}
|
||||
```
|
||||
|
||||
### Add DecodeFieldPriorityFirstWin option ( #242 )
|
||||
|
||||
In the default behavior, go-json, like encoding/json, will reflect the result of the last evaluation when a field with the same name exists. I've added new options to allow you to change this behavior. `json.DecodeFieldPriorityFirstWin` option reflects the result of the first evaluation if a field with the same name exists. This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated.
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix indent number contains recursive type ( #249 )
|
||||
* Fix encoding of using empty interface as map key ( #244 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding fields containing escaped characters ( #237 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* Move some tests to subdirectory ( #243 )
|
||||
* Refactor package layout for decoder ( #238 )
|
||||
|
||||
# v0.6.1 - 2021/06/02
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix value of totalLength for encoding ( #236 )
|
||||
|
||||
# v0.6.0 - 2021/06/01
|
||||
|
||||
### Support Colorize option for encoding (#233)
|
||||
|
||||
```go
|
||||
b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme))
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
fmt.Println(string(b)) // print colored json
|
||||
```
|
||||
|
||||
### Refactor
|
||||
|
||||
* Fix opcode layout - Adjust memory layout of the opcode to 128 bytes in a 64-bit environment ( #230 )
|
||||
* Refactor encode option ( #231 )
|
||||
* Refactor escape string ( #232 )
|
||||
|
||||
# v0.5.1 - 2021/5/20
|
||||
|
||||
### Optimization
|
||||
|
||||
* Add type addrShift to enable bigger encoder/decoder cache ( #213 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Keep original reference of slice element ( #229 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* Refactor Debug mode for encoding ( #226 )
|
||||
* Generate VM sources for encoding ( #227 )
|
||||
* Refactor validator for null/true/false for decoding ( #221 )
|
||||
|
||||
# v0.5.0 - 2021/5/9
|
||||
|
||||
### Supports using omitempty and string tags at the same time ( #216 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix stream decoder for unicode char ( #215 )
|
||||
* Fix decoding of slice element ( #219 )
|
||||
* Fix calculating of buffer length for stream decoder ( #220 )
|
||||
|
||||
### Refactor
|
||||
|
||||
* replace skipWhiteSpace goto by loop ( #212 )
|
||||
|
||||
# v0.4.14 - 2021/5/4
|
||||
|
||||
### Benchmark
|
||||
|
||||
* Add valyala/fastjson to benchmark ( #193 )
|
||||
* Add benchmark task for CI ( #211 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding of slice with unmarshal json type ( #198 )
|
||||
* Fix decoding of null value for interface type that does not implement Unmarshaler ( #205 )
|
||||
* Fix decoding of null value to []byte by json.Unmarshal ( #206 )
|
||||
* Fix decoding of backslash char at the end of string ( #207 )
|
||||
* Fix stream decoder for null/true/false value ( #208 )
|
||||
* Fix stream decoder for slow reader ( #211 )
|
||||
|
||||
### Performance
|
||||
|
||||
* If cap of slice is enough, reuse slice data for compatibility with encoding/json ( #200 )
|
||||
|
||||
# v0.4.13 - 2021/4/20
|
||||
|
||||
### Fix json.Compact and json.Indent
|
||||
|
||||
* Support validation the input buffer for json.Compact and json.Indent ( #189 )
|
||||
* Optimize json.Compact and json.Indent ( improve memory footprint ) ( #190 )
|
||||
|
||||
# v0.4.12 - 2021/4/15
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fix unnecessary indent for empty slice type ( #181 )
|
||||
* Fix encoding of omitempty feature for the slice or interface type ( #183 )
|
||||
* Fix encoding custom types zero values with omitempty when marshaller exists ( #187 )
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoder for invalid top level value ( #184 )
|
||||
* Fix decoder for invalid number value ( #185 )
|
||||
|
||||
# v0.4.11 - 2021/4/3
|
||||
|
||||
* Improve decoder performance for interface type
|
||||
|
||||
# v0.4.10 - 2021/4/2
|
||||
|
||||
### Fix encoder
|
||||
|
||||
* Fixed a bug when encoding slice and map containing recursive structures
|
||||
* Fixed a logic to determine if indirect reference
|
||||
|
||||
# v0.4.9 - 2021/3/29
|
||||
|
||||
### Add debug mode
|
||||
|
||||
If you use `json.MarshalWithOption(v, json.Debug())` and `panic` occurred in `go-json`, produces debug information to console.
|
||||
|
||||
### Support a new feature to compatible with encoding/json
|
||||
|
||||
- invalid UTF-8 is coerced to valid UTF-8 ( without performance down )
|
||||
|
||||
### Fix encoder
|
||||
|
||||
- Fixed handling of MarshalJSON of function type
|
||||
|
||||
### Fix decoding of slice of pointer type
|
||||
|
||||
If there is a pointer value, go-json will use it. (This behavior is necessary to achieve the ability to prioritize pre-filled values). However, since slices are reused internally, there was a bug that referred to the previous pointer value. Therefore, it is not necessary to refer to the pointer value in advance for the slice element, so we explicitly initialize slice element by `nil`.
|
||||
|
||||
# v0.4.8 - 2021/3/21
|
||||
|
||||
### Reduce memory usage at compile time
|
||||
|
||||
* go-json have used about 2GB of memory at compile time, but now it can compile with about less than 550MB.
|
||||
|
||||
### Fix any encoder's bug
|
||||
|
||||
* Add many test cases for encoder
|
||||
* Fix composite type ( slice/array/map )
|
||||
* Fix pointer types
|
||||
* Fix encoding of MarshalJSON or MarshalText or json.Number type
|
||||
|
||||
### Refactor encoder
|
||||
|
||||
* Change package layout for reducing memory usage at compile
|
||||
* Remove anonymous and only operation
|
||||
* Remove root property from encodeCompileContext and opcode
|
||||
|
||||
### Fix CI
|
||||
|
||||
* Add Go 1.16
|
||||
* Remove Go 1.13
|
||||
* Fix `make cover` task
|
||||
|
||||
### Number/Delim/Token/RawMessage use the types defined in encoding/json by type alias
|
||||
|
||||
# v0.4.7 - 2021/02/22
|
||||
|
||||
### Fix decoder
|
||||
|
||||
* Fix decoding of deep recursive structure
|
||||
* Fix decoding of embedded unexported pointer field
|
||||
* Fix invalid test case
|
||||
* Fix decoding of invalid value
|
||||
* Fix decoding of prefilled value
|
||||
* Fix not being able to return UnmarshalTypeError when it should be returned
|
||||
* Fix decoding of null value
|
||||
* Fix decoding of type of null string
|
||||
* Use pre allocated pointer if exists it at decoding
|
||||
|
||||
### Reduce memory usage at compile
|
||||
|
||||
* Integrate int/int8/int16/int32/int64 and uint/uint8/uint16/uint32/uint64 operation to reduce memory usage at compile
|
||||
|
||||
### Remove unnecessary optype
|
||||
21
vendor/github.com/goccy/go-json/LICENSE
generated
vendored
Normal file
21
vendor/github.com/goccy/go-json/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Masaaki Goshima
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
39
vendor/github.com/goccy/go-json/Makefile
generated
vendored
Normal file
39
vendor/github.com/goccy/go-json/Makefile
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
PKG := github.com/goccy/go-json
|
||||
|
||||
BIN_DIR := $(CURDIR)/bin
|
||||
PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test)
|
||||
COVER_PKGS := $(foreach pkg,$(PKGS),$(subst $(PKG),.,$(pkg)))
|
||||
|
||||
COMMA := ,
|
||||
EMPTY :=
|
||||
SPACE := $(EMPTY) $(EMPTY)
|
||||
COVERPKG_OPT := $(subst $(SPACE),$(COMMA),$(COVER_PKGS))
|
||||
|
||||
$(BIN_DIR):
|
||||
@mkdir -p $(BIN_DIR)
|
||||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out ./...
|
||||
|
||||
.PHONY: cover-html
|
||||
cover-html: cover
|
||||
go tool cover -html=cover.out
|
||||
|
||||
.PHONY: lint
|
||||
lint: golangci-lint
|
||||
golangci-lint run
|
||||
|
||||
golangci-lint: | $(BIN_DIR)
|
||||
@{ \
|
||||
set -e; \
|
||||
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
|
||||
cd $$GOLANGCI_LINT_TMP_DIR; \
|
||||
go mod init tmp; \
|
||||
GOBIN=$(BIN_DIR) go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.36.0; \
|
||||
rm -rf $$GOLANGCI_LINT_TMP_DIR; \
|
||||
}
|
||||
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./internal/...
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user