This is an unreleased version of c/image, but it is important to
to have the test added in in the next commit enforcing as soon as
possible.

> go get github.com/containers/image/v5@HEAD
> make vendor

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
Miloslav Trmač 2020-04-30 21:23:18 +02:00 committed by Valentin Rothberg
parent 42f68c1c76
commit 8f845aac23
65 changed files with 545 additions and 364 deletions

4
go.mod
View File

@ -4,9 +4,9 @@ go 1.12
require ( require (
github.com/containerd/containerd v1.3.0 // indirect github.com/containerd/containerd v1.3.0 // indirect
github.com/containers/image/v5 v5.4.3 github.com/containers/image/v5 v5.4.4-0.20200504143706-d52a99c5329e
github.com/containers/ocicrypt v1.0.2 github.com/containers/ocicrypt v1.0.2
github.com/containers/storage v1.19.0 github.com/containers/storage v1.19.1
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f
github.com/dsnet/compress v0.0.1 // indirect github.com/dsnet/compress v0.0.1 // indirect
github.com/go-check/check v0.0.0-20180628173108-788fd7840127 github.com/go-check/check v0.0.0-20180628173108-788fd7840127

27
go.sum
View File

@ -38,16 +38,14 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/containers/image/v5 v5.4.3 h1:zn2HR7uu4hpvT5QQHgjqonOzKDuM1I1UHUEmzZT5sbs= github.com/containers/image/v5 v5.4.4-0.20200504143706-d52a99c5329e h1:9bh+m/q5cuowLt6jMei1gz3b1uqBkQ0hFKQH07OzdqM=
github.com/containers/image/v5 v5.4.3/go.mod h1:pN0tvp3YbDd7BWavK2aE0mvJUqVd2HmhPjekyWSFm0U= github.com/containers/image/v5 v5.4.4-0.20200504143706-d52a99c5329e/go.mod h1:Y16cLFoR9N1yWMeppYTWHd+KmUgwNhAsDiKVCmB+6H4=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo= github.com/containers/ocicrypt v1.0.2 h1:Q0/IPs8ohfbXNxEfyJ2pFVmvJu5BhqJUAmc6ES9NKbo=
github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M= github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M=
github.com/containers/storage v1.18.2 h1:4cgFbrrgr9nR9xCeOmfpyxk1MtXYZGr7XGPJfAVkGmc= github.com/containers/storage v1.19.1 h1:YKIzOO12iaD5Ra0PKFS6emcygbHLmwmQOCQRU/19YAQ=
github.com/containers/storage v1.18.2/go.mod h1:WTBMf+a9ZZ/LbmEVeLHH2TX4CikWbO1Bt+/m58ZHVPg= github.com/containers/storage v1.19.1/go.mod h1:KbXjSwKnx17ejOsjFcCXSf78mCgZkQSLPBNTMRc3XrQ=
github.com/containers/storage v1.19.0 h1:bVIF5EglbT5PQnqcN7sE6VWqoQzlToqzjXdz+eNubQg=
github.com/containers/storage v1.19.0/go.mod h1:9Xc4rrTubn5hmtBfL+PSJH1XlfTQwR4VAG1NDUIpCts=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 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/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-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@ -133,10 +131,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.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8= github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc=
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.3 h1:Ce2to9wvs/cuJ2b86/CKQoTYr9VHfpanYosZ0UBJqdw= github.com/klauspost/pgzip v1.2.3 h1:Ce2to9wvs/cuJ2b86/CKQoTYr9VHfpanYosZ0UBJqdw=
github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@ -185,7 +181,6 @@ github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.m
github.com/opencontainers/runtime-spec v1.0.0 h1:O6L965K88AilqnxeYPks/75HLpp4IG+FjeSCI3cVdRg= github.com/opencontainers/runtime-spec v1.0.0 h1:O6L965K88AilqnxeYPks/75HLpp4IG+FjeSCI3cVdRg=
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.0/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/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
github.com/opencontainers/selinux v1.4.0/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/opencontainers/selinux v1.5.1 h1:jskKwSMFYqyTrHEuJgQoUlTcId0av64S6EWObrIfn5Y= github.com/opencontainers/selinux v1.5.1 h1:jskKwSMFYqyTrHEuJgQoUlTcId0av64S6EWObrIfn5Y=
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw= github.com/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913 h1:TnbXhKzrTOyuvWrjI8W6pcoI9XPbLHFXCdN2dtUw7Rw=
@ -261,8 +256,8 @@ github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE= github.com/vbatts/tar-split v0.11.1 h1:0Odu65rhcZ3JZaPHxl7tCI3V/C/Q9Zf82UFravl02dE=
github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g= github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g=
github.com/vbauerster/mpb/v5 v5.0.3 h1:Ldt/azOkbThTk2loi6FrBd/3fhxGFQ24MxFAS88PoNY= github.com/vbauerster/mpb/v5 v5.0.4 h1:w7l/tJfHmtIOKZkU+bhbDZOUxj1kln9jy4DUOp3Tl14=
github.com/vbauerster/mpb/v5 v5.0.3/go.mod h1:h3YxU5CSr8rZP4Q3xZPVB3jJLhWPou63lHEdr9ytH4Y= github.com/vbauerster/mpb/v5 v5.0.4/go.mod h1:fvzasBUyuo35UyuA6sSOlVhpLoNQsp2nBdHw7OiSUU8=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA=
github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@ -286,9 +281,10 @@ go4.org v0.0.0-20190218023631-ce4c26f7be8e/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -328,10 +324,11 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191127021746-63cb32ae39b2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE=
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=

View File

@ -798,7 +798,6 @@ func (ic *imageCopier) copyLayers(ctx context.Context) error {
// copyGroup is used to determine if all layers are copied // copyGroup is used to determine if all layers are copied
copyGroup := sync.WaitGroup{} copyGroup := sync.WaitGroup{}
copyGroup.Add(numLayers)
// copySemaphore is used to limit the number of parallel downloads to // copySemaphore is used to limit the number of parallel downloads to
// avoid malicious images causing troubles and to be nice to servers. // avoid malicious images causing troubles and to be nice to servers.
@ -850,18 +849,22 @@ func (ic *imageCopier) copyLayers(ctx context.Context) error {
if err := func() error { // A scope for defer if err := func() error { // A scope for defer
progressPool, progressCleanup := ic.c.newProgressPool(ctx) progressPool, progressCleanup := ic.c.newProgressPool(ctx)
defer progressCleanup() defer func() {
// Wait for all layers to be copied. progressCleanup() must not be called while any of the copyLayerHelpers interact with the progressPool.
copyGroup.Wait()
progressCleanup()
}()
for i, srcLayer := range srcInfos { for i, srcLayer := range srcInfos {
err = copySemaphore.Acquire(ctx, 1) err = copySemaphore.Acquire(ctx, 1)
if err != nil { if err != nil {
return errors.Wrapf(err, "Can't acquire semaphore") return errors.Wrapf(err, "Can't acquire semaphore")
} }
copyGroup.Add(1)
go copyLayerHelper(i, srcLayer, encLayerBitmap[i], progressPool) go copyLayerHelper(i, srcLayer, encLayerBitmap[i], progressPool)
} }
// Wait for all layers to be copied // A call to copyGroup.Wait() is done at this point by the defer above.
copyGroup.Wait()
return nil return nil
}(); err != nil { }(); err != nil {
return err return err

View File

@ -613,6 +613,9 @@ func (c *dockerClient) getBearerTokenOAuth2(ctx context.Context, challenge chall
params.Add("client_id", "containers/image") params.Add("client_id", "containers/image")
authReq.Body = ioutil.NopCloser(bytes.NewBufferString(params.Encode())) authReq.Body = ioutil.NopCloser(bytes.NewBufferString(params.Encode()))
if c.sys != nil && c.sys.DockerRegistryUserAgent != "" {
authReq.Header.Add("User-Agent", c.sys.DockerRegistryUserAgent)
}
authReq.Header.Add("Content-Type", "application/x-www-form-urlencoded") authReq.Header.Add("Content-Type", "application/x-www-form-urlencoded")
logrus.Debugf("%s %s", authReq.Method, authReq.URL.String()) logrus.Debugf("%s %s", authReq.Method, authReq.URL.String())
res, err := c.client.Do(authReq) res, err := c.client.Do(authReq)
@ -665,6 +668,9 @@ func (c *dockerClient) getBearerToken(ctx context.Context, challenge challenge,
if c.auth.Username != "" && c.auth.Password != "" { if c.auth.Username != "" && c.auth.Password != "" {
authReq.SetBasicAuth(c.auth.Username, c.auth.Password) authReq.SetBasicAuth(c.auth.Username, c.auth.Password)
} }
if c.sys != nil && c.sys.DockerRegistryUserAgent != "" {
authReq.Header.Add("User-Agent", c.sys.DockerRegistryUserAgent)
}
logrus.Debugf("%s %s", authReq.Method, authReq.URL.String()) logrus.Debugf("%s %s", authReq.Method, authReq.URL.String())
res, err := c.client.Do(authReq) res, err := c.client.Do(authReq)

View File

@ -37,7 +37,7 @@ func newImage(ctx context.Context, sys *types.SystemContext, ref dockerReference
// SourceRefFullName returns a fully expanded name for the repository this image is in. // SourceRefFullName returns a fully expanded name for the repository this image is in.
func (i *Image) SourceRefFullName() string { func (i *Image) SourceRefFullName() string {
return i.src.ref.ref.Name() return i.src.logicalRef.ref.Name()
} }
// GetRepositoryTags list all tags available in the repository. The tag // GetRepositoryTags list all tags available in the repository. The tag
@ -45,7 +45,7 @@ func (i *Image) SourceRefFullName() string {
// backward-compatible shim method which calls the module-level // backward-compatible shim method which calls the module-level
// GetRepositoryTags) // GetRepositoryTags)
func (i *Image) GetRepositoryTags(ctx context.Context) ([]string, error) { func (i *Image) GetRepositoryTags(ctx context.Context) ([]string, error) {
return GetRepositoryTags(ctx, i.src.c.sys, i.src.ref) return GetRepositoryTags(ctx, i.src.c.sys, i.src.logicalRef)
} }
// GetRepositoryTags list all tags available in the repository. The tag // GetRepositoryTags list all tags available in the repository. The tag

View File

@ -16,6 +16,7 @@ import (
"github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/internal/iolimits" "github.com/containers/image/v5/internal/iolimits"
"github.com/containers/image/v5/internal/uploadreader"
"github.com/containers/image/v5/manifest" "github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/pkg/blobinfocache/none" "github.com/containers/image/v5/pkg/blobinfocache/none"
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
@ -162,19 +163,30 @@ func (d *dockerImageDestination) PutBlob(ctx context.Context, stream io.Reader,
digester := digest.Canonical.Digester() digester := digest.Canonical.Digester()
sizeCounter := &sizeCounter{} sizeCounter := &sizeCounter{}
tee := io.TeeReader(stream, io.MultiWriter(digester.Hash(), sizeCounter)) uploadLocation, err = func() (*url.URL, error) { // A scope for defer
res, err = d.c.makeRequestToResolvedURL(ctx, "PATCH", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, tee, inputInfo.Size, v2Auth, nil) uploadReader := uploadreader.NewUploadReader(io.TeeReader(stream, io.MultiWriter(digester.Hash(), sizeCounter)))
// This error text should never be user-visible, we terminate only after makeRequestToResolvedURL
// returns, so there isnt a way for the error text to be provided to any of our callers.
defer uploadReader.Terminate(errors.New("Reading data from an already terminated upload"))
res, err = d.c.makeRequestToResolvedURL(ctx, "PATCH", uploadLocation.String(), map[string][]string{"Content-Type": {"application/octet-stream"}}, uploadReader, inputInfo.Size, v2Auth, nil)
if err != nil { if err != nil {
logrus.Debugf("Error uploading layer chunked, response %#v", res) logrus.Debugf("Error uploading layer chunked %v", err)
return types.BlobInfo{}, err return nil, err
} }
defer res.Body.Close() defer res.Body.Close()
computedDigest := digester.Digest() if !successStatus(res.StatusCode) {
return nil, errors.Wrapf(client.HandleErrorResponse(res), "Error uploading layer chunked")
uploadLocation, err = res.Location()
if err != nil {
return types.BlobInfo{}, errors.Wrap(err, "Error determining upload URL")
} }
uploadLocation, err := res.Location()
if err != nil {
return nil, errors.Wrap(err, "Error determining upload URL")
}
return uploadLocation, nil
}()
if err != nil {
return types.BlobInfo{}, err
}
computedDigest := digester.Digest()
// FIXME: DELETE uploadLocation on failure (does not really work in docker/distribution servers, which incorrectly require the "delete" action in the token's scope) // FIXME: DELETE uploadLocation on failure (does not really work in docker/distribution servers, which incorrectly require the "delete" action in the token's scope)
@ -469,17 +481,17 @@ func (d *dockerImageDestination) PutSignatures(ctx context.Context, signatures [
} }
switch { switch {
case d.c.signatureBase != nil: case d.c.signatureBase != nil:
return d.putSignaturesToLookaside(signatures, instanceDigest) return d.putSignaturesToLookaside(signatures, *instanceDigest)
case d.c.supportsSignatures: case d.c.supportsSignatures:
return d.putSignaturesToAPIExtension(ctx, signatures, instanceDigest) return d.putSignaturesToAPIExtension(ctx, signatures, *instanceDigest)
default: default:
return errors.Errorf("X-Registry-Supports-Signatures extension not supported, and lookaside is not configured") return errors.Errorf("X-Registry-Supports-Signatures extension not supported, and lookaside is not configured")
} }
} }
// putSignaturesToLookaside implements PutSignatures() from the lookaside location configured in s.c.signatureBase, // putSignaturesToLookaside implements PutSignatures() from the lookaside location configured in s.c.signatureBase,
// which is not nil. // which is not nil, for a manifest with manifestDigest.
func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, instanceDigest *digest.Digest) error { func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, manifestDigest digest.Digest) error {
// FIXME? This overwrites files one at a time, definitely not atomic. // FIXME? This overwrites files one at a time, definitely not atomic.
// A failure when updating signatures with a reordered copy could lose some of them. // A failure when updating signatures with a reordered copy could lose some of them.
@ -490,7 +502,7 @@ func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, i
// NOTE: Keep this in sync with docs/signature-protocols.md! // NOTE: Keep this in sync with docs/signature-protocols.md!
for i, signature := range signatures { for i, signature := range signatures {
url := signatureStorageURL(d.c.signatureBase, *instanceDigest, i) url := signatureStorageURL(d.c.signatureBase, manifestDigest, i)
if url == nil { if url == nil {
return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil") return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
} }
@ -505,7 +517,7 @@ func (d *dockerImageDestination) putSignaturesToLookaside(signatures [][]byte, i
// is enough for dockerImageSource to stop looking for other signatures, so that // is enough for dockerImageSource to stop looking for other signatures, so that
// is sufficient. // is sufficient.
for i := len(signatures); ; i++ { for i := len(signatures); ; i++ {
url := signatureStorageURL(d.c.signatureBase, *instanceDigest, i) url := signatureStorageURL(d.c.signatureBase, manifestDigest, i)
if url == nil { if url == nil {
return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil") return errors.Errorf("Internal error: signatureStorageURL with non-nil base returned nil")
} }
@ -564,8 +576,9 @@ func (c *dockerClient) deleteOneSignature(url *url.URL) (missing bool, err error
} }
} }
// putSignaturesToAPIExtension implements PutSignatures() using the X-Registry-Supports-Signatures API extension. // putSignaturesToAPIExtension implements PutSignatures() using the X-Registry-Supports-Signatures API extension,
func (d *dockerImageDestination) putSignaturesToAPIExtension(ctx context.Context, signatures [][]byte, instanceDigest *digest.Digest) error { // for a manifest with manifestDigest.
func (d *dockerImageDestination) putSignaturesToAPIExtension(ctx context.Context, signatures [][]byte, manifestDigest digest.Digest) error {
// Skip dealing with the manifest digest, or reading the old state, if not necessary. // Skip dealing with the manifest digest, or reading the old state, if not necessary.
if len(signatures) == 0 { if len(signatures) == 0 {
return nil return nil
@ -575,7 +588,7 @@ func (d *dockerImageDestination) putSignaturesToAPIExtension(ctx context.Context
// always adds signatures. Eventually we should also allow removing signatures, // always adds signatures. Eventually we should also allow removing signatures,
// but the X-Registry-Supports-Signatures API extension does not support that yet. // but the X-Registry-Supports-Signatures API extension does not support that yet.
existingSignatures, err := d.c.getExtensionsSignatures(ctx, d.ref, *instanceDigest) existingSignatures, err := d.c.getExtensionsSignatures(ctx, d.ref, manifestDigest)
if err != nil { if err != nil {
return err return err
} }
@ -600,7 +613,7 @@ sigExists:
if err != nil || n != 16 { if err != nil || n != 16 {
return errors.Wrapf(err, "Error generating random signature len %d", n) return errors.Wrapf(err, "Error generating random signature len %d", n)
} }
signatureName = fmt.Sprintf("%s@%032x", instanceDigest.String(), randBytes) signatureName = fmt.Sprintf("%s@%032x", manifestDigest.String(), randBytes)
if _, ok := existingSigNames[signatureName]; !ok { if _, ok := existingSigNames[signatureName]; !ok {
break break
} }
@ -616,7 +629,7 @@ sigExists:
return err return err
} }
path := fmt.Sprintf(extensionsSignaturePath, reference.Path(d.ref.ref), d.manifestDigest.String()) path := fmt.Sprintf(extensionsSignaturePath, reference.Path(d.ref.ref), manifestDigest.String())
res, err := d.c.makeRequest(ctx, "PUT", path, nil, bytes.NewReader(body), v2Auth, nil) res, err := d.c.makeRequest(ctx, "PUT", path, nil, bytes.NewReader(body), v2Auth, nil)
if err != nil { if err != nil {
return err return err

View File

@ -24,7 +24,8 @@ import (
) )
type dockerImageSource struct { type dockerImageSource struct {
ref dockerReference logicalRef dockerReference // The reference the user requested.
physicalRef dockerReference // The actual reference we are accessing (possibly a mirror)
c *dockerClient c *dockerClient
// State // State
cachedManifest []byte // nil if not loaded yet cachedManifest []byte // nil if not loaded yet
@ -49,7 +50,6 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
} }
} }
primaryDomain := reference.Domain(ref.ref)
// Check all endpoints for the manifest availability. If we find one that does // Check all endpoints for the manifest availability. If we find one that does
// contain the image, it will be used for all future pull actions. Always try the // contain the image, it will be used for all future pull actions. Always try the
// non-mirror original location last; this both transparently handles the case // non-mirror original location last; this both transparently handles the case
@ -66,7 +66,7 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
attempts := []attempt{} attempts := []attempt{}
for _, pullSource := range pullSources { for _, pullSource := range pullSources {
logrus.Debugf("Trying to access %q", pullSource.Reference) logrus.Debugf("Trying to access %q", pullSource.Reference)
s, err := newImageSourceAttempt(ctx, sys, pullSource, primaryDomain) s, err := newImageSourceAttempt(ctx, sys, ref, pullSource)
if err == nil { if err == nil {
return s, nil return s, nil
} }
@ -95,31 +95,32 @@ func newImageSource(ctx context.Context, sys *types.SystemContext, ref dockerRef
} }
// newImageSourceAttempt is an internal helper for newImageSource. Everyone else must call newImageSource. // newImageSourceAttempt is an internal helper for newImageSource. Everyone else must call newImageSource.
// Given a pullSource and primaryDomain, return a dockerImageSource if it is reachable. // Given a logicalReference and a pullSource, return a dockerImageSource if it is reachable.
// The caller must call .Close() on the returned ImageSource. // The caller must call .Close() on the returned ImageSource.
func newImageSourceAttempt(ctx context.Context, sys *types.SystemContext, pullSource sysregistriesv2.PullSource, primaryDomain string) (*dockerImageSource, error) { func newImageSourceAttempt(ctx context.Context, sys *types.SystemContext, logicalRef dockerReference, pullSource sysregistriesv2.PullSource) (*dockerImageSource, error) {
ref, err := newReference(pullSource.Reference) physicalRef, err := newReference(pullSource.Reference)
if err != nil { if err != nil {
return nil, err return nil, err
} }
endpointSys := sys endpointSys := sys
// sys.DockerAuthConfig does not explicitly specify a registry; we must not blindly send the credentials intended for the primary endpoint to mirrors. // sys.DockerAuthConfig does not explicitly specify a registry; we must not blindly send the credentials intended for the primary endpoint to mirrors.
if endpointSys != nil && endpointSys.DockerAuthConfig != nil && reference.Domain(ref.ref) != primaryDomain { if endpointSys != nil && endpointSys.DockerAuthConfig != nil && reference.Domain(physicalRef.ref) != reference.Domain(logicalRef.ref) {
copy := *endpointSys copy := *endpointSys
copy.DockerAuthConfig = nil copy.DockerAuthConfig = nil
copy.DockerBearerRegistryToken = "" copy.DockerBearerRegistryToken = ""
endpointSys = &copy endpointSys = &copy
} }
client, err := newDockerClientFromRef(endpointSys, ref, false, "pull") client, err := newDockerClientFromRef(endpointSys, physicalRef, false, "pull")
if err != nil { if err != nil {
return nil, err return nil, err
} }
client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure client.tlsClientConfig.InsecureSkipVerify = pullSource.Endpoint.Insecure
s := &dockerImageSource{ s := &dockerImageSource{
ref: ref, logicalRef: logicalRef,
physicalRef: physicalRef,
c: client, c: client,
} }
@ -132,7 +133,7 @@ func newImageSourceAttempt(ctx context.Context, sys *types.SystemContext, pullSo
// Reference returns the reference used to set up this source, _as specified by the user_ // Reference returns the reference used to set up this source, _as specified by the user_
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image. // (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
func (s *dockerImageSource) Reference() types.ImageReference { func (s *dockerImageSource) Reference() types.ImageReference {
return s.ref return s.logicalRef
} }
// Close removes resources associated with an initialized ImageSource, if any. // Close removes resources associated with an initialized ImageSource, if any.
@ -181,7 +182,7 @@ func (s *dockerImageSource) GetManifest(ctx context.Context, instanceDigest *dig
} }
func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest string) ([]byte, string, error) { func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest string) ([]byte, string, error) {
path := fmt.Sprintf(manifestPath, reference.Path(s.ref.ref), tagOrDigest) path := fmt.Sprintf(manifestPath, reference.Path(s.physicalRef.ref), tagOrDigest)
headers := map[string][]string{ headers := map[string][]string{
"Accept": manifest.DefaultRequestedManifestMIMETypes, "Accept": manifest.DefaultRequestedManifestMIMETypes,
} }
@ -191,7 +192,7 @@ func (s *dockerImageSource) fetchManifest(ctx context.Context, tagOrDigest strin
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != http.StatusOK { if res.StatusCode != http.StatusOK {
return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.ref.ref.Name()) return nil, "", errors.Wrapf(client.HandleErrorResponse(res), "Error reading manifest %s in %s", tagOrDigest, s.physicalRef.ref.Name())
} }
manblob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxManifestBodySize) manblob, err := iolimits.ReadAtMost(res.Body, iolimits.MaxManifestBodySize)
@ -213,7 +214,7 @@ func (s *dockerImageSource) ensureManifestIsLoaded(ctx context.Context) error {
return nil return nil
} }
reference, err := s.ref.tagOrDigest() reference, err := s.physicalRef.tagOrDigest()
if err != nil { if err != nil {
return err return err
} }
@ -271,7 +272,7 @@ func (s *dockerImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
return s.getExternalBlob(ctx, info.URLs) return s.getExternalBlob(ctx, info.URLs)
} }
path := fmt.Sprintf(blobsPath, reference.Path(s.ref.ref), info.Digest.String()) path := fmt.Sprintf(blobsPath, reference.Path(s.physicalRef.ref), info.Digest.String())
logrus.Debugf("Downloading %s", path) logrus.Debugf("Downloading %s", path)
res, err := s.c.makeRequest(ctx, "GET", path, nil, nil, v2Auth, nil) res, err := s.c.makeRequest(ctx, "GET", path, nil, nil, v2Auth, nil)
if err != nil { if err != nil {
@ -280,7 +281,7 @@ func (s *dockerImageSource) GetBlob(ctx context.Context, info types.BlobInfo, ca
if err := httpResponseToError(res, "Error fetching blob"); err != nil { if err := httpResponseToError(res, "Error fetching blob"); err != nil {
return nil, 0, err return nil, 0, err
} }
cache.RecordKnownLocation(s.ref.Transport(), bicTransportScope(s.ref), info.Digest, newBICLocationReference(s.ref)) cache.RecordKnownLocation(s.physicalRef.Transport(), bicTransportScope(s.physicalRef), info.Digest, newBICLocationReference(s.physicalRef))
return res.Body, getBlobSize(res), nil return res.Body, getBlobSize(res), nil
} }
@ -308,7 +309,7 @@ func (s *dockerImageSource) manifestDigest(ctx context.Context, instanceDigest *
if instanceDigest != nil { if instanceDigest != nil {
return *instanceDigest, nil return *instanceDigest, nil
} }
if digested, ok := s.ref.ref.(reference.Digested); ok { if digested, ok := s.physicalRef.ref.(reference.Digested); ok {
d := digested.Digest() d := digested.Digest()
if d.Algorithm() == digest.Canonical { if d.Algorithm() == digest.Canonical {
return d, nil return d, nil
@ -398,7 +399,7 @@ func (s *dockerImageSource) getSignaturesFromAPIExtension(ctx context.Context, i
return nil, err return nil, err
} }
parsedBody, err := s.c.getExtensionsSignatures(ctx, s.ref, manifestDigest) parsedBody, err := s.c.getExtensionsSignatures(ctx, s.physicalRef, manifestDigest)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -115,12 +115,23 @@ func getCPUVariant(os string, arch string) string {
return "" return ""
} }
// compatibility contains, for a specified architecture, a list of known variants, in the
// order from most capable (most restrictive) to least capable (most compatible).
// Architectures that dont have variants should not have an entry here.
var compatibility = map[string][]string{ var compatibility = map[string][]string{
"arm": {"v7", "v6", "v5"}, "arm": {"v8", "v7", "v6", "v5"},
"arm64": {"v8"}, "arm64": {"v8"},
} }
// Returns all compatible platforms with the platform specifics possibly overriden by user, // baseVariants contains, for a specified architecture, a variant that is known to be
// supported by _all_ machines using that architecture.
// Architectures that dont have variants, or where there are possible versions without
// an established variant name, should not have an entry here.
var baseVariants = map[string]string{
"arm64": "v8",
}
// WantedPlatforms returns all compatible platforms with the platform specifics possibly overriden by user,
// the most compatible platform is first. // the most compatible platform is first.
// If some option (arch, os, variant) is not present, a value from current platform is detected. // If some option (arch, os, variant) is not present, a value from current platform is detected.
func WantedPlatforms(ctx *types.SystemContext) ([]imgspecv1.Platform, error) { func WantedPlatforms(ctx *types.SystemContext) ([]imgspecv1.Platform, error) {
@ -145,59 +156,45 @@ func WantedPlatforms(ctx *types.SystemContext) ([]imgspecv1.Platform, error) {
wantedOS = ctx.OSChoice wantedOS = ctx.OSChoice
} }
var wantedPlatforms []imgspecv1.Platform var variants []string = nil
if wantedVariant != "" && compatibility[wantedArch] != nil { if wantedVariant != "" {
wantedPlatforms = make([]imgspecv1.Platform, 0, len(compatibility[wantedArch])) if compatibility[wantedArch] != nil {
wantedIndex := -1 variantOrder := compatibility[wantedArch]
for i, v := range compatibility[wantedArch] { for i, v := range variantOrder {
if wantedVariant == v { if wantedVariant == v {
wantedIndex = i variants = variantOrder[i:]
break break
} }
} }
// user wants a variant which we know nothing about - not even compatibility
if wantedIndex == -1 {
wantedPlatforms = []imgspecv1.Platform{
{
OS: wantedOS,
Architecture: wantedArch,
Variant: wantedVariant,
},
} }
if variants == nil {
// user wants a variant which we know nothing about - not even compatibility
variants = []string{wantedVariant}
}
variants = append(variants, "")
} else { } else {
for i := wantedIndex; i < len(compatibility[wantedArch]); i++ { variants = append(variants, "") // No variant specified, use a “no variant specified” image if present
v := compatibility[wantedArch][i] if baseVariant, ok := baseVariants[wantedArch]; ok {
wantedPlatforms = append(wantedPlatforms, imgspecv1.Platform{ // But also accept an image with the “base” variant for the architecture, if it exists.
variants = append(variants, baseVariant)
}
}
res := make([]imgspecv1.Platform, 0, len(variants))
for _, v := range variants {
res = append(res, imgspecv1.Platform{
OS: wantedOS, OS: wantedOS,
Architecture: wantedArch, Architecture: wantedArch,
Variant: v, Variant: v,
}) })
} }
} return res, nil
} else {
wantedPlatforms = []imgspecv1.Platform{
{
OS: wantedOS,
Architecture: wantedArch,
Variant: wantedVariant,
},
}
}
return wantedPlatforms, nil
} }
// MatchesPlatform returns true if a platform descriptor from a multi-arch image matches
// an item from the return value of WantedPlatforms.
func MatchesPlatform(image imgspecv1.Platform, wanted imgspecv1.Platform) bool { func MatchesPlatform(image imgspecv1.Platform, wanted imgspecv1.Platform) bool {
if image.Architecture != wanted.Architecture { return image.Architecture == wanted.Architecture &&
return false image.OS == wanted.OS &&
} image.Variant == wanted.Variant
if image.OS != wanted.OS {
return false
}
if wanted.Variant == "" || image.Variant == wanted.Variant {
return true
}
return false
} }

View File

@ -0,0 +1,61 @@
package uploadreader
import (
"io"
"sync"
)
// UploadReader is a pass-through reader for use in sending non-trivial data using the net/http
// package (http.NewRequest, http.Post and the like).
//
// The net/http package uses a separate goroutine to upload data to a HTTP connection,
// and it is possible for the server to return a response (typically an error) before consuming
// the full body of the request. In that case http.Client.Do can return with an error while
// the body is still being read — regardless of of the cancellation, if any, of http.Request.Context().
//
// As a result, any data used/updated by the io.Reader() provided as the request body may be
// used/updated even after http.Client.Do returns, causing races.
//
// To fix this, UploadReader provides a synchronized Terminate() method, which can block for
// a not-completely-negligible time (for a duration of the underlying Read()), but guarantees that
// after Terminate() returns, the underlying reader is never used any more (unlike calling
// the cancellation callback of context.WithCancel, which returns before any recipients may have
// reacted to the cancellation).
type UploadReader struct {
mutex sync.Mutex
// The following members can only be used with mutex held
reader io.Reader
terminationError error // nil if not terminated yet
}
// NewUploadReader returns an UploadReader for an "underlying" reader.
func NewUploadReader(underlying io.Reader) *UploadReader {
return &UploadReader{
reader: underlying,
terminationError: nil,
}
}
// Read returns the error set by Terminate, if any, or calls the underlying reader.
// It is safe to call this from a different goroutine than Terminate.
func (ur *UploadReader) Read(p []byte) (int, error) {
ur.mutex.Lock()
defer ur.mutex.Unlock()
if ur.terminationError != nil {
return 0, ur.terminationError
}
return ur.reader.Read(p)
}
// Terminate waits for in-progress Read calls, if any, to finish, and ensures that after
// this function returns, any Read calls will fail with the provided error, and the underlying
// reader will never be used any more.
//
// It is safe to call this from a different goroutine than Read.
func (ur *UploadReader) Terminate(err error) {
ur.mutex.Lock() // May block for some time if ur.reader.Read() is in progress
defer ur.mutex.Unlock()
ur.terminationError = err
}

View File

@ -0,0 +1,118 @@
package manifest
import (
"fmt"
"github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/types"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// dupStringSlice returns a deep copy of a slice of strings, or nil if the
// source slice is empty.
func dupStringSlice(list []string) []string {
if len(list) == 0 {
return nil
}
dup := make([]string, len(list))
copy(dup, list)
return dup
}
// dupStringStringMap returns a deep copy of a map[string]string, or nil if the
// passed-in map is nil or has no keys.
func dupStringStringMap(m map[string]string) map[string]string {
if len(m) == 0 {
return nil
}
result := make(map[string]string)
for k, v := range m {
result[k] = v
}
return result
}
// layerInfosToStrings converts a list of layer infos, presumably obtained from a Manifest.LayerInfos()
// method call, into a format suitable for inclusion in a types.ImageInspectInfo structure.
func layerInfosToStrings(infos []LayerInfo) []string {
layers := make([]string, len(infos))
for i, info := range infos {
layers[i] = info.Digest.String()
}
return layers
}
// compressionMIMETypeSet describes a set of MIME type “variants” that represent differently-compressed
// versions of “the same kind of content”.
// The map key is the return value of compression.Algorithm.Name(), or mtsUncompressed;
// the map value is a MIME type, or mtsUnsupportedMIMEType to mean "recognized but unsupported".
type compressionMIMETypeSet map[string]string
const mtsUncompressed = "" // A key in compressionMIMETypeSet for the uncompressed variant
const mtsUnsupportedMIMEType = "" // A value in compressionMIMETypeSet that means “recognized but unsupported”
// compressionVariantMIMEType returns a variant of mimeType for the specified algorithm (which may be nil
// to mean "no compression"), based on variantTable.
func compressionVariantMIMEType(variantTable []compressionMIMETypeSet, mimeType string, algorithm *compression.Algorithm) (string, error) {
if mimeType == mtsUnsupportedMIMEType { // Prevent matching against the {algo:mtsUnsupportedMIMEType} entries
return "", fmt.Errorf("cannot update unknown MIME type")
}
for _, variants := range variantTable {
for _, mt := range variants {
if mt == mimeType { // Found the variant
name := mtsUncompressed
if algorithm != nil {
name = algorithm.Name()
}
if res, ok := variants[name]; ok {
if res != mtsUnsupportedMIMEType {
return res, nil
}
if name != mtsUncompressed {
return "", fmt.Errorf("%s compression is not supported", name)
}
return "", errors.New("uncompressed variant is not supported")
}
if name != mtsUncompressed {
return "", fmt.Errorf("unknown compression algorithm %s", name)
}
// We can't very well say “the idea of no compression is unknown”
return "", errors.New("uncompressed variant is not supported")
}
}
}
if algorithm != nil {
return "", fmt.Errorf("unsupported MIME type for compression: %s", mimeType)
}
return "", fmt.Errorf("unsupported MIME type for decompression: %s", mimeType)
}
// updatedMIMEType returns the result of applying edits in updated (MediaType, CompressionOperation) to
// mimeType, based on variantTable. It may use updated.Digest for error messages.
func updatedMIMEType(variantTable []compressionMIMETypeSet, mimeType string, updated types.BlobInfo) (string, error) {
// Note that manifests in containers-storage might be reporting the
// wrong media type since the original manifests are stored while layers
// are decompressed in storage. Hence, we need to consider the case
// that an already {de}compressed layer should be {de}compressed;
// compressionVariantMIMEType does that by not caring whether the original is
// {de}compressed.
switch updated.CompressionOperation {
case types.PreserveOriginal:
// Keep the original media type.
return mimeType, nil
case types.Decompress:
return compressionVariantMIMEType(variantTable, mimeType, nil)
case types.Compress:
if updated.CompressionAlgorithm == nil {
logrus.Debugf("Error preparing updated manifest: blob %q was compressed but does not specify by which algorithm: falling back to use the original blob", updated.Digest)
return mimeType, nil
}
return compressionVariantMIMEType(variantTable, mimeType, updated.CompressionAlgorithm)
default:
return "", fmt.Errorf("unknown compression operation (%d)", updated.CompressionOperation)
}
}

View File

@ -10,7 +10,6 @@ import (
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
) )
// Schema2Descriptor is a “descriptor” in docker/distribution schema 2. // Schema2Descriptor is a “descriptor” in docker/distribution schema 2.
@ -213,26 +212,17 @@ func (m *Schema2) LayerInfos() []LayerInfo {
return blobs return blobs
} }
// isSchema2ForeignLayer is a convenience wrapper to check if a given mime type var schema2CompressionMIMETypeSets = []compressionMIMETypeSet{
// is a compressed or decompressed schema 2 foreign layer. {
func isSchema2ForeignLayer(mimeType string) bool { mtsUncompressed: DockerV2Schema2ForeignLayerMediaType,
switch mimeType { compression.Gzip.Name(): DockerV2Schema2ForeignLayerMediaTypeGzip,
case DockerV2Schema2ForeignLayerMediaType, DockerV2Schema2ForeignLayerMediaTypeGzip: compression.Zstd.Name(): mtsUnsupportedMIMEType,
return true },
default: {
return false mtsUncompressed: DockerV2SchemaLayerMediaTypeUncompressed,
} compression.Gzip.Name(): DockerV2Schema2LayerMediaType,
} compression.Zstd.Name(): mtsUnsupportedMIMEType,
},
// isSchema2Layer is a convenience wrapper to check if a given mime type is a
// compressed or decompressed schema 2 layer.
func isSchema2Layer(mimeType string) bool {
switch mimeType {
case DockerV2SchemaLayerMediaTypeUncompressed, DockerV2Schema2LayerMediaType:
return true
default:
return false
}
} }
// UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls), in order (the root layer first, and then successive layered layers) // UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls), in order (the root layer first, and then successive layered layers)
@ -243,67 +233,16 @@ func (m *Schema2) UpdateLayerInfos(layerInfos []types.BlobInfo) error {
original := m.LayersDescriptors original := m.LayersDescriptors
m.LayersDescriptors = make([]Schema2Descriptor, len(layerInfos)) m.LayersDescriptors = make([]Schema2Descriptor, len(layerInfos))
for i, info := range layerInfos { for i, info := range layerInfos {
mimeType := original[i].MediaType
// First make sure we support the media type of the original layer. // First make sure we support the media type of the original layer.
if err := SupportedSchema2MediaType(original[i].MediaType); err != nil { if err := SupportedSchema2MediaType(mimeType); err != nil {
return fmt.Errorf("Error preparing updated manifest: unknown media type of original layer: %q", original[i].MediaType) return fmt.Errorf("Error preparing updated manifest: unknown media type of original layer %q: %q", info.Digest, mimeType)
} }
mimeType, err := updatedMIMEType(schema2CompressionMIMETypeSets, mimeType, info)
// Set the correct media types based on the specified compression if err != nil {
// operation, the desired compression algorithm AND the original media return errors.Wrapf(err, "Error preparing updated manifest, layer %q", info.Digest)
// type.
//
// Note that manifests in containers-storage might be reporting the
// wrong media type since the original manifests are stored while layers
// are decompressed in storage. Hence, we need to consider the case
// that an already {de}compressed layer should be {de}compressed, which
// is being addressed in `isSchema2{Foreign}Layer`.
switch info.CompressionOperation {
case types.PreserveOriginal:
// Keep the original media type.
m.LayersDescriptors[i].MediaType = original[i].MediaType
case types.Decompress:
// Decompress the original media type and check if it was
// non-distributable one or not.
mimeType := original[i].MediaType
switch {
case isSchema2ForeignLayer(mimeType):
m.LayersDescriptors[i].MediaType = DockerV2Schema2ForeignLayerMediaType
case isSchema2Layer(mimeType):
m.LayersDescriptors[i].MediaType = DockerV2SchemaLayerMediaTypeUncompressed
default:
return fmt.Errorf("Error preparing updated manifest: unsupported media type for decompression: %q", original[i].MediaType)
}
case types.Compress:
if info.CompressionAlgorithm == nil {
logrus.Debugf("Preparing updated manifest: blob %q was compressed but does not specify by which algorithm: falling back to use the original blob", info.Digest)
m.LayersDescriptors[i].MediaType = original[i].MediaType
break
}
// Compress the original media type and set the new one based on
// that type (distributable or not) and the specified compression
// algorithm. Throw an error if the algorithm is not supported.
switch info.CompressionAlgorithm.Name() {
case compression.Gzip.Name():
mimeType := original[i].MediaType
switch {
case isSchema2ForeignLayer(mimeType):
m.LayersDescriptors[i].MediaType = DockerV2Schema2ForeignLayerMediaTypeGzip
case isSchema2Layer(mimeType):
m.LayersDescriptors[i].MediaType = DockerV2Schema2LayerMediaType
default:
return fmt.Errorf("Error preparing updated manifest: unsupported media type for compression: %q", original[i].MediaType)
}
case compression.Zstd.Name():
return fmt.Errorf("Error preparing updated manifest: zstd compression is not supported for docker images")
default:
return fmt.Errorf("Error preparing updated manifest: unknown compression algorithm %q for layer %q", info.CompressionAlgorithm.Name(), info.Digest)
}
default:
return fmt.Errorf("Error preparing updated manifest: unknown compression operation (%d) for layer %q", info.CompressionOperation, info.Digest)
} }
m.LayersDescriptors[i].MediaType = mimeType
m.LayersDescriptors[i].Digest = info.Digest m.LayersDescriptors[i].Digest = info.Digest
m.LayersDescriptors[i].Size = info.Size m.LayersDescriptors[i].Size = info.Size
m.LayersDescriptors[i].URLs = info.URLs m.LayersDescriptors[i].URLs = info.URLs

View File

@ -107,7 +107,7 @@ func (list *Schema2List) ChooseInstance(ctx *types.SystemContext) (digest.Digest
} }
} }
} }
return "", fmt.Errorf("no image found in manifest list for architecture %s, variant %s, OS %s", wantedPlatforms[0].Architecture, wantedPlatforms[0].Variant, wantedPlatforms[0].OS) return "", fmt.Errorf("no image found in manifest list for architecture %s, variant %q, OS %s", wantedPlatforms[0].Architecture, wantedPlatforms[0].Variant, wantedPlatforms[0].OS)
} }
// Serialize returns the list in a blob format. // Serialize returns the list in a blob format.

View File

@ -59,30 +59,6 @@ type ListUpdate struct {
MediaType string MediaType string
} }
// dupStringSlice returns a deep copy of a slice of strings, or nil if the
// source slice is empty.
func dupStringSlice(list []string) []string {
if len(list) == 0 {
return nil
}
dup := make([]string, len(list))
copy(dup, list)
return dup
}
// dupStringStringMap returns a deep copy of a map[string]string, or nil if the
// passed-in map is nil or has no keys.
func dupStringStringMap(m map[string]string) map[string]string {
if len(m) == 0 {
return nil
}
result := make(map[string]string)
for k, v := range m {
result[k] = v
}
return result
}
// ListFromBlob parses a list of manifests. // ListFromBlob parses a list of manifests.
func ListFromBlob(manifest []byte, manifestMIMEType string) (List, error) { func ListFromBlob(manifest []byte, manifestMIMEType string) (List, error) {
normalized := NormalizedMIMEType(manifestMIMEType) normalized := NormalizedMIMEType(manifestMIMEType)

View File

@ -256,13 +256,3 @@ func FromBlob(manblob []byte, mt string) (Manifest, error) {
// Note that this may not be reachable, NormalizedMIMEType has a default for unknown values. // Note that this may not be reachable, NormalizedMIMEType has a default for unknown values.
return nil, fmt.Errorf("Unimplemented manifest MIME type %s (normalized as %s)", mt, nmt) return nil, fmt.Errorf("Unimplemented manifest MIME type %s (normalized as %s)", mt, nmt)
} }
// layerInfosToStrings converts a list of layer infos, presumably obtained from a Manifest.LayerInfos()
// method call, into a format suitable for inclusion in a types.ImageInspectInfo structure.
func layerInfosToStrings(infos []LayerInfo) []string {
layers := make([]string, len(infos))
for i, info := range infos {
layers[i] = info.Digest.String()
}
return layers
}

View File

@ -12,7 +12,6 @@ import (
"github.com/opencontainers/image-spec/specs-go" "github.com/opencontainers/image-spec/specs-go"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1" imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
) )
// BlobInfoFromOCI1Descriptor returns a types.BlobInfo based on the input OCI1 descriptor. // BlobInfoFromOCI1Descriptor returns a types.BlobInfo based on the input OCI1 descriptor.
@ -95,26 +94,17 @@ func (m *OCI1) LayerInfos() []LayerInfo {
return blobs return blobs
} }
// isOCI1NonDistributableLayer is a convenience wrapper to check if a given mime var oci1CompressionMIMETypeSets = []compressionMIMETypeSet{
// type is a compressed or decompressed OCI v1 non-distributable layer. {
func isOCI1NonDistributableLayer(mimeType string) bool { mtsUncompressed: imgspecv1.MediaTypeImageLayerNonDistributable,
switch mimeType { compression.Gzip.Name(): imgspecv1.MediaTypeImageLayerNonDistributableGzip,
case imgspecv1.MediaTypeImageLayerNonDistributable, imgspecv1.MediaTypeImageLayerNonDistributableGzip, imgspecv1.MediaTypeImageLayerNonDistributableZstd: compression.Zstd.Name(): imgspecv1.MediaTypeImageLayerNonDistributableZstd,
return true },
default: {
return false mtsUncompressed: imgspecv1.MediaTypeImageLayer,
} compression.Gzip.Name(): imgspecv1.MediaTypeImageLayerGzip,
} compression.Zstd.Name(): imgspecv1.MediaTypeImageLayerZstd,
},
// isOCI1Layer is a convenience wrapper to check if a given mime type is a
// compressed or decompressed OCI v1 layer.
func isOCI1Layer(mimeType string) bool {
switch mimeType {
case imgspecv1.MediaTypeImageLayer, imgspecv1.MediaTypeImageLayerGzip, imgspecv1.MediaTypeImageLayerZstd:
return true
default:
return false
}
} }
// UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls+mediatype), in order (the root layer first, and then successive layered layers) // UpdateLayerInfos replaces the original layers with the specified BlobInfos (size+digest+urls+mediatype), in order (the root layer first, and then successive layered layers)
@ -133,79 +123,19 @@ func (m *OCI1) UpdateLayerInfos(layerInfos []types.BlobInfo) error {
} }
mimeType = decMimeType mimeType = decMimeType
} }
mimeType, err := updatedMIMEType(oci1CompressionMIMETypeSets, mimeType, info)
// Set the correct media types based on the specified compression
// operation, the desired compression algorithm AND the original media
// type.
//
// Note that manifests in containers-storage might be reporting the
// wrong media type since the original manifests are stored while layers
// are decompressed in storage. Hence, we need to consider the case
// that an already {de}compressed layer should be {de}compressed, which
// is being addressed in `isSchema2{Foreign}Layer`.
switch info.CompressionOperation {
case types.PreserveOriginal:
// Keep the original media type.
m.Layers[i].MediaType = mimeType
case types.Decompress:
// Decompress the original media type and check if it was
// non-distributable one or not.
switch {
case isOCI1NonDistributableLayer(mimeType):
m.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerNonDistributable
case isOCI1Layer(mimeType):
m.Layers[i].MediaType = imgspecv1.MediaTypeImageLayer
default:
return fmt.Errorf("Error preparing updated manifest: unsupported media type for decompression: %q", mimeType)
}
case types.Compress:
if info.CompressionAlgorithm == nil {
logrus.Debugf("Error preparing updated manifest: blob %q was compressed but does not specify by which algorithm: falling back to use the original blob", info.Digest)
m.Layers[i].MediaType = mimeType
break
}
// Compress the original media type and set the new one based on
// that type (distributable or not) and the specified compression
// algorithm. Throw an error if the algorithm is not supported.
switch info.CompressionAlgorithm.Name() {
case compression.Gzip.Name():
switch {
case isOCI1NonDistributableLayer(mimeType):
m.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerNonDistributableGzip
case isOCI1Layer(mimeType):
m.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerGzip
default:
return fmt.Errorf("Error preparing updated manifest: unsupported media type for compression: %q", mimeType)
}
case compression.Zstd.Name():
switch {
case isOCI1NonDistributableLayer(mimeType):
m.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerNonDistributableZstd
case isOCI1Layer(mimeType):
m.Layers[i].MediaType = imgspecv1.MediaTypeImageLayerZstd
default:
return fmt.Errorf("Error preparing updated manifest: unsupported media type for compression: %q", mimeType)
}
default:
return fmt.Errorf("Error preparing updated manifest: unknown compression algorithm %q for layer %q", info.CompressionAlgorithm.Name(), info.Digest)
}
default:
return fmt.Errorf("Error preparing updated manifest: unknown compression operation (%d) for layer %q", info.CompressionOperation, info.Digest)
}
if info.CryptoOperation == types.Encrypt {
encMediaType, err := getEncryptedMediaType(m.Layers[i].MediaType)
if err != nil { if err != nil {
return fmt.Errorf("error preparing updated manifest: encryption specified but no counterpart for mediatype: %q", m.Layers[i].MediaType) return errors.Wrapf(err, "Error preparing updated manifest, layer %q", info.Digest)
} }
m.Layers[i].MediaType = encMediaType if info.CryptoOperation == types.Encrypt {
encMediaType, err := getEncryptedMediaType(mimeType)
if err != nil {
return fmt.Errorf("error preparing updated manifest: encryption specified but no counterpart for mediatype: %q", mimeType)
}
mimeType = encMediaType
} }
m.Layers[i].MediaType = mimeType
m.Layers[i].Digest = info.Digest m.Layers[i].Digest = info.Digest
m.Layers[i].Size = info.Size m.Layers[i].Size = info.Size
m.Layers[i].Annotations = info.Annotations m.Layers[i].Annotations = info.Annotations

View File

@ -79,6 +79,9 @@ func (index *OCI1Index) ChooseInstance(ctx *types.SystemContext) (digest.Digest,
} }
for _, wantedPlatform := range wantedPlatforms { for _, wantedPlatform := range wantedPlatforms {
for _, d := range index.Manifests { for _, d := range index.Manifests {
if d.Platform == nil {
continue
}
imagePlatform := imgspecv1.Platform{ imagePlatform := imgspecv1.Platform{
Architecture: d.Platform.Architecture, Architecture: d.Platform.Architecture,
OS: d.Platform.OS, OS: d.Platform.OS,
@ -97,7 +100,7 @@ func (index *OCI1Index) ChooseInstance(ctx *types.SystemContext) (digest.Digest,
return d.Digest, nil return d.Digest, nil
} }
} }
return "", fmt.Errorf("no image found in image index for architecture %s, variant %s, OS %s", wantedPlatforms[0].Architecture, wantedPlatforms[0].Variant, wantedPlatforms[0].OS) return "", fmt.Errorf("no image found in image index for architecture %s, variant %q, OS %s", wantedPlatforms[0].Architecture, wantedPlatforms[0].Variant, wantedPlatforms[0].OS)
} }
// Serialize returns the index in a blob format. // Serialize returns the index in a blob format.

View File

@ -6,12 +6,12 @@ const (
// VersionMajor is for an API incompatible changes // VersionMajor is for an API incompatible changes
VersionMajor = 5 VersionMajor = 5
// VersionMinor is for functionality in a backwards-compatible manner // VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 4 VersionMinor = 5
// VersionPatch is for backwards-compatible bug fixes // VersionPatch is for backwards-compatible bug fixes
VersionPatch = 3 VersionPatch = 0
// VersionDev indicates development branch. Releases will be empty string. // VersionDev indicates development branch. Releases will be empty string.
VersionDev = "" VersionDev = "-dev"
) )
// Version is the specification version that the package types support. // Version is the specification version that the package types support.

