mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00
Bump moby/buildkit
Signed-off-by: ulyssessouza <ulyssessouza@gmail.com>
This commit is contained in:
parent
3d630c6f7f
commit
3ff9abca3a
12
go.mod
12
go.mod
@ -14,8 +14,7 @@ require (
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible // indirect
|
||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect
|
||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e
|
||||
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect
|
||||
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf
|
||||
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190315220205-a8ed825ac853 // indirect
|
||||
github.com/docker/cli v1.14.0-0.20190523191156-ab688a9a79a1
|
||||
@ -32,6 +31,7 @@ require (
|
||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
||||
github.com/godbus/dbus v4.1.0+incompatible // indirect
|
||||
github.com/gofrs/flock v0.7.0
|
||||
github.com/gofrs/uuid v3.2.0+incompatible // indirect
|
||||
github.com/gogo/protobuf v1.2.1 // indirect
|
||||
@ -46,7 +46,6 @@ require (
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
|
||||
github.com/hashicorp/go-version v1.1.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0
|
||||
github.com/imdario/mergo v0.3.7 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/jinzhu/gorm v1.9.2 // indirect
|
||||
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a // indirect
|
||||
@ -58,7 +57,7 @@ require (
|
||||
github.com/mattn/go-sqlite3 v1.10.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/miekg/pkcs11 v0.0.0-20190322140431-074fd7a1ed19 // indirect
|
||||
github.com/moby/buildkit v0.6.2-0.20190921002054-ae10b292fefb
|
||||
github.com/moby/buildkit v0.6.2-0.20191022011428-4f4e03067523
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1
|
||||
@ -69,9 +68,8 @@ require (
|
||||
github.com/prometheus/client_golang v0.8.0 // indirect
|
||||
github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612 // indirect
|
||||
github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 // indirect
|
||||
github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be // indirect
|
||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002
|
||||
github.com/sirupsen/logrus v1.4.0
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/spf13/viper v1.3.2 // indirect
|
||||
@ -81,7 +79,7 @@ require (
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad // indirect
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // indirect
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
||||
gopkg.in/fatih/pool.v2 v2.0.0 // indirect
|
||||
|
68
go.sum
68
go.sum
@ -5,8 +5,8 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.13-0.20190408173621-84b4ab48a507 h1:QeteIkN4WmQcflYv2SINj79dlbN22KqsfZHZruD8JXw=
|
||||
github.com/Microsoft/go-winio v0.4.13-0.20190408173621-84b4ab48a507/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/hcsshim v0.8.5/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
@ -34,34 +34,33 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e h1:Qux+lbuMaRzkQyTdzgtz8MgzPtzmaPQy6DXmxpdxT3U=
|
||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/containerd/cgroups v0.0.0-20190226200435-dbea6f2bd416 h1:AaSMvkPaxfZD/OsDVBueAKzY5lnWAqLWgUivNg37WHA=
|
||||
github.com/containerd/cgroups v0.0.0-20190226200435-dbea6f2bd416/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 h1:6xW3ogNpFIly0umJGEKzFfGDNUk5rXFE1lJ3/gBmz3U=
|
||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
||||
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU=
|
||||
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e h1:GdiIYd8ZDOrT++e1NjhSD4rGt9zaJukHm4rt5F4mRQc=
|
||||
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
||||
github.com/containerd/containerd v1.2.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0 h1:enps1EZBEgR8QxwdrpsoSxcsCXWnMKchIQ/0dzC0eKw=
|
||||
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf h1:phUfu9w7+g1Vp149t3FThX2BmW+DkKkHj613PzZrQuU=
|
||||
github.com/containerd/containerd v1.4.0-0.20191014053712-acdcf13d5eaf/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/go-cni v0.0.0-20190610170741-5a4663dad645/go.mod h1:2wlRxCQdiBY+OcjNg5x8kI+5mEL1fGt25L4IzQHYJsM=
|
||||
github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c h1:KFbqHhDeaHM7IfFtXHfUHMDaUStpM2YwBR+iJCIOsKk=
|
||||
github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/go-cni v0.0.0-20190813230227-49fbd9b210f3/go.mod h1:2wlRxCQdiBY+OcjNg5x8kI+5mEL1fGt25L4IzQHYJsM=
|
||||
github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||
github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7 h1:SKDlsIhYxNE1LO0xwuOR+3QWj3zRibVQu5jWIMQmOfU=
|
||||
github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8 h1:jYCTS/16RWXXtVHNHo1KWNegd1kKQ7lHd7BStj/0hKw=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20 h1:14r0i3IeJj6zkNLigAJiv/TWSR8EY+pxIjv5tFiT+n8=
|
||||
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/containernetworking/cni v0.6.1-0.20180218032124-142cde0c766c/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a h1:W8b4lQ4tFF21aspRGoBuCNV6V2fFJBF+pm1J6OY8Lys=
|
||||
github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -111,6 +110,7 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/godbus/dbus v0.0.0-20181101234600-2ff6f7ffd60f/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
|
||||
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/gofrs/flock v0.7.0 h1:pGFUjl501gafK9HBt1VGL1KCOd/YhIooID+xgyJCf3g=
|
||||
@ -136,6 +136,8 @@ github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLm
|
||||
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9 h1:JM174NTeGNJ2m/oLH3UOWOvWQQKd+BoL3hcSCUWFLt0=
|
||||
@ -202,8 +204,8 @@ github.com/miekg/pkcs11 v0.0.0-20190322140431-074fd7a1ed19/go.mod h1:WCBAbTOdfhH
|
||||
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/buildkit v0.6.2-0.20190921002054-ae10b292fefb h1:enyviD1ZOxgo62sGpT2yQY1uTtruq84wYJPjFJwsbH0=
|
||||
github.com/moby/buildkit v0.6.2-0.20190921002054-ae10b292fefb/go.mod h1:JKVImCzxztxvULr5P6ZiBfA/B2P+ZpR6UHxOXQn4KiU=
|
||||
github.com/moby/buildkit v0.6.2-0.20191022011428-4f4e03067523 h1:9kOZqIXIAb7oJEx551SdaIl110iwEpRB4teHPTOjIHc=
|
||||
github.com/moby/buildkit v0.6.2-0.20191022011428-4f4e03067523/go.mod h1:x4qPeGh5UvnIcWVUO/byBE6pOEL8Ncy3tsK89Qt0D7A=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
@ -218,8 +220,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v1.0.0-rc6/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8 h1:dDCFes8Hj1r/i5qnypONo5jdOme/8HWZC/aNDyhECt0=
|
||||
github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190621203724-f4982d86f7fd h1:w9DJ/JL7fK4VjMoGo4e9gsq2xRhZThNI4PFuAwN8dJ0=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190621203724-f4982d86f7fd/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runtime-spec v0.0.0-20180909173843-eba862dc2470/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.1 h1:wY4pOY8fBdSIvs9+IDHC55thBuEulhzfSgKeC1yFvzQ=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
@ -241,15 +243,14 @@ github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612 h1:13pIdM2
|
||||
github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 h1:osmNoEW2SCW3L7EX0km2LYM8HKpNWRiouxjE3XHkyGc=
|
||||
github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be h1:MoyXp/VjXUwM0GyDcdwT7Ubea2gxOSHpPaFo3qV+Y2A=
|
||||
github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002 h1:ka9QPuQg2u4LGipiZGsgkg3rJCo4iIUCy75FddM0GRQ=
|
||||
github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc=
|
||||
github.com/sirupsen/logrus v1.0.3/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
@ -292,8 +293,8 @@ github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad/go.mod h1:5yf
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 h1:j2hhcujLRHAg872RWAV5yaUrEjHEObwDv3aImCaNLek=
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190129210102-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
@ -302,15 +303,21 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190303122642-d455e41777fc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
@ -320,12 +327,13 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZe
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
@ -349,7 +357,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.0.0-20180712090710-2d6f90ab1293 h1:hROmpFC7JMobXFXMmD7ZKZLhDKvr1IKfFJoYS/45G/8=
|
||||
k8s.io/api v0.0.0-20180712090710-2d6f90ab1293/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||
k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d h1:MZjlsu9igBoVPZkXpIGoxI6EonqNsXXZU7hhvfQLkd4=
|
||||
|
18
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
18
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
@ -16,6 +16,7 @@ import (
|
||||
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
|
||||
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
|
||||
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
|
||||
//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
|
||||
|
||||
type atomicBool int32
|
||||
|
||||
@ -79,6 +80,7 @@ type win32File struct {
|
||||
wg sync.WaitGroup
|
||||
wgLock sync.RWMutex
|
||||
closing atomicBool
|
||||
socket bool
|
||||
readDeadline deadlineHandler
|
||||
writeDeadline deadlineHandler
|
||||
}
|
||||
@ -109,7 +111,13 @@ func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||
}
|
||||
|
||||
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||
return makeWin32File(h)
|
||||
// If we return the result of makeWin32File directly, it can result in an
|
||||
// interface-wrapped nil, rather than a nil interface value.
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// closeHandle closes the resources associated with a Win32 handle
|
||||
@ -190,6 +198,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er
|
||||
if f.closing.isSet() {
|
||||
err = ErrFileClosed
|
||||
}
|
||||
} else if err != nil && f.socket {
|
||||
// err is from Win32. Query the overlapped structure to get the winsock error.
|
||||
var bytes, flags uint32
|
||||
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
|
||||
}
|
||||
case <-timeout:
|
||||
cancelIoEx(f.handle, &c.o)
|
||||
@ -265,6 +277,10 @@ func (f *win32File) Flush() error {
|
||||
return syscall.FlushFileBuffers(f.handle)
|
||||
}
|
||||
|
||||
func (f *win32File) Fd() uintptr {
|
||||
return uintptr(f.handle)
|
||||
}
|
||||
|
||||
func (d *deadlineHandler) set(deadline time.Time) error {
|
||||
d.setLock.Lock()
|
||||
defer d.setLock.Unlock()
|
||||
|
9
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
Normal file
9
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
module github.com/Microsoft/go-winio
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b
|
||||
)
|
16
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
Normal file
16
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
305
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
Normal file
305
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
Normal file
@ -0,0 +1,305 @@
|
||||
package winio
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
|
||||
|
||||
const (
|
||||
afHvSock = 34 // AF_HYPERV
|
||||
|
||||
socketError = ^uintptr(0)
|
||||
)
|
||||
|
||||
// An HvsockAddr is an address for a AF_HYPERV socket.
|
||||
type HvsockAddr struct {
|
||||
VMID guid.GUID
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
type rawHvsockAddr struct {
|
||||
Family uint16
|
||||
_ uint16
|
||||
VMID guid.GUID
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
// Network returns the address's network name, "hvsock".
|
||||
func (addr *HvsockAddr) Network() string {
|
||||
return "hvsock"
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) String() string {
|
||||
return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID)
|
||||
}
|
||||
|
||||
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
|
||||
func VsockServiceID(port uint32) guid.GUID {
|
||||
g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
|
||||
g.Data1 = port
|
||||
return g
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) raw() rawHvsockAddr {
|
||||
return rawHvsockAddr{
|
||||
Family: afHvSock,
|
||||
VMID: addr.VMID,
|
||||
ServiceID: addr.ServiceID,
|
||||
}
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
|
||||
addr.VMID = raw.VMID
|
||||
addr.ServiceID = raw.ServiceID
|
||||
}
|
||||
|
||||
// HvsockListener is a socket listener for the AF_HYPERV address family.
|
||||
type HvsockListener struct {
|
||||
sock *win32File
|
||||
addr HvsockAddr
|
||||
}
|
||||
|
||||
// HvsockConn is a connected socket of the AF_HYPERV address family.
|
||||
type HvsockConn struct {
|
||||
sock *win32File
|
||||
local, remote HvsockAddr
|
||||
}
|
||||
|
||||
func newHvSocket() (*win32File, error) {
|
||||
fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
f, err := makeWin32File(fd)
|
||||
if err != nil {
|
||||
syscall.Close(fd)
|
||||
return nil, err
|
||||
}
|
||||
f.socket = true
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// ListenHvsock listens for connections on the specified hvsock address.
|
||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
||||
l := &HvsockListener{addr: *addr}
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", err)
|
||||
}
|
||||
sa := addr.raw()
|
||||
err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
||||
}
|
||||
err = syscall.Listen(sock.handle, 16)
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("listen", err))
|
||||
}
|
||||
return &HvsockListener{sock: sock, addr: *addr}, nil
|
||||
}
|
||||
|
||||
func (l *HvsockListener) opErr(op string, err error) error {
|
||||
return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err}
|
||||
}
|
||||
|
||||
// Addr returns the listener's network address.
|
||||
func (l *HvsockListener) Addr() net.Addr {
|
||||
return &l.addr
|
||||
}
|
||||
|
||||
// Accept waits for the next connection and returns it.
|
||||
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := l.sock.prepareIo()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer l.sock.wg.Done()
|
||||
|
||||
// AcceptEx, per documentation, requires an extra 16 bytes per address.
|
||||
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
|
||||
var addrbuf [addrlen * 2]byte
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
|
||||
_, err = l.sock.asyncIo(c, nil, bytes, err)
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
}
|
||||
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
|
||||
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Close closes the listener, causing any pending Accept calls to fail.
|
||||
func (l *HvsockListener) Close() error {
|
||||
return l.sock.Close()
|
||||
}
|
||||
|
||||
/* Need to finish ConnectEx handling
|
||||
func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := sock.prepareIo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer sock.wg.Done()
|
||||
var bytes uint32
|
||||
err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
|
||||
_, err = sock.asyncIo(ctx, c, nil, bytes, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
remote: *addr,
|
||||
}
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (conn *HvsockConn) opErr(op string, err error) error {
|
||||
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("read", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var flags, bytes uint32
|
||||
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsarecv", err)
|
||||
}
|
||||
return 0, conn.opErr("read", err)
|
||||
} else if n == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Write(b []byte) (int, error) {
|
||||
t := 0
|
||||
for len(b) != 0 {
|
||||
n, err := conn.write(b)
|
||||
if err != nil {
|
||||
return t + n, err
|
||||
}
|
||||
t += n
|
||||
b = b[n:]
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var bytes uint32
|
||||
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsasend", err)
|
||||
}
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the socket connection, failing any pending read or write calls.
|
||||
func (conn *HvsockConn) Close() error {
|
||||
return conn.sock.Close()
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) shutdown(how int) error {
|
||||
err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("shutdown", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseRead shuts down the read end of the socket.
|
||||
func (conn *HvsockConn) CloseRead() error {
|
||||
err := conn.shutdown(syscall.SHUT_RD)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseWrite shuts down the write end of the socket, notifying the other endpoint that
|
||||
// no more data will be written.
|
||||
func (conn *HvsockConn) CloseWrite() error {
|
||||
err := conn.shutdown(syscall.SHUT_WR)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LocalAddr returns the local address of the connection.
|
||||
func (conn *HvsockConn) LocalAddr() net.Addr {
|
||||
return &conn.local
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote address of the connection.
|
||||
func (conn *HvsockConn) RemoteAddr() net.Addr {
|
||||
return &conn.remote
|
||||
}
|
||||
|
||||
// SetDeadline implements the net.Conn SetDeadline method.
|
||||
func (conn *HvsockConn) SetDeadline(t time.Time) error {
|
||||
conn.SetReadDeadline(t)
|
||||
conn.SetWriteDeadline(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetReadDeadline implements the net.Conn SetReadDeadline method.
|
||||
func (conn *HvsockConn) SetReadDeadline(t time.Time) error {
|
||||
return conn.sock.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
|
||||
func (conn *HvsockConn) SetWriteDeadline(t time.Time) error {
|
||||
return conn.sock.SetWriteDeadline(t)
|
||||
}
|
235
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
Normal file
235
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
// Package guid provides a GUID type. The backing structure for a GUID is
|
||||
// identical to that used by the golang.org/x/sys/windows GUID type.
|
||||
// There are two main binary encodings used for a GUID, the big-endian encoding,
|
||||
// and the Windows (mixed-endian) encoding. See here for details:
|
||||
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
|
||||
package guid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// Variant specifies which GUID variant (or "type") of the GUID. It determines
|
||||
// how the entirety of the rest of the GUID is interpreted.
|
||||
type Variant uint8
|
||||
|
||||
// The variants specified by RFC 4122.
|
||||
const (
|
||||
// VariantUnknown specifies a GUID variant which does not conform to one of
|
||||
// the variant encodings specified in RFC 4122.
|
||||
VariantUnknown Variant = iota
|
||||
VariantNCS
|
||||
VariantRFC4122
|
||||
VariantMicrosoft
|
||||
VariantFuture
|
||||
)
|
||||
|
||||
// Version specifies how the bits in the GUID were generated. For instance, a
|
||||
// version 4 GUID is randomly generated, and a version 5 is generated from the
|
||||
// hash of an input string.
|
||||
type Version uint8
|
||||
|
||||
var _ = (encoding.TextMarshaler)(GUID{})
|
||||
var _ = (encoding.TextUnmarshaler)(&GUID{})
|
||||
|
||||
// GUID represents a GUID/UUID. It has the same structure as
|
||||
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
|
||||
// that type. It is defined as its own type so that stringification and
|
||||
// marshaling can be supported. The representation matches that used by native
|
||||
// Windows code.
|
||||
type GUID windows.GUID
|
||||
|
||||
// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
|
||||
func NewV4() (GUID, error) {
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return GUID{}, err
|
||||
}
|
||||
|
||||
g := FromArray(b)
|
||||
g.setVersion(4) // Version 4 means randomly generated.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
|
||||
// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
|
||||
// and the sample code treats it as a series of bytes, so we do the same here.
|
||||
//
|
||||
// Some implementations, such as those found on Windows, treat the name as a
|
||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
||||
// encoded as such before being passed to this function.
|
||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
||||
b := sha1.New()
|
||||
namespaceBytes := namespace.ToArray()
|
||||
b.Write(namespaceBytes[:])
|
||||
b.Write(name)
|
||||
|
||||
a := [16]byte{}
|
||||
copy(a[:], b.Sum(nil))
|
||||
|
||||
g := FromArray(a)
|
||||
g.setVersion(5) // Version 5 means generated from a string.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
|
||||
var g GUID
|
||||
g.Data1 = order.Uint32(b[0:4])
|
||||
g.Data2 = order.Uint16(b[4:6])
|
||||
g.Data3 = order.Uint16(b[6:8])
|
||||
copy(g.Data4[:], b[8:16])
|
||||
return g
|
||||
}
|
||||
|
||||
func (g GUID) toArray(order binary.ByteOrder) [16]byte {
|
||||
b := [16]byte{}
|
||||
order.PutUint32(b[0:4], g.Data1)
|
||||
order.PutUint16(b[4:6], g.Data2)
|
||||
order.PutUint16(b[6:8], g.Data3)
|
||||
copy(b[8:16], g.Data4[:])
|
||||
return b
|
||||
}
|
||||
|
||||
// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
|
||||
func FromArray(b [16]byte) GUID {
|
||||
return fromArray(b, binary.BigEndian)
|
||||
}
|
||||
|
||||
// ToArray returns an array of 16 bytes representing the GUID in big-endian
|
||||
// encoding.
|
||||
func (g GUID) ToArray() [16]byte {
|
||||
return g.toArray(binary.BigEndian)
|
||||
}
|
||||
|
||||
// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
|
||||
func FromWindowsArray(b [16]byte) GUID {
|
||||
return fromArray(b, binary.LittleEndian)
|
||||
}
|
||||
|
||||
// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
|
||||
// encoding.
|
||||
func (g GUID) ToWindowsArray() [16]byte {
|
||||
return g.toArray(binary.LittleEndian)
|
||||
}
|
||||
|
||||
func (g GUID) String() string {
|
||||
return fmt.Sprintf(
|
||||
"%08x-%04x-%04x-%04x-%012x",
|
||||
g.Data1,
|
||||
g.Data2,
|
||||
g.Data3,
|
||||
g.Data4[:2],
|
||||
g.Data4[2:])
|
||||
}
|
||||
|
||||
// FromString parses a string containing a GUID and returns the GUID. The only
|
||||
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
|
||||
// format.
|
||||
func FromString(s string) (GUID, error) {
|
||||
if len(s) != 36 {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
|
||||
var g GUID
|
||||
|
||||
data1, err := strconv.ParseUint(s[0:8], 16, 32)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data1 = uint32(data1)
|
||||
|
||||
data2, err := strconv.ParseUint(s[9:13], 16, 16)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data2 = uint16(data2)
|
||||
|
||||
data3, err := strconv.ParseUint(s[14:18], 16, 16)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data3 = uint16(data3)
|
||||
|
||||
for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
|
||||
v, err := strconv.ParseUint(s[x:x+2], 16, 8)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data4[i] = uint8(v)
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *GUID) setVariant(v Variant) {
|
||||
d := g.Data4[0]
|
||||
switch v {
|
||||
case VariantNCS:
|
||||
d = (d & 0x7f)
|
||||
case VariantRFC4122:
|
||||
d = (d & 0x3f) | 0x80
|
||||
case VariantMicrosoft:
|
||||
d = (d & 0x1f) | 0xc0
|
||||
case VariantFuture:
|
||||
d = (d & 0x0f) | 0xe0
|
||||
case VariantUnknown:
|
||||
fallthrough
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid variant: %d", v))
|
||||
}
|
||||
g.Data4[0] = d
|
||||
}
|
||||
|
||||
// Variant returns the GUID variant, as defined in RFC 4122.
|
||||
func (g GUID) Variant() Variant {
|
||||
b := g.Data4[0]
|
||||
if b&0x80 == 0 {
|
||||
return VariantNCS
|
||||
} else if b&0xc0 == 0x80 {
|
||||
return VariantRFC4122
|
||||
} else if b&0xe0 == 0xc0 {
|
||||
return VariantMicrosoft
|
||||
} else if b&0xe0 == 0xe0 {
|
||||
return VariantFuture
|
||||
}
|
||||
return VariantUnknown
|
||||
}
|
||||
|
||||
func (g *GUID) setVersion(v Version) {
|
||||
g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
|
||||
}
|
||||
|
||||
// Version returns the GUID version, as defined in RFC 4122.
|
||||
func (g GUID) Version() Version {
|
||||
return Version((g.Data3 & 0xF000) >> 12)
|
||||
}
|
||||
|
||||
// MarshalText returns the textual representation of the GUID.
|
||||
func (g GUID) MarshalText() ([]byte, error) {
|
||||
return []byte(g.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText takes the textual representation of a GUID, and unmarhals it
|
||||
// into this GUID.
|
||||
func (g *GUID) UnmarshalText(text []byte) error {
|
||||
g2, err := FromString(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*g = g2
|
||||
return nil
|
||||
}
|
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
2
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
@ -1,3 +1,3 @@
|
||||
package winio
|
||||
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go
|
||||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
||||
|
33
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
33
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
@ -38,6 +38,7 @@ func errnoErr(e syscall.Errno) error {
|
||||
|
||||
var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
|
||||
@ -45,6 +46,7 @@ var (
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
@ -73,6 +75,7 @@ var (
|
||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||
procBackupRead = modkernel32.NewProc("BackupRead")
|
||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
)
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
@ -124,6 +127,24 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro
|
||||
return
|
||||
}
|
||||
|
||||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
@ -527,3 +548,15 @@ func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, p
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
6
vendor/github.com/containerd/containerd/.appveyor.yml
generated
vendored
6
vendor/github.com/containerd/containerd/.appveyor.yml
generated
vendored
@ -12,7 +12,7 @@ environment:
|
||||
GOPATH: C:\gopath
|
||||
CGO_ENABLED: 1
|
||||
matrix:
|
||||
- GO_VERSION: 1.12.1
|
||||
- GO_VERSION: 1.12.10
|
||||
|
||||
before_build:
|
||||
- choco install -y mingw --version 5.3.0
|
||||
@ -54,9 +54,9 @@ test_script:
|
||||
# TODO: need an equivalent of TRAVIS_COMMIT_RANGE
|
||||
# - GIT_CHECK_EXCLUDE="./vendor" TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE/.../..}" C:\MinGW\bin\mingw32-make.exe dco
|
||||
- bash.exe -lc "export PATH=/c/tools/mingw64/bin:/c/gopath/src/github.com/containerd/containerd/bin:$PATH ; mingw32-make.exe coverage root-coverage"
|
||||
- bash.exe -elc "export PATH=/c/tools/mingw64/bin:/c/gopath/src/github.com/containerd/containerd/bin:$PATH ; mingw32-make.exe integration"
|
||||
# - bash.exe -elc "export PATH=/c/tools/mingw64/bin:/c/gopath/src/github.com/containerd/containerd/bin:$PATH ; mingw32-make.exe integration"
|
||||
# Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
|
||||
- bash.exe -elc "export PATH=/c/tools/mingw64/bin:/c/gopath/src/github.com/containerd/containerd/bin:$PATH; TESTFLAGS_PARALLEL=1 mingw32-make.exe integration"
|
||||
# - bash.exe -elc "export PATH=/c/tools/mingw64/bin:/c/gopath/src/github.com/containerd/containerd/bin:$PATH; TESTFLAGS_PARALLEL=1 mingw32-make.exe integration"
|
||||
|
||||
on_success:
|
||||
codecov --flag windows -f coverage.txt
|
||||
|
23
vendor/github.com/containerd/containerd/.golangci.yml
generated
vendored
Normal file
23
vendor/github.com/containerd/containerd/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
linters:
|
||||
enable:
|
||||
- structcheck
|
||||
- varcheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- gofmt
|
||||
- goimports
|
||||
- golint
|
||||
- ineffassign
|
||||
- vet
|
||||
- unused
|
||||
- misspell
|
||||
disable:
|
||||
- errcheck
|
||||
|
||||
run:
|
||||
deadline: 2m
|
||||
skip-dirs:
|
||||
- api
|
||||
- design
|
||||
- docs
|
||||
- docs/man
|
23
vendor/github.com/containerd/containerd/.gometalinter.json
generated
vendored
23
vendor/github.com/containerd/containerd/.gometalinter.json
generated
vendored
@ -1,23 +0,0 @@
|
||||
{
|
||||
"Vendor": true,
|
||||
"Deadline": "2m",
|
||||
"Sort": ["linter", "severity", "path", "line"],
|
||||
"Exclude": [
|
||||
".*\\.pb\\.go",
|
||||
"fetch\\.go:.*::error: unrecognized printf verb 'r'"
|
||||
],
|
||||
"EnableGC": true,
|
||||
|
||||
"Enable": [
|
||||
"structcheck",
|
||||
"varcheck",
|
||||
"staticcheck",
|
||||
"unconvert",
|
||||
|
||||
"gofmt",
|
||||
"goimports",
|
||||
"golint",
|
||||
"ineffassign",
|
||||
"vet"
|
||||
]
|
||||
}
|
77
vendor/github.com/containerd/containerd/.mailmap
generated
vendored
77
vendor/github.com/containerd/containerd/.mailmap
generated
vendored
@ -1,28 +1,49 @@
|
||||
Abhinandan Prativadi <abhi@docker.com> Abhinandan Prativadi <aprativadi@gmail.com>
|
||||
Abhinandan Prativadi <abhi@docker.com> abhi <abhi@docker.com>
|
||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> Akihiro Suda <suda.kyoto@gmail.com>
|
||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
|
||||
Andrei Vagin <avagin@virtuozzo.com> Andrei Vagin <avagin@openvz.org>
|
||||
Brent Baude <bbaude@redhat.com> baude <bbaude@redhat.com>
|
||||
Frank Yang <yyb196@gmail.com> frank yang <yyb196@gmail.com>
|
||||
Georgia Panoutsakopoulou <gpanoutsak@gmail.com> gpanouts <gpanoutsak@gmail.com>
|
||||
Jie Zhang <iamkadisi@163.com> kadisi <iamkadisi@163.com>
|
||||
John Howard <john.howard@microsoft.com> John Howard <jhoward@microsoft.com>
|
||||
Justin Terry <juterry@microsoft.com> Justin Terry (VM) <juterry@microsoft.com>
|
||||
Justin Terry <juterry@microsoft.com> Justin <jterry75@users.noreply.github.com>
|
||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com> Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
|
||||
Kevin Xu <cming.xu@gmail.com> kevin.xu <cming.xu@gmail.com>
|
||||
Lu Jingxiao <lujingxiao@huawei.com> l00397676 <lujingxiao@huawei.com>
|
||||
Lantao Liu <lantaol@google.com> Lantao Liu <taotaotheripper@gmail.com>
|
||||
Phil Estes <estesp@gmail.com> Phil Estes <estesp@linux.vnet.ibm.com>
|
||||
Stephen J Day <stevvooe@gmail.com> Stephen J Day <stephen.day@docker.com>
|
||||
Stephen J Day <stevvooe@gmail.com> Stephen Day <stevvooe@users.noreply.github.com>
|
||||
Stephen J Day <stevvooe@gmail.com> Stephen Day <stephen.day@getcruise.com>
|
||||
Sudeesh John <sudeesh@linux.vnet.ibm.com> sudeesh john <sudeesh@linux.vnet.ibm.com>
|
||||
Tõnis Tiigi <tonistiigi@gmail.com> Tonis Tiigi <tonistiigi@gmail.com>
|
||||
Lifubang <lifubang@aliyun.com> Lifubang <lifubang@acmcoder.com>
|
||||
Xiaodong Zhang <a4012017@sina.com> nashasha1 <a4012017@sina.com>
|
||||
Jian Liao <jliao@alauda.io> liaoj <jliao@alauda.io>
|
||||
Jian Liao <jliao@alauda.io> liaojian <liaojian@Dabllo.local>
|
||||
Rui Cao <ruicao@alauda.io> ruicao <ruicao@alauda.io>
|
||||
Xuean Yan <yan.xuean@zte.com.cn> yanxuean <yan.xuean@zte.com.cn>
|
||||
Abhinandan Prativadi <abhi@docker.com>
|
||||
Abhinandan Prativadi <abhi@docker.com> <aprativadi@gmail.com>
|
||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.akihiro@lab.ntt.co.jp>
|
||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.kyoto@gmail.com>
|
||||
Andrei Vagin <avagin@virtuozzo.com> <avagin@openvz.org>
|
||||
Andrey Kolomentsev <andrey.kolomentsev@gmail.com>
|
||||
Brent Baude <bbaude@redhat.com>
|
||||
Carlos Eduardo <me@carlosedp.com> <me@carlosedp.com>
|
||||
Eric Ren <renzhen.rz@alibaba-linux.com> <renzhen.rz@alibaba-inc.com>
|
||||
Frank Yang <yyb196@gmail.com>
|
||||
Georgia Panoutsakopoulou <gpanoutsak@gmail.com>
|
||||
Guangming Wang <guangming.wang@daocloud.io>
|
||||
Haiyan Meng <haiyanmeng@google.com>
|
||||
Jian Liao <jliao@alauda.io>
|
||||
Jian Liao <jliao@alauda.io> <liaojian@Dabllo.local>
|
||||
Ji'an Liu <anthonyliu@zju.edu.cn>
|
||||
Jie Zhang <iamkadisi@163.com>
|
||||
John Howard <john.howard@microsoft.com> <jhoward@microsoft.com>
|
||||
John Howard <john.howard@microsoft.com> <jhowardmsft@users.noreply.github.com>
|
||||
Julien Balestra <julien.balestra@datadoghq.com>
|
||||
Justin Cormack <justin.cormack@docker.com> <justin@specialbusservice.com>
|
||||
Justin Terry <juterry@microsoft.com>
|
||||
Justin Terry <juterry@microsoft.com> <jterry75@users.noreply.github.com>
|
||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||
Kevin Xu <cming.xu@gmail.com>
|
||||
Lantao Liu <lantaol@google.com> <taotaotheripper@gmail.com>
|
||||
Lifubang <lifubang@aliyun.com> <lifubang@acmcoder.com>
|
||||
Lu Jingxiao <lujingxiao@huawei.com>
|
||||
Maksym Pavlenko <makpav@amazon.com> <pavlenko.maksym@gmail.com>
|
||||
Mark Gordon <msg555@gmail.com>
|
||||
Michael Katsoulis <michaelkatsoulis88@gmail.com>
|
||||
Mike Brown <brownwm@us.ibm.com> <mikebrow@users.noreply.github.com>
|
||||
Nishchay Kumar <mrawesomenix@gmail.com>
|
||||
Phil Estes <estesp@gmail.com> <estesp@linux.vnet.ibm.com>
|
||||
Rui Cao <ruicao@alauda.io> <ruicao@alauda.io>
|
||||
Stephen J Day <stevvooe@gmail.com> <stephen.day@getcruise.com>
|
||||
Stephen J Day <stevvooe@gmail.com> <stevvooe@users.noreply.github.com>
|
||||
Stephen J Day <stevvooe@gmail.com> <stephen.day@docker.com>
|
||||
Sudeesh John <sudeesh@linux.vnet.ibm.com>
|
||||
Su Fei <fesu@ebay.com> <fesu@ebay.com>
|
||||
Tõnis Tiigi <tonistiigi@gmail.com>
|
||||
Wei Fu <fuweid89@gmail.com> <fhfuwei@163.com>
|
||||
Xiaodong Zhang <a4012017@sina.com>
|
||||
Xuean Yan <yan.xuean@zte.com.cn>
|
||||
Yuxing Liu <starnop@163.com>
|
||||
zhenguang zhu <zhengguang.zhu@daocloud.io>
|
||||
zhongming chang<zhongming.chang@daocloud.io>
|
||||
zhoulin xie <zhoulin.xie@daocloud.io>
|
||||
zhoulin xie <zhoulin.xie@daocloud.io> <42261994+JoeWrightss@users.noreply.github.com>
|
||||
|
80
vendor/github.com/containerd/containerd/.travis.yml
generated
vendored
80
vendor/github.com/containerd/containerd/.travis.yml
generated
vendored
@ -1,4 +1,4 @@
|
||||
dist: xenial
|
||||
dist: bionic
|
||||
sudo: required
|
||||
# setup travis so that we can run containers for integration tests
|
||||
services:
|
||||
@ -6,8 +6,25 @@ services:
|
||||
|
||||
language: go
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
go:
|
||||
- "1.11.x"
|
||||
- "1.12.x"
|
||||
|
||||
env:
|
||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v1 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
|
||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic TRAVIS_RELEASE=yes
|
||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
|
||||
- TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Skip testing previous LTS (Xenial / Ubuntu 16.04 LTS) on pull requests
|
||||
- if: type != pull_request
|
||||
os: linux
|
||||
dist: xenial
|
||||
env: TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=xenial
|
||||
|
||||
go_import_path: github.com/containerd/containerd
|
||||
|
||||
@ -22,16 +39,9 @@ addons:
|
||||
- python-minimal
|
||||
- libcap-dev
|
||||
- libaio-dev
|
||||
- libprotobuf-c0-dev
|
||||
- libprotobuf-c-dev
|
||||
- libprotobuf-dev
|
||||
- socat
|
||||
- libseccomp-dev
|
||||
|
||||
env:
|
||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v1 TRAVIS_CGO_ENABLED=1
|
||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1
|
||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1
|
||||
- TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0
|
||||
|
||||
before_install:
|
||||
- uname -r
|
||||
@ -45,12 +55,13 @@ install:
|
||||
- go get -u github.com/vbatts/git-validation
|
||||
- go get -u github.com/kunalkushwaha/ltag
|
||||
- go get -u github.com/LK4D4/vndr
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-seccomp ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-runc ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-cni ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-critools ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then wget https://github.com/checkpoint-restore/criu/archive/v3.7.tar.gz -O /tmp/criu.tar.gz ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then wget https://github.com/checkpoint-restore/criu/archive/v3.12.tar.gz -O /tmp/criu.tar.gz ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then tar -C /tmp/ -zxf /tmp/criu.tar.gz ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then cd /tmp/criu-3.7 && sudo make install-criu ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then cd /tmp/criu-3.12 && sudo make install-criu ; fi
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
|
||||
before_script:
|
||||
@ -61,21 +72,22 @@ script:
|
||||
- export CGO_ENABLED=$TRAVIS_CGO_ENABLED
|
||||
- DCO_VERBOSITY=-q ../project/script/validate/dco
|
||||
- ../project/script/validate/fileheader ../project/
|
||||
- ../project/script/validate/vendor
|
||||
- travis_wait ../project/script/validate/vendor
|
||||
- GOOS=linux script/setup/install-dev-tools
|
||||
- go build -i .
|
||||
- make check
|
||||
- if [ "$GOOS" = "linux" ]; then make check-protos check-api-descriptors; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then make man ; fi
|
||||
- make build
|
||||
- make binaries
|
||||
- if [ "$GOOS" = "linux" ]; then sudo make install ; fi
|
||||
- if [ "$GOOS" = "linux" ]; then make coverage ; fi
|
||||
- if [ "$GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi
|
||||
- if [ "$GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make integration ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo make install ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then make coverage ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make integration ; fi
|
||||
# Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
|
||||
- if [ "$GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH TESTFLAGS_PARALLEL=1 make integration ; fi
|
||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH TESTFLAGS_PARALLEL=1 make integration ; fi
|
||||
- |
|
||||
if [ "$GOOS" = "linux" ]; then
|
||||
if [ "$TRAVIS_GOOS" = "linux" ]; then
|
||||
sudo mkdir -p /etc/containerd
|
||||
sudo bash -c "cat > /etc/containerd/config.toml <<EOF
|
||||
[plugins.cri.containerd.default_runtime]
|
||||
@ -95,15 +107,25 @@ after_success:
|
||||
- bash <(curl -s https://codecov.io/bash) -F linux
|
||||
|
||||
before_deploy:
|
||||
- make release
|
||||
- if [ "$TRAVIS_RELEASE" = "yes" ]; then make release cri-release; fi
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: HO+WSIVVUMMsbU74x+YyFsTP3ahqnR4xjwKAziedJ5lZXKJszQBhiYTFmcTeVBoouNjTISd07GQzpoLChuGC20U3+1NbT+CkK8xWR/x1ao2D3JY3Ds6AD9ubWRNWRLptt/xOn5Vq3F8xZyUYchwvDMl4zKCuTKxQGVdHKsINb2DehKcP5cVL6MMvqzEdfj2g99vqXAqs8uuo6dOmvxmHV43bfzDaAJSabjZZs6TKlWTqCQMet8uxyx2Dmjl2lxLwdqv12oJdrszacasn41NYuEyHI2bXyef1mhWGYN4n9bU/Y5winctZ8DOSOZvYg/2ziAaUN0+CTn1IESwVesrPz23P2Sy7wdLxu8dSIZ2yUHl7OsA5T5a5rDchAGguRVNBWvoGtuepEhdRacxTQUo1cMFZsEXjgRKKjdfc1emYQPVdN8mBv8GJwndty473ZXdvFt5R0kNVFtvWuYCa6UYJD2cKrsPSAfbZCDC/LiR3FOoTaUPMZUVkR2ACEO7Dn4+KlmBajqT40Osk/A7k1XA/TzVhMIpLtE0Vk2DfPmGsjCv8bC+MFd+R2Sc8SFdE92oEWRdoPQY5SxMYQtGxA+cbKVlT1kSw6y80yEbx5JZsBnT6+NTHwmDO3kVU9ztLdawOozTElKNAK8HoAyFmzIZ3wL64oThuDrv/TUuY8Iyn814=
|
||||
file_glob: true
|
||||
file: releases/*.tar.gz
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: containerd/containerd
|
||||
tags: true
|
||||
- provider: releases
|
||||
api_key:
|
||||
secure: HO+WSIVVUMMsbU74x+YyFsTP3ahqnR4xjwKAziedJ5lZXKJszQBhiYTFmcTeVBoouNjTISd07GQzpoLChuGC20U3+1NbT+CkK8xWR/x1ao2D3JY3Ds6AD9ubWRNWRLptt/xOn5Vq3F8xZyUYchwvDMl4zKCuTKxQGVdHKsINb2DehKcP5cVL6MMvqzEdfj2g99vqXAqs8uuo6dOmvxmHV43bfzDaAJSabjZZs6TKlWTqCQMet8uxyx2Dmjl2lxLwdqv12oJdrszacasn41NYuEyHI2bXyef1mhWGYN4n9bU/Y5winctZ8DOSOZvYg/2ziAaUN0+CTn1IESwVesrPz23P2Sy7wdLxu8dSIZ2yUHl7OsA5T5a5rDchAGguRVNBWvoGtuepEhdRacxTQUo1cMFZsEXjgRKKjdfc1emYQPVdN8mBv8GJwndty473ZXdvFt5R0kNVFtvWuYCa6UYJD2cKrsPSAfbZCDC/LiR3FOoTaUPMZUVkR2ACEO7Dn4+KlmBajqT40Osk/A7k1XA/TzVhMIpLtE0Vk2DfPmGsjCv8bC+MFd+R2Sc8SFdE92oEWRdoPQY5SxMYQtGxA+cbKVlT1kSw6y80yEbx5JZsBnT6+NTHwmDO3kVU9ztLdawOozTElKNAK8HoAyFmzIZ3wL64oThuDrv/TUuY8Iyn814=
|
||||
file_glob: true
|
||||
file:
|
||||
- releases/*.tar.gz
|
||||
- releases/*.tar.gz.sha256sum
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: containerd/containerd
|
||||
tags: true
|
||||
condition: $TRAVIS_GOOS = linux
|
||||
- provider: script
|
||||
script: bash script/release/deploy-cri
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: containerd/containerd
|
||||
tags: true
|
||||
condition: $TRAVIS_GOOS = linux
|
||||
|
14
vendor/github.com/containerd/containerd/.zuul.yaml
generated
vendored
Normal file
14
vendor/github.com/containerd/containerd/.zuul.yaml
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
- project:
|
||||
name: containerd/containerd
|
||||
check:
|
||||
jobs:
|
||||
- containerd-build-arm64
|
||||
|
||||
- job:
|
||||
name: containerd-build-arm64
|
||||
parent: init-test
|
||||
description: |
|
||||
Containerd build in openlab cluster.
|
||||
run: .zuul/playbooks/containerd-build/run.yaml
|
||||
nodeset: ubuntu-xenial-arm64
|
||||
voting: false
|
40
vendor/github.com/containerd/containerd/Makefile
generated
vendored
40
vendor/github.com/containerd/containerd/Makefile
generated
vendored
@ -17,7 +17,7 @@
|
||||
ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
# Base path used to install.
|
||||
DESTDIR=/usr/local
|
||||
DESTDIR ?= /usr/local
|
||||
|
||||
# Used to populate variables in version package.
|
||||
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
|
||||
@ -111,17 +111,17 @@ GO_GCFLAGS=$(shell \
|
||||
BINARIES=$(addprefix bin/,$(COMMANDS))
|
||||
|
||||
# Flags passed to `go test`
|
||||
TESTFLAGS ?= -v $(TESTFLAGS_RACE)
|
||||
TESTFLAGS ?= $(TESTFLAGS_RACE)
|
||||
TESTFLAGS_PARALLEL ?= 8
|
||||
|
||||
.PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install uninstall vendor release mandir install-man
|
||||
.PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install uninstall vendor release mandir install-man genman
|
||||
.DEFAULT: default
|
||||
|
||||
all: binaries
|
||||
|
||||
check: proto-fmt ## run all linters
|
||||
@echo "$(WHALE) $@"
|
||||
gometalinter --config .gometalinter.json ./...
|
||||
GOGC=75 golangci-lint run
|
||||
|
||||
ci: check binaries checkprotos coverage coverage-integration ## to be used by the CI
|
||||
|
||||
@ -194,10 +194,6 @@ bin/containerd-shim-runc-v2: cmd/containerd-shim-runc-v2 FORCE # set !cgo and om
|
||||
@echo "$(WHALE) bin/containerd-shim-runc-v2"
|
||||
@CGO_ENABLED=0 go build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runc-v2 ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v2
|
||||
|
||||
bin/containerd-shim-runhcs-v1: cmd/containerd-shim-runhcs-v1 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220
|
||||
@echo "$(WHALE) bin/containerd-shim-runhcs-v1${BINARY_SUFFIX}"
|
||||
@CGO_ENABLED=0 go build ${GO_BUILD_FLAGS} -o bin/containerd-shim-runhcs-v1${BINARY_SUFFIX} ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runhcs-v1
|
||||
|
||||
binaries: $(BINARIES) ## build binaries
|
||||
@echo "$(WHALE) $@"
|
||||
|
||||
@ -207,8 +203,19 @@ man: mandir $(addprefix man/,$(MANPAGES))
|
||||
mandir:
|
||||
@mkdir -p man
|
||||
|
||||
# Kept for backwards compatability
|
||||
genman: man/containerd.1 man/ctr.1
|
||||
|
||||
man/containerd.1: FORCE
|
||||
@echo "$(WHALE) $@"
|
||||
go run cmd/gen-manpages/main.go containerd man/
|
||||
|
||||
man/ctr.1: FORCE
|
||||
@echo "$(WHALE) $@"
|
||||
go run cmd/gen-manpages/main.go ctr man/
|
||||
|
||||
man/%: docs/man/%.md FORCE
|
||||
@echo "$(WHALE) $<"
|
||||
@echo "$(WHALE) $@"
|
||||
go-md2man -in "$<" -out "$@"
|
||||
|
||||
define installmanpage
|
||||
@ -220,12 +227,21 @@ install-man:
|
||||
@echo "$(WHALE) $@"
|
||||
$(foreach manpage,$(addprefix man/,$(MANPAGES)), $(call installmanpage,$(manpage),$(subst .,,$(suffix $(manpage))),$(notdir $(manpage))))
|
||||
|
||||
release: $(BINARIES)
|
||||
releases/$(RELEASE).tar.gz: $(BINARIES)
|
||||
@echo "$(WHALE) $@"
|
||||
@rm -rf releases/$(RELEASE) releases/$(RELEASE).tar.gz
|
||||
@install -d releases/$(RELEASE)/bin
|
||||
@install $(BINARIES) releases/$(RELEASE)/bin
|
||||
@cd releases/$(RELEASE) && tar -czf ../$(RELEASE).tar.gz *
|
||||
@tar -czf releases/$(RELEASE).tar.gz -C releases/$(RELEASE) bin
|
||||
@rm -rf releases/$(RELEASE)
|
||||
|
||||
release: $(BINARIES) releases/$(RELEASE).tar.gz
|
||||
@echo "$(WHALE) $@"
|
||||
@cd releases && sha256sum $(RELEASE).tar.gz >$(RELEASE).tar.gz.sha256sum
|
||||
|
||||
cri-release: $(BINARIES) releases/$(RELEASE).tar.gz
|
||||
@echo "$(WHALE) $@"
|
||||
@VERSION=$(VERSION:v%=%) script/release/release-cri
|
||||
|
||||
clean: ## clean up binaries
|
||||
@echo "$(WHALE) $@"
|
||||
@ -286,7 +302,7 @@ root-coverage: ## generate coverage profiles for unit tests that require root
|
||||
|
||||
vendor:
|
||||
@echo "$(WHALE) $@"
|
||||
@vndr
|
||||
@vndr -whitelist github.com/urfave/cli/autocomplete/
|
||||
|
||||
help: ## this help
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
|
||||
|
1
vendor/github.com/containerd/containerd/Makefile.windows
generated
vendored
1
vendor/github.com/containerd/containerd/Makefile.windows
generated
vendored
@ -16,7 +16,6 @@
|
||||
#Windows specific settings.
|
||||
WHALE = "+"
|
||||
ONI = "-"
|
||||
COMMANDS += containerd-shim-runhcs-v1
|
||||
|
||||
BINARY_SUFFIX=".exe"
|
||||
|
||||
|
16
vendor/github.com/containerd/containerd/Protobuild.toml
generated
vendored
16
vendor/github.com/containerd/containerd/Protobuild.toml
generated
vendored
@ -69,19 +69,3 @@ ignore_files = [
|
||||
"google/protobuf/descriptor.proto",
|
||||
"gogoproto/gogo.proto"
|
||||
]
|
||||
|
||||
[[descriptors]]
|
||||
prefix = "github.com/containerd/containerd/runtime/v2/runhcs/options"
|
||||
target = "runtime/v2/runhcs/options/next.pb.txt"
|
||||
ignore_files = [
|
||||
"google/protobuf/descriptor.proto",
|
||||
"gogoproto/gogo.proto"
|
||||
]
|
||||
|
||||
[[descriptors]]
|
||||
prefix = "github.com/containerd/containerd/windows/hcsshimtypes"
|
||||
target = "windows/hcsshimtypes/next.pb.txt"
|
||||
ignore_files = [
|
||||
"google/protobuf/descriptor.proto",
|
||||
"gogoproto/gogo.proto"
|
||||
]
|
||||
|
30
vendor/github.com/containerd/containerd/README.md
generated
vendored
30
vendor/github.com/containerd/containerd/README.md
generated
vendored
@ -210,6 +210,34 @@ See [PLUGINS.md](PLUGINS.md) for how to create plugins
|
||||
Please see [RELEASES.md](RELEASES.md) for details on versioning and stability
|
||||
of containerd components.
|
||||
|
||||
Downloadable 64-bit Intel/AMD binaries of all official releases are available on
|
||||
our [releases page](https://github.com/containerd/containerd/releases), as well as
|
||||
auto-published to the [cri-containerd-release storage bucket](https://console.cloud.google.com/storage/browser/cri-containerd-release?pli=1).
|
||||
|
||||
For other architectures and distribution support, you will find that many
|
||||
Linux distributions package their own containerd and provide it across several
|
||||
architectures, such as [Canonical's Ubuntu packaging](https://launchpad.net/ubuntu/bionic/+package/containerd).
|
||||
|
||||
#### Enabling command auto-completion
|
||||
|
||||
Starting with containerd 1.4, the urfave client feature for auto-creation of bash
|
||||
autocompletion data is enabled. To use the autocomplete feature in your shell, source
|
||||
the autocomplete/bash_autocomplete file in your .bashrc file while setting the `PROG`
|
||||
variable to `ctr`:
|
||||
|
||||
```
|
||||
$ PROG=ctr source vendor/github.com/urfave/cli/autocomplete/bash_autocomplete
|
||||
```
|
||||
|
||||
#### Distribution of `ctr` autocomplete for bash
|
||||
|
||||
Copy `vendor/github.com/urfave/cli/autocomplete/bash_autocomplete` into
|
||||
`/etc/bash_completion.d/` and rename it to `ctr`.
|
||||
|
||||
Provide documentation to users to `source` this file into their shell if
|
||||
you don't place the autocomplete file in a location where it is automatically
|
||||
loaded for user's bash shell environment.
|
||||
|
||||
### Communication
|
||||
|
||||
For async communication and long running discussions please use issues and pull requests on the github repo.
|
||||
@ -218,7 +246,7 @@ This will be the best place to discuss design and implementation.
|
||||
For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development.
|
||||
|
||||
**Slack:** Catch us in the #containerd and #containerd-dev channels on dockercommunity.slack.com.
|
||||
[Click here for an invite to docker community slack.](https://join.slack.com/t/dockercommunity/shared_invite/enQtNDY4MDc1Mzc0MzIwLTgxZDBlMmM4ZGEyNDc1N2FkMzlhODJkYmE1YTVkYjM1MDE3ZjAwZjBkOGFlOTJkZjRmZGYzNjYyY2M3ZTUxYzQ)
|
||||
[Click here for an invite to docker community slack.](https://dockr.ly/slack)
|
||||
|
||||
### Security audit
|
||||
|
||||
|
35
vendor/github.com/containerd/containerd/RELEASES.md
generated
vendored
35
vendor/github.com/containerd/containerd/RELEASES.md
generated
vendored
@ -77,8 +77,8 @@ Support horizons will be defined corresponding to a release branch, identified
|
||||
by `<major>.<minor>`. Releases branches will be in one of several states:
|
||||
|
||||
- __*Next*__: The next planned release branch.
|
||||
- __*Active*__: The release is currently supported and accepting patches.
|
||||
- __*Extended*__: The release is only accepting security patches.
|
||||
- __*Active*__: The release branch is currently supported and accepting patches.
|
||||
- __*Extended*__: The release branch is only accepting security patches.
|
||||
- __*End of Life*__: The release branch is no longer supported and no new patches will be accepted.
|
||||
|
||||
Releases will be supported up to one year after a _minor_ release. This means that
|
||||
@ -97,9 +97,10 @@ The current state is available in the following table:
|
||||
| [0.1](https://github.com/containerd/containerd/releases/tag/v0.1.0) | End of Life | Mar 21, 2016 | - |
|
||||
| [0.2](https://github.com/containerd/containerd/tree/v0.2.x) | End of Life | Apr 21, 2016 | December 5, 2017 |
|
||||
| [1.0](https://github.com/containerd/containerd/releases/tag/v1.0.3) | End of Life | December 5, 2017 | December 5, 2018 |
|
||||
| [1.1](https://github.com/containerd/containerd/releases/tag/v1.1.7) | Active | April 23, 2018 | July 23, 2019 (Active), October 23, 2019 (Extended) |
|
||||
| [1.2](https://github.com/containerd/containerd/releases/tag/v1.2.6) | Active | October 24, 2018 | max(October 24, 2019, release of 1.3.0 + 6 months) |
|
||||
| [1.3](https://github.com/containerd/containerd/milestone/20) | Next | TBD | max(TBD+1 year, release of 1.4.0 + 6 months) |
|
||||
| [1.1](https://github.com/containerd/containerd/releases/tag/v1.1.8) | Extended | April 23, 2018 | October 23, 2019 |
|
||||
| [1.2](https://github.com/containerd/containerd/releases/tag/v1.2.10) | Active | October 24, 2018 | March 26, 2020 |
|
||||
| [1.3](https://github.com/containerd/containerd/releases/tag/v1.3.0) | Active | September 26, 2019 | max(September 26, 2020, release of 1.4.0 + 6 months) |
|
||||
| [1.4](https://github.com/containerd/containerd/milestone/27) | Next | TBD | max(TBD+1 year, release of 1.5.0 + 6 months) |
|
||||
|
||||
Note that branches and release from before 1.0 may not follow these rules.
|
||||
|
||||
@ -173,6 +174,7 @@ containerd versions:
|
||||
| GRPC API | Stable | 1.0 | [api/](api) |
|
||||
| Metrics API | Stable | 1.0 | - |
|
||||
| Runtime Shim API | Stable | 1.2 | - |
|
||||
| Daemon Config | Stable | 1.0 | - |
|
||||
| Go client API | Unstable | _future_ | [godoc](https://godoc.org/github.com/containerd/containerd) |
|
||||
| CRI GRPC API | Unstable | v1alpha2 _current_ | [api/](https://github.com/kubernetes/kubernetes/tree/master/pkg/kubelet/apis/cri/runtime/v1alpha2) |
|
||||
| `ctr` tool | Unstable | Out of scope | - |
|
||||
@ -198,6 +200,10 @@ enumerating the support services and messages. See [api/](api) for details.
|
||||
Note that new services may be added in _minor_ releases. New service methods
|
||||
and new fields on messages may be added if they are optional.
|
||||
|
||||
`*.pb.txt` files are generated at each API release. They prevent unintentional changes
|
||||
to the API by having a diff that the CI can run. These files are not intended to be
|
||||
consumed or used by clients.
|
||||
|
||||
### Metrics API
|
||||
|
||||
The metrics API that outputs prometheus style metrics will be versioned independently,
|
||||
@ -266,10 +272,23 @@ version of Kubernetes which supports that version of CRI.
|
||||
### `ctr` tool
|
||||
|
||||
The `ctr` tool provides the ability to introspect and understand the containerd
|
||||
API. At this time, it is not considered a primary offering of the project. It
|
||||
may be completely refactored or have breaking changes in _minor_ releases.
|
||||
API. It is not considered a primary offering of the project and is unsupported in
|
||||
that sense. While we understand it's value as a debug tool, it may be completely
|
||||
refactored or have breaking changes in _minor_ releases.
|
||||
|
||||
We will try not break the tool in _patch_ releases.
|
||||
Targeting `ctr` for feature additions reflects a misunderstanding of the containerd
|
||||
architecture. Feature addition should focus on the client Go API and additions to
|
||||
`ctr` may or may not be accepted at the discretion of the maintainers.
|
||||
|
||||
We will do our best to not break compatibility in the tool in _patch_ releases.
|
||||
|
||||
### Daemon Configuration
|
||||
|
||||
The daemon's configuration file, commonly located in `/etc/containerd/config.toml`
|
||||
is versioned and backwards compatible. The `version` field in the config
|
||||
file specifies the config's version. If no version number is specified inside
|
||||
the config file then it is assumed to be a version 1 config and parsed as such.
|
||||
Use `version = 2` to enable version 2 config.
|
||||
|
||||
### Not Covered
|
||||
|
||||
|
266
vendor/github.com/containerd/containerd/api/services/diff/v1/diff.pb.go
generated
vendored
266
vendor/github.com/containerd/containerd/api/services/diff/v1/diff.pb.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
types "github.com/containerd/containerd/api/types"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
types1 "github.com/gogo/protobuf/types"
|
||||
grpc "google.golang.org/grpc"
|
||||
io "io"
|
||||
math "math"
|
||||
@ -29,11 +30,12 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type ApplyRequest struct {
|
||||
// Diff is the descriptor of the diff to be extracted
|
||||
Diff *types.Descriptor `protobuf:"bytes,1,opt,name=diff,proto3" json:"diff,omitempty"`
|
||||
Mounts []*types.Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
Diff *types.Descriptor `protobuf:"bytes,1,opt,name=diff,proto3" json:"diff,omitempty"`
|
||||
Mounts []*types.Mount `protobuf:"bytes,2,rep,name=mounts,proto3" json:"mounts,omitempty"`
|
||||
Payloads map[string]*types1.Any `protobuf:"bytes,3,rep,name=payloads,proto3" json:"payloads,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ApplyRequest) Reset() { *m = ApplyRequest{} }
|
||||
@ -205,6 +207,7 @@ var xxx_messageInfo_DiffResponse proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ApplyRequest)(nil), "containerd.services.diff.v1.ApplyRequest")
|
||||
proto.RegisterMapType((map[string]*types1.Any)(nil), "containerd.services.diff.v1.ApplyRequest.PayloadsEntry")
|
||||
proto.RegisterType((*ApplyResponse)(nil), "containerd.services.diff.v1.ApplyResponse")
|
||||
proto.RegisterType((*DiffRequest)(nil), "containerd.services.diff.v1.DiffRequest")
|
||||
proto.RegisterMapType((map[string]string)(nil), "containerd.services.diff.v1.DiffRequest.LabelsEntry")
|
||||
@ -216,36 +219,40 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_3b36a99e6faaa935 = []byte{
|
||||
// 457 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x4f, 0x6f, 0xd3, 0x30,
|
||||
0x14, 0xaf, 0xfb, 0x0f, 0xf5, 0x75, 0x48, 0xc8, 0x9a, 0x44, 0x14, 0x20, 0xaa, 0x7a, 0xea, 0x40,
|
||||
0x38, 0xac, 0xa0, 0x09, 0xb6, 0xcb, 0x40, 0x43, 0x5c, 0xc6, 0x25, 0xda, 0x01, 0x81, 0x04, 0x4a,
|
||||
0x9b, 0x97, 0xce, 0x22, 0x8d, 0xbd, 0xd8, 0xad, 0x94, 0x1b, 0xdf, 0x85, 0x8f, 0xc2, 0x65, 0x47,
|
||||
0x8e, 0x1c, 0x69, 0x3f, 0x09, 0xb2, 0x93, 0x40, 0x24, 0xa4, 0x12, 0x76, 0xca, 0xcb, 0xf3, 0xef,
|
||||
0x9f, 0xfd, 0x6c, 0x38, 0x5d, 0x70, 0x7d, 0xb9, 0x9a, 0xb1, 0xb9, 0x58, 0xfa, 0x73, 0x91, 0xea,
|
||||
0x90, 0xa7, 0x98, 0x45, 0xf5, 0x32, 0x94, 0xdc, 0x57, 0x98, 0xad, 0xf9, 0x1c, 0x95, 0x1f, 0xf1,
|
||||
0x38, 0xf6, 0xd7, 0x87, 0xf6, 0xcb, 0x64, 0x26, 0xb4, 0xa0, 0xf7, 0xfe, 0x60, 0x59, 0x85, 0x63,
|
||||
0x76, 0x7d, 0x7d, 0xe8, 0xee, 0x2f, 0xc4, 0x42, 0x58, 0x9c, 0x6f, 0xaa, 0x82, 0xe2, 0x1e, 0x35,
|
||||
0x32, 0xd5, 0xb9, 0x44, 0xe5, 0x2f, 0xc5, 0x2a, 0xd5, 0x25, 0xef, 0xe4, 0x3f, 0x78, 0x11, 0xaa,
|
||||
0x79, 0xc6, 0xa5, 0x16, 0x59, 0x41, 0x1e, 0x5f, 0xc1, 0xde, 0x4b, 0x29, 0x93, 0x3c, 0xc0, 0xab,
|
||||
0x15, 0x2a, 0x4d, 0x9f, 0x40, 0xd7, 0xa4, 0x74, 0xc8, 0x88, 0x4c, 0x86, 0xd3, 0xfb, 0xac, 0xb6,
|
||||
0x0d, 0xab, 0xc0, 0xce, 0x7e, 0x2b, 0x04, 0x16, 0x49, 0x7d, 0xe8, 0xdb, 0x34, 0xca, 0x69, 0x8f,
|
||||
0x3a, 0x93, 0xe1, 0xf4, 0xee, 0xdf, 0x9c, 0xb7, 0x66, 0x3d, 0x28, 0x61, 0xe3, 0x37, 0x70, 0xbb,
|
||||
0xb4, 0x54, 0x52, 0xa4, 0x0a, 0xe9, 0x11, 0xdc, 0x0a, 0xa5, 0x4c, 0x38, 0x46, 0x8d, 0x6c, 0x2b,
|
||||
0xf0, 0xf8, 0x6b, 0x1b, 0x86, 0x67, 0x3c, 0x8e, 0xab, 0xec, 0x8f, 0xa0, 0x9b, 0x60, 0xac, 0x1d,
|
||||
0xb2, 0x3b, 0x87, 0x05, 0xd1, 0xc7, 0xd0, 0xcb, 0xf8, 0xe2, 0x52, 0xff, 0x2b, 0x75, 0x81, 0xa2,
|
||||
0x0f, 0x00, 0x96, 0x18, 0xf1, 0xf0, 0x93, 0x59, 0x73, 0x3a, 0x23, 0x32, 0x19, 0x04, 0x03, 0xdb,
|
||||
0xb9, 0xc8, 0x25, 0xd2, 0x3b, 0xd0, 0xc9, 0x30, 0x76, 0xba, 0xb6, 0x6f, 0x4a, 0x7a, 0x0e, 0xfd,
|
||||
0x24, 0x9c, 0x61, 0xa2, 0x9c, 0x9e, 0x35, 0x78, 0xc6, 0x76, 0xdc, 0x08, 0x56, 0xdb, 0x06, 0x3b,
|
||||
0xb7, 0xb4, 0xd7, 0xa9, 0xce, 0xf2, 0xa0, 0xd4, 0x70, 0x5f, 0xc0, 0xb0, 0xd6, 0x36, 0x76, 0x9f,
|
||||
0x31, 0xb7, 0xa7, 0x35, 0x08, 0x4c, 0x49, 0xf7, 0xa1, 0xb7, 0x0e, 0x93, 0x15, 0x3a, 0x6d, 0xdb,
|
||||
0x2b, 0x7e, 0x8e, 0xdb, 0xcf, 0xc9, 0xf8, 0x14, 0xf6, 0x0a, 0xf5, 0xf2, 0xb4, 0xab, 0x09, 0x77,
|
||||
0x9a, 0x4e, 0x78, 0xfa, 0x8d, 0x40, 0xd7, 0x48, 0xd0, 0x8f, 0xd0, 0xb3, 0x93, 0xa3, 0x07, 0x3b,
|
||||
0x37, 0x53, 0xbf, 0x50, 0xee, 0xc3, 0x26, 0xd0, 0x32, 0xda, 0x87, 0xd2, 0x67, 0xd2, 0xf4, 0xac,
|
||||
0xdc, 0x83, 0x06, 0xc8, 0x42, 0xfc, 0xd5, 0xc5, 0xf5, 0xc6, 0x6b, 0xfd, 0xd8, 0x78, 0xad, 0x2f,
|
||||
0x5b, 0x8f, 0x5c, 0x6f, 0x3d, 0xf2, 0x7d, 0xeb, 0x91, 0x9f, 0x5b, 0x8f, 0xbc, 0x3f, 0xbe, 0xd1,
|
||||
0x6b, 0x3f, 0x31, 0xdf, 0x77, 0xad, 0x59, 0xdf, 0x3e, 0xa4, 0xa7, 0xbf, 0x02, 0x00, 0x00, 0xff,
|
||||
0xff, 0x61, 0xd1, 0x6e, 0x9e, 0x34, 0x04, 0x00, 0x00,
|
||||
// 526 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x41, 0x6f, 0xd3, 0x4c,
|
||||
0x10, 0x8d, 0xed, 0x24, 0xdf, 0x97, 0x49, 0x2b, 0xa1, 0x55, 0x24, 0x8c, 0x01, 0xab, 0xca, 0x29,
|
||||
0x2d, 0x62, 0x4d, 0x03, 0x2a, 0xd0, 0x5e, 0x5a, 0x54, 0xc4, 0xa5, 0x48, 0x60, 0x7a, 0x40, 0x20,
|
||||
0x81, 0x9c, 0x78, 0xed, 0xae, 0x70, 0xbc, 0x8b, 0x77, 0x1d, 0xc9, 0x37, 0xfe, 0x06, 0x67, 0x7e,
|
||||
0x0a, 0x97, 0x1e, 0x39, 0x72, 0xa4, 0xf9, 0x25, 0xc8, 0xeb, 0x75, 0x31, 0x02, 0x05, 0xc3, 0xc9,
|
||||
0x9b, 0x9d, 0xf7, 0xde, 0xce, 0xbc, 0x37, 0x0a, 0x1c, 0xc6, 0x54, 0x9e, 0xe5, 0x33, 0x3c, 0x67,
|
||||
0x0b, 0x6f, 0xce, 0x52, 0x19, 0xd0, 0x94, 0x64, 0x61, 0xf3, 0x18, 0x70, 0xea, 0x09, 0x92, 0x2d,
|
||||
0xe9, 0x9c, 0x08, 0x2f, 0xa4, 0x51, 0xe4, 0x2d, 0x77, 0xd5, 0x17, 0xf3, 0x8c, 0x49, 0x86, 0xae,
|
||||
0xff, 0xc0, 0xe2, 0x1a, 0x87, 0x55, 0x7d, 0xb9, 0xeb, 0x8c, 0x62, 0x16, 0x33, 0x85, 0xf3, 0xca,
|
||||
0x53, 0x45, 0x71, 0xae, 0xc5, 0x8c, 0xc5, 0x09, 0xf1, 0xd4, 0xaf, 0x59, 0x1e, 0x79, 0x41, 0x5a,
|
||||
0xe8, 0xd2, 0x5e, 0xab, 0x7e, 0x64, 0xc1, 0x89, 0xf0, 0x16, 0x2c, 0x4f, 0xa5, 0xe6, 0x1d, 0xfc,
|
||||
0x05, 0x2f, 0x24, 0x62, 0x9e, 0x51, 0x2e, 0x59, 0x56, 0x91, 0xc7, 0x1f, 0x4d, 0xd8, 0x38, 0xe2,
|
||||
0x3c, 0x29, 0x7c, 0xf2, 0x3e, 0x27, 0x42, 0xa2, 0x3b, 0xd0, 0x2d, 0x27, 0xb0, 0x8d, 0x2d, 0x63,
|
||||
0x32, 0x9c, 0xde, 0xc0, 0x8d, 0x11, 0x95, 0x04, 0x3e, 0xbe, 0x94, 0xf0, 0x15, 0x12, 0x79, 0xd0,
|
||||
0x57, 0xed, 0x08, 0xdb, 0xdc, 0xb2, 0x26, 0xc3, 0xe9, 0xd5, 0x5f, 0x39, 0x4f, 0xcb, 0xba, 0xaf,
|
||||
0x61, 0xe8, 0x05, 0xfc, 0xcf, 0x83, 0x22, 0x61, 0x41, 0x28, 0x6c, 0x4b, 0x51, 0xee, 0xe3, 0x35,
|
||||
0x4e, 0xe2, 0x66, 0x7f, 0xf8, 0x99, 0x66, 0x3e, 0x4e, 0x65, 0x56, 0xf8, 0x97, 0x42, 0xce, 0x73,
|
||||
0xd8, 0xfc, 0xa9, 0x84, 0xae, 0x80, 0xf5, 0x8e, 0x14, 0x6a, 0x8e, 0x81, 0x5f, 0x1e, 0xd1, 0x0e,
|
||||
0xf4, 0x96, 0x41, 0x92, 0x13, 0xdb, 0x54, 0xb3, 0x8d, 0x70, 0x95, 0x05, 0xae, 0xb3, 0xc0, 0x47,
|
||||
0x69, 0xe1, 0x57, 0x90, 0x7d, 0xf3, 0x81, 0x31, 0x7e, 0x02, 0x9b, 0xfa, 0x69, 0xc1, 0x59, 0x2a,
|
||||
0x08, 0xda, 0x83, 0xff, 0x02, 0xce, 0x13, 0x4a, 0xc2, 0x56, 0xf6, 0xd4, 0xe0, 0xf1, 0x27, 0x13,
|
||||
0x86, 0xc7, 0x34, 0x8a, 0x6a, 0x8f, 0x6f, 0x41, 0x37, 0x21, 0x91, 0xb4, 0x8d, 0xf5, 0x7e, 0x29,
|
||||
0x10, 0xba, 0x0d, 0xbd, 0x8c, 0xc6, 0x67, 0xf2, 0x4f, 0xee, 0x56, 0x28, 0x74, 0x13, 0x60, 0x41,
|
||||
0x42, 0x1a, 0xbc, 0x2d, 0x6b, 0xb6, 0xa5, 0xa6, 0x1f, 0xa8, 0x9b, 0xd3, 0x82, 0x93, 0xd2, 0x95,
|
||||
0x8c, 0x44, 0x76, 0xb7, 0x72, 0x25, 0x23, 0x11, 0x3a, 0x81, 0x7e, 0x12, 0xcc, 0x48, 0x22, 0xec,
|
||||
0x9e, 0x7a, 0xe0, 0xde, 0xda, 0x2c, 0x1a, 0x63, 0xe0, 0x13, 0x45, 0xab, 0x82, 0xd0, 0x1a, 0xce,
|
||||
0x43, 0x18, 0x36, 0xae, 0x7f, 0x13, 0xc2, 0xa8, 0x19, 0xc2, 0xa0, 0x69, 0xf7, 0x21, 0x6c, 0x54,
|
||||
0xea, 0xda, 0xed, 0x7a, 0x13, 0xad, 0xb6, 0x9b, 0x38, 0xfd, 0x6c, 0x40, 0xb7, 0x94, 0x40, 0x6f,
|
||||
0xa0, 0xa7, 0x92, 0x43, 0xdb, 0xad, 0x17, 0xcb, 0xd9, 0x69, 0x03, 0xd5, 0xad, 0xbd, 0xd6, 0xef,
|
||||
0x4c, 0xda, 0x7a, 0xe5, 0x6c, 0xb7, 0x40, 0x56, 0xe2, 0x8f, 0x4e, 0xcf, 0x2f, 0xdc, 0xce, 0xd7,
|
||||
0x0b, 0xb7, 0xf3, 0x61, 0xe5, 0x1a, 0xe7, 0x2b, 0xd7, 0xf8, 0xb2, 0x72, 0x8d, 0x6f, 0x2b, 0xd7,
|
||||
0x78, 0xb5, 0xff, 0x4f, 0xff, 0x58, 0x07, 0xe5, 0xf7, 0x65, 0x67, 0xd6, 0x57, 0x7b, 0x7e, 0xf7,
|
||||
0x7b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x85, 0x25, 0xb8, 0xf8, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -400,6 +407,34 @@ func (m *ApplyRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if len(m.Payloads) > 0 {
|
||||
for k, _ := range m.Payloads {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
v := m.Payloads[k]
|
||||
msgSize := 0
|
||||
if v != nil {
|
||||
msgSize = v.Size()
|
||||
msgSize += 1 + sovDiff(uint64(msgSize))
|
||||
}
|
||||
mapSize := 1 + len(k) + sovDiff(uint64(len(k))) + msgSize
|
||||
i = encodeVarintDiff(dAtA, i, uint64(mapSize))
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintDiff(dAtA, i, uint64(len(k)))
|
||||
i += copy(dAtA[i:], k)
|
||||
if v != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintDiff(dAtA, i, uint64(v.Size()))
|
||||
n2, err := v.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n2
|
||||
}
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
@ -425,11 +460,11 @@ func (m *ApplyResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintDiff(dAtA, i, uint64(m.Applied.Size()))
|
||||
n2, err := m.Applied.MarshalTo(dAtA[i:])
|
||||
n3, err := m.Applied.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n2
|
||||
i += n3
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
@ -530,11 +565,11 @@ func (m *DiffResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintDiff(dAtA, i, uint64(m.Diff.Size()))
|
||||
n3, err := m.Diff.MarshalTo(dAtA[i:])
|
||||
n4, err := m.Diff.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n3
|
||||
i += n4
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
@ -567,6 +602,19 @@ func (m *ApplyRequest) Size() (n int) {
|
||||
n += 1 + l + sovDiff(uint64(l))
|
||||
}
|
||||
}
|
||||
if len(m.Payloads) > 0 {
|
||||
for k, v := range m.Payloads {
|
||||
_ = k
|
||||
_ = v
|
||||
l = 0
|
||||
if v != nil {
|
||||
l = v.Size()
|
||||
l += 1 + sovDiff(uint64(l))
|
||||
}
|
||||
mapEntrySize := 1 + len(k) + sovDiff(uint64(len(k))) + l
|
||||
n += mapEntrySize + 1 + sovDiff(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
@ -662,9 +710,20 @@ func (this *ApplyRequest) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
keysForPayloads := make([]string, 0, len(this.Payloads))
|
||||
for k, _ := range this.Payloads {
|
||||
keysForPayloads = append(keysForPayloads, k)
|
||||
}
|
||||
github_com_gogo_protobuf_sortkeys.Strings(keysForPayloads)
|
||||
mapStringForPayloads := "map[string]*types1.Any{"
|
||||
for _, k := range keysForPayloads {
|
||||
mapStringForPayloads += fmt.Sprintf("%v: %v,", k, this.Payloads[k])
|
||||
}
|
||||
mapStringForPayloads += "}"
|
||||
s := strings.Join([]string{`&ApplyRequest{`,
|
||||
`Diff:` + strings.Replace(fmt.Sprintf("%v", this.Diff), "Descriptor", "types.Descriptor", 1) + `,`,
|
||||
`Mounts:` + strings.Replace(fmt.Sprintf("%v", this.Mounts), "Mount", "types.Mount", 1) + `,`,
|
||||
`Payloads:` + mapStringForPayloads + `,`,
|
||||
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
@ -824,6 +883,135 @@ func (m *ApplyRequest) Unmarshal(dAtA []byte) error {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Payloads", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDiff
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Payloads == nil {
|
||||
m.Payloads = make(map[string]*types1.Any)
|
||||
}
|
||||
var mapkey string
|
||||
var mapvalue *types1.Any
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDiff
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDiff
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
} else if fieldNum == 2 {
|
||||
var mapmsglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDiff
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
mapmsglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if mapmsglen < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
postmsgIndex := iNdEx + mapmsglen
|
||||
if postmsgIndex < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
if postmsgIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapvalue = &types1.Any{}
|
||||
if err := mapvalue.Unmarshal(dAtA[iNdEx:postmsgIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postmsgIndex
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipDiff(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDiff
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Payloads[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipDiff(dAtA[iNdEx:])
|
||||
|
3
vendor/github.com/containerd/containerd/api/services/diff/v1/diff.proto
generated
vendored
3
vendor/github.com/containerd/containerd/api/services/diff/v1/diff.proto
generated
vendored
@ -3,6 +3,7 @@ syntax = "proto3";
|
||||
package containerd.services.diff.v1;
|
||||
|
||||
import weak "gogoproto/gogo.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||
|
||||
@ -25,6 +26,8 @@ message ApplyRequest {
|
||||
containerd.types.Descriptor diff = 1;
|
||||
|
||||
repeated containerd.types.Mount mounts = 2;
|
||||
|
||||
map<string, google.protobuf.Any> payloads = 3;
|
||||
}
|
||||
|
||||
message ApplyResponse {
|
||||
|
284
vendor/github.com/containerd/containerd/api/services/introspection/v1/introspection.pb.go
generated
vendored
284
vendor/github.com/containerd/containerd/api/services/introspection/v1/introspection.pb.go
generated
vendored
@ -10,6 +10,7 @@ import (
|
||||
rpc "github.com/gogo/googleapis/google/rpc"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
types1 "github.com/gogo/protobuf/types"
|
||||
grpc "google.golang.org/grpc"
|
||||
io "io"
|
||||
math "math"
|
||||
@ -191,11 +192,51 @@ func (m *PluginsResponse) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_PluginsResponse proto.InternalMessageInfo
|
||||
|
||||
type ServerResponse struct {
|
||||
UUID string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ServerResponse) Reset() { *m = ServerResponse{} }
|
||||
func (*ServerResponse) ProtoMessage() {}
|
||||
func (*ServerResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_1a14fda866f10715, []int{3}
|
||||
}
|
||||
func (m *ServerResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *ServerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_ServerResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *ServerResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ServerResponse.Merge(m, src)
|
||||
}
|
||||
func (m *ServerResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *ServerResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ServerResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ServerResponse proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Plugin)(nil), "containerd.services.introspection.v1.Plugin")
|
||||
proto.RegisterMapType((map[string]string)(nil), "containerd.services.introspection.v1.Plugin.ExportsEntry")
|
||||
proto.RegisterType((*PluginsRequest)(nil), "containerd.services.introspection.v1.PluginsRequest")
|
||||
proto.RegisterType((*PluginsResponse)(nil), "containerd.services.introspection.v1.PluginsResponse")
|
||||
proto.RegisterType((*ServerResponse)(nil), "containerd.services.introspection.v1.ServerResponse")
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -203,38 +244,42 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_1a14fda866f10715 = []byte{
|
||||
// 487 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x4d, 0x6f, 0xd3, 0x40,
|
||||
0x10, 0xcd, 0x3a, 0x69, 0xdc, 0x4c, 0xca, 0x87, 0x56, 0x15, 0x58, 0x3e, 0xb8, 0x51, 0xc4, 0x21,
|
||||
0x42, 0xb0, 0x56, 0x03, 0x48, 0xb4, 0x48, 0x1c, 0x22, 0x72, 0xa8, 0xd4, 0x43, 0xe5, 0x5e, 0x10,
|
||||
0x97, 0xca, 0x71, 0x36, 0x66, 0x85, 0xeb, 0xdd, 0xee, 0xae, 0x2d, 0x72, 0xe3, 0xc6, 0x5f, 0xcb,
|
||||
0x91, 0x23, 0xa7, 0x8a, 0xfa, 0x37, 0xf0, 0x03, 0x90, 0xbd, 0x76, 0x9b, 0xdc, 0x12, 0x71, 0x9b,
|
||||
0x79, 0x7e, 0x6f, 0xe6, 0xcd, 0x93, 0x17, 0x82, 0x98, 0xe9, 0xaf, 0xd9, 0x8c, 0x44, 0xfc, 0xda,
|
||||
0x8f, 0x78, 0xaa, 0x43, 0x96, 0x52, 0x39, 0x5f, 0x2f, 0x43, 0xc1, 0x7c, 0x45, 0x65, 0xce, 0x22,
|
||||
0xaa, 0x7c, 0x96, 0x6a, 0xc9, 0x95, 0xa0, 0x91, 0x66, 0x3c, 0xf5, 0xf3, 0xe3, 0x4d, 0x80, 0x08,
|
||||
0xc9, 0x35, 0xc7, 0x2f, 0x1e, 0xd4, 0xa4, 0x51, 0x92, 0x4d, 0x62, 0x7e, 0xec, 0x9e, 0x6c, 0xb5,
|
||||
0x59, 0x2f, 0x05, 0x55, 0xbe, 0x48, 0x42, 0xbd, 0xe0, 0xf2, 0xda, 0x2c, 0x70, 0x9f, 0xc7, 0x9c,
|
||||
0xc7, 0x09, 0xf5, 0xa5, 0x88, 0x7c, 0xa5, 0x43, 0x9d, 0xa9, 0xfa, 0xc3, 0x61, 0xcc, 0x63, 0x5e,
|
||||
0x95, 0x7e, 0x59, 0x19, 0x74, 0xf8, 0xd7, 0x82, 0xee, 0x45, 0x92, 0xc5, 0x2c, 0xc5, 0x18, 0x3a,
|
||||
0xe5, 0x44, 0x07, 0x0d, 0xd0, 0xa8, 0x17, 0x54, 0x35, 0x7e, 0x06, 0x16, 0x9b, 0x3b, 0x56, 0x89,
|
||||
0x4c, 0xba, 0xc5, 0xed, 0x91, 0x75, 0xf6, 0x29, 0xb0, 0xd8, 0x1c, 0xbb, 0xb0, 0x2f, 0xe9, 0x4d,
|
||||
0xc6, 0x24, 0x55, 0x4e, 0x7b, 0xd0, 0x1e, 0xf5, 0x82, 0xfb, 0x1e, 0x7f, 0x84, 0x5e, 0xe3, 0x49,
|
||||
0x39, 0x9d, 0x41, 0x7b, 0xd4, 0x1f, 0xbb, 0x64, 0xed, 0xec, 0xca, 0x36, 0xb9, 0xa8, 0x29, 0x93,
|
||||
0xce, 0xea, 0xf6, 0xa8, 0x15, 0x3c, 0x48, 0xf0, 0x25, 0xd8, 0xf4, 0xbb, 0xe0, 0x52, 0x2b, 0x67,
|
||||
0xaf, 0x52, 0x9f, 0x90, 0x6d, 0x42, 0x23, 0xe6, 0x0c, 0x32, 0x35, 0xda, 0x69, 0xaa, 0xe5, 0x32,
|
||||
0x68, 0x26, 0xe1, 0x21, 0x1c, 0x44, 0xa1, 0x08, 0x67, 0x2c, 0x61, 0x9a, 0x51, 0xe5, 0x74, 0x2b,
|
||||
0xd3, 0x1b, 0x18, 0x7e, 0x0d, 0xfb, 0x2c, 0x65, 0xfa, 0x8a, 0x4a, 0xe9, 0xd8, 0x03, 0x34, 0xea,
|
||||
0x8f, 0x31, 0x31, 0x69, 0x12, 0x29, 0x22, 0x72, 0x59, 0xa5, 0x19, 0xd8, 0x25, 0x67, 0x2a, 0xa5,
|
||||
0x7b, 0x0a, 0x07, 0xeb, 0xbb, 0xf0, 0x53, 0x68, 0x7f, 0xa3, 0xcb, 0x3a, 0xbe, 0xb2, 0xc4, 0x87,
|
||||
0xb0, 0x97, 0x87, 0x49, 0x46, 0x4d, 0x80, 0x81, 0x69, 0x4e, 0xad, 0xf7, 0x68, 0xf8, 0x12, 0x1e,
|
||||
0x1b, 0xbb, 0x2a, 0xa0, 0x37, 0x19, 0x55, 0x1a, 0x3b, 0x60, 0x2f, 0x58, 0xa2, 0xa9, 0x54, 0x0e,
|
||||
0xaa, 0xbc, 0x35, 0xed, 0xf0, 0x0a, 0x9e, 0xdc, 0x73, 0x95, 0xe0, 0xa9, 0xa2, 0xf8, 0x1c, 0x6c,
|
||||
0x61, 0xa0, 0x8a, 0xdc, 0x1f, 0xbf, 0xda, 0x25, 0xa2, 0x3a, 0xf2, 0x66, 0xc4, 0xf8, 0x27, 0x82,
|
||||
0x47, 0x67, 0xeb, 0x54, 0x9c, 0x83, 0x5d, 0xaf, 0xc4, 0x6f, 0x77, 0x99, 0xdc, 0x5c, 0xe3, 0xbe,
|
||||
0xdb, 0x51, 0x65, 0xee, 0x9a, 0x2c, 0x56, 0x77, 0x5e, 0xeb, 0xf7, 0x9d, 0xd7, 0xfa, 0x51, 0x78,
|
||||
0x68, 0x55, 0x78, 0xe8, 0x57, 0xe1, 0xa1, 0x3f, 0x85, 0x87, 0xbe, 0x9c, 0xff, 0xdf, 0x5b, 0xfc,
|
||||
0xb0, 0x01, 0x7c, 0xb6, 0x66, 0xdd, 0xea, 0xf7, 0x7f, 0xf3, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xe6,
|
||||
0x72, 0xde, 0x35, 0xe4, 0x03, 0x00, 0x00,
|
||||
// 549 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xc1, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0xad, 0x9d, 0x34, 0x6e, 0x37, 0xa5, 0xa0, 0x55, 0x55, 0x2c, 0x83, 0x9c, 0x28, 0xe2, 0x10,
|
||||
0x21, 0x58, 0xab, 0x01, 0x24, 0x5a, 0x24, 0x0e, 0x51, 0x73, 0x88, 0xd4, 0x43, 0xe5, 0xa8, 0x08,
|
||||
0x71, 0xa9, 0x1c, 0x67, 0x63, 0x56, 0x38, 0xde, 0xed, 0xee, 0xda, 0x22, 0x37, 0x3e, 0x2f, 0x47,
|
||||
0x8e, 0x9c, 0x02, 0xf5, 0x37, 0xf0, 0x01, 0xc8, 0xbb, 0x76, 0x9a, 0xdc, 0x12, 0x71, 0x9b, 0x79,
|
||||
0x33, 0x6f, 0xe6, 0xcd, 0xf3, 0xca, 0xc0, 0x8f, 0x88, 0xfc, 0x9a, 0x8e, 0x51, 0x48, 0x67, 0x5e,
|
||||
0x48, 0x13, 0x19, 0x90, 0x04, 0xf3, 0xc9, 0x7a, 0x18, 0x30, 0xe2, 0x09, 0xcc, 0x33, 0x12, 0x62,
|
||||
0xe1, 0x91, 0x44, 0x72, 0x2a, 0x18, 0x0e, 0x25, 0xa1, 0x89, 0x97, 0x9d, 0x6d, 0x02, 0x88, 0x71,
|
||||
0x2a, 0x29, 0x7c, 0xf1, 0xc0, 0x46, 0x15, 0x13, 0x6d, 0x36, 0x66, 0x67, 0xce, 0xf9, 0x56, 0x9b,
|
||||
0xe5, 0x9c, 0x61, 0xe1, 0xb1, 0x38, 0x90, 0x53, 0xca, 0x67, 0x7a, 0x81, 0xf3, 0x34, 0xa2, 0x34,
|
||||
0x8a, 0xb1, 0xc7, 0x59, 0xe8, 0x09, 0x19, 0xc8, 0x54, 0x94, 0x85, 0x67, 0x65, 0x41, 0x65, 0xe3,
|
||||
0x74, 0xea, 0xe1, 0x19, 0x93, 0xf3, 0xb2, 0x78, 0x12, 0xd1, 0x88, 0xaa, 0xd0, 0x2b, 0x22, 0x8d,
|
||||
0x76, 0xfe, 0x9a, 0xa0, 0x71, 0x1d, 0xa7, 0x11, 0x49, 0x20, 0x04, 0xf5, 0x62, 0x9d, 0x6d, 0xb4,
|
||||
0x8d, 0xee, 0xa1, 0xaf, 0x62, 0x78, 0x0a, 0x4c, 0x32, 0xb1, 0xcd, 0x02, 0xe9, 0x37, 0xf2, 0x65,
|
||||
0xcb, 0x1c, 0x5e, 0xfa, 0x26, 0x99, 0x40, 0x07, 0x1c, 0x70, 0x7c, 0x97, 0x12, 0x8e, 0x85, 0x5d,
|
||||
0x6b, 0xd7, 0xba, 0x87, 0xfe, 0x2a, 0x87, 0x1f, 0xc1, 0x61, 0x25, 0x58, 0xd8, 0xf5, 0x76, 0xad,
|
||||
0xdb, 0xec, 0x39, 0x68, 0xcd, 0x13, 0x75, 0x13, 0xba, 0x2e, 0x5b, 0xfa, 0xf5, 0xc5, 0xb2, 0xb5,
|
||||
0xe7, 0x3f, 0x50, 0xe0, 0x08, 0x58, 0xf8, 0x3b, 0xa3, 0x5c, 0x0a, 0x7b, 0x5f, 0xb1, 0xcf, 0xd1,
|
||||
0x36, 0x8e, 0x22, 0x7d, 0x06, 0x1a, 0x68, 0xee, 0x20, 0x91, 0x7c, 0xee, 0x57, 0x93, 0x60, 0x07,
|
||||
0x1c, 0x85, 0x01, 0x0b, 0xc6, 0x24, 0x26, 0x92, 0x60, 0x61, 0x37, 0x94, 0xe8, 0x0d, 0x0c, 0xbe,
|
||||
0x06, 0x07, 0x24, 0x21, 0xf2, 0x16, 0x73, 0x6e, 0x5b, 0x6d, 0xa3, 0xdb, 0xec, 0x41, 0xa4, 0x1d,
|
||||
0x45, 0x9c, 0x85, 0x68, 0xa4, 0xac, 0xf6, 0xad, 0xa2, 0x67, 0xc0, 0xb9, 0x73, 0x01, 0x8e, 0xd6,
|
||||
0x77, 0xc1, 0x27, 0xa0, 0xf6, 0x0d, 0xcf, 0x4b, 0xfb, 0x8a, 0x10, 0x9e, 0x80, 0xfd, 0x2c, 0x88,
|
||||
0x53, 0xac, 0x0d, 0xf4, 0x75, 0x72, 0x61, 0xbe, 0x37, 0x3a, 0x2f, 0xc1, 0xb1, 0x96, 0x2b, 0x7c,
|
||||
0x7c, 0x97, 0x62, 0x21, 0xa1, 0x0d, 0xac, 0x29, 0x89, 0x25, 0xe6, 0xc2, 0x36, 0x94, 0xb6, 0x2a,
|
||||
0xed, 0xdc, 0x82, 0xc7, 0xab, 0x5e, 0xc1, 0x68, 0x22, 0x30, 0xbc, 0x02, 0x16, 0xd3, 0x90, 0x6a,
|
||||
0x6e, 0xf6, 0x5e, 0xed, 0x62, 0x51, 0x69, 0x79, 0x35, 0xa2, 0x83, 0xc0, 0xf1, 0x08, 0xf3, 0x0c,
|
||||
0xf3, 0xd5, 0xfc, 0xe7, 0xa0, 0x9e, 0xa6, 0x64, 0xa2, 0x6f, 0xe9, 0x1f, 0xe4, 0xcb, 0x56, 0xfd,
|
||||
0xe6, 0x66, 0x78, 0xe9, 0x2b, 0xb4, 0xf7, 0xdb, 0x00, 0x8f, 0x86, 0xeb, 0xa3, 0x61, 0x06, 0xac,
|
||||
0x52, 0x22, 0x7c, 0xbb, 0x8b, 0x92, 0xea, 0x7a, 0xe7, 0xdd, 0x8e, 0xac, 0x52, 0xe7, 0x27, 0xd0,
|
||||
0xd0, 0xca, 0xe1, 0x69, 0xf5, 0xa5, 0xaa, 0xb7, 0x8f, 0x06, 0xc5, 0xdb, 0x77, 0xb6, 0x94, 0xb3,
|
||||
0x79, 0x7f, 0x7f, 0xba, 0xb8, 0x77, 0xf7, 0x7e, 0xdd, 0xbb, 0x7b, 0x3f, 0x72, 0xd7, 0x58, 0xe4,
|
||||
0xae, 0xf1, 0x33, 0x77, 0x8d, 0x3f, 0xb9, 0x6b, 0x7c, 0xb9, 0xfa, 0xbf, 0x1f, 0xc6, 0x87, 0x0d,
|
||||
0xe0, 0x73, 0x6d, 0xdc, 0x50, 0x7a, 0xdf, 0xfc, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x0c, 0xb3, 0x50,
|
||||
0xdc, 0x89, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@ -254,6 +299,8 @@ type IntrospectionClient interface {
|
||||
// Clients can use this to detect features and capabilities when using
|
||||
// containerd.
|
||||
Plugins(ctx context.Context, in *PluginsRequest, opts ...grpc.CallOption) (*PluginsResponse, error)
|
||||
// Server returns information about the containerd server
|
||||
Server(ctx context.Context, in *types1.Empty, opts ...grpc.CallOption) (*ServerResponse, error)
|
||||
}
|
||||
|
||||
type introspectionClient struct {
|
||||
@ -273,6 +320,15 @@ func (c *introspectionClient) Plugins(ctx context.Context, in *PluginsRequest, o
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *introspectionClient) Server(ctx context.Context, in *types1.Empty, opts ...grpc.CallOption) (*ServerResponse, error) {
|
||||
out := new(ServerResponse)
|
||||
err := c.cc.Invoke(ctx, "/containerd.services.introspection.v1.Introspection/Server", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// IntrospectionServer is the server API for Introspection service.
|
||||
type IntrospectionServer interface {
|
||||
// Plugins returns a list of plugins in containerd.
|
||||
@ -280,6 +336,8 @@ type IntrospectionServer interface {
|
||||
// Clients can use this to detect features and capabilities when using
|
||||
// containerd.
|
||||
Plugins(context.Context, *PluginsRequest) (*PluginsResponse, error)
|
||||
// Server returns information about the containerd server
|
||||
Server(context.Context, *types1.Empty) (*ServerResponse, error)
|
||||
}
|
||||
|
||||
func RegisterIntrospectionServer(s *grpc.Server, srv IntrospectionServer) {
|
||||
@ -304,6 +362,24 @@ func _Introspection_Plugins_Handler(srv interface{}, ctx context.Context, dec fu
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Introspection_Server_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(types1.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IntrospectionServer).Server(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/containerd.services.introspection.v1.Introspection/Server",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IntrospectionServer).Server(ctx, req.(*types1.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Introspection_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "containerd.services.introspection.v1.Introspection",
|
||||
HandlerType: (*IntrospectionServer)(nil),
|
||||
@ -312,6 +388,10 @@ var _Introspection_serviceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Plugins",
|
||||
Handler: _Introspection_Plugins_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Server",
|
||||
Handler: _Introspection_Server_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "github.com/containerd/containerd/api/services/introspection/v1/introspection.proto",
|
||||
@ -488,6 +568,33 @@ func (m *PluginsResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *ServerResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *ServerResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.UUID) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintIntrospection(dAtA, i, uint64(len(m.UUID)))
|
||||
i += copy(dAtA[i:], m.UUID)
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintIntrospection(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
@ -583,6 +690,22 @@ func (m *PluginsResponse) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *ServerResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.UUID)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovIntrospection(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovIntrospection(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
@ -645,6 +768,17 @@ func (this *PluginsResponse) String() string {
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func (this *ServerResponse) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&ServerResponse{`,
|
||||
`UUID:` + fmt.Sprintf("%v", this.UUID) + `,`,
|
||||
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func valueToStringIntrospection(v interface{}) string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsNil() {
|
||||
@ -1206,6 +1340,92 @@ func (m *PluginsResponse) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *ServerResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowIntrospection
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: ServerResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: ServerResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field UUID", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowIntrospection
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthIntrospection
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthIntrospection
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.UUID = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipIntrospection(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthIntrospection
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthIntrospection
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipIntrospection(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
|
@ -4,6 +4,7 @@ package containerd.services.introspection.v1;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||
import "google/rpc/status.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import weak "gogoproto/gogo.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/introspection/v1;introspection";
|
||||
@ -14,6 +15,8 @@ service Introspection {
|
||||
// Clients can use this to detect features and capabilities when using
|
||||
// containerd.
|
||||
rpc Plugins(PluginsRequest) returns (PluginsResponse);
|
||||
// Server returns information about the containerd server
|
||||
rpc Server(google.protobuf.Empty) returns (ServerResponse);
|
||||
}
|
||||
|
||||
message Plugin {
|
||||
@ -79,3 +82,7 @@ message PluginsRequest {
|
||||
message PluginsResponse {
|
||||
repeated Plugin plugins = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message ServerResponse {
|
||||
string uuid = 1 [(gogoproto.customname) = "UUID"];
|
||||
}
|
||||
|
1228
vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go
generated
vendored
1228
vendor/github.com/containerd/containerd/api/services/leases/v1/leases.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
38
vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto
generated
vendored
38
vendor/github.com/containerd/containerd/api/services/leases/v1/leases.proto
generated
vendored
@ -22,6 +22,15 @@ service Leases {
|
||||
// List lists all active leases, returning the full list of
|
||||
// leases and optionally including the referenced resources.
|
||||
rpc List(ListRequest) returns (ListResponse);
|
||||
|
||||
// AddResource references the resource by the provided lease.
|
||||
rpc AddResource(AddResourceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// DeleteResource dereferences the resource by the provided lease.
|
||||
rpc DeleteResource(DeleteResourceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// ListResources lists all the resources referenced by the lease.
|
||||
rpc ListResources(ListResourcesRequest) returns (ListResourcesResponse);
|
||||
}
|
||||
|
||||
// Lease is an object which retains resources while it exists.
|
||||
@ -62,3 +71,32 @@ message ListRequest {
|
||||
message ListResponse {
|
||||
repeated Lease leases = 1;
|
||||
}
|
||||
|
||||
message Resource {
|
||||
string id = 1;
|
||||
|
||||
// For snapshotter resource, there are many snapshotter types here, like
|
||||
// overlayfs, devmapper etc. The type will be formatted with type,
|
||||
// like "snapshotter/overlayfs".
|
||||
string type = 2;
|
||||
}
|
||||
|
||||
message AddResourceRequest {
|
||||
string id = 1;
|
||||
|
||||
Resource resource = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message DeleteResourceRequest {
|
||||
string id = 1;
|
||||
|
||||
Resource resource = 2 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
||||
message ListResourcesRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ListResourcesResponse {
|
||||
repeated Resource resources = 1 [(gogoproto.nullable) = false];
|
||||
}
|
||||
|
2
vendor/github.com/containerd/containerd/archive/compression/compression.go
generated
vendored
2
vendor/github.com/containerd/containerd/archive/compression/compression.go
generated
vendored
@ -180,7 +180,7 @@ func DecompressStream(archive io.Reader) (DecompressReadCloser, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// CompressStream compresseses the dest with specified compression algorithm.
|
||||
// CompressStream compresses the dest with specified compression algorithm.
|
||||
func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) {
|
||||
switch compression {
|
||||
case Uncompressed:
|
||||
|
261
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
261
vendor/github.com/containerd/containerd/archive/tar.go
generated
vendored
@ -19,9 +19,7 @@ package archive
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@ -91,11 +89,6 @@ const (
|
||||
// archives.
|
||||
whiteoutMetaPrefix = whiteoutPrefix + whiteoutPrefix
|
||||
|
||||
// whiteoutLinkDir is a directory AUFS uses for storing hardlink links to other
|
||||
// layers. Normally these should not go into exported archives and all changed
|
||||
// hardlinks should be copied to the top layer.
|
||||
whiteoutLinkDir = whiteoutMetaPrefix + "plnk"
|
||||
|
||||
// whiteoutOpaqueDir file means directory has been made opaque - meaning
|
||||
// readdir calls to this directory do not follow to lower layers.
|
||||
whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq"
|
||||
@ -117,11 +110,15 @@ func Apply(ctx context.Context, root string, r io.Reader, opts ...ApplyOpt) (int
|
||||
if options.Filter == nil {
|
||||
options.Filter = all
|
||||
}
|
||||
if options.applyFunc == nil {
|
||||
options.applyFunc = applyNaive
|
||||
}
|
||||
|
||||
return apply(ctx, root, tar.NewReader(r), options)
|
||||
return options.applyFunc(ctx, root, tar.NewReader(r), options)
|
||||
}
|
||||
|
||||
// applyNaive applies a tar stream of an OCI style diff tar.
|
||||
// applyNaive applies a tar stream of an OCI style diff tar to a directory
|
||||
// applying each file as either a whole file or whiteout.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
||||
func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
||||
var (
|
||||
@ -131,11 +128,49 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
||||
// may occur out of order
|
||||
unpackedPaths = make(map[string]struct{})
|
||||
|
||||
// Used for aufs plink directory
|
||||
aufsTempdir = ""
|
||||
aufsHardlinks = make(map[string]*tar.Header)
|
||||
convertWhiteout = options.ConvertWhiteout
|
||||
)
|
||||
|
||||
if convertWhiteout == nil {
|
||||
// handle whiteouts by removing the target files
|
||||
convertWhiteout = func(hdr *tar.Header, path string) (bool, error) {
|
||||
base := filepath.Base(path)
|
||||
dir := filepath.Dir(path)
|
||||
if base == whiteoutOpaqueDir {
|
||||
_, err := os.Lstat(dir)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = nil // parent was deleted
|
||||
}
|
||||
return err
|
||||
}
|
||||
if path == dir {
|
||||
return nil
|
||||
}
|
||||
if _, exists := unpackedPaths[path]; !exists {
|
||||
err := os.RemoveAll(path)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return false, err
|
||||
}
|
||||
|
||||
if strings.HasPrefix(base, whiteoutPrefix) {
|
||||
originalBase := base[len(whiteoutPrefix):]
|
||||
originalPath := filepath.Join(dir, originalBase)
|
||||
|
||||
return false, os.RemoveAll(originalPath)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through the files in the archive.
|
||||
for {
|
||||
select {
|
||||
@ -193,85 +228,21 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
||||
if base == "" {
|
||||
parentPath = filepath.Dir(path)
|
||||
}
|
||||
if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
|
||||
err = mkdirAll(parentPath, 0755)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip AUFS metadata dirs
|
||||
if strings.HasPrefix(hdr.Name, whiteoutMetaPrefix) {
|
||||
// Regular files inside /.wh..wh.plnk can be used as hardlink targets
|
||||
// We don't want this directory, but we need the files in them so that
|
||||
// such hardlinks can be resolved.
|
||||
if strings.HasPrefix(hdr.Name, whiteoutLinkDir) && hdr.Typeflag == tar.TypeReg {
|
||||
basename := filepath.Base(hdr.Name)
|
||||
aufsHardlinks[basename] = hdr
|
||||
if aufsTempdir == "" {
|
||||
if aufsTempdir, err = ioutil.TempDir(os.Getenv("XDG_RUNTIME_DIR"), "dockerplnk"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer os.RemoveAll(aufsTempdir)
|
||||
}
|
||||
p, err := fs.RootPath(aufsTempdir, basename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := createTarFile(ctx, p, root, hdr, tr); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if hdr.Name != whiteoutOpaqueDir {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(base, whiteoutPrefix) {
|
||||
dir := filepath.Dir(path)
|
||||
if base == whiteoutOpaqueDir {
|
||||
_, err := os.Lstat(dir)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = nil // parent was deleted
|
||||
}
|
||||
return err
|
||||
}
|
||||
if path == dir {
|
||||
return nil
|
||||
}
|
||||
if _, exists := unpackedPaths[path]; !exists {
|
||||
err := os.RemoveAll(path)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
originalBase := base[len(whiteoutPrefix):]
|
||||
originalPath := filepath.Join(dir, originalBase)
|
||||
|
||||
// Ensure originalPath is under dir
|
||||
if dir[len(dir)-1] != filepath.Separator {
|
||||
dir += string(filepath.Separator)
|
||||
}
|
||||
if !strings.HasPrefix(originalPath, dir) {
|
||||
return 0, errors.Wrapf(errInvalidArchive, "invalid whiteout name: %v", base)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(originalPath); err != nil {
|
||||
if err := mkparent(ctx, parentPath, root, options.Parents); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
// Naive whiteout convert function which handles whiteout files by
|
||||
// removing the target files.
|
||||
if err := validateWhiteout(path); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
writeFile, err := convertWhiteout(hdr, path)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "failed to convert whiteout file %q", hdr.Name)
|
||||
}
|
||||
if !writeFile {
|
||||
continue
|
||||
}
|
||||
// If path exits we almost always just want to remove and replace it.
|
||||
@ -289,26 +260,6 @@ func applyNaive(ctx context.Context, root string, tr *tar.Reader, options ApplyO
|
||||
srcData := io.Reader(tr)
|
||||
srcHdr := hdr
|
||||
|
||||
// Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so
|
||||
// we manually retarget these into the temporary files we extracted them into
|
||||
if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), whiteoutLinkDir) {
|
||||
linkBasename := filepath.Base(hdr.Linkname)
|
||||
srcHdr = aufsHardlinks[linkBasename]
|
||||
if srcHdr == nil {
|
||||
return 0, fmt.Errorf("invalid aufs hardlink")
|
||||
}
|
||||
p, err := fs.RootPath(aufsTempdir, linkBasename)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
tmpFile, err := os.Open(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer tmpFile.Close()
|
||||
srcData = tmpFile
|
||||
}
|
||||
|
||||
if err := createTarFile(ctx, path, root, srcHdr, srcData); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -428,6 +379,66 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header
|
||||
return chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime))
|
||||
}
|
||||
|
||||
func mkparent(ctx context.Context, path, root string, parents []string) error {
|
||||
if dir, err := os.Lstat(path); err == nil {
|
||||
if dir.IsDir() {
|
||||
return nil
|
||||
}
|
||||
return &os.PathError{
|
||||
Op: "mkparent",
|
||||
Path: path,
|
||||
Err: syscall.ENOTDIR,
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
i := len(path)
|
||||
for i > len(root) && !os.IsPathSeparator(path[i-1]) {
|
||||
i--
|
||||
}
|
||||
|
||||
if i > len(root)+1 {
|
||||
if err := mkparent(ctx, path[:i-1], root, parents); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := mkdir(path, 0755); err != nil {
|
||||
// Check that still doesn't exist
|
||||
dir, err1 := os.Lstat(path)
|
||||
if err1 == nil && dir.IsDir() {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
for _, p := range parents {
|
||||
ppath, err := fs.RootPath(p, path[len(root):])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dir, err := os.Lstat(ppath)
|
||||
if err == nil {
|
||||
if !dir.IsDir() {
|
||||
// Replaced, do not copy attributes
|
||||
break
|
||||
}
|
||||
if err := copyDirInfo(dir, path); err != nil {
|
||||
return err
|
||||
}
|
||||
return copyUpXAttrs(path, ppath)
|
||||
} else if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.G(ctx).Debugf("parent directory %q not found: default permissions(0755) used", path)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type changeWriter struct {
|
||||
tw *tar.Writer
|
||||
source string
|
||||
@ -493,6 +504,12 @@ func (cw *changeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
|
||||
|
||||
hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
|
||||
|
||||
// truncate timestamp for compatibility. without PAX stdlib rounds timestamps instead
|
||||
hdr.Format = tar.FormatPAX
|
||||
hdr.ModTime = hdr.ModTime.Truncate(time.Second)
|
||||
hdr.AccessTime = time.Time{}
|
||||
hdr.ChangeTime = time.Time{}
|
||||
|
||||
name := p
|
||||
if strings.HasPrefix(name, string(filepath.Separator)) {
|
||||
name, err = filepath.Rel(string(filepath.Separator), name)
|
||||
@ -598,6 +615,9 @@ func (cw *changeWriter) Close() error {
|
||||
}
|
||||
|
||||
func (cw *changeWriter) includeParents(hdr *tar.Header) error {
|
||||
if cw.addedDirs == nil {
|
||||
return nil
|
||||
}
|
||||
name := strings.TrimRight(hdr.Name, "/")
|
||||
fname := filepath.Join(cw.source, name)
|
||||
parent := filepath.Dir(name)
|
||||
@ -684,3 +704,26 @@ func hardlinkRootPath(root, linkname string) (string, error) {
|
||||
}
|
||||
return targetPath, nil
|
||||
}
|
||||
|
||||
func validateWhiteout(path string) error {
|
||||
base := filepath.Base(path)
|
||||
dir := filepath.Dir(path)
|
||||
|
||||
if base == whiteoutOpaqueDir {
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(base, whiteoutPrefix) {
|
||||
originalBase := base[len(whiteoutPrefix):]
|
||||
originalPath := filepath.Join(dir, originalBase)
|
||||
|
||||
// Ensure originalPath is under dir
|
||||
if dir[len(dir)-1] != filepath.Separator {
|
||||
dir += string(filepath.Separator)
|
||||
}
|
||||
if !strings.HasPrefix(originalPath, dir) {
|
||||
return errors.Wrapf(errInvalidArchive, "invalid whiteout name: %v", base)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
38
vendor/github.com/containerd/containerd/archive/tar_opts.go
generated
vendored
38
vendor/github.com/containerd/containerd/archive/tar_opts.go
generated
vendored
@ -16,7 +16,19 @@
|
||||
|
||||
package archive
|
||||
|
||||
import "archive/tar"
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
)
|
||||
|
||||
// ApplyOptions provides additional options for an Apply operation
|
||||
type ApplyOptions struct {
|
||||
Filter Filter // Filter tar headers
|
||||
ConvertWhiteout ConvertWhiteout // Convert whiteout files
|
||||
Parents []string // Parent directories to handle inherited attributes without CoW
|
||||
|
||||
applyFunc func(context.Context, string, *tar.Reader, ApplyOptions) (int64, error)
|
||||
}
|
||||
|
||||
// ApplyOpt allows setting mutable archive apply properties on creation
|
||||
type ApplyOpt func(options *ApplyOptions) error
|
||||
@ -24,6 +36,9 @@ type ApplyOpt func(options *ApplyOptions) error
|
||||
// Filter specific files from the archive
|
||||
type Filter func(*tar.Header) (bool, error)
|
||||
|
||||
// ConvertWhiteout converts whiteout files from the archive
|
||||
type ConvertWhiteout func(*tar.Header, string) (bool, error)
|
||||
|
||||
// all allows all files
|
||||
func all(_ *tar.Header) (bool, error) {
|
||||
return true, nil
|
||||
@ -36,3 +51,24 @@ func WithFilter(f Filter) ApplyOpt {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithConvertWhiteout uses the convert function to convert the whiteout files.
|
||||
func WithConvertWhiteout(c ConvertWhiteout) ApplyOpt {
|
||||
return func(options *ApplyOptions) error {
|
||||
options.ConvertWhiteout = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithParents provides parent directories for resolving inherited attributes
|
||||
// directory from the filesystem.
|
||||
// Inherited attributes are searched from first to last, making the first
|
||||
// element in the list the most immediate parent directory.
|
||||
// NOTE: When applying to a filesystem which supports CoW, file attributes
|
||||
// should be inherited by the filesystem.
|
||||
func WithParents(p []string) ApplyOpt {
|
||||
return func(options *ApplyOptions) error {
|
||||
options.Parents = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
59
vendor/github.com/containerd/containerd/archive/tar_opts_linux.go
generated
vendored
Normal file
59
vendor/github.com/containerd/containerd/archive/tar_opts_linux.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
// +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 archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// AufsConvertWhiteout converts whiteout files for aufs.
|
||||
func AufsConvertWhiteout(_ *tar.Header, _ string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// OverlayConvertWhiteout converts whiteout files for overlay.
|
||||
func OverlayConvertWhiteout(hdr *tar.Header, path string) (bool, error) {
|
||||
base := filepath.Base(path)
|
||||
dir := filepath.Dir(path)
|
||||
|
||||
// if a directory is marked as opaque, we need to translate that to overlay
|
||||
if base == whiteoutOpaqueDir {
|
||||
// don't write the file itself
|
||||
return false, unix.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0)
|
||||
}
|
||||
|
||||
// if a file was deleted and we are using overlay, we need to create a character device
|
||||
if strings.HasPrefix(base, whiteoutPrefix) {
|
||||
originalBase := base[len(whiteoutPrefix):]
|
||||
originalPath := filepath.Join(dir, originalBase)
|
||||
|
||||
if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil {
|
||||
return false, err
|
||||
}
|
||||
// don't write the file itself
|
||||
return false, os.Chown(originalPath, hdr.Uid, hdr.Gid)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
24
vendor/github.com/containerd/containerd/archive/tar_opts_unix.go
generated
vendored
24
vendor/github.com/containerd/containerd/archive/tar_opts_unix.go
generated
vendored
@ -1,24 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
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 archive
|
||||
|
||||
// ApplyOptions provides additional options for an Apply operation
|
||||
type ApplyOptions struct {
|
||||
Filter Filter // Filter tar headers
|
||||
}
|
18
vendor/github.com/containerd/containerd/archive/tar_opts_windows.go
generated
vendored
18
vendor/github.com/containerd/containerd/archive/tar_opts_windows.go
generated
vendored
@ -18,28 +18,12 @@
|
||||
|
||||
package archive
|
||||
|
||||
// ApplyOptions provides additional options for an Apply operation
|
||||
type ApplyOptions struct {
|
||||
ParentLayerPaths []string // Parent layer paths used for Windows layer apply
|
||||
IsWindowsContainerLayer bool // True if the tar stream to be applied is a Windows Container Layer
|
||||
Filter Filter // Filter tar headers
|
||||
}
|
||||
|
||||
// WithParentLayers adds parent layers to the apply process this is required
|
||||
// for all Windows layers except the base layer.
|
||||
func WithParentLayers(parentPaths []string) ApplyOpt {
|
||||
return func(options *ApplyOptions) error {
|
||||
options.ParentLayerPaths = parentPaths
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AsWindowsContainerLayer indicates that the tar stream to apply is that of
|
||||
// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
|
||||
// SeRestorePrivilege.
|
||||
func AsWindowsContainerLayer() ApplyOpt {
|
||||
return func(options *ApplyOptions) error {
|
||||
options.IsWindowsContainerLayer = true
|
||||
options.applyFunc = applyWindowsLayer
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
77
vendor/github.com/containerd/containerd/archive/tar_unix.go
generated
vendored
77
vendor/github.com/containerd/containerd/archive/tar_unix.go
generated
vendored
@ -20,11 +20,12 @@ package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
"github.com/pkg/errors"
|
||||
@ -74,10 +75,6 @@ func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
return f, err
|
||||
}
|
||||
|
||||
func mkdirAll(path string, perm os.FileMode) error {
|
||||
return os.MkdirAll(path, perm)
|
||||
}
|
||||
|
||||
func mkdir(path string, perm os.FileMode) error {
|
||||
if err := os.Mkdir(path, perm); err != nil {
|
||||
return err
|
||||
@ -149,11 +146,71 @@ func getxattr(path, attr string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func setxattr(path, key, value string) error {
|
||||
return sysx.LSetxattr(path, key, []byte(value), 0)
|
||||
// Do not set trusted attributes
|
||||
if strings.HasPrefix(key, "trusted.") {
|
||||
return errors.Wrap(unix.ENOTSUP, "admin attributes from archive not supported")
|
||||
}
|
||||
return unix.Lsetxattr(path, key, []byte(value), 0)
|
||||
}
|
||||
|
||||
// apply applies a tar stream of an OCI style diff tar.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
||||
func apply(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
||||
return applyNaive(ctx, root, tr, options)
|
||||
func copyDirInfo(fi os.FileInfo, path string) error {
|
||||
st := fi.Sys().(*syscall.Stat_t)
|
||||
if err := os.Lchown(path, int(st.Uid), int(st.Gid)); err != nil {
|
||||
if os.IsPermission(err) {
|
||||
// Normally if uid/gid are the same this would be a no-op, but some
|
||||
// filesystems may still return EPERM... for instance NFS does this.
|
||||
// In such a case, this is not an error.
|
||||
if dstStat, err2 := os.Lstat(path); err2 == nil {
|
||||
st2 := dstStat.Sys().(*syscall.Stat_t)
|
||||
if st.Uid == st2.Uid && st.Gid == st2.Gid {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to chown %s", path)
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Chmod(path, fi.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to chmod %s", path)
|
||||
}
|
||||
|
||||
timespec := []unix.Timespec{unix.Timespec(fs.StatAtime(st)), unix.Timespec(fs.StatMtime(st))}
|
||||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, path, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
||||
return errors.Wrapf(err, "failed to utime %s", path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyUpXAttrs(dst, src string) error {
|
||||
xattrKeys, err := sysx.LListxattr(src)
|
||||
if err != nil {
|
||||
if err == unix.ENOTSUP || err == sysx.ENODATA {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(err, "failed to list xattrs on %s", src)
|
||||
}
|
||||
for _, xattr := range xattrKeys {
|
||||
// Do not copy up trusted attributes
|
||||
if strings.HasPrefix(xattr, "trusted.") {
|
||||
continue
|
||||
}
|
||||
data, err := sysx.LGetxattr(src, xattr)
|
||||
if err != nil {
|
||||
if err == unix.ENOTSUP || err == sysx.ENODATA {
|
||||
continue
|
||||
}
|
||||
return errors.Wrapf(err, "failed to get xattr %q on %s", xattr, src)
|
||||
}
|
||||
if err := unix.Lsetxattr(dst, xattr, data, unix.XATTR_CREATE); err != nil {
|
||||
if err == unix.ENOTSUP || err == unix.ENODATA || err == unix.EEXIST {
|
||||
continue
|
||||
}
|
||||
return errors.Wrapf(err, "failed to set xattr %q on %s", xattr, dst)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
31
vendor/github.com/containerd/containerd/archive/tar_windows.go
generated
vendored
31
vendor/github.com/containerd/containerd/archive/tar_windows.go
generated
vendored
@ -23,7 +23,6 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -36,6 +35,7 @@ import (
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/containerd/containerd/sys"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -107,10 +107,6 @@ func openFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
return sys.OpenFileSequential(name, flag, perm)
|
||||
}
|
||||
|
||||
func mkdirAll(path string, perm os.FileMode) error {
|
||||
return sys.MkdirAll(path, perm)
|
||||
}
|
||||
|
||||
func mkdir(path string, perm os.FileMode) error {
|
||||
return os.Mkdir(path, perm)
|
||||
}
|
||||
@ -153,16 +149,8 @@ func setxattr(path, key, value string) error {
|
||||
return errors.New("xattrs not supported on Windows")
|
||||
}
|
||||
|
||||
// apply applies a tar stream of an OCI style diff tar of a Windows layer.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
||||
func apply(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
||||
if options.IsWindowsContainerLayer {
|
||||
return applyWindowsLayer(ctx, root, tr, options)
|
||||
}
|
||||
return applyNaive(ctx, root, tr, options)
|
||||
}
|
||||
|
||||
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows layer.
|
||||
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows
|
||||
// layer using the hcsshim layer writer and backup streams.
|
||||
// See https://github.com/opencontainers/image-spec/blob/master/layer.md#applying-changesets
|
||||
func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options ApplyOptions) (size int64, err error) {
|
||||
home, id := filepath.Split(root)
|
||||
@ -170,7 +158,7 @@ func applyWindowsLayer(ctx context.Context, root string, tr *tar.Reader, options
|
||||
HomeDir: home,
|
||||
}
|
||||
|
||||
w, err := hcsshim.NewLayerWriter(info, id, options.ParentLayerPaths)
|
||||
w, err := hcsshim.NewLayerWriter(info, id, options.Parents)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -443,3 +431,14 @@ func writeBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func copyDirInfo(fi os.FileInfo, path string) error {
|
||||
if err := os.Chmod(path, fi.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "failed to chmod %s", path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyUpXAttrs(dst, src string) error {
|
||||
return nil
|
||||
}
|
||||
|
2
vendor/github.com/containerd/containerd/archive/time_unix.go
generated
vendored
2
vendor/github.com/containerd/containerd/archive/time_unix.go
generated
vendored
@ -32,7 +32,7 @@ func chtimes(path string, atime, mtime time.Time) error {
|
||||
utimes[1] = unix.NsecToTimespec(mtime.UnixNano())
|
||||
|
||||
if err := unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW); err != nil {
|
||||
return errors.Wrap(err, "failed call to UtimesNanoAt")
|
||||
return errors.Wrapf(err, "failed call to UtimesNanoAt for %s", path)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
29
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
29
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
@ -18,10 +18,13 @@ package cio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/defaults"
|
||||
@ -242,17 +245,24 @@ func LogURI(uri *url.URL) Creator {
|
||||
// BinaryIO forwards container STDOUT|STDERR directly to a logging binary
|
||||
func BinaryIO(binary string, args map[string]string) Creator {
|
||||
return func(_ string) (IO, error) {
|
||||
binary = filepath.Clean(binary)
|
||||
if !strings.HasPrefix(binary, "/") {
|
||||
return nil, errors.New("absolute path needed")
|
||||
}
|
||||
uri := &url.URL{
|
||||
Scheme: "binary",
|
||||
Host: binary,
|
||||
Path: binary,
|
||||
}
|
||||
q := uri.Query()
|
||||
for k, v := range args {
|
||||
uri.Query().Set(k, v)
|
||||
q.Set(k, v)
|
||||
}
|
||||
uri.RawQuery = q.Encode()
|
||||
res := uri.String()
|
||||
return &logURI{
|
||||
config: Config{
|
||||
Stdout: uri.String(),
|
||||
Stderr: uri.String(),
|
||||
Stdout: res,
|
||||
Stderr: res,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@ -262,14 +272,19 @@ func BinaryIO(binary string, args map[string]string) Creator {
|
||||
// If the log file already exists, the logs will be appended to the file.
|
||||
func LogFile(path string) Creator {
|
||||
return func(_ string) (IO, error) {
|
||||
path = filepath.Clean(path)
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
return nil, errors.New("absolute path needed")
|
||||
}
|
||||
uri := &url.URL{
|
||||
Scheme: "file",
|
||||
Host: path,
|
||||
Path: path,
|
||||
}
|
||||
res := uri.String()
|
||||
return &logURI{
|
||||
config: Config{
|
||||
Stdout: uri.String(),
|
||||
Stderr: uri.String(),
|
||||
Stdout: res,
|
||||
Stderr: res,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
20
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
20
vendor/github.com/containerd/containerd/cio/io_unix.go
generated
vendored
@ -72,17 +72,19 @@ func copyIO(fifos *FIFOSet, ioset *Streams) (*cio, error) {
|
||||
}
|
||||
|
||||
var wg = &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
if fifos.Stdout != "" {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
|
||||
io.CopyBuffer(ioset.Stdout, pipes.Stdout, *p)
|
||||
pipes.Stdout.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
io.CopyBuffer(ioset.Stdout, pipes.Stdout, *p)
|
||||
pipes.Stdout.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
if !fifos.Terminal {
|
||||
if !fifos.Terminal && fifos.Stderr != "" {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
p := bufPool.Get().(*[]byte)
|
||||
|
159
vendor/github.com/containerd/containerd/client.go
generated
vendored
159
vendor/github.com/containerd/containerd/client.go
generated
vendored
@ -43,6 +43,7 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
contentproxy "github.com/containerd/containerd/content/proxy"
|
||||
"github.com/containerd/containerd/defaults"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/events"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/leases"
|
||||
@ -56,6 +57,7 @@ import (
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
snproxy "github.com/containerd/containerd/snapshots/proxy"
|
||||
"github.com/containerd/typeurl"
|
||||
"github.com/gogo/protobuf/types"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
@ -86,13 +88,23 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
||||
if copts.timeout == 0 {
|
||||
copts.timeout = 10 * time.Second
|
||||
}
|
||||
rt := fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS)
|
||||
if copts.defaultRuntime != "" {
|
||||
rt = copts.defaultRuntime
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
runtime: rt,
|
||||
defaultns: copts.defaultns,
|
||||
}
|
||||
|
||||
if copts.defaultRuntime != "" {
|
||||
c.runtime = copts.defaultRuntime
|
||||
} else {
|
||||
c.runtime = defaults.DefaultRuntime
|
||||
}
|
||||
|
||||
if copts.defaultPlatform != nil {
|
||||
c.platform = copts.defaultPlatform
|
||||
} else {
|
||||
c.platform = platforms.Default()
|
||||
}
|
||||
|
||||
if copts.services != nil {
|
||||
c.services = *copts.services
|
||||
}
|
||||
@ -102,7 +114,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
||||
grpc.WithInsecure(),
|
||||
grpc.FailOnNonTempDialError(true),
|
||||
grpc.WithBackoffMaxDelay(3 * time.Second),
|
||||
grpc.WithDialer(dialer.Dialer),
|
||||
grpc.WithContextDialer(dialer.ContextDialer),
|
||||
|
||||
// TODO(stevvooe): We may need to allow configuration of this on the client.
|
||||
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),
|
||||
@ -134,19 +146,15 @@ func New(address string, opts ...ClientOpt) (*Client, error) {
|
||||
c.conn, c.connector = conn, connector
|
||||
}
|
||||
if copts.services == nil && c.conn == nil {
|
||||
return nil, errors.New("no grpc connection or services is available")
|
||||
return nil, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection or services is available")
|
||||
}
|
||||
|
||||
// check namespace labels for default runtime
|
||||
if copts.defaultRuntime == "" && copts.defaultns != "" {
|
||||
namespaces := c.NamespaceService()
|
||||
ctx := context.Background()
|
||||
if labels, err := namespaces.Labels(ctx, copts.defaultns); err == nil {
|
||||
if defaultRuntime, ok := labels[defaults.DefaultRuntimeNSLabel]; ok {
|
||||
c.runtime = defaultRuntime
|
||||
}
|
||||
} else {
|
||||
if copts.defaultRuntime == "" && c.defaultns != "" {
|
||||
if label, err := c.GetLabel(context.Background(), defaults.DefaultRuntimeNSLabel); err != nil {
|
||||
return nil, err
|
||||
} else if label != "" {
|
||||
c.runtime = label
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,20 +171,17 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
|
||||
}
|
||||
}
|
||||
c := &Client{
|
||||
conn: conn,
|
||||
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
||||
defaultns: copts.defaultns,
|
||||
conn: conn,
|
||||
runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS),
|
||||
}
|
||||
|
||||
// check namespace labels for default runtime
|
||||
if copts.defaultRuntime == "" && copts.defaultns != "" {
|
||||
namespaces := c.NamespaceService()
|
||||
ctx := context.Background()
|
||||
if labels, err := namespaces.Labels(ctx, copts.defaultns); err == nil {
|
||||
if defaultRuntime, ok := labels[defaults.DefaultRuntimeNSLabel]; ok {
|
||||
c.runtime = defaultRuntime
|
||||
}
|
||||
} else {
|
||||
if copts.defaultRuntime == "" && c.defaultns != "" {
|
||||
if label, err := c.GetLabel(context.Background(), defaults.DefaultRuntimeNSLabel); err != nil {
|
||||
return nil, err
|
||||
} else if label != "" {
|
||||
c.runtime = label
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,13 +198,15 @@ type Client struct {
|
||||
connMu sync.Mutex
|
||||
conn *grpc.ClientConn
|
||||
runtime string
|
||||
defaultns string
|
||||
platform platforms.MatchComparer
|
||||
connector func() (*grpc.ClientConn, error)
|
||||
}
|
||||
|
||||
// Reconnect re-establishes the GRPC connection to the containerd daemon
|
||||
func (c *Client) Reconnect() error {
|
||||
if c.connector == nil {
|
||||
return errors.New("unable to reconnect to containerd, no connector available")
|
||||
return errors.Wrap(errdefs.ErrUnavailable, "unable to reconnect to containerd, no connector available")
|
||||
}
|
||||
c.connMu.Lock()
|
||||
defer c.connMu.Unlock()
|
||||
@ -222,10 +229,10 @@ func (c *Client) IsServing(ctx context.Context) (bool, error) {
|
||||
c.connMu.Lock()
|
||||
if c.conn == nil {
|
||||
c.connMu.Unlock()
|
||||
return false, errors.New("no grpc connection available")
|
||||
return false, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available")
|
||||
}
|
||||
c.connMu.Unlock()
|
||||
r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.FailFast(false))
|
||||
r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -294,10 +301,14 @@ type RemoteContext struct {
|
||||
PlatformMatcher platforms.MatchComparer
|
||||
|
||||
// Unpack is done after an image is pulled to extract into a snapshotter.
|
||||
// It is done simultaneously for schema 2 images when they are pulled.
|
||||
// If an image is not unpacked on pull, it can be unpacked any time
|
||||
// afterwards. Unpacking is required to run an image.
|
||||
Unpack bool
|
||||
|
||||
// UnpackOpts handles options to the unpack call.
|
||||
UnpackOpts []UnpackOpt
|
||||
|
||||
// Snapshotter used for unpacking
|
||||
Snapshotter string
|
||||
|
||||
@ -329,9 +340,8 @@ type RemoteContext struct {
|
||||
// MaxConcurrentDownloads is the max concurrent content downloads for each pull.
|
||||
MaxConcurrentDownloads int
|
||||
|
||||
// AppendDistributionSourceLabel allows fetcher to add distribute source
|
||||
// label for each blob content, which doesn't work for legacy schema1.
|
||||
AppendDistributionSourceLabel bool
|
||||
// AllMetadata downloads all manifests and known-configuration files
|
||||
AllMetadata bool
|
||||
}
|
||||
|
||||
func defaultRemoteContext() *RemoteContext {
|
||||
@ -339,7 +349,6 @@ func defaultRemoteContext() *RemoteContext {
|
||||
Resolver: docker.NewResolver(docker.ResolverOptions{
|
||||
Client: http.DefaultClient,
|
||||
}),
|
||||
Snapshotter: DefaultSnapshotter,
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +363,7 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag
|
||||
}
|
||||
|
||||
if fetchCtx.Unpack {
|
||||
return images.Image{}, errors.New("unpack on fetch not supported, try pull")
|
||||
return images.Image{}, errors.Wrap(errdefs.ErrNotImplemented, "unpack on fetch not supported, try pull")
|
||||
}
|
||||
|
||||
if fetchCtx.PlatformMatcher == nil {
|
||||
@ -407,6 +416,11 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor,
|
||||
}
|
||||
}
|
||||
|
||||
// Annotate ref with digest to push only push tag for single digest
|
||||
if !strings.Contains(ref, "@") {
|
||||
ref = ref + "@" + desc.Digest.String()
|
||||
}
|
||||
|
||||
pusher, err := pushCtx.Resolver.Pusher(ctx, ref)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -490,6 +504,27 @@ func writeIndex(ctx context.Context, index *ocispec.Index, client *Client, ref s
|
||||
return writeContent(ctx, client.ContentStore(), ocispec.MediaTypeImageIndex, ref, bytes.NewReader(data), content.WithLabels(labels))
|
||||
}
|
||||
|
||||
// GetLabel gets a label value from namespace store
|
||||
// If there is no default label, an empty string returned with nil error
|
||||
func (c *Client) GetLabel(ctx context.Context, label string) (string, error) {
|
||||
ns, err := namespaces.NamespaceRequired(ctx)
|
||||
if err != nil {
|
||||
if c.defaultns == "" {
|
||||
return "", err
|
||||
}
|
||||
ns = c.defaultns
|
||||
}
|
||||
|
||||
srv := c.NamespaceService()
|
||||
labels, err := srv.Labels(ctx, ns)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
value := labels[label]
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// Subscribe to events that match one or more of the provided filters.
|
||||
//
|
||||
// Callers should listen on both the envelope and errs channels. If the errs
|
||||
@ -543,6 +578,10 @@ func (c *Client) ContentStore() content.Store {
|
||||
|
||||
// SnapshotService returns the underlying snapshotter for the provided snapshotter name
|
||||
func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter {
|
||||
snapshotterName, err := c.resolveSnapshotterName(context.Background(), snapshotterName)
|
||||
if err != nil {
|
||||
snapshotterName = DefaultSnapshotter
|
||||
}
|
||||
if c.snapshotters != nil {
|
||||
return c.snapshotters[snapshotterName]
|
||||
}
|
||||
@ -642,7 +681,7 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
|
||||
c.connMu.Lock()
|
||||
if c.conn == nil {
|
||||
c.connMu.Unlock()
|
||||
return Version{}, errors.New("no grpc connection available")
|
||||
return Version{}, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available")
|
||||
}
|
||||
c.connMu.Unlock()
|
||||
response, err := c.VersionService().Version(ctx, &ptypes.Empty{})
|
||||
@ -655,6 +694,58 @@ func (c *Client) Version(ctx context.Context) (Version, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ServerInfo struct {
|
||||
UUID string
|
||||
}
|
||||
|
||||
func (c *Client) Server(ctx context.Context) (ServerInfo, error) {
|
||||
c.connMu.Lock()
|
||||
if c.conn == nil {
|
||||
c.connMu.Unlock()
|
||||
return ServerInfo{}, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available")
|
||||
}
|
||||
c.connMu.Unlock()
|
||||
|
||||
response, err := c.IntrospectionService().Server(ctx, &types.Empty{})
|
||||
if err != nil {
|
||||
return ServerInfo{}, err
|
||||
}
|
||||
return ServerInfo{
|
||||
UUID: response.UUID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) resolveSnapshotterName(ctx context.Context, name string) (string, error) {
|
||||
if name == "" {
|
||||
label, err := c.GetLabel(ctx, defaults.DefaultSnapshotterNSLabel)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if label != "" {
|
||||
name = label
|
||||
} else {
|
||||
name = DefaultSnapshotter
|
||||
}
|
||||
}
|
||||
|
||||
return name, nil
|
||||
}
|
||||
|
||||
func (c *Client) getSnapshotter(ctx context.Context, name string) (snapshots.Snapshotter, error) {
|
||||
name, err := c.resolveSnapshotterName(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := c.SnapshotService(name)
|
||||
if s == nil {
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "snapshotter %s was not found", name)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// CheckRuntime returns true if the current runtime matches the expected
|
||||
// runtime. Providing various parts of the runtime schema will match those
|
||||
// parts of the expected runtime
|
||||
|
26
vendor/github.com/containerd/containerd/client_opts.go
generated
vendored
26
vendor/github.com/containerd/containerd/client_opts.go
generated
vendored
@ -26,11 +26,12 @@ import (
|
||||
)
|
||||
|
||||
type clientOpts struct {
|
||||
defaultns string
|
||||
defaultRuntime string
|
||||
services *services
|
||||
dialOptions []grpc.DialOption
|
||||
timeout time.Duration
|
||||
defaultns string
|
||||
defaultRuntime string
|
||||
defaultPlatform platforms.MatchComparer
|
||||
services *services
|
||||
dialOptions []grpc.DialOption
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// ClientOpt allows callers to set options on the containerd client
|
||||
@ -55,6 +56,14 @@ func WithDefaultRuntime(rt string) ClientOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultPlatform sets the default platform matcher on the client
|
||||
func WithDefaultPlatform(platform platforms.MatchComparer) ClientOpt {
|
||||
return func(c *clientOpts) error {
|
||||
c.defaultPlatform = platform
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDialOpts allows grpc.DialOptions to be set on the connection
|
||||
func WithDialOpts(opts []grpc.DialOption) ClientOpt {
|
||||
return func(c *clientOpts) error {
|
||||
@ -195,11 +204,10 @@ func WithMaxConcurrentDownloads(max int) RemoteOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithAppendDistributionSourceLabel allows fetcher to add distribute source
|
||||
// label for each blob content, which doesn't work for legacy schema1.
|
||||
func WithAppendDistributionSourceLabel() RemoteOpt {
|
||||
// WithAllMetadata downloads all manifests and known-configuration files
|
||||
func WithAllMetadata() RemoteOpt {
|
||||
return func(_ *Client, c *RemoteContext) error {
|
||||
c.AppendDistributionSourceLabel = true
|
||||
c.AllMetadata = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
41
vendor/github.com/containerd/containerd/container.go
generated
vendored
41
vendor/github.com/containerd/containerd/container.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||
"github.com/containerd/containerd/api/types"
|
||||
tasktypes "github.com/containerd/containerd/api/types/task"
|
||||
"github.com/containerd/containerd/cio"
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
@ -49,7 +50,7 @@ type Container interface {
|
||||
// ID identifies the container
|
||||
ID() string
|
||||
// Info returns the underlying container record type
|
||||
Info(context.Context) (containers.Container, error)
|
||||
Info(context.Context, ...InfoOpts) (containers.Container, error)
|
||||
// Delete removes the container
|
||||
Delete(context.Context, ...DeleteOpts) error
|
||||
// NewTask creates a new task based on the container metadata
|
||||
@ -80,16 +81,18 @@ type Container interface {
|
||||
|
||||
func containerFromRecord(client *Client, c containers.Container) *container {
|
||||
return &container{
|
||||
client: client,
|
||||
id: c.ID,
|
||||
client: client,
|
||||
id: c.ID,
|
||||
metadata: c,
|
||||
}
|
||||
}
|
||||
|
||||
var _ = (Container)(&container{})
|
||||
|
||||
type container struct {
|
||||
client *Client
|
||||
id string
|
||||
client *Client
|
||||
id string
|
||||
metadata containers.Container
|
||||
}
|
||||
|
||||
// ID returns the container's unique id
|
||||
@ -97,8 +100,22 @@ func (c *container) ID() string {
|
||||
return c.id
|
||||
}
|
||||
|
||||
func (c *container) Info(ctx context.Context) (containers.Container, error) {
|
||||
return c.get(ctx)
|
||||
func (c *container) Info(ctx context.Context, opts ...InfoOpts) (containers.Container, error) {
|
||||
i := &InfoConfig{
|
||||
// default to refreshing the container's local metadata
|
||||
Refresh: true,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(i)
|
||||
}
|
||||
if i.Refresh {
|
||||
metadata, err := c.get(ctx)
|
||||
if err != nil {
|
||||
return c.metadata, err
|
||||
}
|
||||
c.metadata = metadata
|
||||
}
|
||||
return c.metadata, nil
|
||||
}
|
||||
|
||||
func (c *container) Extensions(ctx context.Context) (map[string]prototypes.Any, error) {
|
||||
@ -217,7 +234,11 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N
|
||||
}
|
||||
|
||||
// get the rootfs from the snapshotter and add it to the request
|
||||
mounts, err := c.client.SnapshotService(r.Snapshotter).Mounts(ctx, r.SnapshotKey)
|
||||
s, err := c.client.getSnapshotter(ctx, r.Snapshotter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mounts, err := s.Mounts(ctx, r.SnapshotKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -362,7 +383,9 @@ func (c *container) loadTask(ctx context.Context, ioAttach cio.Attach) (Task, er
|
||||
return nil, err
|
||||
}
|
||||
var i cio.IO
|
||||
if ioAttach != nil {
|
||||
if ioAttach != nil && response.Process.Status != tasktypes.StatusUnknown {
|
||||
// Do not attach IO for task in unknown state, because there
|
||||
// are no fifo paths anyway.
|
||||
if i, err = attachExistingIO(response, ioAttach); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
88
vendor/github.com/containerd/containerd/container_opts.go
generated
vendored
88
vendor/github.com/containerd/containerd/container_opts.go
generated
vendored
@ -20,11 +20,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/defaults"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
"github.com/containerd/typeurl"
|
||||
"github.com/gogo/protobuf/types"
|
||||
@ -41,6 +38,15 @@ type NewContainerOpts func(ctx context.Context, client *Client, c *containers.Co
|
||||
// UpdateContainerOpts allows the caller to set additional options when updating a container
|
||||
type UpdateContainerOpts func(ctx context.Context, client *Client, c *containers.Container) error
|
||||
|
||||
// InfoOpts controls how container metadata is fetched and returned
|
||||
type InfoOpts func(*InfoConfig)
|
||||
|
||||
// InfoConfig specifies how container metadata is fetched
|
||||
type InfoConfig struct {
|
||||
// Refresh will to a fetch of the latest container metadata
|
||||
Refresh bool
|
||||
}
|
||||
|
||||
// WithRuntime allows a user to specify the runtime name and additional options that should
|
||||
// be used to create tasks for the container
|
||||
func WithRuntime(name string, options interface{}) NewContainerOpts {
|
||||
@ -71,6 +77,14 @@ func WithImage(i Image) NewContainerOpts {
|
||||
}
|
||||
}
|
||||
|
||||
// WithImageName allows setting the image name as the base for the container
|
||||
func WithImageName(n string) NewContainerOpts {
|
||||
return func(ctx context.Context, _ *Client, c *containers.Container) error {
|
||||
c.Image = n
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithContainerLabels adds the provided labels to the container
|
||||
func WithContainerLabels(labels map[string]string) NewContainerOpts {
|
||||
return func(_ context.Context, _ *Client, c *containers.Container) error {
|
||||
@ -109,9 +123,17 @@ func WithSnapshotter(name string) NewContainerOpts {
|
||||
// WithSnapshot uses an existing root filesystem for the container
|
||||
func WithSnapshot(id string) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
setSnapshotterIfEmpty(ctx, client, c)
|
||||
// check that the snapshot exists, if not, fail on creation
|
||||
if _, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, id); err != nil {
|
||||
var err error
|
||||
c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := client.getSnapshotter(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := s.Mounts(ctx, id); err != nil {
|
||||
return err
|
||||
}
|
||||
c.SnapshotKey = id
|
||||
@ -123,13 +145,21 @@ func WithSnapshot(id string) NewContainerOpts {
|
||||
// root filesystem in read-write mode
|
||||
func WithNewSnapshot(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
|
||||
diffIDs, err := i.RootFS(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setSnapshotterIfEmpty(ctx, client, c)
|
||||
|
||||
parent := identity.ChainID(diffIDs).String()
|
||||
if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent, opts...); err != nil {
|
||||
c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := client.getSnapshotter(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := s.Prepare(ctx, id, parent, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
c.SnapshotKey = id
|
||||
@ -144,7 +174,13 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta
|
||||
if c.Snapshotter == "" {
|
||||
return errors.Wrapf(errdefs.ErrInvalidArgument, "container.Snapshotter must be set to cleanup rootfs snapshot")
|
||||
}
|
||||
return client.SnapshotService(c.Snapshotter).Remove(ctx, c.SnapshotKey)
|
||||
s, err := client.getSnapshotter(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.Remove(ctx, c.SnapshotKey); err != nil && !errdefs.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -153,13 +189,21 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta
|
||||
// root filesystem in read-only mode
|
||||
func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setSnapshotterIfEmpty(ctx, client, c)
|
||||
|
||||
parent := identity.ChainID(diffIDs).String()
|
||||
if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent, opts...); err != nil {
|
||||
c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := client.getSnapshotter(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := s.View(ctx, id, parent, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
c.SnapshotKey = id
|
||||
@ -168,21 +212,6 @@ func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainer
|
||||
}
|
||||
}
|
||||
|
||||
func setSnapshotterIfEmpty(ctx context.Context, client *Client, c *containers.Container) {
|
||||
if c.Snapshotter == "" {
|
||||
defaultSnapshotter := DefaultSnapshotter
|
||||
namespaceService := client.NamespaceService()
|
||||
if ns, err := namespaces.NamespaceRequired(ctx); err == nil {
|
||||
if labels, err := namespaceService.Labels(ctx, ns); err == nil {
|
||||
if snapshotLabel, ok := labels[defaults.DefaultSnapshotterNSLabel]; ok {
|
||||
defaultSnapshotter = snapshotLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
c.Snapshotter = defaultSnapshotter
|
||||
}
|
||||
}
|
||||
|
||||
// WithContainerExtension appends extension data to the container object.
|
||||
// Use this to decorate the container object with additional data for the client
|
||||
// integration.
|
||||
@ -235,3 +264,8 @@ func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// WithoutRefreshedMetadata will use the current metadata attached to the container object
|
||||
func WithoutRefreshedMetadata(i *InfoConfig) {
|
||||
i.Refresh = false
|
||||
}
|
||||
|
18
vendor/github.com/containerd/containerd/container_opts_unix.go
generated
vendored
18
vendor/github.com/containerd/containerd/container_opts_unix.go
generated
vendored
@ -28,7 +28,6 @@ import (
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
)
|
||||
|
||||
@ -45,18 +44,23 @@ func WithRemappedSnapshotView(id string, i Image, uid, gid uint32) NewContainerO
|
||||
|
||||
func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool) NewContainerOpts {
|
||||
return func(ctx context.Context, client *Client, c *containers.Container) error {
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setSnapshotterIfEmpty(ctx, client, c)
|
||||
|
||||
var (
|
||||
snapshotter = client.SnapshotService(c.Snapshotter)
|
||||
parent = identity.ChainID(diffIDs).String()
|
||||
usernsID = fmt.Sprintf("%s-%d-%d", parent, uid, gid)
|
||||
parent = identity.ChainID(diffIDs).String()
|
||||
usernsID = fmt.Sprintf("%s-%d-%d", parent, uid, gid)
|
||||
)
|
||||
c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshotter, err := client.getSnapshotter(ctx, c.Snapshotter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := snapshotter.Stat(ctx, usernsID); err == nil {
|
||||
if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil {
|
||||
c.SnapshotKey = id
|
||||
|
3
vendor/github.com/containerd/containerd/container_restore_opts.go
generated
vendored
3
vendor/github.com/containerd/containerd/container_restore_opts.go
generated
vendored
@ -22,7 +22,6 @@ import (
|
||||
"github.com/containerd/containerd/containers"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
ptypes "github.com/gogo/protobuf/types"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
@ -58,7 +57,7 @@ func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint
|
||||
return err
|
||||
}
|
||||
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), platforms.Default())
|
||||
diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
3
vendor/github.com/containerd/containerd/containerd.service
generated
vendored
3
vendor/github.com/containerd/containerd/containerd.service
generated
vendored
@ -1,7 +1,7 @@
|
||||
[Unit]
|
||||
Description=containerd container runtime
|
||||
Documentation=https://containerd.io
|
||||
After=network.target
|
||||
After=network.target local-fs.target
|
||||
|
||||
[Service]
|
||||
ExecStartPre=-/sbin/modprobe overlay
|
||||
@ -9,6 +9,7 @@ ExecStart=/usr/local/bin/containerd
|
||||
|
||||
Delegate=yes
|
||||
KillMode=process
|
||||
Restart=always
|
||||
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||
LimitNPROC=infinity
|
||||
|
2
vendor/github.com/containerd/containerd/containers/containers.go
generated
vendored
2
vendor/github.com/containerd/containerd/containers/containers.go
generated
vendored
@ -49,7 +49,7 @@ type Container struct {
|
||||
// This property is required and immutable.
|
||||
Runtime RuntimeInfo
|
||||
|
||||
// Spec should carry the the runtime specification used to implement the
|
||||
// Spec should carry the runtime specification used to implement the
|
||||
// container.
|
||||
//
|
||||
// This field is required but mutable.
|
||||
|
31
vendor/github.com/containerd/containerd/content/helpers.go
generated
vendored
31
vendor/github.com/containerd/containerd/content/helpers.go
generated
vendored
@ -55,7 +55,14 @@ func ReadBlob(ctx context.Context, provider Provider, desc ocispec.Descriptor) (
|
||||
|
||||
p := make([]byte, ra.Size())
|
||||
|
||||
_, err = ra.ReadAt(p, 0)
|
||||
n, err := ra.ReadAt(p, 0)
|
||||
if err == io.EOF {
|
||||
if int64(n) != ra.Size() {
|
||||
err = io.ErrUnexpectedEOF
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
|
||||
@ -162,6 +169,28 @@ func CopyReaderAt(cw Writer, ra ReaderAt, n int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// CopyReader copies to a writer from a given reader, returning
|
||||
// the number of bytes copied.
|
||||
// Note: if the writer has a non-zero offset, the total number
|
||||
// of bytes read may be greater than those copied if the reader
|
||||
// is not an io.Seeker.
|
||||
// This copy does not commit the writer.
|
||||
func CopyReader(cw Writer, r io.Reader) (int64, error) {
|
||||
ws, err := cw.Status()
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to get status")
|
||||
}
|
||||
|
||||
if ws.Offset > 0 {
|
||||
r, err = seekReader(r, ws.Offset, 0)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "unable to resume write to %v", ws.Ref)
|
||||
}
|
||||
}
|
||||
|
||||
return copyWithBuffer(cw, r)
|
||||
}
|
||||
|
||||
// seekReader attempts to seek the reader to the given offset, either by
|
||||
// resolving `io.Seeker`, by detecting `io.ReaderAt`, or discarding
|
||||
// up to the given offset.
|
||||
|
18
vendor/github.com/containerd/containerd/content/local/store.go
generated
vendored
18
vendor/github.com/containerd/containerd/content/local/store.go
generated
vendored
@ -35,7 +35,6 @@ import (
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/containerd/continuity"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@ -661,6 +660,19 @@ func writeTimestampFile(p string, t time.Time) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return continuity.AtomicWriteFile(p, b, 0666)
|
||||
return atomicWrite(p, b, 0666)
|
||||
}
|
||||
|
||||
func atomicWrite(path string, data []byte, mode os.FileMode) error {
|
||||
tmp := fmt.Sprintf("%s.tmp", path)
|
||||
f, err := os.OpenFile(tmp, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_SYNC, mode)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create tmp file")
|
||||
}
|
||||
_, err = f.Write(data)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "write atomic data")
|
||||
}
|
||||
return os.Rename(tmp, path)
|
||||
}
|
||||
|
4
vendor/github.com/containerd/containerd/defaults/defaults.go
generated
vendored
4
vendor/github.com/containerd/containerd/defaults/defaults.go
generated
vendored
@ -23,10 +23,10 @@ const (
|
||||
// DefaultMaxSendMsgSize defines the default maximum message size for
|
||||
// sending protobufs passed over the GRPC API.
|
||||
DefaultMaxSendMsgSize = 16 << 20
|
||||
// DefaultRuntimeNSLabel defines the namespace label to check for
|
||||
// DefaultRuntimeNSLabel defines the namespace label to check for the
|
||||
// default runtime
|
||||
DefaultRuntimeNSLabel = "containerd.io/defaults/runtime"
|
||||
// DefaultSnapshotterNSLabel defines the namespances label to check for
|
||||
// DefaultSnapshotterNSLabel defines the namespace label to check for the
|
||||
// default snapshotter
|
||||
DefaultSnapshotterNSLabel = "containerd.io/defaults/snapshotter"
|
||||
)
|
||||
|
2
vendor/github.com/containerd/containerd/defaults/defaults_unix.go
generated
vendored
2
vendor/github.com/containerd/containerd/defaults/defaults_unix.go
generated
vendored
@ -32,4 +32,6 @@ const (
|
||||
// DefaultFIFODir is the default location used by client-side cio library
|
||||
// to store FIFOs.
|
||||
DefaultFIFODir = "/run/containerd/fifo"
|
||||
// DefaultRuntime is the default linux runtime
|
||||
DefaultRuntime = "io.containerd.runc.v2"
|
||||
)
|
||||
|
2
vendor/github.com/containerd/containerd/defaults/defaults_windows.go
generated
vendored
2
vendor/github.com/containerd/containerd/defaults/defaults_windows.go
generated
vendored
@ -40,4 +40,6 @@ const (
|
||||
// DefaultFIFODir is the default location used by client-side cio library
|
||||
// to store FIFOs. Unused on Windows.
|
||||
DefaultFIFODir = ""
|
||||
// DefaultRuntime is the default windows runtime
|
||||
DefaultRuntime = "io.containerd.runhcs.v1"
|
||||
)
|
||||
|
13
vendor/github.com/containerd/containerd/diff.go
generated
vendored
13
vendor/github.com/containerd/containerd/diff.go
generated
vendored
@ -45,10 +45,17 @@ type diffRemote struct {
|
||||
client diffapi.DiffClient
|
||||
}
|
||||
|
||||
func (r *diffRemote) Apply(ctx context.Context, diff ocispec.Descriptor, mounts []mount.Mount) (ocispec.Descriptor, error) {
|
||||
func (r *diffRemote) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (ocispec.Descriptor, error) {
|
||||
var config diff.ApplyConfig
|
||||
for _, opt := range opts {
|
||||
if err := opt(ctx, desc, &config); err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
req := &diffapi.ApplyRequest{
|
||||
Diff: fromDescriptor(diff),
|
||||
Mounts: fromMounts(mounts),
|
||||
Diff: fromDescriptor(desc),
|
||||
Mounts: fromMounts(mounts),
|
||||
Payloads: config.ProcessorPayloads,
|
||||
}
|
||||
resp, err := r.client.Apply(ctx, req)
|
||||
if err != nil {
|
||||
|
20
vendor/github.com/containerd/containerd/diff/diff.go
generated
vendored
20
vendor/github.com/containerd/containerd/diff/diff.go
generated
vendored
@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/gogo/protobuf/types"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@ -51,6 +52,15 @@ type Comparer interface {
|
||||
Compare(ctx context.Context, lower, upper []mount.Mount, opts ...Opt) (ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
// ApplyConfig is used to hold parameters needed for a apply operation
|
||||
type ApplyConfig struct {
|
||||
// ProcessorPayloads specifies the payload sent to various processors
|
||||
ProcessorPayloads map[string]*types.Any
|
||||
}
|
||||
|
||||
// ApplyOpt is used to configure an Apply operation
|
||||
type ApplyOpt func(context.Context, ocispec.Descriptor, *ApplyConfig) error
|
||||
|
||||
// Applier allows applying diffs between mounts
|
||||
type Applier interface {
|
||||
// Apply applies the content referred to by the given descriptor to
|
||||
@ -58,7 +68,7 @@ type Applier interface {
|
||||
// implementation and content descriptor. For example, in the common
|
||||
// case the descriptor is a file system difference in tar format,
|
||||
// that tar would be applied on top of the mounts.
|
||||
Apply(ctx context.Context, desc ocispec.Descriptor, mount []mount.Mount) (ocispec.Descriptor, error)
|
||||
Apply(ctx context.Context, desc ocispec.Descriptor, mount []mount.Mount, opts ...ApplyOpt) (ocispec.Descriptor, error)
|
||||
}
|
||||
|
||||
// WithMediaType sets the media type to use for creating the diff, without
|
||||
@ -87,3 +97,11 @@ func WithLabels(labels map[string]string) Opt {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPayloads sets the apply processor payloads to the config
|
||||
func WithPayloads(payloads map[string]*types.Any) ApplyOpt {
|
||||
return func(_ context.Context, _ ocispec.Descriptor, c *ApplyConfig) error {
|
||||
c.ProcessorPayloads = payloads
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
187
vendor/github.com/containerd/containerd/diff/stream.go
generated
vendored
Normal file
187
vendor/github.com/containerd/containerd/diff/stream.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
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 diff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/containerd/archive/compression"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/gogo/protobuf/types"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
handlers []Handler
|
||||
|
||||
// ErrNoProcessor is returned when no stream processor is available for a media-type
|
||||
ErrNoProcessor = errors.New("no processor for media-type")
|
||||
)
|
||||
|
||||
func init() {
|
||||
// register the default compression handler
|
||||
RegisterProcessor(compressedHandler)
|
||||
}
|
||||
|
||||
// RegisterProcessor registers a stream processor for media-types
|
||||
func RegisterProcessor(handler Handler) {
|
||||
handlers = append(handlers, handler)
|
||||
}
|
||||
|
||||
// GetProcessor returns the processor for a media-type
|
||||
func GetProcessor(ctx context.Context, stream StreamProcessor, payloads map[string]*types.Any) (StreamProcessor, error) {
|
||||
// reverse this list so that user configured handlers come up first
|
||||
for i := len(handlers) - 1; i >= 0; i-- {
|
||||
processor, ok := handlers[i](ctx, stream.MediaType())
|
||||
if ok {
|
||||
return processor(ctx, stream, payloads)
|
||||
}
|
||||
}
|
||||
return nil, ErrNoProcessor
|
||||
}
|
||||
|
||||
// Handler checks a media-type and initializes the processor
|
||||
type Handler func(ctx context.Context, mediaType string) (StreamProcessorInit, bool)
|
||||
|
||||
// StaticHandler returns the processor init func for a static media-type
|
||||
func StaticHandler(expectedMediaType string, fn StreamProcessorInit) Handler {
|
||||
return func(ctx context.Context, mediaType string) (StreamProcessorInit, bool) {
|
||||
if mediaType == expectedMediaType {
|
||||
return fn, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// StreamProcessorInit returns the initialized stream processor
|
||||
type StreamProcessorInit func(ctx context.Context, stream StreamProcessor, payloads map[string]*types.Any) (StreamProcessor, error)
|
||||
|
||||
// RawProcessor provides access to direct fd for processing
|
||||
type RawProcessor interface {
|
||||
// File returns the fd for the read stream of the underlying processor
|
||||
File() *os.File
|
||||
}
|
||||
|
||||
// StreamProcessor handles processing a content stream and transforming it into a different media-type
|
||||
type StreamProcessor interface {
|
||||
io.ReadCloser
|
||||
|
||||
// MediaType is the resulting media-type that the processor processes the stream into
|
||||
MediaType() string
|
||||
}
|
||||
|
||||
func compressedHandler(ctx context.Context, mediaType string) (StreamProcessorInit, bool) {
|
||||
compressed, err := images.DiffCompression(ctx, mediaType)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
if compressed != "" {
|
||||
return func(ctx context.Context, stream StreamProcessor, payloads map[string]*types.Any) (StreamProcessor, error) {
|
||||
ds, err := compression.DecompressStream(stream)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &compressedProcessor{
|
||||
rc: ds,
|
||||
}, nil
|
||||
}, true
|
||||
}
|
||||
return func(ctx context.Context, stream StreamProcessor, payloads map[string]*types.Any) (StreamProcessor, error) {
|
||||
return &stdProcessor{
|
||||
rc: stream,
|
||||
}, nil
|
||||
}, true
|
||||
}
|
||||
|
||||
// NewProcessorChain initialized the root StreamProcessor
|
||||
func NewProcessorChain(mt string, r io.Reader) StreamProcessor {
|
||||
return &processorChain{
|
||||
mt: mt,
|
||||
rc: r,
|
||||
}
|
||||
}
|
||||
|
||||
type processorChain struct {
|
||||
mt string
|
||||
rc io.Reader
|
||||
}
|
||||
|
||||
func (c *processorChain) MediaType() string {
|
||||
return c.mt
|
||||
}
|
||||
|
||||
func (c *processorChain) Read(p []byte) (int, error) {
|
||||
return c.rc.Read(p)
|
||||
}
|
||||
|
||||
func (c *processorChain) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type stdProcessor struct {
|
||||
rc StreamProcessor
|
||||
}
|
||||
|
||||
func (c *stdProcessor) MediaType() string {
|
||||
return ocispec.MediaTypeImageLayer
|
||||
}
|
||||
|
||||
func (c *stdProcessor) Read(p []byte) (int, error) {
|
||||
return c.rc.Read(p)
|
||||
}
|
||||
|
||||
func (c *stdProcessor) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type compressedProcessor struct {
|
||||
rc io.ReadCloser
|
||||
}
|
||||
|
||||
func (c *compressedProcessor) MediaType() string {
|
||||
return ocispec.MediaTypeImageLayer
|
||||
}
|
||||
|
||||
func (c *compressedProcessor) Read(p []byte) (int, error) {
|
||||
return c.rc.Read(p)
|
||||
}
|
||||
|
||||
func (c *compressedProcessor) Close() error {
|
||||
return c.rc.Close()
|
||||
}
|
||||
|
||||
func BinaryHandler(id, returnsMediaType string, mediaTypes []string, path string, args []string) Handler {
|
||||
set := make(map[string]struct{}, len(mediaTypes))
|
||||
for _, m := range mediaTypes {
|
||||
set[m] = struct{}{}
|
||||
}
|
||||
return func(_ context.Context, mediaType string) (StreamProcessorInit, bool) {
|
||||
if _, ok := set[mediaType]; ok {
|
||||
return func(ctx context.Context, stream StreamProcessor, payloads map[string]*types.Any) (StreamProcessor, error) {
|
||||
payload := payloads[id]
|
||||
return NewBinaryProcessor(ctx, mediaType, returnsMediaType, stream, path, args, payload)
|
||||
}, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
const mediaTypeEnvVar = "STREAM_PROCESSOR_MEDIATYPE"
|
146
vendor/github.com/containerd/containerd/diff/stream_unix.go
generated
vendored
Normal file
146
vendor/github.com/containerd/containerd/diff/stream_unix.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
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 diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// NewBinaryProcessor returns a binary processor for use with processing content streams
|
||||
func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProcessor, name string, args []string, payload *types.Any) (StreamProcessor, error) {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
var payloadC io.Closer
|
||||
if payload != nil {
|
||||
data, err := proto.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go func() {
|
||||
io.Copy(w, bytes.NewReader(data))
|
||||
w.Close()
|
||||
}()
|
||||
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, r)
|
||||
payloadC = r
|
||||
}
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", mediaTypeEnvVar, imt))
|
||||
var (
|
||||
stdin io.Reader
|
||||
closer func() error
|
||||
err error
|
||||
)
|
||||
if f, ok := stream.(RawProcessor); ok {
|
||||
stdin = f.File()
|
||||
closer = f.File().Close
|
||||
} else {
|
||||
stdin = stream
|
||||
}
|
||||
cmd.Stdin = stdin
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd.Stdout = w
|
||||
|
||||
stderr := bytes.NewBuffer(nil)
|
||||
cmd.Stderr = stderr
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := &binaryProcessor{
|
||||
cmd: cmd,
|
||||
r: r,
|
||||
mt: rmt,
|
||||
stderr: stderr,
|
||||
}
|
||||
go p.wait()
|
||||
|
||||
// close after start and dup
|
||||
w.Close()
|
||||
if closer != nil {
|
||||
closer()
|
||||
}
|
||||
if payloadC != nil {
|
||||
payloadC.Close()
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
type binaryProcessor struct {
|
||||
cmd *exec.Cmd
|
||||
r *os.File
|
||||
mt string
|
||||
stderr *bytes.Buffer
|
||||
|
||||
mu sync.Mutex
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) Err() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.err
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) wait() {
|
||||
if err := c.cmd.Wait(); err != nil {
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
c.mu.Lock()
|
||||
c.err = errors.New(c.stderr.String())
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) File() *os.File {
|
||||
return c.r
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) MediaType() string {
|
||||
return c.mt
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) Read(p []byte) (int, error) {
|
||||
return c.r.Read(p)
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) Close() error {
|
||||
err := c.r.Close()
|
||||
if kerr := c.cmd.Process.Kill(); err == nil {
|
||||
err = kerr
|
||||
}
|
||||
return err
|
||||
}
|
165
vendor/github.com/containerd/containerd/diff/stream_windows.go
generated
vendored
Normal file
165
vendor/github.com/containerd/containerd/diff/stream_windows.go
generated
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
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 diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
winio "github.com/Microsoft/go-winio"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const processorPipe = "STREAM_PROCESSOR_PIPE"
|
||||
|
||||
// NewBinaryProcessor returns a binary processor for use with processing content streams
|
||||
func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProcessor, name string, args []string, payload *types.Any) (StreamProcessor, error) {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
if payload != nil {
|
||||
data, err := proto.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
up, err := getUiqPath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path := fmt.Sprintf("\\\\.\\pipe\\containerd-processor-%s-pipe", up)
|
||||
l, err := winio.ListenPipe(path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go func() {
|
||||
defer l.Close()
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Error("accept npipe connection")
|
||||
return
|
||||
}
|
||||
io.Copy(conn, bytes.NewReader(data))
|
||||
conn.Close()
|
||||
}()
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", processorPipe, path))
|
||||
}
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", mediaTypeEnvVar, imt))
|
||||
var (
|
||||
stdin io.Reader
|
||||
closer func() error
|
||||
err error
|
||||
)
|
||||
if f, ok := stream.(RawProcessor); ok {
|
||||
stdin = f.File()
|
||||
closer = f.File().Close
|
||||
} else {
|
||||
stdin = stream
|
||||
}
|
||||
cmd.Stdin = stdin
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd.Stdout = w
|
||||
stderr := bytes.NewBuffer(nil)
|
||||
cmd.Stderr = stderr
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := &binaryProcessor{
|
||||
cmd: cmd,
|
||||
r: r,
|
||||
mt: rmt,
|
||||
stderr: stderr,
|
||||
}
|
||||
go p.wait()
|
||||
|
||||
// close after start and dup
|
||||
w.Close()
|
||||
if closer != nil {
|
||||
closer()
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
type binaryProcessor struct {
|
||||
cmd *exec.Cmd
|
||||
r *os.File
|
||||
mt string
|
||||
stderr *bytes.Buffer
|
||||
|
||||
mu sync.Mutex
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) Err() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.err
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) wait() {
|
||||
if err := c.cmd.Wait(); err != nil {
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
c.mu.Lock()
|
||||
c.err = errors.New(c.stderr.String())
|
||||
c.mu.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) File() *os.File {
|
||||
return c.r
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) MediaType() string {
|
||||
return c.mt
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) Read(p []byte) (int, error) {
|
||||
return c.r.Read(p)
|
||||
}
|
||||
|
||||
func (c *binaryProcessor) Close() error {
|
||||
err := c.r.Close()
|
||||
if kerr := c.cmd.Process.Kill(); err == nil {
|
||||
err = kerr
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getUiqPath() (string, error) {
|
||||
dir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
os.Remove(dir)
|
||||
return filepath.Base(dir), nil
|
||||
}
|
17
vendor/github.com/containerd/containerd/errdefs/errors.go
generated
vendored
17
vendor/github.com/containerd/containerd/errdefs/errors.go
generated
vendored
@ -26,7 +26,11 @@
|
||||
// client-side errors to the correct types.
|
||||
package errdefs
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Definitions of common error types used throughout containerd. All containerd
|
||||
// errors returned by most packages will map into one of these errors classes.
|
||||
@ -76,3 +80,14 @@ func IsUnavailable(err error) bool {
|
||||
func IsNotImplemented(err error) bool {
|
||||
return errors.Cause(err) == ErrNotImplemented
|
||||
}
|
||||
|
||||
// IsCanceled returns true if the error is due to `context.Canceled`.
|
||||
func IsCanceled(err error) bool {
|
||||
return errors.Cause(err) == context.Canceled
|
||||
}
|
||||
|
||||
// IsDeadlineExceeded returns true if the error is due to
|
||||
// `context.DeadlineExceeded`.
|
||||
func IsDeadlineExceeded(err error) bool {
|
||||
return errors.Cause(err) == context.DeadlineExceeded
|
||||
}
|
||||
|
9
vendor/github.com/containerd/containerd/errdefs/grpc.go
generated
vendored
9
vendor/github.com/containerd/containerd/errdefs/grpc.go
generated
vendored
@ -17,6 +17,7 @@
|
||||
package errdefs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -55,6 +56,10 @@ func ToGRPC(err error) error {
|
||||
return status.Errorf(codes.Unavailable, err.Error())
|
||||
case IsNotImplemented(err):
|
||||
return status.Errorf(codes.Unimplemented, err.Error())
|
||||
case IsCanceled(err):
|
||||
return status.Errorf(codes.Canceled, err.Error())
|
||||
case IsDeadlineExceeded(err):
|
||||
return status.Errorf(codes.DeadlineExceeded, err.Error())
|
||||
}
|
||||
|
||||
return err
|
||||
@ -89,6 +94,10 @@ func FromGRPC(err error) error {
|
||||
cls = ErrFailedPrecondition
|
||||
case codes.Unimplemented:
|
||||
cls = ErrNotImplemented
|
||||
case codes.Canceled:
|
||||
cls = context.Canceled
|
||||
case codes.DeadlineExceeded:
|
||||
cls = context.DeadlineExceeded
|
||||
default:
|
||||
cls = ErrUnknown
|
||||
}
|
||||
|
2
vendor/github.com/containerd/containerd/events/exchange/exchange.go
generated
vendored
2
vendor/github.com/containerd/containerd/events/exchange/exchange.go
generated
vendored
@ -50,7 +50,7 @@ var _ events.Publisher = &Exchange{}
|
||||
var _ events.Forwarder = &Exchange{}
|
||||
var _ events.Subscriber = &Exchange{}
|
||||
|
||||
// Forward accepts an envelope to be direcly distributed on the exchange.
|
||||
// Forward accepts an envelope to be directly distributed on the exchange.
|
||||
//
|
||||
// This is useful when an event is forwarded on behalf of another namespace or
|
||||
// when the event is propagated on behalf of another publisher.
|
||||
|
26
vendor/github.com/containerd/containerd/export.go
generated
vendored
26
vendor/github.com/containerd/containerd/export.go
generated
vendored
@ -20,26 +20,12 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/containerd/containerd/images/oci"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
)
|
||||
|
||||
// Export exports an image to a Tar stream.
|
||||
// OCI format is used by default.
|
||||
// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
|
||||
// TODO(AkihiroSuda): support exporting multiple descriptors at once to a single archive stream.
|
||||
func (c *Client) Export(ctx context.Context, desc ocispec.Descriptor, opts ...oci.V1ExporterOpt) (io.ReadCloser, error) {
|
||||
|
||||
exporter, err := oci.ResolveV1ExportOpt(opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pr, pw := io.Pipe()
|
||||
go func() {
|
||||
pw.CloseWithError(errors.Wrap(exporter.Export(ctx, c.ContentStore(), desc, pw), "export failed"))
|
||||
}()
|
||||
return pr, nil
|
||||
// Export exports images to a Tar stream.
|
||||
// The tar archive is in OCI format with a Docker compatible manifest
|
||||
// when a single target platform is given.
|
||||
func (c *Client) Export(ctx context.Context, w io.Writer, opts ...archive.ExportOpt) error {
|
||||
return archive.Export(ctx, c.ContentStore(), w, opts...)
|
||||
}
|
||||
|
183
vendor/github.com/containerd/containerd/image.go
generated
vendored
183
vendor/github.com/containerd/containerd/image.go
generated
vendored
@ -19,16 +19,21 @@ package containerd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/diff"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/rootfs"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
// Image describes an image used by containers
|
||||
@ -40,11 +45,13 @@ type Image interface {
|
||||
// Labels of the image
|
||||
Labels() map[string]string
|
||||
// Unpack unpacks the image's content into a snapshot
|
||||
Unpack(context.Context, string) error
|
||||
Unpack(context.Context, string, ...UnpackOpt) error
|
||||
// RootFS returns the unpacked diffids that make up images rootfs.
|
||||
RootFS(ctx context.Context) ([]digest.Digest, error)
|
||||
// Size returns the total size of the image's packed resources.
|
||||
Size(ctx context.Context) (int64, error)
|
||||
// Usage returns a usage calculation for the image.
|
||||
Usage(context.Context, ...UsageOpt) (int64, error)
|
||||
// Config descriptor for the image.
|
||||
Config(ctx context.Context) (ocispec.Descriptor, error)
|
||||
// IsUnpacked returns whether or not an image is unpacked.
|
||||
@ -53,6 +60,49 @@ type Image interface {
|
||||
ContentStore() content.Store
|
||||
}
|
||||
|
||||
type usageOptions struct {
|
||||
manifestLimit *int
|
||||
manifestOnly bool
|
||||
snapshots bool
|
||||
}
|
||||
|
||||
// UsageOpt is used to configure the usage calculation
|
||||
type UsageOpt func(*usageOptions) error
|
||||
|
||||
// WithUsageManifestLimit sets the limit to the number of manifests which will
|
||||
// be walked for usage. Setting this value to 0 will require all manifests to
|
||||
// be walked, returning ErrNotFound if manifests are missing.
|
||||
// NOTE: By default all manifests which exist will be walked
|
||||
// and any non-existent manifests and their subobjects will be ignored.
|
||||
func WithUsageManifestLimit(i int) UsageOpt {
|
||||
// If 0 then don't filter any manifests
|
||||
// By default limits to current platform
|
||||
return func(o *usageOptions) error {
|
||||
o.manifestLimit = &i
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSnapshotUsage will check for referenced snapshots from the image objects
|
||||
// and include the snapshot size in the total usage.
|
||||
func WithSnapshotUsage() UsageOpt {
|
||||
return func(o *usageOptions) error {
|
||||
o.snapshots = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithManifestUsage is used to get the usage for an image based on what is
|
||||
// reported by the manifests rather than what exists in the content store.
|
||||
// NOTE: This function is best used with the manifest limit set to get a
|
||||
// consistent value, otherwise non-existent manifests will be excluded.
|
||||
func WithManifestUsage() UsageOpt {
|
||||
return func(o *usageOptions) error {
|
||||
o.manifestOnly = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var _ = (Image)(&image{})
|
||||
|
||||
// NewImage returns a client image object from the metadata image
|
||||
@ -60,7 +110,7 @@ func NewImage(client *Client, i images.Image) Image {
|
||||
return &image{
|
||||
client: client,
|
||||
i: i,
|
||||
platform: platforms.Default(),
|
||||
platform: client.platform,
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,8 +148,95 @@ func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) {
|
||||
}
|
||||
|
||||
func (i *image) Size(ctx context.Context) (int64, error) {
|
||||
provider := i.client.ContentStore()
|
||||
return i.i.Size(ctx, provider, i.platform)
|
||||
return i.Usage(ctx, WithUsageManifestLimit(1), WithManifestUsage())
|
||||
}
|
||||
|
||||
func (i *image) Usage(ctx context.Context, opts ...UsageOpt) (int64, error) {
|
||||
var config usageOptions
|
||||
for _, opt := range opts {
|
||||
if err := opt(&config); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
provider = i.client.ContentStore()
|
||||
handler = images.ChildrenHandler(provider)
|
||||
size int64
|
||||
mustExist bool
|
||||
)
|
||||
|
||||
if config.manifestLimit != nil {
|
||||
handler = images.LimitManifests(handler, i.platform, *config.manifestLimit)
|
||||
mustExist = true
|
||||
}
|
||||
|
||||
var wh images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
var usage int64
|
||||
children, err := handler(ctx, desc)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) || mustExist {
|
||||
return nil, err
|
||||
}
|
||||
if !config.manifestOnly {
|
||||
// Do not count size of non-existent objects
|
||||
desc.Size = 0
|
||||
}
|
||||
} else if config.snapshots || !config.manifestOnly {
|
||||
info, err := provider.Info(ctx, desc.Digest)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
if !config.manifestOnly {
|
||||
// Do not count size of non-existent objects
|
||||
desc.Size = 0
|
||||
}
|
||||
} else if info.Size > desc.Size {
|
||||
// Count actual usage, Size may be unset or -1
|
||||
desc.Size = info.Size
|
||||
}
|
||||
|
||||
for k, v := range info.Labels {
|
||||
const prefix = "containerd.io/gc.ref.snapshot."
|
||||
if !strings.HasPrefix(k, prefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
sn := i.client.SnapshotService(k[len(prefix):])
|
||||
if sn == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
u, err := sn.Usage(ctx, v)
|
||||
if err != nil {
|
||||
if !errdefs.IsNotFound(err) && !errdefs.IsInvalidArgument(err) {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
usage += u.Size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore unknown sizes. Generally unknown sizes should
|
||||
// never be set in manifests, however, the usage
|
||||
// calculation does not need to enforce this.
|
||||
if desc.Size >= 0 {
|
||||
usage += desc.Size
|
||||
}
|
||||
|
||||
atomic.AddInt64(&size, usage)
|
||||
|
||||
return children, nil
|
||||
}
|
||||
|
||||
l := semaphore.NewWeighted(3)
|
||||
if err := images.Dispatch(ctx, wh, l, i.i.Target); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return size, nil
|
||||
}
|
||||
|
||||
func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {
|
||||
@ -108,7 +245,10 @@ func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {
|
||||
}
|
||||
|
||||
func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, error) {
|
||||
sn := i.client.SnapshotService(snapshotterName)
|
||||
sn, err := i.client.getSnapshotter(ctx, snapshotterName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
cs := i.client.ContentStore()
|
||||
|
||||
diffs, err := i.i.RootFS(ctx, cs, i.platform)
|
||||
@ -127,28 +267,53 @@ func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, e
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
|
||||
// UnpackConfig provides configuration for the unpack of an image
|
||||
type UnpackConfig struct {
|
||||
// ApplyOpts for applying a diff to a snapshotter
|
||||
ApplyOpts []diff.ApplyOpt
|
||||
// SnapshotOpts for configuring a snapshotter
|
||||
SnapshotOpts []snapshots.Opt
|
||||
}
|
||||
|
||||
// UnpackOpt provides configuration for unpack
|
||||
type UnpackOpt func(context.Context, *UnpackConfig) error
|
||||
|
||||
func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...UnpackOpt) error {
|
||||
ctx, done, err := i.client.WithLease(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
var config UnpackConfig
|
||||
for _, o := range opts {
|
||||
if err := o(ctx, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
layers, err := i.getLayers(ctx, i.platform)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
sn = i.client.SnapshotService(snapshotterName)
|
||||
a = i.client.DiffService()
|
||||
cs = i.client.ContentStore()
|
||||
|
||||
chain []digest.Digest
|
||||
unpacked bool
|
||||
)
|
||||
snapshotterName, err = i.client.resolveSnapshotterName(ctx, snapshotterName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sn, err := i.client.getSnapshotter(ctx, snapshotterName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, layer := range layers {
|
||||
unpacked, err = rootfs.ApplyLayer(ctx, layer, chain, sn, a)
|
||||
unpacked, err = rootfs.ApplyLayerWithOpts(ctx, layer, chain, sn, a, config.SnapshotOpts, config.ApplyOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -14,14 +14,10 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package devices
|
||||
package images
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
const (
|
||||
// AnnotationImageName is an annotation on a Descriptor in an index.json
|
||||
// containing the `Name` value as used by an `Image` struct
|
||||
AnnotationImageName = "io.containerd.image.name"
|
||||
)
|
||||
|
||||
func DeviceInfo(fi os.FileInfo) (uint64, uint64, error) {
|
||||
return 0, 0, errors.Wrap(ErrNotSupported, "cannot get device info on windows")
|
||||
}
|
468
vendor/github.com/containerd/containerd/images/archive/exporter.go
generated
vendored
Normal file
468
vendor/github.com/containerd/containerd/images/archive/exporter.go
generated
vendored
Normal file
@ -0,0 +1,468 @@
|
||||
/*
|
||||
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 archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"path"
|
||||
"sort"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type exportOptions struct {
|
||||
manifests []ocispec.Descriptor
|
||||
platform platforms.MatchComparer
|
||||
allPlatforms bool
|
||||
skipDockerManifest bool
|
||||
}
|
||||
|
||||
// ExportOpt defines options for configuring exported descriptors
|
||||
type ExportOpt func(context.Context, *exportOptions) error
|
||||
|
||||
// WithPlatform defines the platform to require manifest lists have
|
||||
// not exporting all platforms.
|
||||
// Additionally, platform is used to resolve image configs for
|
||||
// Docker v1.1, v1.2 format compatibility.
|
||||
func WithPlatform(p platforms.MatchComparer) ExportOpt {
|
||||
return func(ctx context.Context, o *exportOptions) error {
|
||||
o.platform = p
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithAllPlatforms exports all manifests from a manifest list.
|
||||
// Missing content will fail the export.
|
||||
func WithAllPlatforms() ExportOpt {
|
||||
return func(ctx context.Context, o *exportOptions) error {
|
||||
o.allPlatforms = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSkipDockerManifest skips creation of the Docker compatible
|
||||
// manifest.json file.
|
||||
func WithSkipDockerManifest() ExportOpt {
|
||||
return func(ctx context.Context, o *exportOptions) error {
|
||||
o.skipDockerManifest = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithImage adds the provided images to the exported archive.
|
||||
func WithImage(is images.Store, name string) ExportOpt {
|
||||
return func(ctx context.Context, o *exportOptions) error {
|
||||
img, err := is.Get(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
img.Target.Annotations = addNameAnnotation(name, img.Target.Annotations)
|
||||
o.manifests = append(o.manifests, img.Target)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithManifest adds a manifest to the exported archive.
|
||||
// When names are given they will be set on the manifest in the
|
||||
// exported archive, creating an index record for each name.
|
||||
// When no names are provided, it is up to caller to put name annotation to
|
||||
// on the manifest descriptor if needed.
|
||||
func WithManifest(manifest ocispec.Descriptor, names ...string) ExportOpt {
|
||||
return func(ctx context.Context, o *exportOptions) error {
|
||||
if len(names) == 0 {
|
||||
o.manifests = append(o.manifests, manifest)
|
||||
}
|
||||
for _, name := range names {
|
||||
mc := manifest
|
||||
mc.Annotations = addNameAnnotation(name, manifest.Annotations)
|
||||
o.manifests = append(o.manifests, mc)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func addNameAnnotation(name string, base map[string]string) map[string]string {
|
||||
annotations := map[string]string{}
|
||||
for k, v := range base {
|
||||
annotations[k] = v
|
||||
}
|
||||
|
||||
annotations[images.AnnotationImageName] = name
|
||||
annotations[ocispec.AnnotationRefName] = ociReferenceName(name)
|
||||
|
||||
return annotations
|
||||
}
|
||||
|
||||
// Export implements Exporter.
|
||||
func Export(ctx context.Context, store content.Provider, writer io.Writer, opts ...ExportOpt) error {
|
||||
var eo exportOptions
|
||||
for _, opt := range opts {
|
||||
if err := opt(ctx, &eo); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
records := []tarRecord{
|
||||
ociLayoutFile(""),
|
||||
ociIndexRecord(eo.manifests),
|
||||
}
|
||||
|
||||
algorithms := map[string]struct{}{}
|
||||
dManifests := map[digest.Digest]*exportManifest{}
|
||||
resolvedIndex := map[digest.Digest]digest.Digest{}
|
||||
for _, desc := range eo.manifests {
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:
|
||||
mt, ok := dManifests[desc.Digest]
|
||||
if !ok {
|
||||
// TODO(containerd): Skip if already added
|
||||
r, err := getRecords(ctx, store, desc, algorithms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
records = append(records, r...)
|
||||
|
||||
mt = &exportManifest{
|
||||
manifest: desc,
|
||||
}
|
||||
dManifests[desc.Digest] = mt
|
||||
}
|
||||
|
||||
name := desc.Annotations[images.AnnotationImageName]
|
||||
if name != "" && !eo.skipDockerManifest {
|
||||
mt.names = append(mt.names, name)
|
||||
}
|
||||
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
|
||||
d, ok := resolvedIndex[desc.Digest]
|
||||
if !ok {
|
||||
records = append(records, blobRecord(store, desc))
|
||||
|
||||
p, err := content.ReadBlob(ctx, store, desc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var index ocispec.Index
|
||||
if err := json.Unmarshal(p, &index); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var manifests []ocispec.Descriptor
|
||||
for _, m := range index.Manifests {
|
||||
if eo.platform != nil {
|
||||
if m.Platform == nil || eo.platform.Match(*m.Platform) {
|
||||
manifests = append(manifests, m)
|
||||
} else if !eo.allPlatforms {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
r, err := getRecords(ctx, store, m, algorithms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
records = append(records, r...)
|
||||
}
|
||||
|
||||
if !eo.skipDockerManifest {
|
||||
if len(manifests) >= 1 {
|
||||
if len(manifests) > 1 {
|
||||
sort.SliceStable(manifests, func(i, j int) bool {
|
||||
if manifests[i].Platform == nil {
|
||||
return false
|
||||
}
|
||||
if manifests[j].Platform == nil {
|
||||
return true
|
||||
}
|
||||
return eo.platform.Less(*manifests[i].Platform, *manifests[j].Platform)
|
||||
})
|
||||
}
|
||||
d = manifests[0].Digest
|
||||
dManifests[d] = &exportManifest{
|
||||
manifest: manifests[0],
|
||||
}
|
||||
} else if eo.platform != nil {
|
||||
return errors.Wrap(errdefs.ErrNotFound, "no manifest found for platform")
|
||||
}
|
||||
}
|
||||
resolvedIndex[desc.Digest] = d
|
||||
}
|
||||
if d != "" {
|
||||
if name := desc.Annotations[images.AnnotationImageName]; name != "" {
|
||||
mt := dManifests[d]
|
||||
mt.names = append(mt.names, name)
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
return errors.Wrap(errdefs.ErrInvalidArgument, "only manifests may be exported")
|
||||
}
|
||||
}
|
||||
|
||||
if len(dManifests) > 0 {
|
||||
tr, err := manifestsRecord(ctx, store, dManifests)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to create manifests file")
|
||||
}
|
||||
|
||||
records = append(records, tr)
|
||||
}
|
||||
|
||||
if len(algorithms) > 0 {
|
||||
records = append(records, directoryRecord("blobs/", 0755))
|
||||
for alg := range algorithms {
|
||||
records = append(records, directoryRecord("blobs/"+alg+"/", 0755))
|
||||
}
|
||||
}
|
||||
|
||||
tw := tar.NewWriter(writer)
|
||||
defer tw.Close()
|
||||
return writeTar(ctx, tw, records)
|
||||
}
|
||||
|
||||
func getRecords(ctx context.Context, store content.Provider, desc ocispec.Descriptor, algorithms map[string]struct{}) ([]tarRecord, error) {
|
||||
var records []tarRecord
|
||||
exportHandler := func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
records = append(records, blobRecord(store, desc))
|
||||
algorithms[desc.Digest.Algorithm().String()] = struct{}{}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
childrenHandler := images.ChildrenHandler(store)
|
||||
|
||||
handlers := images.Handlers(
|
||||
childrenHandler,
|
||||
images.HandlerFunc(exportHandler),
|
||||
)
|
||||
|
||||
// Walk sequentially since the number of fetches is likely one and doing in
|
||||
// parallel requires locking the export handler
|
||||
if err := images.Walk(ctx, handlers, desc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
type tarRecord struct {
|
||||
Header *tar.Header
|
||||
CopyTo func(context.Context, io.Writer) (int64, error)
|
||||
}
|
||||
|
||||
func blobRecord(cs content.Provider, desc ocispec.Descriptor) tarRecord {
|
||||
path := path.Join("blobs", desc.Digest.Algorithm().String(), desc.Digest.Encoded())
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: path,
|
||||
Mode: 0444,
|
||||
Size: desc.Size,
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
r, err := cs.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to get reader")
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
// Verify digest
|
||||
dgstr := desc.Digest.Algorithm().Digester()
|
||||
|
||||
n, err := io.Copy(io.MultiWriter(w, dgstr.Hash()), content.NewReader(r))
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to copy to tar")
|
||||
}
|
||||
if dgstr.Digest() != desc.Digest {
|
||||
return 0, errors.Errorf("unexpected digest %s copied", dgstr.Digest())
|
||||
}
|
||||
return n, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func directoryRecord(name string, mode int64) tarRecord {
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: name,
|
||||
Mode: mode,
|
||||
Typeflag: tar.TypeDir,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ociLayoutFile(version string) tarRecord {
|
||||
if version == "" {
|
||||
version = ocispec.ImageLayoutVersion
|
||||
}
|
||||
layout := ocispec.ImageLayout{
|
||||
Version: version,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(layout)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: ocispec.ImageLayoutFile,
|
||||
Mode: 0444,
|
||||
Size: int64(len(b)),
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b)
|
||||
return int64(n), err
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func ociIndexRecord(manifests []ocispec.Descriptor) tarRecord {
|
||||
index := ocispec.Index{
|
||||
Versioned: ocispecs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Manifests: manifests,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(index)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: "index.json",
|
||||
Mode: 0644,
|
||||
Size: int64(len(b)),
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b)
|
||||
return int64(n), err
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type exportManifest struct {
|
||||
manifest ocispec.Descriptor
|
||||
names []string
|
||||
}
|
||||
|
||||
func manifestsRecord(ctx context.Context, store content.Provider, manifests map[digest.Digest]*exportManifest) (tarRecord, error) {
|
||||
mfsts := make([]struct {
|
||||
Config string
|
||||
RepoTags []string
|
||||
Layers []string
|
||||
}, len(manifests))
|
||||
|
||||
var i int
|
||||
for _, m := range manifests {
|
||||
p, err := content.ReadBlob(ctx, store, m.manifest)
|
||||
if err != nil {
|
||||
return tarRecord{}, err
|
||||
}
|
||||
|
||||
var manifest ocispec.Manifest
|
||||
if err := json.Unmarshal(p, &manifest); err != nil {
|
||||
return tarRecord{}, err
|
||||
}
|
||||
if err := manifest.Config.Digest.Validate(); err != nil {
|
||||
return tarRecord{}, errors.Wrapf(err, "invalid manifest %q", m.manifest.Digest)
|
||||
}
|
||||
|
||||
dgst := manifest.Config.Digest
|
||||
mfsts[i].Config = path.Join("blobs", dgst.Algorithm().String(), dgst.Encoded())
|
||||
for _, l := range manifest.Layers {
|
||||
path := path.Join("blobs", l.Digest.Algorithm().String(), l.Digest.Encoded())
|
||||
mfsts[i].Layers = append(mfsts[i].Layers, path)
|
||||
}
|
||||
|
||||
for _, name := range m.names {
|
||||
nname, err := familiarizeReference(name)
|
||||
if err != nil {
|
||||
return tarRecord{}, err
|
||||
}
|
||||
|
||||
mfsts[i].RepoTags = append(mfsts[i].RepoTags, nname)
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
b, err := json.Marshal(mfsts)
|
||||
if err != nil {
|
||||
return tarRecord{}, err
|
||||
}
|
||||
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: "manifest.json",
|
||||
Mode: 0644,
|
||||
Size: int64(len(b)),
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b)
|
||||
return int64(n), err
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func writeTar(ctx context.Context, tw *tar.Writer, records []tarRecord) error {
|
||||
sort.Slice(records, func(i, j int) bool {
|
||||
return records[i].Header.Name < records[j].Header.Name
|
||||
})
|
||||
|
||||
var last string
|
||||
for _, record := range records {
|
||||
if record.Header.Name == last {
|
||||
continue
|
||||
}
|
||||
last = record.Header.Name
|
||||
if err := tw.WriteHeader(record.Header); err != nil {
|
||||
return err
|
||||
}
|
||||
if record.CopyTo != nil {
|
||||
n, err := record.CopyTo(ctx, tw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != record.Header.Size {
|
||||
return errors.Errorf("unexpected copy size for %s", record.Header.Name)
|
||||
}
|
||||
} else if record.Header.Size > 0 {
|
||||
return errors.Errorf("no content to write to record with non-zero size for %s", record.Header.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
154
vendor/github.com/containerd/containerd/images/archive/importer.go
generated
vendored
154
vendor/github.com/containerd/containerd/images/archive/importer.go
generated
vendored
@ -22,12 +22,14 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
|
||||
"github.com/containerd/containerd/archive/compression"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/log"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
@ -36,6 +38,22 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type importOpts struct {
|
||||
compress bool
|
||||
}
|
||||
|
||||
// ImportOpt is an option for importing an OCI index
|
||||
type ImportOpt func(*importOpts) error
|
||||
|
||||
// WithImportCompression compresses uncompressed layers on import.
|
||||
// This is used for import formats which do not include the manifest.
|
||||
func WithImportCompression() ImportOpt {
|
||||
return func(io *importOpts) error {
|
||||
io.compress = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ImportIndex imports an index from a tar archive image bundle
|
||||
// - implements Docker v1.1, v1.2 and OCI v1.
|
||||
// - prefers OCI v1 when provided
|
||||
@ -43,8 +61,7 @@ import (
|
||||
// - normalizes Docker references and adds as OCI ref name
|
||||
// e.g. alpine:latest -> docker.io/library/alpine:latest
|
||||
// - existing OCI reference names are untouched
|
||||
// - TODO: support option to compress layers on ingest
|
||||
func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (ocispec.Descriptor, error) {
|
||||
func ImportIndex(ctx context.Context, store content.Store, reader io.Reader, opts ...ImportOpt) (ocispec.Descriptor, error) {
|
||||
var (
|
||||
tr = tar.NewReader(reader)
|
||||
|
||||
@ -56,7 +73,15 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
|
||||
}
|
||||
symlinks = make(map[string]string)
|
||||
blobs = make(map[string]ocispec.Descriptor)
|
||||
iopts importOpts
|
||||
)
|
||||
|
||||
for _, o := range opts {
|
||||
if err := o(&iopts); err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
@ -99,7 +124,7 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
|
||||
}
|
||||
|
||||
// If OCI layout was given, interpret the tar as an OCI layout.
|
||||
// When not provided, the layout of the tar will be interpretted
|
||||
// When not provided, the layout of the tar will be interpreted
|
||||
// as Docker v1.1 or v1.2.
|
||||
if ociLayout.Version != "" {
|
||||
if ociLayout.Version != ocispec.ImageLayoutVersion {
|
||||
@ -137,19 +162,23 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
|
||||
if !ok {
|
||||
return ocispec.Descriptor{}, errors.Errorf("image config %q not found", mfst.Config)
|
||||
}
|
||||
config.MediaType = ocispec.MediaTypeImageConfig
|
||||
config.MediaType = images.MediaTypeDockerSchema2Config
|
||||
|
||||
layers, err := resolveLayers(ctx, store, mfst.Layers, blobs)
|
||||
layers, err := resolveLayers(ctx, store, mfst.Layers, blobs, iopts.compress)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to resolve layers")
|
||||
}
|
||||
|
||||
manifest := ocispec.Manifest{
|
||||
Versioned: specs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Config: config,
|
||||
Layers: layers,
|
||||
manifest := struct {
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Config ocispec.Descriptor `json:"config"`
|
||||
Layers []ocispec.Descriptor `json:"layers"`
|
||||
}{
|
||||
SchemaVersion: 2,
|
||||
MediaType: images.MediaTypeDockerSchema2Manifest,
|
||||
Config: config,
|
||||
Layers: layers,
|
||||
}
|
||||
|
||||
desc, err := writeManifest(ctx, store, manifest, ocispec.MediaTypeImageManifest)
|
||||
@ -181,7 +210,8 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader) (oc
|
||||
}
|
||||
|
||||
mfstdesc.Annotations = map[string]string{
|
||||
ocispec.AnnotationRefName: normalized,
|
||||
images.AnnotationImageName: normalized,
|
||||
ocispec.AnnotationRefName: ociReferenceName(normalized),
|
||||
}
|
||||
|
||||
idx.Manifests = append(idx.Manifests, mfstdesc)
|
||||
@ -210,36 +240,118 @@ func onUntarBlob(ctx context.Context, r io.Reader, store content.Ingester, size
|
||||
return dgstr.Digest(), nil
|
||||
}
|
||||
|
||||
func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
var layers []ocispec.Descriptor
|
||||
for _, f := range layerFiles {
|
||||
func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor, compress bool) ([]ocispec.Descriptor, error) {
|
||||
layers := make([]ocispec.Descriptor, len(layerFiles))
|
||||
descs := map[digest.Digest]*ocispec.Descriptor{}
|
||||
filters := []string{}
|
||||
for i, f := range layerFiles {
|
||||
desc, ok := blobs[f]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("layer %q not found", f)
|
||||
}
|
||||
layers[i] = desc
|
||||
descs[desc.Digest] = &layers[i]
|
||||
filters = append(filters, "labels.\"containerd.io/uncompressed\"=="+desc.Digest.String())
|
||||
}
|
||||
|
||||
err := store.Walk(ctx, func(info content.Info) error {
|
||||
dgst, ok := info.Labels["containerd.io/uncompressed"]
|
||||
if ok {
|
||||
desc := descs[digest.Digest(dgst)]
|
||||
if desc != nil {
|
||||
desc.MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
desc.Digest = info.Digest
|
||||
desc.Size = info.Size
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}, filters...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failure checking for compressed blobs")
|
||||
}
|
||||
|
||||
for i, desc := range layers {
|
||||
if desc.MediaType != "" {
|
||||
continue
|
||||
}
|
||||
// Open blob, resolve media type
|
||||
ra, err := store.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to open %q (%s)", f, desc.Digest)
|
||||
return nil, errors.Wrapf(err, "failed to open %q (%s)", layerFiles[i], desc.Digest)
|
||||
}
|
||||
s, err := compression.DecompressStream(content.NewReader(ra))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to detect compression for %q", f)
|
||||
return nil, errors.Wrapf(err, "failed to detect compression for %q", layerFiles[i])
|
||||
}
|
||||
if s.GetCompression() == compression.Uncompressed {
|
||||
// TODO: Support compressing and writing back to content store
|
||||
desc.MediaType = ocispec.MediaTypeImageLayer
|
||||
if compress {
|
||||
ref := fmt.Sprintf("compress-blob-%s-%s", desc.Digest.Algorithm().String(), desc.Digest.Encoded())
|
||||
labels := map[string]string{
|
||||
"containerd.io/uncompressed": desc.Digest.String(),
|
||||
}
|
||||
layers[i], err = compressBlob(ctx, store, s, ref, content.WithLabels(labels))
|
||||
if err != nil {
|
||||
s.Close()
|
||||
return nil, err
|
||||
}
|
||||
layers[i].MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
} else {
|
||||
layers[i].MediaType = images.MediaTypeDockerSchema2Layer
|
||||
}
|
||||
} else {
|
||||
desc.MediaType = ocispec.MediaTypeImageLayerGzip
|
||||
layers[i].MediaType = images.MediaTypeDockerSchema2LayerGzip
|
||||
}
|
||||
s.Close()
|
||||
|
||||
layers = append(layers, desc)
|
||||
}
|
||||
return layers, nil
|
||||
}
|
||||
|
||||
func compressBlob(ctx context.Context, cs content.Store, r io.Reader, ref string, opts ...content.Opt) (desc ocispec.Descriptor, err error) {
|
||||
w, err := content.OpenWriter(ctx, cs, content.WithRef(ref))
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to open writer")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
w.Close()
|
||||
if err != nil {
|
||||
cs.Abort(ctx, ref)
|
||||
}
|
||||
}()
|
||||
if err := w.Truncate(0); err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to truncate writer")
|
||||
}
|
||||
|
||||
cw, err := compression.CompressStream(w, compression.Gzip)
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(cw, r); err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
if err := cw.Close(); err != nil {
|
||||
return ocispec.Descriptor{}, err
|
||||
}
|
||||
|
||||
cst, err := w.Status()
|
||||
if err != nil {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to get writer status")
|
||||
}
|
||||
|
||||
desc.Digest = w.Digest()
|
||||
desc.Size = cst.Offset
|
||||
|
||||
if err := w.Commit(ctx, desc.Size, desc.Digest, opts...); err != nil {
|
||||
if !errdefs.IsAlreadyExists(err) {
|
||||
return ocispec.Descriptor{}, errors.Wrap(err, "failed to commit")
|
||||
}
|
||||
}
|
||||
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
func writeManifest(ctx context.Context, cs content.Ingester, manifest interface{}, mediaType string) (ocispec.Descriptor, error) {
|
||||
manifestBytes, err := json.Marshal(manifest)
|
||||
if err != nil {
|
||||
|
30
vendor/github.com/containerd/containerd/images/archive/reference.go
generated
vendored
30
vendor/github.com/containerd/containerd/images/archive/reference.go
generated
vendored
@ -19,7 +19,8 @@ package archive
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/containerd/containerd/reference"
|
||||
distref "github.com/containerd/containerd/reference/docker"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -69,7 +70,7 @@ func isImagePrefix(s, prefix string) bool {
|
||||
|
||||
func normalizeReference(ref string) (string, error) {
|
||||
// TODO: Replace this function to not depend on reference package
|
||||
normalized, err := reference.ParseDockerRef(ref)
|
||||
normalized, err := distref.ParseDockerRef(ref)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "normalize image ref %q", ref)
|
||||
}
|
||||
@ -77,6 +78,31 @@ func normalizeReference(ref string) (string, error) {
|
||||
return normalized.String(), nil
|
||||
}
|
||||
|
||||
func familiarizeReference(ref string) (string, error) {
|
||||
named, err := distref.ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to parse %q", ref)
|
||||
}
|
||||
named = distref.TagNameOnly(named)
|
||||
|
||||
return distref.FamiliarString(named), nil
|
||||
}
|
||||
|
||||
func ociReferenceName(name string) string {
|
||||
// OCI defines the reference name as only a tag excluding the
|
||||
// repository. The containerd annotation contains the full image name
|
||||
// since the tag is insufficient for correctly naming and referring to an
|
||||
// image
|
||||
var ociRef string
|
||||
if spec, err := reference.Parse(name); err == nil {
|
||||
ociRef = spec.Object
|
||||
} else {
|
||||
ociRef = name
|
||||
}
|
||||
|
||||
return ociRef
|
||||
}
|
||||
|
||||
// DigestTranslator creates a digest reference by adding the
|
||||
// digest to an image name
|
||||
func DigestTranslator(prefix string) func(digest.Digest) string {
|
||||
|
7
vendor/github.com/containerd/containerd/images/handlers.go
generated
vendored
7
vendor/github.com/containerd/containerd/images/handlers.go
generated
vendored
@ -117,7 +117,7 @@ func Walk(ctx context.Context, handler Handler, descs ...ocispec.Descriptor) err
|
||||
//
|
||||
// If any handler returns an error, the dispatch session will be canceled.
|
||||
func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted, descs ...ocispec.Descriptor) error {
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
eg, ctx2 := errgroup.WithContext(ctx)
|
||||
for _, desc := range descs {
|
||||
desc := desc
|
||||
|
||||
@ -126,10 +126,11 @@ func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted,
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
eg.Go(func() error {
|
||||
desc := desc
|
||||
|
||||
children, err := handler.Handle(ctx, desc)
|
||||
children, err := handler.Handle(ctx2, desc)
|
||||
if limiter != nil {
|
||||
limiter.Release(1)
|
||||
}
|
||||
@ -141,7 +142,7 @@ func Dispatch(ctx context.Context, handler Handler, limiter *semaphore.Weighted,
|
||||
}
|
||||
|
||||
if len(children) > 0 {
|
||||
return Dispatch(ctx, handler, limiter, children...)
|
||||
return Dispatch(ctx2, handler, limiter, children...)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
60
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
60
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
@ -20,7 +20,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
@ -119,7 +118,7 @@ func (image *Image) Size(ctx context.Context, provider content.Provider, platfor
|
||||
}
|
||||
size += desc.Size
|
||||
return nil, nil
|
||||
}), FilterPlatforms(ChildrenHandler(provider), platform)), image.Target)
|
||||
}), LimitManifests(FilterPlatforms(ChildrenHandler(provider), platform), platform, 1)), image.Target)
|
||||
}
|
||||
|
||||
type platformManifest struct {
|
||||
@ -142,6 +141,7 @@ type platformManifest struct {
|
||||
// this direction because this abstraction is not needed.`
|
||||
func Manifest(ctx context.Context, provider content.Provider, image ocispec.Descriptor, platform platforms.MatchComparer) (ocispec.Manifest, error) {
|
||||
var (
|
||||
limit = 1
|
||||
m []platformManifest
|
||||
wasIndex bool
|
||||
)
|
||||
@ -210,10 +210,22 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
||||
}
|
||||
}
|
||||
|
||||
sort.SliceStable(descs, func(i, j int) bool {
|
||||
if descs[i].Platform == nil {
|
||||
return false
|
||||
}
|
||||
if descs[j].Platform == nil {
|
||||
return true
|
||||
}
|
||||
return platform.Less(*descs[i].Platform, *descs[j].Platform)
|
||||
})
|
||||
|
||||
wasIndex = true
|
||||
|
||||
if len(descs) > limit {
|
||||
return descs[:limit], nil
|
||||
}
|
||||
return descs, nil
|
||||
|
||||
}
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "unexpected media type %v for %v", desc.MediaType, desc.Digest)
|
||||
}), image); err != nil {
|
||||
@ -227,17 +239,6 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
||||
}
|
||||
return ocispec.Manifest{}, err
|
||||
}
|
||||
|
||||
sort.SliceStable(m, func(i, j int) bool {
|
||||
if m[i].p == nil {
|
||||
return false
|
||||
}
|
||||
if m[j].p == nil {
|
||||
return true
|
||||
}
|
||||
return platform.Less(*m[i].p, *m[j].p)
|
||||
})
|
||||
|
||||
return *m[0].m, nil
|
||||
}
|
||||
|
||||
@ -356,15 +357,11 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr
|
||||
}
|
||||
|
||||
descs = append(descs, index.Manifests...)
|
||||
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
|
||||
MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip,
|
||||
MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
|
||||
ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerGzip,
|
||||
ocispec.MediaTypeImageLayerNonDistributable, ocispec.MediaTypeImageLayerNonDistributableGzip,
|
||||
MediaTypeContainerd1Checkpoint, MediaTypeContainerd1CheckpointConfig:
|
||||
// childless data types.
|
||||
return nil, nil
|
||||
default:
|
||||
if IsLayerType(desc.MediaType) || IsKnownConfig(desc.MediaType) {
|
||||
// childless data types.
|
||||
return nil, nil
|
||||
}
|
||||
log.G(ctx).Warnf("encountered unknown type %v; children may not be fetched", desc.MediaType)
|
||||
}
|
||||
|
||||
@ -387,22 +384,3 @@ func RootFS(ctx context.Context, provider content.Provider, configDesc ocispec.D
|
||||
}
|
||||
return config.RootFS.DiffIDs, nil
|
||||
}
|
||||
|
||||
// IsCompressedDiff returns true if mediaType is a known compressed diff media type.
|
||||
// It returns false if the media type is a diff, but not compressed. If the media type
|
||||
// is not a known diff type, it returns errdefs.ErrNotImplemented
|
||||
func IsCompressedDiff(ctx context.Context, mediaType string) (bool, error) {
|
||||
switch mediaType {
|
||||
case ocispec.MediaTypeImageLayer, MediaTypeDockerSchema2Layer:
|
||||
case ocispec.MediaTypeImageLayerGzip, MediaTypeDockerSchema2LayerGzip:
|
||||
return true, nil
|
||||
default:
|
||||
// Still apply all generic media types *.tar[.+]gzip and *.tar
|
||||
if strings.HasSuffix(mediaType, ".tar.gzip") || strings.HasSuffix(mediaType, ".tar+gzip") {
|
||||
return true, nil
|
||||
} else if !strings.HasSuffix(mediaType, ".tar") {
|
||||
return false, errdefs.ErrNotImplemented
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
84
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
84
vendor/github.com/containerd/containerd/images/mediatypes.go
generated
vendored
@ -16,6 +16,15 @@
|
||||
|
||||
package images
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// mediatype definitions for image components handled in containerd.
|
||||
//
|
||||
// oci components are generally referenced directly, although we may centralize
|
||||
@ -40,3 +49,78 @@ const (
|
||||
// Legacy Docker schema1 manifest
|
||||
MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws"
|
||||
)
|
||||
|
||||
// DiffCompression returns the compression as defined by the layer diff media
|
||||
// type. For Docker media types without compression, "unknown" is returned to
|
||||
// indicate that the media type may be compressed. If the media type is not
|
||||
// recognized as a layer diff, then it returns errdefs.ErrNotImplemented
|
||||
func DiffCompression(ctx context.Context, mediaType string) (string, error) {
|
||||
base, ext := parseMediaTypes(mediaType)
|
||||
switch base {
|
||||
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerForeign:
|
||||
if len(ext) > 0 {
|
||||
// Type is wrapped
|
||||
return "", nil
|
||||
}
|
||||
// These media types may have been compressed but failed to
|
||||
// use the correct media type. The decompression function
|
||||
// should detect and handle this case.
|
||||
return "unknown", nil
|
||||
case MediaTypeDockerSchema2LayerGzip, MediaTypeDockerSchema2LayerForeignGzip:
|
||||
if len(ext) > 0 {
|
||||
// Type is wrapped
|
||||
return "", nil
|
||||
}
|
||||
return "gzip", nil
|
||||
case ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerNonDistributable:
|
||||
if len(ext) > 0 {
|
||||
switch ext[len(ext)-1] {
|
||||
case "gzip":
|
||||
return "gzip", nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
default:
|
||||
return "", errdefs.ErrNotImplemented
|
||||
}
|
||||
}
|
||||
|
||||
// parseMediaTypes splits the media type into the base type and
|
||||
// an array of sorted extensions
|
||||
func parseMediaTypes(mt string) (string, []string) {
|
||||
if mt == "" {
|
||||
return "", []string{}
|
||||
}
|
||||
|
||||
s := strings.Split(mt, "+")
|
||||
ext := s[1:]
|
||||
sort.Strings(ext)
|
||||
|
||||
return s[0], ext
|
||||
}
|
||||
|
||||
// IsLayerTypes returns true if the media type is a layer
|
||||
func IsLayerType(mt string) bool {
|
||||
if strings.HasPrefix(mt, "application/vnd.oci.image.layer.") {
|
||||
return true
|
||||
}
|
||||
|
||||
// Parse Docker media types, strip off any + suffixes first
|
||||
base, _ := parseMediaTypes(mt)
|
||||
switch base {
|
||||
case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip,
|
||||
MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsKnownConfig returns true if the media type is a known config type
|
||||
func IsKnownConfig(mt string) bool {
|
||||
switch mt {
|
||||
case MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig,
|
||||
MediaTypeContainerd1Checkpoint, MediaTypeContainerd1CheckpointConfig:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
241
vendor/github.com/containerd/containerd/images/oci/exporter.go
generated
vendored
241
vendor/github.com/containerd/containerd/images/oci/exporter.go
generated
vendored
@ -1,241 +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 oci
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// V1Exporter implements OCI Image Spec v1.
|
||||
// It is up to caller to put "org.opencontainers.image.ref.name" annotation to desc.
|
||||
//
|
||||
// TODO(AkihiroSuda): add V1Exporter{TranslateMediaTypes: true} that transforms media types,
|
||||
// e.g. application/vnd.docker.image.rootfs.diff.tar.gzip
|
||||
// -> application/vnd.oci.image.layer.v1.tar+gzip
|
||||
type V1Exporter struct {
|
||||
AllPlatforms bool
|
||||
}
|
||||
|
||||
// V1ExporterOpt allows the caller to set additional options to a new V1Exporter
|
||||
type V1ExporterOpt func(c *V1Exporter) error
|
||||
|
||||
// DefaultV1Exporter return a default V1Exporter pointer
|
||||
func DefaultV1Exporter() *V1Exporter {
|
||||
return &V1Exporter{
|
||||
AllPlatforms: false,
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveV1ExportOpt return a new V1Exporter with V1ExporterOpt
|
||||
func ResolveV1ExportOpt(opts ...V1ExporterOpt) (*V1Exporter, error) {
|
||||
exporter := DefaultV1Exporter()
|
||||
for _, o := range opts {
|
||||
if err := o(exporter); err != nil {
|
||||
return exporter, err
|
||||
}
|
||||
}
|
||||
return exporter, nil
|
||||
}
|
||||
|
||||
// WithAllPlatforms set V1Exporter`s AllPlatforms option
|
||||
func WithAllPlatforms(allPlatforms bool) V1ExporterOpt {
|
||||
return func(c *V1Exporter) error {
|
||||
c.AllPlatforms = allPlatforms
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Export implements Exporter.
|
||||
func (oe *V1Exporter) Export(ctx context.Context, store content.Provider, desc ocispec.Descriptor, writer io.Writer) error {
|
||||
tw := tar.NewWriter(writer)
|
||||
defer tw.Close()
|
||||
|
||||
records := []tarRecord{
|
||||
ociLayoutFile(""),
|
||||
ociIndexRecord(desc),
|
||||
}
|
||||
|
||||
algorithms := map[string]struct{}{}
|
||||
exportHandler := func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
records = append(records, blobRecord(store, desc))
|
||||
algorithms[desc.Digest.Algorithm().String()] = struct{}{}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
childrenHandler := images.ChildrenHandler(store)
|
||||
|
||||
if !oe.AllPlatforms {
|
||||
// get local default platform to fetch image manifest
|
||||
childrenHandler = images.FilterPlatforms(childrenHandler, platforms.Any(platforms.DefaultSpec()))
|
||||
}
|
||||
|
||||
handlers := images.Handlers(
|
||||
childrenHandler,
|
||||
images.HandlerFunc(exportHandler),
|
||||
)
|
||||
|
||||
// Walk sequentially since the number of fetchs is likely one and doing in
|
||||
// parallel requires locking the export handler
|
||||
if err := images.Walk(ctx, handlers, desc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(algorithms) > 0 {
|
||||
records = append(records, directoryRecord("blobs/", 0755))
|
||||
for alg := range algorithms {
|
||||
records = append(records, directoryRecord("blobs/"+alg+"/", 0755))
|
||||
}
|
||||
}
|
||||
|
||||
return writeTar(ctx, tw, records)
|
||||
}
|
||||
|
||||
type tarRecord struct {
|
||||
Header *tar.Header
|
||||
CopyTo func(context.Context, io.Writer) (int64, error)
|
||||
}
|
||||
|
||||
func blobRecord(cs content.Provider, desc ocispec.Descriptor) tarRecord {
|
||||
path := "blobs/" + desc.Digest.Algorithm().String() + "/" + desc.Digest.Hex()
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: path,
|
||||
Mode: 0444,
|
||||
Size: desc.Size,
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
r, err := cs.ReaderAt(ctx, desc)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to get reader")
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
// Verify digest
|
||||
dgstr := desc.Digest.Algorithm().Digester()
|
||||
|
||||
n, err := io.Copy(io.MultiWriter(w, dgstr.Hash()), content.NewReader(r))
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to copy to tar")
|
||||
}
|
||||
if dgstr.Digest() != desc.Digest {
|
||||
return 0, errors.Errorf("unexpected digest %s copied", dgstr.Digest())
|
||||
}
|
||||
return n, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func directoryRecord(name string, mode int64) tarRecord {
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: name,
|
||||
Mode: mode,
|
||||
Typeflag: tar.TypeDir,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ociLayoutFile(version string) tarRecord {
|
||||
if version == "" {
|
||||
version = ocispec.ImageLayoutVersion
|
||||
}
|
||||
layout := ocispec.ImageLayout{
|
||||
Version: version,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(layout)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: ocispec.ImageLayoutFile,
|
||||
Mode: 0444,
|
||||
Size: int64(len(b)),
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b)
|
||||
return int64(n), err
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func ociIndexRecord(manifests ...ocispec.Descriptor) tarRecord {
|
||||
index := ocispec.Index{
|
||||
Versioned: ocispecs.Versioned{
|
||||
SchemaVersion: 2,
|
||||
},
|
||||
Manifests: manifests,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(index)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return tarRecord{
|
||||
Header: &tar.Header{
|
||||
Name: "index.json",
|
||||
Mode: 0644,
|
||||
Size: int64(len(b)),
|
||||
Typeflag: tar.TypeReg,
|
||||
},
|
||||
CopyTo: func(ctx context.Context, w io.Writer) (int64, error) {
|
||||
n, err := w.Write(b)
|
||||
return int64(n), err
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func writeTar(ctx context.Context, tw *tar.Writer, records []tarRecord) error {
|
||||
sort.Slice(records, func(i, j int) bool {
|
||||
return records[i].Header.Name < records[j].Header.Name
|
||||
})
|
||||
|
||||
for _, record := range records {
|
||||
if err := tw.WriteHeader(record.Header); err != nil {
|
||||
return err
|
||||
}
|
||||
if record.CopyTo != nil {
|
||||
n, err := record.CopyTo(ctx, tw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != record.Header.Size {
|
||||
return errors.Errorf("unexpected copy size for %s", record.Header.Name)
|
||||
}
|
||||
} else if record.Header.Size > 0 {
|
||||
return errors.Errorf("no content to write to record with non-zero size for %s", record.Header.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
51
vendor/github.com/containerd/containerd/import.go
generated
vendored
51
vendor/github.com/containerd/containerd/import.go
generated
vendored
@ -35,6 +35,7 @@ type importOpts struct {
|
||||
imageRefT func(string) string
|
||||
dgstRefT func(digest.Digest) string
|
||||
allPlatforms bool
|
||||
compress bool
|
||||
}
|
||||
|
||||
// ImportOpt allows the caller to specify import specific options
|
||||
@ -74,9 +75,18 @@ func WithAllPlatforms(allPlatforms bool) ImportOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithImportCompression compresses uncompressed layers on import.
|
||||
// This is used for import formats which do not include the manifest.
|
||||
func WithImportCompression() ImportOpt {
|
||||
return func(c *importOpts) error {
|
||||
c.compress = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Import imports an image from a Tar stream using reader.
|
||||
// Caller needs to specify importer. Future version may use oci.v1 as the default.
|
||||
// Note that unreferrenced blobs may be imported to the content store as well.
|
||||
// Note that unreferenced blobs may be imported to the content store as well.
|
||||
func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt) ([]images.Image, error) {
|
||||
var iopts importOpts
|
||||
for _, o := range opts {
|
||||
@ -91,7 +101,12 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
index, err := archive.ImportIndex(ctx, c.ContentStore(), reader)
|
||||
var aio []archive.ImportOpt
|
||||
if iopts.compress {
|
||||
aio = append(aio, archive.WithImportCompression())
|
||||
}
|
||||
|
||||
index, err := archive.ImportIndex(ctx, c.ContentStore(), reader, aio...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -110,7 +125,7 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
||||
}
|
||||
var platformMatcher = platforms.All
|
||||
if !iopts.allPlatforms {
|
||||
platformMatcher = platforms.Default()
|
||||
platformMatcher = c.platform
|
||||
}
|
||||
|
||||
var handler images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
||||
@ -130,16 +145,12 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
||||
}
|
||||
|
||||
for _, m := range idx.Manifests {
|
||||
if ref := m.Annotations[ocispec.AnnotationRefName]; ref != "" {
|
||||
if iopts.imageRefT != nil {
|
||||
ref = iopts.imageRefT(ref)
|
||||
}
|
||||
if ref != "" {
|
||||
imgs = append(imgs, images.Image{
|
||||
Name: ref,
|
||||
Target: m,
|
||||
})
|
||||
}
|
||||
name := imageName(m.Annotations, iopts.imageRefT)
|
||||
if name != "" {
|
||||
imgs = append(imgs, images.Image{
|
||||
Name: name,
|
||||
Target: m,
|
||||
})
|
||||
}
|
||||
if iopts.dgstRefT != nil {
|
||||
ref := iopts.dgstRefT(m.Digest)
|
||||
@ -178,3 +189,17 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt
|
||||
|
||||
return imgs, nil
|
||||
}
|
||||
|
||||
func imageName(annotations map[string]string, ociCleanup func(string) string) string {
|
||||
name := annotations[images.AnnotationImageName]
|
||||
if name != "" {
|
||||
return name
|
||||
}
|
||||
name = annotations[ocispec.AnnotationRefName]
|
||||
if name != "" {
|
||||
if ociCleanup != nil {
|
||||
name = ociCleanup(name)
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
3
vendor/github.com/containerd/containerd/install.go
generated
vendored
3
vendor/github.com/containerd/containerd/install.go
generated
vendored
@ -27,7 +27,6 @@ import (
|
||||
"github.com/containerd/containerd/archive/compression"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -43,7 +42,7 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
|
||||
}
|
||||
var (
|
||||
cs = image.ContentStore()
|
||||
platform = platforms.Default()
|
||||
platform = c.platform
|
||||
)
|
||||
manifest, err := images.Manifest(ctx, cs, image.Target(), platform)
|
||||
if err != nil {
|
||||
|
12
vendor/github.com/containerd/containerd/lease.go
generated
vendored
12
vendor/github.com/containerd/containerd/lease.go
generated
vendored
@ -24,7 +24,7 @@ import (
|
||||
)
|
||||
|
||||
// WithLease attaches a lease on the context
|
||||
func (c *Client) WithLease(ctx context.Context) (context.Context, func(context.Context) error, error) {
|
||||
func (c *Client) WithLease(ctx context.Context, opts ...leases.Opt) (context.Context, func(context.Context) error, error) {
|
||||
_, ok := leases.FromContext(ctx)
|
||||
if ok {
|
||||
return ctx, func(context.Context) error {
|
||||
@ -34,7 +34,15 @@ func (c *Client) WithLease(ctx context.Context) (context.Context, func(context.C
|
||||
|
||||
ls := c.LeasesService()
|
||||
|
||||
l, err := ls.Create(ctx, leases.WithRandomID(), leases.WithExpiration(24*time.Hour))
|
||||
if len(opts) == 0 {
|
||||
// Use default lease configuration if no options provided
|
||||
opts = []leases.Opt{
|
||||
leases.WithRandomID(),
|
||||
leases.WithExpiration(24 * time.Hour),
|
||||
}
|
||||
}
|
||||
|
||||
l, err := ls.Create(ctx, opts...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
10
vendor/github.com/containerd/containerd/leases/lease.go
generated
vendored
10
vendor/github.com/containerd/containerd/leases/lease.go
generated
vendored
@ -32,6 +32,9 @@ type Manager interface {
|
||||
Create(context.Context, ...Opt) (Lease, error)
|
||||
Delete(context.Context, Lease, ...DeleteOpt) error
|
||||
List(context.Context, ...string) ([]Lease, error)
|
||||
AddResource(context.Context, Lease, Resource) error
|
||||
DeleteResource(context.Context, Lease, Resource) error
|
||||
ListResources(context.Context, Lease) ([]Resource, error)
|
||||
}
|
||||
|
||||
// Lease retains resources to prevent cleanup before
|
||||
@ -42,6 +45,13 @@ type Lease struct {
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// Resource represents low level resource of image, like content, ingest and
|
||||
// snapshotter.
|
||||
type Resource struct {
|
||||
ID string
|
||||
Type string
|
||||
}
|
||||
|
||||
// DeleteOptions provide options on image delete
|
||||
type DeleteOptions struct {
|
||||
Synchronous bool
|
||||
|
40
vendor/github.com/containerd/containerd/leases/proxy/manager.go
generated
vendored
40
vendor/github.com/containerd/containerd/leases/proxy/manager.go
generated
vendored
@ -91,3 +91,43 @@ func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.L
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (pm *proxyManager) AddResource(ctx context.Context, lease leases.Lease, r leases.Resource) error {
|
||||
_, err := pm.client.AddResource(ctx, &leasesapi.AddResourceRequest{
|
||||
ID: lease.ID,
|
||||
Resource: leasesapi.Resource{
|
||||
ID: r.ID,
|
||||
Type: r.Type,
|
||||
},
|
||||
})
|
||||
return errdefs.FromGRPC(err)
|
||||
}
|
||||
|
||||
func (pm *proxyManager) DeleteResource(ctx context.Context, lease leases.Lease, r leases.Resource) error {
|
||||
_, err := pm.client.DeleteResource(ctx, &leasesapi.DeleteResourceRequest{
|
||||
ID: lease.ID,
|
||||
Resource: leasesapi.Resource{
|
||||
ID: r.ID,
|
||||
Type: r.Type,
|
||||
},
|
||||
})
|
||||
return errdefs.FromGRPC(err)
|
||||
}
|
||||
|
||||
func (pm *proxyManager) ListResources(ctx context.Context, lease leases.Lease) ([]leases.Resource, error) {
|
||||
resp, err := pm.client.ListResources(ctx, &leasesapi.ListResourcesRequest{
|
||||
ID: lease.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errdefs.FromGRPC(err)
|
||||
}
|
||||
|
||||
rs := make([]leases.Resource, 0, len(resp.Resources))
|
||||
for _, i := range resp.Resources {
|
||||
rs = append(rs, leases.Resource{
|
||||
ID: i.ID,
|
||||
Type: i.Type,
|
||||
})
|
||||
}
|
||||
return rs, nil
|
||||
}
|
||||
|
2
vendor/github.com/containerd/containerd/log/context.go
generated
vendored
2
vendor/github.com/containerd/containerd/log/context.go
generated
vendored
@ -30,7 +30,7 @@ var (
|
||||
// messages.
|
||||
G = GetLogger
|
||||
|
||||
// L is an alias for the the standard logger.
|
||||
// L is an alias for the standard logger.
|
||||
L = logrus.NewEntry(logrus.StandardLogger())
|
||||
)
|
||||
|
||||
|
16
vendor/github.com/containerd/containerd/namespaces.go
generated
vendored
16
vendor/github.com/containerd/containerd/namespaces.go
generated
vendored
@ -100,10 +100,18 @@ func (r *remoteNamespaces) List(ctx context.Context) ([]string, error) {
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func (r *remoteNamespaces) Delete(ctx context.Context, namespace string) error {
|
||||
var req api.DeleteNamespaceRequest
|
||||
|
||||
req.Name = namespace
|
||||
func (r *remoteNamespaces) Delete(ctx context.Context, namespace string, opts ...namespaces.DeleteOpts) error {
|
||||
i := namespaces.DeleteInfo{
|
||||
Name: namespace,
|
||||
}
|
||||
for _, o := range opts {
|
||||
if err := o(ctx, &i); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
req := api.DeleteNamespaceRequest{
|
||||
Name: namespace,
|
||||
}
|
||||
_, err := r.client.Delete(ctx, &req)
|
||||
if err != nil {
|
||||
return errdefs.FromGRPC(err)
|
||||
|
14
vendor/github.com/containerd/containerd/namespaces/context.go
generated
vendored
14
vendor/github.com/containerd/containerd/namespaces/context.go
generated
vendored
@ -36,10 +36,9 @@ type namespaceKey struct{}
|
||||
// WithNamespace sets a given namespace on the context
|
||||
func WithNamespace(ctx context.Context, namespace string) context.Context {
|
||||
ctx = context.WithValue(ctx, namespaceKey{}, namespace) // set our key for namespace
|
||||
|
||||
// also store on the grpc headers so it gets picked up by any clients that
|
||||
// also store on the grpc and ttrpc headers so it gets picked up by any clients that
|
||||
// are using this.
|
||||
return withGRPCNamespaceHeader(ctx, namespace)
|
||||
return withTTRPCNamespaceHeader(withGRPCNamespaceHeader(ctx, namespace), namespace)
|
||||
}
|
||||
|
||||
// NamespaceFromEnv uses the namespace defined in CONTAINERD_NAMESPACE or
|
||||
@ -58,22 +57,21 @@ func NamespaceFromEnv(ctx context.Context) context.Context {
|
||||
func Namespace(ctx context.Context) (string, bool) {
|
||||
namespace, ok := ctx.Value(namespaceKey{}).(string)
|
||||
if !ok {
|
||||
return fromGRPCHeader(ctx)
|
||||
if namespace, ok = fromGRPCHeader(ctx); !ok {
|
||||
return fromTTRPCHeader(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return namespace, ok
|
||||
}
|
||||
|
||||
// NamespaceRequired returns the valid namepace from the context or an error.
|
||||
// NamespaceRequired returns the valid namespace from the context or an error.
|
||||
func NamespaceRequired(ctx context.Context) (string, error) {
|
||||
namespace, ok := Namespace(ctx)
|
||||
if !ok || namespace == "" {
|
||||
return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required")
|
||||
}
|
||||
|
||||
if err := Validate(namespace); err != nil {
|
||||
return "", errors.Wrap(err, "namespace validation")
|
||||
}
|
||||
|
||||
return namespace, nil
|
||||
}
|
||||
|
11
vendor/github.com/containerd/containerd/namespaces/store.go
generated
vendored
11
vendor/github.com/containerd/containerd/namespaces/store.go
generated
vendored
@ -33,5 +33,14 @@ type Store interface {
|
||||
List(ctx context.Context) ([]string, error)
|
||||
|
||||
// Delete removes the namespace. The namespace must be empty to be deleted.
|
||||
Delete(ctx context.Context, namespace string) error
|
||||
Delete(ctx context.Context, namespace string, opts ...DeleteOpts) error
|
||||
}
|
||||
|
||||
// DeleteInfo specifies information for the deletion of a namespace
|
||||
type DeleteInfo struct {
|
||||
// Name of the namespace
|
||||
Name string
|
||||
}
|
||||
|
||||
// DeleteOpts allows the caller to set options for namespace deletion
|
||||
type DeleteOpts func(context.Context, *DeleteInfo) error
|
||||
|
51
vendor/github.com/containerd/containerd/namespaces/ttrpc.go
generated
vendored
Normal file
51
vendor/github.com/containerd/containerd/namespaces/ttrpc.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
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 namespaces
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/ttrpc"
|
||||
)
|
||||
|
||||
const (
|
||||
// TTRPCHeader defines the header name for specifying a containerd namespace
|
||||
TTRPCHeader = "containerd-namespace-ttrpc"
|
||||
)
|
||||
|
||||
func copyMetadata(src ttrpc.MD) ttrpc.MD {
|
||||
md := ttrpc.MD{}
|
||||
for k, v := range src {
|
||||
md[k] = append(md[k], v...)
|
||||
}
|
||||
return md
|
||||
}
|
||||
|
||||
func withTTRPCNamespaceHeader(ctx context.Context, namespace string) context.Context {
|
||||
md, ok := ttrpc.GetMetadata(ctx)
|
||||
if !ok {
|
||||
md = ttrpc.MD{}
|
||||
} else {
|
||||
md = copyMetadata(md)
|
||||
}
|
||||
md.Set(TTRPCHeader, namespace)
|
||||
return ttrpc.WithMetadata(ctx, md)
|
||||
}
|
||||
|
||||
func fromTTRPCHeader(ctx context.Context) (string, bool) {
|
||||
return ttrpc.GetMetadataValue(ctx, TTRPCHeader)
|
||||
}
|
3
vendor/github.com/containerd/containerd/oci/spec.go
generated
vendored
3
vendor/github.com/containerd/containerd/oci/spec.go
generated
vendored
@ -78,7 +78,7 @@ func generateDefaultSpecWithPlatform(ctx context.Context, platform, id string, s
|
||||
return err
|
||||
}
|
||||
|
||||
// ApplyOpts applys the options to the given spec, injecting data from the
|
||||
// ApplyOpts applies the options to the given spec, injecting data from the
|
||||
// context, client and container instance.
|
||||
func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *Spec, opts ...SpecOpts) error {
|
||||
for _, o := range opts {
|
||||
@ -141,7 +141,6 @@ func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error {
|
||||
Path: defaultRootfsPath,
|
||||
},
|
||||
Process: &specs.Process{
|
||||
Env: defaultUnixEnv,
|
||||
Cwd: "/",
|
||||
NoNewPrivileges: true,
|
||||
User: specs.User{
|
||||
|
132
vendor/github.com/containerd/containerd/oci/spec_opts.go
generated
vendored
132
vendor/github.com/containerd/containerd/oci/spec_opts.go
generated
vendored
@ -17,6 +17,7 @@
|
||||
package oci
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@ -76,6 +77,20 @@ func setLinux(s *Spec) {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint
|
||||
func setResources(s *Spec) {
|
||||
if s.Linux != nil {
|
||||
if s.Linux.Resources == nil {
|
||||
s.Linux.Resources = &specs.LinuxResources{}
|
||||
}
|
||||
}
|
||||
if s.Windows != nil {
|
||||
if s.Windows.Resources == nil {
|
||||
s.Windows.Resources = &specs.WindowsResources{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setCapabilities sets Linux Capabilities to empty if unset
|
||||
func setCapabilities(s *Spec) {
|
||||
setProcess(s)
|
||||
@ -104,7 +119,7 @@ func WithDefaultSpecForPlatform(platform string) SpecOpts {
|
||||
}
|
||||
}
|
||||
|
||||
// WithSpecFromBytes loads the the spec from the provided byte slice.
|
||||
// WithSpecFromBytes loads the spec from the provided byte slice.
|
||||
func WithSpecFromBytes(p []byte) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
*s = Spec{} // make sure spec is cleared.
|
||||
@ -137,6 +152,13 @@ func WithEnv(environmentVariables []string) SpecOpts {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultPathEnv sets the $PATH environment variable to the
|
||||
// default PATH defined in this package.
|
||||
func WithDefaultPathEnv(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, defaultUnixEnv)
|
||||
return nil
|
||||
}
|
||||
|
||||
// replaceOrAppendEnvValues returns the defaults with the overrides either
|
||||
// replaced by env key or appended to the list
|
||||
func replaceOrAppendEnvValues(defaults, overrides []string) []string {
|
||||
@ -312,7 +334,11 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts {
|
||||
|
||||
setProcess(s)
|
||||
if s.Linux != nil {
|
||||
s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, config.Env)
|
||||
defaults := config.Env
|
||||
if len(defaults) == 0 {
|
||||
defaults = defaultUnixEnv
|
||||
}
|
||||
s.Process.Env = replaceOrAppendEnvValues(defaults, s.Process.Env)
|
||||
cmd := config.Cmd
|
||||
if len(args) > 0 {
|
||||
cmd = args
|
||||
@ -334,7 +360,7 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts {
|
||||
// even if there is no specified user in the image config
|
||||
return WithAdditionalGIDs("root")(ctx, client, c, s)
|
||||
} else if s.Windows != nil {
|
||||
s.Process.Env = replaceOrAppendEnvValues(s.Process.Env, config.Env)
|
||||
s.Process.Env = replaceOrAppendEnvValues(config.Env, s.Process.Env)
|
||||
cmd := config.Cmd
|
||||
if len(args) > 0 {
|
||||
cmd = args
|
||||
@ -607,7 +633,7 @@ func WithUserID(uid uint32) SpecOpts {
|
||||
}
|
||||
|
||||
// WithUsername sets the correct UID and GID for the container
|
||||
// based on the the image's /etc/passwd contents. If /etc/passwd
|
||||
// based on the image's /etc/passwd contents. If /etc/passwd
|
||||
// does not exist, or the username is not found in /etc/passwd,
|
||||
// it returns error.
|
||||
func WithUsername(username string) SpecOpts {
|
||||
@ -980,6 +1006,21 @@ func WithParentCgroupDevices(_ context.Context, _ Client, _ *containers.Containe
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithAllDevicesAllowed permits READ WRITE MKNOD on all devices nodes for the container
|
||||
func WithAllDevicesAllowed(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
if s.Linux.Resources == nil {
|
||||
s.Linux.Resources = &specs.LinuxResources{}
|
||||
}
|
||||
s.Linux.Resources.Devices = []specs.LinuxDeviceCgroup{
|
||||
{
|
||||
Allow: true,
|
||||
Access: rwm,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithDefaultUnixDevices adds the default devices for unix such as /dev/null, /dev/random to
|
||||
// the container's resource cgroup spec
|
||||
func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
@ -1074,7 +1115,6 @@ func WithDefaultUnixDevices(_ context.Context, _ Client, _ *containers.Container
|
||||
}
|
||||
|
||||
// WithPrivileged sets up options for a privileged container
|
||||
// TODO(justincormack) device handling
|
||||
var WithPrivileged = Compose(
|
||||
WithAllCapabilities,
|
||||
WithMaskedPaths(nil),
|
||||
@ -1139,3 +1179,85 @@ func WithAnnotations(annotations map[string]string) SpecOpts {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithLinuxDevices adds the provided linux devices to the spec
|
||||
func WithLinuxDevices(devices []specs.LinuxDevice) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
s.Linux.Devices = append(s.Linux.Devices, devices...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var ErrNotADevice = errors.New("not a device node")
|
||||
|
||||
// WithLinuxDevice adds the device specified by path to the spec
|
||||
func WithLinuxDevice(path, permissions string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
setResources(s)
|
||||
|
||||
dev, err := deviceFromPath(path, permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Linux.Devices = append(s.Linux.Devices, *dev)
|
||||
|
||||
s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, specs.LinuxDeviceCgroup{
|
||||
Type: dev.Type,
|
||||
Allow: true,
|
||||
Major: &dev.Major,
|
||||
Minor: &dev.Minor,
|
||||
Access: permissions,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnvFile adds environment variables from a file to the container's spec
|
||||
func WithEnvFile(path string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
var vars []string
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
sc := bufio.NewScanner(f)
|
||||
for sc.Scan() {
|
||||
if sc.Err() != nil {
|
||||
return sc.Err()
|
||||
}
|
||||
vars = append(vars, sc.Text())
|
||||
}
|
||||
return WithEnv(vars)(nil, nil, nil, s)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrNoShmMount is returned when there is no /dev/shm mount specified in the config
|
||||
// and an Opts was trying to set a configuration value on the mount.
|
||||
var ErrNoShmMount = errors.New("no /dev/shm mount specified")
|
||||
|
||||
// WithDevShmSize sets the size of the /dev/shm mount for the container.
|
||||
//
|
||||
// The size value is specified in kb, kilobytes.
|
||||
func WithDevShmSize(kb int64) SpecOpts {
|
||||
return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error {
|
||||
for _, m := range s.Mounts {
|
||||
if m.Source == "shm" && m.Type == "tmpfs" {
|
||||
for i, o := range m.Options {
|
||||
if strings.HasPrefix(o, "size=") {
|
||||
m.Options[i] = fmt.Sprintf("size=%dk", kb)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
m.Options = append(m.Options, fmt.Sprintf("size=%dk", kb))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ErrNoShmMount
|
||||
}
|
||||
}
|
||||
|
121
vendor/github.com/containerd/containerd/oci/spec_opts_linux.go
generated
vendored
Normal file
121
vendor/github.com/containerd/containerd/oci/spec_opts_linux.go
generated
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
// +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 oci
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// WithHostDevices adds all the hosts device nodes to the container's spec
|
||||
func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
|
||||
devs, err := getDevices("/dev")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Linux.Devices = append(s.Linux.Devices, devs...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDevices(path string) ([]specs.LinuxDevice, error) {
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []specs.LinuxDevice
|
||||
for _, f := range files {
|
||||
switch {
|
||||
case f.IsDir():
|
||||
switch f.Name() {
|
||||
// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
|
||||
// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
|
||||
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
|
||||
continue
|
||||
default:
|
||||
sub, err := getDevices(filepath.Join(path, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, sub...)
|
||||
continue
|
||||
}
|
||||
case f.Name() == "console":
|
||||
continue
|
||||
}
|
||||
device, err := deviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
||||
if err != nil {
|
||||
if err == ErrNotADevice {
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, *device)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
|
||||
var stat unix.Stat_t
|
||||
if err := unix.Lstat(path, &stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
// The type is 32bit on mips.
|
||||
devNumber = uint64(stat.Rdev) // nolint: unconvert
|
||||
major = unix.Major(devNumber)
|
||||
minor = unix.Minor(devNumber)
|
||||
)
|
||||
if major == 0 {
|
||||
return nil, ErrNotADevice
|
||||
}
|
||||
|
||||
var (
|
||||
devType string
|
||||
mode = stat.Mode
|
||||
)
|
||||
switch {
|
||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
||||
devType = "b"
|
||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
||||
devType = "c"
|
||||
}
|
||||
fm := os.FileMode(mode)
|
||||
return &specs.LinuxDevice{
|
||||
Type: devType,
|
||||
Path: path,
|
||||
Major: int64(major),
|
||||
Minor: int64(minor),
|
||||
FileMode: &fm,
|
||||
UID: &stat.Uid,
|
||||
GID: &stat.Gid,
|
||||
}, nil
|
||||
}
|
120
vendor/github.com/containerd/containerd/oci/spec_opts_unix.go
generated
vendored
Normal file
120
vendor/github.com/containerd/containerd/oci/spec_opts_unix.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
// +build !linux,!windows
|
||||
|
||||
/*
|
||||
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 oci
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// WithHostDevices adds all the hosts device nodes to the container's spec
|
||||
func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
setLinux(s)
|
||||
|
||||
devs, err := getDevices("/dev")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Linux.Devices = append(s.Linux.Devices, devs...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDevices(path string) ([]specs.LinuxDevice, error) {
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []specs.LinuxDevice
|
||||
for _, f := range files {
|
||||
switch {
|
||||
case f.IsDir():
|
||||
switch f.Name() {
|
||||
// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
|
||||
// ".udev" added to address https://github.com/opencontainers/runc/issues/2093
|
||||
case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts", ".udev":
|
||||
continue
|
||||
default:
|
||||
sub, err := getDevices(filepath.Join(path, f.Name()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, sub...)
|
||||
continue
|
||||
}
|
||||
case f.Name() == "console":
|
||||
continue
|
||||
}
|
||||
device, err := deviceFromPath(filepath.Join(path, f.Name()), "rwm")
|
||||
if err != nil {
|
||||
if err == ErrNotADevice {
|
||||
continue
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, *device)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
|
||||
var stat unix.Stat_t
|
||||
if err := unix.Lstat(path, &stat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
devNumber = uint64(stat.Rdev)
|
||||
major = unix.Major(devNumber)
|
||||
minor = unix.Minor(devNumber)
|
||||
)
|
||||
if major == 0 {
|
||||
return nil, ErrNotADevice
|
||||
}
|
||||
|
||||
var (
|
||||
devType string
|
||||
mode = stat.Mode
|
||||
)
|
||||
switch {
|
||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
||||
devType = "b"
|
||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
||||
devType = "c"
|
||||
}
|
||||
fm := os.FileMode(mode)
|
||||
return &specs.LinuxDevice{
|
||||
Type: devType,
|
||||
Path: path,
|
||||
Major: int64(major),
|
||||
Minor: int64(minor),
|
||||
FileMode: &fm,
|
||||
UID: &stat.Uid,
|
||||
GID: &stat.Gid,
|
||||
}, nil
|
||||
}
|
12
vendor/github.com/containerd/containerd/oci/spec_opts_windows.go
generated
vendored
12
vendor/github.com/containerd/containerd/oci/spec_opts_windows.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/containers"
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// WithWindowsCPUCount sets the `Windows.Resources.CPU.Count` section to the
|
||||
@ -65,3 +66,14 @@ func WithWindowNetworksAllowUnqualifiedDNSQuery() SpecOpts {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithHostDevices adds all the hosts device nodes to the container's spec
|
||||
//
|
||||
// Not supported on windows
|
||||
func WithHostDevices(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func deviceFromPath(path, permissions string) (*specs.LinuxDevice, error) {
|
||||
return nil, errors.New("device from path not supported on Windows")
|
||||
}
|
||||
|
14
vendor/github.com/containerd/containerd/pkg/dialer/dialer.go
generated
vendored
14
vendor/github.com/containerd/containerd/pkg/dialer/dialer.go
generated
vendored
@ -17,6 +17,7 @@
|
||||
package dialer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
@ -28,8 +29,19 @@ type dialResult struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// ContextDialer returns a GRPC net.Conn connected to the provided address
|
||||
func ContextDialer(ctx context.Context, address string) (net.Conn, error) {
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
return timeoutDialer(address, time.Until(deadline))
|
||||
}
|
||||
return timeoutDialer(address, 0)
|
||||
}
|
||||
|
||||
// Dialer returns a GRPC net.Conn connected to the provided address
|
||||
func Dialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||
// Deprecated: use ContextDialer and grpc.WithContextDialer.
|
||||
var Dialer = timeoutDialer
|
||||
|
||||
func timeoutDialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||
var (
|
||||
stopC = make(chan struct{})
|
||||
synC = make(chan *dialResult)
|
||||
|
37
vendor/github.com/containerd/containerd/platforms/compare.go
generated
vendored
37
vendor/github.com/containerd/containerd/platforms/compare.go
generated
vendored
@ -29,11 +29,48 @@ type MatchComparer interface {
|
||||
// Only returns a match comparer for a single platform
|
||||
// using default resolution logic for the platform.
|
||||
//
|
||||
// For ARMv8, will also match ARMv7, ARMv6 and ARMv5 (for 32bit runtimes)
|
||||
// For ARMv7, will also match ARMv6 and ARMv5
|
||||
// For ARMv6, will also match ARMv5
|
||||
func Only(platform specs.Platform) MatchComparer {
|
||||
platform = Normalize(platform)
|
||||
if platform.Architecture == "arm" {
|
||||
if platform.Variant == "v8" {
|
||||
return orderedPlatformComparer{
|
||||
matchers: []Matcher{
|
||||
&matcher{
|
||||
Platform: platform,
|
||||
},
|
||||
&matcher{
|
||||
Platform: specs.Platform{
|
||||
Architecture: platform.Architecture,
|
||||
OS: platform.OS,
|
||||
OSVersion: platform.OSVersion,
|
||||
OSFeatures: platform.OSFeatures,
|
||||
Variant: "v7",
|
||||
},
|
||||
},
|
||||
&matcher{
|
||||
Platform: specs.Platform{
|
||||
Architecture: platform.Architecture,
|
||||
OS: platform.OS,
|
||||
OSVersion: platform.OSVersion,
|
||||
OSFeatures: platform.OSFeatures,
|
||||
Variant: "v6",
|
||||
},
|
||||
},
|
||||
&matcher{
|
||||
Platform: specs.Platform{
|
||||
Architecture: platform.Architecture,
|
||||
OS: platform.OS,
|
||||
OSVersion: platform.OSVersion,
|
||||
OSFeatures: platform.OSFeatures,
|
||||
Variant: "v5",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
if platform.Variant == "v7" {
|
||||
return orderedPlatformComparer{
|
||||
matchers: []Matcher{
|
||||
|
2
vendor/github.com/containerd/containerd/platforms/cpuinfo.go
generated
vendored
2
vendor/github.com/containerd/containerd/platforms/cpuinfo.go
generated
vendored
@ -97,7 +97,7 @@ func getCPUVariant() string {
|
||||
}
|
||||
|
||||
switch variant {
|
||||
case "8":
|
||||
case "8", "AArch64":
|
||||
variant = "v8"
|
||||
case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)":
|
||||
variant = "v7"
|
||||
|
6
vendor/github.com/containerd/containerd/platforms/database.go
generated
vendored
6
vendor/github.com/containerd/containerd/platforms/database.go
generated
vendored
@ -28,7 +28,7 @@ func isLinuxOS(os string) bool {
|
||||
return os == "linux"
|
||||
}
|
||||
|
||||
// These function are generated from from https://golang.org/src/go/build/syslist.go.
|
||||
// These function are generated from https://golang.org/src/go/build/syslist.go.
|
||||
//
|
||||
// We use switch statements because they are slightly faster than map lookups
|
||||
// and use a little less memory.
|
||||
@ -38,7 +38,7 @@ func isLinuxOS(os string) bool {
|
||||
// The OS value should be normalized before calling this function.
|
||||
func isKnownOS(os string) bool {
|
||||
switch os {
|
||||
case "android", "darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos":
|
||||
case "aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -60,7 +60,7 @@ func isArmArch(arch string) bool {
|
||||
// The arch value should be normalized before being passed to this function.
|
||||
func isKnownArch(arch string) bool {
|
||||
switch arch {
|
||||
case "386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", "ppc", "s390", "s390x", "sparc", "sparc64":
|
||||
case "386", "amd64", "amd64p32", "arm", "armbe", "arm64", "arm64be", "ppc64", "ppc64le", "mips", "mipsle", "mips64", "mips64le", "mips64p32", "mips64p32le", "ppc", "riscv", "riscv64", "s390", "s390x", "sparc", "sparc64", "wasm":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
2
vendor/github.com/containerd/containerd/platforms/platforms.go
generated
vendored
2
vendor/github.com/containerd/containerd/platforms/platforms.go
generated
vendored
@ -130,7 +130,7 @@ type Matcher interface {
|
||||
// specification. The returned matcher only looks for equality based on os,
|
||||
// architecture and variant.
|
||||
//
|
||||
// One may implement their own matcher if this doesn't provide the the required
|
||||
// One may implement their own matcher if this doesn't provide the required
|
||||
// functionality.
|
||||
//
|
||||
// Applications should opt to use `Match` over directly parsing specifiers.
|
||||
|
13
vendor/github.com/containerd/containerd/plugin/context.go
generated
vendored
13
vendor/github.com/containerd/containerd/plugin/context.go
generated
vendored
@ -28,12 +28,13 @@ import (
|
||||
|
||||
// InitContext is used for plugin inititalization
|
||||
type InitContext struct {
|
||||
Context context.Context
|
||||
Root string
|
||||
State string
|
||||
Config interface{}
|
||||
Address string
|
||||
Events *exchange.Exchange
|
||||
Context context.Context
|
||||
Root string
|
||||
State string
|
||||
Config interface{}
|
||||
Address string
|
||||
TTRPCAddress string
|
||||
Events *exchange.Exchange
|
||||
|
||||
Meta *Meta // plugins can fill in metadata at init.
|
||||
|
||||
|
49
vendor/github.com/containerd/containerd/plugin/plugin.go
generated
vendored
49
vendor/github.com/containerd/containerd/plugin/plugin.go
generated
vendored
@ -30,7 +30,8 @@ var (
|
||||
ErrNoType = errors.New("plugin: no type")
|
||||
// ErrNoPluginID is returned when no id is specified
|
||||
ErrNoPluginID = errors.New("plugin: no id")
|
||||
|
||||
// ErrIDRegistered is returned when a duplicate id is already registered
|
||||
ErrIDRegistered = errors.New("plugin: id already registered")
|
||||
// ErrSkipPlugin is used when a plugin is not initialized and should not be loaded,
|
||||
// this allows the plugin loader differentiate between a plugin which is configured
|
||||
// not to load and one that fails to load.
|
||||
@ -100,6 +101,8 @@ type Registration struct {
|
||||
// context are passed in. The init function may modify the registration to
|
||||
// add exports, capabilities and platform support declarations.
|
||||
InitFn func(*InitContext) (interface{}, error)
|
||||
// Disable the plugin from loading
|
||||
Disable bool
|
||||
}
|
||||
|
||||
// Init the registered plugin
|
||||
@ -157,12 +160,16 @@ func Load(path string) (err error) {
|
||||
func Register(r *Registration) {
|
||||
register.Lock()
|
||||
defer register.Unlock()
|
||||
|
||||
if r.Type == "" {
|
||||
panic(ErrNoType)
|
||||
}
|
||||
if r.ID == "" {
|
||||
panic(ErrNoPluginID)
|
||||
}
|
||||
if err := checkUnique(r); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var last bool
|
||||
for _, requires := range r.Requires {
|
||||
@ -177,24 +184,36 @@ func Register(r *Registration) {
|
||||
register.r = append(register.r, r)
|
||||
}
|
||||
|
||||
func checkUnique(r *Registration) error {
|
||||
for _, registered := range register.r {
|
||||
if r.URI() == registered.URI() {
|
||||
return errors.Wrap(ErrIDRegistered, r.URI())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableFilter filters out disabled plugins
|
||||
type DisableFilter func(r *Registration) bool
|
||||
|
||||
// Graph returns an ordered list of registered plugins for initialization.
|
||||
// Plugins in disableList specified by id will be disabled.
|
||||
func Graph(disableList []string) (ordered []*Registration) {
|
||||
func Graph(filter DisableFilter) (ordered []*Registration) {
|
||||
register.RLock()
|
||||
defer register.RUnlock()
|
||||
for _, d := range disableList {
|
||||
for i, r := range register.r {
|
||||
if r.ID == d {
|
||||
register.r = append(register.r[:i], register.r[i+1:]...)
|
||||
break
|
||||
}
|
||||
|
||||
for _, r := range register.r {
|
||||
if filter(r) {
|
||||
r.Disable = true
|
||||
}
|
||||
}
|
||||
|
||||
added := map[*Registration]bool{}
|
||||
for _, r := range register.r {
|
||||
|
||||
children(r.ID, r.Requires, added, &ordered)
|
||||
if r.Disable {
|
||||
continue
|
||||
}
|
||||
children(r, added, &ordered)
|
||||
if !added[r] {
|
||||
ordered = append(ordered, r)
|
||||
added[r] = true
|
||||
@ -203,11 +222,13 @@ func Graph(disableList []string) (ordered []*Registration) {
|
||||
return ordered
|
||||
}
|
||||
|
||||
func children(id string, types []Type, added map[*Registration]bool, ordered *[]*Registration) {
|
||||
for _, t := range types {
|
||||
func children(reg *Registration, added map[*Registration]bool, ordered *[]*Registration) {
|
||||
for _, t := range reg.Requires {
|
||||
for _, r := range register.r {
|
||||
if r.ID != id && (t == "*" || r.Type == t) {
|
||||
children(r.ID, r.Requires, added, ordered)
|
||||
if !r.Disable &&
|
||||
r.URI() != reg.URI() &&
|
||||
(t == "*" || r.Type == t) {
|
||||
children(r, added, ordered)
|
||||
if !added[r] {
|
||||
*ordered = append(*ordered, r)
|
||||
added[r] = true
|
||||
|
4
vendor/github.com/containerd/containerd/process.go
generated
vendored
4
vendor/github.com/containerd/containerd/process.go
generated
vendored
@ -44,7 +44,7 @@ type Process interface {
|
||||
Wait(context.Context) (<-chan ExitStatus, error)
|
||||
// CloseIO allows various pipes to be closed on the process
|
||||
CloseIO(context.Context, ...IOCloserOpts) error
|
||||
// Resize changes the width and heigh of the process's terminal
|
||||
// Resize changes the width and height of the process's terminal
|
||||
Resize(ctx context.Context, w, h uint32) error
|
||||
// IO returns the io set for the process
|
||||
IO() cio.IO
|
||||
@ -61,7 +61,7 @@ func NewExitStatus(code uint32, t time.Time, err error) *ExitStatus {
|
||||
}
|
||||
}
|
||||
|
||||
// ExitStatus encapsulates a process' exit status.
|
||||
// ExitStatus encapsulates a process's exit status.
|
||||
// It is used by `Wait()` to return either a process exit code or an error
|
||||
type ExitStatus struct {
|
||||
code uint32
|
||||
|
63
vendor/github.com/containerd/containerd/pull.go
generated
vendored
63
vendor/github.com/containerd/containerd/pull.go
generated
vendored
@ -32,7 +32,7 @@ import (
|
||||
|
||||
// Pull downloads the provided content into containerd's content store
|
||||
// and returns a platform specific image object
|
||||
func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image, error) {
|
||||
func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Image, retErr error) {
|
||||
pullCtx := defaultRemoteContext()
|
||||
for _, o := range opts {
|
||||
if err := o(c, pullCtx); err != nil {
|
||||
@ -44,7 +44,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
if len(pullCtx.Platforms) > 1 {
|
||||
return nil, errors.New("cannot pull multiplatform image locally, try Fetch")
|
||||
} else if len(pullCtx.Platforms) == 0 {
|
||||
pullCtx.PlatformMatcher = platforms.Default()
|
||||
pullCtx.PlatformMatcher = c.platform
|
||||
} else {
|
||||
p, err := platforms.Parse(pullCtx.Platforms[0])
|
||||
if err != nil {
|
||||
@ -61,6 +61,30 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
}
|
||||
defer done(ctx)
|
||||
|
||||
var unpacks int32
|
||||
if pullCtx.Unpack {
|
||||
// unpacker only supports schema 2 image, for schema 1 this is noop.
|
||||
u, err := c.newUnpacker(ctx, pullCtx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "create unpacker")
|
||||
}
|
||||
unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks)
|
||||
defer func() {
|
||||
if err := eg.Wait(); err != nil {
|
||||
if retErr == nil {
|
||||
retErr = errors.Wrap(err, "unpack")
|
||||
}
|
||||
}
|
||||
}()
|
||||
wrapper := pullCtx.HandlerWrapper
|
||||
pullCtx.HandlerWrapper = func(h images.Handler) images.Handler {
|
||||
if wrapper == nil {
|
||||
return unpackWrapper(h)
|
||||
}
|
||||
return wrapper(unpackWrapper(h))
|
||||
}
|
||||
}
|
||||
|
||||
img, err := c.fetch(ctx, pullCtx, ref, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -69,8 +93,12 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image
|
||||
i := NewImageWithPlatform(c, img, pullCtx.PlatformMatcher)
|
||||
|
||||
if pullCtx.Unpack {
|
||||
if err := i.Unpack(ctx, pullCtx.Snapshotter); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
|
||||
if unpacks == 0 {
|
||||
// Try to unpack is none is done previously.
|
||||
// This is at least required for schema 1 image.
|
||||
if err := i.Unpack(ctx, pullCtx.Snapshotter, pullCtx.UnpackOpts...); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unpack image on snapshotter %s", pullCtx.Snapshotter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,9 +140,14 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
|
||||
childrenHandler := images.ChildrenHandler(store)
|
||||
// Set any children labels for that content
|
||||
childrenHandler = images.SetChildrenLabels(store, childrenHandler)
|
||||
// Filter manifests by platforms but allow to handle manifest
|
||||
// and configuration for not-target platforms
|
||||
childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher)
|
||||
if rCtx.AllMetadata {
|
||||
// Filter manifests by platforms but allow to handle manifest
|
||||
// and configuration for not-target platforms
|
||||
childrenHandler = remotes.FilterManifestByPlatformHandler(childrenHandler, rCtx.PlatformMatcher)
|
||||
} else {
|
||||
// Filter children by platforms if specified.
|
||||
childrenHandler = images.FilterPlatforms(childrenHandler, rCtx.PlatformMatcher)
|
||||
}
|
||||
// Sort and limit manifests if a finite number is needed
|
||||
if limit > 0 {
|
||||
childrenHandler = images.LimitManifests(childrenHandler, rCtx.PlatformMatcher, limit)
|
||||
@ -131,22 +164,18 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim
|
||||
},
|
||||
)
|
||||
|
||||
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
|
||||
if err != nil {
|
||||
return images.Image{}, err
|
||||
}
|
||||
|
||||
handlers := append(rCtx.BaseHandlers,
|
||||
remotes.FetchHandler(store, fetcher),
|
||||
convertibleHandler,
|
||||
childrenHandler,
|
||||
appendDistSrcLabelHandler,
|
||||
)
|
||||
|
||||
// append distribution source label to blob data
|
||||
if rCtx.AppendDistributionSourceLabel {
|
||||
appendDistSrcLabelHandler, err := docker.AppendDistributionSourceLabel(store, ref)
|
||||
if err != nil {
|
||||
return images.Image{}, err
|
||||
}
|
||||
|
||||
handlers = append(handlers, appendDistSrcLabelHandler)
|
||||
}
|
||||
|
||||
handler = images.Handlers(handlers...)
|
||||
|
||||
converterFunc = func(ctx context.Context, desc ocispec.Descriptor) (ocispec.Descriptor, error) {
|
||||
|
797
vendor/github.com/containerd/containerd/reference/docker/reference.go
generated
vendored
Normal file
797
vendor/github.com/containerd/containerd/reference/docker/reference.go
generated
vendored
Normal file
@ -0,0 +1,797 @@
|
||||
/*
|
||||
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 docker provides a general type to represent any way of referencing images within the registry.
|
||||
// Its main purpose is to abstract tags and digests (content-addressable hash).
|
||||
//
|
||||
// Grammar
|
||||
//
|
||||
// reference := name [ ":" tag ] [ "@" digest ]
|
||||
// name := [domain '/'] path-component ['/' path-component]*
|
||||
// domain := domain-component ['.' domain-component]* [':' port-number]
|
||||
// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
||||
// port-number := /[0-9]+/
|
||||
// path-component := alpha-numeric [separator alpha-numeric]*
|
||||
// alpha-numeric := /[a-z0-9]+/
|
||||
// separator := /[_.]|__|[-]*/
|
||||
//
|
||||
// tag := /[\w][\w.-]{0,127}/
|
||||
//
|
||||
// digest := digest-algorithm ":" digest-hex
|
||||
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]*
|
||||
// digest-algorithm-separator := /[+.-_]/
|
||||
// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
|
||||
// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
|
||||
//
|
||||
// identifier := /[a-f0-9]{64}/
|
||||
// short-identifier := /[a-f0-9]{6,64}/
|
||||
package docker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
const (
|
||||
// NameTotalLengthMax is the maximum total number of characters in a repository name.
|
||||
NameTotalLengthMax = 255
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrReferenceInvalidFormat represents an error while trying to parse a string as a reference.
|
||||
ErrReferenceInvalidFormat = errors.New("invalid reference format")
|
||||
|
||||
// ErrTagInvalidFormat represents an error while trying to parse a string as a tag.
|
||||
ErrTagInvalidFormat = errors.New("invalid tag format")
|
||||
|
||||
// ErrDigestInvalidFormat represents an error while trying to parse a string as a tag.
|
||||
ErrDigestInvalidFormat = errors.New("invalid digest format")
|
||||
|
||||
// ErrNameContainsUppercase is returned for invalid repository names that contain uppercase characters.
|
||||
ErrNameContainsUppercase = errors.New("repository name must be lowercase")
|
||||
|
||||
// ErrNameEmpty is returned for empty, invalid repository names.
|
||||
ErrNameEmpty = errors.New("repository name must have at least one component")
|
||||
|
||||
// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
|
||||
ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
|
||||
|
||||
// ErrNameNotCanonical is returned when a name is not canonical.
|
||||
ErrNameNotCanonical = errors.New("repository name must be canonical")
|
||||
)
|
||||
|
||||
// Reference is an opaque object reference identifier that may include
|
||||
// modifiers such as a hostname, name, tag, and digest.
|
||||
type Reference interface {
|
||||
// String returns the full reference
|
||||
String() string
|
||||
}
|
||||
|
||||
// Field provides a wrapper type for resolving correct reference types when
|
||||
// working with encoding.
|
||||
type Field struct {
|
||||
reference Reference
|
||||
}
|
||||
|
||||
// AsField wraps a reference in a Field for encoding.
|
||||
func AsField(reference Reference) Field {
|
||||
return Field{reference}
|
||||
}
|
||||
|
||||
// Reference unwraps the reference type from the field to
|
||||
// return the Reference object. This object should be
|
||||
// of the appropriate type to further check for different
|
||||
// reference types.
|
||||
func (f Field) Reference() Reference {
|
||||
return f.reference
|
||||
}
|
||||
|
||||
// MarshalText serializes the field to byte text which
|
||||
// is the string of the reference.
|
||||
func (f Field) MarshalText() (p []byte, err error) {
|
||||
return []byte(f.reference.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText parses text bytes by invoking the
|
||||
// reference parser to ensure the appropriately
|
||||
// typed reference object is wrapped by field.
|
||||
func (f *Field) UnmarshalText(p []byte) error {
|
||||
r, err := Parse(string(p))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.reference = r
|
||||
return nil
|
||||
}
|
||||
|
||||
// Named is an object with a full name
|
||||
type Named interface {
|
||||
Reference
|
||||
Name() string
|
||||
}
|
||||
|
||||
// Tagged is an object which has a tag
|
||||
type Tagged interface {
|
||||
Reference
|
||||
Tag() string
|
||||
}
|
||||
|
||||
// NamedTagged is an object including a name and tag.
|
||||
type NamedTagged interface {
|
||||
Named
|
||||
Tag() string
|
||||
}
|
||||
|
||||
// Digested is an object which has a digest
|
||||
// in which it can be referenced by
|
||||
type Digested interface {
|
||||
Reference
|
||||
Digest() digest.Digest
|
||||
}
|
||||
|
||||
// Canonical reference is an object with a fully unique
|
||||
// name including a name with domain and digest
|
||||
type Canonical interface {
|
||||
Named
|
||||
Digest() digest.Digest
|
||||
}
|
||||
|
||||
// namedRepository is a reference to a repository with a name.
|
||||
// A namedRepository has both domain and path components.
|
||||
type namedRepository interface {
|
||||
Named
|
||||
Domain() string
|
||||
Path() string
|
||||
}
|
||||
|
||||
// Domain returns the domain part of the Named reference
|
||||
func Domain(named Named) string {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Domain()
|
||||
}
|
||||
domain, _ := splitDomain(named.Name())
|
||||
return domain
|
||||
}
|
||||
|
||||
// Path returns the name without the domain part of the Named reference
|
||||
func Path(named Named) (name string) {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Path()
|
||||
}
|
||||
_, path := splitDomain(named.Name())
|
||||
return path
|
||||
}
|
||||
|
||||
func splitDomain(name string) (string, string) {
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if len(match) != 3 {
|
||||
return "", name
|
||||
}
|
||||
return match[1], match[2]
|
||||
}
|
||||
|
||||
// SplitHostname splits a named reference into a
|
||||
// hostname and name string. If no valid hostname is
|
||||
// found, the hostname is empty and the full value
|
||||
// is returned as name
|
||||
// DEPRECATED: Use Domain or Path
|
||||
func SplitHostname(named Named) (string, string) {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Domain(), r.Path()
|
||||
}
|
||||
return splitDomain(named.Name())
|
||||
}
|
||||
|
||||
// Parse parses s and returns a syntactically valid Reference.
|
||||
// If an error was encountered it is returned, along with a nil Reference.
|
||||
// NOTE: Parse will not handle short digests.
|
||||
func Parse(s string) (Reference, error) {
|
||||
matches := ReferenceRegexp.FindStringSubmatch(s)
|
||||
if matches == nil {
|
||||
if s == "" {
|
||||
return nil, ErrNameEmpty
|
||||
}
|
||||
if ReferenceRegexp.FindStringSubmatch(strings.ToLower(s)) != nil {
|
||||
return nil, ErrNameContainsUppercase
|
||||
}
|
||||
return nil, ErrReferenceInvalidFormat
|
||||
}
|
||||
|
||||
if len(matches[1]) > NameTotalLengthMax {
|
||||
return nil, ErrNameTooLong
|
||||
}
|
||||
|
||||
var repo repository
|
||||
|
||||
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
||||
if len(nameMatch) == 3 {
|
||||
repo.domain = nameMatch[1]
|
||||
repo.path = nameMatch[2]
|
||||
} else {
|
||||
repo.domain = ""
|
||||
repo.path = matches[1]
|
||||
}
|
||||
|
||||
ref := reference{
|
||||
namedRepository: repo,
|
||||
tag: matches[2],
|
||||
}
|
||||
if matches[3] != "" {
|
||||
var err error
|
||||
ref.digest, err = digest.Parse(matches[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
r := getBestReferenceType(ref)
|
||||
if r == nil {
|
||||
return nil, ErrNameEmpty
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// ParseNamed parses s and returns a syntactically valid reference implementing
|
||||
// the Named interface. The reference must have a name and be in the canonical
|
||||
// form, otherwise an error is returned.
|
||||
// If an error was encountered it is returned, along with a nil Reference.
|
||||
// NOTE: ParseNamed will not handle short digests.
|
||||
func ParseNamed(s string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if named.String() != s {
|
||||
return nil, ErrNameNotCanonical
|
||||
}
|
||||
return named, nil
|
||||
}
|
||||
|
||||
// WithName returns a named object representing the given string. If the input
|
||||
// is invalid ErrReferenceInvalidFormat will be returned.
|
||||
func WithName(name string) (Named, error) {
|
||||
if len(name) > NameTotalLengthMax {
|
||||
return nil, ErrNameTooLong
|
||||
}
|
||||
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if match == nil || len(match) != 3 {
|
||||
return nil, ErrReferenceInvalidFormat
|
||||
}
|
||||
return repository{
|
||||
domain: match[1],
|
||||
path: match[2],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithTag combines the name from "name" and the tag from "tag" to form a
|
||||
// reference incorporating both the name and the tag.
|
||||
func WithTag(name Named, tag string) (NamedTagged, error) {
|
||||
if !anchoredTagRegexp.MatchString(tag) {
|
||||
return nil, ErrTagInvalidFormat
|
||||
}
|
||||
var repo repository
|
||||
if r, ok := name.(namedRepository); ok {
|
||||
repo.domain = r.Domain()
|
||||
repo.path = r.Path()
|
||||
} else {
|
||||
repo.path = name.Name()
|
||||
}
|
||||
if canonical, ok := name.(Canonical); ok {
|
||||
return reference{
|
||||
namedRepository: repo,
|
||||
tag: tag,
|
||||
digest: canonical.Digest(),
|
||||
}, nil
|
||||
}
|
||||
return taggedReference{
|
||||
namedRepository: repo,
|
||||
tag: tag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// WithDigest combines the name from "name" and the digest from "digest" to form
|
||||
// a reference incorporating both the name and the digest.
|
||||
func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
|
||||
if !anchoredDigestRegexp.MatchString(digest.String()) {
|
||||
return nil, ErrDigestInvalidFormat
|
||||
}
|
||||
var repo repository
|
||||
if r, ok := name.(namedRepository); ok {
|
||||
repo.domain = r.Domain()
|
||||
repo.path = r.Path()
|
||||
} else {
|
||||
repo.path = name.Name()
|
||||
}
|
||||
if tagged, ok := name.(Tagged); ok {
|
||||
return reference{
|
||||
namedRepository: repo,
|
||||
tag: tagged.Tag(),
|
||||
digest: digest,
|
||||
}, nil
|
||||
}
|
||||
return canonicalReference{
|
||||
namedRepository: repo,
|
||||
digest: digest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TrimNamed removes any tag or digest from the named reference.
|
||||
func TrimNamed(ref Named) Named {
|
||||
domain, path := SplitHostname(ref)
|
||||
return repository{
|
||||
domain: domain,
|
||||
path: path,
|
||||
}
|
||||
}
|
||||
|
||||
func getBestReferenceType(ref reference) Reference {
|
||||
if ref.Name() == "" {
|
||||
// Allow digest only references
|
||||
if ref.digest != "" {
|
||||
return digestReference(ref.digest)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if ref.tag == "" {
|
||||
if ref.digest != "" {
|
||||
return canonicalReference{
|
||||
namedRepository: ref.namedRepository,
|
||||
digest: ref.digest,
|
||||
}
|
||||
}
|
||||
return ref.namedRepository
|
||||
}
|
||||
if ref.digest == "" {
|
||||
return taggedReference{
|
||||
namedRepository: ref.namedRepository,
|
||||
tag: ref.tag,
|
||||
}
|
||||
}
|
||||
|
||||
return ref
|
||||
}
|
||||
|
||||
type reference struct {
|
||||
namedRepository
|
||||
tag string
|
||||
digest digest.Digest
|
||||
}
|
||||
|
||||
func (r reference) String() string {
|
||||
return r.Name() + ":" + r.tag + "@" + r.digest.String()
|
||||
}
|
||||
|
||||
func (r reference) Tag() string {
|
||||
return r.tag
|
||||
}
|
||||
|
||||
func (r reference) Digest() digest.Digest {
|
||||
return r.digest
|
||||
}
|
||||
|
||||
type repository struct {
|
||||
domain string
|
||||
path string
|
||||
}
|
||||
|
||||
func (r repository) String() string {
|
||||
return r.Name()
|
||||
}
|
||||
|
||||
func (r repository) Name() string {
|
||||
if r.domain == "" {
|
||||
return r.path
|
||||
}
|
||||
return r.domain + "/" + r.path
|
||||
}
|
||||
|
||||
func (r repository) Domain() string {
|
||||
return r.domain
|
||||
}
|
||||
|
||||
func (r repository) Path() string {
|
||||
return r.path
|
||||
}
|
||||
|
||||
type digestReference digest.Digest
|
||||
|
||||
func (d digestReference) String() string {
|
||||
return digest.Digest(d).String()
|
||||
}
|
||||
|
||||
func (d digestReference) Digest() digest.Digest {
|
||||
return digest.Digest(d)
|
||||
}
|
||||
|
||||
type taggedReference struct {
|
||||
namedRepository
|
||||
tag string
|
||||
}
|
||||
|
||||
func (t taggedReference) String() string {
|
||||
return t.Name() + ":" + t.tag
|
||||
}
|
||||
|
||||
func (t taggedReference) Tag() string {
|
||||
return t.tag
|
||||
}
|
||||
|
||||
type canonicalReference struct {
|
||||
namedRepository
|
||||
digest digest.Digest
|
||||
}
|
||||
|
||||
func (c canonicalReference) String() string {
|
||||
return c.Name() + "@" + c.digest.String()
|
||||
}
|
||||
|
||||
func (c canonicalReference) Digest() digest.Digest {
|
||||
return c.digest
|
||||
}
|
||||
|
||||
var (
|
||||
// alphaNumericRegexp defines the alpha numeric atom, typically a
|
||||
// component of names. This only allows lower case characters and digits.
|
||||
alphaNumericRegexp = match(`[a-z0-9]+`)
|
||||
|
||||
// separatorRegexp defines the separators allowed to be embedded in name
|
||||
// components. This allow one period, one or two underscore and multiple
|
||||
// dashes.
|
||||
separatorRegexp = match(`(?:[._]|__|[-]*)`)
|
||||
|
||||
// nameComponentRegexp restricts registry path component names to start
|
||||
// with at least one letter or number, with following parts able to be
|
||||
// separated by one period, one or two underscore and multiple dashes.
|
||||
nameComponentRegexp = expression(
|
||||
alphaNumericRegexp,
|
||||
optional(repeated(separatorRegexp, alphaNumericRegexp)))
|
||||
|
||||
// domainComponentRegexp restricts the registry domain component of a
|
||||
// repository name to start with a component as defined by DomainRegexp
|
||||
// and followed by an optional port.
|
||||
domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
|
||||
|
||||
// DomainRegexp defines the structure of potential domain components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
// names.
|
||||
DomainRegexp = expression(
|
||||
domainComponentRegexp,
|
||||
optional(repeated(literal(`.`), domainComponentRegexp)),
|
||||
optional(literal(`:`), match(`[0-9]+`)))
|
||||
|
||||
// TagRegexp matches valid tag names. From docker/docker:graph/tags.go.
|
||||
TagRegexp = match(`[\w][\w.-]{0,127}`)
|
||||
|
||||
// anchoredTagRegexp matches valid tag names, anchored at the start and
|
||||
// end of the matched string.
|
||||
anchoredTagRegexp = anchored(TagRegexp)
|
||||
|
||||
// DigestRegexp matches valid digests.
|
||||
DigestRegexp = match(`[A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}`)
|
||||
|
||||
// anchoredDigestRegexp matches valid digests, anchored at the start and
|
||||
// end of the matched string.
|
||||
anchoredDigestRegexp = anchored(DigestRegexp)
|
||||
|
||||
// NameRegexp is the format for the name component of references. The
|
||||
// regexp has capturing groups for the domain and name part omitting
|
||||
// the separating forward slash from either.
|
||||
NameRegexp = expression(
|
||||
optional(DomainRegexp, literal(`/`)),
|
||||
nameComponentRegexp,
|
||||
optional(repeated(literal(`/`), nameComponentRegexp)))
|
||||
|
||||
// anchoredNameRegexp is used to parse a name value, capturing the
|
||||
// domain and trailing components.
|
||||
anchoredNameRegexp = anchored(
|
||||
optional(capture(DomainRegexp), literal(`/`)),
|
||||
capture(nameComponentRegexp,
|
||||
optional(repeated(literal(`/`), nameComponentRegexp))))
|
||||
|
||||
// ReferenceRegexp is the full supported format of a reference. The regexp
|
||||
// is anchored and has capturing groups for name, tag, and digest
|
||||
// components.
|
||||
ReferenceRegexp = anchored(capture(NameRegexp),
|
||||
optional(literal(":"), capture(TagRegexp)),
|
||||
optional(literal("@"), capture(DigestRegexp)))
|
||||
|
||||
// IdentifierRegexp is the format for string identifier used as a
|
||||
// content addressable identifier using sha256. These identifiers
|
||||
// are like digests without the algorithm, since sha256 is used.
|
||||
IdentifierRegexp = match(`([a-f0-9]{64})`)
|
||||
|
||||
// ShortIdentifierRegexp is the format used to represent a prefix
|
||||
// of an identifier. A prefix may be used to match a sha256 identifier
|
||||
// within a list of trusted identifiers.
|
||||
ShortIdentifierRegexp = match(`([a-f0-9]{6,64})`)
|
||||
|
||||
// anchoredIdentifierRegexp is used to check or match an
|
||||
// identifier value, anchored at start and end of string.
|
||||
anchoredIdentifierRegexp = anchored(IdentifierRegexp)
|
||||
)
|
||||
|
||||
// match compiles the string to a regular expression.
|
||||
var match = regexp.MustCompile
|
||||
|
||||
// literal compiles s into a literal regular expression, escaping any regexp
|
||||
// reserved characters.
|
||||
func literal(s string) *regexp.Regexp {
|
||||
re := match(regexp.QuoteMeta(s))
|
||||
|
||||
if _, complete := re.LiteralPrefix(); !complete {
|
||||
panic("must be a literal")
|
||||
}
|
||||
|
||||
return re
|
||||
}
|
||||
|
||||
// expression defines a full expression, where each regular expression must
|
||||
// follow the previous.
|
||||
func expression(res ...*regexp.Regexp) *regexp.Regexp {
|
||||
var s string
|
||||
for _, re := range res {
|
||||
s += re.String()
|
||||
}
|
||||
|
||||
return match(s)
|
||||
}
|
||||
|
||||
// optional wraps the expression in a non-capturing group and makes the
|
||||
// production optional.
|
||||
func optional(res ...*regexp.Regexp) *regexp.Regexp {
|
||||
return match(group(expression(res...)).String() + `?`)
|
||||
}
|
||||
|
||||
// repeated wraps the regexp in a non-capturing group to get one or more
|
||||
// matches.
|
||||
func repeated(res ...*regexp.Regexp) *regexp.Regexp {
|
||||
return match(group(expression(res...)).String() + `+`)
|
||||
}
|
||||
|
||||
// group wraps the regexp in a non-capturing group.
|
||||
func group(res ...*regexp.Regexp) *regexp.Regexp {
|
||||
return match(`(?:` + expression(res...).String() + `)`)
|
||||
}
|
||||
|
||||
// capture wraps the expression in a capturing group.
|
||||
func capture(res ...*regexp.Regexp) *regexp.Regexp {
|
||||
return match(`(` + expression(res...).String() + `)`)
|
||||
}
|
||||
|
||||
// anchored anchors the regular expression by adding start and end delimiters.
|
||||
func anchored(res ...*regexp.Regexp) *regexp.Regexp {
|
||||
return match(`^` + expression(res...).String() + `$`)
|
||||
}
|
||||
|
||||
var (
|
||||
legacyDefaultDomain = "index.docker.io"
|
||||
defaultDomain = "docker.io"
|
||||
officialRepoName = "library"
|
||||
defaultTag = "latest"
|
||||
)
|
||||
|
||||
// normalizedNamed represents a name which has been
|
||||
// normalized and has a familiar form. A familiar name
|
||||
// is what is used in Docker UI. An example normalized
|
||||
// name is "docker.io/library/ubuntu" and corresponding
|
||||
// familiar name of "ubuntu".
|
||||
type normalizedNamed interface {
|
||||
Named
|
||||
Familiar() Named
|
||||
}
|
||||
|
||||
// ParseNormalizedNamed parses a string into a named reference
|
||||
// transforming a familiar name from Docker UI to a fully
|
||||
// qualified reference. If the value may be an identifier
|
||||
// use ParseAnyReference.
|
||||
func ParseNormalizedNamed(s string) (Named, error) {
|
||||
if ok := anchoredIdentifierRegexp.MatchString(s); ok {
|
||||
return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s)
|
||||
}
|
||||
domain, remainder := splitDockerDomain(s)
|
||||
var remoteName string
|
||||
if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 {
|
||||
remoteName = remainder[:tagSep]
|
||||
} else {
|
||||
remoteName = remainder
|
||||
}
|
||||
if strings.ToLower(remoteName) != remoteName {
|
||||
return nil, errors.New("invalid reference format: repository name must be lowercase")
|
||||
}
|
||||
|
||||
ref, err := Parse(domain + "/" + remainder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
named, isNamed := ref.(Named)
|
||||
if !isNamed {
|
||||
return nil, fmt.Errorf("reference %s has no name", ref.String())
|
||||
}
|
||||
return named, nil
|
||||
}
|
||||
|
||||
// ParseDockerRef normalizes the image reference following the docker convention. This is added
|
||||
// mainly for backward compatibility.
|
||||
// The reference returned can only be either tagged or digested. For reference contains both tag
|
||||
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
||||
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
||||
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
||||
func ParseDockerRef(ref string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := named.(NamedTagged); ok {
|
||||
if canonical, ok := named.(Canonical); ok {
|
||||
// The reference is both tagged and digested, only
|
||||
// return digested.
|
||||
newNamed, err := WithName(canonical.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newCanonical, err := WithDigest(newNamed, canonical.Digest())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newCanonical, nil
|
||||
}
|
||||
}
|
||||
return TagNameOnly(named), nil
|
||||
}
|
||||
|
||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||
// If no valid domain is found, the default domain is used. Repository name
|
||||
// needs to be already validated before.
|
||||
func splitDockerDomain(name string) (domain, remainder string) {
|
||||
i := strings.IndexRune(name, '/')
|
||||
if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") {
|
||||
domain, remainder = defaultDomain, name
|
||||
} else {
|
||||
domain, remainder = name[:i], name[i+1:]
|
||||
}
|
||||
if domain == legacyDefaultDomain {
|
||||
domain = defaultDomain
|
||||
}
|
||||
if domain == defaultDomain && !strings.ContainsRune(remainder, '/') {
|
||||
remainder = officialRepoName + "/" + remainder
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// familiarizeName returns a shortened version of the name familiar
|
||||
// to to the Docker UI. Familiar names have the default domain
|
||||
// "docker.io" and "library/" repository prefix removed.
|
||||
// For example, "docker.io/library/redis" will have the familiar
|
||||
// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp".
|
||||
// Returns a familiarized named only reference.
|
||||
func familiarizeName(named namedRepository) repository {
|
||||
repo := repository{
|
||||
domain: named.Domain(),
|
||||
path: named.Path(),
|
||||
}
|
||||
|
||||
if repo.domain == defaultDomain {
|
||||
repo.domain = ""
|
||||
// Handle official repositories which have the pattern "library/<official repo name>"
|
||||
if split := strings.Split(repo.path, "/"); len(split) == 2 && split[0] == officialRepoName {
|
||||
repo.path = split[1]
|
||||
}
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func (r reference) Familiar() Named {
|
||||
return reference{
|
||||
namedRepository: familiarizeName(r.namedRepository),
|
||||
tag: r.tag,
|
||||
digest: r.digest,
|
||||
}
|
||||
}
|
||||
|
||||
func (r repository) Familiar() Named {
|
||||
return familiarizeName(r)
|
||||
}
|
||||
|
||||
func (t taggedReference) Familiar() Named {
|
||||
return taggedReference{
|
||||
namedRepository: familiarizeName(t.namedRepository),
|
||||
tag: t.tag,
|
||||
}
|
||||
}
|
||||
|
||||
func (c canonicalReference) Familiar() Named {
|
||||
return canonicalReference{
|
||||
namedRepository: familiarizeName(c.namedRepository),
|
||||
digest: c.digest,
|
||||
}
|
||||
}
|
||||
|
||||
// TagNameOnly adds the default tag "latest" to a reference if it only has
|
||||
// a repo name.
|
||||
func TagNameOnly(ref Named) Named {
|
||||
if IsNameOnly(ref) {
|
||||
namedTagged, err := WithTag(ref, defaultTag)
|
||||
if err != nil {
|
||||
// Default tag must be valid, to create a NamedTagged
|
||||
// type with non-validated input the WithTag function
|
||||
// should be used instead
|
||||
panic(err)
|
||||
}
|
||||
return namedTagged
|
||||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
// ParseAnyReference parses a reference string as a possible identifier,
|
||||
// full digest, or familiar name.
|
||||
func ParseAnyReference(ref string) (Reference, error) {
|
||||
if ok := anchoredIdentifierRegexp.MatchString(ref); ok {
|
||||
return digestReference("sha256:" + ref), nil
|
||||
}
|
||||
if dgst, err := digest.Parse(ref); err == nil {
|
||||
return digestReference(dgst), nil
|
||||
}
|
||||
|
||||
return ParseNormalizedNamed(ref)
|
||||
}
|
||||
|
||||
// IsNameOnly returns true if reference only contains a repo name.
|
||||
func IsNameOnly(ref Named) bool {
|
||||
if _, ok := ref.(NamedTagged); ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := ref.(Canonical); ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// FamiliarName returns the familiar name string
|
||||
// for the given named, familiarizing if needed.
|
||||
func FamiliarName(ref Named) string {
|
||||
if nn, ok := ref.(normalizedNamed); ok {
|
||||
return nn.Familiar().Name()
|
||||
}
|
||||
return ref.Name()
|
||||
}
|
||||
|
||||
// FamiliarString returns the familiar string representation
|
||||
// for the given reference, familiarizing if needed.
|
||||
func FamiliarString(ref Reference) string {
|
||||
if nn, ok := ref.(normalizedNamed); ok {
|
||||
return nn.Familiar().String()
|
||||
}
|
||||
return ref.String()
|
||||
}
|
||||
|
||||
// FamiliarMatch reports whether ref matches the specified pattern.
|
||||
// See https://godoc.org/path#Match for supported patterns.
|
||||
func FamiliarMatch(pattern string, ref Reference) (bool, error) {
|
||||
matched, err := path.Match(pattern, FamiliarString(ref))
|
||||
if namedRef, isNamed := ref.(Named); isNamed && !matched {
|
||||
matched, _ = path.Match(pattern, FamiliarName(namedRef))
|
||||
}
|
||||
return matched, err
|
||||
}
|
305
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
305
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
@ -40,126 +40,278 @@ type dockerAuthorizer struct {
|
||||
credentials func(string) (string, string, error)
|
||||
|
||||
client *http.Client
|
||||
header http.Header
|
||||
mu sync.Mutex
|
||||
|
||||
auth map[string]string
|
||||
// indexed by host name
|
||||
handlers map[string]*authHandler
|
||||
}
|
||||
|
||||
// NewAuthorizer creates a Docker authorizer using the provided function to
|
||||
// get credentials for the token server or basic auth.
|
||||
// Deprecated: Use NewDockerAuthorizer
|
||||
func NewAuthorizer(client *http.Client, f func(string) (string, string, error)) Authorizer {
|
||||
if client == nil {
|
||||
client = http.DefaultClient
|
||||
}
|
||||
return &dockerAuthorizer{
|
||||
credentials: f,
|
||||
client: client,
|
||||
auth: map[string]string{},
|
||||
return NewDockerAuthorizer(WithAuthClient(client), WithAuthCreds(f))
|
||||
}
|
||||
|
||||
type authorizerConfig struct {
|
||||
credentials func(string) (string, string, error)
|
||||
client *http.Client
|
||||
header http.Header
|
||||
}
|
||||
|
||||
// AuthorizerOpt configures an authorizer
|
||||
type AuthorizerOpt func(*authorizerConfig)
|
||||
|
||||
// WithAuthClient provides the HTTP client for the authorizer
|
||||
func WithAuthClient(client *http.Client) AuthorizerOpt {
|
||||
return func(opt *authorizerConfig) {
|
||||
opt.client = client
|
||||
}
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
|
||||
// TODO: Lookup matching challenge and scope rather than just host
|
||||
if auth := a.getAuth(req.URL.Host); auth != "" {
|
||||
req.Header.Set("Authorization", auth)
|
||||
// WithAuthCreds provides a credential function to the authorizer
|
||||
func WithAuthCreds(creds func(string) (string, string, error)) AuthorizerOpt {
|
||||
return func(opt *authorizerConfig) {
|
||||
opt.credentials = creds
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuthHeader provides HTTP headers for authorization
|
||||
func WithAuthHeader(hdr http.Header) AuthorizerOpt {
|
||||
return func(opt *authorizerConfig) {
|
||||
opt.header = hdr
|
||||
}
|
||||
}
|
||||
|
||||
// NewDockerAuthorizer creates an authorizer using Docker's registry
|
||||
// authentication spec.
|
||||
// See https://docs.docker.com/registry/spec/auth/
|
||||
func NewDockerAuthorizer(opts ...AuthorizerOpt) Authorizer {
|
||||
var ao authorizerConfig
|
||||
for _, opt := range opts {
|
||||
opt(&ao)
|
||||
}
|
||||
|
||||
if ao.client == nil {
|
||||
ao.client = http.DefaultClient
|
||||
}
|
||||
|
||||
return &dockerAuthorizer{
|
||||
credentials: ao.credentials,
|
||||
client: ao.client,
|
||||
header: ao.header,
|
||||
handlers: make(map[string]*authHandler),
|
||||
}
|
||||
}
|
||||
|
||||
// Authorize handles auth request.
|
||||
func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
|
||||
// skip if there is no auth handler
|
||||
ah := a.getAuthHandler(req.URL.Host)
|
||||
if ah == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
auth, err := ah.authorize(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", auth)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) getAuthHandler(host string) *authHandler {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
return a.handlers[host]
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {
|
||||
last := responses[len(responses)-1]
|
||||
host := last.Request.URL.Host
|
||||
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
for _, c := range parseAuthHeader(last.Header) {
|
||||
if c.scheme == bearerAuth {
|
||||
if err := invalidAuthorization(c, responses); err != nil {
|
||||
// TODO: Clear token
|
||||
a.setAuth(host, "")
|
||||
delete(a.handlers, host)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(dmcg): Store challenge, not token
|
||||
// Move token fetching to authorize
|
||||
return a.setTokenAuth(ctx, host, c.parameters)
|
||||
// reuse existing handler
|
||||
//
|
||||
// assume that one registry will return the common
|
||||
// challenge information, including realm and service.
|
||||
// and the resource scope is only different part
|
||||
// which can be provided by each request.
|
||||
if _, ok := a.handlers[host]; ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
common, err := a.generateTokenOptions(ctx, host, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
|
||||
return nil
|
||||
} else if c.scheme == basicAuth && a.credentials != nil {
|
||||
// TODO: Resolve credentials on authorize
|
||||
username, secret, err := a.credentials(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if username != "" && secret != "" {
|
||||
auth := username + ":" + secret
|
||||
a.setAuth(host, fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(auth))))
|
||||
common := tokenOptions{
|
||||
username: username,
|
||||
secret: secret,
|
||||
}
|
||||
|
||||
a.handlers[host] = newAuthHandler(a.client, a.header, c.scheme, common)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) getAuth(host string) string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
return a.auth[host]
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) setAuth(host string, auth string) bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
changed := a.auth[host] != auth
|
||||
a.auth[host] = auth
|
||||
|
||||
return changed
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) setTokenAuth(ctx context.Context, host string, params map[string]string) error {
|
||||
realm, ok := params["realm"]
|
||||
func (a *dockerAuthorizer) generateTokenOptions(ctx context.Context, host string, c challenge) (tokenOptions, error) {
|
||||
realm, ok := c.parameters["realm"]
|
||||
if !ok {
|
||||
return errors.New("no realm specified for token auth challenge")
|
||||
return tokenOptions{}, errors.New("no realm specified for token auth challenge")
|
||||
}
|
||||
|
||||
realmURL, err := url.Parse(realm)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid token auth challenge realm")
|
||||
return tokenOptions{}, errors.Wrap(err, "invalid token auth challenge realm")
|
||||
}
|
||||
|
||||
to := tokenOptions{
|
||||
realm: realmURL.String(),
|
||||
service: params["service"],
|
||||
service: c.parameters["service"],
|
||||
}
|
||||
|
||||
to.scopes = getTokenScopes(ctx, params)
|
||||
if len(to.scopes) == 0 {
|
||||
return errors.Errorf("no scope specified for token auth challenge")
|
||||
scope, ok := c.parameters["scope"]
|
||||
if !ok {
|
||||
return tokenOptions{}, errors.Errorf("no scope specified for token auth challenge")
|
||||
}
|
||||
to.scopes = append(to.scopes, scope)
|
||||
|
||||
if a.credentials != nil {
|
||||
to.username, to.secret, err = a.credentials(host)
|
||||
if err != nil {
|
||||
return err
|
||||
return tokenOptions{}, err
|
||||
}
|
||||
}
|
||||
return to, nil
|
||||
}
|
||||
|
||||
var token string
|
||||
// authResult is used to control limit rate.
|
||||
type authResult struct {
|
||||
sync.WaitGroup
|
||||
token string
|
||||
err error
|
||||
}
|
||||
|
||||
// authHandler is used to handle auth request per registry server.
|
||||
type authHandler struct {
|
||||
sync.Mutex
|
||||
|
||||
header http.Header
|
||||
|
||||
client *http.Client
|
||||
|
||||
// only support basic and bearer schemes
|
||||
scheme authenticationScheme
|
||||
|
||||
// common contains common challenge answer
|
||||
common tokenOptions
|
||||
|
||||
// scopedTokens caches token indexed by scopes, which used in
|
||||
// bearer auth case
|
||||
scopedTokens map[string]*authResult
|
||||
}
|
||||
|
||||
func newAuthHandler(client *http.Client, hdr http.Header, scheme authenticationScheme, opts tokenOptions) *authHandler {
|
||||
return &authHandler{
|
||||
header: hdr,
|
||||
client: client,
|
||||
scheme: scheme,
|
||||
common: opts,
|
||||
scopedTokens: map[string]*authResult{},
|
||||
}
|
||||
}
|
||||
|
||||
func (ah *authHandler) authorize(ctx context.Context) (string, error) {
|
||||
switch ah.scheme {
|
||||
case basicAuth:
|
||||
return ah.doBasicAuth(ctx)
|
||||
case bearerAuth:
|
||||
return ah.doBearerAuth(ctx)
|
||||
default:
|
||||
return "", errors.Wrap(errdefs.ErrNotImplemented, "failed to find supported auth scheme")
|
||||
}
|
||||
}
|
||||
|
||||
func (ah *authHandler) doBasicAuth(ctx context.Context) (string, error) {
|
||||
username, secret := ah.common.username, ah.common.secret
|
||||
|
||||
if username == "" || secret == "" {
|
||||
return "", fmt.Errorf("failed to handle basic auth because missing username or secret")
|
||||
}
|
||||
|
||||
auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + secret))
|
||||
return fmt.Sprintf("Basic %s", auth), nil
|
||||
}
|
||||
|
||||
func (ah *authHandler) doBearerAuth(ctx context.Context) (string, error) {
|
||||
// copy common tokenOptions
|
||||
to := ah.common
|
||||
|
||||
to.scopes = getTokenScopes(ctx, to.scopes)
|
||||
if len(to.scopes) == 0 {
|
||||
return "", errors.Errorf("no scope specified for token auth challenge")
|
||||
}
|
||||
|
||||
// Docs: https://docs.docker.com/registry/spec/auth/scope
|
||||
scoped := strings.Join(to.scopes, " ")
|
||||
|
||||
ah.Lock()
|
||||
if r, exist := ah.scopedTokens[scoped]; exist {
|
||||
ah.Unlock()
|
||||
r.Wait()
|
||||
return r.token, r.err
|
||||
}
|
||||
|
||||
// only one fetch token job
|
||||
r := new(authResult)
|
||||
r.Add(1)
|
||||
ah.scopedTokens[scoped] = r
|
||||
ah.Unlock()
|
||||
|
||||
// fetch token for the resource scope
|
||||
var (
|
||||
token string
|
||||
err error
|
||||
)
|
||||
if to.secret != "" {
|
||||
// Credential information is provided, use oauth POST endpoint
|
||||
token, err = a.fetchTokenWithOAuth(ctx, to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to fetch oauth token")
|
||||
}
|
||||
// credential information is provided, use oauth POST endpoint
|
||||
token, err = ah.fetchTokenWithOAuth(ctx, to)
|
||||
err = errors.Wrap(err, "failed to fetch oauth token")
|
||||
} else {
|
||||
// Do request anonymously
|
||||
token, err = a.fetchToken(ctx, to)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to fetch anonymous token")
|
||||
}
|
||||
// do request anonymously
|
||||
token, err = ah.fetchToken(ctx, to)
|
||||
err = errors.Wrap(err, "failed to fetch anonymous token")
|
||||
}
|
||||
a.setAuth(host, fmt.Sprintf("Bearer %s", token))
|
||||
token = fmt.Sprintf("Bearer %s", token)
|
||||
|
||||
return nil
|
||||
r.token, r.err = token, err
|
||||
r.Done()
|
||||
return r.token, r.err
|
||||
}
|
||||
|
||||
type tokenOptions struct {
|
||||
@ -178,7 +330,7 @@ type postTokenResponse struct {
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
|
||||
func (ah *authHandler) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
|
||||
form := url.Values{}
|
||||
form.Set("scope", strings.Join(to.scopes, " "))
|
||||
form.Set("service", to.service)
|
||||
@ -194,11 +346,18 @@ func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOpti
|
||||
form.Set("password", to.secret)
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.Post(
|
||||
ctx, a.client, to.realm,
|
||||
"application/x-www-form-urlencoded; charset=utf-8",
|
||||
strings.NewReader(form.Encode()),
|
||||
)
|
||||
req, err := http.NewRequest("POST", to.realm, strings.NewReader(form.Encode()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
|
||||
if ah.header != nil {
|
||||
for k, v := range ah.header {
|
||||
req.Header[k] = append(req.Header[k], v...)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, ah.client, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -208,7 +367,7 @@ func (a *dockerAuthorizer) fetchTokenWithOAuth(ctx context.Context, to tokenOpti
|
||||
// As of September 2017, GCR is known to return 404.
|
||||
// As of February 2018, JFrog Artifactory is known to return 401.
|
||||
if (resp.StatusCode == 405 && to.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
|
||||
return a.fetchToken(ctx, to)
|
||||
return ah.fetchToken(ctx, to)
|
||||
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
||||
log.G(ctx).WithFields(logrus.Fields{
|
||||
@ -237,13 +396,19 @@ type getTokenResponse struct {
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
// getToken fetches a token using a GET request
|
||||
func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
||||
// fetchToken fetches a token using a GET request
|
||||
func (ah *authHandler) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
||||
req, err := http.NewRequest("GET", to.realm, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if ah.header != nil {
|
||||
for k, v := range ah.header {
|
||||
req.Header[k] = append(req.Header[k], v...)
|
||||
}
|
||||
}
|
||||
|
||||
reqParams := req.URL.Query()
|
||||
|
||||
if to.service != "" {
|
||||
@ -260,7 +425,7 @@ func (a *dockerAuthorizer) fetchToken(ctx context.Context, to tokenOptions) (str
|
||||
|
||||
req.URL.RawQuery = reqParams.Encode()
|
||||
|
||||
resp, err := ctxhttp.Do(ctx, a.client, req)
|
||||
resp, err := ctxhttp.Do(ctx, ah.client, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
283
vendor/github.com/containerd/containerd/remotes/docker/errcode.go
generated
vendored
Normal file
283
vendor/github.com/containerd/containerd/remotes/docker/errcode.go
generated
vendored
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
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 docker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ErrorCoder is the base interface for ErrorCode and Error allowing
|
||||
// users of each to just call ErrorCode to get the real ID of each
|
||||
type ErrorCoder interface {
|
||||
ErrorCode() ErrorCode
|
||||
}
|
||||
|
||||
// ErrorCode represents the error type. The errors are serialized via strings
|
||||
// and the integer format may change and should *never* be exported.
|
||||
type ErrorCode int
|
||||
|
||||
var _ error = ErrorCode(0)
|
||||
|
||||
// ErrorCode just returns itself
|
||||
func (ec ErrorCode) ErrorCode() ErrorCode {
|
||||
return ec
|
||||
}
|
||||
|
||||
// Error returns the ID/Value
|
||||
func (ec ErrorCode) Error() string {
|
||||
// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.
|
||||
return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1))
|
||||
}
|
||||
|
||||
// Descriptor returns the descriptor for the error code.
|
||||
func (ec ErrorCode) Descriptor() ErrorDescriptor {
|
||||
d, ok := errorCodeToDescriptors[ec]
|
||||
|
||||
if !ok {
|
||||
return ErrorCodeUnknown.Descriptor()
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// String returns the canonical identifier for this error code.
|
||||
func (ec ErrorCode) String() string {
|
||||
return ec.Descriptor().Value
|
||||
}
|
||||
|
||||
// Message returned the human-readable error message for this error code.
|
||||
func (ec ErrorCode) Message() string {
|
||||
return ec.Descriptor().Message
|
||||
}
|
||||
|
||||
// MarshalText encodes the receiver into UTF-8-encoded text and returns the
|
||||
// result.
|
||||
func (ec ErrorCode) MarshalText() (text []byte, err error) {
|
||||
return []byte(ec.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText decodes the form generated by MarshalText.
|
||||
func (ec *ErrorCode) UnmarshalText(text []byte) error {
|
||||
desc, ok := idToDescriptors[string(text)]
|
||||
|
||||
if !ok {
|
||||
desc = ErrorCodeUnknown.Descriptor()
|
||||
}
|
||||
|
||||
*ec = desc.Code
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithMessage creates a new Error struct based on the passed-in info and
|
||||
// overrides the Message property.
|
||||
func (ec ErrorCode) WithMessage(message string) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
// WithDetail creates a new Error struct based on the passed-in info and
|
||||
// set the Detail property appropriately
|
||||
func (ec ErrorCode) WithDetail(detail interface{}) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: ec.Message(),
|
||||
}.WithDetail(detail)
|
||||
}
|
||||
|
||||
// WithArgs creates a new Error struct and sets the Args slice
|
||||
func (ec ErrorCode) WithArgs(args ...interface{}) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: ec.Message(),
|
||||
}.WithArgs(args...)
|
||||
}
|
||||
|
||||
// Error provides a wrapper around ErrorCode with extra Details provided.
|
||||
type Error struct {
|
||||
Code ErrorCode `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Detail interface{} `json:"detail,omitempty"`
|
||||
|
||||
// TODO(duglin): See if we need an "args" property so we can do the
|
||||
// variable substitution right before showing the message to the user
|
||||
}
|
||||
|
||||
var _ error = Error{}
|
||||
|
||||
// ErrorCode returns the ID/Value of this Error
|
||||
func (e Error) ErrorCode() ErrorCode {
|
||||
return e.Code
|
||||
}
|
||||
|
||||
// Error returns a human readable representation of the error.
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code.Error(), e.Message)
|
||||
}
|
||||
|
||||
// WithDetail will return a new Error, based on the current one, but with
|
||||
// some Detail info added
|
||||
func (e Error) WithDetail(detail interface{}) Error {
|
||||
return Error{
|
||||
Code: e.Code,
|
||||
Message: e.Message,
|
||||
Detail: detail,
|
||||
}
|
||||
}
|
||||
|
||||
// WithArgs uses the passed-in list of interface{} as the substitution
|
||||
// variables in the Error's Message string, but returns a new Error
|
||||
func (e Error) WithArgs(args ...interface{}) Error {
|
||||
return Error{
|
||||
Code: e.Code,
|
||||
Message: fmt.Sprintf(e.Code.Message(), args...),
|
||||
Detail: e.Detail,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorDescriptor provides relevant information about a given error code.
|
||||
type ErrorDescriptor struct {
|
||||
// Code is the error code that this descriptor describes.
|
||||
Code ErrorCode
|
||||
|
||||
// Value provides a unique, string key, often captilized with
|
||||
// underscores, to identify the error code. This value is used as the
|
||||
// keyed value when serializing api errors.
|
||||
Value string
|
||||
|
||||
// Message is a short, human readable decription of the error condition
|
||||
// included in API responses.
|
||||
Message string
|
||||
|
||||
// Description provides a complete account of the errors purpose, suitable
|
||||
// for use in documentation.
|
||||
Description string
|
||||
|
||||
// HTTPStatusCode provides the http status code that is associated with
|
||||
// this error condition.
|
||||
HTTPStatusCode int
|
||||
}
|
||||
|
||||
// ParseErrorCode returns the value by the string error code.
|
||||
// `ErrorCodeUnknown` will be returned if the error is not known.
|
||||
func ParseErrorCode(value string) ErrorCode {
|
||||
ed, ok := idToDescriptors[value]
|
||||
if ok {
|
||||
return ed.Code
|
||||
}
|
||||
|
||||
return ErrorCodeUnknown
|
||||
}
|
||||
|
||||
// Errors provides the envelope for multiple errors and a few sugar methods
|
||||
// for use within the application.
|
||||
type Errors []error
|
||||
|
||||
var _ error = Errors{}
|
||||
|
||||
func (errs Errors) Error() string {
|
||||
switch len(errs) {
|
||||
case 0:
|
||||
return "<nil>"
|
||||
case 1:
|
||||
return errs[0].Error()
|
||||
default:
|
||||
msg := "errors:\n"
|
||||
for _, err := range errs {
|
||||
msg += err.Error() + "\n"
|
||||
}
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the current number of errors.
|
||||
func (errs Errors) Len() int {
|
||||
return len(errs)
|
||||
}
|
||||
|
||||
// MarshalJSON converts slice of error, ErrorCode or Error into a
|
||||
// slice of Error - then serializes
|
||||
func (errs Errors) MarshalJSON() ([]byte, error) {
|
||||
var tmpErrs struct {
|
||||
Errors []Error `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
for _, daErr := range errs {
|
||||
var err Error
|
||||
|
||||
switch daErr := daErr.(type) {
|
||||
case ErrorCode:
|
||||
err = daErr.WithDetail(nil)
|
||||
case Error:
|
||||
err = daErr
|
||||
default:
|
||||
err = ErrorCodeUnknown.WithDetail(daErr)
|
||||
|
||||
}
|
||||
|
||||
// If the Error struct was setup and they forgot to set the
|
||||
// Message field (meaning its "") then grab it from the ErrCode
|
||||
msg := err.Message
|
||||
if msg == "" {
|
||||
msg = err.Code.Message()
|
||||
}
|
||||
|
||||
tmpErrs.Errors = append(tmpErrs.Errors, Error{
|
||||
Code: err.Code,
|
||||
Message: msg,
|
||||
Detail: err.Detail,
|
||||
})
|
||||
}
|
||||
|
||||
return json.Marshal(tmpErrs)
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserializes []Error and then converts it into slice of
|
||||
// Error or ErrorCode
|
||||
func (errs *Errors) UnmarshalJSON(data []byte) error {
|
||||
var tmpErrs struct {
|
||||
Errors []Error
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &tmpErrs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newErrs Errors
|
||||
for _, daErr := range tmpErrs.Errors {
|
||||
// If Message is empty or exactly matches the Code's message string
|
||||
// then just use the Code, no need for a full Error struct
|
||||
if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) {
|
||||
// Error's w/o details get converted to ErrorCode
|
||||
newErrs = append(newErrs, daErr.Code)
|
||||
} else {
|
||||
// Error's w/ details are untouched
|
||||
newErrs = append(newErrs, Error{
|
||||
Code: daErr.Code,
|
||||
Message: daErr.Message,
|
||||
Detail: daErr.Detail,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
*errs = newErrs
|
||||
return nil
|
||||
}
|
154
vendor/github.com/containerd/containerd/remotes/docker/errdesc.go
generated
vendored
Normal file
154
vendor/github.com/containerd/containerd/remotes/docker/errdesc.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
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 docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}
|
||||
idToDescriptors = map[string]ErrorDescriptor{}
|
||||
groupToDescriptors = map[string][]ErrorDescriptor{}
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorCodeUnknown is a generic error that can be used as a last
|
||||
// resort if there is no situation-specific error message that can be used
|
||||
ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNKNOWN",
|
||||
Message: "unknown error",
|
||||
Description: `Generic error returned when the error does not have an
|
||||
API classification.`,
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeUnsupported is returned when an operation is not supported.
|
||||
ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNSUPPORTED",
|
||||
Message: "The operation is unsupported.",
|
||||
Description: `The operation was unsupported due to a missing
|
||||
implementation or invalid set of parameters.`,
|
||||
HTTPStatusCode: http.StatusMethodNotAllowed,
|
||||
})
|
||||
|
||||
// ErrorCodeUnauthorized is returned if a request requires
|
||||
// authentication.
|
||||
ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNAUTHORIZED",
|
||||
Message: "authentication required",
|
||||
Description: `The access controller was unable to authenticate
|
||||
the client. Often this will be accompanied by a
|
||||
Www-Authenticate HTTP response header indicating how to
|
||||
authenticate.`,
|
||||
HTTPStatusCode: http.StatusUnauthorized,
|
||||
})
|
||||
|
||||
// ErrorCodeDenied is returned if a client does not have sufficient
|
||||
// permission to perform an action.
|
||||
ErrorCodeDenied = Register("errcode", ErrorDescriptor{
|
||||
Value: "DENIED",
|
||||
Message: "requested access to the resource is denied",
|
||||
Description: `The access controller denied access for the
|
||||
operation on a resource.`,
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
})
|
||||
|
||||
// ErrorCodeUnavailable provides a common error to report unavailability
|
||||
// of a service or endpoint.
|
||||
ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNAVAILABLE",
|
||||
Message: "service unavailable",
|
||||
Description: "Returned when a service is not available",
|
||||
HTTPStatusCode: http.StatusServiceUnavailable,
|
||||
})
|
||||
|
||||
// ErrorCodeTooManyRequests is returned if a client attempts too many
|
||||
// times to contact a service endpoint.
|
||||
ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{
|
||||
Value: "TOOMANYREQUESTS",
|
||||
Message: "too many requests",
|
||||
Description: `Returned when a client attempts to contact a
|
||||
service too many times`,
|
||||
HTTPStatusCode: http.StatusTooManyRequests,
|
||||
})
|
||||
)
|
||||
|
||||
var nextCode = 1000
|
||||
var registerLock sync.Mutex
|
||||
|
||||
// Register will make the passed-in error known to the environment and
|
||||
// return a new ErrorCode
|
||||
func Register(group string, descriptor ErrorDescriptor) ErrorCode {
|
||||
registerLock.Lock()
|
||||
defer registerLock.Unlock()
|
||||
|
||||
descriptor.Code = ErrorCode(nextCode)
|
||||
|
||||
if _, ok := idToDescriptors[descriptor.Value]; ok {
|
||||
panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value))
|
||||
}
|
||||
if _, ok := errorCodeToDescriptors[descriptor.Code]; ok {
|
||||
panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code))
|
||||
}
|
||||
|
||||
groupToDescriptors[group] = append(groupToDescriptors[group], descriptor)
|
||||
errorCodeToDescriptors[descriptor.Code] = descriptor
|
||||
idToDescriptors[descriptor.Value] = descriptor
|
||||
|
||||
nextCode++
|
||||
return descriptor.Code
|
||||
}
|
||||
|
||||
type byValue []ErrorDescriptor
|
||||
|
||||
func (a byValue) Len() int { return len(a) }
|
||||
func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value }
|
||||
|
||||
// GetGroupNames returns the list of Error group names that are registered
|
||||
func GetGroupNames() []string {
|
||||
keys := []string{}
|
||||
|
||||
for k := range groupToDescriptors {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// GetErrorCodeGroup returns the named group of error descriptors
|
||||
func GetErrorCodeGroup(name string) []ErrorDescriptor {
|
||||
desc := groupToDescriptors[name]
|
||||
sort.Sort(byValue(desc))
|
||||
return desc
|
||||
}
|
||||
|
||||
// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are
|
||||
// registered, irrespective of what group they're in
|
||||
func GetErrorAllDescriptors() []ErrorDescriptor {
|
||||
result := []ErrorDescriptor{}
|
||||
|
||||
for _, group := range GetGroupNames() {
|
||||
result = append(result, GetErrorCodeGroup(group)...)
|
||||
}
|
||||
sort.Sort(byValue(result))
|
||||
return result
|
||||
}
|
134
vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
generated
vendored
134
vendor/github.com/containerd/containerd/remotes/docker/fetcher.go
generated
vendored
@ -23,16 +23,14 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type dockerFetcher struct {
|
||||
@ -40,26 +38,46 @@ type dockerFetcher struct {
|
||||
}
|
||||
|
||||
func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
|
||||
logrus.Fields{
|
||||
"base": r.base.String(),
|
||||
"digest": desc.Digest,
|
||||
},
|
||||
))
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", desc.Digest))
|
||||
|
||||
urls, err := r.getV2URLPaths(ctx, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
hosts := r.filterHosts(HostCapabilityPull)
|
||||
if len(hosts) == 0 {
|
||||
return nil, errors.Wrap(errdefs.ErrNotFound, "no pull hosts")
|
||||
}
|
||||
|
||||
ctx, err = contextWithRepositoryScope(ctx, r.refspec, false)
|
||||
ctx, err := contextWithRepositoryScope(ctx, r.refspec, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) {
|
||||
for _, u := range urls {
|
||||
rc, err := r.open(ctx, u, desc.MediaType, offset)
|
||||
// firstly try fetch via external urls
|
||||
for _, us := range desc.URLs {
|
||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", us))
|
||||
|
||||
u, err := url.Parse(us)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Debug("failed to parse")
|
||||
continue
|
||||
}
|
||||
log.G(ctx).Debug("trying alternative url")
|
||||
|
||||
// Try this first, parse it
|
||||
host := RegistryHost{
|
||||
Client: http.DefaultClient,
|
||||
Host: u.Host,
|
||||
Scheme: u.Scheme,
|
||||
Path: u.Path,
|
||||
Capabilities: HostCapabilityPull,
|
||||
}
|
||||
req := r.request(host, http.MethodGet)
|
||||
// Strip namespace from base
|
||||
req.path = u.Path
|
||||
if u.RawQuery != "" {
|
||||
req.path = req.path + "?" + u.RawQuery
|
||||
}
|
||||
|
||||
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue // try one of the other urls.
|
||||
@ -71,6 +89,44 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
// Try manifests endpoints for manifests types
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,
|
||||
images.MediaTypeDockerSchema1Manifest,
|
||||
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
||||
|
||||
for _, host := range r.hosts {
|
||||
req := r.request(host, http.MethodGet, "manifests", desc.Digest.String())
|
||||
|
||||
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue // try another host
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Finally use blobs endpoints
|
||||
for _, host := range r.hosts {
|
||||
req := r.request(host, http.MethodGet, "blobs", desc.Digest.String())
|
||||
|
||||
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
continue // try another host
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rc, nil
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound,
|
||||
"could not fetch content descriptor %v (%v) from remote",
|
||||
desc.Digest, desc.MediaType)
|
||||
@ -78,22 +134,17 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||
})
|
||||
}
|
||||
|
||||
func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int64) (io.ReadCloser, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", strings.Join([]string{mediatype, `*`}, ", "))
|
||||
func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64) (io.ReadCloser, error) {
|
||||
req.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", "))
|
||||
|
||||
if offset > 0 {
|
||||
// Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints
|
||||
// will return the header without supporting the range. The content
|
||||
// range must always be checked.
|
||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
|
||||
req.header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
|
||||
}
|
||||
|
||||
resp, err := r.doRequestWithRetries(ctx, req, nil)
|
||||
resp, err := req.doWithRetries(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -106,13 +157,13 @@ func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusNotFound {
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "content at %v not found", u)
|
||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "content at %v not found", req.String())
|
||||
}
|
||||
var registryErr errcode.Errors
|
||||
var registryErr Errors
|
||||
if err := json.NewDecoder(resp.Body).Decode(®istryErr); err != nil || registryErr.Len() < 1 {
|
||||
return nil, errors.Errorf("unexpected status code %v: %v", u, resp.Status)
|
||||
return nil, errors.Errorf("unexpected status code %v: %v", req.String(), resp.Status)
|
||||
}
|
||||
return nil, errors.Errorf("unexpected status code %v: %s - Server message: %s", u, resp.Status, registryErr.Error())
|
||||
return nil, errors.Errorf("unexpected status code %v: %s - Server message: %s", req.String(), resp.Status, registryErr.Error())
|
||||
}
|
||||
if offset > 0 {
|
||||
cr := resp.Header.Get("content-range")
|
||||
@ -141,30 +192,3 @@ func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int
|
||||
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
// getV2URLPaths generates the candidate urls paths for the object based on the
|
||||
// set of hints and the provided object id. URLs are returned in the order of
|
||||
// most to least likely succeed.
|
||||
func (r *dockerFetcher) getV2URLPaths(ctx context.Context, desc ocispec.Descriptor) ([]string, error) {
|
||||
var urls []string
|
||||
|
||||
if len(desc.URLs) > 0 {
|
||||
// handle fetch via external urls.
|
||||
for _, u := range desc.URLs {
|
||||
log.G(ctx).WithField("url", u).Debug("adding alternative url")
|
||||
urls = append(urls, u)
|
||||
}
|
||||
}
|
||||
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,
|
||||
images.MediaTypeDockerSchema1Manifest,
|
||||
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
||||
urls = append(urls, r.url(path.Join("manifests", desc.Digest.String())))
|
||||
}
|
||||
|
||||
// always fallback to attempting to get the object out of the blobs store.
|
||||
urls = append(urls, r.url(path.Join("blobs", desc.Digest.String())))
|
||||
|
||||
return urls, nil
|
||||
}
|
||||
|
42
vendor/github.com/containerd/containerd/remotes/docker/handler.go
generated
vendored
42
vendor/github.com/containerd/containerd/remotes/docker/handler.go
generated
vendored
@ -110,3 +110,45 @@ func appendDistributionSourceLabel(originLabel, repo string) string {
|
||||
func distributionSourceLabelKey(source string) string {
|
||||
return fmt.Sprintf("%s.%s", labelDistributionSource, source)
|
||||
}
|
||||
|
||||
// selectRepositoryMountCandidate will select the repo which has longest
|
||||
// common prefix components as the candidate.
|
||||
func selectRepositoryMountCandidate(refspec reference.Spec, sources map[string]string) string {
|
||||
u, err := url.Parse("dummy://" + refspec.Locator)
|
||||
if err != nil {
|
||||
// NOTE: basically, it won't be error here
|
||||
return ""
|
||||
}
|
||||
|
||||
source, target := u.Hostname(), strings.TrimPrefix(u.Path, "/")
|
||||
repoLabel, ok := sources[distributionSourceLabelKey(source)]
|
||||
if !ok || repoLabel == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
n, match := 0, ""
|
||||
components := strings.Split(target, "/")
|
||||
for _, repo := range strings.Split(repoLabel, ",") {
|
||||
// the target repo is not a candidate
|
||||
if repo == target {
|
||||
continue
|
||||
}
|
||||
|
||||
if l := commonPrefixComponents(components, repo); l >= n {
|
||||
n, match = l, repo
|
||||
}
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
func commonPrefixComponents(components []string, target string) int {
|
||||
targetComponents := strings.Split(target, "/")
|
||||
|
||||
i := 0
|
||||
for ; i < len(components) && i < len(targetComponents); i++ {
|
||||
if components[i] != targetComponents[i] {
|
||||
break
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
191
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
191
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
@ -21,7 +21,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -37,7 +37,7 @@ import (
|
||||
|
||||
type dockerPusher struct {
|
||||
*dockerBase
|
||||
tag string
|
||||
object string
|
||||
|
||||
// TODO: namespace tracker
|
||||
tracker StatusTracker
|
||||
@ -59,31 +59,32 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||
return nil, errors.Wrap(err, "failed to get status")
|
||||
}
|
||||
|
||||
hosts := p.filterHosts(HostCapabilityPush)
|
||||
if len(hosts) == 0 {
|
||||
return nil, errors.Wrap(errdefs.ErrNotFound, "no push hosts")
|
||||
}
|
||||
|
||||
var (
|
||||
isManifest bool
|
||||
existCheck string
|
||||
existCheck []string
|
||||
host = hosts[0]
|
||||
)
|
||||
|
||||
switch desc.MediaType {
|
||||
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,
|
||||
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
||||
isManifest = true
|
||||
if p.tag == "" {
|
||||
existCheck = path.Join("manifests", desc.Digest.String())
|
||||
} else {
|
||||
existCheck = path.Join("manifests", p.tag)
|
||||
}
|
||||
existCheck = getManifestPath(p.object, desc.Digest)
|
||||
default:
|
||||
existCheck = path.Join("blobs", desc.Digest.String())
|
||||
existCheck = []string{"blobs", desc.Digest.String()}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodHead, p.url(existCheck), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := p.request(host, http.MethodHead, existCheck...)
|
||||
req.header.Set("Accept", strings.Join([]string{desc.MediaType, `*/*`}, ", "))
|
||||
|
||||
req.Header.Set("Accept", strings.Join([]string{desc.MediaType, `*`}, ", "))
|
||||
resp, err := p.doRequestWithRetries(ctx, req, nil)
|
||||
log.G(ctx).WithField("url", req.String()).Debugf("checking and pushing to")
|
||||
|
||||
resp, err := req.doWithRetries(ctx, nil)
|
||||
if err != nil {
|
||||
if errors.Cause(err) != ErrInvalidAuthorization {
|
||||
return nil, err
|
||||
@ -92,7 +93,7 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||
} else {
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
var exists bool
|
||||
if isManifest && p.tag != "" {
|
||||
if isManifest && existCheck[1] != desc.Digest.String() {
|
||||
dgstHeader := digest.Digest(resp.Header.Get("Docker-Content-Digest"))
|
||||
if dgstHeader == desc.Digest {
|
||||
exists = true
|
||||
@ -116,67 +117,94 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Lookup related objects for cross repository push
|
||||
|
||||
if isManifest {
|
||||
var putPath string
|
||||
if p.tag != "" {
|
||||
putPath = path.Join("manifests", p.tag)
|
||||
} else {
|
||||
putPath = path.Join("manifests", desc.Digest.String())
|
||||
}
|
||||
|
||||
req, err = http.NewRequest(http.MethodPut, p.url(putPath), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Content-Type", desc.MediaType)
|
||||
putPath := getManifestPath(p.object, desc.Digest)
|
||||
req = p.request(host, http.MethodPut, putPath...)
|
||||
req.header.Add("Content-Type", desc.MediaType)
|
||||
} else {
|
||||
// TODO: Do monolithic upload if size is small
|
||||
|
||||
// Start upload request
|
||||
req, err = http.NewRequest(http.MethodPost, p.url("blobs", "uploads")+"/", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
req = p.request(host, http.MethodPost, "blobs", "uploads/")
|
||||
|
||||
var resp *http.Response
|
||||
if fromRepo := selectRepositoryMountCandidate(p.refspec, desc.Annotations); fromRepo != "" {
|
||||
preq := requestWithMountFrom(req, desc.Digest.String(), fromRepo)
|
||||
pctx := contextWithAppendPullRepositoryScope(ctx, fromRepo)
|
||||
|
||||
// NOTE: the fromRepo might be private repo and
|
||||
// auth service still can grant token without error.
|
||||
// but the post request will fail because of 401.
|
||||
//
|
||||
// for the private repo, we should remove mount-from
|
||||
// query and send the request again.
|
||||
resp, err = preq.do(pctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusUnauthorized {
|
||||
log.G(ctx).Debugf("failed to mount from repository %s", fromRepo)
|
||||
|
||||
resp.Body.Close()
|
||||
resp = nil
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := p.doRequestWithRetries(ctx, req, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if resp == nil {
|
||||
resp, err = req.doWithRetries(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK, http.StatusAccepted, http.StatusNoContent:
|
||||
case http.StatusCreated:
|
||||
p.tracker.SetStatus(ref, Status{
|
||||
Status: content.Status{
|
||||
Ref: ref,
|
||||
},
|
||||
})
|
||||
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
||||
default:
|
||||
// TODO: log error
|
||||
return nil, errors.Errorf("unexpected response: %s", resp.Status)
|
||||
}
|
||||
|
||||
location := resp.Header.Get("Location")
|
||||
var (
|
||||
location = resp.Header.Get("Location")
|
||||
lurl *url.URL
|
||||
lhost = host
|
||||
)
|
||||
// Support paths without host in location
|
||||
if strings.HasPrefix(location, "/") {
|
||||
// Support location string containing path and query
|
||||
qmIndex := strings.Index(location, "?")
|
||||
if qmIndex > 0 {
|
||||
u := p.base
|
||||
u.Path = location[:qmIndex]
|
||||
u.RawQuery = location[qmIndex+1:]
|
||||
location = u.String()
|
||||
} else {
|
||||
u := p.base
|
||||
u.Path = location
|
||||
location = u.String()
|
||||
lurl, err = url.Parse(lhost.Scheme + "://" + lhost.Host + location)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to parse location %v", location)
|
||||
}
|
||||
} else {
|
||||
if !strings.Contains(location, "://") {
|
||||
location = lhost.Scheme + "://" + location
|
||||
}
|
||||
lurl, err = url.Parse(location)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to parse location %v", location)
|
||||
}
|
||||
|
||||
if lurl.Host != lhost.Host || lhost.Scheme != lurl.Scheme {
|
||||
|
||||
lhost.Scheme = lurl.Scheme
|
||||
lhost.Host = lurl.Host
|
||||
log.G(ctx).WithField("host", lhost.Host).WithField("scheme", lhost.Scheme).Debug("upload changed destination")
|
||||
|
||||
// Strip authorizer if change to host or scheme
|
||||
lhost.Authorizer = nil
|
||||
}
|
||||
}
|
||||
|
||||
req, err = http.NewRequest(http.MethodPut, location, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := req.URL.Query()
|
||||
q := lurl.Query()
|
||||
q.Add("digest", desc.Digest.String())
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
req = p.request(lhost, http.MethodPut)
|
||||
req.path = lurl.Path + "?" + q.Encode()
|
||||
}
|
||||
p.tracker.SetStatus(ref, Status{
|
||||
Status: content.Status{
|
||||
@ -191,13 +219,22 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||
|
||||
pr, pw := io.Pipe()
|
||||
respC := make(chan *http.Response, 1)
|
||||
body := ioutil.NopCloser(pr)
|
||||
|
||||
req.Body = ioutil.NopCloser(pr)
|
||||
req.ContentLength = desc.Size
|
||||
req.body = func() (io.ReadCloser, error) {
|
||||
if body == nil {
|
||||
return nil, errors.New("cannot reuse body, request must be retried")
|
||||
}
|
||||
// Only use the body once since pipe cannot be seeked
|
||||
ob := body
|
||||
body = nil
|
||||
return ob, nil
|
||||
}
|
||||
req.size = desc.Size
|
||||
|
||||
go func() {
|
||||
defer close(respC)
|
||||
resp, err = p.doRequest(ctx, req)
|
||||
resp, err = req.do(ctx)
|
||||
if err != nil {
|
||||
pr.CloseWithError(err)
|
||||
return
|
||||
@ -223,6 +260,25 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getManifestPath(object string, dgst digest.Digest) []string {
|
||||
if i := strings.IndexByte(object, '@'); i >= 0 {
|
||||
if object[i+1:] != dgst.String() {
|
||||
// use digest, not tag
|
||||
object = ""
|
||||
} else {
|
||||
// strip @<digest> for registry path to make tag
|
||||
object = object[:i]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if object == "" {
|
||||
return []string{"manifests", dgst.String()}
|
||||
}
|
||||
|
||||
return []string{"manifests", object}
|
||||
}
|
||||
|
||||
type pushWriter struct {
|
||||
base *dockerBase
|
||||
ref string
|
||||
@ -296,7 +352,7 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
|
||||
}
|
||||
|
||||
if size > 0 && size != status.Offset {
|
||||
return errors.Errorf("unxpected size %d, expected %d", status.Offset, size)
|
||||
return errors.Errorf("unexpected size %d, expected %d", status.Offset, size)
|
||||
}
|
||||
|
||||
if expected == "" {
|
||||
@ -320,3 +376,16 @@ func (pw *pushWriter) Truncate(size int64) error {
|
||||
// TODO: always error on manifest
|
||||
return errors.New("cannot truncate remote upload")
|
||||
}
|
||||
|
||||
func requestWithMountFrom(req *request, mount, from string) *request {
|
||||
creq := *req
|
||||
|
||||
sep := "?"
|
||||
if strings.Contains(creq.path, sep) {
|
||||
sep = "&"
|
||||
}
|
||||
|
||||
creq.path = creq.path + sep + "mount=" + mount + "&from=" + from
|
||||
|
||||
return &creq
|
||||
}
|
||||
|
202
vendor/github.com/containerd/containerd/remotes/docker/registry.go
generated
vendored
Normal file
202
vendor/github.com/containerd/containerd/remotes/docker/registry.go
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
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 docker
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HostCapabilities represent the capabilities of the registry
|
||||
// host. This also represents the set of operations for which
|
||||
// the registry host may be trusted to perform.
|
||||
//
|
||||
// For example pushing is a capability which should only be
|
||||
// performed on an upstream source, not a mirror.
|
||||
// Resolving (the process of converting a name into a digest)
|
||||
// must be considered a trusted operation and only done by
|
||||
// a host which is trusted (or more preferably by secure process
|
||||
// which can prove the provenance of the mapping). A public
|
||||
// mirror should never be trusted to do a resolve action.
|
||||
//
|
||||
// | Registry Type | Pull | Resolve | Push |
|
||||
// |------------------|------|---------|------|
|
||||
// | Public Registry | yes | yes | yes |
|
||||
// | Private Registry | yes | yes | yes |
|
||||
// | Public Mirror | yes | no | no |
|
||||
// | Private Mirror | yes | yes | no |
|
||||
type HostCapabilities uint8
|
||||
|
||||
const (
|
||||
// HostCapabilityPull represents the capability to fetch manifests
|
||||
// and blobs by digest
|
||||
HostCapabilityPull HostCapabilities = 1 << iota
|
||||
|
||||
// HostCapabilityResolve represents the capability to fetch manifests
|
||||
// by name
|
||||
HostCapabilityResolve
|
||||
|
||||
// HostCapabilityPush represents the capability to push blobs and
|
||||
// manifests
|
||||
HostCapabilityPush
|
||||
|
||||
// Reserved for future capabilities (i.e. search, catalog, remove)
|
||||
)
|
||||
|
||||
func (c HostCapabilities) Has(t HostCapabilities) bool {
|
||||
return c&t == t
|
||||
}
|
||||
|
||||
// RegistryHost represents a complete configuration for a registry
|
||||
// host, representing the capabilities, authorizations, connection
|
||||
// configuration, and location.
|
||||
type RegistryHost struct {
|
||||
Client *http.Client
|
||||
Authorizer Authorizer
|
||||
Host string
|
||||
Scheme string
|
||||
Path string
|
||||
Capabilities HostCapabilities
|
||||
}
|
||||
|
||||
// RegistryHosts fetches the registry hosts for a given namespace,
|
||||
// provided by the host component of an distribution image reference.
|
||||
type RegistryHosts func(string) ([]RegistryHost, error)
|
||||
|
||||
// Registries joins multiple registry configuration functions, using the same
|
||||
// order as provided within the arguments. When an empty registry configuration
|
||||
// is returned with a nil error, the next function will be called.
|
||||
// NOTE: This function will not join configurations, as soon as a non-empty
|
||||
// configuration is returned from a configuration function, it will be returned
|
||||
// to the caller.
|
||||
func Registries(registries ...RegistryHosts) RegistryHosts {
|
||||
return func(host string) ([]RegistryHost, error) {
|
||||
for _, registry := range registries {
|
||||
config, err := registry(host)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
if len(config) > 0 {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
type registryOpts struct {
|
||||
authorizer Authorizer
|
||||
plainHTTP func(string) (bool, error)
|
||||
host func(string) (string, error)
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// RegistryOpt defines a registry default option
|
||||
type RegistryOpt func(*registryOpts)
|
||||
|
||||
// WithPlainHTTP configures registries to use plaintext http scheme
|
||||
// for the provided host match function.
|
||||
func WithPlainHTTP(f func(string) (bool, error)) RegistryOpt {
|
||||
return func(opts *registryOpts) {
|
||||
opts.plainHTTP = f
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuthorizer configures the default authorizer for a registry
|
||||
func WithAuthorizer(a Authorizer) RegistryOpt {
|
||||
return func(opts *registryOpts) {
|
||||
opts.authorizer = a
|
||||
}
|
||||
}
|
||||
|
||||
// WithHostTranslator defines the default translator to use for registry hosts
|
||||
func WithHostTranslator(h func(string) (string, error)) RegistryOpt {
|
||||
return func(opts *registryOpts) {
|
||||
opts.host = h
|
||||
}
|
||||
}
|
||||
|
||||
// WithClient configures the default http client for a registry
|
||||
func WithClient(c *http.Client) RegistryOpt {
|
||||
return func(opts *registryOpts) {
|
||||
opts.client = c
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigureDefaultRegistries is used to create a default configuration for
|
||||
// registries. For more advanced configurations or per-domain setups,
|
||||
// the RegistryHosts interface should be used directly.
|
||||
// NOTE: This function will always return a non-empty value or error
|
||||
func ConfigureDefaultRegistries(ropts ...RegistryOpt) RegistryHosts {
|
||||
var opts registryOpts
|
||||
for _, opt := range ropts {
|
||||
opt(&opts)
|
||||
}
|
||||
|
||||
return func(host string) ([]RegistryHost, error) {
|
||||
config := RegistryHost{
|
||||
Client: opts.client,
|
||||
Authorizer: opts.authorizer,
|
||||
Host: host,
|
||||
Scheme: "https",
|
||||
Path: "/v2",
|
||||
Capabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,
|
||||
}
|
||||
|
||||
if config.Client == nil {
|
||||
config.Client = http.DefaultClient
|
||||
}
|
||||
|
||||
if opts.plainHTTP != nil {
|
||||
match, err := opts.plainHTTP(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if match {
|
||||
config.Scheme = "http"
|
||||
}
|
||||
}
|
||||
|
||||
if opts.host != nil {
|
||||
var err error
|
||||
config.Host, err = opts.host(config.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if host == "docker.io" {
|
||||
config.Host = "registry-1.docker.io"
|
||||
}
|
||||
|
||||
return []RegistryHost{config}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MatchAllHosts is a host match function which is always true.
|
||||
func MatchAllHosts(string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// MatchLocalhost is a host match function which returns true for
|
||||
// localhost.
|
||||
func MatchLocalhost(host string) (bool, error) {
|
||||
for _, s := range []string{"localhost", "127.0.0.1", "[::1]"} {
|
||||
if len(host) >= len(s) && host[0:len(s)] == s && (len(host) == len(s) || host[len(s)] == ':') {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return host == "::1", nil
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user