mirror of https://github.com/docker/buildx.git
vendor: update buildkit to v0.16.0-rc1
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
parent
e58a1d35d1
commit
7bea00f3dd
13
go.mod
13
go.mod
|
@ -13,12 +13,12 @@ require (
|
||||||
github.com/containerd/errdefs v0.1.0
|
github.com/containerd/errdefs v0.1.0
|
||||||
github.com/containerd/log v0.1.0
|
github.com/containerd/log v0.1.0
|
||||||
github.com/containerd/platforms v0.2.1
|
github.com/containerd/platforms v0.2.1
|
||||||
github.com/containerd/typeurl/v2 v2.1.1
|
github.com/containerd/typeurl/v2 v2.2.0
|
||||||
github.com/creack/pty v1.1.21
|
github.com/creack/pty v1.1.21
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli v27.1.1+incompatible
|
github.com/docker/cli v27.2.0+incompatible
|
||||||
github.com/docker/cli-docs-tool v0.8.0
|
github.com/docker/cli-docs-tool v0.8.0
|
||||||
github.com/docker/docker v27.1.1+incompatible
|
github.com/docker/docker v27.2.0+incompatible
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/gofrs/flock v0.12.1
|
github.com/gofrs/flock v0.12.1
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
|
@ -29,9 +29,9 @@ require (
|
||||||
github.com/hashicorp/hcl/v2 v2.20.1
|
github.com/hashicorp/hcl/v2 v2.20.1
|
||||||
github.com/in-toto/in-toto-golang v0.5.0
|
github.com/in-toto/in-toto-golang v0.5.0
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||||
github.com/moby/buildkit v0.15.1-0.20240810140024-664c2b469f19
|
github.com/moby/buildkit v0.16.0-rc1
|
||||||
github.com/moby/sys/mountinfo v0.7.1
|
github.com/moby/sys/mountinfo v0.7.2
|
||||||
github.com/moby/sys/signal v0.7.0
|
github.com/moby/sys/signal v0.7.1
|
||||||
github.com/morikuni/aec v1.0.0
|
github.com/morikuni/aec v1.0.0
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0
|
github.com/opencontainers/image-spec v1.1.0
|
||||||
|
@ -129,6 +129,7 @@ require (
|
||||||
github.com/moby/spdystream v0.2.0 // indirect
|
github.com/moby/spdystream v0.2.0 // indirect
|
||||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||||
github.com/moby/sys/user v0.3.0 // indirect
|
github.com/moby/sys/user v0.3.0 // indirect
|
||||||
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
|
28
go.sum
28
go.sum
|
@ -111,8 +111,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
|
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
|
||||||
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
|
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
|
||||||
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||||
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
|
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso=
|
||||||
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
@ -124,15 +124,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE=
|
github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM=
|
||||||
github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU=
|
github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU=
|
||||||
github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk=
|
github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY=
|
github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4=
|
||||||
github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
|
||||||
|
@ -307,8 +307,8 @@ github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/z
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/moby/buildkit v0.15.1-0.20240810140024-664c2b469f19 h1:0T8RSjj+Li33TiaWxzxUPJ15kGSuOwSjkiL4H86v/Tc=
|
github.com/moby/buildkit v0.16.0-rc1 h1:G6KBYr6T4B1ylpinYIjcNLcVkPUkuddw3daqaM9yg9A=
|
||||||
github.com/moby/buildkit v0.15.1-0.20240810140024-664c2b469f19/go.mod h1:uJOz8k3rWgVrcMPArjtz85jrwOWD4MaLBzk64mCe1yY=
|
github.com/moby/buildkit v0.16.0-rc1/go.mod h1:WLr3pMBXsAoSuZIGdGww1JPz8S8Qp+OTf0dlrPnzbDg=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||||
|
@ -317,14 +317,16 @@ github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkV
|
||||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
|
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||||
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
|
||||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=
|
||||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||||
|
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||||
|
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
@ -551,7 +553,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -597,7 +598,6 @@ google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
|
||||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package userns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
inUserNS bool
|
|
||||||
nsOnce sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
// RunningInUserNS detects whether we are currently running in a user namespace.
|
|
||||||
// Originally copied from github.com/lxc/lxd/shared/util.go
|
|
||||||
func RunningInUserNS() bool {
|
|
||||||
nsOnce.Do(func() {
|
|
||||||
file, err := os.Open("/proc/self/uid_map")
|
|
||||||
if err != nil {
|
|
||||||
// This kernel-provided file only exists if user namespaces are supported
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
buf := bufio.NewReader(file)
|
|
||||||
l, _, err := buf.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
line := string(l)
|
|
||||||
var a, b, c int64
|
|
||||||
fmt.Sscanf(line, "%d %d %d", &a, &b, &c)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We assume we are in the initial user namespace if we have a full
|
|
||||||
* range - 4294967295 uids starting at uid 0.
|
|
||||||
*/
|
|
||||||
if a == 0 && b == 0 && c == 4294967295 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
inUserNS = true
|
|
||||||
})
|
|
||||||
return inUserNS
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
//go:build !linux
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package userns
|
|
||||||
|
|
||||||
// RunningInUserNS is a stub for non-Linux systems
|
|
||||||
// Always returns false
|
|
||||||
func RunningInUserNS() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/typeurl)](https://pkg.go.dev/github.com/containerd/typeurl)
|
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/typeurl)](https://pkg.go.dev/github.com/containerd/typeurl)
|
||||||
[![Build Status](https://github.com/containerd/typeurl/workflows/CI/badge.svg)](https://github.com/containerd/typeurl/actions?query=workflow%3ACI)
|
[![Build Status](https://github.com/containerd/typeurl/workflows/CI/badge.svg)](https://github.com/containerd/typeurl/actions?query=workflow%3ACI)
|
||||||
[![codecov](https://codecov.io/gh/containerd/typeurl/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/typeurl)
|
[![codecov](https://codecov.io/gh/containerd/typeurl/branch/main/graph/badge.svg)](https://codecov.io/gh/containerd/typeurl)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/typeurl)](https://goreportcard.com/report/github.com/containerd/typeurl)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/typeurl)](https://goreportcard.com/report/github.com/containerd/typeurl)
|
||||||
|
|
||||||
A Go package for managing the registration, marshaling, and unmarshaling of encoded types.
|
A Go package for managing the registration, marshaling, and unmarshaling of encoded types.
|
||||||
|
@ -13,8 +13,8 @@ This package helps when types are sent over a ttrpc/GRPC API and marshaled as a
|
||||||
|
|
||||||
**typeurl** is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
**typeurl** is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||||
As a containerd sub-project, you will find the:
|
As a containerd sub-project, you will find the:
|
||||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
|
||||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||||
|
|
||||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
gogoproto "github.com/gogo/protobuf/proto"
|
gogoproto "github.com/gogo/protobuf/proto"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/reflect/protoregistry"
|
"google.golang.org/protobuf/reflect/protoregistry"
|
||||||
|
"google.golang.org/protobuf/types/known/anypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -122,6 +123,9 @@ func TypeURL(v interface{}) (string, error) {
|
||||||
|
|
||||||
// Is returns true if the type of the Any is the same as v.
|
// Is returns true if the type of the Any is the same as v.
|
||||||
func Is(any Any, v interface{}) bool {
|
func Is(any Any, v interface{}) bool {
|
||||||
|
if any == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
// call to check that v is a pointer
|
// call to check that v is a pointer
|
||||||
tryDereference(v)
|
tryDereference(v)
|
||||||
url, err := TypeURL(v)
|
url, err := TypeURL(v)
|
||||||
|
@ -193,6 +197,31 @@ func UnmarshalToByTypeURL(typeURL string, value []byte, out interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalProto converts typeurl.Any to google.golang.org/protobuf/types/known/anypb.Any.
|
||||||
|
func MarshalProto(from Any) *anypb.Any {
|
||||||
|
if from == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if pbany, ok := from.(*anypb.Any); ok {
|
||||||
|
return pbany
|
||||||
|
}
|
||||||
|
|
||||||
|
return &anypb.Any{
|
||||||
|
TypeUrl: from.GetTypeUrl(),
|
||||||
|
Value: from.GetValue(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalAnyToProto converts an arbitrary interface to google.golang.org/protobuf/types/known/anypb.Any.
|
||||||
|
func MarshalAnyToProto(from interface{}) (*anypb.Any, error) {
|
||||||
|
anyType, err := MarshalAny(from)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return MarshalProto(anyType), nil
|
||||||
|
}
|
||||||
|
|
||||||
func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
|
func unmarshal(typeURL string, value []byte, v interface{}) (interface{}, error) {
|
||||||
t, err := getTypeByUrl(typeURL)
|
t, err := getTypeByUrl(typeURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -95,6 +95,9 @@ func (pl *PluginServer) Addr() net.Addr {
|
||||||
//
|
//
|
||||||
// The error value is that of the underlying [net.Listner.Close] call.
|
// The error value is that of the underlying [net.Listner.Close] call.
|
||||||
func (pl *PluginServer) Close() error {
|
func (pl *PluginServer) Close() error {
|
||||||
|
if pl == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
logrus.Trace("Closing plugin server")
|
logrus.Trace("Closing plugin server")
|
||||||
// Close connections first to ensure the connections get io.EOF instead
|
// Close connections first to ensure the connections get io.EOF instead
|
||||||
// of a connection reset.
|
// of a connection reset.
|
||||||
|
|
|
@ -5,6 +5,7 @@ package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -331,7 +332,8 @@ func DisplayablePorts(ports []types.Port) string {
|
||||||
portKey := port.Type
|
portKey := port.Type
|
||||||
if port.IP != "" {
|
if port.IP != "" {
|
||||||
if port.PublicPort != current {
|
if port.PublicPort != current {
|
||||||
hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type))
|
hAddrPort := net.JoinHostPort(port.IP, strconv.Itoa(int(port.PublicPort)))
|
||||||
|
hostMappings = append(hostMappings, fmt.Sprintf("%s->%d/%s", hAddrPort, port.PrivatePort, port.Type))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
portKey = port.IP + "/" + port.Type
|
portKey = port.IP + "/" + port.Type
|
||||||
|
|
|
@ -41,7 +41,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ConfigureAuth(ctx, cli, "", "", &authConfig, isDefaultRegistry)
|
authConfig, err = PromptUserForCredentials(ctx, cli, "", "", authConfig.Username, indexServer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -86,8 +86,32 @@ func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serve
|
||||||
return registrytypes.AuthConfig(authconfig), nil
|
return registrytypes.AuthConfig(authconfig), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigureAuth handles prompting of user's username and password if needed
|
// ConfigureAuth handles prompting of user's username and password if needed.
|
||||||
func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, authconfig *registrytypes.AuthConfig, isDefaultRegistry bool) error {
|
// Deprecated: use PromptUserForCredentials instead.
|
||||||
|
func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, authConfig *registrytypes.AuthConfig, _ bool) error {
|
||||||
|
defaultUsername := authConfig.Username
|
||||||
|
serverAddress := authConfig.ServerAddress
|
||||||
|
|
||||||
|
newAuthConfig, err := PromptUserForCredentials(ctx, cli, flUser, flPassword, defaultUsername, serverAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
authConfig.Username = newAuthConfig.Username
|
||||||
|
authConfig.Password = newAuthConfig.Password
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PromptUserForCredentials handles the CLI prompt for the user to input
|
||||||
|
// credentials.
|
||||||
|
// If argUser is not empty, then the user is only prompted for their password.
|
||||||
|
// If argPassword is not empty, then the user is only prompted for their username
|
||||||
|
// If neither argUser nor argPassword are empty, then the user is not prompted and
|
||||||
|
// an AuthConfig is returned with those values.
|
||||||
|
// If defaultUsername is not empty, the username prompt includes that username
|
||||||
|
// and the user can hit enter without inputting a username to use that default
|
||||||
|
// username.
|
||||||
|
func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword, defaultUsername, serverAddress string) (authConfig registrytypes.AuthConfig, err error) {
|
||||||
// On Windows, force the use of the regular OS stdin stream.
|
// On Windows, force the use of the regular OS stdin stream.
|
||||||
//
|
//
|
||||||
// See:
|
// See:
|
||||||
|
@ -107,13 +131,14 @@ func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, auth
|
||||||
// Linux will hit this if you attempt `cat | docker login`, and Windows
|
// Linux will hit this if you attempt `cat | docker login`, and Windows
|
||||||
// will hit this if you attempt docker login from mintty where stdin
|
// will hit this if you attempt docker login from mintty where stdin
|
||||||
// is a pipe, not a character based console.
|
// is a pipe, not a character based console.
|
||||||
if flPassword == "" && !cli.In().IsTerminal() {
|
if argPassword == "" && !cli.In().IsTerminal() {
|
||||||
return errors.Errorf("Error: Cannot perform an interactive login from a non TTY device")
|
return authConfig, errors.Errorf("Error: Cannot perform an interactive login from a non TTY device")
|
||||||
}
|
}
|
||||||
|
|
||||||
authconfig.Username = strings.TrimSpace(authconfig.Username)
|
isDefaultRegistry := serverAddress == registry.IndexServer
|
||||||
|
defaultUsername = strings.TrimSpace(defaultUsername)
|
||||||
|
|
||||||
if flUser = strings.TrimSpace(flUser); flUser == "" {
|
if argUser = strings.TrimSpace(argUser); argUser == "" {
|
||||||
if isDefaultRegistry {
|
if isDefaultRegistry {
|
||||||
// if this is a default registry (docker hub), then display the following message.
|
// if this is a default registry (docker hub), then display the following message.
|
||||||
fmt.Fprintln(cli.Out(), "Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.")
|
fmt.Fprintln(cli.Out(), "Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.")
|
||||||
|
@ -124,44 +149,43 @@ func ConfigureAuth(ctx context.Context, cli Cli, flUser, flPassword string, auth
|
||||||
}
|
}
|
||||||
|
|
||||||
var prompt string
|
var prompt string
|
||||||
if authconfig.Username == "" {
|
if defaultUsername == "" {
|
||||||
prompt = "Username: "
|
prompt = "Username: "
|
||||||
} else {
|
} else {
|
||||||
prompt = fmt.Sprintf("Username (%s): ", authconfig.Username)
|
prompt = fmt.Sprintf("Username (%s): ", defaultUsername)
|
||||||
}
|
}
|
||||||
var err error
|
argUser, err = PromptForInput(ctx, cli.In(), cli.Out(), prompt)
|
||||||
flUser, err = PromptForInput(ctx, cli.In(), cli.Out(), prompt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return authConfig, err
|
||||||
}
|
}
|
||||||
if flUser == "" {
|
if argUser == "" {
|
||||||
flUser = authconfig.Username
|
argUser = defaultUsername
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if flUser == "" {
|
if argUser == "" {
|
||||||
return errors.Errorf("Error: Non-null Username Required")
|
return authConfig, errors.Errorf("Error: Non-null Username Required")
|
||||||
}
|
}
|
||||||
if flPassword == "" {
|
if argPassword == "" {
|
||||||
restoreInput, err := DisableInputEcho(cli.In())
|
restoreInput, err := DisableInputEcho(cli.In())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return authConfig, err
|
||||||
}
|
}
|
||||||
defer restoreInput()
|
defer restoreInput()
|
||||||
|
|
||||||
flPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ")
|
argPassword, err = PromptForInput(ctx, cli.In(), cli.Out(), "Password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return authConfig, err
|
||||||
}
|
}
|
||||||
fmt.Fprint(cli.Out(), "\n")
|
fmt.Fprint(cli.Out(), "\n")
|
||||||
if flPassword == "" {
|
if argPassword == "" {
|
||||||
return errors.Errorf("Error: Password Required")
|
return authConfig, errors.Errorf("Error: Password Required")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
authconfig.Username = flUser
|
authConfig.Username = argUser
|
||||||
authconfig.Password = flPassword
|
authConfig.Password = argPassword
|
||||||
|
authConfig.ServerAddress = serverAddress
|
||||||
return nil
|
return authConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete
|
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete
|
||||||
|
|
|
@ -222,7 +222,7 @@ func ValidateOutputPath(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ValidateOutputPathFileMode(fileInfo.Mode()); err != nil {
|
if err := ValidateOutputPathFileMode(fileInfo.Mode()); err != nil {
|
||||||
return errors.Wrapf(err, fmt.Sprintf("invalid output path: %q must be a directory or a regular file", path))
|
return errors.Wrapf(err, "invalid output path: %q must be a directory or a regular file", path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -52,6 +52,7 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
|
||||||
args = append(args, "--host", "unix://"+sp.Path)
|
args = append(args, "--host", "unix://"+sp.Path)
|
||||||
}
|
}
|
||||||
sshFlags = addSSHTimeout(sshFlags)
|
sshFlags = addSSHTimeout(sshFlags)
|
||||||
|
sshFlags = disablePseudoTerminalAllocation(sshFlags)
|
||||||
args = append(args, "system", "dial-stdio")
|
args = append(args, "system", "dial-stdio")
|
||||||
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
|
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
|
||||||
},
|
},
|
||||||
|
@ -79,3 +80,14 @@ func addSSHTimeout(sshFlags []string) []string {
|
||||||
}
|
}
|
||||||
return sshFlags
|
return sshFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// disablePseudoTerminalAllocation disables pseudo-terminal allocation to
|
||||||
|
// prevent SSH from executing as a login shell
|
||||||
|
func disablePseudoTerminalAllocation(sshFlags []string) []string {
|
||||||
|
for _, flag := range sshFlags {
|
||||||
|
if flag == "-T" {
|
||||||
|
return sshFlags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return append(sshFlags, "-T")
|
||||||
|
}
|
||||||
|
|
|
@ -27,16 +27,16 @@ func NoArgs(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiresMinArgs returns an error if there is not at least min args
|
// RequiresMinArgs returns an error if there is not at least min args
|
||||||
func RequiresMinArgs(min int) cobra.PositionalArgs {
|
func RequiresMinArgs(minArgs int) cobra.PositionalArgs {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
if len(args) >= min {
|
if len(args) >= minArgs {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Errorf(
|
return errors.Errorf(
|
||||||
"%q requires at least %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
"%q requires at least %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
||||||
cmd.CommandPath(),
|
cmd.CommandPath(),
|
||||||
min,
|
minArgs,
|
||||||
pluralize("argument", min),
|
pluralize("argument", minArgs),
|
||||||
cmd.CommandPath(),
|
cmd.CommandPath(),
|
||||||
cmd.UseLine(),
|
cmd.UseLine(),
|
||||||
cmd.Short,
|
cmd.Short,
|
||||||
|
@ -45,16 +45,16 @@ func RequiresMinArgs(min int) cobra.PositionalArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiresMaxArgs returns an error if there is not at most max args
|
// RequiresMaxArgs returns an error if there is not at most max args
|
||||||
func RequiresMaxArgs(max int) cobra.PositionalArgs {
|
func RequiresMaxArgs(maxArgs int) cobra.PositionalArgs {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
if len(args) <= max {
|
if len(args) <= maxArgs {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Errorf(
|
return errors.Errorf(
|
||||||
"%q requires at most %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
"%q requires at most %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
||||||
cmd.CommandPath(),
|
cmd.CommandPath(),
|
||||||
max,
|
maxArgs,
|
||||||
pluralize("argument", max),
|
pluralize("argument", maxArgs),
|
||||||
cmd.CommandPath(),
|
cmd.CommandPath(),
|
||||||
cmd.UseLine(),
|
cmd.UseLine(),
|
||||||
cmd.Short,
|
cmd.Short,
|
||||||
|
@ -63,17 +63,17 @@ func RequiresMaxArgs(max int) cobra.PositionalArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiresRangeArgs returns an error if there is not at least min args and at most max args
|
// RequiresRangeArgs returns an error if there is not at least min args and at most max args
|
||||||
func RequiresRangeArgs(min int, max int) cobra.PositionalArgs {
|
func RequiresRangeArgs(minArgs int, maxArgs int) cobra.PositionalArgs {
|
||||||
return func(cmd *cobra.Command, args []string) error {
|
return func(cmd *cobra.Command, args []string) error {
|
||||||
if len(args) >= min && len(args) <= max {
|
if len(args) >= minArgs && len(args) <= maxArgs {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return errors.Errorf(
|
return errors.Errorf(
|
||||||
"%q requires at least %d and at most %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
"%q requires at least %d and at most %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s",
|
||||||
cmd.CommandPath(),
|
cmd.CommandPath(),
|
||||||
min,
|
minArgs,
|
||||||
max,
|
maxArgs,
|
||||||
pluralize("argument", max),
|
pluralize("argument", maxArgs),
|
||||||
cmd.CommandPath(),
|
cmd.CommandPath(),
|
||||||
cmd.UseLine(),
|
cmd.UseLine(),
|
||||||
cmd.Short,
|
cmd.Short,
|
||||||
|
|
|
@ -94,7 +94,7 @@ func (opt *ThrottledeviceOpt) String() string {
|
||||||
|
|
||||||
// GetList returns a slice of pointers to ThrottleDevices.
|
// GetList returns a slice of pointers to ThrottleDevices.
|
||||||
func (opt *ThrottledeviceOpt) GetList() []*blkiodev.ThrottleDevice {
|
func (opt *ThrottledeviceOpt) GetList() []*blkiodev.ThrottleDevice {
|
||||||
out := make([]*blkiodev.ThrottleDevice, 0, len(opt.values))
|
out := make([]*blkiodev.ThrottleDevice, len(opt.values))
|
||||||
copy(out, opt.values)
|
copy(out, opt.values)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
|
||||||
// Common constants for daemon and client.
|
// Common constants for daemon and client.
|
||||||
const (
|
const (
|
||||||
// DefaultVersion of the current REST API.
|
// DefaultVersion of the current REST API.
|
||||||
DefaultVersion = "1.46"
|
DefaultVersion = "1.47"
|
||||||
|
|
||||||
// MinSupportedAPIVersion is the minimum API version that can be supported
|
// MinSupportedAPIVersion is the minimum API version that can be supported
|
||||||
// by the API server, specified as "major.minor". Note that the daemon
|
// by the API server, specified as "major.minor". Note that the daemon
|
||||||
|
|
|
@ -19,10 +19,10 @@ produces:
|
||||||
consumes:
|
consumes:
|
||||||
- "application/json"
|
- "application/json"
|
||||||
- "text/plain"
|
- "text/plain"
|
||||||
basePath: "/v1.46"
|
basePath: "/v1.47"
|
||||||
info:
|
info:
|
||||||
title: "Docker Engine API"
|
title: "Docker Engine API"
|
||||||
version: "1.46"
|
version: "1.47"
|
||||||
x-logo:
|
x-logo:
|
||||||
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
|
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
|
||||||
description: |
|
description: |
|
||||||
|
@ -55,8 +55,8 @@ info:
|
||||||
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
|
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
|
||||||
is returned.
|
is returned.
|
||||||
|
|
||||||
If you omit the version-prefix, the current version of the API (v1.46) is used.
|
If you omit the version-prefix, the current version of the API (v1.47) is used.
|
||||||
For example, calling `/info` is the same as calling `/v1.46/info`. Using the
|
For example, calling `/info` is the same as calling `/v1.47/info`. Using the
|
||||||
API without a version-prefix is deprecated and will be removed in a future release.
|
API without a version-prefix is deprecated and will be removed in a future release.
|
||||||
|
|
||||||
Engine releases in the near future should support this version of the API,
|
Engine releases in the near future should support this version of the API,
|
||||||
|
@ -2265,6 +2265,19 @@ definitions:
|
||||||
x-nullable: false
|
x-nullable: false
|
||||||
type: "integer"
|
type: "integer"
|
||||||
example: 2
|
example: 2
|
||||||
|
Manifests:
|
||||||
|
description: |
|
||||||
|
Manifests is a list of manifests available in this image.
|
||||||
|
It provides a more detailed view of the platform-specific image manifests
|
||||||
|
or other image-attached data like build attestations.
|
||||||
|
|
||||||
|
WARNING: This is experimental and may change at any time without any backward
|
||||||
|
compatibility.
|
||||||
|
type: "array"
|
||||||
|
x-nullable: false
|
||||||
|
x-omitempty: true
|
||||||
|
items:
|
||||||
|
$ref: "#/definitions/ImageManifestSummary"
|
||||||
|
|
||||||
AuthConfig:
|
AuthConfig:
|
||||||
type: "object"
|
type: "object"
|
||||||
|
@ -5318,7 +5331,7 @@ definitions:
|
||||||
description: |
|
description: |
|
||||||
The default (and highest) API version that is supported by the daemon
|
The default (and highest) API version that is supported by the daemon
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "1.46"
|
example: "1.47"
|
||||||
MinAPIVersion:
|
MinAPIVersion:
|
||||||
description: |
|
description: |
|
||||||
The minimum API version that is supported by the daemon
|
The minimum API version that is supported by the daemon
|
||||||
|
@ -5334,7 +5347,7 @@ definitions:
|
||||||
The version Go used to compile the daemon, and the version of the Go
|
The version Go used to compile the daemon, and the version of the Go
|
||||||
runtime in use.
|
runtime in use.
|
||||||
type: "string"
|
type: "string"
|
||||||
example: "go1.21.12"
|
example: "go1.21.13"
|
||||||
Os:
|
Os:
|
||||||
description: |
|
description: |
|
||||||
The operating system that the daemon is running on ("linux" or "windows")
|
The operating system that the daemon is running on ("linux" or "windows")
|
||||||
|
@ -5830,13 +5843,13 @@ definitions:
|
||||||
- "/var/run/cdi"
|
- "/var/run/cdi"
|
||||||
Containerd:
|
Containerd:
|
||||||
$ref: "#/definitions/ContainerdInfo"
|
$ref: "#/definitions/ContainerdInfo"
|
||||||
x-nullable: true
|
|
||||||
|
|
||||||
ContainerdInfo:
|
ContainerdInfo:
|
||||||
description: |
|
description: |
|
||||||
Information for connecting to the containerd instance that is used by the daemon.
|
Information for connecting to the containerd instance that is used by the daemon.
|
||||||
This is included for debugging purposes only.
|
This is included for debugging purposes only.
|
||||||
type: "object"
|
type: "object"
|
||||||
|
x-nullable: true
|
||||||
properties:
|
properties:
|
||||||
Address:
|
Address:
|
||||||
description: "The address of the containerd socket."
|
description: "The address of the containerd socket."
|
||||||
|
@ -6644,6 +6657,120 @@ definitions:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: "string"
|
type: "string"
|
||||||
|
|
||||||
|
ImageManifestSummary:
|
||||||
|
x-go-name: "ManifestSummary"
|
||||||
|
description: |
|
||||||
|
ImageManifestSummary represents a summary of an image manifest.
|
||||||
|
type: "object"
|
||||||
|
required: ["ID", "Descriptor", "Available", "Size", "Kind"]
|
||||||
|
properties:
|
||||||
|
ID:
|
||||||
|
description: |
|
||||||
|
ID is the content-addressable ID of an image and is the same as the
|
||||||
|
digest of the image manifest.
|
||||||
|
type: "string"
|
||||||
|
example: "sha256:95869fbcf224d947ace8d61d0e931d49e31bb7fc67fffbbe9c3198c33aa8e93f"
|
||||||
|
Descriptor:
|
||||||
|
$ref: "#/definitions/OCIDescriptor"
|
||||||
|
Available:
|
||||||
|
description: Indicates whether all the child content (image config, layers) is fully available locally.
|
||||||
|
type: "boolean"
|
||||||
|
example: true
|
||||||
|
Size:
|
||||||
|
type: "object"
|
||||||
|
x-nullable: false
|
||||||
|
required: ["Content", "Total"]
|
||||||
|
properties:
|
||||||
|
Total:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
example: 8213251
|
||||||
|
description: |
|
||||||
|
Total is the total size (in bytes) of all the locally present
|
||||||
|
data (both distributable and non-distributable) that's related to
|
||||||
|
this manifest and its children.
|
||||||
|
This equal to the sum of [Content] size AND all the sizes in the
|
||||||
|
[Size] struct present in the Kind-specific data struct.
|
||||||
|
For example, for an image kind (Kind == "image")
|
||||||
|
this would include the size of the image content and unpacked
|
||||||
|
image snapshots ([Size.Content] + [ImageData.Size.Unpacked]).
|
||||||
|
Content:
|
||||||
|
description: |
|
||||||
|
Content is the size (in bytes) of all the locally present
|
||||||
|
content in the content store (e.g. image config, layers)
|
||||||
|
referenced by this manifest and its children.
|
||||||
|
This only includes blobs in the content store.
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
example: 3987495
|
||||||
|
Kind:
|
||||||
|
type: "string"
|
||||||
|
example: "image"
|
||||||
|
enum:
|
||||||
|
- "image"
|
||||||
|
- "attestation"
|
||||||
|
- "unknown"
|
||||||
|
description: |
|
||||||
|
The kind of the manifest.
|
||||||
|
|
||||||
|
kind | description
|
||||||
|
-------------|-----------------------------------------------------------
|
||||||
|
image | Image manifest that can be used to start a container.
|
||||||
|
attestation | Attestation manifest produced by the Buildkit builder for a specific image manifest.
|
||||||
|
ImageData:
|
||||||
|
description: |
|
||||||
|
The image data for the image manifest.
|
||||||
|
This field is only populated when Kind is "image".
|
||||||
|
type: "object"
|
||||||
|
x-nullable: true
|
||||||
|
x-omitempty: true
|
||||||
|
required: ["Platform", "Containers", "Size", "UnpackedSize"]
|
||||||
|
properties:
|
||||||
|
Platform:
|
||||||
|
$ref: "#/definitions/OCIPlatform"
|
||||||
|
description: |
|
||||||
|
OCI platform of the image. This will be the platform specified in the
|
||||||
|
manifest descriptor from the index/manifest list.
|
||||||
|
If it's not available, it will be obtained from the image config.
|
||||||
|
Containers:
|
||||||
|
description: |
|
||||||
|
The IDs of the containers that are using this image.
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
type: "string"
|
||||||
|
example: ["ede54ee1fda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c7430", "abadbce344c096744d8d6071a90d474d28af8f1034b5ea9fb03c3f4bfc6d005e"]
|
||||||
|
Size:
|
||||||
|
type: "object"
|
||||||
|
x-nullable: false
|
||||||
|
required: ["Unpacked"]
|
||||||
|
properties:
|
||||||
|
Unpacked:
|
||||||
|
type: "integer"
|
||||||
|
format: "int64"
|
||||||
|
example: 3987495
|
||||||
|
description: |
|
||||||
|
Unpacked is the size (in bytes) of the locally unpacked
|
||||||
|
(uncompressed) image content that's directly usable by the containers
|
||||||
|
running this image.
|
||||||
|
It's independent of the distributable content - e.g.
|
||||||
|
the image might still have an unpacked data that's still used by
|
||||||
|
some container even when the distributable/compressed content is
|
||||||
|
already gone.
|
||||||
|
AttestationData:
|
||||||
|
description: |
|
||||||
|
The image data for the attestation manifest.
|
||||||
|
This field is only populated when Kind is "attestation".
|
||||||
|
type: "object"
|
||||||
|
x-nullable: true
|
||||||
|
x-omitempty: true
|
||||||
|
required: ["For"]
|
||||||
|
properties:
|
||||||
|
For:
|
||||||
|
description: |
|
||||||
|
The digest of the image manifest that this attestation is for.
|
||||||
|
type: "string"
|
||||||
|
example: "sha256:95869fbcf224d947ace8d61d0e931d49e31bb7fc67fffbbe9c3198c33aa8e93f"
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
/containers/json:
|
/containers/json:
|
||||||
get:
|
get:
|
||||||
|
@ -8622,6 +8749,11 @@ paths:
|
||||||
description: "Show digest information as a `RepoDigests` field on each image."
|
description: "Show digest information as a `RepoDigests` field on each image."
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
default: false
|
default: false
|
||||||
|
- name: "manifests"
|
||||||
|
in: "query"
|
||||||
|
description: "Include `Manifests` in the image summary."
|
||||||
|
type: "boolean"
|
||||||
|
default: false
|
||||||
tags: ["Image"]
|
tags: ["Image"]
|
||||||
/build:
|
/build:
|
||||||
post:
|
post:
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
package image
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ManifestKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ManifestKindImage ManifestKind = "image"
|
||||||
|
ManifestKindAttestation ManifestKind = "attestation"
|
||||||
|
ManifestKindUnknown ManifestKind = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ManifestSummary struct {
|
||||||
|
// ID is the content-addressable ID of an image and is the same as the
|
||||||
|
// digest of the image manifest.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
ID string `json:"ID"`
|
||||||
|
|
||||||
|
// Descriptor is the OCI descriptor of the image.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Descriptor ocispec.Descriptor `json:"Descriptor"`
|
||||||
|
|
||||||
|
// Indicates whether all the child content (image config, layers) is
|
||||||
|
// fully available locally
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Available bool `json:"Available"`
|
||||||
|
|
||||||
|
// Size is the size information of the content related to this manifest.
|
||||||
|
// Note: These sizes only take the locally available content into account.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Size struct {
|
||||||
|
// Content is the size (in bytes) of all the locally present
|
||||||
|
// content in the content store (e.g. image config, layers)
|
||||||
|
// referenced by this manifest and its children.
|
||||||
|
// This only includes blobs in the content store.
|
||||||
|
Content int64 `json:"Content"`
|
||||||
|
|
||||||
|
// Total is the total size (in bytes) of all the locally present
|
||||||
|
// data (both distributable and non-distributable) that's related to
|
||||||
|
// this manifest and its children.
|
||||||
|
// This equal to the sum of [Content] size AND all the sizes in the
|
||||||
|
// [Size] struct present in the Kind-specific data struct.
|
||||||
|
// For example, for an image kind (Kind == ManifestKindImage),
|
||||||
|
// this would include the size of the image content and unpacked
|
||||||
|
// image snapshots ([Size.Content] + [ImageData.Size.Unpacked]).
|
||||||
|
Total int64 `json:"Total"`
|
||||||
|
} `json:"Size"`
|
||||||
|
|
||||||
|
// Kind is the kind of the image manifest.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Kind ManifestKind `json:"Kind"`
|
||||||
|
|
||||||
|
// Fields below are specific to the kind of the image manifest.
|
||||||
|
|
||||||
|
// Present only if Kind == ManifestKindImage.
|
||||||
|
ImageData *ImageProperties `json:"ImageData,omitempty"`
|
||||||
|
|
||||||
|
// Present only if Kind == ManifestKindAttestation.
|
||||||
|
AttestationData *AttestationProperties `json:"AttestationData,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageProperties struct {
|
||||||
|
// Platform is the OCI platform object describing the platform of the image.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Platform ocispec.Platform `json:"Platform"`
|
||||||
|
|
||||||
|
Size struct {
|
||||||
|
// Unpacked is the size (in bytes) of the locally unpacked
|
||||||
|
// (uncompressed) image content that's directly usable by the containers
|
||||||
|
// running this image.
|
||||||
|
// It's independent of the distributable content - e.g.
|
||||||
|
// the image might still have an unpacked data that's still used by
|
||||||
|
// some container even when the distributable/compressed content is
|
||||||
|
// already gone.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Unpacked int64 `json:"Unpacked"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Containers is an array containing the IDs of the containers that are
|
||||||
|
// using this image.
|
||||||
|
//
|
||||||
|
// Required: true
|
||||||
|
Containers []string `json:"Containers"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AttestationProperties struct {
|
||||||
|
// For is the digest of the image manifest that this attestation is for.
|
||||||
|
For digest.Digest `json:"For"`
|
||||||
|
}
|
|
@ -76,6 +76,9 @@ type ListOptions struct {
|
||||||
|
|
||||||
// ContainerCount indicates whether container count should be computed.
|
// ContainerCount indicates whether container count should be computed.
|
||||||
ContainerCount bool
|
ContainerCount bool
|
||||||
|
|
||||||
|
// Manifests indicates whether the image manifests should be returned.
|
||||||
|
Manifests bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOptions holds parameters to remove images.
|
// RemoveOptions holds parameters to remove images.
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
package image
|
package image
|
||||||
|
|
||||||
// This file was generated by the swagger tool.
|
|
||||||
// Editing this file might prove futile when you re-run the swagger generate command
|
|
||||||
|
|
||||||
// Summary summary
|
|
||||||
// swagger:model Summary
|
|
||||||
type Summary struct {
|
type Summary struct {
|
||||||
|
|
||||||
// Number of containers using this image. Includes both stopped and running
|
// Number of containers using this image. Includes both stopped and running
|
||||||
|
@ -47,6 +42,14 @@ type Summary struct {
|
||||||
// Required: true
|
// Required: true
|
||||||
ParentID string `json:"ParentId"`
|
ParentID string `json:"ParentId"`
|
||||||
|
|
||||||
|
// Manifests is a list of image manifests available in this image. It
|
||||||
|
// provides a more detailed view of the platform-specific image manifests or
|
||||||
|
// other image-attached data like build attestations.
|
||||||
|
//
|
||||||
|
// WARNING: This is experimental and may change at any time without any backward
|
||||||
|
// compatibility.
|
||||||
|
Manifests []ManifestSummary `json:"Manifests,omitempty"`
|
||||||
|
|
||||||
// List of content-addressable digests of locally available image manifests
|
// List of content-addressable digests of locally available image manifests
|
||||||
// that the image is referenced from. Multiple manifests can refer to the
|
// that the image is referenced from. Multiple manifests can refer to the
|
||||||
// same image.
|
// same image.
|
||||||
|
|
|
@ -34,10 +34,9 @@ type AuthConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeAuthConfig serializes the auth configuration as a base64url encoded
|
// EncodeAuthConfig serializes the auth configuration as a base64url encoded
|
||||||
// RFC4648, section 5) JSON string for sending through the X-Registry-Auth header.
|
// ([RFC4648, section 5]) JSON string for sending through the X-Registry-Auth header.
|
||||||
//
|
//
|
||||||
// For details on base64url encoding, see:
|
// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5
|
||||||
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
|
|
||||||
func EncodeAuthConfig(authConfig AuthConfig) (string, error) {
|
func EncodeAuthConfig(authConfig AuthConfig) (string, error) {
|
||||||
buf, err := json.Marshal(authConfig)
|
buf, err := json.Marshal(authConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -46,15 +45,14 @@ func EncodeAuthConfig(authConfig AuthConfig) (string, error) {
|
||||||
return base64.URLEncoding.EncodeToString(buf), nil
|
return base64.URLEncoding.EncodeToString(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeAuthConfig decodes base64url encoded (RFC4648, section 5) JSON
|
// DecodeAuthConfig decodes base64url encoded ([RFC4648, section 5]) JSON
|
||||||
// authentication information as sent through the X-Registry-Auth header.
|
// authentication information as sent through the X-Registry-Auth header.
|
||||||
//
|
//
|
||||||
// This function always returns an AuthConfig, even if an error occurs. It is up
|
// This function always returns an [AuthConfig], even if an error occurs. It is up
|
||||||
// to the caller to decide if authentication is required, and if the error can
|
// to the caller to decide if authentication is required, and if the error can
|
||||||
// be ignored.
|
// be ignored.
|
||||||
//
|
//
|
||||||
// For details on base64url encoding, see:
|
// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5
|
||||||
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
|
|
||||||
func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) {
|
func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) {
|
||||||
if authEncoded == "" {
|
if authEncoded == "" {
|
||||||
return &AuthConfig{}, nil
|
return &AuthConfig{}, nil
|
||||||
|
@ -69,7 +67,7 @@ func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) {
|
||||||
// clients and API versions. Current clients and API versions expect authentication
|
// clients and API versions. Current clients and API versions expect authentication
|
||||||
// to be provided through the X-Registry-Auth header.
|
// to be provided through the X-Registry-Auth header.
|
||||||
//
|
//
|
||||||
// Like DecodeAuthConfig, this function always returns an AuthConfig, even if an
|
// Like [DecodeAuthConfig], this function always returns an [AuthConfig], even if an
|
||||||
// error occurs. It is up to the caller to decide if authentication is required,
|
// error occurs. It is up to the caller to decide if authentication is required,
|
||||||
// and if the error can be ignored.
|
// and if the error can be ignored.
|
||||||
func DecodeAuthConfigBody(rdr io.ReadCloser) (*AuthConfig, error) {
|
func DecodeAuthConfigBody(rdr io.ReadCloser) (*AuthConfig, error) {
|
||||||
|
|
|
@ -11,6 +11,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImageList returns a list of images in the docker host.
|
// ImageList returns a list of images in the docker host.
|
||||||
|
//
|
||||||
|
// Experimental: Setting the [options.Manifest] will populate
|
||||||
|
// [image.Summary.Manifests] with information about image manifests.
|
||||||
|
// This is experimental and might change in the future without any backward
|
||||||
|
// compatibility.
|
||||||
func (cli *Client) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) {
|
func (cli *Client) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) {
|
||||||
var images []image.Summary
|
var images []image.Summary
|
||||||
|
|
||||||
|
@ -47,6 +52,9 @@ func (cli *Client) ImageList(ctx context.Context, options image.ListOptions) ([]
|
||||||
if options.SharedSize && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
|
if options.SharedSize && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
|
||||||
query.Set("shared-size", "1")
|
query.Set("shared-size", "1")
|
||||||
}
|
}
|
||||||
|
if options.Manifests && versions.GreaterThanOrEqualTo(cli.version, "1.47") {
|
||||||
|
query.Set("manifests", "1")
|
||||||
|
}
|
||||||
|
|
||||||
serverResp, err := cli.get(ctx, "/images/json", query, nil)
|
serverResp, err := cli.get(ctx, "/images/json", query, nil)
|
||||||
defer ensureReaderClosed(serverResp)
|
defer ensureReaderClosed(serverResp)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/pkg/userns"
|
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
|
"github.com/moby/sys/userns"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/moby/buildkit/solver/pb"
|
"github.com/moby/buildkit/solver/pb"
|
||||||
"github.com/moby/buildkit/util/system"
|
"github.com/moby/buildkit/util/system"
|
||||||
|
@ -290,7 +291,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
if len(e.secrets) > 0 {
|
if len(e.secrets) > 0 {
|
||||||
addCap(&e.constraints, pb.CapExecMountSecret)
|
addCap(&e.constraints, pb.CapExecMountSecret)
|
||||||
for _, s := range e.secrets {
|
for _, s := range e.secrets {
|
||||||
if s.IsEnv {
|
if s.Env != nil {
|
||||||
addCap(&e.constraints, pb.CapExecSecretEnv)
|
addCap(&e.constraints, pb.CapExecSecretEnv)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -388,15 +389,17 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range e.secrets {
|
for _, s := range e.secrets {
|
||||||
if s.IsEnv {
|
if s.Env != nil {
|
||||||
peo.Secretenv = append(peo.Secretenv, &pb.SecretEnv{
|
peo.Secretenv = append(peo.Secretenv, &pb.SecretEnv{
|
||||||
ID: s.ID,
|
ID: s.ID,
|
||||||
Name: s.Target,
|
Name: *s.Env,
|
||||||
Optional: s.Optional,
|
Optional: s.Optional,
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
|
if s.Target != nil {
|
||||||
pm := &pb.Mount{
|
pm := &pb.Mount{
|
||||||
Dest: s.Target,
|
Input: pb.Empty,
|
||||||
|
Dest: *s.Target,
|
||||||
MountType: pb.MountType_SECRET,
|
MountType: pb.MountType_SECRET,
|
||||||
SecretOpt: &pb.SecretOpt{
|
SecretOpt: &pb.SecretOpt{
|
||||||
ID: s.ID,
|
ID: s.ID,
|
||||||
|
@ -412,6 +415,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
|
||||||
|
|
||||||
for _, s := range e.ssh {
|
for _, s := range e.ssh {
|
||||||
pm := &pb.Mount{
|
pm := &pb.Mount{
|
||||||
|
Input: pb.Empty,
|
||||||
Dest: s.Target,
|
Dest: s.Target,
|
||||||
MountType: pb.MountType_SSH,
|
MountType: pb.MountType_SSH,
|
||||||
SSHOpt: &pb.SSHOpt{
|
SSHOpt: &pb.SSHOpt{
|
||||||
|
@ -678,7 +682,19 @@ type SSHInfo struct {
|
||||||
// AddSecret is a RunOption that adds a secret to the exec.
|
// AddSecret is a RunOption that adds a secret to the exec.
|
||||||
func AddSecret(dest string, opts ...SecretOption) RunOption {
|
func AddSecret(dest string, opts ...SecretOption) RunOption {
|
||||||
return runOptionFunc(func(ei *ExecInfo) {
|
return runOptionFunc(func(ei *ExecInfo) {
|
||||||
s := &SecretInfo{ID: dest, Target: dest, Mode: 0400}
|
s := &SecretInfo{ID: dest, Target: &dest, Mode: 0400}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt.SetSecretOption(s)
|
||||||
|
}
|
||||||
|
ei.Secrets = append(ei.Secrets, *s)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSecretWithDest is a RunOption that adds a secret to the exec
|
||||||
|
// with an optional destination.
|
||||||
|
func AddSecretWithDest(src string, dest *string, opts ...SecretOption) RunOption {
|
||||||
|
return runOptionFunc(func(ei *ExecInfo) {
|
||||||
|
s := &SecretInfo{ID: src, Target: dest, Mode: 0400}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt.SetSecretOption(s)
|
opt.SetSecretOption(s)
|
||||||
}
|
}
|
||||||
|
@ -697,13 +713,15 @@ func (fn secretOptionFunc) SetSecretOption(si *SecretInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SecretInfo struct {
|
type SecretInfo struct {
|
||||||
ID string
|
ID string
|
||||||
Target string
|
// Target optionally specifies the target for the secret mount
|
||||||
|
Target *string
|
||||||
|
// Env optionally names the environment variable for the secret
|
||||||
|
Env *string
|
||||||
Mode int
|
Mode int
|
||||||
UID int
|
UID int
|
||||||
GID int
|
GID int
|
||||||
Optional bool
|
Optional bool
|
||||||
IsEnv bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var SecretOptional = secretOptionFunc(func(si *SecretInfo) {
|
var SecretOptional = secretOptionFunc(func(si *SecretInfo) {
|
||||||
|
@ -719,7 +737,24 @@ func SecretID(id string) SecretOption {
|
||||||
// SecretAsEnv defines if the secret should be added as an environment variable
|
// SecretAsEnv defines if the secret should be added as an environment variable
|
||||||
func SecretAsEnv(v bool) SecretOption {
|
func SecretAsEnv(v bool) SecretOption {
|
||||||
return secretOptionFunc(func(si *SecretInfo) {
|
return secretOptionFunc(func(si *SecretInfo) {
|
||||||
si.IsEnv = v
|
if !v {
|
||||||
|
si.Env = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if si.Target == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
target := strings.Clone(*si.Target)
|
||||||
|
si.Env = &target
|
||||||
|
si.Target = nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecretAsEnvName defines if the secret should be added as an environment variable
|
||||||
|
// with the specified name
|
||||||
|
func SecretAsEnvName(v string) SecretOption {
|
||||||
|
return secretOptionFunc(func(si *SecretInfo) {
|
||||||
|
si.Env = &v
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package errdefs
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
type internalErr struct {
|
|
||||||
error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (internalErr) System() {}
|
|
||||||
|
|
||||||
func (err internalErr) Unwrap() error {
|
|
||||||
return err.error
|
|
||||||
}
|
|
||||||
|
|
||||||
type system interface {
|
|
||||||
System()
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ system = internalErr{}
|
|
||||||
|
|
||||||
func Internal(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return internalErr{err}
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsInternal(err error) bool {
|
|
||||||
var s system
|
|
||||||
return errors.As(err, &s)
|
|
||||||
}
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package errdefs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
type internalErr struct {
|
||||||
|
error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (internalErr) System() {}
|
||||||
|
|
||||||
|
func (err internalErr) Unwrap() error {
|
||||||
|
return err.error
|
||||||
|
}
|
||||||
|
|
||||||
|
type system interface {
|
||||||
|
System()
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ system = internalErr{}
|
||||||
|
|
||||||
|
func Internal(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return internalErr{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsInternal(err error) bool {
|
||||||
|
var s system
|
||||||
|
if errors.As(err, &s) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var errno syscall.Errno
|
||||||
|
if errors.As(err, &errno) {
|
||||||
|
if _, ok := isInternalSyscall(errno); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsResourceExhausted(err error) bool {
|
||||||
|
var errno syscall.Errno
|
||||||
|
if errors.As(err, &errno) {
|
||||||
|
if v, ok := isInternalSyscall(errno); ok && v {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInternalSyscall(err syscall.Errno) (bool, bool) {
|
||||||
|
v, ok := syscallErrors()[err]
|
||||||
|
return v, ok
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package errdefs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// syscallErrors returns a map of syscall errors that are considered internal.
|
||||||
|
// value is true if the error is of type resource exhaustion, false otherwise.
|
||||||
|
func syscallErrors() map[syscall.Errno]bool {
|
||||||
|
return map[syscall.Errno]bool{
|
||||||
|
unix.EIO: false, // I/O error
|
||||||
|
unix.ENOMEM: true, // Out of memory
|
||||||
|
unix.EFAULT: false, // Bad address
|
||||||
|
unix.ENOSPC: true, // No space left on device
|
||||||
|
unix.ENOTRECOVERABLE: false, // State not recoverable
|
||||||
|
unix.EHWPOISON: false, // Memory page has hardware error
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package errdefs
|
||||||
|
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
|
func syscallErrors() map[syscall.Errno]bool {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -10,42 +10,61 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Warn LintWarnFunc
|
ExperimentalAll bool
|
||||||
SkipRules []string
|
ExperimentalRules []string
|
||||||
SkipAll bool
|
ReturnAsError bool
|
||||||
ReturnAsError bool
|
SkipAll bool
|
||||||
|
SkipRules []string
|
||||||
|
Warn LintWarnFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
type Linter struct {
|
type Linter struct {
|
||||||
SkippedRules map[string]struct{}
|
CalledRules []string
|
||||||
CalledRules []string
|
ExperimentalAll bool
|
||||||
SkipAll bool
|
ExperimentalRules map[string]struct{}
|
||||||
ReturnAsError bool
|
ReturnAsError bool
|
||||||
Warn LintWarnFunc
|
SkipAll bool
|
||||||
|
SkippedRules map[string]struct{}
|
||||||
|
Warn LintWarnFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config *Config) *Linter {
|
func New(config *Config) *Linter {
|
||||||
toret := &Linter{
|
toret := &Linter{
|
||||||
SkippedRules: map[string]struct{}{},
|
SkippedRules: map[string]struct{}{},
|
||||||
CalledRules: []string{},
|
ExperimentalRules: map[string]struct{}{},
|
||||||
Warn: config.Warn,
|
CalledRules: []string{},
|
||||||
|
Warn: config.Warn,
|
||||||
}
|
}
|
||||||
toret.SkipAll = config.SkipAll
|
toret.SkipAll = config.SkipAll
|
||||||
|
toret.ExperimentalAll = config.ExperimentalAll
|
||||||
toret.ReturnAsError = config.ReturnAsError
|
toret.ReturnAsError = config.ReturnAsError
|
||||||
for _, rule := range config.SkipRules {
|
for _, rule := range config.SkipRules {
|
||||||
toret.SkippedRules[rule] = struct{}{}
|
toret.SkippedRules[rule] = struct{}{}
|
||||||
}
|
}
|
||||||
|
for _, rule := range config.ExperimentalRules {
|
||||||
|
toret.ExperimentalRules[rule] = struct{}{}
|
||||||
|
}
|
||||||
return toret
|
return toret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *Linter) Run(rule LinterRuleI, location []parser.Range, txt ...string) {
|
func (lc *Linter) Run(rule LinterRuleI, location []parser.Range, txt ...string) {
|
||||||
if lc == nil || lc.Warn == nil || lc.SkipAll || rule.IsDeprecated() {
|
if lc == nil || lc.Warn == nil || rule.IsDeprecated() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rulename := rule.RuleName()
|
rulename := rule.RuleName()
|
||||||
if _, ok := lc.SkippedRules[rulename]; ok {
|
if rule.IsExperimental() {
|
||||||
return
|
_, experimentalOk := lc.ExperimentalRules[rulename]
|
||||||
|
if !(lc.ExperimentalAll || experimentalOk) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, skipOk := lc.SkippedRules[rulename]
|
||||||
|
if lc.SkipAll || skipOk {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.CalledRules = append(lc.CalledRules, rulename)
|
lc.CalledRules = append(lc.CalledRules, rulename)
|
||||||
rule.Run(lc.Warn, location, txt...)
|
rule.Run(lc.Warn, location, txt...)
|
||||||
}
|
}
|
||||||
|
@ -72,14 +91,16 @@ type LinterRuleI interface {
|
||||||
RuleName() string
|
RuleName() string
|
||||||
Run(warn LintWarnFunc, location []parser.Range, txt ...string)
|
Run(warn LintWarnFunc, location []parser.Range, txt ...string)
|
||||||
IsDeprecated() bool
|
IsDeprecated() bool
|
||||||
|
IsExperimental() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinterRule[F any] struct {
|
type LinterRule[F any] struct {
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
Deprecated bool
|
Deprecated bool
|
||||||
URL string
|
Experimental bool
|
||||||
Format F
|
URL string
|
||||||
|
Format F
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rule *LinterRule[F]) RuleName() string {
|
func (rule *LinterRule[F]) RuleName() string {
|
||||||
|
@ -98,6 +119,10 @@ func (rule *LinterRule[F]) IsDeprecated() bool {
|
||||||
return rule.Deprecated
|
return rule.Deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rule *LinterRule[F]) IsExperimental() bool {
|
||||||
|
return rule.Experimental
|
||||||
|
}
|
||||||
|
|
||||||
func LintFormatShort(rulename, msg string, line int) string {
|
func LintFormatShort(rulename, msg string, line int) string {
|
||||||
msg = fmt.Sprintf("%s: %s", rulename, msg)
|
msg = fmt.Sprintf("%s: %s", rulename, msg)
|
||||||
if line > 0 {
|
if line > 0 {
|
||||||
|
@ -114,9 +139,9 @@ func ParseLintOptions(checkStr string) (*Config, error) {
|
||||||
return &Config{}, nil
|
return &Config{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(checkStr, ";", 2)
|
parts := strings.SplitN(checkStr, ";", 3)
|
||||||
var skipSet []string
|
var skipSet, experimentalSet []string
|
||||||
var errorOnWarn, skipAll bool
|
var errorOnWarn, skipAll, experimentalAll bool
|
||||||
for _, p := range parts {
|
for _, p := range parts {
|
||||||
k, v, ok := strings.Cut(p, "=")
|
k, v, ok := strings.Cut(p, "=")
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -134,6 +159,16 @@ func ParseLintOptions(checkStr string) (*Config, error) {
|
||||||
skipSet[i] = strings.TrimSpace(rule)
|
skipSet[i] = strings.TrimSpace(rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "experimental":
|
||||||
|
v = strings.TrimSpace(v)
|
||||||
|
if v == "all" {
|
||||||
|
experimentalAll = true
|
||||||
|
} else {
|
||||||
|
experimentalSet = strings.Split(v, ",")
|
||||||
|
for i, rule := range experimentalSet {
|
||||||
|
experimentalSet[i] = strings.TrimSpace(rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
case "error":
|
case "error":
|
||||||
v, err := strconv.ParseBool(strings.TrimSpace(v))
|
v, err := strconv.ParseBool(strings.TrimSpace(v))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -145,8 +180,10 @@ func ParseLintOptions(checkStr string) (*Config, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Config{
|
return &Config{
|
||||||
SkipRules: skipSet,
|
ExperimentalAll: experimentalAll,
|
||||||
SkipAll: skipAll,
|
ExperimentalRules: experimentalSet,
|
||||||
ReturnAsError: errorOnWarn,
|
SkipRules: skipSet,
|
||||||
|
SkipAll: skipAll,
|
||||||
|
ReturnAsError: errorOnWarn,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,5 +163,6 @@ var (
|
||||||
Format: func(cmd, file string) string {
|
Format: func(cmd, file string) string {
|
||||||
return fmt.Sprintf("Attempting to %s file %q that is excluded by .dockerignore", cmd, file)
|
return fmt.Sprintf("Attempting to %s file %q that is excluded by .dockerignore", cmd, file)
|
||||||
},
|
},
|
||||||
|
Experimental: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -378,6 +378,9 @@ func (sw *shellWord) processDollar() (string, error) {
|
||||||
fallthrough
|
fallthrough
|
||||||
case '+', '-', '?', '#', '%':
|
case '+', '-', '?', '#', '%':
|
||||||
rawEscapes := ch == '#' || ch == '%'
|
rawEscapes := ch == '#' || ch == '%'
|
||||||
|
if nullIsUnset && rawEscapes {
|
||||||
|
return "", errors.Errorf("unsupported modifier (%s) in substitution", chs)
|
||||||
|
}
|
||||||
word, _, err := sw.processStopOn('}', rawEscapes)
|
word, _, err := sw.processStopOn('}', rawEscapes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if sw.scanner.Peek() == scanner.EOF {
|
if sw.scanner.Peek() == scanner.EOF {
|
||||||
|
|
|
@ -46,30 +46,28 @@ const (
|
||||||
|
|
||||||
// Don't forget to update frontend documentation if you add
|
// Don't forget to update frontend documentation if you add
|
||||||
// a new build-arg: frontend/dockerfile/docs/reference.md
|
// a new build-arg: frontend/dockerfile/docs/reference.md
|
||||||
keyCacheNSArg = "build-arg:BUILDKIT_CACHE_MOUNT_NS"
|
keyCacheNSArg = "build-arg:BUILDKIT_CACHE_MOUNT_NS"
|
||||||
keyMultiPlatformArg = "build-arg:BUILDKIT_MULTI_PLATFORM"
|
keyMultiPlatformArg = "build-arg:BUILDKIT_MULTI_PLATFORM"
|
||||||
keyHostnameArg = "build-arg:BUILDKIT_SANDBOX_HOSTNAME"
|
keyHostnameArg = "build-arg:BUILDKIT_SANDBOX_HOSTNAME"
|
||||||
keyDockerfileLintArg = "build-arg:BUILDKIT_DOCKERFILE_CHECK"
|
keyDockerfileLintArg = "build-arg:BUILDKIT_DOCKERFILE_CHECK"
|
||||||
keyContextKeepGitDirArg = "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR"
|
keyContextKeepGitDirArg = "build-arg:BUILDKIT_CONTEXT_KEEP_GIT_DIR"
|
||||||
keySourceDateEpoch = "build-arg:SOURCE_DATE_EPOCH"
|
keySourceDateEpoch = "build-arg:SOURCE_DATE_EPOCH"
|
||||||
keyCopyIgnoredCheckEnabled = "build-arg:BUILDKIT_DOCKERFILE_CHECK_COPYIGNORED_EXPERIMENT"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
BuildArgs map[string]string
|
BuildArgs map[string]string
|
||||||
CacheIDNamespace string
|
CacheIDNamespace string
|
||||||
CgroupParent string
|
CgroupParent string
|
||||||
Epoch *time.Time
|
Epoch *time.Time
|
||||||
ExtraHosts []llb.HostIP
|
ExtraHosts []llb.HostIP
|
||||||
Hostname string
|
Hostname string
|
||||||
ImageResolveMode llb.ResolveMode
|
ImageResolveMode llb.ResolveMode
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
NetworkMode pb.NetMode
|
NetworkMode pb.NetMode
|
||||||
ShmSize int64
|
ShmSize int64
|
||||||
Target string
|
Target string
|
||||||
Ulimits []pb.Ulimit
|
Ulimits []pb.Ulimit
|
||||||
LinterConfig *linter.Config
|
LinterConfig *linter.Config
|
||||||
CopyIgnoredCheckEnabled bool
|
|
||||||
|
|
||||||
CacheImports []client.CacheOptionsEntry
|
CacheImports []client.CacheOptionsEntry
|
||||||
TargetPlatforms []ocispecs.Platform // nil means default
|
TargetPlatforms []ocispecs.Platform // nil means default
|
||||||
|
@ -291,16 +289,6 @@ func (bc *Client) init() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyIgnoredCheckEnabled is an experimental feature to check if COPY is ignored by .dockerignore,
|
|
||||||
// and it is disabled by default. It is expected that this feature will be enabled by default in a future
|
|
||||||
// release, and this build-arg will be removed.
|
|
||||||
if v, ok := opts[keyCopyIgnoredCheckEnabled]; ok {
|
|
||||||
bc.CopyIgnoredCheckEnabled, err = strconv.ParseBool(v)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to parse %s", keyCopyIgnoredCheckEnabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bc.localsSessionIDs = parseLocalSessionIDs(opts)
|
bc.localsSessionIDs = parseLocalSessionIDs(opts)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -66,7 +66,7 @@ func (bc *Client) HandleSubrequest(ctx context.Context, h RequestHandler) (*clie
|
||||||
if warnings == nil {
|
if warnings == nil {
|
||||||
return nil, true, nil
|
return nil, true, nil
|
||||||
}
|
}
|
||||||
res, err := warnings.ToResult()
|
res, err := warnings.ToResult(nil)
|
||||||
return res, true, err
|
return res, true, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SourceInfoMap func(*pb.SourceInfo) *pb.SourceInfo
|
||||||
|
|
||||||
const RequestLint = "frontend.lint"
|
const RequestLint = "frontend.lint"
|
||||||
|
|
||||||
var SubrequestLintDefinition = subrequests.Request{
|
var SubrequestLintDefinition = subrequests.Request{
|
||||||
|
@ -39,6 +41,27 @@ type Warning struct {
|
||||||
Location pb.Location `json:"location,omitempty"`
|
Location pb.Location `json:"location,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Warning) PrintTo(wr io.Writer, sources []*pb.SourceInfo, scb SourceInfoMap) error {
|
||||||
|
fmt.Fprintf(wr, "\nWARNING: %s", w.RuleName)
|
||||||
|
if w.URL != "" {
|
||||||
|
fmt.Fprintf(wr, " - %s", w.URL)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(wr, "\n%s\n", w.Detail)
|
||||||
|
|
||||||
|
if w.Location.SourceIndex < 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sourceInfo := sources[w.Location.SourceIndex]
|
||||||
|
if scb != nil {
|
||||||
|
sourceInfo = scb(sourceInfo)
|
||||||
|
}
|
||||||
|
source := errdefs.Source{
|
||||||
|
Info: sourceInfo,
|
||||||
|
Ranges: w.Location.Ranges,
|
||||||
|
}
|
||||||
|
return source.Print(wr)
|
||||||
|
}
|
||||||
|
|
||||||
type BuildError struct {
|
type BuildError struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Location pb.Location `json:"location"`
|
Location pb.Location `json:"location"`
|
||||||
|
@ -93,7 +116,7 @@ func (results *LintResults) AddWarning(rulename, description, url, fmtmsg string
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (results *LintResults) ToResult() (*client.Result, error) {
|
func (results *LintResults) ToResult(scb SourceInfoMap) (*client.Result, error) {
|
||||||
res := client.NewResult()
|
res := client.NewResult()
|
||||||
dt, err := json.MarshalIndent(results, "", " ")
|
dt, err := json.MarshalIndent(results, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -102,7 +125,7 @@ func (results *LintResults) ToResult() (*client.Result, error) {
|
||||||
res.AddMeta("result.json", dt)
|
res.AddMeta("result.json", dt)
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
b := bytes.NewBuffer(nil)
|
||||||
if err := PrintLintViolations(dt, b); err != nil {
|
if err := PrintLintViolations(dt, b, scb); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
res.AddMeta("result.txt", b.Bytes())
|
res.AddMeta("result.txt", b.Bytes())
|
||||||
|
@ -117,28 +140,7 @@ func (results *LintResults) ToResult() (*client.Result, error) {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (results *LintResults) validateWarnings() error {
|
func (results *LintResults) PrintTo(w io.Writer, scb SourceInfoMap) error {
|
||||||
for _, warning := range results.Warnings {
|
|
||||||
if int(warning.Location.SourceIndex) >= len(results.Sources) {
|
|
||||||
return errors.Errorf("sourceIndex is out of range")
|
|
||||||
}
|
|
||||||
if warning.Location.SourceIndex > 0 {
|
|
||||||
warningSource := results.Sources[warning.Location.SourceIndex]
|
|
||||||
if warningSource == nil {
|
|
||||||
return errors.Errorf("sourceIndex points to nil source")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintLintViolations(dt []byte, w io.Writer) error {
|
|
||||||
var results LintResults
|
|
||||||
|
|
||||||
if err := json.Unmarshal(dt, &results); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := results.validateWarnings(); err != nil {
|
if err := results.validateWarnings(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -169,21 +171,7 @@ func PrintLintViolations(dt []byte, w io.Writer) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, warning := range results.Warnings {
|
for _, warning := range results.Warnings {
|
||||||
fmt.Fprintf(w, "\nWARNING: %s", warning.RuleName)
|
err := warning.PrintTo(w, results.Sources, scb)
|
||||||
if warning.URL != "" {
|
|
||||||
fmt.Fprintf(w, " - %s", warning.URL)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "\n%s\n", warning.Detail)
|
|
||||||
|
|
||||||
if warning.Location.SourceIndex < 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sourceInfo := results.Sources[warning.Location.SourceIndex]
|
|
||||||
source := errdefs.Source{
|
|
||||||
Info: sourceInfo,
|
|
||||||
Ranges: warning.Location.Ranges,
|
|
||||||
}
|
|
||||||
err := source.Print(w)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -192,6 +180,47 @@ func PrintLintViolations(dt []byte, w io.Writer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (results *LintResults) PrintErrorTo(w io.Writer) {
|
||||||
|
// This prints out the error in LintResults to the writer in a format that
|
||||||
|
// is consistent with the warnings for easier downstream consumption.
|
||||||
|
if results.Error == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(w, results.Error.Message)
|
||||||
|
sourceInfo := results.Sources[results.Error.Location.SourceIndex]
|
||||||
|
source := errdefs.Source{
|
||||||
|
Info: sourceInfo,
|
||||||
|
Ranges: results.Error.Location.Ranges,
|
||||||
|
}
|
||||||
|
source.Print(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (results *LintResults) validateWarnings() error {
|
||||||
|
for _, warning := range results.Warnings {
|
||||||
|
if int(warning.Location.SourceIndex) >= len(results.Sources) {
|
||||||
|
return errors.Errorf("sourceIndex is out of range")
|
||||||
|
}
|
||||||
|
if warning.Location.SourceIndex > 0 {
|
||||||
|
warningSource := results.Sources[warning.Location.SourceIndex]
|
||||||
|
if warningSource == nil {
|
||||||
|
return errors.Errorf("sourceIndex points to nil source")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintLintViolations(dt []byte, w io.Writer, scb SourceInfoMap) error {
|
||||||
|
var results LintResults
|
||||||
|
|
||||||
|
if err := json.Unmarshal(dt, &results); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.PrintTo(w, scb)
|
||||||
|
}
|
||||||
|
|
||||||
func sourceInfoEqual(a, b *pb.SourceInfo) bool {
|
func sourceInfoEqual(a, b *pb.SourceInfo) bool {
|
||||||
if a.Filename != b.Filename || a.Language != b.Language {
|
if a.Filename != b.Filename || a.Language != b.Language {
|
||||||
return false
|
return false
|
||||||
|
|
2
vendor/github.com/moby/buildkit/session/secrets/secretsprovider/secretsprovider.go
generated
vendored
2
vendor/github.com/moby/buildkit/session/secrets/secretsprovider/secretsprovider.go
generated
vendored
|
@ -32,7 +32,7 @@ func (sp *secretProvider) GetSecret(ctx context.Context, req *secrets.GetSecretR
|
||||||
dt, err := sp.store.GetSecret(ctx, req.ID)
|
dt, err := sp.store.GetSecret(ctx, req.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, secrets.ErrNotFound) {
|
if errors.Is(err, secrets.ErrNotFound) {
|
||||||
return nil, status.Errorf(codes.NotFound, err.Error())
|
return nil, status.Error(codes.NotFound, err.Error())
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,15 +13,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func New() *Uploader {
|
func New() *Uploader {
|
||||||
return &Uploader{m: map[string]io.Reader{}}
|
return &Uploader{m: map[string]io.ReadCloser{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Uploader struct {
|
type Uploader struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
m map[string]io.Reader
|
m map[string]io.ReadCloser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hp *Uploader) Add(r io.Reader) string {
|
func (hp *Uploader) Add(r io.ReadCloser) string {
|
||||||
id := identity.NewID()
|
id := identity.NewID()
|
||||||
hp.m[id] = r
|
hp.m[id] = r
|
||||||
return "http://buildkit-session/" + id
|
return "http://buildkit-session/" + id
|
||||||
|
@ -51,6 +51,11 @@ func (hp *Uploader) Pull(stream upload.Upload_PullServer) error {
|
||||||
hp.mu.Unlock()
|
hp.mu.Unlock()
|
||||||
|
|
||||||
_, err := io.Copy(&writer{stream}, r)
|
_, err := io.Copy(&writer{stream}, r)
|
||||||
|
|
||||||
|
if err1 := r.Close(); err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ func Context() context.Context {
|
||||||
err := errors.Errorf("got %d SIGTERM/SIGINTs, forcing shutdown", retries)
|
err := errors.Errorf("got %d SIGTERM/SIGINTs, forcing shutdown", retries)
|
||||||
cancel(err)
|
cancel(err)
|
||||||
if retries >= exitLimit {
|
if retries >= exitLimit {
|
||||||
bklog.G(ctx).Errorf(err.Error())
|
bklog.G(ctx).Error(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
vendor/github.com/moby/buildkit/util/appdefaults/appdefaults_linux.go
generated
vendored
Normal file
6
vendor/github.com/moby/buildkit/util/appdefaults/appdefaults_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package appdefaults
|
||||||
|
|
||||||
|
const (
|
||||||
|
Address = "unix:///run/buildkit/buildkitd.sock"
|
||||||
|
traceSocketPath = "/run/buildkit/otel-grpc.sock"
|
||||||
|
)
|
|
@ -10,7 +10,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Address = "unix:///run/buildkit/buildkitd.sock"
|
|
||||||
Root = "/var/lib/buildkit"
|
Root = "/var/lib/buildkit"
|
||||||
ConfigDir = "/etc/buildkit"
|
ConfigDir = "/etc/buildkit"
|
||||||
DefaultCNIBinDir = "/opt/cni/bin"
|
DefaultCNIBinDir = "/opt/cni/bin"
|
||||||
|
@ -82,5 +81,5 @@ func TraceSocketPath(inUserNS bool) string {
|
||||||
return filepath.Join(dirs[0], "buildkit", "otel-grpc.sock")
|
return filepath.Join(dirs[0], "buildkit", "otel-grpc.sock")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "/run/buildkit/otel-grpc.sock"
|
return traceSocketPath
|
||||||
}
|
}
|
||||||
|
|
8
vendor/github.com/moby/buildkit/util/appdefaults/appdefaults_unix_nolinux.go
generated
vendored
Normal file
8
vendor/github.com/moby/buildkit/util/appdefaults/appdefaults_unix_nolinux.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
//go:build unix && !linux
|
||||||
|
|
||||||
|
package appdefaults
|
||||||
|
|
||||||
|
const (
|
||||||
|
Address = "unix:///var/run/buildkit/buildkitd.sock"
|
||||||
|
traceSocketPath = "/var/run/buildkit/otel-grpc.sock"
|
||||||
|
)
|
|
@ -96,6 +96,9 @@ func withDetails(ctx context.Context, s *status.Status, details ...proto.Message
|
||||||
|
|
||||||
func Code(err error) codes.Code {
|
func Code(err error) codes.Code {
|
||||||
if errdefs.IsInternal(err) {
|
if errdefs.IsInternal(err) {
|
||||||
|
if errdefs.IsResourceExhausted(err) {
|
||||||
|
return codes.ResourceExhausted
|
||||||
|
}
|
||||||
return codes.Internal
|
return codes.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ func retryError(err error) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// catches TLS timeout or other network-related temporary errors
|
// catches TLS timeout or other network-related temporary errors
|
||||||
if ne := net.Error(nil); errors.As(err, &ne) && ne.Temporary() { //nolint:staticcheck // ignoring "SA1019: Temporary is deprecated", continue to propagate net.Error through the "temporary" status
|
if ne := net.Error(nil); errors.As(err, &ne) && ne.Temporary() { // ignoring "SA1019: Temporary is deprecated", continue to propagate net.Error through the "temporary" status
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package stack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
func compressStacks(st []*Stack) []*Stack {
|
||||||
|
if len(st) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.SortFunc(st, func(a, b *Stack) int {
|
||||||
|
return len(b.Frames) - len(a.Frames)
|
||||||
|
})
|
||||||
|
|
||||||
|
out := []*Stack{st[0]}
|
||||||
|
|
||||||
|
loop0:
|
||||||
|
for _, st := range st[1:] {
|
||||||
|
maxIdx := -1
|
||||||
|
for _, prev := range out {
|
||||||
|
idx := subFrames(st.Frames, prev.Frames)
|
||||||
|
if idx == -1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// full match, potentially skip all
|
||||||
|
if idx == len(st.Frames)-1 {
|
||||||
|
if st.Pid == prev.Pid && st.Version == prev.Version && slices.Compare(st.Cmdline, st.Cmdline) == 0 {
|
||||||
|
continue loop0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if idx > maxIdx {
|
||||||
|
maxIdx = idx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxIdx > 0 {
|
||||||
|
st.Frames = st.Frames[:len(st.Frames)-maxIdx]
|
||||||
|
}
|
||||||
|
out = append(out, st)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func subFrames(a, b []*Frame) int {
|
||||||
|
idx := -1
|
||||||
|
i := len(a) - 1
|
||||||
|
j := len(b) - 1
|
||||||
|
for i >= 0 {
|
||||||
|
if j < 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if a[i].Equal(b[j]) {
|
||||||
|
idx++
|
||||||
|
i--
|
||||||
|
j--
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Frame) Equal(b *Frame) bool {
|
||||||
|
return a.File == b.File && a.Line == b.Line && a.Name == b.Name
|
||||||
|
}
|
|
@ -44,6 +44,10 @@ func Helper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Traces(err error) []*Stack {
|
func Traces(err error) []*Stack {
|
||||||
|
return compressStacks(traces(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func traces(err error) []*Stack {
|
||||||
var st []*Stack
|
var st []*Stack
|
||||||
|
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
|
|
|
@ -220,7 +220,7 @@ func Run(t *testing.T, testCases []Test, opt ...TestOpt) {
|
||||||
func getFunctionName(i interface{}) string {
|
func getFunctionName(i interface{}) string {
|
||||||
fullname := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
fullname := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||||
dot := strings.LastIndex(fullname, ".") + 1
|
dot := strings.LastIndex(fullname, ".") + 1
|
||||||
return strings.Title(fullname[dot:]) //nolint:staticcheck // ignoring "SA1019: strings.Title is deprecated", as for our use we don't need full unicode support
|
return strings.Title(fullname[dot:]) // ignoring "SA1019: strings.Title is deprecated", as for our use we don't need full unicode support
|
||||||
}
|
}
|
||||||
|
|
||||||
var localImageCache map[string]map[string]struct{}
|
var localImageCache map[string]map[string]struct{}
|
||||||
|
|
|
@ -59,6 +59,8 @@ func (sb *sandbox) NewRegistry() (string, error) {
|
||||||
|
|
||||||
func (sb *sandbox) Cmd(args ...string) *exec.Cmd {
|
func (sb *sandbox) Cmd(args ...string) *exec.Cmd {
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
|
// \\ being stripped off for Windows paths, convert to unix style
|
||||||
|
args[0] = strings.ReplaceAll(args[0], "\\", "/")
|
||||||
if split, err := shlex.Split(args[0]); err == nil {
|
if split, err := shlex.Split(args[0]); err == nil {
|
||||||
args = split
|
args = split
|
||||||
}
|
}
|
||||||
|
@ -151,7 +153,7 @@ func FormatLogs(m map[string]*bytes.Buffer) string {
|
||||||
func CheckFeatureCompat(t *testing.T, sb Sandbox, features map[string]struct{}, reason ...string) {
|
func CheckFeatureCompat(t *testing.T, sb Sandbox, features map[string]struct{}, reason ...string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := HasFeatureCompat(t, sb, features, reason...); err != nil {
|
if err := HasFeatureCompat(t, sb, features, reason...); err != nil {
|
||||||
t.Skipf(err.Error())
|
t.Skip(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@ var windowsImagesMirrorMap = map[string]string{
|
||||||
"nanoserver:latest": "mcr.microsoft.com/windows/nanoserver:ltsc2022",
|
"nanoserver:latest": "mcr.microsoft.com/windows/nanoserver:ltsc2022",
|
||||||
"servercore:latest": "mcr.microsoft.com/windows/servercore:ltsc2022",
|
"servercore:latest": "mcr.microsoft.com/windows/servercore:ltsc2022",
|
||||||
"busybox:latest": "registry.k8s.io/e2e-test-images/busybox@sha256:6d854ffad9666d2041b879a1c128c9922d77faced7745ad676639b07111ab650",
|
"busybox:latest": "registry.k8s.io/e2e-test-images/busybox@sha256:6d854ffad9666d2041b879a1c128c9922d77faced7745ad676639b07111ab650",
|
||||||
|
// nanoserver with extra binaries, like fc.exe
|
||||||
|
// TODO(profnandaa): get an approved/compliant repo, placeholder for now
|
||||||
|
// see dockerfile here - https://github.com/microsoft/windows-container-tools/pull/178
|
||||||
|
"nanoserver:plus": "docker.io/wintools/nanoserver:ltsc2022",
|
||||||
}
|
}
|
||||||
|
|
||||||
// abstracted function to handle pipe dialing on windows.
|
// abstracted function to handle pipe dialing on windows.
|
||||||
|
|
|
@ -51,7 +51,7 @@ func mountedByOpenat2(path string) (bool, error) {
|
||||||
Resolve: unix.RESOLVE_NO_XDEV,
|
Resolve: unix.RESOLVE_NO_XDEV,
|
||||||
})
|
})
|
||||||
_ = unix.Close(dirfd)
|
_ = unix.Close(dirfd)
|
||||||
switch err { //nolint:errorlint // unix errors are bare
|
switch err {
|
||||||
case nil: // definitely not a mount
|
case nil: // definitely not a mount
|
||||||
_ = unix.Close(fd)
|
_ = unix.Close(fd)
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Package userns provides utilities to detect whether we are currently running
|
||||||
|
// in a Linux user namespace.
|
||||||
|
//
|
||||||
|
// This code was migrated from [libcontainer/runc], which based its implementation
|
||||||
|
// on code from [lcx/incus].
|
||||||
|
//
|
||||||
|
// [libcontainer/runc]: https://github.com/opencontainers/runc/blob/3778ae603c706494fd1e2c2faf83b406e38d687d/libcontainer/userns/userns_linux.go#L12-L49
|
||||||
|
// [lcx/incus]: https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700
|
||||||
|
package userns
|
||||||
|
|
||||||
|
// RunningInUserNS detects whether we are currently running in a Linux
|
||||||
|
// user namespace and memoizes the result. It returns false on non-Linux
|
||||||
|
// platforms.
|
||||||
|
func RunningInUserNS() bool {
|
||||||
|
return inUserNS()
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package userns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var inUserNS = sync.OnceValue(runningInUserNS)
|
||||||
|
|
||||||
|
// runningInUserNS detects whether we are currently running in a user namespace.
|
||||||
|
//
|
||||||
|
// This code was migrated from [libcontainer/runc] and based on an implementation
|
||||||
|
// from [lcx/incus].
|
||||||
|
//
|
||||||
|
// [libcontainer/runc]: https://github.com/opencontainers/runc/blob/3778ae603c706494fd1e2c2faf83b406e38d687d/libcontainer/userns/userns_linux.go#L12-L49
|
||||||
|
// [lcx/incus]: https://github.com/lxc/incus/blob/e45085dd42f826b3c8c3228e9733c0b6f998eafe/shared/util.go#L678-L700
|
||||||
|
func runningInUserNS() bool {
|
||||||
|
file, err := os.Open("/proc/self/uid_map")
|
||||||
|
if err != nil {
|
||||||
|
// This kernel-provided file only exists if user namespaces are supported.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
buf := bufio.NewReader(file)
|
||||||
|
l, _, err := buf.ReadLine()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return uidMapInUserNS(string(l))
|
||||||
|
}
|
||||||
|
|
||||||
|
func uidMapInUserNS(uidMap string) bool {
|
||||||
|
if uidMap == "" {
|
||||||
|
// File exist but empty (the initial state when userns is created,
|
||||||
|
// see user_namespaces(7)).
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var a, b, c int64
|
||||||
|
if _, err := fmt.Sscanf(uidMap, "%d %d %d", &a, &b, &c); err != nil {
|
||||||
|
// Assume we are in a regular, non user namespace.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// As per user_namespaces(7), /proc/self/uid_map of
|
||||||
|
// the initial user namespace shows 0 0 4294967295.
|
||||||
|
initNS := a == 0 && b == 0 && c == 4294967295
|
||||||
|
return !initNS
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
//go:build linux && gofuzz
|
||||||
|
|
||||||
|
package userns
|
||||||
|
|
||||||
|
func FuzzUIDMap(uidmap []byte) int {
|
||||||
|
_ = uidMapInUserNS(string(uidmap))
|
||||||
|
return 1
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package userns
|
||||||
|
|
||||||
|
// inUserNS is a stub for non-Linux systems. Always returns false.
|
||||||
|
func inUserNS() bool { return false }
|
|
@ -167,7 +167,6 @@ github.com/containerd/containerd/namespaces
|
||||||
github.com/containerd/containerd/pkg/dialer
|
github.com/containerd/containerd/pkg/dialer
|
||||||
github.com/containerd/containerd/pkg/randutil
|
github.com/containerd/containerd/pkg/randutil
|
||||||
github.com/containerd/containerd/pkg/seed
|
github.com/containerd/containerd/pkg/seed
|
||||||
github.com/containerd/containerd/pkg/userns
|
|
||||||
github.com/containerd/containerd/protobuf
|
github.com/containerd/containerd/protobuf
|
||||||
github.com/containerd/containerd/protobuf/types
|
github.com/containerd/containerd/protobuf/types
|
||||||
github.com/containerd/containerd/reference
|
github.com/containerd/containerd/reference
|
||||||
|
@ -204,8 +203,8 @@ github.com/containerd/platforms
|
||||||
# github.com/containerd/ttrpc v1.2.5
|
# github.com/containerd/ttrpc v1.2.5
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/containerd/ttrpc
|
github.com/containerd/ttrpc
|
||||||
# github.com/containerd/typeurl/v2 v2.1.1
|
# github.com/containerd/typeurl/v2 v2.2.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.21
|
||||||
github.com/containerd/typeurl/v2
|
github.com/containerd/typeurl/v2
|
||||||
# github.com/cpuguy83/go-md2man/v2 v2.0.4
|
# github.com/cpuguy83/go-md2man/v2 v2.0.4
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
|
@ -219,7 +218,7 @@ github.com/davecgh/go-spew/spew
|
||||||
# github.com/distribution/reference v0.6.0
|
# github.com/distribution/reference v0.6.0
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/distribution/reference
|
github.com/distribution/reference
|
||||||
# github.com/docker/cli v27.1.1+incompatible
|
# github.com/docker/cli v27.2.0+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/cli/cli
|
github.com/docker/cli/cli
|
||||||
github.com/docker/cli/cli-plugins/hooks
|
github.com/docker/cli/cli-plugins/hooks
|
||||||
|
@ -271,7 +270,7 @@ github.com/docker/distribution/registry/client/transport
|
||||||
github.com/docker/distribution/registry/storage/cache
|
github.com/docker/distribution/registry/storage/cache
|
||||||
github.com/docker/distribution/registry/storage/cache/memory
|
github.com/docker/distribution/registry/storage/cache/memory
|
||||||
github.com/docker/distribution/uuid
|
github.com/docker/distribution/uuid
|
||||||
# github.com/docker/docker v27.1.1+incompatible
|
# github.com/docker/docker v27.2.0+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/docker/api
|
github.com/docker/docker/api
|
||||||
github.com/docker/docker/api/types
|
github.com/docker/docker/api/types
|
||||||
|
@ -516,7 +515,7 @@ github.com/mitchellh/go-wordwrap
|
||||||
github.com/mitchellh/hashstructure/v2
|
github.com/mitchellh/hashstructure/v2
|
||||||
# github.com/mitchellh/mapstructure v1.5.0
|
# github.com/mitchellh/mapstructure v1.5.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
# github.com/moby/buildkit v0.15.1-0.20240810140024-664c2b469f19
|
# github.com/moby/buildkit v0.16.0-rc1
|
||||||
## explicit; go 1.21.0
|
## explicit; go 1.21.0
|
||||||
github.com/moby/buildkit/api/services/control
|
github.com/moby/buildkit/api/services/control
|
||||||
github.com/moby/buildkit/api/types
|
github.com/moby/buildkit/api/types
|
||||||
|
@ -612,18 +611,21 @@ github.com/moby/patternmatcher/ignorefile
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/moby/spdystream
|
github.com/moby/spdystream
|
||||||
github.com/moby/spdystream/spdy
|
github.com/moby/spdystream/spdy
|
||||||
# github.com/moby/sys/mountinfo v0.7.1
|
# github.com/moby/sys/mountinfo v0.7.2
|
||||||
## explicit; go 1.16
|
## explicit; go 1.17
|
||||||
github.com/moby/sys/mountinfo
|
github.com/moby/sys/mountinfo
|
||||||
# github.com/moby/sys/sequential v0.5.0
|
# github.com/moby/sys/sequential v0.5.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
github.com/moby/sys/sequential
|
github.com/moby/sys/sequential
|
||||||
# github.com/moby/sys/signal v0.7.0
|
# github.com/moby/sys/signal v0.7.1
|
||||||
## explicit; go 1.16
|
## explicit; go 1.17
|
||||||
github.com/moby/sys/signal
|
github.com/moby/sys/signal
|
||||||
# github.com/moby/sys/user v0.3.0
|
# github.com/moby/sys/user v0.3.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
github.com/moby/sys/user
|
github.com/moby/sys/user
|
||||||
|
# github.com/moby/sys/userns v0.1.0
|
||||||
|
## explicit; go 1.21
|
||||||
|
github.com/moby/sys/userns
|
||||||
# github.com/moby/term v0.5.0
|
# github.com/moby/term v0.5.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/moby/term
|
github.com/moby/term
|
||||||
|
|
Loading…
Reference in New Issue