View File

@ -19,9 +19,9 @@ env:
#### ####
# GCE project where images live # GCE project where images live
IMAGE_PROJECT: "libpod-218412" IMAGE_PROJECT: "libpod-218412"
_BUILT_IMAGE_SUFFIX: "libpod-5874660151656448" _BUILT_IMAGE_SUFFIX: "libpod-6301182083727360"
FEDORA_CACHE_IMAGE_NAME: "fedora-31-${_BUILT_IMAGE_SUFFIX}" FEDORA_CACHE_IMAGE_NAME: "fedora-32-${_BUILT_IMAGE_SUFFIX}"
PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-30-${_BUILT_IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-31-${_BUILT_IMAGE_SUFFIX}"
UBUNTU_CACHE_IMAGE_NAME: "ubuntu-19-${_BUILT_IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "ubuntu-19-${_BUILT_IMAGE_SUFFIX}"
PRIOR_UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-${_BUILT_IMAGE_SUFFIX}" PRIOR_UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-${_BUILT_IMAGE_SUFFIX}"

View File

@ -1 +1 @@
1.19.0 1.19.1

View File

@ -148,10 +148,20 @@ func (c *Container) ProcessLabel() string {
} }
func (c *Container) MountOpts() []string { func (c *Container) MountOpts() []string {
if mountOpts, ok := c.Flags["MountOpts"].([]string); ok { switch c.Flags["MountOpts"].(type) {
return mountOpts case []string:
return c.Flags["MountOpts"].([]string)
case []interface{}:
var mountOpts []string
for _, v := range c.Flags["MountOpts"].([]interface{}) {
if flag, ok := v.(string); ok {
mountOpts = append(mountOpts, flag)
} }
}
return mountOpts
default:
return nil return nil
}
} }
func (r *containerStore) Containers() ([]Container, error) { func (r *containerStore) Containers() ([]Container, error) {

View File

@ -384,9 +384,21 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr
} }
}() }()
// In the case of a read-only mount we first mount read-write so we can set the
// correct permissions on the mount point and remount read-only afterwards.
remountReadOnly := false
mountOptions := d.options.mountOptions mountOptions := d.options.mountOptions
if len(options.Options) > 0 { if len(options.Options) > 0 {
mountOptions = strings.Join(options.Options, ",") var newOptions []string
for _, option := range options.Options {
if option == "ro" {
// Filter out read-only mount option but remember for later remounting.
remountReadOnly = true
} else {
newOptions = append(newOptions, option)
}
}
mountOptions = strings.Join(newOptions, ",")
} }
filesystem := d.zfsPath(id) filesystem := d.zfsPath(id)
@ -409,7 +421,14 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr
// this could be our first mount after creation of the filesystem, and the root dir may still have root // this could be our first mount after creation of the filesystem, and the root dir may still have root
// permissions instead of the remapped root uid:gid (if user namespaces are enabled): // permissions instead of the remapped root uid:gid (if user namespaces are enabled):
if err := os.Chown(mountpoint, rootUID, rootGID); err != nil { if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err) return "", errors.Wrapf(err, "modifying zfs mountpoint (%s) ownership", mountpoint)
}
if remountReadOnly {
opts = label.FormatMountLabel("remount,ro", options.MountLabel)
if err := mount.Mount(filesystem, mountpoint, "zfs", opts); err != nil {
return "", errors.Wrap(err, "error remounting zfs mount read-only")
}
} }
return mountpoint, nil return mountpoint, nil

View File

@ -6,7 +6,7 @@ require (
github.com/Microsoft/hcsshim v0.8.7 github.com/Microsoft/hcsshim v0.8.7
github.com/docker/go-units v0.4.0 github.com/docker/go-units v0.4.0
github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-multierror v1.0.0
github.com/klauspost/compress v1.10.4 github.com/klauspost/compress v1.10.5
github.com/klauspost/pgzip v1.2.3 github.com/klauspost/pgzip v1.2.3
github.com/mattn/go-shellwords v1.0.10 github.com/mattn/go-shellwords v1.0.10
github.com/mistifyio/go-zfs v2.1.1+incompatible github.com/mistifyio/go-zfs v2.1.1+incompatible

View File

@ -41,8 +41,8 @@ github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 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/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc= github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc=
github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/pgzip v1.2.3 h1:Ce2to9wvs/cuJ2b86/CKQoTYr9VHfpanYosZ0UBJqdw= github.com/klauspost/pgzip v1.2.3 h1:Ce2to9wvs/cuJ2b86/CKQoTYr9VHfpanYosZ0UBJqdw=
github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=

View File

@ -992,6 +992,9 @@ func (r *layerStore) deleteInternal(id string) error {
if err == nil { if err == nil {
os.Remove(r.tspath(id)) os.Remove(r.tspath(id))
delete(r.byid, id) delete(r.byid, id)
for _, name := range layer.Names {
delete(r.byname, name)
}
r.idindex.Delete(id) r.idindex.Delete(id)
mountLabel := layer.MountLabel mountLabel := layer.MountLabel
if layer.MountPoint != "" { if layer.MountPoint != "" {

View File

@ -394,7 +394,7 @@ func fillGo18FileTypeBits(mode int64, fi os.FileInfo) int64 {
// to a tar header // to a tar header
func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error {
capability, err := system.Lgetxattr(path, "security.capability") capability, err := system.Lgetxattr(path, "security.capability")
if err != nil && err != system.EOPNOTSUPP { if err != nil && err != system.EOPNOTSUPP && err != system.ErrNotSupportedPlatform {
return err return err
} }
if capability != nil { if capability != nil {
@ -407,7 +407,7 @@ func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error {
// ReadUserXattrToTarHeader reads user.* xattr from filesystem to a tar header // ReadUserXattrToTarHeader reads user.* xattr from filesystem to a tar header
func ReadUserXattrToTarHeader(path string, hdr *tar.Header) error { func ReadUserXattrToTarHeader(path string, hdr *tar.Header) error {
xattrs, err := system.Llistxattr(path) xattrs, err := system.Llistxattr(path)
if err != nil && err != system.EOPNOTSUPP { if err != nil && err != system.EOPNOTSUPP && err != system.ErrNotSupportedPlatform {
return err return err
} }
for _, key := range xattrs { for _, key := range xattrs {

View File

@ -3397,7 +3397,7 @@ func copyStringInterfaceMap(m map[string]interface{}) map[string]interface{} {
} }
// defaultConfigFile path to the system wide storage.conf file // defaultConfigFile path to the system wide storage.conf file
const defaultConfigFile = "/etc/containers/storage.conf" var defaultConfigFile = "/etc/containers/storage.conf"
// AutoUserNsMinSize is the minimum size for automatically created user namespaces // AutoUserNsMinSize is the minimum size for automatically created user namespaces
const AutoUserNsMinSize = 1024 const AutoUserNsMinSize = 1024
@ -3409,6 +3409,11 @@ const AutoUserNsMaxSize = 65536
// creating a user namespace. // creating a user namespace.
const RootAutoUserNsUser = "containers" const RootAutoUserNsUser = "containers"
// SetDefaultConfigFilePath sets the default configuration to the specified path
func SetDefaultConfigFilePath(path string) {
defaultConfigFile = path
}
// DefaultConfigFile returns the path to the storage config file used // DefaultConfigFile returns the path to the storage config file used
func DefaultConfigFile(rootless bool) (string, error) { func DefaultConfigFile(rootless bool) (string, error) {
if rootless { if rootless {

View File

@ -131,17 +131,25 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
b.Type = blockType((bh >> 1) & 3) b.Type = blockType((bh >> 1) & 3)
// find size. // find size.
cSize := int(bh >> 3) cSize := int(bh >> 3)
maxSize := maxBlockSize
switch b.Type { switch b.Type {
case blockTypeReserved: case blockTypeReserved:
return ErrReservedBlockType return ErrReservedBlockType
case blockTypeRLE: case blockTypeRLE:
b.RLESize = uint32(cSize) b.RLESize = uint32(cSize)
if b.lowMem {
maxSize = cSize
}
cSize = 1 cSize = 1
case blockTypeCompressed: case blockTypeCompressed:
if debug { if debug {
println("Data size on stream:", cSize) println("Data size on stream:", cSize)
} }
b.RLESize = 0 b.RLESize = 0
maxSize = maxCompressedBlockSize
if windowSize < maxCompressedBlockSize && b.lowMem {
maxSize = int(windowSize)
}
if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize { if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize {
if debug { if debug {
printf("compressed block too big: csize:%d block: %+v\n", uint64(cSize), b) printf("compressed block too big: csize:%d block: %+v\n", uint64(cSize), b)
@ -160,8 +168,8 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
b.dataStorage = make([]byte, 0, maxBlockSize) b.dataStorage = make([]byte, 0, maxBlockSize)
} }
} }
if cap(b.dst) <= maxBlockSize { if cap(b.dst) <= maxSize {
b.dst = make([]byte, 0, maxBlockSize+1) b.dst = make([]byte, 0, maxSize+1)
} }
var err error var err error
b.data, err = br.readBig(cSize, b.dataStorage) b.data, err = br.readBig(cSize, b.dataStorage)
@ -679,8 +687,11 @@ func (b *blockDec) decodeCompressed(hist *history) error {
println("initializing sequences:", err) println("initializing sequences:", err)
return err return err
} }
hbytes := hist.b
err = seqs.decode(nSeqs, br, hist.b) if len(hbytes) > hist.windowSize {
hbytes = hbytes[len(hbytes)-hist.windowSize:]
}
err = seqs.decode(nSeqs, br, hbytes)
if err != nil { if err != nil {
return err return err
} }

View File

@ -233,7 +233,11 @@ func (d *frameDec) reset(br byteBuffer) error {
return ErrWindowSizeTooSmall return ErrWindowSizeTooSmall
} }
d.history.windowSize = int(d.WindowSize) d.history.windowSize = int(d.WindowSize)
if d.o.lowMem && d.history.windowSize < maxBlockSize {
d.history.maxSize = d.history.windowSize * 2
} else {
d.history.maxSize = d.history.windowSize + maxBlockSize d.history.maxSize = d.history.windowSize + maxBlockSize
}
// history contains input - maybe we do something // history contains input - maybe we do something
d.rawInput = br d.rawInput = br
return nil return nil
@ -320,8 +324,8 @@ func (d *frameDec) checkCRC() error {
func (d *frameDec) initAsync() { func (d *frameDec) initAsync() {
if !d.o.lowMem && !d.SingleSegment { if !d.o.lowMem && !d.SingleSegment {
// set max extra size history to 20MB. // set max extra size history to 10MB.
d.history.maxSize = d.history.windowSize + maxBlockSize*10 d.history.maxSize = d.history.windowSize + maxBlockSize*5
} }
// re-alloc if more than one extra block size. // re-alloc if more than one extra block size.
if d.o.lowMem && cap(d.history.b) > d.history.maxSize+maxBlockSize { if d.o.lowMem && cap(d.history.b) > d.history.maxSize+maxBlockSize {

View File

@ -69,6 +69,7 @@ type bState struct {
trimSpace bool trimSpace bool
toComplete bool toComplete bool
completeFlushed bool completeFlushed bool
ignoreComplete bool
noPop bool noPop bool
aDecorators []decor.Decorator aDecorators []decor.Decorator
pDecorators []decor.Decorator pDecorators []decor.Decorator
@ -170,17 +171,18 @@ func (b *Bar) TraverseDecorators(cb func(decor.Decorator)) {
} }
// SetTotal sets total dynamically. // SetTotal sets total dynamically.
// If total is less or equal to zero it takes progress' current value. // If total is less than or equal to zero it takes progress' current value.
// If complete is true, complete event will be triggered. // A complete flag enables or disables complete event on `current >= total`.
func (b *Bar) SetTotal(total int64, complete bool) { func (b *Bar) SetTotal(total int64, complete bool) {
select { select {
case b.operateState <- func(s *bState) { case b.operateState <- func(s *bState) {
s.ignoreComplete = !complete
if total <= 0 { if total <= 0 {
s.total = s.current s.total = s.current
} else { } else {
s.total = total s.total = total
} }
if complete && !s.toComplete { if !s.ignoreComplete && !s.toComplete {
s.current = s.total s.current = s.total
s.toComplete = true s.toComplete = true
go b.refreshTillShutdown() go b.refreshTillShutdown()
@ -197,7 +199,7 @@ func (b *Bar) SetCurrent(current int64) {
s.iterated = true s.iterated = true
s.lastN = current - s.current s.lastN = current - s.current
s.current = current s.current = current
if s.total > 0 && s.current >= s.total { if !s.ignoreComplete && s.current >= s.total {
s.current = s.total s.current = s.total
s.toComplete = true s.toComplete = true
go b.refreshTillShutdown() go b.refreshTillShutdown()
@ -224,7 +226,7 @@ func (b *Bar) IncrInt64(n int64) {
s.iterated = true s.iterated = true
s.lastN = n s.lastN = n
s.current += n s.current += n
if s.total > 0 && s.current >= s.total { if !s.ignoreComplete && s.current >= s.total {
s.current = s.total s.current = s.total
s.toComplete = true s.toComplete = true
go b.refreshTillShutdown() go b.refreshTillShutdown()

View File

@ -76,7 +76,7 @@ func (s *barFiller) SetReverse(reverse bool) {
s.flush = reverseFlush s.flush = reverseFlush
} else { } else {
s.tip = s.format[rTip] s.tip = s.format[rTip]
s.flush = normalFlush s.flush = regularFlush
} }
s.reverse = reverse s.reverse = reverse
} }
@ -125,7 +125,7 @@ func (s *barFiller) Fill(w io.Writer, width int, stat *decor.Statistics) {
s.flush(w, bb) s.flush(w, bb)
} }
func normalFlush(w io.Writer, bb [][]byte) { func regularFlush(w io.Writer, bb [][]byte) {
for i := 0; i < len(bb); i++ { for i := 0; i < len(bb); i++ {
w.Write(bb[i]) w.Write(bb[i])
} }

View File

@ -3,8 +3,8 @@ module github.com/vbauerster/mpb/v5
require ( require (
github.com/VividCortex/ewma v1.1.1 github.com/VividCortex/ewma v1.1.1
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f // indirect
) )
go 1.14 go 1.14

View File

@ -3,11 +3,11 @@ github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmx
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -7,6 +7,9 @@ func Percentage(total, current int64, width int) float64 {
if total <= 0 { if total <= 0 {
return 0 return 0
} }
if current >= total {
return float64(width)
}
return float64(int64(width)*current) / float64(total) return float64(int64(width)*current) / float64(total)
} }

View File

@ -113,6 +113,7 @@ func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
} }
const ( const (
keyCtrlC = 3
keyCtrlD = 4 keyCtrlD = 4
keyCtrlU = 21 keyCtrlU = 21
keyEnter = '\r' keyEnter = '\r'
@ -151,8 +152,12 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
switch b[0] { switch b[0] {
case 1: // ^A case 1: // ^A
return keyHome, b[1:] return keyHome, b[1:]
case 2: // ^B
return keyLeft, b[1:]
case 5: // ^E case 5: // ^E
return keyEnd, b[1:] return keyEnd, b[1:]
case 6: // ^F
return keyRight, b[1:]
case 8: // ^H case 8: // ^H
return keyBackspace, b[1:] return keyBackspace, b[1:]
case 11: // ^K case 11: // ^K
@ -738,6 +743,9 @@ func (t *Terminal) readLine() (line string, err error) {
return "", io.EOF return "", io.EOF
} }
} }
if key == keyCtrlC {
return "", io.EOF
}
if key == keyPasteStart { if key == keyPasteStart {
t.pasteActive = true t.pasteActive = true
if len(t.line) == 0 { if len(t.line) == 0 {

View File

@ -89,7 +89,7 @@ constants.
Adding new syscall numbers is mostly done by running the build on a sufficiently Adding new syscall numbers is mostly done by running the build on a sufficiently
new installation of the target OS (or updating the source checkouts for the new installation of the target OS (or updating the source checkouts for the
new build system). However, depending on the OS, you make need to update the new build system). However, depending on the OS, you may need to update the
parsing in mksysnum. parsing in mksysnum.
### mksyscall.go ### mksyscall.go
@ -163,7 +163,7 @@ The merge is performed in the following steps:
## Generated files ## Generated files
### `zerror_${GOOS}_${GOARCH}.go` ### `zerrors_${GOOS}_${GOARCH}.go`
A file containing all of the system's generated error numbers, error strings, A file containing all of the system's generated error numbers, error strings,
signal numbers, and constants. Generated by `mkerrors.sh` (see above). signal numbers, and constants. Generated by `mkerrors.sh` (see above).

View File

@ -486,6 +486,7 @@ ccflags="$@"
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
$2 ~ /^MODULE_INIT_/ || $2 ~ /^MODULE_INIT_/ ||
$2 !~ "NLA_TYPE_MASK" && $2 !~ "NLA_TYPE_MASK" &&
$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
$2 ~ /^SIOC/ || $2 ~ /^SIOC/ ||
$2 ~ /^TIOC/ || $2 ~ /^TIOC/ ||

View File

@ -216,6 +216,7 @@ const (
BPF_F_RDONLY = 0x8 BPF_F_RDONLY = 0x8
BPF_F_RDONLY_PROG = 0x80 BPF_F_RDONLY_PROG = 0x80
BPF_F_RECOMPUTE_CSUM = 0x1 BPF_F_RECOMPUTE_CSUM = 0x1
BPF_F_REPLACE = 0x4
BPF_F_REUSE_STACKID = 0x400 BPF_F_REUSE_STACKID = 0x400
BPF_F_SEQ_NUMBER = 0x8 BPF_F_SEQ_NUMBER = 0x8
BPF_F_SKIP_FIELD_MASK = 0xff BPF_F_SKIP_FIELD_MASK = 0xff
@ -389,6 +390,7 @@ const (
CLONE_NEWNET = 0x40000000 CLONE_NEWNET = 0x40000000
CLONE_NEWNS = 0x20000 CLONE_NEWNS = 0x20000
CLONE_NEWPID = 0x20000000 CLONE_NEWPID = 0x20000000
CLONE_NEWTIME = 0x80
CLONE_NEWUSER = 0x10000000 CLONE_NEWUSER = 0x10000000
CLONE_NEWUTS = 0x4000000 CLONE_NEWUTS = 0x4000000
CLONE_PARENT = 0x8000 CLONE_PARENT = 0x8000
@ -737,6 +739,7 @@ const (
GENL_NAMSIZ = 0x10 GENL_NAMSIZ = 0x10
GENL_START_ALLOC = 0x13 GENL_START_ALLOC = 0x13
GENL_UNS_ADMIN_PERM = 0x10 GENL_UNS_ADMIN_PERM = 0x10
GRND_INSECURE = 0x4
GRND_NONBLOCK = 0x1 GRND_NONBLOCK = 0x1
GRND_RANDOM = 0x2 GRND_RANDOM = 0x2
HDIO_DRIVE_CMD = 0x31f HDIO_DRIVE_CMD = 0x31f
@ -1487,6 +1490,7 @@ const (
PR_GET_FPEMU = 0x9 PR_GET_FPEMU = 0x9
PR_GET_FPEXC = 0xb PR_GET_FPEXC = 0xb
PR_GET_FP_MODE = 0x2e PR_GET_FP_MODE = 0x2e
PR_GET_IO_FLUSHER = 0x3a
PR_GET_KEEPCAPS = 0x7 PR_GET_KEEPCAPS = 0x7
PR_GET_NAME = 0x10 PR_GET_NAME = 0x10
PR_GET_NO_NEW_PRIVS = 0x27 PR_GET_NO_NEW_PRIVS = 0x27
@ -1522,6 +1526,7 @@ const (
PR_SET_FPEMU = 0xa PR_SET_FPEMU = 0xa
PR_SET_FPEXC = 0xc PR_SET_FPEXC = 0xc
PR_SET_FP_MODE = 0x2d PR_SET_FP_MODE = 0x2d
PR_SET_IO_FLUSHER = 0x39
PR_SET_KEEPCAPS = 0x8 PR_SET_KEEPCAPS = 0x8
PR_SET_MM = 0x23 PR_SET_MM = 0x23
PR_SET_MM_ARG_END = 0x9 PR_SET_MM_ARG_END = 0x9
@ -1750,12 +1755,15 @@ const (
RTM_DELRULE = 0x21 RTM_DELRULE = 0x21
RTM_DELTCLASS = 0x29 RTM_DELTCLASS = 0x29
RTM_DELTFILTER = 0x2d RTM_DELTFILTER = 0x2d
RTM_DELVLAN = 0x71
RTM_F_CLONED = 0x200 RTM_F_CLONED = 0x200
RTM_F_EQUALIZE = 0x400 RTM_F_EQUALIZE = 0x400
RTM_F_FIB_MATCH = 0x2000 RTM_F_FIB_MATCH = 0x2000
RTM_F_LOOKUP_TABLE = 0x1000 RTM_F_LOOKUP_TABLE = 0x1000
RTM_F_NOTIFY = 0x100 RTM_F_NOTIFY = 0x100
RTM_F_OFFLOAD = 0x4000
RTM_F_PREFIX = 0x800 RTM_F_PREFIX = 0x800
RTM_F_TRAP = 0x8000
RTM_GETACTION = 0x32 RTM_GETACTION = 0x32
RTM_GETADDR = 0x16 RTM_GETADDR = 0x16
RTM_GETADDRLABEL = 0x4a RTM_GETADDRLABEL = 0x4a
@ -1777,7 +1785,8 @@ const (
RTM_GETSTATS = 0x5e RTM_GETSTATS = 0x5e
RTM_GETTCLASS = 0x2a RTM_GETTCLASS = 0x2a
RTM_GETTFILTER = 0x2e RTM_GETTFILTER = 0x2e
RTM_MAX = 0x6f RTM_GETVLAN = 0x72
RTM_MAX = 0x73
RTM_NEWACTION = 0x30 RTM_NEWACTION = 0x30
RTM_NEWADDR = 0x14 RTM_NEWADDR = 0x14
RTM_NEWADDRLABEL = 0x48 RTM_NEWADDRLABEL = 0x48
@ -1792,6 +1801,7 @@ const (
RTM_NEWNETCONF = 0x50 RTM_NEWNETCONF = 0x50
RTM_NEWNEXTHOP = 0x68 RTM_NEWNEXTHOP = 0x68
RTM_NEWNSID = 0x58 RTM_NEWNSID = 0x58
RTM_NEWNVLAN = 0x70
RTM_NEWPREFIX = 0x34 RTM_NEWPREFIX = 0x34
RTM_NEWQDISC = 0x24 RTM_NEWQDISC = 0x24
RTM_NEWROUTE = 0x18 RTM_NEWROUTE = 0x18
@ -1799,8 +1809,8 @@ const (
RTM_NEWSTATS = 0x5c RTM_NEWSTATS = 0x5c
RTM_NEWTCLASS = 0x28 RTM_NEWTCLASS = 0x28
RTM_NEWTFILTER = 0x2c RTM_NEWTFILTER = 0x2c
RTM_NR_FAMILIES = 0x18 RTM_NR_FAMILIES = 0x19
RTM_NR_MSGTYPES = 0x60 RTM_NR_MSGTYPES = 0x64
RTM_SETDCB = 0x4f RTM_SETDCB = 0x4f
RTM_SETLINK = 0x13 RTM_SETLINK = 0x13
RTM_SETNEIGHTBL = 0x43 RTM_SETNEIGHTBL = 0x43
@ -2090,7 +2100,7 @@ const (
TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_NAME = "TASKSTATS"
TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_GENL_VERSION = 0x1
TASKSTATS_TYPE_MAX = 0x6 TASKSTATS_TYPE_MAX = 0x6
TASKSTATS_VERSION = 0x9 TASKSTATS_VERSION = 0xa
TCIFLUSH = 0x0 TCIFLUSH = 0x0
TCIOFF = 0x2 TCIOFF = 0x2
TCIOFLUSH = 0x2 TCIOFLUSH = 0x2
@ -2271,7 +2281,7 @@ const (
VMADDR_CID_ANY = 0xffffffff VMADDR_CID_ANY = 0xffffffff
VMADDR_CID_HOST = 0x2 VMADDR_CID_HOST = 0x2
VMADDR_CID_HYPERVISOR = 0x0 VMADDR_CID_HYPERVISOR = 0x0
VMADDR_CID_RESERVED = 0x1 VMADDR_CID_LOCAL = 0x1
VMADDR_PORT_ANY = 0xffffffff VMADDR_PORT_ANY = 0xffffffff
VM_SOCKETS_INVALID_VERSION = 0xffffffff VM_SOCKETS_INVALID_VERSION = 0xffffffff
VQUIT = 0x1 VQUIT = 0x1
@ -2398,6 +2408,7 @@ const (
XENFS_SUPER_MAGIC = 0xabba1974 XENFS_SUPER_MAGIC = 0xabba1974
XFS_SUPER_MAGIC = 0x58465342 XFS_SUPER_MAGIC = 0x58465342
Z3FOLD_MAGIC = 0x33 Z3FOLD_MAGIC = 0x33
ZONEFS_MAGIC = 0x5a4f4653
ZSMALLOC_MAGIC = 0x58295829 ZSMALLOC_MAGIC = 0x58295829
) )

View File

@ -431,4 +431,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -353,4 +353,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -395,4 +395,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -298,4 +298,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -416,4 +416,6 @@ const (
SYS_FSPICK = 4433 SYS_FSPICK = 4433
SYS_PIDFD_OPEN = 4434 SYS_PIDFD_OPEN = 4434
SYS_CLONE3 = 4435 SYS_CLONE3 = 4435
SYS_OPENAT2 = 4437
SYS_PIDFD_GETFD = 4438
) )

View File

@ -346,4 +346,6 @@ const (
SYS_FSPICK = 5433 SYS_FSPICK = 5433
SYS_PIDFD_OPEN = 5434 SYS_PIDFD_OPEN = 5434
SYS_CLONE3 = 5435 SYS_CLONE3 = 5435
SYS_OPENAT2 = 5437
SYS_PIDFD_GETFD = 5438
) )

View File

@ -346,4 +346,6 @@ const (
SYS_FSPICK = 5433 SYS_FSPICK = 5433
SYS_PIDFD_OPEN = 5434 SYS_PIDFD_OPEN = 5434
SYS_CLONE3 = 5435 SYS_CLONE3 = 5435
SYS_OPENAT2 = 5437
SYS_PIDFD_GETFD = 5438
) )

View File

@ -416,4 +416,6 @@ const (
SYS_FSPICK = 4433 SYS_FSPICK = 4433
SYS_PIDFD_OPEN = 4434 SYS_PIDFD_OPEN = 4434
SYS_CLONE3 = 4435 SYS_CLONE3 = 4435
SYS_OPENAT2 = 4437
SYS_PIDFD_GETFD = 4438
) )

View File

@ -395,4 +395,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -395,4 +395,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -297,4 +297,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -360,4 +360,6 @@ const (
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435 SYS_CLONE3 = 435
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -374,4 +374,6 @@ const (
SYS_FSMOUNT = 432 SYS_FSMOUNT = 432
SYS_FSPICK = 433 SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434 SYS_PIDFD_OPEN = 434
SYS_OPENAT2 = 437
SYS_PIDFD_GETFD = 438
) )

View File

@ -114,7 +114,8 @@ type FscryptKeySpecifier struct {
type FscryptAddKeyArg struct { type FscryptAddKeyArg struct {
Key_spec FscryptKeySpecifier Key_spec FscryptKeySpecifier
Raw_size uint32 Raw_size uint32
_ [9]uint32 Key_id uint32
_ [8]uint32
} }
type FscryptRemoveKeyArg struct { type FscryptRemoveKeyArg struct {
@ -479,7 +480,7 @@ const (
IFLA_NEW_IFINDEX = 0x31 IFLA_NEW_IFINDEX = 0x31
IFLA_MIN_MTU = 0x32 IFLA_MIN_MTU = 0x32
IFLA_MAX_MTU = 0x33 IFLA_MAX_MTU = 0x33
IFLA_MAX = 0x35 IFLA_MAX = 0x36
IFLA_INFO_KIND = 0x1 IFLA_INFO_KIND = 0x1
IFLA_INFO_DATA = 0x2 IFLA_INFO_DATA = 0x2
IFLA_INFO_XSTATS = 0x3 IFLA_INFO_XSTATS = 0x3
@ -2308,3 +2309,32 @@ type FsverityEnableArg struct {
Sig_ptr uint64 Sig_ptr uint64
_ [11]uint64 _ [11]uint64
} }
type Nhmsg struct {
Family uint8
Scope uint8
Protocol uint8
Resvd uint8
Flags uint32
}
type NexthopGrp struct {
Id uint32
Weight uint8
Resvd1 uint8
Resvd2 uint16
}
const (
NHA_UNSPEC = 0x0
NHA_ID = 0x1
NHA_GROUP = 0x2
NHA_GROUP_TYPE = 0x3
NHA_BLACKHOLE = 0x4
NHA_OIF = 0x5
NHA_GATEWAY = 0x6
NHA_ENCAP_TYPE = 0x7
NHA_ENCAP = 0x8
NHA_GROUPS = 0x9
NHA_MASTER = 0xa
)

View File

@ -287,6 +287,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint32 type cpuMask uint32

View File

@ -298,6 +298,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -276,6 +276,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint32 type cpuMask uint32

View File

@ -277,6 +277,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -281,6 +281,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint32 type cpuMask uint32

View File

@ -280,6 +280,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -280,6 +280,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -281,6 +281,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint32 type cpuMask uint32

View File

@ -287,6 +287,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -287,6 +287,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -305,6 +305,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -300,6 +300,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

View File

@ -282,6 +282,7 @@ type Taskstats struct {
Freepages_delay_total uint64 Freepages_delay_total uint64
Thrashing_count uint64 Thrashing_count uint64
Thrashing_delay_total uint64 Thrashing_delay_total uint64
Ac_btime64 uint64
} }
type cpuMask uint64 type cpuMask uint64

13
vendor/modules.txt vendored
View File

@ -36,7 +36,7 @@ github.com/containerd/cgroups/stats/v1
github.com/containerd/containerd/errdefs github.com/containerd/containerd/errdefs
github.com/containerd/containerd/log github.com/containerd/containerd/log
github.com/containerd/containerd/platforms github.com/containerd/containerd/platforms
# github.com/containers/image/v5 v5.4.3 # github.com/containers/image/v5 v5.4.4-0.20200504143706-d52a99c5329e
github.com/containers/image/v5/copy github.com/containers/image/v5/copy
github.com/containers/image/v5/directory github.com/containers/image/v5/directory
github.com/containers/image/v5/directory/explicitfilepath github.com/containers/image/v5/directory/explicitfilepath
@ -51,6 +51,7 @@ github.com/containers/image/v5/internal/iolimits
github.com/containers/image/v5/internal/pkg/keyctl github.com/containers/image/v5/internal/pkg/keyctl
github.com/containers/image/v5/internal/pkg/platform github.com/containers/image/v5/internal/pkg/platform
github.com/containers/image/v5/internal/tmpdir github.com/containers/image/v5/internal/tmpdir
github.com/containers/image/v5/internal/uploadreader
github.com/containers/image/v5/manifest github.com/containers/image/v5/manifest
github.com/containers/image/v5/oci/archive github.com/containers/image/v5/oci/archive
github.com/containers/image/v5/oci/internal github.com/containers/image/v5/oci/internal
@ -89,7 +90,7 @@ github.com/containers/ocicrypt/keywrap/pgp
github.com/containers/ocicrypt/keywrap/pkcs7 github.com/containers/ocicrypt/keywrap/pkcs7
github.com/containers/ocicrypt/spec github.com/containers/ocicrypt/spec
github.com/containers/ocicrypt/utils github.com/containers/ocicrypt/utils
# github.com/containers/storage v1.19.0 # github.com/containers/storage v1.19.1
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs github.com/containers/storage/drivers/aufs
@ -203,7 +204,7 @@ github.com/hashicorp/golang-lru/simplelru
github.com/imdario/mergo github.com/imdario/mergo
# github.com/inconshreveable/mousetrap v1.0.0 # github.com/inconshreveable/mousetrap v1.0.0
github.com/inconshreveable/mousetrap github.com/inconshreveable/mousetrap
# github.com/klauspost/compress v1.10.4 # github.com/klauspost/compress v1.10.5
github.com/klauspost/compress/flate github.com/klauspost/compress/flate
github.com/klauspost/compress/fse github.com/klauspost/compress/fse
github.com/klauspost/compress/huff0 github.com/klauspost/compress/huff0
@ -291,7 +292,7 @@ github.com/ulikunitz/xz/lzma
github.com/vbatts/tar-split/archive/tar github.com/vbatts/tar-split/archive/tar
github.com/vbatts/tar-split/tar/asm github.com/vbatts/tar-split/tar/asm
github.com/vbatts/tar-split/tar/storage github.com/vbatts/tar-split/tar/storage
# github.com/vbauerster/mpb/v5 v5.0.3 # github.com/vbauerster/mpb/v5 v5.0.4
github.com/vbauerster/mpb/v5 github.com/vbauerster/mpb/v5
github.com/vbauerster/mpb/v5/cwriter github.com/vbauerster/mpb/v5/cwriter
github.com/vbauerster/mpb/v5/decor github.com/vbauerster/mpb/v5/decor
@ -312,7 +313,7 @@ go.opencensus.io/trace/internal
go.opencensus.io/trace/tracestate go.opencensus.io/trace/tracestate
# go4.org v0.0.0-20190218023631-ce4c26f7be8e # go4.org v0.0.0-20190218023631-ce4c26f7be8e
go4.org/errorutil go4.org/errorutil
# golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 # golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
golang.org/x/crypto/cast5 golang.org/x/crypto/cast5
golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519
golang.org/x/crypto/ed25519/internal/edwards25519 golang.org/x/crypto/ed25519/internal/edwards25519
@ -334,7 +335,7 @@ golang.org/x/net/internal/socks
golang.org/x/net/proxy golang.org/x/net/proxy
# golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a # golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
golang.org/x/sync/semaphore golang.org/x/sync/semaphore
# golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 # golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f
golang.org/x/sys/unix golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
# golang.org/x/text v0.3.2 # golang.org/x/text v0.3.2